moved gl3 code here; added files i forgot last time

This commit is contained in:
aap
2016-06-24 15:24:58 +02:00
parent 9623bdbf11
commit e3fa1fcc7f
29 changed files with 8464 additions and 2 deletions

613
src/d3d/d3d.cpp Normal file
View File

@@ -0,0 +1,613 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwd3d.h"
namespace rw {
namespace d3d {
bool32 isP8supported = 1;
#ifdef RW_D3D9
IDirect3DDevice9 *device = nil;
#else
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | \
((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 ))
enum {
D3DFMT_UNKNOWN = 0,
D3DFMT_R8G8B8 = 20,
D3DFMT_A8R8G8B8 = 21,
D3DFMT_X8R8G8B8 = 22,
D3DFMT_R5G6B5 = 23,
D3DFMT_X1R5G5B5 = 24,
D3DFMT_A1R5G5B5 = 25,
D3DFMT_A4R4G4B4 = 26,
D3DFMT_R3G3B2 = 27,
D3DFMT_A8 = 28,
D3DFMT_A8R3G3B2 = 29,
D3DFMT_X4R4G4B4 = 30,
D3DFMT_A2B10G10R10 = 31,
D3DFMT_A8B8G8R8 = 32,
D3DFMT_X8B8G8R8 = 33,
D3DFMT_G16R16 = 34,
D3DFMT_A2R10G10B10 = 35,
D3DFMT_A16B16G16R16 = 36,
D3DFMT_A8P8 = 40,
D3DFMT_P8 = 41,
D3DFMT_L8 = 50,
D3DFMT_A8L8 = 51,
D3DFMT_A4L4 = 52,
D3DFMT_V8U8 = 60,
D3DFMT_L6V5U5 = 61,
D3DFMT_X8L8V8U8 = 62,
D3DFMT_Q8W8V8U8 = 63,
D3DFMT_V16U16 = 64,
D3DFMT_A2W10V10U10 = 67,
D3DFMT_UYVY = MAKEFOURCC('U', 'Y', 'V', 'Y'),
D3DFMT_R8G8_B8G8 = MAKEFOURCC('R', 'G', 'B', 'G'),
D3DFMT_YUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'),
D3DFMT_G8R8_G8B8 = MAKEFOURCC('G', 'R', 'G', 'B'),
D3DFMT_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'),
D3DFMT_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'),
D3DFMT_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'),
D3DFMT_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'),
D3DFMT_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'),
D3DFMT_D16_LOCKABLE = 70,
D3DFMT_D32 = 71,
D3DFMT_D15S1 = 73,
D3DFMT_D24S8 = 75,
D3DFMT_D24X8 = 77,
D3DFMT_D24X4S4 = 79,
D3DFMT_D16 = 80,
D3DFMT_D32F_LOCKABLE = 82,
D3DFMT_D24FS8 = 83,
// d3d9ex only
/* Z-Stencil formats valid for CPU access */
D3DFMT_D32_LOCKABLE = 84,
D3DFMT_S8_LOCKABLE = 85,
D3DFMT_L16 = 81,
D3DFMT_VERTEXDATA =100,
D3DFMT_INDEX16 =101,
D3DFMT_INDEX32 =102,
D3DFMT_Q16W16V16U16 =110,
D3DFMT_MULTI2_ARGB8 = MAKEFOURCC('M','E','T','1'),
// Floating point surface formats
// s10e5 formats (16-bits per channel)
D3DFMT_R16F = 111,
D3DFMT_G16R16F = 112,
D3DFMT_A16B16G16R16F = 113,
// IEEE s23e8 formats (32-bits per channel)
D3DFMT_R32F = 114,
D3DFMT_G32R32F = 115,
D3DFMT_A32B32G32R32F = 116,
D3DFMT_CxV8U8 = 117,
// d3d9ex only
// Monochrome 1 bit per pixel format
D3DFMT_A1 = 118,
// 2.8 biased fixed point
D3DFMT_A2B10G10R10_XR_BIAS = 119,
// Binary format indicating that the data has no inherent type
D3DFMT_BINARYBUFFER = 199,
};
#endif
// stolen from d3d8to9
static uint32
calculateTextureSize(uint32 width, uint32 height, uint32 depth, uint32 format)
{
#define D3DFMT_W11V11U10 65
switch(format){
default:
case D3DFMT_UNKNOWN:
return 0;
case D3DFMT_R3G3B2:
case D3DFMT_A8:
case D3DFMT_P8:
case D3DFMT_L8:
case D3DFMT_A4L4:
return width * height * depth;
case D3DFMT_R5G6B5:
case D3DFMT_X1R5G5B5:
case D3DFMT_A1R5G5B5:
case D3DFMT_A4R4G4B4:
case D3DFMT_A8R3G3B2:
case D3DFMT_X4R4G4B4:
case D3DFMT_A8P8:
case D3DFMT_A8L8:
case D3DFMT_V8U8:
case D3DFMT_L6V5U5:
case D3DFMT_D16_LOCKABLE:
case D3DFMT_D15S1:
case D3DFMT_D16:
case D3DFMT_UYVY:
case D3DFMT_YUY2:
return width * 2 * height * depth;
case D3DFMT_R8G8B8:
return width * 3 * height * depth;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
case D3DFMT_A2B10G10R10:
case D3DFMT_A8B8G8R8:
case D3DFMT_X8B8G8R8:
case D3DFMT_G16R16:
case D3DFMT_X8L8V8U8:
case D3DFMT_Q8W8V8U8:
case D3DFMT_V16U16:
case D3DFMT_W11V11U10:
case D3DFMT_A2W10V10U10:
case D3DFMT_D32:
case D3DFMT_D24S8:
case D3DFMT_D24X8:
case D3DFMT_D24X4S4:
return width * 4 * height * depth;
case D3DFMT_DXT1:
assert(depth <= 1);
return ((width + 3) >> 2) * ((height + 3) >> 2) * 8;
case D3DFMT_DXT2:
case D3DFMT_DXT3:
case D3DFMT_DXT4:
case D3DFMT_DXT5:
assert(depth <= 1);
return ((width + 3) >> 2) * ((height + 3) >> 2) * 16;
}
}
int vertFormatMap[] = {
-1, VERT_FLOAT2, VERT_FLOAT3, -1, VERT_ARGB
};
void*
createIndexBuffer(uint32 length)
{
#ifdef RW_D3D9
IDirect3DIndexBuffer9 *ibuf;
device->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0);
return ibuf;
#else
return new uint8[length];
#endif
}
uint16*
lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags)
{
if(indexBuffer == nil)
return nil;
#ifdef RW_D3D9
uint16 *indices;
IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
ibuf->Lock(offset, size, (void**)&indices, flags);
return indices;
#else
(void)offset;
(void)size;
(void)flags;
return (uint16*)indexBuffer;
#endif
}
void
unlockIndices(void *indexBuffer)
{
if(indexBuffer == nil)
return;
#ifdef RW_D3D9
IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
ibuf->Unlock();
#endif
}
void*
createVertexBuffer(uint32 length, uint32 fvf, int32 pool)
{
#ifdef RW_D3D9
IDirect3DVertexBuffer9 *vbuf;
device->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, fvf, (D3DPOOL)pool, &vbuf, 0);
return vbuf;
#else
(void)fvf;
(void)pool;
return new uint8[length];
#endif
}
uint8*
lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags)
{
if(vertexBuffer == nil)
return nil;
#ifdef RW_D3D9
uint8 *verts;
IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
vertbuf->Lock(offset, size, (void**)&verts, flags);
return verts;
#else
(void)offset;
(void)size;
(void)flags;
return (uint8*)vertexBuffer;
#endif
}
void
unlockVertices(void *vertexBuffer)
{
if(vertexBuffer == nil)
return;
#ifdef RW_D3D9
IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
vertbuf->Unlock();
#endif
}
void*
createTexture(int32 width, int32 height, int32 numlevels, uint32 format)
{
#ifdef RW_D3D9
IDirect3DTexture9 *tex;
device->CreateTexture(width, height, numlevels, 0,
(D3DFORMAT)format, D3DPOOL_MANAGED, &tex, nil);
return tex;
#else
int32 w = width;
int32 h = height;
int32 size = 0;
for(int32 i = 0; i < numlevels; i++){
size += calculateTextureSize(w, h, 1, format);
w /= 2;
if(w == 0) w = 1;
h /= 2;
if(h == 0) h = 1;
}
uint8 *data = new uint8[sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1)+size];
RasterLevels *levels = (RasterLevels*)data;
data += sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1);
levels->numlevels = numlevels;
levels->format = format;
w = width;
h = height;
for(int32 i = 0; i < numlevels; i++){
levels->levels[i].width = w;
levels->levels[i].height = h;
levels->levels[i].data = data;
levels->levels[i].size = calculateTextureSize(w, h, 1, format);
data += levels->levels[i].size;
w /= 2;
if(w == 0) w = 1;
h /= 2;
if(h == 0) h = 1;
}
return levels;
#endif
}
uint8*
lockTexture(void *texture, int32 level)
{
#ifdef RW_D3D9
IDirect3DTexture9 *tex = (IDirect3DTexture9*)texture;
D3DLOCKED_RECT lr;
tex->LockRect(level, &lr, 0, 0);
return (uint8*)lr.pBits;
#else
RasterLevels *levels = (RasterLevels*)texture;
return levels->levels[level].data;
#endif
}
void
unlockTexture(void *texture, int32 level)
{
(void)texture;
(void)level;
#ifdef RW_D3D9
IDirect3DTexture9 *tex = (IDirect3DTexture9*)texture;
tex->UnlockRect(level);
#endif
}
void
deleteObject(void *object)
{
if(object == nil)
return;
#ifdef RW_D3D9
IUnknown *unk = (IUnknown*)object;
unk->Release();
#else
delete[] (uint*)object;
#endif
}
// Native Raster
int32 nativeRasterOffset;
static void
rasterCreate(Raster *raster)
{
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
static uint32 formatMap[] = {
0,
D3DFMT_A1R5G5B5,
D3DFMT_R5G6B5,
D3DFMT_A4R4G4B4,
D3DFMT_L8,
D3DFMT_A8R8G8B8,
D3DFMT_X8R8G8B8,
0, 0, 0,
D3DFMT_X1R5G5B5,
0, 0, 0, 0, 0
};
static bool32 alphaMap[] = {
0,
1,
0,
1,
0,
1,
0,
0, 0, 0,
0,
0, 0, 0, 0, 0
};
if(raster->flags & 0x80)
return;
uint32 format;
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
format = D3DFMT_P8;
natras->palette = new uint8[4*256];
}else
format = formatMap[(raster->format >> 8) & 0xF];
natras->format = 0;
natras->hasAlpha = alphaMap[(raster->format >> 8) & 0xF];
int32 levels = Raster::calculateNumLevels(raster->width, raster->height);
natras->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? levels : 1,
format);
}
static uint8*
rasterLock(Raster *raster, int32 level)
{
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
return lockTexture(natras->texture, level);
}
static void
rasterUnlock(Raster *raster, int32 level)
{
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
unlockTexture(natras->texture, level);
}
static int32
rasterNumLevels(Raster *raster)
{
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
#ifdef RW_D3D9
IDirect3DTexture9 *tex = (IDirect3DTexture9*)natras->texture;
return tex->GetLevelCount();
#else
RasterLevels *levels = (RasterLevels*)natras->texture;
return levels->numlevels;
#endif
}
static void
rasterFromImage(Raster *raster, Image *image)
{
int32 format;
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
switch(image->depth){
case 32:
format = image->hasAlpha() ? Raster::C8888 : Raster::C888;
break;
case 24:
format = Raster::C888;
break;
case 16:
format = Raster::C1555;
break;
case 8:
format = Raster::PAL8 | Raster::C8888;
break;
case 4:
format = Raster::PAL4 | Raster::C8888;
break;
default:
return;
}
format |= 4;
raster->type = format & 0x7;
raster->flags = format & 0xF8;
raster->format = format & 0xFF00;
rasterCreate(raster);
uint8 *in, *out;
int pallength = 0;
if(raster->format & Raster::PAL4)
pallength = 16;
else if(raster->format & Raster::PAL8)
pallength = 256;
if(pallength){
in = image->palette;
out = (uint8*)natras->palette;
for(int32 i = 0; i < pallength; i++){
out[0] = in[2];
out[1] = in[1];
out[2] = in[0];
out[3] = in[3];
in += 4;
out += 4;
}
}
int32 inc = image->depth/8;
in = image->pixels;
out = raster->lock(0);
if(pallength)
memcpy(out, in, raster->width*raster->height);
else
// TODO: stride
for(int32 y = 0; y < image->height; y++)
for(int32 x = 0; x < image->width; x++)
switch(raster->format & 0xF00){
case Raster::C8888:
out[0] = in[2];
out[1] = in[1];
out[2] = in[0];
out[3] = in[3];
in += inc;
out += 4;
break;
case Raster::C888:
out[0] = in[2];
out[1] = in[1];
out[2] = in[0];
out[3] = 0xFF;
in += inc;
out += 4;
break;
case Raster::C1555:
out[0] = in[0];
out[1] = in[1];
in += 2;
out += 2;
break;
}
raster->unlock(0);
}
int32
getLevelSize(Raster *raster, int32 level)
{
D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
#ifdef RW_D3D9
IDirect3DTexture9 *tex = (IDirect3DTexture9*)ras->texture;
D3DSURFACE_DESC desc;
tex->GetLevelDesc(level, &desc);
return calculateTextureSize(desc.Width, desc.Height, 1, desc.Format);
#else
RasterLevels *levels = (RasterLevels*)ras->texture;
return levels->levels[level].size;
#endif
}
void
allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha)
{
static uint32 dxtMap[] = {
0x31545844, // DXT1
0x32545844, // DXT2
0x33545844, // DXT3
0x34545844, // DXT4
0x35545844, // DXT5
};
D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
ras->format = dxtMap[dxt-1];
ras->hasAlpha = hasAlpha;
ras->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? numLevels : 1,
ras->format);
raster->flags &= ~0x80;
}
void
setPalette(Raster *raster, void *palette, int32 size)
{
D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
memcpy(ras->palette, palette, 4*size);
}
void
setTexels(Raster *raster, void *texels, int32 level)
{
uint8 *dst = raster->lock(level);
memcpy(dst, texels, getLevelSize(raster, level));
raster->unlock(level);
}
static void*
createNativeRaster(void *object, int32 offset, int32)
{
D3dRaster *raster = PLUGINOFFSET(D3dRaster, object, offset);
raster->texture = nil;
raster->palette = nil;
raster->format = 0;
raster->hasAlpha = 0;
raster->customFormat = 0;
return object;
}
static void*
destroyNativeRaster(void *object, int32 offset, int32)
{
// TODO:
(void)offset;
return object;
}
static void*
copyNativeRaster(void *dst, void *, int32 offset, int32)
{
D3dRaster *raster = PLUGINOFFSET(D3dRaster, dst, offset);
raster->texture = nil;
raster->palette = nil;
raster->format = 0;
raster->hasAlpha = 0;
raster->customFormat = 0;
return dst;
}
void
registerNativeRaster(void)
{
nativeRasterOffset = Raster::registerPlugin(sizeof(D3dRaster),
0x12340000 | PLATFORM_D3D9,
createNativeRaster,
destroyNativeRaster,
copyNativeRaster);
driver[PLATFORM_D3D8].rasterNativeOffset = nativeRasterOffset;
driver[PLATFORM_D3D8].rasterCreate = rasterCreate;
driver[PLATFORM_D3D8].rasterLock = rasterLock;
driver[PLATFORM_D3D8].rasterUnlock = rasterUnlock;
driver[PLATFORM_D3D8].rasterNumLevels = rasterNumLevels;
driver[PLATFORM_D3D8].rasterFromImage = rasterFromImage;
driver[PLATFORM_D3D9].rasterNativeOffset = nativeRasterOffset;
driver[PLATFORM_D3D9].rasterCreate = rasterCreate;
driver[PLATFORM_D3D9].rasterLock = rasterLock;
driver[PLATFORM_D3D9].rasterUnlock = rasterUnlock;
driver[PLATFORM_D3D9].rasterNumLevels = rasterNumLevels;
driver[PLATFORM_D3D9].rasterFromImage = rasterFromImage;
}
}
}

