lots of changes to rasters; mostly mipmap support and DXT conversion

This commit is contained in:
aap
2020-11-11 09:34:36 +01:00
parent 3e2080ad56
commit 7e80d45cdb
19 changed files with 895 additions and 328 deletions

View File

@@ -207,11 +207,11 @@ unlockVertices(void *vertexBuffer)
}
void*
createTexture(int32 width, int32 height, int32 numlevels, uint32 format)
createTexture(int32 width, int32 height, int32 numlevels, uint32 usage, uint32 format)
{
#ifdef RW_D3D9
IDirect3DTexture9 *tex;
d3ddevice->CreateTexture(width, height, numlevels, 0,
d3ddevice->CreateTexture(width, height, numlevels, usage,
(D3DFORMAT)format, D3DPOOL_MANAGED, &tex, nil);
if(tex)
d3d9Globals.numTextures++;
@@ -406,11 +406,7 @@ rasterSetFormat(Raster *raster)
natras->hasAlpha = formatInfoRW[(raster->format >> 8) & 0xF].hasAlpha;
raster->stride = raster->width*natras->bpp;
raster->pixels = nil;
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->originalStride = raster->stride;
raster->originalPixels = raster->pixels;
natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP);
}
static Raster*
@@ -421,10 +417,17 @@ rasterCreateTexture(Raster *raster)
if(natras->format == D3DFMT_P8)
natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER);
levels = Raster::calculateNumLevels(raster->width, raster->height);
if(natras->autogenMipmap)
levels = 0;
else if(raster->format & Raster::MIPMAP)
levels = Raster::calculateNumLevels(raster->width, raster->height);
else
levels = 1;
assert(natras->texture == nil);
natras->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? levels : 1,
levels,
natras->autogenMipmap ? D3DUSAGE_AUTOGENMIPMAP : 0,
natras->format);
if(natras->texture == nil){
RWERROR((ERR_NOTEXTURE));
@@ -445,12 +448,17 @@ rasterCreateCameraTexture(Raster *raster)
int32 levels;
D3dRaster *natras = GETD3DRASTEREXT(raster);
levels = Raster::calculateNumLevels(raster->width, raster->height);
if(natras->autogenMipmap)
levels = 0;
else if(raster->format & Raster::MIPMAP)
levels = Raster::calculateNumLevels(raster->width, raster->height);
else
levels = 1;
IDirect3DTexture9 *tex;
d3ddevice->CreateTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? levels : 1,
D3DUSAGE_RENDERTARGET,
levels,
(natras->autogenMipmap ? D3DUSAGE_AUTOGENMIPMAP : 0) | D3DUSAGE_RENDERTARGET,
(D3DFORMAT)natras->format, D3DPOOL_DEFAULT, &tex, nil);
assert(natras->texture == nil);
natras->texture = tex;
@@ -467,10 +475,8 @@ static Raster*
rasterCreateCamera(Raster *raster)
{
D3dRaster *natras = GETD3DRASTEREXT(raster);
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->originalStride = raster->stride = 0;
raster->originalPixels = raster->pixels = nil;
natras->autogenMipmap = 0;
natras->format = d3d9Globals.present.BackBufferFormat;
raster->depth = findFormatDepth(natras->format);
@@ -483,10 +489,8 @@ static Raster*
rasterCreateZbuffer(Raster *raster)
{
D3dRaster *natras = GETD3DRASTEREXT(raster);
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->originalStride = raster->stride = 0;
raster->originalPixels = raster->pixels = nil;
natras->autogenMipmap = 0;
// TODO: allow other formats
natras->format = d3d9Globals.present.AutoDepthStencilFormat;
@@ -518,33 +522,47 @@ rasterCreateZbuffer(Raster *raster)
Raster*
rasterCreate(Raster *raster)
{
D3dRaster *natras = GETD3DRASTEREXT(raster);
rasterSetFormat(raster);
Raster *ret = raster;
if(raster->width == 0 || raster->height == 0){
raster->flags |= Raster::DONTALLOCATE;
raster->stride = 0;
return raster;
goto ret;
}
if(raster->flags & Raster::DONTALLOCATE)
return raster;
goto ret;
switch(raster->type){
case Raster::NORMAL:
case Raster::TEXTURE:
return rasterCreateTexture(raster);
ret = rasterCreateTexture(raster);
break;
#ifdef RW_D3D9
case Raster::CAMERATEXTURE:
return rasterCreateCameraTexture(raster);
ret = rasterCreateCameraTexture(raster);
break;
case Raster::ZBUFFER:
return rasterCreateZbuffer(raster);
ret = rasterCreateZbuffer(raster);
break;
case Raster::CAMERA:
return rasterCreateCamera(raster);
ret = rasterCreateCamera(raster);
break;
#endif
default:
RWERROR((ERR_INVRASTER));
return nil;
}
return nil;
ret:
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->originalStride = raster->stride;
raster->originalPixels = raster->pixels;
return ret;
}
uint8*
@@ -569,7 +587,8 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
case Raster::TEXTURE: {
tex->GetSurfaceLevel(level, &surf);
natras->lockedSurf = surf;
surf->LockRect(&lr, 0, flags);
HRESULT res = surf->LockRect(&lr, 0, flags);
assert(res == D3D_OK);
break;
}
@@ -583,15 +602,17 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
raster->stride = lr.Pitch;
if(raster->width == 0) raster->width = 1;
if(raster->height == 0) raster->height = 1;
#else
RasterLevels *levels = (RasterLevels*)natras->texture;
raster->pixels = levels->levels[level].data;
raster->width = levels->levels[level].width;
raster->height = levels->levels[level].height;
raster->stride = raster->width*natras->bpp;
#endif
if(lockMode & Raster::LOCKREAD) raster->privateFlags |= Raster::PRIVATELOCK_READ;
if(lockMode & Raster::LOCKWRITE) raster->privateFlags |= Raster::PRIVATELOCK_WRITE;
return raster->pixels;
#else
RasterLevels *levels = (RasterLevels*)natras->texture;
return levels->levels[level].data;
#endif
}
void
@@ -701,38 +722,39 @@ rasterFromImage(Raster *raster, Image *image)
}
D3dRaster *natras = GETD3DRASTEREXT(raster);
int32 format = raster->format&0xF00;
switch(image->depth){
case 32:
if(raster->format == Raster::C8888)
if(format == Raster::C8888)
conv = conv_BGRA8888_from_RGBA8888;
else if(raster->format == Raster::C888)
else if(format == Raster::C888)
conv = conv_BGR888_from_RGB888;
else
goto err;
break;
case 24:
if(raster->format == Raster::C8888)
if(format == Raster::C8888)
conv = conv_BGRA8888_from_RGB888;
else if(raster->format == Raster::C888)
else if(format == Raster::C888)
conv = conv_BGR888_from_RGB888;
else
goto err;
break;
case 16:
if(raster->format == Raster::C1555)
if(format == Raster::C1555)
conv = conv_ARGB1555_from_ARGB1555;
else
goto err;
break;
case 8:
if(raster->format == (Raster::PAL8 | Raster::C8888))
if(format == (Raster::PAL8 | Raster::C8888))
conv = conv_8_from_8;
else
goto err;
break;
case 4:
if(raster->format == (Raster::PAL4 | Raster::C8888) ||
raster->format == (Raster::PAL8 | Raster::C8888))
if(format == (Raster::PAL4 | Raster::C8888) ||
format == (Raster::PAL8 | Raster::C8888))
conv = conv_8_from_8;
else
goto err;
@@ -758,7 +780,13 @@ rasterFromImage(Raster *raster, Image *image)
}
}
uint8 *pixels = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
bool unlock = false;
if(raster->pixels == nil){
raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
unlock = true;
}
uint8 *pixels = raster->pixels;
assert(pixels);
uint8 *imgpixels = image->pixels;
@@ -776,7 +804,8 @@ rasterFromImage(Raster *raster, Image *image)
imgpixels += image->stride;
pixels += raster->stride;
}
raster->unlock(0);
if(unlock)
raster->unlock(0);
if(truecolimg)
truecolimg->destroy();
@@ -789,11 +818,23 @@ rasterToImage(Raster *raster)
{
int32 depth;
Image *image;
bool unlock = false;
if(raster->pixels == nil){
raster->lock(0, Raster::LOCKREAD);
unlock = true;
}
D3dRaster *natras = GETD3DRASTEREXT(raster);
if(natras->customFormat){
image = Image::create(raster->width, raster->height, 32);
int w = raster->width;
int h = raster->height;
// pixels are in the upper right corner
if(w < 4) w = 4;
if(h < 4) h = 4;
image = Image::create(w, h, 32);
image->allocate();
uint8 *pix = raster->lock(0, Raster::LOCKREAD);
uint8 *pix = raster->pixels;
switch(natras->format){
case D3DFMT_DXT1:
image->setPixelsDXT(1, pix);
@@ -807,11 +848,17 @@ rasterToImage(Raster *raster)
image->setPixelsDXT(5, pix);
break;
default:
raster->unlock(0);
image->destroy();
if(unlock)
raster->unlock(0);
return nil;
}
raster->unlock(0);
// fix it up again
image->width = raster->width;
image->height = raster->height;
if(unlock)
raster->unlock(0);
return image;
}
@@ -865,7 +912,7 @@ rasterToImage(Raster *raster)
}
uint8 *imgpixels = image->pixels;
uint8 *pixels = raster->lock(0, Raster::LOCKREAD);
uint8 *pixels = raster->pixels;
int x, y;
assert(image->width == raster->width);
@@ -881,10 +928,11 @@ rasterToImage(Raster *raster)
imgpixels += image->stride;
pixels += raster->stride;
}
raster->unlock(0);
image->compressPalette();
if(unlock)
raster->unlock(0);
return image;
}
@@ -916,8 +964,16 @@ allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha)
D3dRaster *ras = GETD3DRASTEREXT(raster);
ras->format = dxtMap[dxt-1];
ras->hasAlpha = hasAlpha;
ras->customFormat = 1;
if(ras->autogenMipmap)
numLevels = 0;
else if(raster->format & Raster::MIPMAP)
{}
else
numLevels = 1;
ras->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? numLevels : 1,
numLevels,
ras->autogenMipmap ? D3DUSAGE_AUTOGENMIPMAP : 0,
ras->format);
raster->flags &= ~Raster::DONTALLOCATE;
}

