librw/src/d3d/d3ddevice.cpp

848 lines
20 KiB
C++
Raw Normal View History

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwplg.h"
2017-08-09 10:57:32 +02:00
#include "../rwerror.h"
2017-08-29 10:12:56 +02:00
#include "../rwrender.h"
#include "../rwengine.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "rwd3d.h"
#include "rwd3dimpl.h"
2017-08-09 10:57:32 +02:00
#define PLUGIN_ID 0
namespace rw {
namespace d3d {
#ifdef RW_D3D9
2017-10-20 22:38:28 +02:00
struct D3d9Globals
{
HWND window;
bool windowed;
int presentWidth, presentHeight;
} d3d9Globals;
2018-01-08 12:55:15 +01:00
// Keep track of rasters exclusively in video memory
// as they need special treatment sometimes
struct VidmemRaster
{
Raster *raster;
VidmemRaster *next;
};
static VidmemRaster *vidmemRasters;
void addVidmemRaster(Raster *raster);
void removeVidmemRaster(Raster *raster);
2017-08-09 10:57:32 +02:00
// 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;
2018-01-03 18:02:02 +01:00
static uint32 cullmode;
2017-08-09 10:57:32 +02:00
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];
2017-08-09 10:57:32 +02:00
// TODO: not only rasters, make a struct
static Raster *d3dRaster[MAXNUMSTAGES];
static D3DMATERIAL9 d3dmaterial;
2017-08-09 10:57:32 +02:00
// 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;
}
}
}
2017-12-30 11:43:17 +01:00
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++;
}
}
}
2017-12-30 11:43:17 +01:00
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){
2017-08-09 10:57:32 +02:00
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){
2017-08-09 10:57:32 +02:00
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){
2017-08-09 10:57:32 +02:00
d3ddevice->SetSamplerState(stage, (D3DSAMPLERSTATETYPE)type, value);
d3dSamplerStates[type][stage] = value;
}
}
2017-12-30 11:43:17 +01:00
void
getSamplerState(uint32 stage, uint32 type, uint32 *value)
{
*value = d3dSamplerStates[type][stage];
}
2017-10-20 22:38:28 +02:00
// 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);
}
2017-08-09 10:57:32 +02:00
// 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
};
2018-01-03 18:02:02 +01:00
uint32 cullmodeMap[] = {
D3DCULL_NONE,
D3DCULL_CW,
D3DCULL_CCW
};
2017-08-09 10:57:32 +02:00
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:{
2018-05-24 00:53:50 +02:00
RGBA c;
c.red = value;
c.green = value>>8;
c.blue = value>>16;
c.alpha = value>>24;
2017-08-09 10:57:32 +02:00
if(!equal(fogcolor, c)){
fogcolor = c;
setRenderState(D3DRS_FOGCOLOR, D3DCOLOR_RGBA(c.red, c.green, c.blue, c.alpha));
}} break;
2018-01-03 18:02:02 +01:00
case CULLMODE:
if(cullmode != value){
cullmode = value;
setRenderState(D3DRS_CULLMODE, cullmodeMap[value]);
}
break;
2017-08-09 10:57:32 +02:00
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:
2018-05-24 00:53:50 +02:00
return RWRGBAINT(fogcolor.red, fogcolor.green, fogcolor.blue, fogcolor.alpha);
2018-01-03 18:02:02 +01:00
case CULLMODE:
return cullmode;
2017-08-09 10:57:32 +02:00
case ALPHATESTFUNC:
return alphafunc;
case ALPHATESTREF:
return alpharef;
}
return 0;
}
void
setRasterStage(uint32 stage, Raster *raster)
{
2017-08-09 10:57:32 +02:00
bool32 alpha;
D3dRaster *d3draster = nil;
if(raster != d3dRaster[stage]){
d3dRaster[stage] = raster;
if(raster){
d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
2017-08-09 10:57:32 +02:00
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);
}
2017-11-15 19:23:50 +01:00
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
2018-01-03 18:02:02 +01:00
setMaterial(SurfaceProperties surfProps, rw::RGBA color)
{
D3DMATERIAL9 mat9;
D3DCOLORVALUE black = { 0, 0, 0, 0 };
2018-01-03 18:02:02 +01:00
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;
2017-11-15 19:23:50 +01:00
setD3dMaterial(&mat9);
}
2018-01-09 23:09:26 +01:00
// Shaders
void
setVertexShader(void *vs)
{
d3ddevice->SetVertexShader((IDirect3DVertexShader9*)vs);
}
void
setPixelShader(void *ps)
{
d3ddevice->SetPixelShader((IDirect3DPixelShader9*)ps);
}
void*
createVertexShader(void *csosrc)
{
void *shdr;
if(d3ddevice->CreateVertexShader((DWORD*)csosrc, (IDirect3DVertexShader9**)&shdr) == D3D_OK)
return shdr;
return nil;
}
void*
createPixelShader(void *csosrc)
{
void *shdr;
if(d3ddevice->CreatePixelShader((DWORD*)csosrc, (IDirect3DPixelShader9**)&shdr) == D3D_OK)
return shdr;
return nil;
}
// Camera
2017-08-09 10:57:32 +02:00
static void
2016-07-05 11:36:43 +02:00
beginUpdate(Camera *cam)
{
float view[16], proj[16];
// View Matrix
Matrix inv;
2017-08-09 10:57:32 +02:00
Matrix::invert(&inv, cam->getFrame()->getLTM());
2016-07-05 11:36:43 +02:00
// 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;
2017-12-31 10:50:49 +01:00
memcpy(&cam->devView, view, sizeof(RawMatrix));
2017-08-09 10:57:32 +02:00
d3ddevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view);
2016-07-05 11:36:43 +02:00
// Projection Matrix
2016-07-06 11:44:59 +02:00
float32 invwx = 1.0f/cam->viewWindow.x;
float32 invwy = 1.0f/cam->viewWindow.y;
float32 invz = 1.0f/(cam->farPlane-cam->nearPlane);
2016-07-05 11:36:43 +02:00
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;
2016-07-06 11:44:59 +02:00
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){
2016-07-06 11:44:59 +02:00
proj[10] = cam->farPlane*invz;
2016-07-05 11:36:43 +02:00
proj[11] = 1.0f;
proj[15] = 0.0f;
}else{
proj[10] = invz;
proj[11] = 0.0f;
proj[15] = 1.0f;
}
2016-07-06 11:44:59 +02:00
proj[14] = -cam->nearPlane*proj[10];
2017-12-31 10:50:49 +01:00
memcpy(&cam->devProj, proj, sizeof(RawMatrix));
2017-08-09 10:57:32 +02:00
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);
2017-12-31 10:50:49 +01:00
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);
2017-08-09 10:57:32 +02:00
// TODO: figure out when to call this
d3ddevice->BeginScene();
2016-07-05 11:36:43 +02:00
}
2017-08-09 10:57:32 +02:00
static void
endUpdate(Camera *cam)
{
// TODO: figure out when to call this
d3ddevice->EndScene();
}
2018-01-08 12:55:15 +01:00
void
addVidmemRaster(Raster *raster)
{
VidmemRaster *vmr = rwNewT(VidmemRaster, 1, ID_DRIVER | MEMDUR_EVENT);
vmr->raster = raster;
vmr->next = vidmemRasters;
vidmemRasters = vmr;
}
void
removeVidmemRaster(Raster *raster)
{
VidmemRaster **p, *vmr;
for(p = &vidmemRasters; *p; p = &(*p)->next)
if((*p)->raster == raster)
goto found;
return;
found:
vmr = *p;
*p = vmr->next;
rwFree(vmr);
}
static void
releaseVidmemRasters(void)
{
VidmemRaster *vmr;
Raster *raster;
D3dRaster *natras;
for(vmr = vidmemRasters; vmr; vmr = vmr->next){
raster = vmr->raster;
natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
if(raster->type == Raster::CAMERATEXTURE){
deleteObject(natras->texture);
natras->texture = nil;
}
}
}
static void
recreateVidmemRasters(void)
{
VidmemRaster *vmr;
Raster *raster;
D3dRaster *natras;
for(vmr = vidmemRasters; vmr; vmr = vmr->next){
raster = vmr->raster;
natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
if(raster->type == Raster::CAMERATEXTURE){
int32 levels = Raster::calculateNumLevels(raster->width, raster->height);
IDirect3DTexture9 *tex;
d3ddevice->CreateTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? levels : 1,
D3DUSAGE_RENDERTARGET,
(D3DFORMAT)natras->format, D3DPOOL_DEFAULT, &tex, nil);
natras->texture = tex;
}
}
}
2017-08-09 10:57:32 +02:00
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);
2017-10-20 22:38:28 +02:00
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)){
2018-01-08 12:55:15 +01:00
releaseVidmemRasters();
2017-10-20 22:38:28 +02:00
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;
2017-12-30 11:43:17 +01:00
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
2017-10-20 22:38:28 +02:00
// TODO: check result
d3d::d3ddevice->Reset(&d3dpp);
d3d9Globals.presentWidth = r.right;
d3d9Globals.presentHeight = r.bottom;
resetD3d9Device();
}
2017-08-09 10:57:32 +02:00
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);
2017-08-09 10:57:32 +02:00
d3ddevice->Present(nil, nil, 0, nil);
}
// taken from Frank Luna's d3d9 book
static int
2017-08-29 10:12:56 +02:00
openD3D(EngineStartParams *params)
2017-08-09 10:57:32 +02:00
{
HWND win = params->window;
bool windowed = true;
2017-10-20 22:38:28 +02:00
d3d9Globals.window = win;
d3d9Globals.windowed = windowed;
2017-08-09 10:57:32 +02:00
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;
2017-10-20 22:38:28 +02:00
d3d9Globals.presentWidth = width;
d3d9Globals.presentHeight = height;
2017-08-09 10:57:32 +02:00
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;
2017-12-30 11:43:17 +01:00
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
2017-08-09 10:57:32 +02:00
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
2017-08-29 10:12:56 +02:00
closeD3D(void)
2016-07-05 11:36:43 +02:00
{
2017-08-09 10:57:32 +02:00
d3d::d3ddevice->Release();
d3d::d3ddevice = nil;
return 1;
2016-07-05 11:36:43 +02:00
}
2017-08-09 10:57:32 +02:00
static int
initD3D(void)
{
2017-10-20 22:38:28 +02:00
int32 s, t;
2017-08-09 10:57:32 +02:00
// 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);
2018-01-03 18:02:02 +01:00
cullmode = CULLNONE;
2017-08-09 10:57:32 +02:00
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);
2017-10-20 22:38:28 +02:00
// Save the current states
2017-11-15 19:23:50 +01:00
for(s = 0; s < MAXNUMSTATES; s++){
2017-10-20 22:38:28 +02:00
d3ddevice->GetRenderState((D3DRENDERSTATETYPE)s, (DWORD*)&d3dStates[s]);
2017-11-15 19:23:50 +01:00
stateCache[s].value = d3dStates[s];
}
2017-10-20 22:38:28 +02:00
for(t = 0; t < MAXNUMSTATES; t++)
2017-11-15 19:23:50 +01:00
for(s = 0; s < MAXNUMSTAGES; s++){
2017-10-20 22:38:28 +02:00
d3ddevice->GetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, (DWORD*)&d3dTextureStageStates[t][s]);
2017-11-15 19:23:50 +01:00
textureStageStateCache[t][s].value = d3dTextureStageStates[t][s];
}
2017-10-20 22:38:28 +02:00
for(t = 0; t < MAXNUMSAMPLERSTATES; t++)
2017-11-15 19:23:50 +01:00
for(s = 0; s < MAXNUMSTAGES; s++){
2017-10-20 22:38:28 +02:00
d3ddevice->GetSamplerState(s, (D3DSAMPLERSTATETYPE)t, (DWORD*)&d3dSamplerStates[t][s]);
2017-11-15 19:23:50 +01:00
d3dSamplerStates[t][s] = d3dSamplerStates[t][s];
}
2017-10-20 22:38:28 +02:00
openIm2D();
2017-08-29 10:12:56 +02:00
openIm3D();
return 1;
}
2017-08-29 10:12:56 +02:00
static int
termD3D(void)
{
closeIm3D();
closeIm2D();
return 1;
}
static int
finalizeD3D(void)
{
2017-08-09 10:57:32 +02:00
return 1;
}
static int
deviceSystem(DeviceReq req, void *arg0)
{
switch(req){
2017-08-29 10:12:56 +02:00
case DEVICEOPEN:
return openD3D((EngineStartParams*)arg0);
case DEVICECLOSE:
return closeD3D();
2017-08-09 10:57:32 +02:00
case DEVICEINIT:
return initD3D();
2017-08-29 10:12:56 +02:00
case DEVICETERM:
return termD3D();
case DEVICEFINALIZE:
return finalizeD3D();
2017-08-09 10:57:32 +02:00
}
return 1;
}
Device renderdevice = {
0.0f, 1.0f,
d3d::beginUpdate,
d3d::endUpdate,
d3d::clearCamera,
d3d::showRaster,
d3d::setRwRenderState,
d3d::getRwRenderState,
d3d::im2DRenderIndexedPrimitive,
2017-08-29 10:12:56 +02:00
d3d::im3DTransform,
d3d::im3DRenderIndexed,
d3d::im3DEnd,
2017-08-09 10:57:32 +02:00
d3d::deviceSystem,
};
#endif
}
}