630
src/d3d/d3d8.cpp Normal file
View File

@@ -0,0 +1,630 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwd3d.h"
#include "rwd3d8.h"
#define PLUGIN_ID 2
namespace rw {
namespace d3d8 {
using namespace d3d;
void
initializePlatform(void)
{
driver[PLATFORM_D3D8].defaultPipeline = makeDefaultPipeline();
}
uint32
makeFVFDeclaration(uint32 flags, int32 numTex)
{
uint32 fvf = 0x2;
if(flags & Geometry::NORMALS)
fvf |= 0x10;
if(flags & Geometry::PRELIT)
fvf |= 0x40;
fvf |= numTex << 8;
return fvf;
}
int32
getStride(uint32 flags, int32 numTex)
{
int32 stride = 12;
if(flags & Geometry::NORMALS)
stride += 12;;
if(flags & Geometry::PRELIT)
stride += 4;
stride += numTex*8;
return stride;
}
void*
destroyNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_D3D8)
return object;
InstanceDataHeader *header =
(InstanceDataHeader*)geometry->instData;
geometry->instData = nil;
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
deleteObject(inst->indexBuffer);
deleteObject(inst->vertexBuffer);
inst++;
}
delete[] header->inst;
delete header;
return object;
}
Stream*
readNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
uint32 platform;
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"))
return nil;
}
platform = stream->readU32();
if(platform != PLATFORM_D3D8){
RWERROR((ERR_PLATFORM, platform));
return nil;
}
InstanceDataHeader *header = new InstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_D3D8;
int32 size = stream->readI32();
uint8 *data = new uint8[size];
stream->read(data, size);
uint8 *p = data;
header->serialNumber = *(uint16*)p; p += 2;
header->numMeshes = *(uint16*)p; p += 2;
header->inst = new InstanceData[header->numMeshes];
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
inst->minVert = *(uint32*)p; p += 4;
inst->stride = *(uint32*)p; p += 4;
inst->numVertices = *(uint32*)p; p += 4;
inst->numIndices = *(uint32*)p; p += 4;
uint32 matid = *(uint32*)p; p += 4;
inst->material = geometry->materialList[matid];
inst->vertexShader = *(uint32*)p; p += 4;
inst->primType = *(uint32*)p; p += 4;
inst->indexBuffer = nil; p += 4;
inst->vertexBuffer = nil; p += 4;
inst->baseIndex = 0; p += 4;
inst->vertexAlpha = *p++;
inst->managed = 0; p++;
inst->remapped = 0; p++; // TODO: really unused? and what's that anyway?
inst++;
}
delete[] data;
inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
inst->indexBuffer = createIndexBuffer(inst->numIndices*2);
uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
stream->read(indices, 2*inst->numIndices);
unlockIndices(inst->indexBuffer);
inst->managed = 1;
inst->vertexBuffer = createVertexBuffer(inst->stride*inst->numVertices, 0, D3DPOOL_MANAGED);
uint8 *verts = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
stream->read(verts, inst->stride*inst->numVertices);
unlockVertices(inst->vertexBuffer);
inst++;
}
return stream;
}
Stream*
writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
writeChunkHeader(stream, ID_STRUCT, len-12);
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_D3D8)
return stream;
stream->writeU32(PLATFORM_D3D8);
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
int32 size = 4 + geometry->meshHeader->numMeshes*0x2C;
uint8 *data = new uint8[size];
stream->writeI32(size);
uint8 *p = data;
*(uint16*)p = header->serialNumber; p += 2;
*(uint16*)p = header->numMeshes; p += 2;
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
*(uint32*)p = inst->minVert; p += 4;
*(uint32*)p = inst->stride; p += 4;
*(uint32*)p = inst->numVertices; p += 4;
*(uint32*)p = inst->numIndices; p += 4;
int32 matid = findPointer(inst->material, (void**)geometry->materialList, geometry->numMaterials);
*(int32*)p = matid; p += 4;
*(uint32*)p = inst->vertexShader; p += 4;
*(uint32*)p = inst->primType; p += 4;
*(uint32*)p = 0; p += 4; // index buffer
*(uint32*)p = 0; p += 4; // vertex buffer
*(uint32*)p = inst->baseIndex; p += 4;
*p++ = inst->vertexAlpha;
*p++ = inst->managed;
*p++ = inst->remapped;
inst++;
}
stream->write(data, size);
delete[] data;
inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
stream->write(indices, 2*inst->numIndices);
unlockIndices(inst->indexBuffer);
uint8 *verts = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
stream->write(verts, inst->stride*inst->numVertices);
unlockVertices(inst->vertexBuffer);
inst++;
}
return stream;
}
int32
getSizeNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_D3D8)
return 0;
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
InstanceData *inst = header->inst;
int32 size = 12 + 4 + 4 + 4 + header->numMeshes*0x2C;
for(int32 i = 0; i < header->numMeshes; i++){
size += inst->numIndices*2 + inst->numVertices*inst->stride;
inst++;
}
return size;
}
void
registerNativeDataPlugin(void)
{
Geometry::registerPlugin(0, ID_NATIVEDATA,
nil, destroyNativeData, nil);
Geometry::registerPluginStream(ID_NATIVEDATA,
readNativeData,
writeNativeData,
getSizeNativeData);
}
static void
instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
return;
geo->geoflags |= Geometry::NATIVE;
InstanceDataHeader *header = new InstanceDataHeader;
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
header->platform = PLATFORM_D3D8;
header->serialNumber = 0;
header->numMeshes = meshh->numMeshes;
header->inst = new InstanceData[header->numMeshes];
InstanceData *inst = header->inst;
Mesh *mesh = meshh->mesh;
for(uint32 i = 0; i < header->numMeshes; i++){
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
&inst->minVert, &inst->numVertices);
inst->numIndices = mesh->numIndices;
inst->material = mesh->material;
inst->vertexShader = 0;
inst->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
inst->vertexBuffer = nil;
inst->baseIndex = 0; // (maybe) not used by us
inst->vertexAlpha = 0;
inst->managed = 0;
inst->remapped = 0;
inst->indexBuffer = createIndexBuffer(inst->numIndices*2);
uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
if(inst->minVert == 0)
memcpy(indices, mesh->indices, inst->numIndices*2);
else
for(int32 j = 0; j < inst->numIndices; j++)
indices[j] = mesh->indices[j] - inst->minVert;
unlockIndices(inst->indexBuffer);
pipe->instanceCB(geo, inst);
mesh++;
inst++;
}
}
static void
uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
return;
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_D3D8);
geo->geoflags &= ~Geometry::NATIVE;
geo->allocateData();
geo->meshHeader->allocateIndices();
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
InstanceData *inst = header->inst;
Mesh *mesh = geo->meshHeader->mesh;
for(uint32 i = 0; i < header->numMeshes; i++){
uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
if(inst->minVert == 0)
memcpy(mesh->indices, indices, inst->numIndices*2);
else
for(int32 j = 0; j < inst->numIndices; j++)
mesh->indices[j] = indices[j] + inst->minVert;
unlockIndices(inst->indexBuffer);
pipe->uninstanceCB(geo, inst);
mesh++;
inst++;
}
geo->generateTriangles();
destroyNativeData(geo, 0, 0);
}
static void
render(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
pipe->instance(atomic);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_D3D8);
if(pipe->renderCB)
pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData);
}
ObjPipeline::ObjPipeline(uint32 platform)
: rw::ObjPipeline(platform)
{
this->impl.instance = d3d8::instance;
this->impl.uninstance = d3d8::uninstance;
this->impl.render = d3d8::render;
this->instanceCB = nil;
this->uninstanceCB = nil;
this->renderCB = nil;
}
void
defaultInstanceCB(Geometry *geo, InstanceData *inst)
{
inst->vertexShader = makeFVFDeclaration(geo->geoflags, geo->numTexCoordSets);
inst->stride = getStride(geo->geoflags, geo->numTexCoordSets);
inst->vertexBuffer = createVertexBuffer(inst->numVertices*inst->stride,
inst->vertexShader, D3DPOOL_MANAGED);
inst->managed = 1;
uint8 *dst = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
instV3d(VERT_FLOAT3, dst,
&geo->morphTargets[0].vertices[3*inst->minVert],
inst->numVertices, inst->stride);
dst += 12;
if(geo->geoflags & Geometry::NORMALS){
instV3d(VERT_FLOAT3, dst,
&geo->morphTargets[0].normals[3*inst->minVert],
inst->numVertices, inst->stride);
dst += 12;
}
inst->vertexAlpha = 0;
if(geo->geoflags & Geometry::PRELIT){
inst->vertexAlpha = instColor(VERT_ARGB, dst, &geo->colors[4*inst->minVert],
inst->numVertices, inst->stride);
dst += 4;
}
for(int32 i = 0; i < geo->numTexCoordSets; i++){
instV2d(VERT_FLOAT2, dst, &geo->texCoords[i][2*inst->minVert],
inst->numVertices, inst->stride);
dst += 8;
}
unlockVertices(inst->vertexBuffer);
}
void
defaultUninstanceCB(Geometry *geo, InstanceData *inst)
{
uint8 *src = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
uninstV3d(VERT_FLOAT3,
&geo->morphTargets[0].vertices[3*inst->minVert],
src, inst->numVertices, inst->stride);
src += 12;
if(geo->geoflags & Geometry::NORMALS){
uninstV3d(VERT_FLOAT3,
&geo->morphTargets[0].normals[3*inst->minVert],
src, inst->numVertices, inst->stride);
src += 12;
}
inst->vertexAlpha = 0;
if(geo->geoflags & Geometry::PRELIT){
uninstColor(VERT_ARGB, &geo->colors[4*inst->minVert], src,
inst->numVertices, inst->stride);
src += 4;
}
for(int32 i = 0; i < geo->numTexCoordSets; i++){
uninstV2d(VERT_FLOAT2, &geo->texCoords[i][2*inst->minVert], src,
inst->numVertices, inst->stride);
src += 8;
}
unlockVertices(inst->vertexBuffer);
}
ObjPipeline*
makeDefaultPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8);
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
return pipe;
}
ObjPipeline*
makeSkinPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8);
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
pipe->pluginID = ID_SKIN;
pipe->pluginData = 1;
return pipe;
}
ObjPipeline*
makeMatFXPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8);
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
pipe->pluginID = ID_MATFX;
pipe->pluginData = 0;
return pipe;
}
// Native Texture and Raster
// only handles 4 and 8 bit textures right now
Raster*
readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format, int32 numLevels)
{
uint8 palette[256*4];
uint8 *data;
Image *img = Image::create(width, height, 32);
img->allocate();
if(format & Raster::PAL4)
stream->read(palette, 4*32);
else if(format & Raster::PAL8)
stream->read(palette, 4*256);
// Only read one mipmap
for(int32 i = 0; i < numLevels; i++){
uint32 size = stream->readU32();
if(i == 0){
data = new uint8[size];
stream->read(data, size);
}else
stream->seek(size);
}
if(format & (Raster::PAL4 | Raster::PAL8)){
uint8 *idx = data;
uint8 *pixels = img->pixels;
for(int y = 0; y < img->height; y++){
uint8 *line = pixels;
for(int x = 0; x < img->width; x++){
line[0] = palette[*idx*4+0];
line[1] = palette[*idx*4+1];
line[2] = palette[*idx*4+2];
line[3] = palette[*idx*4+3];
line += 4;
idx++;
}
pixels += img->stride;
}
}
delete[] data;
Raster *ras = Raster::createFromImage(img);
img->destroy();
return ras;
}
Texture*
readNativeTexture(Stream *stream)
{
uint32 platform;
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"))
return nil;
}
platform = stream->readU32();
if(platform != PLATFORM_D3D8){
RWERROR((ERR_PLATFORM, platform));
return nil;
}
Texture *tex = Texture::create(nil);
if(tex == nil)
return nil;
// Texture
tex->filterAddressing = stream->readU32();
stream->read(tex->name, 32);
stream->read(tex->mask, 32);
// Raster
uint32 format = stream->readU32();
bool32 hasAlpha = stream->readI32();
int32 width = stream->readU16();
int32 height = stream->readU16();
int32 depth = stream->readU8();
int32 numLevels = stream->readU8();
int32 type = stream->readU8();
int32 compression = stream->readU8();
int32 pallength = 0;
if(format & Raster::PAL4 || format & Raster::PAL8){
pallength = format & Raster::PAL4 ? 32 : 256;
if(!d3d::isP8supported){
tex->raster = readAsImage(stream, width, height, depth, format|type, numLevels);
tex->streamReadPlugins(stream);
return tex;
}
}
Raster *raster;
D3dRaster *ras;
if(compression){
raster = Raster::create(width, height, depth, format | type | 0x80, PLATFORM_D3D8);
ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
allocateDXT(raster, compression, numLevels, hasAlpha);
ras->customFormat = 1;
}else{
raster = Raster::create(width, height, depth, format | type, PLATFORM_D3D8);
ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
}
tex->raster = raster;
// TODO: check if format supported and convert if necessary
if(pallength != 0)
stream->read(ras->palette, 4*pallength);
uint32 size;
uint8 *data;
for(int32 i = 0; i < numLevels; i++){
size = stream->readU32();
if(i < raster->getNumLevels()){
data = raster->lock(i);
stream->read(data, size);
raster->unlock(i);
}else
stream->seek(size);
}
tex->streamReadPlugins(stream);
return tex;
}
void
writeNativeTexture(Texture *tex, Stream *stream)
{
int32 chunksize = getSizeNativeTexture(tex);
int32 plgsize = tex->streamGetPluginSize();
writeChunkHeader(stream, ID_TEXTURENATIVE, chunksize);
writeChunkHeader(stream, ID_STRUCT, chunksize-24-plgsize);
stream->writeU32(PLATFORM_D3D8);
// Texture
stream->writeU32(tex->filterAddressing);
stream->write(tex->name, 32);
stream->write(tex->mask, 32);
// Raster
Raster *raster = tex->raster;
D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
int32 numLevels = raster->getNumLevels();
stream->writeI32(raster->format);
stream->writeI32(ras->hasAlpha);
stream->writeU16(raster->width);
stream->writeU16(raster->height);
stream->writeU8(raster->depth);
stream->writeU8(numLevels);
stream->writeU8(raster->type);
int32 compression = 0;
if(ras->format)
switch(ras->format){
case 0x31545844: // DXT1
compression = 1;
break;
case 0x32545844: // DXT2
compression = 2;
break;
case 0x33545844: // DXT3
compression = 3;
break;
case 0x34545844: // DXT4
compression = 4;
break;
case 0x35545844: // DXT5
compression = 5;
break;
}
stream->writeU8(compression);
if(raster->format & Raster::PAL4)
stream->write(ras->palette, 4*32);
else if(raster->format & Raster::PAL8)
stream->write(ras->palette, 4*256);
uint32 size;
uint8 *data;
for(int32 i = 0; i < numLevels; i++){
size = getLevelSize(raster, i);
stream->writeU32(size);
data = raster->lock(i);
stream->write(data, size);
raster->unlock(i);
}
tex->streamWritePlugins(stream);
}
uint32
getSizeNativeTexture(Texture *tex)
{
uint32 size = 12 + 72 + 16;
int32 levels = tex->raster->getNumLevels();
if(tex->raster->format & Raster::PAL4)
size += 4*32;
else if(tex->raster->format & Raster::PAL8)
size += 4*256;
for(int32 i = 0; i < levels; i++)
size += 4 + getLevelSize(tex->raster, i);
size += 12 + tex->streamGetPluginSize();
return size;
}
}
}

