work on rasters

This commit is contained in:
aap 2019-08-07 22:37:43 +02:00
parent 0c8398c7e4
commit 5685e6109e
17 changed files with 314 additions and 240 deletions

View File

@ -500,7 +500,7 @@ Camera::setFOV(float32 hfov, float32 ratio)
} }
hfov = hfov*3.14159f/360.0f; // deg to rad and halved hfov = hfov*3.14159f/360.0f; // deg to rad and halved
float ar1 = 4.0/3.0; float ar1 = 4.0f/3.0f;
float ar2 = w/h; float ar2 = w/h;
float vfov = atanf(tanf(hfov/2) / ar1) *2; float vfov = atanf(tanf(hfov/2) / ar1) *2;
hfov = atanf(tanf(vfov/2) * ar2) *2; hfov = atanf(tanf(vfov/2) * ar2) *2;

View File

@ -309,8 +309,10 @@ createTexture(int32 width, int32 height, int32 numlevels, uint32 format)
} }
uint8* uint8*
lockTexture(void *texture, int32 level) lockTexture(void *texture, int32 level, int32 lockMode)
{ {
// TODO: don't ignore this
(void)lockMode;
#ifdef RW_D3D9 #ifdef RW_D3D9
IDirect3DTexture9 *tex = (IDirect3DTexture9*)texture; IDirect3DTexture9 *tex = (IDirect3DTexture9*)texture;
D3DLOCKED_RECT lr; D3DLOCKED_RECT lr;
@ -458,10 +460,10 @@ rasterCreate(Raster *raster)
} }
uint8* uint8*
rasterLock(Raster *raster, int32 level) rasterLock(Raster *raster, int32 level, int32 lockMode)
{ {
D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
return lockTexture(natras->texture, level); return lockTexture(natras->texture, level, lockMode);
} }
void void
@ -546,7 +548,7 @@ rasterFromImage(Raster *raster, Image *image)
int32 inc = image->bpp; int32 inc = image->bpp;
in = image->pixels; in = image->pixels;
out = raster->lock(0); out = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
if(pallength) if(pallength)
memcpy(out, in, raster->width*raster->height); memcpy(out, in, raster->width*raster->height);
else else
@ -592,7 +594,7 @@ rasterToImage(Raster *raster)
if(natras->customFormat){ if(natras->customFormat){
image = Image::create(raster->width, raster->height, 32); image = Image::create(raster->width, raster->height, 32);
image->allocate(); image->allocate();
uint8 *pix = raster->lock(0); uint8 *pix = raster->lock(0, Raster::LOCKREAD);
switch(natras->format){ switch(natras->format){
case D3DFMT_DXT1: case D3DFMT_DXT1:
image->setPixelsDXT(1, pix); image->setPixelsDXT(1, pix);
@ -660,7 +662,7 @@ rasterToImage(Raster *raster)
} }
out = image->pixels; out = image->pixels;
in = raster->lock(0); in = raster->lock(0, Raster::LOCKREAD);
if(pallength) if(pallength)
memcpy(out, in, raster->width*raster->height); memcpy(out, in, raster->width*raster->height);
else else
@ -745,7 +747,7 @@ setPalette(Raster *raster, void *palette, int32 size)
void void
setTexels(Raster *raster, void *texels, int32 level) setTexels(Raster *raster, void *texels, int32 level)
{ {
uint8 *dst = raster->lock(level); uint8 *dst = raster->lock(level, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
memcpy(dst, texels, getLevelSize(raster, level)); memcpy(dst, texels, getLevelSize(raster, level));
raster->unlock(level); raster->unlock(level);
} }

View File

@ -549,7 +549,7 @@ readNativeTexture(Stream *stream)
for(int32 i = 0; i < numLevels; i++){ for(int32 i = 0; i < numLevels; i++){
size = stream->readU32(); size = stream->readU32();
if(i < raster->getNumLevels()){ if(i < raster->getNumLevels()){
data = raster->lock(i); data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
stream->read(data, size); stream->read(data, size);
raster->unlock(i); raster->unlock(i);
}else }else
@ -612,7 +612,7 @@ writeNativeTexture(Texture *tex, Stream *stream)
for(int32 i = 0; i < numLevels; i++){ for(int32 i = 0; i < numLevels; i++){
size = getLevelSize(raster, i); size = getLevelSize(raster, i);
stream->writeU32(size); stream->writeU32(size);
data = raster->lock(i); data = raster->lock(i, Raster::LOCKREAD);
stream->write(data, size); stream->write(data, size);
raster->unlock(i); raster->unlock(i);
} }

View File

@ -669,7 +669,7 @@ readNativeTexture(Stream *stream)
for(int32 i = 0; i < numLevels; i++){ for(int32 i = 0; i < numLevels; i++){
size = stream->readU32(); size = stream->readU32();
if(i < raster->getNumLevels()){ if(i < raster->getNumLevels()){
data = raster->lock(i); data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
stream->read(data, size); stream->read(data, size);
raster->unlock(i); raster->unlock(i);
}else }else
@ -719,7 +719,7 @@ writeNativeTexture(Texture *tex, Stream *stream)
for(int32 i = 0; i < numLevels; i++){ for(int32 i = 0; i < numLevels; i++){
size = getLevelSize(raster, i); size = getLevelSize(raster, i);
stream->writeU32(size); stream->writeU32(size);
data = raster->lock(i); data = raster->lock(i, Raster::LOCKREAD);
stream->write(data, size); stream->write(data, size);
raster->unlock(i); raster->unlock(i);
} }

View File

@ -21,7 +21,7 @@ void im3DEnd(void);
#endif #endif
void rasterCreate(Raster *raster); void rasterCreate(Raster *raster);
uint8 *rasterLock(Raster *raster, int32 level); uint8 *rasterLock(Raster *raster, int32 level, int32 lockMode);
void rasterUnlock(Raster *raster, int32 level); void rasterUnlock(Raster *raster, int32 level);
int32 rasterNumLevels(Raster *raster); int32 rasterNumLevels(Raster *raster);
void rasterFromImage(Raster *raster, Image *image); void rasterFromImage(Raster *raster, Image *image);

View File

@ -2,7 +2,7 @@ namespace rw {
namespace xbox { namespace xbox {
void rasterCreate(Raster *raster); void rasterCreate(Raster *raster);
uint8 *rasterLock(Raster *raster, int32 level); uint8 *rasterLock(Raster *raster, int32 level, int32 lockMode);
void rasterUnlock(Raster*, int32); void rasterUnlock(Raster*, int32);
int32 rasterNumLevels(Raster *raster); int32 rasterNumLevels(Raster *raster);
Image *rasterToImage(Raster *raster); Image *rasterToImage(Raster *raster);

View File

@ -580,8 +580,11 @@ rasterCreate(Raster *raster)
} }
uint8* uint8*
rasterLock(Raster *raster, int32 level) rasterLock(Raster *raster, int32 level, int32 lockMode)
{ {
// TODO?
(void)lockMode;
XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset); XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
RasterLevels *levels = (RasterLevels*)natras->texture; RasterLevels *levels = (RasterLevels*)natras->texture;
return levels->levels[level].data; return levels->levels[level].data;
@ -644,7 +647,7 @@ rasterToImage(Raster *raster)
if(natras->format){ if(natras->format){
image = Image::create(raster->width, raster->height, 32); image = Image::create(raster->width, raster->height, 32);
image->allocate(); image->allocate();
uint8 *pix = raster->lock(0); uint8 *pix = raster->lock(0, Raster::LOCKREAD);
switch(natras->format){ switch(natras->format){
case D3DFMT_DXT1: case D3DFMT_DXT1:
image->setPixelsDXT(1, pix); image->setPixelsDXT(1, pix);
@ -715,7 +718,7 @@ rasterToImage(Raster *raster)
} }
out = image->pixels; out = image->pixels;
in = raster->lock(0); in = raster->lock(0, Raster::LOCKREAD);
unswizzle(out, in, image->width, image->height, depth < 8 ? 1 : depth/8); unswizzle(out, in, image->width, image->height, depth < 8 ? 1 : depth/8);
// Fix RGB order // Fix RGB order
@ -854,7 +857,7 @@ readNativeTexture(Stream *stream)
stream->read(ras->palette, 4*256); stream->read(ras->palette, 4*256);
// exploit the fact that mipmaps are allocated consecutively // exploit the fact that mipmaps are allocated consecutively
uint8 *data = raster->lock(0); uint8 *data = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
stream->read(data, totalSize); stream->read(data, totalSize);
raster->unlock(0); raster->unlock(0);
@ -899,7 +902,7 @@ writeNativeTexture(Texture *tex, Stream *stream)
stream->write(ras->palette, 4*256); stream->write(ras->palette, 4*256);
// exploit the fact that mipmaps are allocated consecutively // exploit the fact that mipmaps are allocated consecutively
uint8 *data = raster->lock(0); uint8 *data = raster->lock(0, Raster::LOCKREAD);
stream->write(data, totalSize); stream->write(data, totalSize);
raster->unlock(0); raster->unlock(0);
} }

View File

@ -138,6 +138,8 @@ Engine::open(void)
engine->driver[i]->rasterCreate = null::rasterCreate; engine->driver[i]->rasterCreate = null::rasterCreate;
engine->driver[i]->rasterLock = null::rasterLock; engine->driver[i]->rasterLock = null::rasterLock;
engine->driver[i]->rasterUnlock = null::rasterUnlock; engine->driver[i]->rasterUnlock = null::rasterUnlock;
engine->driver[i]->rasterLockPalette = null::rasterLockPalette;
engine->driver[i]->rasterUnlockPalette = null::rasterUnlockPalette;
engine->driver[i]->rasterNumLevels = null::rasterNumLevels; engine->driver[i]->rasterNumLevels = null::rasterNumLevels;
engine->driver[i]->rasterFromImage = null::rasterFromImage; engine->driver[i]->rasterFromImage = null::rasterFromImage;
engine->driver[i]->rasterToImage = null::rasterToImage; engine->driver[i]->rasterToImage = null::rasterToImage;
@ -225,7 +227,7 @@ rasterCreate(Raster*)
} }
uint8* uint8*
rasterLock(Raster*, int32) rasterLock(Raster*, int32, int32)
{ {
assert(0 && "lockRaster not implemented"); assert(0 && "lockRaster not implemented");
return nil; return nil;
@ -237,6 +239,19 @@ rasterUnlock(Raster*, int32)
assert(0 && "unlockRaster not implemented"); assert(0 && "unlockRaster not implemented");
} }
uint8*
rasterLockPalette(Raster*, int32)
{
assert(0 && "rasterLockPalette not implemented");
return nil;
}
void
rasterUnlockPalette(Raster*)
{
assert(0 && "rasterUnlockPalette not implemented");
}
int32 int32
rasterNumLevels(Raster*) rasterNumLevels(Raster*)
{ {

View File

@ -95,7 +95,7 @@ rasterCreate(Raster *raster)
} }
uint8* uint8*
rasterLock(Raster*, int32 level) rasterLock(Raster*, int32 level, int32 lockMode)
{ {
printf("locking\n"); printf("locking\n");
return nil; return nil;

View File

@ -23,7 +23,7 @@ void im3DEnd(void);
#endif #endif
void rasterCreate(Raster *raster); void rasterCreate(Raster *raster);
uint8 *rasterLock(Raster*, int32 level); uint8 *rasterLock(Raster*, int32 level, int32 lockMode);
void rasterUnlock(Raster*, int32); void rasterUnlock(Raster*, int32);
int32 rasterNumLevels(Raster*); int32 rasterNumLevels(Raster*);
void rasterFromImage(Raster *raster, Image *image); void rasterFromImage(Raster *raster, Image *image);

View File

@ -32,6 +32,8 @@ driverOpen(void *o, int32, int32)
engine->driver[PLATFORM_PS2]->rasterCreate = rasterCreate; engine->driver[PLATFORM_PS2]->rasterCreate = rasterCreate;
engine->driver[PLATFORM_PS2]->rasterLock = rasterLock; engine->driver[PLATFORM_PS2]->rasterLock = rasterLock;
engine->driver[PLATFORM_PS2]->rasterUnlock = rasterUnlock; engine->driver[PLATFORM_PS2]->rasterUnlock = rasterUnlock;
engine->driver[PLATFORM_PS2]->rasterLockPalette = rasterLockPalette;
engine->driver[PLATFORM_PS2]->rasterUnlockPalette = rasterUnlockPalette;
engine->driver[PLATFORM_PS2]->rasterNumLevels = rasterNumLevels; engine->driver[PLATFORM_PS2]->rasterNumLevels = rasterNumLevels;
engine->driver[PLATFORM_PS2]->rasterFromImage = rasterFromImage; engine->driver[PLATFORM_PS2]->rasterFromImage = rasterFromImage;
engine->driver[PLATFORM_PS2]->rasterToImage = rasterToImage; engine->driver[PLATFORM_PS2]->rasterToImage = rasterToImage;

View File

@ -19,6 +19,15 @@
namespace rw { namespace rw {
namespace ps2 { namespace ps2 {
enum
{
// from RW
PS2LOCK_READ = 0x02,
PS2LOCK_WRITE = 0x04,
PS2LOCK_READ_PALETTE = 0x08,
PS2LOCK_WRITE_PALETTE = 0x10,
};
int32 nativeRasterOffset; int32 nativeRasterOffset;
#define MAXLEVEL(r) ((r)->tex1low >> 2) #define MAXLEVEL(r) ((r)->tex1low >> 2)
@ -1345,168 +1354,217 @@ rasterCreate(Raster *raster)
} }
uint8* static uint32
rasterLock(Raster *raster, int32 level) swizzle(uint32 x, uint32 y, uint32 logw)
{ {
#define X(n) ((x>>(n))&1)
#define Y(n) ((y>>(n))&1)
uint32 nx, ny, n;
x ^= (Y(1)^Y(2))<<2;
nx = x&7 | (x>>1)&~7;
ny = y&1 | (y>>1)&~1;
n = Y(1) | X(3)<<1;
return n | nx<<2 | ny<<logw-1+2;
}
void
unswizzleRaster(Raster *raster)
{
uint8 tmpbuf[1024*4]; // 1024x4px, maximum possible width
uint32 mask;
int32 x, y, w, h;
int32 i;
int32 logw;
Ps2Raster *natras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
uint8 *px;
if((raster->format & (Raster::PAL4|Raster::PAL8)) == 0)
return;
int minw, minh;
transferMinSize(raster->format & Raster::PAL4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
w = max(raster->width, minw);
h = max(raster->height, minh);
px = raster->pixels;
logw = 0;
for(i = 1; i < raster->width; i *= 2) logw++;
mask = (1<<logw+2)-1;
if(raster->format & Raster::PAL4 && natras->flags & Ps2Raster::SWIZZLED4){
for(y = 0; y < h; y += 4){
memcpy(tmpbuf, &px[y<<logw-1], 2*w);
for(i = 0; i < 4; i++)
for(x = 0; x < w; x++){
uint32 a = (y+i<<logw)+x;
uint32 s = swizzle(x, y+i, logw)&mask;
uint8 c = s & 1 ? tmpbuf[s>>1] >> 4 : tmpbuf[s>>1] & 0xF;
px[a>>1] = a & 1 ? px[a>>1]&0xF | c<<4 : px[a>>1]&0xF0 | c;
}
}
}else if(raster->format & Raster::PAL8 && natras->flags & Ps2Raster::SWIZZLED8){
for(y = 0; y < h; y += 4){
memcpy(tmpbuf, &px[y<<logw], 4*w);
for(i = 0; i < 4; i++)
for(x = 0; x < w; x++){
uint32 a = (y+i<<logw)+x;
uint32 s = swizzle(x, y+i, logw)&mask;
px[a] = tmpbuf[s];
}
}
}
}
void
swizzleRaster(Raster *raster)
{
uint8 tmpbuf[1024*4]; // 1024x4px, maximum possible width
uint32 mask;
int32 x, y, w, h;
int32 i;
int32 logw;
Ps2Raster *natras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
uint8 *px;
if((raster->format & (Raster::PAL4|Raster::PAL8)) == 0)
return;
int minw, minh;
transferMinSize(raster->format & Raster::PAL4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
w = max(raster->width, minw);
h = max(raster->height, minh);
px = raster->pixels;
logw = 0;
for(i = 1; i < raster->width; i *= 2) logw++;
mask = (1<<logw+2)-1;
if(raster->format & Raster::PAL4 && natras->flags & Ps2Raster::SWIZZLED4){
for(y = 0; y < h; y += 4){
for(i = 0; i < 4; i++)
for(x = 0; x < w; x++){
uint32 a = (y+i<<logw)+x;
uint32 s = swizzle(x, y+i, logw)&mask;
uint8 c = a & 1 ? px[a>>1] >> 4 : px[a>>1] & 0xF;
tmpbuf[s>>1] = s & 1 ? tmpbuf[s>>1]&0xF | c<<4 : tmpbuf[s>>1]&0xF0 | c;
}
memcpy(&px[y<<logw-1], tmpbuf, 2*w);
}
}else if(raster->format & Raster::PAL8 && natras->flags & Ps2Raster::SWIZZLED8){
for(y = 0; y < h; y += 4){
for(i = 0; i < 4; i++)
for(x = 0; x < w; x++){
uint32 a = (y+i<<logw)+x;
uint32 s = swizzle(x, y+i, logw)&mask;
tmpbuf[s] = px[a];
}
memcpy(&px[y<<logw], tmpbuf, 4*w);
}
}
}
uint8*
rasterLock(Raster *raster, int32 level, int32 lockMode)
{
Ps2Raster *natras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
if(level > 0){
int32 minw, minh;
int32 mipw, miph;
transferMinSize(raster->format & Raster::PAL4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
while(level--){
mipw = max(raster->width, minw);
miph = max(raster->height, minh);
raster->pixels += ALIGN16(mipw*miph*raster->depth/8) + 0x50;
raster->width /= 2;
raster->height /= 2;
}
}
if((lockMode & Raster::LOCKNOFETCH) == 0)
unswizzleRaster(raster);
if(lockMode & Raster::LOCKREAD) raster->privateFlags |= PS2LOCK_READ;
if(lockMode & Raster::LOCKWRITE) raster->privateFlags |= PS2LOCK_WRITE;
return raster->pixels; return raster->pixels;
} }
void void
rasterUnlock(Raster *raster, int32 level) rasterUnlock(Raster *raster, int32 level)
{ {
// TODO Ps2Raster *natras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
(void)raster; if(raster->format & (Raster::PAL4 | Raster::PAL8))
(void)level; swizzleRaster(raster);
raster->width = raster->originalWidth;
raster->height = raster->originalHeight;
raster->pixels = raster->originalPixels;
raster->stride = raster->originalStride;
if(natras->flags & Ps2Raster::NEWSTYLE)
raster->pixels = ((Ps2Raster::PixelPtr*)raster->pixels)->pixels + 0x50;
raster->privateFlags &= ~(PS2LOCK_READ|PS2LOCK_WRITE);
// TODO: generate mipmaps
} }
static void
convertCSM1_16(uint32 *pal)
{
int i, j;
uint32 tmp;
for(i = 0; i < 256; i++)
// palette index bits 0x08 and 0x10 are flipped
if((i & 0x18) == 0x10){
j = i ^ 0x18;
tmp = pal[i];
pal[i] = pal[j];
pal[j] = tmp;
}
}
static void
convertCSM1_32(uint32 *pal)
{
int i, j;
uint32 tmp;
for(i = 0; i < 256; i++)
// palette index bits 0x08 and 0x10 are flipped
if((i & 0x18) == 0x10){
j = i ^ 0x18;
tmp = pal[i];
pal[i] = pal[j];
pal[j] = tmp;
}
}
static void
convertPalette(Raster *raster)
{
if(raster->format & Raster::PAL8){
if((raster->format & 0xF00) == Raster::C8888)
convertCSM1_32((uint32*)raster->palette);
else if((raster->format & 0xF00) == Raster::C8888)
convertCSM1_16((uint32*)raster->palette);
}
}
// NB: RW doesn't convert the palette when locking/unlocking
uint8* uint8*
paletteLock(Raster *raster) rasterLockPalette(Raster *raster, int32 lockMode)
{ {
if((raster->format & (Raster::PAL4 | Raster::PAL8)) == 0) if((raster->format & (Raster::PAL4 | Raster::PAL8)) == 0)
return nil; return nil;
if((lockMode & Raster::LOCKNOFETCH) == 0)
convertPalette(raster);
if(lockMode & Raster::LOCKREAD) raster->privateFlags |= PS2LOCK_READ_PALETTE;
if(lockMode & Raster::LOCKWRITE) raster->privateFlags |= PS2LOCK_WRITE_PALETTE;
return raster->palette; return raster->palette;
} }
void void
paletteUnlock(Raster *raster) rasterUnlockPalette(Raster *raster)
{ {
// TODO if(raster->format & (Raster::PAL4 | Raster::PAL8))
(void)raster; convertPalette(raster);
} raster->privateFlags &= ~(PS2LOCK_READ_PALETTE|PS2LOCK_WRITE_PALETTE);
static void
convertCSM1_16(uint16 *dst, uint16 *src)
{
// palette index bits 0x08 and 0x10 are flipped
int i, j;
for(i = 0; i < 256; i++){
j = i&~0x18 | (i&0x10)>>1 | (i&0x8)<<1;
dst[i] = src[j];
}
}
static void
convertCSM1_32(uint32 *dst, uint32 *src)
{
// palette index bits 0x08 and 0x10 are flipped
int i, j;
for(i = 0; i < 256; i++){
j = i&~0x18 | (i&0x10)>>1 | (i&0x8)<<1;
dst[i] = src[j];
}
}
// Unswizzle PSMT8 from PSMCT32 format
// Original code from http://ps2linux.no-ip.info/playstation2-linux.com/docs/howto/display_docef7c.html?docid=75
static void
unswizzle32to8(uint8 *dst, uint8 *src, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w; x++) {
// byte address of beginning of PSMCT32 block
// yblock = y/16 * w/16 * 256
int32 block_loc = (y&(~0xF))*w + (x&(~0xF))*2;
// y coordinate in PSMCT32 block
int32 ypos = (((y&~3)>>1) // column number
+ (y&1))&0x7; // row inside column
// indices are swapped in groups of 4 every 4
// pixel rows in a block, first at y = 2
int32 swap_sel = (y+2)&4;
// byte address of word in PSMCT32 block
int32 word_loc = ypos*w*2 + ((x+swap_sel)&0x7)*4;
// byte offset in 32 bit word
int32 byte_loc = ((y>>1)&1) + ((x>>2)&2);
int32 swizzled = block_loc + word_loc + byte_loc;
dst[y*w+x] = src[swizzled];
}
}
static void
swizzle8to32(uint8 *dst, uint8 *src, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w; x++) {
// byte address of beginning of PSMCT32 block
// yblock = y/16 * w/16 * 256
int32 block_loc = (y&(~0xF))*w + (x&(~0xF))*2;
// y coordinate in PSMCT32 block
int32 ypos = (((y&~3)>>1) // column number
+ (y&1))&0x7; // row inside column
// indices are swapped in groups of 4 every 4
// pixel rows in a block, first at y = 2
int32 swap_sel = (y+2)&4;
// byte address of word in PSMCT32 block
int32 word_loc = ypos*w*2 + ((x+swap_sel)&0x7)*4;
// byte offset in 32 bit word
int32 byte_loc = ((y>>1)&1) + ((x>>2)&2);
int32 swizzled = block_loc + word_loc + byte_loc;
dst[swizzled] = src[y*w+x];
}
}
// Unswizzle PSMT4 from PSMCT16 format
static void
unswizzle16to4(uint8 *dst, uint8 *src, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w; x++){
// byte address of beginning of PSMCT16 block
// yblock = y/16 * w/32 * 256
int32 block_loc = (y&(~0xF))*w/2 + (x&(~0x1F));
// y coordinate in PSMCT16 block
int32 ypos = (((y&~3)>>1) // column number
+ (y&1))&0x7; // row inside column
// indices are swapped in groups of 4 every 4
// pixel rows in a block, first at y = 2
int32 swap_sel = (y+2)&4;
// byte address of halfword in PSMCT16 block
int32 hword_loc = ypos*w
+ (((x+swap_sel) & 0x7) + ((x & 0x10)>>1))*2;
// byte offset in 16 bit word
int32 byte_loc = (x>>3)&1;
uint32 swizzled = block_loc + hword_loc + byte_loc;
// y&2 selects nibbles
int8 c = y & 2 ? src[swizzled] >> 4 : src[swizzled] & 0xF;
int32 addr = y*w + x;
if(addr & 1)
dst[addr>>1] = dst[addr>>1]&0xF | c<<4;
else
dst[addr>>1] = dst[addr>>1]&0xF0 | c;
}
}
static void
swizzle4to16(uint8 *dst, uint8 *src, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w; x++){
// byte address of beginning of PSMCT16 block
// yblock = y/16 * w/32 * 256
int32 block_loc = (y&(~0xF))*w/2 + (x&(~0x1F));
// y coordinate in PSMCT16 block
int32 ypos = (((y&~3)>>1) // column number
+ (y&1))&0x7; // row inside column
// indices are swapped in groups of 4 every 4
// pixel rows in a block, first at y = 2
int32 swap_sel = (y+2)&4;
// byte address of halfword in PSMCT16 block
int32 hword_loc = ypos*w
+ (((x+swap_sel) & 0x7) + ((x & 0x10)>>1))*2;
// byte offset in 16 bit word
int32 byte_loc = (x>>3)&1;
uint32 swizzled = block_loc + hword_loc + byte_loc;
int32 addr = y*w + x;
int8 c = addr & 1 ? src[addr>>1] >> 4 : src[addr>>1] & 0xF;
// y&2 selects nibbles
if(y & 2)
dst[swizzled] = dst[swizzled]&0xF | c<<4;
else
dst[swizzled] = dst[swizzled]&0xF0 | c;
}
} }
void void
@ -1550,44 +1608,34 @@ rasterFromImage(Raster *raster, Image *image)
} }
rasterCreate(raster); rasterCreate(raster);
int32 pallength = 0;
if(raster->format & Raster::PAL4)
pallength = 16;
else if(raster->format & Raster::PAL8)
pallength = 256;
uint8 *in, *out; uint8 *in, *out;
if(image->depth <= 8){ if(image->depth <= 8){
in = image->palette; in = image->palette;
out = paletteLock(raster); out = raster->lockPalette(Raster::LOCKWRITE|Raster::LOCKNOFETCH);
if(image->depth == 4) memcpy(out, in, 4*pallength);
memcpy(out, in, 4*16); for(int32 i = 0; i < pallength; i++){
else out[3] = out[3]*128/255;
convertCSM1_32((uint32*)out, (uint32*)in); out += 4;
paletteUnlock(raster); }
raster->unlockPalette();
} }
int32 w, h;
w = image->width;
h = image->height;
int minw, minh; int minw, minh;
int th, tw; int tw;
transferMinSize(image->depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh); transferMinSize(image->depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
tw = max(w, minw); tw = max(image->width, minw);
th = max(h, minh);
in = image->pixels; in = image->pixels;
out = raster->lock(0); out = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
if(image->depth == 4){ if(image->depth == 4){
if(natras->flags & Ps2Raster::SWIZZLED4){ compressPSMT4(out, in, image->width, image->height, tw);
uint8 *tmp = rwNewT(uint8, tw*th/2, MEMDUR_FUNCTION | ID_RASTERPS2);
compressPSMT4(tmp, in, w, h, tw);
swizzle4to16(out, tmp, tw, th);
rwFree(tmp);
}else
compressPSMT4(out, in, w, h, tw);
}else if(image->depth == 8){ }else if(image->depth == 8){
if(natras->flags & Ps2Raster::SWIZZLED8){ copyPSMT8(out, in, image->width, image->height, tw);
uint8 *tmp = rwNewT(uint8, tw*th, MEMDUR_FUNCTION | ID_RASTERPS2);
copyPSMT8(tmp, in, w, h, tw);
swizzle8to32(out, tmp, tw, th);
rwFree(tmp);
}else
copyPSMT8(out, in, w, h, tw);
}else{ }else{
// TODO: stride // TODO: stride
for(int32 y = 0; y < image->height; y++) for(int32 y = 0; y < image->height; y++)
@ -1666,52 +1714,28 @@ rasterToImage(Raster *raster)
if(pallength){ if(pallength){
out = image->palette; out = image->palette;
in = paletteLock(raster); in = raster->lockPalette(Raster::LOCKREAD);
if(rasterFormat == Raster::C1555){ if(rasterFormat == Raster::C8888){
if(depth == 8) memcpy(out, in, pallength*4);
convertCSM1_16((uint16*)out, (uint16*)in);
else
memcpy(out, in, pallength*2);
}else if(rasterFormat == Raster::C8888){
if(depth == 8)
convertCSM1_32((uint32*)out, (uint32*)in);
else
memcpy(out, in, pallength*4);
for(int32 i = 0; i < pallength; i++){ for(int32 i = 0; i < pallength; i++){
out[3] = out[3]*255/128; out[3] = out[3]*255/128;
out += 4; out += 4;
} }
} }else
paletteUnlock(raster); memcpy(out, in, pallength*2);
raster->unlockPalette();
} }
int32 w, h;
w = raster->width;
h = raster->height;
int minw, minh; int minw, minh;
int th, tw; int tw;
transferMinSize(depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh); transferMinSize(depth == 4 ? PSMT4 : PSMT8, natras->flags, &minw, &minh);
tw = max(w, minw); tw = max(raster->width, minw);
th = max(h, minh);
out = image->pixels; out = image->pixels;
in = raster->lock(0); in = raster->lock(0, Raster::LOCKREAD);
if(depth == 4){ if(depth == 4){
if(natras->flags & Ps2Raster::SWIZZLED4){ expandPSMT4(out, in, raster->width, raster->height, tw);
uint8 *tmp = rwNewT(uint8, tw*th/2, MEMDUR_FUNCTION | ID_RASTERPS2);
unswizzle16to4(tmp, in, tw, th);
expandPSMT4(out, tmp, w, h, tw);
rwFree(tmp);
}else
expandPSMT4(out, in, w, h, tw);
}else if(depth == 8){ }else if(depth == 8){
if(natras->flags & Ps2Raster::SWIZZLED8){ copyPSMT8(out, in, raster->width, raster->height, tw);
uint8 *tmp = rwNewT(uint8, tw*th, MEMDUR_FUNCTION | ID_RASTERPS2);
unswizzle32to8(tmp, in, tw, th);
copyPSMT8(out, tmp, w, h, tw);
rwFree(tmp);
}else
copyPSMT8(out, in, w, h, tw);
}else }else
// TODO: stride // TODO: stride
for(int32 y = 0; y < image->height; y++) for(int32 y = 0; y < image->height; y++)
@ -1787,8 +1811,8 @@ createNativeRaster(void *object, int32 offset, int32)
static void* static void*
destroyNativeRaster(void *object, int32 offset, int32) destroyNativeRaster(void *object, int32 offset, int32)
{ {
// TODO Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, object, offset);
(void)offset; freealign(raster->data);
return object; return object;
} }

View File

@ -2,8 +2,10 @@ namespace rw {
namespace ps2 { namespace ps2 {
void rasterCreate(Raster *raster); void rasterCreate(Raster *raster);
uint8 *rasterLock(Raster*, int32 level); uint8 *rasterLock(Raster*, int32 level, int32 lockMode);
void rasterUnlock(Raster*, int32); void rasterUnlock(Raster*, int32 level);
uint8 *rasterLockPalette(Raster*, int32 lockMode);
void rasterUnlockPalette(Raster*);
int32 rasterNumLevels(Raster*); int32 rasterNumLevels(Raster*);
void rasterFromImage(Raster *raster, Image *image); void rasterFromImage(Raster *raster, Image *image);
Image *rasterToImage(Raster *raster); Image *rasterToImage(Raster *raster);

View File

@ -59,8 +59,10 @@ struct Driver
int32 rasterNativeOffset; int32 rasterNativeOffset;
void (*rasterCreate)(Raster*); void (*rasterCreate)(Raster*);
uint8 *(*rasterLock)(Raster*, int32 level); uint8 *(*rasterLock)(Raster*, int32 level, int32 lockMode);
void (*rasterUnlock)(Raster*, int32 level); void (*rasterUnlock)(Raster*, int32 level);
uint8 *(*rasterLockPalette)(Raster*, int32 lockMode);
void (*rasterUnlockPalette)(Raster*);
int32 (*rasterNumLevels)(Raster*); int32 (*rasterNumLevels)(Raster*);
void (*rasterFromImage)(Raster*, Image*); void (*rasterFromImage)(Raster*, Image*);
Image *(*rasterToImage)(Raster*); Image *(*rasterToImage)(Raster*);
@ -158,8 +160,10 @@ namespace null {
void *getRenderState(int32 state); void *getRenderState(int32 state);
void rasterCreate(Raster*); void rasterCreate(Raster*);
uint8 *rasterLock(Raster*, int32 level); uint8 *rasterLock(Raster*, int32 level, int32 lockMode);
void rasterUnlock(Raster*, int32 level); void rasterUnlock(Raster*, int32 level);
uint8 *rasterLockPalette(Raster*, int32 lockMode);
void rasterUnlockPalette(Raster*);
int32 rasterNumLevels(Raster*); int32 rasterNumLevels(Raster*);
void rasterFromImage(Raster*, Image*); void rasterFromImage(Raster*, Image*);
Image *rasterToImage(Raster*); Image *rasterToImage(Raster*);

View File

@ -170,13 +170,14 @@ struct Raster
// TODO: use bytes // TODO: use bytes
int32 type; int32 type;
int32 flags; int32 flags;
int32 privateFlags;
int32 format; int32 format;
int32 width, height, depth; int32 width, height, depth;
int32 stride; int32 stride;
uint8 *pixels; uint8 *pixels;
uint8 *palette; uint8 *palette;
// remember for locked rasters
uint8 *originalPixels; uint8 *originalPixels;
// TODO: use them (for locking mainly)
int32 originalWidth; int32 originalWidth;
int32 originalHeight; int32 originalHeight;
int32 originalStride; int32 originalStride;
@ -190,8 +191,10 @@ struct Raster
void destroy(void); void destroy(void);
static Raster *createFromImage(Image *image, int32 platform = 0); static Raster *createFromImage(Image *image, int32 platform = 0);
Image *toImage(void); Image *toImage(void);
uint8 *lock(int32 level); uint8 *lock(int32 level, int32 lockMode);
void unlock(int32 level); void unlock(int32 level);
uint8 *lockPalette(int32 lockMode);
void unlockPalette(void);
int32 getNumLevels(void); int32 getNumLevels(void);
static int32 calculateNumLevels(int32 width, int32 height); static int32 calculateNumLevels(int32 width, int32 height);
static bool formatHasAlpha(int32 format); static bool formatHasAlpha(int32 format);
@ -221,6 +224,12 @@ struct Raster
CAMERATEXTURE = 0x05, CAMERATEXTURE = 0x05,
DONTALLOCATE = 0x80 DONTALLOCATE = 0x80
}; };
enum LockMode {
LOCKWRITE = 1,
LOCKREAD = 2,
LOCKNOFETCH = 4, // don't fetch pixel data
LOCKRAW = 8,
};
}; };
#define IGNORERASTERIMP 0 #define IGNORERASTERIMP 0

View File

@ -464,6 +464,7 @@ Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platf
raster->platform = platform ? platform : rw::platform; raster->platform = platform ? platform : rw::platform;
raster->type = format & 0x7; raster->type = format & 0x7;
raster->flags = format & 0xF8; raster->flags = format & 0xF8;
raster->privateFlags = 0;
raster->format = format & 0xFF00; raster->format = format & 0xFF00;
raster->width = width; raster->width = width;
raster->height = height; raster->height = height;
@ -498,9 +499,9 @@ Raster::destroy(void)
} }
uint8* uint8*
Raster::lock(int32 level) Raster::lock(int32 level, int32 lockMode)
{ {
return engine->driver[this->platform]->rasterLock(this, level); return engine->driver[this->platform]->rasterLock(this, level, lockMode);
} }
void void
@ -509,6 +510,18 @@ Raster::unlock(int32 level)
engine->driver[this->platform]->rasterUnlock(this, level); engine->driver[this->platform]->rasterUnlock(this, level);
} }
uint8*
Raster::lockPalette(int32 lockMode)
{
return engine->driver[this->platform]->rasterLockPalette(this, lockMode);
}
void
Raster::unlockPalette(void)
{
engine->driver[this->platform]->rasterUnlockPalette(this);
}
int32 int32
Raster::getNumLevels(void) Raster::getNumLevels(void)
{ {

View File

@ -842,7 +842,7 @@ void
endSoftras(void) endSoftras(void)
{ {
int i; int i;
uint8 *dst = testras->lock(0); uint8 *dst = testras->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
uint8 *src = rs::canvas->fb; uint8 *src = rs::canvas->fb;
for(i = 0; i < rs::canvas->w*rs::canvas->h; i++){ for(i = 0; i < rs::canvas->w*rs::canvas->h; i++){
dst[0] = src[1]; dst[0] = src[1];