d3d: camera textures

This commit is contained in:
aap 2018-01-08 12:55:15 +01:00
parent d7406e30fb
commit 0c5295fe10
2 changed files with 155 additions and 42 deletions

View File

@ -114,6 +114,9 @@ enum {
};
#endif
void addVidmemRaster(Raster *raster);
void removeVidmemRaster(Raster *raster);
// stolen from d3d8to9
static uint32
calculateTextureSize(uint32 width, uint32 height, uint32 depth, uint32 format)
@ -347,37 +350,76 @@ deleteObject(void *object)
int32 nativeRasterOffset;
struct RasterFormatInfo
{
uint32 d3dformat;
int32 depth;
bool32 hasAlpha;
};
static RasterFormatInfo formatInfo[16] = {
{ 0, 0, 0},
{ D3DFMT_A1R5G5B5, 16, 1 }, // C1555
{ D3DFMT_R5G6B5, 16, 0 }, // C565
{ D3DFMT_A4R4G4B4, 16, 1 }, // C4444
{ D3DFMT_L8, 8, 0 }, // LUM8
{ D3DFMT_A8R8G8B8, 32, 1 }, // C8888
{ D3DFMT_X8R8G8B8, 32, 0 }, // C888
{ D3DFMT_D16, 16, 0 }, // D16
{ D3DFMT_D24X8, 32, 0 }, // D24
{ D3DFMT_D32, 32, 0 }, // D32
{ D3DFMT_X1R5G5B5, 16, 0 }, // C555
};
static void
rasterCreateTexture(Raster *raster)
{
uint32 format;
int32 levels;
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
format = D3DFMT_P8;
natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER);
}else
format = formatInfo[(raster->format >> 8) & 0xF].d3dformat;
natras->format = format;
natras->hasAlpha = formatInfo[(raster->format >> 8) & 0xF].hasAlpha;
levels = Raster::calculateNumLevels(raster->width, raster->height);
natras->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? levels : 1,
format);
}
static void
rasterCreateCameraTexture(Raster *raster)
{
if(raster->format & (Raster::PAL4 | Raster::PAL8))
// TODO: give some error
return;
int32 levels;
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
natras->format = formatInfo[(raster->format >> 8) & 0xF].d3dformat;
natras->hasAlpha = formatInfo[(raster->format >> 8) & 0xF].hasAlpha;
levels = Raster::calculateNumLevels(raster->width, raster->height);
#ifdef RW_D3D9
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;
addVidmemRaster(raster);
#else
natras->texture = nil;
#endif
}
void
rasterCreate(Raster *raster)
{
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
};
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
uint32 format;
int32 levels;
// Dummy to use as subraster
if(raster->width == 0 || raster->height == 0){
@ -391,17 +433,7 @@ rasterCreate(Raster *raster)
case Raster::TEXTURE:
if(raster->flags & Raster::DONTALLOCATE)
return;
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
format = D3DFMT_P8;
natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER);
}else
format = formatMap[(raster->format >> 8) & 0xF];
natras->format = format;
natras->hasAlpha = alphaMap[(raster->format >> 8) & 0xF];
levels = Raster::calculateNumLevels(raster->width, raster->height);
natras->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? levels : 1,
format);
rasterCreateTexture(raster);
break;
case Raster::ZBUFFER:
@ -417,8 +449,9 @@ rasterCreate(Raster *raster)
raster->pixels = nil;
break;
case Raster::CAMERATEXTURE:
raster->flags |= Raster::DONTALLOCATE;
// TODO
if(raster->flags & Raster::DONTALLOCATE)
return;
rasterCreateCameraTexture(raster);
break;
}
}
@ -731,8 +764,15 @@ createNativeRaster(void *object, int32 offset, int32)
static void*
destroyNativeRaster(void *object, int32 offset, int32)
{
// TODO:
(void)offset;
Raster *raster = (Raster*)object;
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, offset);
#ifdef RW_D3D9
if(raster->type == Raster::CAMERATEXTURE)
removeVidmemRaster(raster);
#endif
if(natras->texture)
deleteObject(natras->texture);
rwFree(natras->palette);
return object;
}

View File

@ -27,6 +27,17 @@ struct D3d9Globals
int presentWidth, presentHeight;
} d3d9Globals;
// 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);
// cached RW render states
static bool32 vertexAlpha;
static bool32 textureAlpha;
@ -494,6 +505,66 @@ endUpdate(Camera *cam)
d3ddevice->EndScene();
}
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;
}
}
}
static void
clearCamera(Camera *cam, RGBA *col, uint32 mode)
{
@ -510,6 +581,8 @@ clearCamera(Camera *cam, RGBA *col, uint32 mode)
Raster *ras = cam->frameBuffer;
if(!icon &&
(r.right != d3d9Globals.presentWidth || r.bottom != d3d9Globals.presentHeight)){
releaseVidmemRasters();
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = r.right;
d3dpp.BackBufferHeight = r.bottom;