51
src/d3d/d3d8render.cpp Normal file
View File

@@ -0,0 +1,51 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "rwd3d.h"
#include "rwd3d8.h"
namespace rw {
namespace d3d8 {
using namespace d3d;
#ifndef RW_D3D9
void defaultRenderCB(Atomic*, InstanceDataHeader*) {}
#else
void
defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
{
Geometry *geo = atomic->geometry;
Frame *f = atomic->getFrame();
device->SetTransform(D3DTS_WORLD, (D3DMATRIX*)f->getLTM());
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
d3d::setTexture(0, inst->material->texture);
d3d::setMaterial(inst->material);
d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40));
d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
if(geo->geoflags & Geometry::PRELIT)
d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
device->SetFVF(inst->vertexShader);
device->SetStreamSource(0, (IDirect3DVertexBuffer9*)inst->vertexBuffer, 0, inst->stride);
device->SetIndices((IDirect3DIndexBuffer9*)inst->indexBuffer);
uint32 numPrim = inst->primType == D3DPT_TRIANGLESTRIP ? inst->numIndices-2 : inst->numIndices/3;
d3d::flushCache();
device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)inst->primType, inst->baseIndex,
0, inst->numVertices, 0, numPrim);
inst++;
}
}
#endif
}
}

727
src/d3d/d3d9.cpp Normal file
View File