View File

@@ -468,35 +468,54 @@ readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format
for(int32 i = 0; i < pallen; i++)
palette[i*4+3] = 0xFF;
// Only read one mipmap
for(int32 i = 0; i < numLevels; i++){
uint32 size = stream->readU32();
if(i == 0){
data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_IMAGE);
stream->read8(data, size);
}else
stream->seek(size);
}
Raster *ras = nil;
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;
for(int i = 0; i < numLevels; i++){
if(ras){
ras->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
img->width = ras->width;
img->height = ras->height;
img->stride = img->width*img->bpp;
}
uint32 size = stream->readU32();
// one allocation is enough, first level is largest
if(data == nil)
data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_IMAGE);
stream->read8(data, 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 += img->bpp;
idx++;
}
pixels += img->stride;
}
}
if(ras == nil){
// Important to have filled the image with data
int32 newformat;
Raster::imageFindRasterFormat(img, format&7, &width, &height, &depth, &newformat);
newformat |= format & (Raster::MIPMAP | Raster::AUTOMIPMAP);
ras = Raster::create(width, height, depth, newformat);
ras->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
}
ras->setFromImage(img);
ras->unlock(i);
}
rwFree(data);
Raster *ras = Raster::createFromImage(img, PLATFORM_D3D8);
img->destroy();
return ras;
}
@@ -545,7 +564,7 @@ readNativeTexture(Stream *stream)
Raster *raster;
D3dRaster *ras;
if(compression){
raster = Raster::create(width, height, depth, format | type | 0x80, PLATFORM_D3D8);
raster = Raster::create(width, height, depth, format | type | Raster::DONTALLOCATE, PLATFORM_D3D8);
ras = GETD3DRASTEREXT(raster);
allocateDXT(raster, compression, numLevels, hasAlpha);
ras->customFormat = 1;

View File

@@ -751,6 +751,7 @@ readNativeTexture(Stream *stream)
ext->hasAlpha = flags & 1;
ext->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? numLevels : 1,
0,
ext->format);
assert(ext->texture);
raster->flags &= ~Raster::DONTALLOCATE;
@@ -811,7 +812,9 @@ writeNativeTexture(Texture *tex, Stream *stream)
uint8 flags = 0;
if(ext->hasAlpha)
flags |= 1;
// no automipmapgen and cube supported yet
// no cube supported yet
if(ext->autogenMipmap)
flags |= 4;
if(ext->customFormat)
flags |= 8;
stream->writeU8(flags);

