Files
fs2open.github.com/code/graphics/grd3dcalls.cpp
T
bobboau 0ace2693ee update for the specmapping code includeing
suport for seperate specular levels on lights and
optional strings for the stars table
code has been made more organised,
though there seems to be a bug in the state selecting code
resulting in the HUD being rendered incorectly
and specmapping failing ocasionaly
2003-08-16 03:52:24 +00:00

379 lines
13 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#include <d3d8.h>
#include "graphics/grd3dinternal.h"
// Uncomment this to disable checking if states are already set, slower but useful for searching for bugs
#define D3D_CALLS_CHECK 1
// Heres the internal vertex information that DX need to know to render them
VertexTypeInfo vertex_types[D3DVT_MAX] =
{
(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2), sizeof(D3DTLVERTEX),
(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1), sizeof(D3DLVERTEX),
(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1), sizeof(D3DVERTEX),
};
// This is all stuff needed for set render state calls
const float fone = 1.0f;
const float fzero = 0.0f;
const float fsixtyfour = 64.0f;
DWORD *pfone = (DWORD *) &fone;
DWORD *pfzero = (DWORD *) &fzero;
DWORD *pfsixtyfour = (DWORD *) &fsixtyfour;
const int NUM_STATES = 174;
unsigned long current_render_states[NUM_STATES];
// These are the default states that D3D8 starts with an returns to on a reset
const unsigned long default_render_states[NUM_STATES] =
{
0,0,0,0,0,0,0, // not used
D3DZB_TRUE, // D3DRS_ZENABLE = 7,
D3DFILL_SOLID, // D3DRS_FILLMODE = 8,
D3DSHADE_GOURAUD, // D3DRS_SHADEMODE = 9,
0, // D3DRS_LINEPATTERN = 10,
0,0,0,
TRUE, // D3DRS_ZWRITEENABLE = 14,
FALSE, // D3DRS_ALPHATESTENABLE = 15,
TRUE, // D3DRS_LASTPIXEL = 16,
0,0,
D3DBLEND_ONE, // D3DRS_SRCBLEND = 19,
D3DBLEND_ZERO, // D3DRS_DESTBLEND = 20,
0,
D3DCULL_CCW, // D3DRS_CULLMODE = 22,
D3DCMP_LESSEQUAL, // D3DRS_ZFUNC = 23,
0x00000000, // D3DRS_ALPHAREF = 24, ?????????????????????
D3DCMP_ALWAYS, // D3DRS_ALPHAFUNC = 25,
FALSE, // D3DRS_DITHERENABLE = 26,
FALSE, // D3DRS_ALPHABLENDENABLE = 27,
FALSE, // D3DRS_FOGENABLE = 28,
FALSE, // D3DRS_SPECULARENABLE = 29,
0, // D3DRS_ZVISIBLE (not supported) = 30,
0,0,0,
0, // D3DRS_FOGCOLOR = 34,
D3DFOG_NONE, // D3DRS_FOGTABLEMODE = 35,
*pfzero, // D3DRS_FOGSTART = 36,
*pfone, // D3DRS_FOGEND = 37,
*pfone, // D3DRS_FOGDENSITY = 38,
0,
FALSE, // D3DRS_EDGEANTIALIAS = 40,
0,0,0,0,0,0,
0, // D3DRS_ZBIAS = 47,
FALSE, // D3DRS_RANGEFOGENABLE = 48,
0,0,0,
FALSE, // D3DRS_STENCILENABLE = 52,
D3DSTENCILOP_KEEP, // D3DRS_STENCILFAIL = 53,
D3DSTENCILOP_KEEP, // D3DRS_STENCILZFAIL = 54,
D3DSTENCILOP_KEEP, // D3DRS_STENCILPASS = 55,
D3DCMP_ALWAYS, // D3DRS_STENCILFUNC = 56,
0, // D3DRS_STENCILREF = 57,
0xFFFFFFFF, // D3DRS_STENCILMASK = 58,
0xFFFFFFFF, // D3DRS_STENCILWRITEMASK = 59,
0xFFFFFFFF, // D3DRS_TEXTUREFACTOR = 60,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0, // D3DRS_WRAP0 = 128,
0, // D3DRS_WRAP1 = 129,
0, // D3DRS_WRAP2 = 130,
0, // D3DRS_WRAP3 = 131,
0, // D3DRS_WRAP4 = 132,
0, // D3DRS_WRAP5 = 133,
0, // D3DRS_WRAP6 = 134,
0, // D3DRS_WRAP7 = 135,
TRUE, // D3DRS_CLIPPING = 136,
TRUE, // D3DRS_LIGHTING = 137,
0,
0, // D3DRS_AMBIENT = 139,
0,
D3DFOG_NONE, // D3DRS_FOGVERTEXMODE = 140,
TRUE, // D3DRS_COLORVERTEX = 141,
TRUE, // D3DRS_LOCALVIEWER = 142,
FALSE, // D3DRS_NORMALIZENORMALS = 143,
0,
D3DMCS_COLOR1, // D3DRS_DIFFUSEMATERIALSOURCE = 145,
D3DMCS_COLOR2, // D3DRS_SPECULARMATERIALSOURCE = 146,
D3DMCS_COLOR2, // D3DRS_AMBIENTMATERIALSOURCE = 147,
D3DMCS_MATERIAL, // D3DRS_EMISSIVEMATERIALSOURCE = 148,
0,0,
D3DVBF_DISABLE, // D3DRS_VERTEXBLEND = 151,
0, // D3DRS_CLIPPLANEENABLE = 152,
TRUE, // D3DRS_SOFTWAREVERTEXPROCESSING = 153, RT, never us this!
*pfone, // D3DRS_POINTSIZE = 154,
*pfzero, // D3DRS_POINTSIZE_MIN = 155,
FALSE, // D3DRS_POINTSPRITEENABLE = 156,
FALSE, // D3DRS_POINTSCALEENABLE = 157,
*pfone, // D3DRS_POINTSCALE_A = 158,
*pfzero, // D3DRS_POINTSCALE_B = 159,
*pfzero, // D3DRS_POINTSCALE_C = 160,
TRUE, // D3DRS_MULTISAMPLEANTIALIAS = 161,
0xFFFFFFFF, // D3DRS_MULTISAMPLEMASK = 162,
D3DPATCHEDGE_DISCRETE, // D3DRS_PATCHEDGESTYLE = 163,
*pfone, // D3DRS_PATCHSEGMENTS = 164,
D3DDMT_ENABLE, // D3DRS_DEBUGMONITORTOKEN = 165,
*pfsixtyfour, // D3DRS_POINTSIZE_MAX = 166,
FALSE, // D3DRS_INDEXEDVERTEXBLENDENABLE = 167,
0x0000000F, // D3DRS_COLORWRITEENABLE = 168,
*pfzero, // D3DRS_TWEENFACTOR = 170,
D3DBLENDOP_ADD, // D3DRS_BLENDOP = 171,
D3DORDER_CUBIC, // D3DRS_POSITIONORDER = 172,
D3DORDER_LINEAR // D3DRS_NORMALORDER = 173,
};
/**
* Resets all render states to defaults,
*
* @return void
*/
void d3d_reset_render_states()
{
memcpy(current_render_states, default_render_states, sizeof(unsigned long) * NUM_STATES);
}
/**
* This is a wrapper function for the D3D8.1 call SetRenderState,
*
* @param D3DRENDERSTATETYPE render_state_type - Check DX docs
* @param DWORD render_state - Check DX docs
*
* @return HRESULT - directx error code
*/
HRESULT d3d_SetRenderState( D3DRENDERSTATETYPE render_state_type, DWORD render_state )
{
Assert(render_state_type < NUM_STATES);
#ifdef D3D_CALLS_CHECK
// If the state is already set to that parameter
if(current_render_states[render_state_type] == render_state) {
// Leave without setting
return S_OK;
}
#endif
HRESULT hr = lpD3DDevice->SetRenderState(render_state_type, render_state );
// A set render state should never fail because we should always know the caps.
if(FAILED(hr)) {
mprintf(("Failed set render state %d!", render_state_type));
} else {
current_render_states[render_state_type] = render_state;
}
return hr;
}
// This is all stuff needed for draw primitive call
int D3D_vertex_type = -1;
/**
* This is a wrapper function for the D3D8.1 call DrawPrimitveUP, it also handles the vertex shader
*
* @param int vertex_type - This should be one of D3DVT_TLVERTEX, D3DVT_LVERTEX or D3DVT_VERTEX,
* @param D3DPRIMITIVETYPE prim_type - Look at DX docs
* @param LPVOID pvertices - Pointer to the vertex data, must match the vertex_type chosen
* @param DWORD vertex_count - Number of vertices in the array to render
*
* @return HRESULT - directx error code
*/
HRESULT d3d_DrawPrimitive(int vertex_type, D3DPRIMITIVETYPE prim_type, LPVOID pvertices, DWORD vertex_count)
{
HRESULT hr;
Assert( vertex_type < D3DVT_MAX);
int prim_count = 0;
switch( prim_type)
{
case D3DPT_POINTLIST:
prim_count = vertex_count;
break;
case D3DPT_LINELIST:
prim_count = vertex_count / 2;
break;
case D3DPT_LINESTRIP:
prim_count = vertex_count - 1;
break;
case D3DPT_TRIANGLELIST:
prim_count = vertex_count / 3;
break;
case D3DPT_TRIANGLESTRIP:
case D3DPT_TRIANGLEFAN:
prim_count = vertex_count - 2;
break;
default:
mprintf(("Prim type not known, primitive will not be drawn"));
return !S_OK;
}
#ifdef D3D_CALLS_CHECK
if(D3D_vertex_type != vertex_type)
#endif
{
hr = lpD3DDevice->SetVertexShader( vertex_types[vertex_type].fvf );
if(FAILED(hr)) {
mprintf(("Failed to set vertex shader"));
return hr;
}
D3D_vertex_type = vertex_type;
}
hr = lpD3DDevice->DrawPrimitiveUP(prim_type, prim_count, pvertices, vertex_types[vertex_type].size);
if(FAILED(hr)) {
mprintf(("Failed to draw primitive"));
}
return hr;
}
// This is all stuff needed for set texture stage state
const int NUM_STAGE_TYPES = 29;
unsigned long current_stages_zero[NUM_STAGE_TYPES];
const unsigned long default_stages_zero[NUM_STAGE_TYPES] =
{
0,
D3DTOP_MODULATE, // D3DTSS_COLOROP = 1,
D3DTA_TEXTURE, // D3DTSS_COLORARG1 = 2,
D3DTA_CURRENT, // D3DTSS_COLORARG2 = 3,
D3DTOP_SELECTARG1, // D3DTSS_ALPHAOP = 4,
D3DTA_DIFFUSE, // D3DTSS_ALPHAARG1 = 5,
D3DTA_CURRENT, // D3DTSS_ALPHAARG2 = 6,
*pfzero, // D3DTSS_BUMPENVMAT00 = 7,
*pfzero, // D3DTSS_BUMPENVMAT01 = 8,
*pfzero, // D3DTSS_BUMPENVMAT10 = 9,
*pfzero, // D3DTSS_BUMPENVMAT11 = 10,
0, // D3DTSS_TEXCOORDINDEX = 11,
0,
D3DTADDRESS_WRAP, // D3DTSS_ADDRESSU = 13,
D3DTADDRESS_WRAP, // D3DTSS_ADDRESSV = 14,
0x00000000, // D3DTSS_BORDERCOLOR = 15,
D3DTEXF_POINT, // D3DTSS_MAGFILTER = 16,
D3DTEXF_POINT, // D3DTSS_MINFILTER = 17,
D3DTEXF_NONE, // D3DTSS_MIPFILTER = 18,
*pfzero, // D3DTSS_MIPMAPLODBIAS = 19,
0, // D3DTSS_MAXMIPLEVEL = 20,
1, // D3DTSS_MAXANISOTROPY = 21,
*pfzero, // D3DTSS_BUMPENVLSCALE = 22,
*pfzero, // D3DTSS_BUMPENVLOFFSET = 23,
D3DTTFF_DISABLE, // D3DTSS_TEXTURETRANSFORMFLAGS = 24,
D3DTADDRESS_WRAP, // D3DTSS_ADDRESSW = 25,
D3DTA_CURRENT, // D3DTSS_COLORARG0 = 26,
D3DTA_CURRENT, // D3DTSS_ALPHAARG0 = 27,
D3DTA_CURRENT // D3DTSS_RESULTARG = 28,
};
/**
* Set current texture states to default, stage 0 only
* @return void
*/
void d3d_reset_texture_stage_states()
{
memcpy( current_stages_zero, default_stages_zero, sizeof(unsigned long) * NUM_STAGE_TYPES);
}
/**
* This is a wrapper function for the D3D8.1 call SetTextureStageState, consult DX documentation
* for parameter options
*
* @param DWORD stage - Texture state, currently only 0 is supported
* @param D3DTEXTURESTAGESTATETYPE type - Type to attemp to change
* @param DWORD value - New value to attempt to set
*
* @return HRESULT - DirectX error code
*/
HRESULT d3d_SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
{
// Only for first stage because it has different default properties to the others but
// since they are not even in use, who cares!
#ifdef D3D_CALLS_CHECK
if(stage == 0 && current_stages_zero[type] == value) {
return S_OK;
}
#endif
HRESULT hr = lpD3DDevice->SetTextureStageState(stage, type, value);
if(FAILED(hr)) {
mprintf(("Failed to set TextureStageState %d for stage %d", type, stage));
} else if (stage == 0) {
current_stages_zero[type] = value;
}
return hr;
}
// Texture set call
const int MAX_TSTAGES = 8;
IDirect3DBaseTexture8 *tinterfaces[MAX_TSTAGES] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
/**
* This should be called if the device is lost, this will ensure all state default are properly reset
*
* @param int stage - Can only be in range 0 - 7, only 0 is currently supported by vertex coords
* @param IDirect3DBaseTexture8* texture_ptr - Pointer to texture to be used
* @return HRESULT
*
*/
HRESULT d3d_SetTexture(int stage, IDirect3DBaseTexture8* texture_ptr)
{
#ifdef D3D_CALLS_CHECK
if( texture_ptr == tinterfaces[stage]) {
return S_OK;
}
#endif
HRESULT hr = lpD3DDevice->SetTexture(stage, texture_ptr);
//changed from this -Bobboau
// HRESULT hr = lpD3DDevice->SetTexture(0, texture_ptr);
if(FAILED(hr)) {
mprintf(("Failed to set texture"));
} else {
tinterfaces[stage] = texture_ptr;
}
return hr;
}
/**
* This should be called if the device is lost, this will ensure all state default are properly reset
*
* @return void
*
*/
void d3d_lost_device()
{
// Set states to what they will be after reset
gr_d3d_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_NONE, ZBUFFER_TYPE_DEFAULT);
// Calling Reset causes all texture memory surfaces to be lost, managed textures to be flushed
// from video memory, and all state information to be lost. Before calling the Reset method for a
// device, an application should release any explicit render targets, depth stencil surfaces,
// additional swap chains and D3DPOOL_DEFAULT resources associated with the device.
lpD3DDevice->Reset(&d3dpp);
d3d_reset_render_states();
d3d_reset_texture_stage_states();
memset(tinterfaces, 0, sizeof(IDirect3DBaseTexture8 *) * MAX_TSTAGES);
d3d_set_initial_render_state();
D3D_vertex_type = -1;
}