@@ -0,0 +1,727 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwd3d.h"
#include "rwd3d9.h"
#define PLUGIN_ID 2
namespace rw {
namespace d3d9 {
using namespace d3d;
// TODO: move to header, but not as #define
#ifndef RW_D3D9
#define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0}
#endif
#define NUMDECLELT 12
void
initializePlatform(void)
{
driver[PLATFORM_D3D9].defaultPipeline = makeDefaultPipeline();
}
void*
createVertexDeclaration(VertexElement *elements)
{
#ifdef RW_D3D9
IDirect3DVertexDeclaration9 *decl = 0;
device->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &decl);
return decl;
#else
int n = 0;
VertexElement *e = (VertexElement*)elements;
while(e[n++].stream != 0xFF)
;
e = (VertexElement*)new uint8[n*sizeof(VertexElement)];
memcpy(e, elements, n*sizeof(VertexElement));
return e;
#endif
}
uint32
getDeclaration(void *declaration, VertexElement *elements)
{
#ifdef RW_D3D9
IDirect3DVertexDeclaration9 *decl = (IDirect3DVertexDeclaration9*)declaration;
UINT numElt;
decl->GetDeclaration((D3DVERTEXELEMENT9*)elements, &numElt);
return numElt;
#else
int n = 0;
VertexElement *e = (VertexElement*)declaration;
while(e[n++].stream != 0xFF)
;
if(elements)
memcpy(elements, declaration, n*sizeof(VertexElement));
return n;
#endif
}
void*
destroyNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_D3D9)
return object;
InstanceDataHeader *header =
(InstanceDataHeader*)geometry->instData;
geometry->instData = nil;
deleteObject(header->vertexDeclaration);
deleteObject(header->indexBuffer);
deleteObject(header->vertexStream[0].vertexBuffer);
deleteObject(header->vertexStream[1].vertexBuffer);
delete[] header->inst;
delete header;
return object;
}
Stream*
readNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
uint32 platform;
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"))
return nil;
}
platform = stream->readU32();
if(platform != PLATFORM_D3D9){
RWERROR((ERR_PLATFORM, platform));
return nil;
}
InstanceDataHeader *header = new InstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_D3D9;
int32 size = stream->readI32();
uint8 *data = new uint8[size];
stream->read(data, size);
uint8 *p = data;
header->serialNumber = *(uint32*)p; p += 4;
header->numMeshes = *(uint32*)p; p += 4;
header->indexBuffer = nil; p += 4;
header->primType = *(uint32*)p; p += 4;
p += 16*2; // skip vertex streams, they're repeated with the vertex buffers
header->useOffsets = *(bool32*)p; p += 4;
header->vertexDeclaration = nil; p += 4;
header->totalNumIndex = *(uint32*)p; p += 4;
header->totalNumVertex = *(uint32*)p; p += 4;
header->inst = new InstanceData[header->numMeshes];
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
inst->numIndex = *(uint32*)p; p += 4;
inst->minVert = *(uint32*)p; p += 4;
uint32 matid = *(uint32*)p; p += 4;
inst->material = geometry->materialList[matid];
inst->vertexAlpha = *(bool32*)p; p += 4;
inst->vertexShader = nil; p += 4;
inst->baseIndex = 0; p += 4;
inst->numVertices = *(uint32*)p; p += 4;
inst->startIndex = *(uint32*)p; p += 4;
inst->numPrimitives = *(uint32*)p; p += 4;
inst++;
}
VertexElement elements[NUMDECLELT];
uint32 numDeclarations = stream->readU32();
stream->read(elements, numDeclarations*8);
header->vertexDeclaration = createVertexDeclaration(elements);
header->indexBuffer = createIndexBuffer(header->totalNumIndex*2);
uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
stream->read(indices, 2*header->totalNumIndex);
unlockIndices(header->indexBuffer);
VertexStream *s;
p = data;
for(int i = 0; i < 2; i++){
stream->read(p, 16);
s = &header->vertexStream[i];
s->vertexBuffer = (void*)*(uint32*)p; p += 4;
s->offset = 0; p += 4;
s->stride = *(uint32*)p; p += 4;
s->geometryFlags = *(uint16*)p; p += 2;
s->managed = *p++;
s->dynamicLock = *p++;
if(s->vertexBuffer == nil)
continue;
// TODO: unset managed flag when using morph targets.
// also uses different buffer type and locks differently
s->vertexBuffer = createVertexBuffer(s->stride*header->totalNumVertex, 0, D3DPOOL_MANAGED);
uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
stream->read(verts, s->stride*header->totalNumVertex);
unlockVertices(s->vertexBuffer);
}
// TODO: somehow depends on number of streams used (baseIndex = minVert when more than one)
inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
inst->baseIndex = inst->minVert + header->vertexStream[0].offset / header->vertexStream[0].stride;
inst++;
}
delete[] data;
return stream;
}
Stream*
writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
writeChunkHeader(stream, ID_STRUCT, len-12);
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_D3D9)
return stream;
stream->writeU32(PLATFORM_D3D9);
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
int32 size = 64 + geometry->meshHeader->numMeshes*36;
uint8 *data = new uint8[size];
stream->writeI32(size);
uint8 *p = data;
*(uint32*)p = header->serialNumber; p += 4;
*(uint32*)p = header->numMeshes; p += 4;
p += 4; // skip index buffer
*(uint32*)p = header->primType; p += 4;
p += 16*2; // skip vertex streams, they're repeated with the vertex buffers
*(bool32*)p = header->useOffsets; p += 4;
p += 4; // skip vertex declaration
*(uint32*)p = header->totalNumIndex; p += 4;
*(uint32*)p = header->totalNumVertex; p += 4;
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
*(uint32*)p = inst->numIndex; p += 4;
*(uint32*)p = inst->minVert; p += 4;
int32 matid = findPointer(inst->material, (void**)geometry->materialList, geometry->numMaterials);
*(int32*)p = matid; p += 4;
*(bool32*)p = inst->vertexAlpha; p += 4;
*(uint32*)p = 0; p += 4; // vertex shader
*(uint32*)p = inst->baseIndex; p += 4; // not used but meh...
*(uint32*)p = inst->numVertices; p += 4;
*(uint32*)p = inst->startIndex; p += 4;
*(uint32*)p = inst->numPrimitives; p += 4;
inst++;
}
stream->write(data, size);
VertexElement elements[NUMDECLELT];
uint32 numElt = getDeclaration(header->vertexDeclaration, elements);
stream->writeU32(numElt);
stream->write(elements, 8*numElt);
uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
stream->write(indices, 2*header->totalNumIndex);
unlockIndices(header->indexBuffer);
VertexStream *s;
for(int i = 0; i < 2; i++){
s = &header->vertexStream[i];
p = data;
*(uint32*)p = s->vertexBuffer ? 0xbadeaffe : 0; p += 4;
*(uint32*)p = s->offset; p += 4;
*(uint32*)p = s->stride; p += 4;
*(uint16*)p = s->geometryFlags; p += 2;
*p++ = s->managed;
*p++ = s->dynamicLock;
stream->write(data, 16);
if(s->vertexBuffer == nil)
continue;
uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
stream->write(verts, s->stride*header->totalNumVertex);
unlockVertices(s->vertexBuffer);
}
delete[] data;
return stream;
}
int32
getSizeNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_D3D9)
return 0;
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
int32 size = 12 + 4 + 4 + 64 + header->numMeshes*36;
uint32 numElt = getDeclaration(header->vertexDeclaration, nil);
size += 4 + numElt*8;
size += 2*header->totalNumIndex;
size += 0x10 + header->vertexStream[0].stride*header->totalNumVertex;
size += 0x10 + header->vertexStream[1].stride*header->totalNumVertex;
return size;
}
void
registerNativeDataPlugin(void)
{
Geometry::registerPlugin(0, ID_NATIVEDATA,
nil, destroyNativeData, nil);
Geometry::registerPluginStream(ID_NATIVEDATA,
readNativeData,
writeNativeData,
getSizeNativeData);
}
static void
instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
return;
geo->geoflags |= Geometry::NATIVE;
InstanceDataHeader *header = new InstanceDataHeader;
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
header->platform = PLATFORM_D3D9;
header->serialNumber = 0;
header->numMeshes = meshh->numMeshes;
header->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
header->useOffsets = 0;
header->totalNumVertex = geo->numVertices;
header->totalNumIndex = meshh->totalIndices;
header->inst = new InstanceData[header->numMeshes];
header->indexBuffer = createIndexBuffer(header->totalNumIndex*2);
uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
InstanceData *inst = header->inst;
Mesh *mesh = meshh->mesh;
uint32 startindex = 0;
for(uint32 i = 0; i < header->numMeshes; i++){
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
&inst->minVert, (int32*)&inst->numVertices);
inst->numIndex = mesh->numIndices;
inst->material = mesh->material;
inst->vertexAlpha = 0;
inst->vertexShader = nil;
inst->baseIndex = inst->minVert;
inst->startIndex = startindex;
inst->numPrimitives = header->primType == D3DPT_TRIANGLESTRIP ? inst->numIndex-2 : inst->numIndex/3;
if(inst->minVert == 0)
memcpy(&indices[inst->startIndex], mesh->indices, inst->numIndex*2);
else
for(uint32 j = 0; j < inst->numIndex; j++)
indices[inst->startIndex+j] = mesh->indices[j] - inst->minVert;
startindex += inst->numIndex;
mesh++;
inst++;
}
unlockIndices(header->indexBuffer);
memset(&header->vertexStream, 0, 2*sizeof(VertexStream));
pipe->instanceCB(geo, header);
}
static void
uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
return;
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_D3D9);
geo->geoflags &= ~Geometry::NATIVE;
geo->allocateData();
geo->meshHeader->allocateIndices();
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
InstanceData *inst = header->inst;
Mesh *mesh = geo->meshHeader->mesh;
for(uint32 i = 0; i < header->numMeshes; i++){
if(inst->minVert == 0)
memcpy(mesh->indices, &indices[inst->startIndex], inst->numIndex*2);
else
for(uint32 j = 0; j < inst->numIndex; j++)
mesh->indices[j] = indices[inst->startIndex+j] + inst->minVert;
mesh++;
inst++;
}
unlockIndices(header->indexBuffer);
pipe->uninstanceCB(geo, header);
geo->generateTriangles();
destroyNativeData(geo, 0, 0);
}
static void
render(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
pipe->instance(atomic);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_D3D9);
if(pipe->renderCB)
pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData);
}
ObjPipeline::ObjPipeline(uint32 platform)
: rw::ObjPipeline(platform)
{
this->impl.instance = d3d9::instance;
this->impl.uninstance = d3d9::uninstance;
this->impl.render = d3d9::render;
this->instanceCB = nil;
this->uninstanceCB = nil;
this->renderCB = nil;
}
void
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
{
VertexElement dcl[NUMDECLELT];
VertexStream *s = &header->vertexStream[0];
s->offset = 0;
s->managed = 1;
s->geometryFlags = 0;
s->dynamicLock = 0;
int i = 0;
dcl[i].stream = 0;
dcl[i].offset = 0;
dcl[i].type = D3DDECLTYPE_FLOAT3;
dcl[i].method = D3DDECLMETHOD_DEFAULT;
dcl[i].usage = D3DDECLUSAGE_POSITION;
dcl[i].usageIndex = 0;
i++;
uint16 stride = 12;
s->geometryFlags |= 0x2;
bool isPrelit = (geo->geoflags & Geometry::PRELIT) != 0;
if(isPrelit){
dcl[i].stream = 0;
dcl[i].offset = stride;
dcl[i].type = D3DDECLTYPE_D3DCOLOR;
dcl[i].method = D3DDECLMETHOD_DEFAULT;
dcl[i].usage = D3DDECLUSAGE_COLOR;
dcl[i].usageIndex = 0;
i++;
s->geometryFlags |= 0x8;
stride += 4;
}
for(int32 n = 0; n < geo->numTexCoordSets; n++){
dcl[i].stream = 0;
dcl[i].offset = stride;
dcl[i].type = D3DDECLTYPE_FLOAT2;
dcl[i].method = D3DDECLMETHOD_DEFAULT;
dcl[i].usage = D3DDECLUSAGE_TEXCOORD;
dcl[i].usageIndex = (uint8)n;
i++;
s->geometryFlags |= 0x10 << n;
stride += 8;
}
bool hasNormals = (geo->geoflags & Geometry::NORMALS) != 0;
if(hasNormals){
dcl[i].stream = 0;
dcl[i].offset = stride;
dcl[i].type = D3DDECLTYPE_FLOAT3;
dcl[i].method = D3DDECLMETHOD_DEFAULT;
dcl[i].usage = D3DDECLUSAGE_NORMAL;
dcl[i].usageIndex = 0;
i++;
s->geometryFlags |= 0x4;
stride += 12;
}
dcl[i] = D3DDECL_END();
header->vertexStream[0].stride = stride;
header->vertexDeclaration = createVertexDeclaration((VertexElement*)dcl);
s->vertexBuffer = createVertexBuffer(header->totalNumVertex*s->stride, 0, D3DPOOL_MANAGED);
// TODO: support both vertex buffers
uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++)
;
instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
geo->morphTargets[0].vertices,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
if(isPrelit){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++)
;
// TODO: vertex alpha (instance per mesh)
instColor(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
geo->colors,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
}
for(int32 n = 0; n < geo->numTexCoordSets; n++){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != n; i++)
;
instV2d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
geo->texCoords[n],
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
}
if(hasNormals){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++)
;
instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
geo->morphTargets[0].normals,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
}
unlockVertices(s->vertexBuffer);
}
void
defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header)
{
VertexElement dcl[NUMDECLELT];
uint8 *verts[2];
verts[0] = lockVertices(header->vertexStream[0].vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
verts[1] = lockVertices(header->vertexStream[1].vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
int i;
for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++)
;
uninstV3d(vertFormatMap[dcl[i].type],
geo->morphTargets[0].vertices,
verts[dcl[i].stream] + dcl[i].offset,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
if(geo->geoflags & Geometry::PRELIT){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++)
;
uninstColor(vertFormatMap[dcl[i].type],
geo->colors,
verts[dcl[i].stream] + dcl[i].offset,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
}
for(int32 n = 0; n < geo->numTexCoordSets; n++){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != n; i++)
;
uninstV2d(vertFormatMap[dcl[i].type],
geo->texCoords[n],
verts[dcl[i].stream] + dcl[i].offset,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
}
if(geo->geoflags & Geometry::NORMALS){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++)
;
uninstV3d(vertFormatMap[dcl[i].type],
geo->morphTargets[0].normals,
verts[dcl[i].stream] + dcl[i].offset,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
}
unlockVertices(verts[0]);
unlockVertices(verts[1]);
}
ObjPipeline*
makeDefaultPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
return pipe;
}
ObjPipeline*
makeSkinPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
pipe->pluginID = ID_SKIN;
pipe->pluginData = 1;
return pipe;
}
ObjPipeline*
makeMatFXPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
pipe->pluginID = ID_MATFX;
pipe->pluginData = 0;
return pipe;
}
// Native Texture and Raster
Texture*
readNativeTexture(Stream *stream)
{
uint32 platform;
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"))
return nil;
}
platform = stream->readU32();
if(platform != PLATFORM_D3D9){
RWERROR((ERR_PLATFORM, platform));
return nil;
}
Texture *tex = Texture::create(nil);
if(tex == nil)
return nil;
// Texture
tex->filterAddressing = stream->readU32();
stream->read(tex->name, 32);
stream->read(tex->mask, 32);
// Raster
int32 format = stream->readI32();
int32 d3dformat = stream->readI32();
int32 width = stream->readU16();
int32 height = stream->readU16();
int32 depth = stream->readU8();
int32 numLevels = stream->readU8();
int32 type = stream->readU8();
int32 flags = stream->readU8();
Raster *raster;
D3dRaster *ras;
assert((flags & 2) == 0);
if(flags & 8){
raster = Raster::create(width, height, depth, format | type | 0x80, PLATFORM_D3D9);
ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
ras->format = d3dformat;
ras->hasAlpha = flags & 1;
ras->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? numLevels : 1,
ras->format);
raster->flags &= ~0x80;
ras->customFormat = 1;
}else{
raster = Raster::create(width, height, depth, format | type, PLATFORM_D3D9);
ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
}
tex->raster = raster;
// TODO: check if format supported and convert if necessary
if(raster->format & Raster::PAL4)
stream->read(ras->palette, 4*32);
else if(raster->format & Raster::PAL8)
stream->read(ras->palette, 4*256);
uint32 size;
uint8 *data;
for(int32 i = 0; i < numLevels; i++){
size = stream->readU32();
if(i < raster->getNumLevels()){
data = raster->lock(i);
stream->read(data, size);
raster->unlock(i);
}else
stream->seek(size);
}
tex->streamReadPlugins(stream);
return tex;
}
void
writeNativeTexture(Texture *tex, Stream *stream)
{
int32 chunksize = getSizeNativeTexture(tex);
int32 plgsize = tex->streamGetPluginSize();
writeChunkHeader(stream, ID_TEXTURENATIVE, chunksize);
writeChunkHeader(stream, ID_STRUCT, chunksize-24-plgsize);
stream->writeU32(PLATFORM_D3D9);
// Texture
stream->writeU32(tex->filterAddressing);
stream->write(tex->name, 32);
stream->write(tex->mask, 32);
// Raster
Raster *raster = tex->raster;
D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
int32 numLevels = raster->getNumLevels();
stream->writeI32(raster->format);
stream->writeU32(ras->format);
stream->writeU16(raster->width);
stream->writeU16(raster->height);
stream->writeU8(raster->depth);
stream->writeU8(numLevels);
stream->writeU8(raster->type);
uint8 flags = 0;
if(ras->hasAlpha)
flags |= 1;
// 2 - cube map
// 4 - something about mipmaps...
if(ras->customFormat)
flags |= 8;
stream->writeU8(flags);
if(raster->format & Raster::PAL4)
stream->write(ras->palette, 4*32);
else if(raster->format & Raster::PAL8)
stream->write(ras->palette, 4*256);
uint32 size;
uint8 *data;
for(int32 i = 0; i < numLevels; i++){
size = getLevelSize(raster, i);
stream->writeU32(size);
data = raster->lock(i);
stream->write(data, size);
raster->unlock(i);
}
tex->streamWritePlugins(stream);
}
uint32
getSizeNativeTexture(Texture *tex)
{
uint32 size = 12 + 72 + 16;
int32 levels = tex->raster->getNumLevels();
if(tex->raster->format & Raster::PAL4)
size += 4*32;
else if(tex->raster->format & Raster::PAL8)
size += 4*256;
for(int32 i = 0; i < levels; i++)
size += 4 + getLevelSize(tex->raster, i);
size += 12 + tex->streamGetPluginSize();
return size;
}
}
}