View File

@@ -170,12 +170,16 @@ static uint32 cullmodeMap[] = {
D3DCULL_CCW
};
// TODO: support mipmaps
static uint32 filterConvMap_NoMIP[] = {
static uint32 filterConvMap[] = {
0, D3DTEXF_POINT, D3DTEXF_LINEAR,
D3DTEXF_POINT, D3DTEXF_LINEAR,
D3DTEXF_POINT, D3DTEXF_LINEAR
};
static uint32 filterConvMap_MIP[] = {
0, D3DTEXF_NONE, D3DTEXF_NONE,
D3DTEXF_POINT, D3DTEXF_POINT,
D3DTEXF_LINEAR, D3DTEXF_LINEAR
};
static uint32 addressConvMap[] = {
0, D3DTADDRESS_WRAP, D3DTADDRESS_MIRROR,
D3DTADDRESS_CLAMP, D3DTADDRESS_BORDER
@@ -304,8 +308,9 @@ restoreD3d9Device(void)
d3ddevice->SetTexture(i, nil);
setSamplerState(i, D3DSAMP_ADDRESSU, addressConvMap[rwStateCache.texstage[i].addressingU]);
setSamplerState(i, D3DSAMP_ADDRESSV, addressConvMap[rwStateCache.texstage[i].addressingV]);
setSamplerState(i, D3DSAMP_MAGFILTER, filterConvMap_NoMIP[rwStateCache.texstage[i].filter]);
setSamplerState(i, D3DSAMP_MINFILTER, filterConvMap_NoMIP[rwStateCache.texstage[i].filter]);
setSamplerState(i, D3DSAMP_MAGFILTER, filterConvMap[rwStateCache.texstage[i].filter]);
setSamplerState(i, D3DSAMP_MINFILTER, filterConvMap[rwStateCache.texstage[i].filter]);
setSamplerState(i, D3DSAMP_MIPFILTER, filterConvMap_MIP[rwStateCache.texstage[i].filter]);
}
for(s = 0; s < MAXNUMSTATES; s++)
if(validStates[s])
@@ -438,11 +443,11 @@ setRasterStage(uint32 stage, Raster *raster)
static void
setFilterMode(uint32 stage, int32 filter)
{
// TODO: mip mapping
if(rwStateCache.texstage[stage].filter != (Texture::FilterMode)filter){
rwStateCache.texstage[stage].filter = (Texture::FilterMode)filter;
setSamplerState(stage, D3DSAMP_MAGFILTER, filterConvMap_NoMIP[filter]);
setSamplerState(stage, D3DSAMP_MINFILTER, filterConvMap_NoMIP[filter]);
setSamplerState(stage, D3DSAMP_MAGFILTER, filterConvMap[filter]);
setSamplerState(stage, D3DSAMP_MINFILTER, filterConvMap[filter]);
setSamplerState(stage, D3DSAMP_MIPFILTER, filterConvMap_MIP[filter]);
}
}

View File

@@ -234,6 +234,9 @@ enum {
D3DDECLUSAGE_FOG, // 11
D3DDECLUSAGE_DEPTH, // 12
D3DDECLUSAGE_SAMPLE // 13
,
D3DUSAGE_AUTOGENMIPMAP = 0x400
};
#endif
@@ -249,7 +252,7 @@ void destroyVertexBuffer(void *vertexBuffer);
uint8 *lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags);
void unlockVertices(void *vertexBuffer);
void *createTexture(int32 width, int32 height, int32 levels, uint32 format);
void *createTexture(int32 width, int32 height, int32 levels, uint32 usage, uint32 format);
void destroyTexture(void *texture);
uint8 *lockTexture(void *texture, int32 level);
void unlockTexture(void *texture, int32 level);
@@ -263,8 +266,9 @@ struct D3dRaster
void *lockedSurf;
uint32 format;
uint32 bpp; // bytes per pixel
bool32 hasAlpha;
bool32 customFormat;
bool hasAlpha;
bool customFormat;
bool autogenMipmap;
};
int32 getLevelSize(Raster *raster, int32 level);

