mirror of
https://github.com/aap/librw.git
synced 2025-01-23 17:22:23 +00:00
737 lines
18 KiB
C++
Executable File
737 lines
18 KiB
C++
Executable File
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <cassert>
|
|
|
|
#include "../rwbase.h"
|
|
#include "../rwplg.h"
|
|
#include "../rwerror.h"
|
|
#include "../rwrender.h"
|
|
#include "../rwengine.h"
|
|
#include "../rwpipeline.h"
|
|
#include "../rwobjects.h"
|
|
#include "rwd3d.h"
|
|
#include "rwd3dimpl.h"
|
|
|
|
#define PLUGIN_ID 0
|
|
|
|
namespace rw {
|
|
namespace d3d {
|
|
|
|
#ifdef RW_D3D9
|
|
|
|
struct D3d9Globals
|
|
{
|
|
HWND window;
|
|
bool windowed;
|
|
int presentWidth, presentHeight;
|
|
} d3d9Globals;
|
|
|
|
// cached RW render states
|
|
static bool32 vertexAlpha;
|
|
static bool32 textureAlpha;
|
|
static uint32 srcblend, destblend;
|
|
static uint32 zwrite;
|
|
static uint32 ztest;
|
|
static uint32 fogenable;
|
|
static RGBA fogcolor;
|
|
static uint32 cullmode;
|
|
static uint32 alphafunc;
|
|
static uint32 alpharef;
|
|
|
|
|
|
#define MAXNUMSTATES D3DRS_BLENDOPALPHA
|
|
#define MAXNUMSTAGES 8
|
|
#define MAXNUMTEXSTATES D3DTSS_CONSTANT
|
|
#define MAXNUMSAMPLERSTATES D3DSAMP_DMAPOFFSET
|
|
|
|
static int32 numDirtyStates;
|
|
static uint32 dirtyStates[MAXNUMSTATES];
|
|
static struct {
|
|
uint32 value;
|
|
bool32 dirty;
|
|
} stateCache[MAXNUMSTATES];
|
|
static uint32 d3dStates[MAXNUMSTATES];
|
|
|
|
static int32 numDirtyTextureStageStates;
|
|
static struct {
|
|
uint32 stage;
|
|
uint32 type;
|
|
} dirtyTextureStageStates[MAXNUMTEXSTATES*MAXNUMSTAGES];
|
|
static struct {
|
|
uint32 value;
|
|
bool32 dirty;
|
|
} textureStageStateCache[MAXNUMSTATES][MAXNUMSTAGES];
|
|
static uint32 d3dTextureStageStates[MAXNUMSTATES][MAXNUMSTAGES];
|
|
|
|
static uint32 d3dSamplerStates[MAXNUMSAMPLERSTATES][MAXNUMSTAGES];
|
|
|
|
// TODO: not only rasters, make a struct
|
|
static Raster *d3dRaster[MAXNUMSTAGES];
|
|
|
|
static D3DMATERIAL9 d3dmaterial;
|
|
|
|
// D3D render state
|
|
|
|
void
|
|
setRenderState(uint32 state, uint32 value)
|
|
{
|
|
if(stateCache[state].value != value){
|
|
stateCache[state].value = value;
|
|
if(!stateCache[state].dirty){
|
|
stateCache[state].dirty = 1;
|
|
dirtyStates[numDirtyStates++] = state;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
getRenderState(uint32 state, uint32 *value)
|
|
{
|
|
*value = stateCache[state].value;
|
|
}
|
|
|
|
void
|
|
setTextureStageState(uint32 stage, uint32 type, uint32 value)
|
|
{
|
|
if(textureStageStateCache[type][stage].value != value){
|
|
textureStageStateCache[type][stage].value = value;
|
|
if(!textureStageStateCache[type][stage].dirty){
|
|
textureStageStateCache[type][stage].dirty = 1;
|
|
dirtyTextureStageStates[numDirtyTextureStageStates].stage = stage;
|
|
dirtyTextureStageStates[numDirtyTextureStageStates].type = type;
|
|
numDirtyTextureStageStates++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
getTextureStageState(uint32 stage, uint32 type, uint32 *value)
|
|
{
|
|
*value = textureStageStateCache[type][stage].value;
|
|
}
|
|
|
|
void
|
|
flushCache(void)
|
|
{
|
|
uint32 s, t;
|
|
uint32 v;
|
|
for(int32 i = 0; i < numDirtyStates; i++){
|
|
s = dirtyStates[i];
|
|
v = stateCache[s].value;
|
|
stateCache[s].dirty = 0;
|
|
if(d3dStates[s] != v){
|
|
d3ddevice->SetRenderState((D3DRENDERSTATETYPE)s, v);
|
|
d3dStates[s] = v;
|
|
}
|
|
}
|
|
numDirtyStates = 0;
|
|
for(int32 i = 0; i < numDirtyTextureStageStates; i++){
|
|
s = dirtyTextureStageStates[i].stage;
|
|
t = dirtyTextureStageStates[i].type;
|
|
v = textureStageStateCache[t][s].value;
|
|
textureStageStateCache[t][s].dirty = 0;
|
|
if(d3dTextureStageStates[t][s] != v){
|
|
d3ddevice->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, v);
|
|
d3dTextureStageStates[t][s] = v;
|
|
}
|
|
}
|
|
numDirtyTextureStageStates = 0;
|
|
}
|
|
|
|
void
|
|
setSamplerState(uint32 stage, uint32 type, uint32 value)
|
|
{
|
|
if(d3dSamplerStates[type][stage] != value){
|
|
d3ddevice->SetSamplerState(stage, (D3DSAMPLERSTATETYPE)type, value);
|
|
d3dSamplerStates[type][stage] = value;
|
|
}
|
|
}
|
|
|
|
void
|
|
getSamplerState(uint32 stage, uint32 type, uint32 *value)
|
|
{
|
|
*value = d3dSamplerStates[type][stage];
|
|
}
|
|
|
|
// Bring D3D device in accordance with saved render states (after a reset)
|
|
static void
|
|
resetD3d9Device(void)
|
|
{
|
|
int32 i;
|
|
uint32 s, t;
|
|
for(i = 0; i < MAXNUMSTAGES; i++){
|
|
d3dRaster[i] = nil;
|
|
d3ddevice->SetTexture(i, nil);
|
|
}
|
|
for(s = 0; s < MAXNUMSTATES; s++)
|
|
d3ddevice->SetRenderState((D3DRENDERSTATETYPE)s, d3dStates[s]);
|
|
for(t = 0; t < MAXNUMSTATES; t++)
|
|
for(s = 0; s < MAXNUMSTAGES; s++)
|
|
d3ddevice->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, d3dTextureStageStates[t][s]);
|
|
for(t = 0; t < MAXNUMSAMPLERSTATES; t++)
|
|
for(s = 0; s < MAXNUMSTAGES; s++)
|
|
d3ddevice->SetSamplerState(s, (D3DSAMPLERSTATETYPE)t, d3dSamplerStates[t][s]);
|
|
d3ddevice->SetMaterial(&d3dmaterial);
|
|
}
|
|
|
|
// RW render state
|
|
|
|
static void
|
|
setVertexAlpha(bool32 enable)
|
|
{
|
|
if(vertexAlpha != enable){
|
|
if(!textureAlpha){
|
|
setRenderState(D3DRS_ALPHABLENDENABLE, enable);
|
|
setRenderState(D3DRS_ALPHATESTENABLE, enable);
|
|
}
|
|
vertexAlpha = enable;
|
|
}
|
|
}
|
|
|
|
static uint32 blendMap[] = {
|
|
D3DBLEND_ZERO,
|
|
D3DBLEND_ONE,
|
|
D3DBLEND_SRCCOLOR,
|
|
D3DBLEND_INVSRCCOLOR,
|
|
D3DBLEND_SRCALPHA,
|
|
D3DBLEND_INVSRCALPHA,
|
|
D3DBLEND_DESTALPHA,
|
|
D3DBLEND_INVDESTALPHA,
|
|
D3DBLEND_DESTCOLOR,
|
|
D3DBLEND_INVDESTCOLOR,
|
|
D3DBLEND_SRCALPHASAT
|
|
};
|
|
|
|
uint32 alphafuncMap[] = {
|
|
D3DCMP_ALWAYS,
|
|
D3DCMP_GREATEREQUAL,
|
|
D3DCMP_LESS
|
|
};
|
|
|
|
uint32 cullmodeMap[] = {
|
|
D3DCULL_NONE,
|
|
D3DCULL_CW,
|
|
D3DCULL_CCW
|
|
};
|
|
|
|
static void
|
|
setRwRenderState(int32 state, uint32 value)
|
|
{
|
|
uint32 bval = value ? TRUE : FALSE;
|
|
switch(state){
|
|
case VERTEXALPHA:
|
|
setVertexAlpha(bval);
|
|
break;
|
|
case SRCBLEND:
|
|
if(srcblend != value){
|
|
srcblend = value;
|
|
setRenderState(D3DRS_SRCBLEND, blendMap[value]);
|
|
}
|
|
break;
|
|
case DESTBLEND:
|
|
if(destblend != value){
|
|
destblend = value;
|
|
setRenderState(D3DRS_DESTBLEND, blendMap[value]);
|
|
}
|
|
break;
|
|
case ZTESTENABLE:
|
|
if(ztest != bval){
|
|
ztest = bval;
|
|
setRenderState(D3DRS_ZENABLE, ztest);
|
|
}
|
|
break;
|
|
case ZWRITEENABLE:
|
|
if(zwrite != bval){
|
|
zwrite = bval;
|
|
setRenderState(D3DRS_ZWRITEENABLE, zwrite);
|
|
}
|
|
break;
|
|
case FOGENABLE:
|
|
if(fogenable != bval){
|
|
fogenable = bval;
|
|
setRenderState(D3DRS_FOGENABLE, fogenable);
|
|
};
|
|
break;
|
|
case FOGCOLOR:{
|
|
RGBA c = *(RGBA*)&value;
|
|
if(!equal(fogcolor, c)){
|
|
fogcolor = c;
|
|
setRenderState(D3DRS_FOGCOLOR, D3DCOLOR_RGBA(c.red, c.green, c.blue, c.alpha));
|
|
}} break;
|
|
case CULLMODE:
|
|
if(cullmode != value){
|
|
cullmode = value;
|
|
setRenderState(D3DRS_CULLMODE, cullmodeMap[value]);
|
|
}
|
|
break;
|
|
case ALPHATESTFUNC:
|
|
if(alphafunc != value){
|
|
alphafunc = value;
|
|
setRenderState(D3DRS_ALPHAFUNC, alphafuncMap[alphafunc]);
|
|
}
|
|
break;
|
|
case ALPHATESTREF:
|
|
if(alpharef != value){
|
|
alpharef = value;
|
|
setRenderState(D3DRS_ALPHAREF, alpharef);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static uint32
|
|
getRwRenderState(int32 state)
|
|
{
|
|
switch(state){
|
|
case VERTEXALPHA:
|
|
return vertexAlpha;
|
|
case SRCBLEND:
|
|
return srcblend;
|
|
case DESTBLEND:
|
|
return destblend;
|
|
case ZTESTENABLE:
|
|
return ztest;
|
|
case ZWRITEENABLE:
|
|
return zwrite;
|
|
case FOGENABLE:
|
|
return fogenable;
|
|
case FOGCOLOR:
|
|
return *(uint32*)&fogcolor;
|
|
case CULLMODE:
|
|
return cullmode;
|
|
case ALPHATESTFUNC:
|
|
return alphafunc;
|
|
case ALPHATESTREF:
|
|
return alpharef;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
setRasterStage(uint32 stage, Raster *raster)
|
|
{
|
|
bool32 alpha;
|
|
D3dRaster *d3draster = nil;
|
|
if(raster != d3dRaster[stage]){
|
|
d3dRaster[stage] = raster;
|
|
if(raster){
|
|
d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
|
|
d3ddevice->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture);
|
|
alpha = d3draster->hasAlpha;
|
|
}else{
|
|
d3ddevice->SetTexture(stage, nil);
|
|
alpha = 0;
|
|
}
|
|
if(stage == 0){
|
|
if(textureAlpha != alpha){
|
|
textureAlpha = alpha;
|
|
if(!vertexAlpha){
|
|
setRenderState(D3DRS_ALPHABLENDENABLE, alpha);
|
|
setRenderState(D3DRS_ALPHATESTENABLE, alpha);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
setTexture(uint32 stage, Texture *tex)
|
|
{
|
|
// TODO: support mipmaps
|
|
static DWORD filternomip[] = {
|
|
0, D3DTEXF_POINT, D3DTEXF_LINEAR,
|
|
D3DTEXF_POINT, D3DTEXF_LINEAR,
|
|
D3DTEXF_POINT, D3DTEXF_LINEAR
|
|
};
|
|
static DWORD wrap[] = {
|
|
0, D3DTADDRESS_WRAP, D3DTADDRESS_MIRROR,
|
|
D3DTADDRESS_CLAMP, D3DTADDRESS_BORDER
|
|
};
|
|
if(tex == nil){
|
|
setRasterStage(stage, nil);
|
|
return;
|
|
}
|
|
if(tex->raster){
|
|
setSamplerState(stage, D3DSAMP_MAGFILTER, filternomip[tex->getFilter()]);
|
|
setSamplerState(stage, D3DSAMP_MINFILTER, filternomip[tex->getFilter()]);
|
|
setSamplerState(stage, D3DSAMP_ADDRESSU, wrap[tex->getAddressU()]);
|
|
setSamplerState(stage, D3DSAMP_ADDRESSV, wrap[tex->getAddressV()]);
|
|
}
|
|
setRasterStage(stage, tex->raster);
|
|
}
|
|
|
|
void
|
|
setD3dMaterial(D3DMATERIAL9 *mat9)
|
|
{
|
|
if(d3dmaterial.Diffuse.r != mat9->Diffuse.r ||
|
|
d3dmaterial.Diffuse.g != mat9->Diffuse.g ||
|
|
d3dmaterial.Diffuse.b != mat9->Diffuse.b ||
|
|
d3dmaterial.Diffuse.a != mat9->Diffuse.a ||
|
|
d3dmaterial.Ambient.r != mat9->Ambient.r ||
|
|
d3dmaterial.Ambient.g != mat9->Ambient.g ||
|
|
d3dmaterial.Ambient.b != mat9->Ambient.b ||
|
|
d3dmaterial.Ambient.a != mat9->Ambient.a ||
|
|
d3dmaterial.Specular.r != mat9->Specular.r ||
|
|
d3dmaterial.Specular.g != mat9->Specular.g ||
|
|
d3dmaterial.Specular.b != mat9->Specular.b ||
|
|
d3dmaterial.Specular.a != mat9->Specular.a ||
|
|
d3dmaterial.Emissive.r != mat9->Emissive.r ||
|
|
d3dmaterial.Emissive.g != mat9->Emissive.g ||
|
|
d3dmaterial.Emissive.b != mat9->Emissive.b ||
|
|
d3dmaterial.Emissive.a != mat9->Emissive.a ||
|
|
d3dmaterial.Power != mat9->Power){
|
|
d3ddevice->SetMaterial(mat9);
|
|
d3dmaterial = *mat9;
|
|
}
|
|
}
|
|
|
|
void
|
|
setMaterial(SurfaceProperties surfProps, rw::RGBA color)
|
|
{
|
|
D3DMATERIAL9 mat9;
|
|
D3DCOLORVALUE black = { 0, 0, 0, 0 };
|
|
float ambmult = surfProps.ambient/255.0f;
|
|
float diffmult = surfProps.diffuse/255.0f;
|
|
mat9.Ambient.r = color.red*ambmult;
|
|
mat9.Ambient.g = color.green*ambmult;
|
|
mat9.Ambient.b = color.blue*ambmult;
|
|
mat9.Ambient.a = color.alpha*ambmult;
|
|
mat9.Diffuse.r = color.red*diffmult;
|
|
mat9.Diffuse.g = color.green*diffmult;
|
|
mat9.Diffuse.b = color.blue*diffmult;
|
|
mat9.Diffuse.a = color.alpha*diffmult;
|
|
mat9.Power = 0.0f;
|
|
mat9.Emissive = black;
|
|
mat9.Specular = black;
|
|
setD3dMaterial(&mat9);
|
|
}
|
|
|
|
static void
|
|
beginUpdate(Camera *cam)
|
|
{
|
|
float view[16], proj[16];
|
|
|
|
// View Matrix
|
|
Matrix inv;
|
|
Matrix::invert(&inv, cam->getFrame()->getLTM());
|
|
// Since we're looking into positive Z,
|
|
// flip X to ge a left handed view space.
|
|
view[0] = -inv.right.x;
|
|
view[1] = inv.right.y;
|
|
view[2] = inv.right.z;
|
|
view[3] = 0.0f;
|
|
view[4] = -inv.up.x;
|
|
view[5] = inv.up.y;
|
|
view[6] = inv.up.z;
|
|
view[7] = 0.0f;
|
|
view[8] = -inv.at.x;
|
|
view[9] = inv.at.y;
|
|
view[10] = inv.at.z;
|
|
view[11] = 0.0f;
|
|
view[12] = -inv.pos.x;
|
|
view[13] = inv.pos.y;
|
|
view[14] = inv.pos.z;
|
|
view[15] = 1.0f;
|
|
memcpy(&cam->devView, view, sizeof(RawMatrix));
|
|
d3ddevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view);
|
|
|
|
// Projection Matrix
|
|
float32 invwx = 1.0f/cam->viewWindow.x;
|
|
float32 invwy = 1.0f/cam->viewWindow.y;
|
|
float32 invz = 1.0f/(cam->farPlane-cam->nearPlane);
|
|
|
|
proj[0] = invwx;
|
|
proj[1] = 0.0f;
|
|
proj[2] = 0.0f;
|
|
proj[3] = 0.0f;
|
|
|
|
proj[4] = 0.0f;
|
|
proj[5] = invwy;
|
|
proj[6] = 0.0f;
|
|
proj[7] = 0.0f;
|
|
|
|
proj[8] = cam->viewOffset.x*invwx;
|
|
proj[9] = cam->viewOffset.y*invwy;
|
|
proj[12] = -proj[8];
|
|
proj[13] = -proj[9];
|
|
if(cam->projection == Camera::PERSPECTIVE){
|
|
proj[10] = cam->farPlane*invz;
|
|
proj[11] = 1.0f;
|
|
|
|
proj[15] = 0.0f;
|
|
}else{
|
|
proj[10] = invz;
|
|
proj[11] = 0.0f;
|
|
|
|
proj[15] = 1.0f;
|
|
}
|
|
proj[14] = -cam->nearPlane*proj[10];
|
|
memcpy(&cam->devProj, proj, sizeof(RawMatrix));
|
|
d3ddevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj);
|
|
|
|
// TODO: figure out where this is really done
|
|
setRenderState(D3DRS_FOGSTART, *(uint32*)&cam->fogPlane);
|
|
setRenderState(D3DRS_FOGEND, *(uint32*)&cam->farPlane);
|
|
|
|
D3DVIEWPORT9 vp;
|
|
vp.MinZ = 0.0f;
|
|
vp.MaxZ = 1.0f;
|
|
vp.X = cam->frameBuffer->offsetX;
|
|
vp.Y = cam->frameBuffer->offsetY;
|
|
vp.Width = cam->frameBuffer->width;
|
|
vp.Height = cam->frameBuffer->height;
|
|
d3ddevice->SetViewport(&vp);
|
|
|
|
// TODO: figure out when to call this
|
|
d3ddevice->BeginScene();
|
|
}
|
|
|
|
static void
|
|
endUpdate(Camera *cam)
|
|
{
|
|
// TODO: figure out when to call this
|
|
d3ddevice->EndScene();
|
|
}
|
|
|
|
static void
|
|
clearCamera(Camera *cam, RGBA *col, uint32 mode)
|
|
{
|
|
int flags = 0;
|
|
if(mode & Camera::CLEARIMAGE)
|
|
mode |= D3DCLEAR_TARGET;
|
|
if(mode & Camera::CLEARZ)
|
|
mode |= D3DCLEAR_ZBUFFER;
|
|
D3DCOLOR c = D3DCOLOR_RGBA(col->red, col->green, col->blue, col->alpha);
|
|
|
|
RECT r;
|
|
GetClientRect(d3d9Globals.window, &r);
|
|
BOOL icon = IsIconic(d3d9Globals.window);
|
|
Raster *ras = cam->frameBuffer;
|
|
if(!icon &&
|
|
(r.right != d3d9Globals.presentWidth || r.bottom != d3d9Globals.presentHeight)){
|
|
D3DPRESENT_PARAMETERS d3dpp;
|
|
d3dpp.BackBufferWidth = r.right;
|
|
d3dpp.BackBufferHeight = r.bottom;
|
|
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
|
d3dpp.BackBufferCount = 1;
|
|
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
|
d3dpp.MultiSampleQuality = 0;
|
|
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
d3dpp.hDeviceWindow = d3d9Globals.window;
|
|
d3dpp.Windowed = d3d9Globals.windowed;
|
|
d3dpp.EnableAutoDepthStencil = true;
|
|
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
|
|
d3dpp.Flags = 0;
|
|
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
|
|
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
|
|
// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
|
// TODO: check result
|
|
d3d::d3ddevice->Reset(&d3dpp);
|
|
d3d9Globals.presentWidth = r.right;
|
|
d3d9Globals.presentHeight = r.bottom;
|
|
resetD3d9Device();
|
|
}
|
|
|
|
d3ddevice->Clear(0, 0, mode, c, 1.0f, 0);
|
|
}
|
|
|
|
static void
|
|
showRaster(Raster *raster)
|
|
{
|
|
// TODO: do this properly!
|
|
|
|
// not used but we want cameras to have rasters
|
|
assert(raster);
|
|
d3ddevice->Present(nil, nil, 0, nil);
|
|
}
|
|
|
|
// taken from Frank Luna's d3d9 book
|
|
static int
|
|
openD3D(EngineStartParams *params)
|
|
{
|
|
HWND win = params->window;
|
|
bool windowed = true;
|
|
|
|
d3d9Globals.window = win;
|
|
d3d9Globals.windowed = windowed;
|
|
|
|
HRESULT hr = 0;
|
|
IDirect3D9 *d3d9 = 0;
|
|
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
|
|
if(!d3d9){
|
|
RWERROR((ERR_GENERAL, "Direct3DCreate9() failed"));
|
|
return 0;
|
|
}
|
|
|
|
D3DCAPS9 caps;
|
|
d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
|
|
int vp = 0;
|
|
if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
|
|
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
|
|
else
|
|
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
|
|
|
RECT rect;
|
|
GetClientRect(win, &rect);
|
|
int width = rect.right - rect.left;
|
|
int height = rect.bottom - rect.top;
|
|
|
|
d3d9Globals.presentWidth = width;
|
|
d3d9Globals.presentHeight = height;
|
|
D3DPRESENT_PARAMETERS d3dpp;
|
|
d3dpp.BackBufferWidth = width;
|
|
d3dpp.BackBufferHeight = height;
|
|
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
|
d3dpp.BackBufferCount = 1;
|
|
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
|
d3dpp.MultiSampleQuality = 0;
|
|
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
d3dpp.hDeviceWindow = win;
|
|
d3dpp.Windowed = windowed;
|
|
d3dpp.EnableAutoDepthStencil = true;
|
|
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
|
|
d3dpp.Flags = 0;
|
|
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
|
|
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
|
|
// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
|
|
|
IDirect3DDevice9 *dev;
|
|
hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, win,
|
|
vp, &d3dpp, &dev);
|
|
if(FAILED(hr)){
|
|
// try again using a 16-bit depth buffer
|
|
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
|
|
|
|
hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
|
|
win, vp, &d3dpp, &dev);
|
|
|
|
if(FAILED(hr)){
|
|
RWERROR((ERR_GENERAL, "CreateDevice() failed"));
|
|
d3d9->Release();
|
|
return 0;
|
|
}
|
|
}
|
|
d3d9->Release();
|
|
d3d::d3ddevice = dev;
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
closeD3D(void)
|
|
{
|
|
d3d::d3ddevice->Release();
|
|
d3d::d3ddevice = nil;
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
initD3D(void)
|
|
{
|
|
int32 s, t;
|
|
|
|
// TODO: do some real stuff here
|
|
|
|
d3ddevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
|
alphafunc = ALPHAGREATEREQUAL;
|
|
d3ddevice->SetRenderState(D3DRS_ALPHAREF, 10);
|
|
alpharef = 10;
|
|
|
|
d3ddevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
|
fogenable = 0;
|
|
d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
|
|
// TODO: more fog stuff
|
|
|
|
d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
|
cullmode = CULLNONE;
|
|
|
|
d3ddevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
|
d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
|
srcblend = BLENDSRCALPHA;
|
|
d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
|
destblend = BLENDINVSRCALPHA;
|
|
d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 0);
|
|
vertexAlpha = 0;
|
|
textureAlpha = 0;
|
|
|
|
setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
|
// setTextureStageState(0, D3DTSS_CONSTANT, 0xFFFFFFFF);
|
|
// setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
|
// setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CONSTANT);
|
|
// setTextureStageState(0, D3DTSS_COLOROP, D3DTA_CONSTANT);
|
|
|
|
// Save the current states
|
|
for(s = 0; s < MAXNUMSTATES; s++){
|
|
d3ddevice->GetRenderState((D3DRENDERSTATETYPE)s, (DWORD*)&d3dStates[s]);
|
|
stateCache[s].value = d3dStates[s];
|
|
}
|
|
for(t = 0; t < MAXNUMSTATES; t++)
|
|
for(s = 0; s < MAXNUMSTAGES; s++){
|
|
d3ddevice->GetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, (DWORD*)&d3dTextureStageStates[t][s]);
|
|
textureStageStateCache[t][s].value = d3dTextureStageStates[t][s];
|
|
}
|
|
for(t = 0; t < MAXNUMSAMPLERSTATES; t++)
|
|
for(s = 0; s < MAXNUMSTAGES; s++){
|
|
d3ddevice->GetSamplerState(s, (D3DSAMPLERSTATETYPE)t, (DWORD*)&d3dSamplerStates[t][s]);
|
|
d3dSamplerStates[t][s] = d3dSamplerStates[t][s];
|
|
}
|
|
|
|
openIm2D();
|
|
openIm3D();
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
termD3D(void)
|
|
{
|
|
closeIm3D();
|
|
closeIm2D();
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
finalizeD3D(void)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
deviceSystem(DeviceReq req, void *arg0)
|
|
{
|
|
switch(req){
|
|
case DEVICEOPEN:
|
|
return openD3D((EngineStartParams*)arg0);
|
|
case DEVICECLOSE:
|
|
return closeD3D();
|
|
|
|
case DEVICEINIT:
|
|
return initD3D();
|
|
case DEVICETERM:
|
|
return termD3D();
|
|
|
|
case DEVICEFINALIZE:
|
|
return finalizeD3D();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
Device renderdevice = {
|
|
0.0f, 1.0f,
|
|
d3d::beginUpdate,
|
|
d3d::endUpdate,
|
|
d3d::clearCamera,
|
|
d3d::showRaster,
|
|
d3d::setRwRenderState,
|
|
d3d::getRwRenderState,
|
|
d3d::im2DRenderIndexedPrimitive,
|
|
d3d::im3DTransform,
|
|
d3d::im3DRenderIndexed,
|
|
d3d::im3DEnd,
|
|
d3d::deviceSystem,
|
|
};
|
|
|
|
#endif
|
|
}
|
|
}
|