52
src/d3d/d3d9render.cpp Normal file
View File

@@ -0,0 +1,52 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "rwd3d.h"
#include "rwd3d9.h"
namespace rw {
namespace d3d9 {
using namespace d3d;
#ifndef RW_D3D9
void defaultRenderCB(Atomic*, InstanceDataHeader*) {}
#else
void
defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
{
Geometry *geo = atomic->geometry;
Frame *f = atomic->getFrame();
device->SetTransform(D3DTS_WORLD, (D3DMATRIX*)f->getLTM());
device->SetStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer,
0, header->vertexStream[0].stride);
device->SetIndices((IDirect3DIndexBuffer9*)header->indexBuffer);
device->SetVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration);
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
d3d::setTexture(0, inst->material->texture);
d3d::setMaterial(inst->material);
d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40));
d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
if(geo->geoflags & Geometry::PRELIT)
d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
d3d::flushCache();
device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex,
0, inst->numVertices,
inst->startIndex, inst->numPrimitives);
inst++;
}
}
#endif
}
}

182
src/d3d/d3ddriver.cpp Normal file
View File

@@ -0,0 +1,182 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "rwd3d.h"
namespace rw {
namespace d3d {
#ifdef RW_D3D9
#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];
static Raster *d3dRaster[MAXNUMSTAGES];
static D3DMATERIAL9 d3dmaterial;
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
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
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){
device->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){
device->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, v);
d3dTextureStageStates[t][s] = v;
}
}
numDirtyTextureStageStates = 0;
}
void
setSamplerState(uint32 stage, uint32 type, uint32 value)
{
if(d3dSamplerStates[type][stage] != value){
device->SetSamplerState(stage, (D3DSAMPLERSTATETYPE)type, value);
d3dSamplerStates[type][stage] = value;
}
}
void
setRasterStage(uint32 stage, Raster *raster)
{
D3dRaster *d3draster = nil;
if(raster != d3dRaster[stage]){
d3dRaster[stage] = raster;
if(raster){
d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
device->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture);
}else
device->SetTexture(stage, nil);
}
}
void
setTexture(uint32 stage, Texture *tex)
{
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->filterAddressing & 0xFF]);
setSamplerState(stage, D3DSAMP_MINFILTER, filternomip[tex->filterAddressing & 0xFF]);
setSamplerState(stage, D3DSAMP_ADDRESSU, wrap[(tex->filterAddressing >> 8) & 0xF]);
setSamplerState(stage, D3DSAMP_ADDRESSV, wrap[(tex->filterAddressing >> 12) & 0xF]);
}
setRasterStage(stage, tex->raster);
}
void
setMaterial(Material *mat)
{
D3DMATERIAL9 mat9;
D3DCOLORVALUE black = { 0, 0, 0, 0 };
float ambmult = mat->surfaceProps.ambient/255.0f;
float diffmult = mat->surfaceProps.diffuse/255.0f;
mat9.Ambient.r = mat->color.red*ambmult;
mat9.Ambient.g = mat->color.green*ambmult;
mat9.Ambient.b = mat->color.blue*ambmult;
mat9.Ambient.a = mat->color.alpha*ambmult;
mat9.Diffuse.r = mat->color.red*diffmult;
mat9.Diffuse.g = mat->color.green*diffmult;
mat9.Diffuse.b = mat->color.blue*diffmult;
mat9.Diffuse.a = mat->color.alpha*diffmult;
mat9.Power = 0.0f;
mat9.Emissive = black;
mat9.Specular = black;
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){
device->SetMaterial(&mat9);
d3dmaterial = mat9;
}
}
#endif
}
}