View File

@@ -84,7 +84,9 @@ struct XboxRaster
void *texture;
void *palette;
uint32 format;
bool32 hasAlpha;
uint32 bpp; // bytes per pixel
bool hasAlpha;
bool customFormat;
bool32 unknownFlag;
};
@@ -92,6 +94,7 @@ int32 getLevelSize(Raster *raster, int32 level);
extern int32 nativeRasterOffset;
void registerNativeRaster(void);
#define GETXBOXRASTEREXT(raster) PLUGINOFFSET(rw::xbox::XboxRaster, raster, rw::xbox::nativeRasterOffset)
Texture *readNativeTexture(Stream *stream);
void writeNativeTexture(Texture *tex, Stream *stream);

View File

@@ -522,97 +522,137 @@ createTexture(int32 width, int32 height, int32 numlevels, uint32 format)
return levels;
}
struct RasterFormatInfo
{
uint32 d3dformat;
int32 depth;
bool32 hasAlpha;
uint32 rwFormat;
};
// indexed directly by RW format
static RasterFormatInfo formatInfoRW[16] = {
{ 0, 0, 0},
{ D3DFMT_A1R5G5B5, 16, 1, Raster::C1555 },
{ D3DFMT_R5G6B5, 16, 0, Raster::C565 },
{ D3DFMT_A4R4G4B4, 16, 1, Raster::C4444 },
{ D3DFMT_L8, 8, 0, Raster::LUM8 },
{ D3DFMT_A8R8G8B8, 32, 1, Raster::C8888 },
{ D3DFMT_X8R8G8B8, 32, 0, Raster::C888 },
{ D3DFMT_UNKNOWN, 16, 0, Raster::D16 },
{ D3DFMT_UNKNOWN, 32, 0, Raster::D24 },
{ D3DFMT_UNKNOWN, 32, 0, Raster::D32 },
{ D3DFMT_X1R5G5B5, 16, 0, Raster::C555 }
};
static void
rasterSetFormat(Raster *raster)
{
assert(raster->format != 0); // no default yet
XboxRaster *natras = GETXBOXRASTEREXT(raster);
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
natras->format = D3DFMT_P8;
raster->depth = 8;
}else{
natras->format = formatInfoRW[(raster->format >> 8) & 0xF].d3dformat;
raster->depth = formatInfoRW[(raster->format >> 8) & 0xF].depth;
}
natras->bpp = raster->depth/8;
natras->hasAlpha = formatInfoRW[(raster->format >> 8) & 0xF].hasAlpha;
raster->stride = raster->width&natras->bpp;
}
static Raster*
rasterCreateTexture(Raster *raster)
{
XboxRaster *natras = GETXBOXRASTEREXT(raster);
int32 levels;
if(natras->format == D3DFMT_P8)
natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER);
levels = Raster::calculateNumLevels(raster->width, raster->height);
assert(natras->texture == nil);
natras->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? levels : 1,
natras->format);
if(natras->texture == nil){
RWERROR((ERR_NOTEXTURE));
return nil;
}
return raster;
}
Raster*
rasterCreate(Raster *raster)
{
static uint32 formatMap[] = {
D3DFMT_UNKNOWN,
D3DFMT_A1R5G5B5,
D3DFMT_R5G6B5,
D3DFMT_A4R4G4B4,
D3DFMT_L8,
D3DFMT_A8R8G8B8,
D3DFMT_X8R8G8B8,
D3DFMT_UNKNOWN,
D3DFMT_UNKNOWN,
D3DFMT_UNKNOWN,
D3DFMT_X1R5G5B5,
D3DFMT_UNKNOWN,
D3DFMT_UNKNOWN,
D3DFMT_UNKNOWN,
D3DFMT_UNKNOWN,
D3DFMT_UNKNOWN
};
static bool32 alphaMap[] = {
0,
1,
0,
1,
0,
1,
0,
0, 0, 0,
0,
0, 0, 0, 0, 0
};
rasterSetFormat(raster);
XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
uint32 format;
int32 levels;
Raster *ret = raster;
// Dummy to use as subraster
if(raster->width == 0 || raster->height == 0){
raster->flags |= Raster::DONTALLOCATE;
raster->stride = 0;
return raster;
goto ret;
}
if(raster->flags & Raster::DONTALLOCATE)
goto ret;
switch(raster->type){
case Raster::NORMAL:
case Raster::TEXTURE:
if(raster->flags & Raster::DONTALLOCATE)
return raster;
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 = 0;
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);
if(natras->texture == nil){
RWERROR((ERR_NOTEXTURE));
return nil;
}
return raster;
ret = rasterCreateTexture(raster);
break;
default:
RWERROR((ERR_INVRASTER));
return nil;
}
// unsupported
return nil;
ret:
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->originalStride = raster->stride;
raster->originalPixels = raster->pixels;
return ret;
}
uint8*
rasterLock(Raster *raster, int32 level, int32 lockMode)
{
// TODO?
(void)lockMode;
XboxRaster *natras = GETXBOXRASTEREXT(raster);
// check if already locked
if(raster->privateFlags & (Raster::PRIVATELOCK_READ|Raster::PRIVATELOCK_WRITE))
return nil;
XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
RasterLevels *levels = (RasterLevels*)natras->texture;
return levels->levels[level].data;
raster->pixels = levels->levels[level].data;
raster->width = levels->levels[level].width;
raster->height = levels->levels[level].height;
raster->stride = raster->width*natras->bpp;
if(lockMode & Raster::LOCKREAD) raster->privateFlags |= Raster::PRIVATELOCK_READ;
if(lockMode & Raster::LOCKWRITE) raster->privateFlags |= Raster::PRIVATELOCK_WRITE;
return raster->pixels;
}
void
rasterUnlock(Raster*, int32)
rasterUnlock(Raster *raster, int32 level)
{
raster->width = raster->originalWidth;
raster->height = raster->originalHeight;
raster->stride = raster->originalStride;
raster->pixels = raster->originalPixels;
raster->privateFlags &= ~(Raster::PRIVATELOCK_READ|Raster::PRIVATELOCK_WRITE);
}
int32
rasterNumLevels(Raster *raster)
{
XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
XboxRaster *natras = GETXBOXRASTEREXT(raster);
RasterLevels *levels = (RasterLevels*)natras->texture;
return levels->numlevels;
}
@@ -656,12 +696,23 @@ rasterToImage(Raster *raster)
{
int32 depth;
Image *image;
XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
if(natras->format){
image = Image::create(raster->width, raster->height, 32);
bool unlock = false;
if(raster->pixels == nil){
raster->lock(0, Raster::LOCKREAD);
unlock = true;
}
XboxRaster *natras = GETXBOXRASTEREXT(raster);
if(natras->customFormat){
int w = raster->width;
int h = raster->height;
// pixels are in the upper right corner
if(w < 4) w = 4;
if(h < 4) h = 4;
image = Image::create(w, h, 32);
image->allocate();
uint8 *pix = raster->lock(0, Raster::LOCKREAD);
uint8 *pix = raster->pixels;
switch(natras->format){
case D3DFMT_DXT1:
image->setPixelsDXT(1, pix);
@@ -677,11 +728,17 @@ rasterToImage(Raster *raster)
break;
default:
assert(0 && "unknown format");
raster->unlock(0);
image->destroy();
if(unlock)
raster->unlock(0);
return nil;
}
raster->unlock(0);
// fix it up again
image->width = raster->width;
image->height = raster->height;
if(unlock)
raster->unlock(0);
return image;
}
@@ -714,48 +771,51 @@ rasterToImage(Raster *raster)
pallength = 256;
}
uint8 *in, *out;
image = Image::create(raster->width, raster->height, depth);
image->allocate();
if(pallength){
out = image->palette;
in = (uint8*)natras->palette;
uint8 *out = image->palette;
uint8 *in = (uint8*)natras->palette;
// bytes are BGRA unlike regular d3d!
for(int32 i = 0; i < pallength; i++){
out[0] = in[2];
out[1] = in[1];
out[2] = in[0];
out[3] = in[3];
conv_BGRA8888_from_RGBA8888(out, in);
in += 4;
out += 4;
}
}
out = image->pixels;
in = raster->lock(0, Raster::LOCKREAD);
uint8 *imgpixels = image->pixels;
uint8 *pixels = raster->pixels;
unswizzle(out, in, image->width, image->height, depth < 8 ? 1 : depth/8);
// NB:
assert(image->bpp == natras->bpp);
assert(image->stride == raster->stride);
unswizzle(imgpixels, pixels, image->width, image->height, image->bpp);
// Fix RGB order
// TODO: stride
uint8 tmp;
if(depth > 8)
for(int32 y = 0; y < image->height; y++)
for(int32 x = 0; x < image->width; x++)
for(int32 y = 0; y < image->height; y++){
uint8 *imgrow = imgpixels;
// uint8 *rasrow = pixels;
for(int32 x = 0; x < image->width; x++){
switch(raster->format & 0xF00){
case Raster::C8888:
tmp = out[0];
out[0] = out[2];
out[2] = tmp;
out += 4;
break;
case Raster::C888:
tmp = out[0];
out[0] = out[2];
out[2] = tmp;
out += 3;
tmp = imgrow[0];
imgrow[0] = imgrow[2];
imgrow[2] = tmp;
imgrow += image->bpp;
break;
}
raster->unlock(0);
}
imgpixels += image->stride;
// pixels += raster->stride;
}
image->compressPalette();
if(unlock)
raster->unlock(0);
return image;
}
@@ -763,7 +823,7 @@ rasterToImage(Raster *raster)
int32
getLevelSize(Raster *raster, int32 level)
{
XboxRaster *ras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
XboxRaster *ras = GETXBOXRASTEREXT(raster);
RasterLevels *levels = (RasterLevels*)ras->texture;
return levels->levels[level].size;
}
@@ -776,6 +836,7 @@ createNativeRaster(void *object, int32 offset, int32)
raster->palette = nil;
raster->format = 0;
raster->hasAlpha = 0;
raster->customFormat = 0;
raster->unknownFlag = 0;
return object;
}
@@ -836,6 +897,9 @@ readNativeTexture(Stream *stream)
stream->read8(tex->name, 32);
stream->read8(tex->mask, 32);
//if(strcmp(tex->name, "bluallu") == 0)
//__debugbreak();
// Raster
int32 format = stream->readI32();
bool32 hasAlpha = stream->readI16();
@@ -853,16 +917,17 @@ readNativeTexture(Stream *stream)
Raster *raster;
if(compression){
raster = Raster::create(width, height, depth, format | type | Raster::DONTALLOCATE, PLATFORM_XBOX);
XboxRaster *ras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
XboxRaster *ras = GETXBOXRASTEREXT(raster);
ras->format = compression;
ras->hasAlpha = hasAlpha;
ras->texture = createTexture(raster->width, raster->height,
raster->format & Raster::MIPMAP ? numLevels : 1,
ras->format);
ras->customFormat = 1;
raster->flags &= ~Raster::DONTALLOCATE;
}else
raster = Raster::create(width, height, depth, format | type, PLATFORM_XBOX);
XboxRaster *ras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
XboxRaster *ras = GETXBOXRASTEREXT(raster);
tex->raster = raster;
if(raster->format & Raster::PAL4)
@@ -892,7 +957,7 @@ writeNativeTexture(Texture *tex, Stream *stream)
// Raster
Raster *raster = tex->raster;
XboxRaster *ras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
XboxRaster *ras = GETXBOXRASTEREXT(raster);
int32 numLevels = raster->getNumLevels();
stream->writeI32(raster->format);
stream->writeI16(ras->hasAlpha);