105
src/d3d/rwd3d.h Normal file
View File

@@ -0,0 +1,105 @@
#ifdef RW_D3D9
#include <d3d9.h>
#endif
namespace rw {
namespace d3d {
extern bool32 isP8supported;
#ifdef RW_D3D9
extern IDirect3DDevice9 *device;
#else
enum {
D3DLOCK_NOSYSLOCK = 0, // ignored
D3DPOOL_MANAGED = 0, // ignored
D3DPT_TRIANGLELIST = 4,
D3DPT_TRIANGLESTRIP = 5,
D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.)
D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.)
D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.)
D3DDECLTYPE_FLOAT4 = 3, // 4D float
D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range
// Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte
D3DDECLTYPE_SHORT2 = 6, // 2D signed short expanded to (value, value, 0., 1.)
D3DDECLTYPE_SHORT4 = 7, // 4D signed short
D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0
D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1)
D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values
D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused.
D3DDECLMETHOD_DEFAULT = 0,
D3DDECLUSAGE_POSITION = 0,
D3DDECLUSAGE_BLENDWEIGHT, // 1
D3DDECLUSAGE_BLENDINDICES, // 2
D3DDECLUSAGE_NORMAL, // 3
D3DDECLUSAGE_PSIZE, // 4
D3DDECLUSAGE_TEXCOORD, // 5
D3DDECLUSAGE_TANGENT, // 6
D3DDECLUSAGE_BINORMAL, // 7
D3DDECLUSAGE_TESSFACTOR, // 8
D3DDECLUSAGE_POSITIONT, // 9
D3DDECLUSAGE_COLOR, // 10
D3DDECLUSAGE_FOG, // 11
D3DDECLUSAGE_DEPTH, // 12
D3DDECLUSAGE_SAMPLE, // 13
};
#endif
extern int vertFormatMap[];
void *createIndexBuffer(uint32 length);
uint16 *lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags);
void unlockIndices(void *indexBuffer);
void *createVertexBuffer(uint32 length, uint32 fvf, int32 pool);
uint8 *lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags);
void unlockVertices(void *vertexBuffer);
void *createTexture(int32 width, int32 height, int32 levels, uint32 format);
uint8 *lockTexture(void *texture, int32 level);
void unlockTexture(void *texture, int32 level);
void deleteObject(void *object);
// Native Texture and Raster
struct D3dRaster
{
void *texture;
void *palette;
uint32 format;
bool32 hasAlpha;
bool32 customFormat;
};
int32 getLevelSize(Raster *raster, int32 level);
void allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha);
void setPalette(Raster *raster, void *palette, int32 size);
void setTexels(Raster *raster, void *texels, int32 level);
extern int32 nativeRasterOffset;
void registerNativeRaster(void);
// Rendering
void setRenderState(uint32 state, uint32 value);
void setTextureStageState(uint32 stage, uint32 type, uint32 value);
void flushCache(void);
void setSamplerState(uint32 stage, uint32 type, uint32 value);
void setTexture(uint32 stage, Texture *tex);
void setMaterial(Material *mat);
}
}

67
src/d3d/rwd3d8.h Normal file
View File

@@ -0,0 +1,67 @@
namespace rw {
namespace d3d8 {
void initializePlatform(void);
struct InstanceData
{
uint32 minVert;
int32 stride;
int32 numVertices;
int32 numIndices;
Material *material;
uint32 vertexShader;
uint32 primType;
void *indexBuffer;
void *vertexBuffer;
uint32 baseIndex;
uint8 vertexAlpha;
uint8 managed;
uint8 remapped;
};
struct InstanceDataHeader : rw::InstanceDataHeader
{
uint16 serialNumber;
uint16 numMeshes;
InstanceData *inst;
};
uint32 makeFVFDeclaration(uint32 flags, int32 numTex);
int32 getStride(uint32 flags, int32 numTex);
void *destroyNativeData(void *object, int32, int32);
Stream *readNativeData(Stream *stream, int32 len, void *object, int32, int32);
Stream *writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
class ObjPipeline : public rw::ObjPipeline
{
public:
void (*instanceCB)(Geometry *geo, InstanceData *header);
void (*uninstanceCB)(Geometry *geo, InstanceData *header);
void (*renderCB)(Atomic *atomic, InstanceDataHeader *header);
ObjPipeline(uint32 platform);
};
void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header);
void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header);
void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header);
ObjPipeline *makeDefaultPipeline(void);
ObjPipeline *makeSkinPipeline(void);
ObjPipeline *makeMatFXPipeline(void);
// Native Texture and Raster
Texture *readNativeTexture(Stream *stream);
void writeNativeTexture(Texture *tex, Stream *stream);
uint32 getSizeNativeTexture(Texture *tex);
}
}

90
src/d3d/rwd3d9.h Normal file
View File

@@ -0,0 +1,90 @@
namespace rw {
namespace d3d9 {
void initializePlatform(void);
struct VertexElement
{
uint16 stream;
uint16 offset;
uint8 type;
uint8 method;
uint8 usage;
uint8 usageIndex;
};
struct VertexStream
{
void *vertexBuffer;
uint32 offset;
uint32 stride;
uint16 geometryFlags;
uint8 managed;
uint8 dynamicLock;
};
struct InstanceData
{
uint32 numIndex;
uint32 minVert;
Material *material;
bool32 vertexAlpha;
void *vertexShader;
uint32 baseIndex;
uint32 numVertices;
uint32 startIndex;
uint32 numPrimitives;
};
struct InstanceDataHeader : rw::InstanceDataHeader
{
uint32 serialNumber;
uint32 numMeshes;
void *indexBuffer;
uint32 primType;
VertexStream vertexStream[2];
bool32 useOffsets;
void *vertexDeclaration;
uint32 totalNumIndex;
uint32 totalNumVertex;
InstanceData *inst;
};
void *createVertexDeclaration(VertexElement *elements);
uint32 getDeclaration(void *declaration, VertexElement *elements);
void *destroyNativeData(void *object, int32, int32);
Stream *readNativeData(Stream *stream, int32 len, void *object, int32, int32);
Stream *writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
class ObjPipeline : public rw::ObjPipeline
{
public:
void (*instanceCB)(Geometry *geo, InstanceDataHeader *header);
void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
void (*renderCB)(Atomic *atomic, InstanceDataHeader *header);
ObjPipeline(uint32 platform);
};
void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header);
void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header);
void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header);
ObjPipeline *makeDefaultPipeline(void);
ObjPipeline *makeSkinPipeline(void);
ObjPipeline *makeMatFXPipeline(void);
// Native Texture and Raster
Texture *readNativeTexture(Stream *stream);
void writeNativeTexture(Texture *tex, Stream *stream);
uint32 getSizeNativeTexture(Texture *tex);
}
}

181
src/d3d/rwxbox.h Normal file
View File

@@ -0,0 +1,181 @@
namespace rw {
namespace xbox {
void initializePlatform(void);
struct InstanceData
{
uint32 minVert;
int32 numVertices;
int32 numIndices;
void *indexBuffer;
Material *material;
uint32 vertexShader;
};
struct InstanceDataHeader : rw::InstanceDataHeader
{
int32 size;
uint16 serialNumber;
uint16 numMeshes;
uint32 primType;
int32 numVertices;
int32 stride;
void *vertexBuffer;
bool32 vertexAlpha;
InstanceData *begin;
InstanceData *end;
uint8 *data;
};
void *destroyNativeData(void *object, int32, int32);
Stream *readNativeData(Stream *stream, int32 len, void *object, int32, int32);
Stream *writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
class ObjPipeline : public rw::ObjPipeline
{
public:
void (*instanceCB)(Geometry *geo, InstanceDataHeader *header);
void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
ObjPipeline(uint32 platform);
};
ObjPipeline *makeDefaultPipeline(void);
// Skin plugin
Stream *readNativeSkin(Stream *stream, int32, void *object, int32 offset);
Stream *writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset);
int32 getSizeNativeSkin(void *object, int32 offset);
ObjPipeline *makeSkinPipeline(void);
ObjPipeline *makeMatFXPipeline(void);
// Vertex Format plugin
extern uint32 vertexFormatSizes[6];
uint32 *getVertexFmt(Geometry *g);
uint32 makeVertexFmt(int32 flags, uint32 numTexSets);
uint32 getVertexFmtStride(uint32 fmt);
void registerVertexFormatPlugin(void);
// Native Texture and Raster
struct XboxRaster
{
void *texture;
void *palette;
uint32 format;
bool32 hasAlpha;
bool32 unknownFlag;
};
int32 getLevelSize(Raster *raster, int32 level);
extern int32 nativeRasterOffset;
void registerNativeRaster(void);
Texture *readNativeTexture(Stream *stream);
void writeNativeTexture(Texture *tex, Stream *stream);
uint32 getSizeNativeTexture(Texture *tex);
enum {
D3DFMT_UNKNOWN = 0xFFFFFFFF,
/* Swizzled formats */
D3DFMT_A8R8G8B8 = 0x00000006,
D3DFMT_X8R8G8B8 = 0x00000007,
D3DFMT_R5G6B5 = 0x00000005,
D3DFMT_R6G5B5 = 0x00000027,
D3DFMT_X1R5G5B5 = 0x00000003,
D3DFMT_A1R5G5B5 = 0x00000002,
D3DFMT_A4R4G4B4 = 0x00000004,
D3DFMT_A8 = 0x00000019,
D3DFMT_A8B8G8R8 = 0x0000003A,
D3DFMT_B8G8R8A8 = 0x0000003B,
D3DFMT_R4G4B4A4 = 0x00000039,
D3DFMT_R5G5B5A1 = 0x00000038,
D3DFMT_R8G8B8A8 = 0x0000003C,
D3DFMT_R8B8 = 0x00000029,
D3DFMT_G8B8 = 0x00000028,
D3DFMT_P8 = 0x0000000B,
D3DFMT_L8 = 0x00000000,
D3DFMT_A8L8 = 0x0000001A,
D3DFMT_AL8 = 0x00000001,
D3DFMT_L16 = 0x00000032,
D3DFMT_V8U8 = 0x00000028,
D3DFMT_L6V5U5 = 0x00000027,
D3DFMT_X8L8V8U8 = 0x00000007,
D3DFMT_Q8W8V8U8 = 0x0000003A,
D3DFMT_V16U16 = 0x00000033,
D3DFMT_D16_LOCKABLE = 0x0000002C,
D3DFMT_D16 = 0x0000002C,
D3DFMT_D24S8 = 0x0000002A,
D3DFMT_F16 = 0x0000002D,
D3DFMT_F24S8 = 0x0000002B,
/* YUV formats */
D3DFMT_YUY2 = 0x00000024,
D3DFMT_UYVY = 0x00000025,
/* Compressed formats */
D3DFMT_DXT1 = 0x0000000C,
D3DFMT_DXT2 = 0x0000000E,
D3DFMT_DXT3 = 0x0000000E,
D3DFMT_DXT4 = 0x0000000F,
D3DFMT_DXT5 = 0x0000000F,
/* Linear formats */
D3DFMT_LIN_A1R5G5B5 = 0x00000010,
D3DFMT_LIN_A4R4G4B4 = 0x0000001D,
D3DFMT_LIN_A8 = 0x0000001F,
D3DFMT_LIN_A8B8G8R8 = 0x0000003F,
D3DFMT_LIN_A8R8G8B8 = 0x00000012,
D3DFMT_LIN_B8G8R8A8 = 0x00000040,
D3DFMT_LIN_G8B8 = 0x00000017,
D3DFMT_LIN_R4G4B4A4 = 0x0000003E,
D3DFMT_LIN_R5G5B5A1 = 0x0000003D,
D3DFMT_LIN_R5G6B5 = 0x00000011,
D3DFMT_LIN_R6G5B5 = 0x00000037,
D3DFMT_LIN_R8B8 = 0x00000016,
D3DFMT_LIN_R8G8B8A8 = 0x00000041,
D3DFMT_LIN_X1R5G5B5 = 0x0000001C,
D3DFMT_LIN_X8R8G8B8 = 0x0000001E,
D3DFMT_LIN_A8L8 = 0x00000020,
D3DFMT_LIN_AL8 = 0x0000001B,
D3DFMT_LIN_L16 = 0x00000035,
D3DFMT_LIN_L8 = 0x00000013,
D3DFMT_LIN_V16U16 = 0x00000036,
D3DFMT_LIN_V8U8 = 0x00000017,
D3DFMT_LIN_L6V5U5 = 0x00000037,
D3DFMT_LIN_X8L8V8U8 = 0x0000001E,
D3DFMT_LIN_Q8W8V8U8 = 0x00000012,
D3DFMT_LIN_D24S8 = 0x0000002E,
D3DFMT_LIN_F24S8 = 0x0000002F,
D3DFMT_LIN_D16 = 0x00000030,
D3DFMT_LIN_F16 = 0x00000031,
D3DFMT_VERTEXDATA = 100,
D3DFMT_INDEX16 = 101,
};
}
}

1050
src/d3d/xbox.cpp Normal file

File diff suppressed because it is too large Load Diff