mirror of https://github.com/aap/librw.git
lots of changes to rasters; mostly mipmap support and DXT conversion
This commit is contained in:
parent
3e2080ad56
commit
7e80d45cdb
4
TODO
4
TODO
|
@ -9,10 +9,6 @@ TODO:
|
||||||
|
|
||||||
driver
|
driver
|
||||||
- metrics
|
- metrics
|
||||||
- mipmaps
|
|
||||||
|
|
||||||
opengl
|
|
||||||
- DXT conversion from d3d
|
|
||||||
|
|
||||||
ps2
|
ps2
|
||||||
- rendering!
|
- rendering!
|
||||||
|
|
162
src/d3d/d3d.cpp
162
src/d3d/d3d.cpp
|
@ -207,11 +207,11 @@ unlockVertices(void *vertexBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
createTexture(int32 width, int32 height, int32 numlevels, uint32 format)
|
createTexture(int32 width, int32 height, int32 numlevels, uint32 usage, uint32 format)
|
||||||
{
|
{
|
||||||
#ifdef RW_D3D9
|
#ifdef RW_D3D9
|
||||||
IDirect3DTexture9 *tex;
|
IDirect3DTexture9 *tex;
|
||||||
d3ddevice->CreateTexture(width, height, numlevels, 0,
|
d3ddevice->CreateTexture(width, height, numlevels, usage,
|
||||||
(D3DFORMAT)format, D3DPOOL_MANAGED, &tex, nil);
|
(D3DFORMAT)format, D3DPOOL_MANAGED, &tex, nil);
|
||||||
if(tex)
|
if(tex)
|
||||||
d3d9Globals.numTextures++;
|
d3d9Globals.numTextures++;
|
||||||
|
@ -406,11 +406,7 @@ rasterSetFormat(Raster *raster)
|
||||||
natras->hasAlpha = formatInfoRW[(raster->format >> 8) & 0xF].hasAlpha;
|
natras->hasAlpha = formatInfoRW[(raster->format >> 8) & 0xF].hasAlpha;
|
||||||
raster->stride = raster->width*natras->bpp;
|
raster->stride = raster->width*natras->bpp;
|
||||||
|
|
||||||
raster->pixels = nil;
|
natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP);
|
||||||
raster->originalWidth = raster->width;
|
|
||||||
raster->originalHeight = raster->height;
|
|
||||||
raster->originalStride = raster->stride;
|
|
||||||
raster->originalPixels = raster->pixels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Raster*
|
static Raster*
|
||||||
|
@ -421,10 +417,17 @@ rasterCreateTexture(Raster *raster)
|
||||||
|
|
||||||
if(natras->format == D3DFMT_P8)
|
if(natras->format == D3DFMT_P8)
|
||||||
natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER);
|
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);
|
assert(natras->texture == nil);
|
||||||
natras->texture = createTexture(raster->width, raster->height,
|
natras->texture = createTexture(raster->width, raster->height,
|
||||||
raster->format & Raster::MIPMAP ? levels : 1,
|
levels,
|
||||||
|
natras->autogenMipmap ? D3DUSAGE_AUTOGENMIPMAP : 0,
|
||||||
natras->format);
|
natras->format);
|
||||||
if(natras->texture == nil){
|
if(natras->texture == nil){
|
||||||
RWERROR((ERR_NOTEXTURE));
|
RWERROR((ERR_NOTEXTURE));
|
||||||
|
@ -445,12 +448,17 @@ rasterCreateCameraTexture(Raster *raster)
|
||||||
|
|
||||||
int32 levels;
|
int32 levels;
|
||||||
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
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;
|
IDirect3DTexture9 *tex;
|
||||||
d3ddevice->CreateTexture(raster->width, raster->height,
|
d3ddevice->CreateTexture(raster->width, raster->height,
|
||||||
raster->format & Raster::MIPMAP ? levels : 1,
|
levels,
|
||||||
D3DUSAGE_RENDERTARGET,
|
(natras->autogenMipmap ? D3DUSAGE_AUTOGENMIPMAP : 0) | D3DUSAGE_RENDERTARGET,
|
||||||
(D3DFORMAT)natras->format, D3DPOOL_DEFAULT, &tex, nil);
|
(D3DFORMAT)natras->format, D3DPOOL_DEFAULT, &tex, nil);
|
||||||
assert(natras->texture == nil);
|
assert(natras->texture == nil);
|
||||||
natras->texture = tex;
|
natras->texture = tex;
|
||||||
|
@ -467,10 +475,8 @@ static Raster*
|
||||||
rasterCreateCamera(Raster *raster)
|
rasterCreateCamera(Raster *raster)
|
||||||
{
|
{
|
||||||
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
||||||
raster->originalWidth = raster->width;
|
|
||||||
raster->originalHeight = raster->height;
|
natras->autogenMipmap = 0;
|
||||||
raster->originalStride = raster->stride = 0;
|
|
||||||
raster->originalPixels = raster->pixels = nil;
|
|
||||||
|
|
||||||
natras->format = d3d9Globals.present.BackBufferFormat;
|
natras->format = d3d9Globals.present.BackBufferFormat;
|
||||||
raster->depth = findFormatDepth(natras->format);
|
raster->depth = findFormatDepth(natras->format);
|
||||||
|
@ -483,10 +489,8 @@ static Raster*
|
||||||
rasterCreateZbuffer(Raster *raster)
|
rasterCreateZbuffer(Raster *raster)
|
||||||
{
|
{
|
||||||
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
||||||
raster->originalWidth = raster->width;
|
|
||||||
raster->originalHeight = raster->height;
|
natras->autogenMipmap = 0;
|
||||||
raster->originalStride = raster->stride = 0;
|
|
||||||
raster->originalPixels = raster->pixels = nil;
|
|
||||||
|
|
||||||
// TODO: allow other formats
|
// TODO: allow other formats
|
||||||
natras->format = d3d9Globals.present.AutoDepthStencilFormat;
|
natras->format = d3d9Globals.present.AutoDepthStencilFormat;
|
||||||
|
@ -518,33 +522,47 @@ rasterCreateZbuffer(Raster *raster)
|
||||||
Raster*
|
Raster*
|
||||||
rasterCreate(Raster *raster)
|
rasterCreate(Raster *raster)
|
||||||
{
|
{
|
||||||
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
|
||||||
|
|
||||||
rasterSetFormat(raster);
|
rasterSetFormat(raster);
|
||||||
|
|
||||||
|
Raster *ret = raster;
|
||||||
|
|
||||||
if(raster->width == 0 || raster->height == 0){
|
if(raster->width == 0 || raster->height == 0){
|
||||||
raster->flags |= Raster::DONTALLOCATE;
|
raster->flags |= Raster::DONTALLOCATE;
|
||||||
raster->stride = 0;
|
raster->stride = 0;
|
||||||
return raster;
|
goto ret;
|
||||||
}
|
}
|
||||||
if(raster->flags & Raster::DONTALLOCATE)
|
if(raster->flags & Raster::DONTALLOCATE)
|
||||||
return raster;
|
goto ret;
|
||||||
|
|
||||||
switch(raster->type){
|
switch(raster->type){
|
||||||
case Raster::NORMAL:
|
case Raster::NORMAL:
|
||||||
case Raster::TEXTURE:
|
case Raster::TEXTURE:
|
||||||
return rasterCreateTexture(raster);
|
ret = rasterCreateTexture(raster);
|
||||||
|
break;
|
||||||
|
|
||||||
#ifdef RW_D3D9
|
#ifdef RW_D3D9
|
||||||
case Raster::CAMERATEXTURE:
|
case Raster::CAMERATEXTURE:
|
||||||
return rasterCreateCameraTexture(raster);
|
ret = rasterCreateCameraTexture(raster);
|
||||||
|
break;
|
||||||
case Raster::ZBUFFER:
|
case Raster::ZBUFFER:
|
||||||
return rasterCreateZbuffer(raster);
|
ret = rasterCreateZbuffer(raster);
|
||||||
|
break;
|
||||||
case Raster::CAMERA:
|
case Raster::CAMERA:
|
||||||
return rasterCreateCamera(raster);
|
ret = rasterCreateCamera(raster);
|
||||||
|
break;
|
||||||
#endif
|
#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*
|
uint8*
|
||||||
|
@ -569,7 +587,8 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
|
||||||
case Raster::TEXTURE: {
|
case Raster::TEXTURE: {
|
||||||
tex->GetSurfaceLevel(level, &surf);
|
tex->GetSurfaceLevel(level, &surf);
|
||||||
natras->lockedSurf = surf;
|
natras->lockedSurf = surf;
|
||||||
surf->LockRect(&lr, 0, flags);
|
HRESULT res = surf->LockRect(&lr, 0, flags);
|
||||||
|
assert(res == D3D_OK);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,15 +602,17 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
|
||||||
raster->stride = lr.Pitch;
|
raster->stride = lr.Pitch;
|
||||||
if(raster->width == 0) raster->width = 1;
|
if(raster->width == 0) raster->width = 1;
|
||||||
if(raster->height == 0) raster->height = 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::LOCKREAD) raster->privateFlags |= Raster::PRIVATELOCK_READ;
|
||||||
if(lockMode & Raster::LOCKWRITE) raster->privateFlags |= Raster::PRIVATELOCK_WRITE;
|
if(lockMode & Raster::LOCKWRITE) raster->privateFlags |= Raster::PRIVATELOCK_WRITE;
|
||||||
|
|
||||||
return raster->pixels;
|
return raster->pixels;
|
||||||
#else
|
|
||||||
RasterLevels *levels = (RasterLevels*)natras->texture;
|
|
||||||
return levels->levels[level].data;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -701,38 +722,39 @@ rasterFromImage(Raster *raster, Image *image)
|
||||||
}
|
}
|
||||||
|
|
||||||
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
||||||
|
int32 format = raster->format&0xF00;
|
||||||
switch(image->depth){
|
switch(image->depth){
|
||||||
case 32:
|
case 32:
|
||||||
if(raster->format == Raster::C8888)
|
if(format == Raster::C8888)
|
||||||
conv = conv_BGRA8888_from_RGBA8888;
|
conv = conv_BGRA8888_from_RGBA8888;
|
||||||
else if(raster->format == Raster::C888)
|
else if(format == Raster::C888)
|
||||||
conv = conv_BGR888_from_RGB888;
|
conv = conv_BGR888_from_RGB888;
|
||||||
else
|
else
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
if(raster->format == Raster::C8888)
|
if(format == Raster::C8888)
|
||||||
conv = conv_BGRA8888_from_RGB888;
|
conv = conv_BGRA8888_from_RGB888;
|
||||||
else if(raster->format == Raster::C888)
|
else if(format == Raster::C888)
|
||||||
conv = conv_BGR888_from_RGB888;
|
conv = conv_BGR888_from_RGB888;
|
||||||
else
|
else
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
if(raster->format == Raster::C1555)
|
if(format == Raster::C1555)
|
||||||
conv = conv_ARGB1555_from_ARGB1555;
|
conv = conv_ARGB1555_from_ARGB1555;
|
||||||
else
|
else
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
if(raster->format == (Raster::PAL8 | Raster::C8888))
|
if(format == (Raster::PAL8 | Raster::C8888))
|
||||||
conv = conv_8_from_8;
|
conv = conv_8_from_8;
|
||||||
else
|
else
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if(raster->format == (Raster::PAL4 | Raster::C8888) ||
|
if(format == (Raster::PAL4 | Raster::C8888) ||
|
||||||
raster->format == (Raster::PAL8 | Raster::C8888))
|
format == (Raster::PAL8 | Raster::C8888))
|
||||||
conv = conv_8_from_8;
|
conv = conv_8_from_8;
|
||||||
else
|
else
|
||||||
goto err;
|
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);
|
assert(pixels);
|
||||||
uint8 *imgpixels = image->pixels;
|
uint8 *imgpixels = image->pixels;
|
||||||
|
|
||||||
|
@ -776,7 +804,8 @@ rasterFromImage(Raster *raster, Image *image)
|
||||||
imgpixels += image->stride;
|
imgpixels += image->stride;
|
||||||
pixels += raster->stride;
|
pixels += raster->stride;
|
||||||
}
|
}
|
||||||
raster->unlock(0);
|
if(unlock)
|
||||||
|
raster->unlock(0);
|
||||||
|
|
||||||
if(truecolimg)
|
if(truecolimg)
|
||||||
truecolimg->destroy();
|
truecolimg->destroy();
|
||||||
|
@ -789,11 +818,23 @@ rasterToImage(Raster *raster)
|
||||||
{
|
{
|
||||||
int32 depth;
|
int32 depth;
|
||||||
Image *image;
|
Image *image;
|
||||||
|
|
||||||
|
bool unlock = false;
|
||||||
|
if(raster->pixels == nil){
|
||||||
|
raster->lock(0, Raster::LOCKREAD);
|
||||||
|
unlock = true;
|
||||||
|
}
|
||||||
|
|
||||||
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
D3dRaster *natras = GETD3DRASTEREXT(raster);
|
||||||
if(natras->customFormat){
|
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();
|
image->allocate();
|
||||||
uint8 *pix = raster->lock(0, Raster::LOCKREAD);
|
uint8 *pix = raster->pixels;
|
||||||
switch(natras->format){
|
switch(natras->format){
|
||||||
case D3DFMT_DXT1:
|
case D3DFMT_DXT1:
|
||||||
image->setPixelsDXT(1, pix);
|
image->setPixelsDXT(1, pix);
|
||||||
|
@ -807,11 +848,17 @@ rasterToImage(Raster *raster)
|
||||||
image->setPixelsDXT(5, pix);
|
image->setPixelsDXT(5, pix);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
raster->unlock(0);
|
|
||||||
image->destroy();
|
image->destroy();
|
||||||
|
if(unlock)
|
||||||
|
raster->unlock(0);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
raster->unlock(0);
|
// fix it up again
|
||||||
|
image->width = raster->width;
|
||||||
|
image->height = raster->height;
|
||||||
|
|
||||||
|
if(unlock)
|
||||||
|
raster->unlock(0);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,7 +912,7 @@ rasterToImage(Raster *raster)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 *imgpixels = image->pixels;
|
uint8 *imgpixels = image->pixels;
|
||||||
uint8 *pixels = raster->lock(0, Raster::LOCKREAD);
|
uint8 *pixels = raster->pixels;
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
assert(image->width == raster->width);
|
assert(image->width == raster->width);
|
||||||
|
@ -881,10 +928,11 @@ rasterToImage(Raster *raster)
|
||||||
imgpixels += image->stride;
|
imgpixels += image->stride;
|
||||||
pixels += raster->stride;
|
pixels += raster->stride;
|
||||||
}
|
}
|
||||||
raster->unlock(0);
|
|
||||||
|
|
||||||
image->compressPalette();
|
image->compressPalette();
|
||||||
|
|
||||||
|
if(unlock)
|
||||||
|
raster->unlock(0);
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,8 +964,16 @@ allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha)
|
||||||
D3dRaster *ras = GETD3DRASTEREXT(raster);
|
D3dRaster *ras = GETD3DRASTEREXT(raster);
|
||||||
ras->format = dxtMap[dxt-1];
|
ras->format = dxtMap[dxt-1];
|
||||||
ras->hasAlpha = hasAlpha;
|
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,
|
ras->texture = createTexture(raster->width, raster->height,
|
||||||
raster->format & Raster::MIPMAP ? numLevels : 1,
|
numLevels,
|
||||||
|
ras->autogenMipmap ? D3DUSAGE_AUTOGENMIPMAP : 0,
|
||||||
ras->format);
|
ras->format);
|
||||||
raster->flags &= ~Raster::DONTALLOCATE;
|
raster->flags &= ~Raster::DONTALLOCATE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,35 +468,54 @@ readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format
|
||||||
for(int32 i = 0; i < pallen; i++)
|
for(int32 i = 0; i < pallen; i++)
|
||||||
palette[i*4+3] = 0xFF;
|
palette[i*4+3] = 0xFF;
|
||||||
|
|
||||||
// Only read one mipmap
|
Raster *ras = nil;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(format & (Raster::PAL4 | Raster::PAL8)){
|
for(int i = 0; i < numLevels; i++){
|
||||||
uint8 *idx = data;
|
if(ras){
|
||||||
uint8 *pixels = img->pixels;
|
ras->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
|
||||||
for(int y = 0; y < img->height; y++){
|
img->width = ras->width;
|
||||||
uint8 *line = pixels;
|
img->height = ras->height;
|
||||||
for(int x = 0; x < img->width; x++){
|
img->stride = img->width*img->bpp;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
rwFree(data);
|
||||||
Raster *ras = Raster::createFromImage(img, PLATFORM_D3D8);
|
|
||||||
img->destroy();
|
img->destroy();
|
||||||
return ras;
|
return ras;
|
||||||
}
|
}
|
||||||
|
@ -545,7 +564,7 @@ readNativeTexture(Stream *stream)
|
||||||
Raster *raster;
|
Raster *raster;
|
||||||
D3dRaster *ras;
|
D3dRaster *ras;
|
||||||
if(compression){
|
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);
|
ras = GETD3DRASTEREXT(raster);
|
||||||
allocateDXT(raster, compression, numLevels, hasAlpha);
|
allocateDXT(raster, compression, numLevels, hasAlpha);
|
||||||
ras->customFormat = 1;
|
ras->customFormat = 1;
|
||||||
|
|
|
@ -751,6 +751,7 @@ readNativeTexture(Stream *stream)
|
||||||
ext->hasAlpha = flags & 1;
|
ext->hasAlpha = flags & 1;
|
||||||
ext->texture = createTexture(raster->width, raster->height,
|
ext->texture = createTexture(raster->width, raster->height,
|
||||||
raster->format & Raster::MIPMAP ? numLevels : 1,
|
raster->format & Raster::MIPMAP ? numLevels : 1,
|
||||||
|
0,
|
||||||
ext->format);
|
ext->format);
|
||||||
assert(ext->texture);
|
assert(ext->texture);
|
||||||
raster->flags &= ~Raster::DONTALLOCATE;
|
raster->flags &= ~Raster::DONTALLOCATE;
|
||||||
|
@ -811,7 +812,9 @@ writeNativeTexture(Texture *tex, Stream *stream)
|
||||||
uint8 flags = 0;
|
uint8 flags = 0;
|
||||||
if(ext->hasAlpha)
|
if(ext->hasAlpha)
|
||||||
flags |= 1;
|
flags |= 1;
|
||||||
// no automipmapgen and cube supported yet
|
// no cube supported yet
|
||||||
|
if(ext->autogenMipmap)
|
||||||
|
flags |= 4;
|
||||||
if(ext->customFormat)
|
if(ext->customFormat)
|
||||||
flags |= 8;
|
flags |= 8;
|
||||||
stream->writeU8(flags);
|
stream->writeU8(flags);
|
||||||
|
|
|
@ -170,12 +170,16 @@ static uint32 cullmodeMap[] = {
|
||||||
D3DCULL_CCW
|
D3DCULL_CCW
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: support mipmaps
|
static uint32 filterConvMap[] = {
|
||||||
static uint32 filterConvMap_NoMIP[] = {
|
|
||||||
0, D3DTEXF_POINT, D3DTEXF_LINEAR,
|
0, D3DTEXF_POINT, D3DTEXF_LINEAR,
|
||||||
D3DTEXF_POINT, D3DTEXF_LINEAR,
|
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[] = {
|
static uint32 addressConvMap[] = {
|
||||||
0, D3DTADDRESS_WRAP, D3DTADDRESS_MIRROR,
|
0, D3DTADDRESS_WRAP, D3DTADDRESS_MIRROR,
|
||||||
D3DTADDRESS_CLAMP, D3DTADDRESS_BORDER
|
D3DTADDRESS_CLAMP, D3DTADDRESS_BORDER
|
||||||
|
@ -304,8 +308,9 @@ restoreD3d9Device(void)
|
||||||
d3ddevice->SetTexture(i, nil);
|
d3ddevice->SetTexture(i, nil);
|
||||||
setSamplerState(i, D3DSAMP_ADDRESSU, addressConvMap[rwStateCache.texstage[i].addressingU]);
|
setSamplerState(i, D3DSAMP_ADDRESSU, addressConvMap[rwStateCache.texstage[i].addressingU]);
|
||||||
setSamplerState(i, D3DSAMP_ADDRESSV, addressConvMap[rwStateCache.texstage[i].addressingV]);
|
setSamplerState(i, D3DSAMP_ADDRESSV, addressConvMap[rwStateCache.texstage[i].addressingV]);
|
||||||
setSamplerState(i, D3DSAMP_MAGFILTER, filterConvMap_NoMIP[rwStateCache.texstage[i].filter]);
|
setSamplerState(i, D3DSAMP_MAGFILTER, filterConvMap[rwStateCache.texstage[i].filter]);
|
||||||
setSamplerState(i, D3DSAMP_MINFILTER, filterConvMap_NoMIP[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++)
|
for(s = 0; s < MAXNUMSTATES; s++)
|
||||||
if(validStates[s])
|
if(validStates[s])
|
||||||
|
@ -438,11 +443,11 @@ setRasterStage(uint32 stage, Raster *raster)
|
||||||
static void
|
static void
|
||||||
setFilterMode(uint32 stage, int32 filter)
|
setFilterMode(uint32 stage, int32 filter)
|
||||||
{
|
{
|
||||||
// TODO: mip mapping
|
|
||||||
if(rwStateCache.texstage[stage].filter != (Texture::FilterMode)filter){
|
if(rwStateCache.texstage[stage].filter != (Texture::FilterMode)filter){
|
||||||
rwStateCache.texstage[stage].filter = (Texture::FilterMode)filter;
|
rwStateCache.texstage[stage].filter = (Texture::FilterMode)filter;
|
||||||
setSamplerState(stage, D3DSAMP_MAGFILTER, filterConvMap_NoMIP[filter]);
|
setSamplerState(stage, D3DSAMP_MAGFILTER, filterConvMap[filter]);
|
||||||
setSamplerState(stage, D3DSAMP_MINFILTER, filterConvMap_NoMIP[filter]);
|
setSamplerState(stage, D3DSAMP_MINFILTER, filterConvMap[filter]);
|
||||||
|
setSamplerState(stage, D3DSAMP_MIPFILTER, filterConvMap_MIP[filter]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -234,6 +234,9 @@ enum {
|
||||||
D3DDECLUSAGE_FOG, // 11
|
D3DDECLUSAGE_FOG, // 11
|
||||||
D3DDECLUSAGE_DEPTH, // 12
|
D3DDECLUSAGE_DEPTH, // 12
|
||||||
D3DDECLUSAGE_SAMPLE // 13
|
D3DDECLUSAGE_SAMPLE // 13
|
||||||
|
,
|
||||||
|
|
||||||
|
D3DUSAGE_AUTOGENMIPMAP = 0x400
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -249,7 +252,7 @@ void destroyVertexBuffer(void *vertexBuffer);
|
||||||
uint8 *lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags);
|
uint8 *lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags);
|
||||||
void unlockVertices(void *vertexBuffer);
|
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);
|
void destroyTexture(void *texture);
|
||||||
uint8 *lockTexture(void *texture, int32 level);
|
uint8 *lockTexture(void *texture, int32 level);
|
||||||
void unlockTexture(void *texture, int32 level);
|
void unlockTexture(void *texture, int32 level);
|
||||||
|
@ -263,8 +266,9 @@ struct D3dRaster
|
||||||
void *lockedSurf;
|
void *lockedSurf;
|
||||||
uint32 format;
|
uint32 format;
|
||||||
uint32 bpp; // bytes per pixel
|
uint32 bpp; // bytes per pixel
|
||||||
bool32 hasAlpha;
|
bool hasAlpha;
|
||||||
bool32 customFormat;
|
bool customFormat;
|
||||||
|
bool autogenMipmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
int32 getLevelSize(Raster *raster, int32 level);
|
int32 getLevelSize(Raster *raster, int32 level);
|
||||||
|
|
|
@ -84,7 +84,9 @@ struct XboxRaster
|
||||||
void *texture;
|
void *texture;
|
||||||
void *palette;
|
void *palette;
|
||||||
uint32 format;
|
uint32 format;
|
||||||
bool32 hasAlpha;
|
uint32 bpp; // bytes per pixel
|
||||||
|
bool hasAlpha;
|
||||||
|
bool customFormat;
|
||||||
bool32 unknownFlag;
|
bool32 unknownFlag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,6 +94,7 @@ int32 getLevelSize(Raster *raster, int32 level);
|
||||||
|
|
||||||
extern int32 nativeRasterOffset;
|
extern int32 nativeRasterOffset;
|
||||||
void registerNativeRaster(void);
|
void registerNativeRaster(void);
|
||||||
|
#define GETXBOXRASTEREXT(raster) PLUGINOFFSET(rw::xbox::XboxRaster, raster, rw::xbox::nativeRasterOffset)
|
||||||
|
|
||||||
Texture *readNativeTexture(Stream *stream);
|
Texture *readNativeTexture(Stream *stream);
|
||||||
void writeNativeTexture(Texture *tex, Stream *stream);
|
void writeNativeTexture(Texture *tex, Stream *stream);
|
||||||
|
|
251
src/d3d/xbox.cpp
251
src/d3d/xbox.cpp
|
@ -522,97 +522,137 @@ createTexture(int32 width, int32 height, int32 numlevels, uint32 format)
|
||||||
return levels;
|
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*
|
Raster*
|
||||||
rasterCreate(Raster *raster)
|
rasterCreate(Raster *raster)
|
||||||
{
|
{
|
||||||
static uint32 formatMap[] = {
|
rasterSetFormat(raster);
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
|
Raster *ret = raster;
|
||||||
uint32 format;
|
|
||||||
int32 levels;
|
|
||||||
|
|
||||||
// Dummy to use as subraster
|
// Dummy to use as subraster
|
||||||
if(raster->width == 0 || raster->height == 0){
|
if(raster->width == 0 || raster->height == 0){
|
||||||
raster->flags |= Raster::DONTALLOCATE;
|
raster->flags |= Raster::DONTALLOCATE;
|
||||||
raster->stride = 0;
|
raster->stride = 0;
|
||||||
return raster;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
if(raster->flags & Raster::DONTALLOCATE)
|
||||||
|
goto ret;
|
||||||
|
|
||||||
switch(raster->type){
|
switch(raster->type){
|
||||||
case Raster::NORMAL:
|
case Raster::NORMAL:
|
||||||
case Raster::TEXTURE:
|
case Raster::TEXTURE:
|
||||||
if(raster->flags & Raster::DONTALLOCATE)
|
ret = rasterCreateTexture(raster);
|
||||||
return raster;
|
break;
|
||||||
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
|
default:
|
||||||
format = D3DFMT_P8;
|
RWERROR((ERR_INVRASTER));
|
||||||
natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER);
|
return nil;
|
||||||
}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;
|
|
||||||
}
|
}
|
||||||
// unsupported
|
|
||||||
return nil;
|
ret:
|
||||||
|
raster->originalWidth = raster->width;
|
||||||
|
raster->originalHeight = raster->height;
|
||||||
|
raster->originalStride = raster->stride;
|
||||||
|
raster->originalPixels = raster->pixels;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8*
|
uint8*
|
||||||
rasterLock(Raster *raster, int32 level, int32 lockMode)
|
rasterLock(Raster *raster, int32 level, int32 lockMode)
|
||||||
{
|
{
|
||||||
// TODO?
|
XboxRaster *natras = GETXBOXRASTEREXT(raster);
|
||||||
(void)lockMode;
|
|
||||||
|
// 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;
|
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
|
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
|
int32
|
||||||
rasterNumLevels(Raster *raster)
|
rasterNumLevels(Raster *raster)
|
||||||
{
|
{
|
||||||
XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
|
XboxRaster *natras = GETXBOXRASTEREXT(raster);
|
||||||
RasterLevels *levels = (RasterLevels*)natras->texture;
|
RasterLevels *levels = (RasterLevels*)natras->texture;
|
||||||
return levels->numlevels;
|
return levels->numlevels;
|
||||||
}
|
}
|
||||||
|
@ -656,12 +696,23 @@ rasterToImage(Raster *raster)
|
||||||
{
|
{
|
||||||
int32 depth;
|
int32 depth;
|
||||||
Image *image;
|
Image *image;
|
||||||
XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
|
|
||||||
|
|
||||||
if(natras->format){
|
bool unlock = false;
|
||||||
image = Image::create(raster->width, raster->height, 32);
|
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();
|
image->allocate();
|
||||||
uint8 *pix = raster->lock(0, Raster::LOCKREAD);
|
uint8 *pix = raster->pixels;
|
||||||
switch(natras->format){
|
switch(natras->format){
|
||||||
case D3DFMT_DXT1:
|
case D3DFMT_DXT1:
|
||||||
image->setPixelsDXT(1, pix);
|
image->setPixelsDXT(1, pix);
|
||||||
|
@ -677,11 +728,17 @@ rasterToImage(Raster *raster)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0 && "unknown format");
|
assert(0 && "unknown format");
|
||||||
raster->unlock(0);
|
|
||||||
image->destroy();
|
image->destroy();
|
||||||
|
if(unlock)
|
||||||
|
raster->unlock(0);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
raster->unlock(0);
|
// fix it up again
|
||||||
|
image->width = raster->width;
|
||||||
|
image->height = raster->height;
|
||||||
|
|
||||||
|
if(unlock)
|
||||||
|
raster->unlock(0);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,48 +771,51 @@ rasterToImage(Raster *raster)
|
||||||
pallength = 256;
|
pallength = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 *in, *out;
|
|
||||||
image = Image::create(raster->width, raster->height, depth);
|
image = Image::create(raster->width, raster->height, depth);
|
||||||
image->allocate();
|
image->allocate();
|
||||||
|
|
||||||
if(pallength){
|
if(pallength){
|
||||||
out = image->palette;
|
uint8 *out = image->palette;
|
||||||
in = (uint8*)natras->palette;
|
uint8 *in = (uint8*)natras->palette;
|
||||||
|
// bytes are BGRA unlike regular d3d!
|
||||||
for(int32 i = 0; i < pallength; i++){
|
for(int32 i = 0; i < pallength; i++){
|
||||||
out[0] = in[2];
|
conv_BGRA8888_from_RGBA8888(out, in);
|
||||||
out[1] = in[1];
|
|
||||||
out[2] = in[0];
|
|
||||||
out[3] = in[3];
|
|
||||||
in += 4;
|
in += 4;
|
||||||
out += 4;
|
out += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out = image->pixels;
|
uint8 *imgpixels = image->pixels;
|
||||||
in = raster->lock(0, Raster::LOCKREAD);
|
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
|
// Fix RGB order
|
||||||
// TODO: stride
|
|
||||||
uint8 tmp;
|
uint8 tmp;
|
||||||
if(depth > 8)
|
if(depth > 8)
|
||||||
for(int32 y = 0; y < image->height; y++)
|
for(int32 y = 0; y < image->height; y++){
|
||||||
for(int32 x = 0; x < image->width; x++)
|
uint8 *imgrow = imgpixels;
|
||||||
|
// uint8 *rasrow = pixels;
|
||||||
|
for(int32 x = 0; x < image->width; x++){
|
||||||
switch(raster->format & 0xF00){
|
switch(raster->format & 0xF00){
|
||||||
case Raster::C8888:
|
case Raster::C8888:
|
||||||
tmp = out[0];
|
|
||||||
out[0] = out[2];
|
|
||||||
out[2] = tmp;
|
|
||||||
out += 4;
|
|
||||||
break;
|
|
||||||
case Raster::C888:
|
case Raster::C888:
|
||||||
tmp = out[0];
|
tmp = imgrow[0];
|
||||||
out[0] = out[2];
|
imgrow[0] = imgrow[2];
|
||||||
out[2] = tmp;
|
imgrow[2] = tmp;
|
||||||
out += 3;
|
imgrow += image->bpp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
raster->unlock(0);
|
}
|
||||||
|
imgpixels += image->stride;
|
||||||
|
// pixels += raster->stride;
|
||||||
|
}
|
||||||
|
image->compressPalette();
|
||||||
|
|
||||||
|
if(unlock)
|
||||||
|
raster->unlock(0);
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
@ -763,7 +823,7 @@ rasterToImage(Raster *raster)
|
||||||
int32
|
int32
|
||||||
getLevelSize(Raster *raster, int32 level)
|
getLevelSize(Raster *raster, int32 level)
|
||||||
{
|
{
|
||||||
XboxRaster *ras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
|
XboxRaster *ras = GETXBOXRASTEREXT(raster);
|
||||||
RasterLevels *levels = (RasterLevels*)ras->texture;
|
RasterLevels *levels = (RasterLevels*)ras->texture;
|
||||||
return levels->levels[level].size;
|
return levels->levels[level].size;
|
||||||
}
|
}
|
||||||
|
@ -776,6 +836,7 @@ createNativeRaster(void *object, int32 offset, int32)
|
||||||
raster->palette = nil;
|
raster->palette = nil;
|
||||||
raster->format = 0;
|
raster->format = 0;
|
||||||
raster->hasAlpha = 0;
|
raster->hasAlpha = 0;
|
||||||
|
raster->customFormat = 0;
|
||||||
raster->unknownFlag = 0;
|
raster->unknownFlag = 0;
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
@ -836,6 +897,9 @@ readNativeTexture(Stream *stream)
|
||||||
stream->read8(tex->name, 32);
|
stream->read8(tex->name, 32);
|
||||||
stream->read8(tex->mask, 32);
|
stream->read8(tex->mask, 32);
|
||||||
|
|
||||||
|
//if(strcmp(tex->name, "bluallu") == 0)
|
||||||
|
//__debugbreak();
|
||||||
|
|
||||||
// Raster
|
// Raster
|
||||||
int32 format = stream->readI32();
|
int32 format = stream->readI32();
|
||||||
bool32 hasAlpha = stream->readI16();
|
bool32 hasAlpha = stream->readI16();
|
||||||
|
@ -853,16 +917,17 @@ readNativeTexture(Stream *stream)
|
||||||
Raster *raster;
|
Raster *raster;
|
||||||
if(compression){
|
if(compression){
|
||||||
raster = Raster::create(width, height, depth, format | type | Raster::DONTALLOCATE, PLATFORM_XBOX);
|
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->format = compression;
|
||||||
ras->hasAlpha = hasAlpha;
|
ras->hasAlpha = hasAlpha;
|
||||||
ras->texture = createTexture(raster->width, raster->height,
|
ras->texture = createTexture(raster->width, raster->height,
|
||||||
raster->format & Raster::MIPMAP ? numLevels : 1,
|
raster->format & Raster::MIPMAP ? numLevels : 1,
|
||||||
ras->format);
|
ras->format);
|
||||||
|
ras->customFormat = 1;
|
||||||
raster->flags &= ~Raster::DONTALLOCATE;
|
raster->flags &= ~Raster::DONTALLOCATE;
|
||||||
}else
|
}else
|
||||||
raster = Raster::create(width, height, depth, format | type, PLATFORM_XBOX);
|
raster = Raster::create(width, height, depth, format | type, PLATFORM_XBOX);
|
||||||
XboxRaster *ras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
|
XboxRaster *ras = GETXBOXRASTEREXT(raster);
|
||||||
tex->raster = raster;
|
tex->raster = raster;
|
||||||
|
|
||||||
if(raster->format & Raster::PAL4)
|
if(raster->format & Raster::PAL4)
|
||||||
|
@ -892,7 +957,7 @@ writeNativeTexture(Texture *tex, Stream *stream)
|
||||||
|
|
||||||
// Raster
|
// Raster
|
||||||
Raster *raster = tex->raster;
|
Raster *raster = tex->raster;
|
||||||
XboxRaster *ras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset);
|
XboxRaster *ras = GETXBOXRASTEREXT(raster);
|
||||||
int32 numLevels = raster->getNumLevels();
|
int32 numLevels = raster->getNumLevels();
|
||||||
stream->writeI32(raster->format);
|
stream->writeI32(raster->format);
|
||||||
stream->writeI16(ras->hasAlpha);
|
stream->writeI16(ras->hasAlpha);
|
||||||
|
|
|
@ -260,6 +260,8 @@ static uint32 blendMap[] = {
|
||||||
GL_SRC_ALPHA_SATURATE,
|
GL_SRC_ALPHA_SATURATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static float maxAnisotropy;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GL state cache
|
* GL state cache
|
||||||
*/
|
*/
|
||||||
|
@ -434,12 +436,16 @@ bindFramebuffer(uint32 fbo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: support mipmaps
|
|
||||||
static GLint filterConvMap_NoMIP[] = {
|
static GLint filterConvMap_NoMIP[] = {
|
||||||
0, GL_NEAREST, GL_LINEAR,
|
0, GL_NEAREST, GL_LINEAR,
|
||||||
GL_NEAREST, GL_LINEAR,
|
GL_NEAREST, GL_LINEAR,
|
||||||
GL_NEAREST, GL_LINEAR
|
GL_NEAREST, GL_LINEAR
|
||||||
};
|
};
|
||||||
|
static GLint filterConvMap_MIP[] = {
|
||||||
|
0, GL_NEAREST, GL_LINEAR,
|
||||||
|
GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST,
|
||||||
|
GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR
|
||||||
|
};
|
||||||
|
|
||||||
static GLint addressConvMap[] = {
|
static GLint addressConvMap[] = {
|
||||||
0, GL_REPEAT, GL_MIRRORED_REPEAT,
|
0, GL_REPEAT, GL_MIRRORED_REPEAT,
|
||||||
|
@ -456,8 +462,13 @@ setFilterMode(uint32 stage, int32 filter)
|
||||||
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, rwStateCache.texstage[stage].raster, nativeRasterOffset);
|
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, rwStateCache.texstage[stage].raster, nativeRasterOffset);
|
||||||
if(natras->filterMode != filter){
|
if(natras->filterMode != filter){
|
||||||
setActiveTexture(stage);
|
setActiveTexture(stage);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_NoMIP[filter]);
|
if(natras->autogenMipmap || natras->numLevels > 1){
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_MIP[filter]);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_MIP[filter]);
|
||||||
|
}else{
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_NoMIP[filter]);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]);
|
||||||
|
}
|
||||||
natras->filterMode = filter;
|
natras->filterMode = filter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,8 +558,13 @@ setRasterStage(uint32 stage, Raster *raster)
|
||||||
uint32 addrU = rwStateCache.texstage[stage].addressingU;
|
uint32 addrU = rwStateCache.texstage[stage].addressingU;
|
||||||
uint32 addrV = rwStateCache.texstage[stage].addressingV;
|
uint32 addrV = rwStateCache.texstage[stage].addressingV;
|
||||||
if(natras->filterMode != filter){
|
if(natras->filterMode != filter){
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_NoMIP[filter]);
|
if(natras->autogenMipmap || natras->numLevels > 1){
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_MIP[filter]);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_MIP[filter]);
|
||||||
|
}else{
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_NoMIP[filter]);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]);
|
||||||
|
}
|
||||||
natras->filterMode = filter;
|
natras->filterMode = filter;
|
||||||
}
|
}
|
||||||
if(natras->addressU != addrU){
|
if(natras->addressU != addrU){
|
||||||
|
@ -1521,6 +1537,8 @@ initOpenGL(void)
|
||||||
|
|
||||||
resetRenderState();
|
resetRenderState();
|
||||||
|
|
||||||
|
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
|
||||||
|
|
||||||
#ifndef RW_GLES2
|
#ifndef RW_GLES2
|
||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &vao);
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(vao);
|
||||||
|
|
|
@ -22,10 +22,50 @@ namespace gl3 {
|
||||||
|
|
||||||
int32 nativeRasterOffset;
|
int32 nativeRasterOffset;
|
||||||
|
|
||||||
|
static uint32
|
||||||
|
getLevelSize(Raster *raster, int32 level)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
||||||
|
|
||||||
|
int w = raster->originalWidth;
|
||||||
|
int h = raster->originalHeight;
|
||||||
|
int s = raster->originalStride;
|
||||||
|
int minDim = 1;
|
||||||
|
|
||||||
#ifdef RW_OPENGL
|
#ifdef RW_OPENGL
|
||||||
|
switch(natras->internalFormat){
|
||||||
|
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||||
|
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||||
|
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||||
|
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||||
|
minDim = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(i = 0; i < level; i++){
|
||||||
|
if(w > minDim){
|
||||||
|
w /= 2;
|
||||||
|
s /= 2;
|
||||||
|
}
|
||||||
|
if(h > minDim)
|
||||||
|
h /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s*h;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RW_OPENGL
|
||||||
|
|
||||||
static Raster*
|
static Raster*
|
||||||
rasterCreateTexture(Raster *raster)
|
rasterCreateTexture(Raster *raster)
|
||||||
{
|
{
|
||||||
|
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
|
||||||
|
RWERROR((ERR_NOTEXTURE));
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
||||||
switch(raster->format & 0xF00){
|
switch(raster->format & 0xF00){
|
||||||
case Raster::C8888:
|
case Raster::C8888:
|
||||||
|
@ -65,19 +105,36 @@ rasterCreateTexture(Raster *raster)
|
||||||
natras->bpp = 4;
|
natras->bpp = 4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
natras->isCompressed = 0;
|
|
||||||
|
|
||||||
raster->stride = raster->width*natras->bpp;
|
raster->stride = raster->width*natras->bpp;
|
||||||
|
|
||||||
|
if(raster->format & Raster::MIPMAP){
|
||||||
|
int w = raster->width;
|
||||||
|
int h = raster->height;
|
||||||
|
natras->numLevels = 0;
|
||||||
|
while(w != 1 || h != 1){
|
||||||
|
natras->numLevels++;
|
||||||
|
if(w > 1) w /= 2;
|
||||||
|
if(h > 1) h /= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP);
|
||||||
|
if(natras->autogenMipmap)
|
||||||
|
natras->numLevels = 1;
|
||||||
|
|
||||||
glGenTextures(1, &natras->texid);
|
glGenTextures(1, &natras->texid);
|
||||||
uint32 prev = bindTexture(natras->texid);
|
uint32 prev = bindTexture(natras->texid);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
|
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
|
||||||
raster->width, raster->height,
|
raster->width, raster->height,
|
||||||
0, natras->format, natras->type, nil);
|
0, natras->format, natras->type, nil);
|
||||||
|
// TODO: allocate other levels...probably
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, natras->numLevels-1);
|
||||||
natras->filterMode = 0;
|
natras->filterMode = 0;
|
||||||
natras->addressU = 0;
|
natras->addressU = 0;
|
||||||
natras->addressV = 0;
|
natras->addressV = 0;
|
||||||
|
|
||||||
|
// TEST
|
||||||
|
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f);
|
||||||
|
|
||||||
bindTexture(prev);
|
bindTexture(prev);
|
||||||
return raster;
|
return raster;
|
||||||
}
|
}
|
||||||
|
@ -125,10 +182,10 @@ rasterCreateCameraTexture(Raster *raster)
|
||||||
// natras->bpp = 4;
|
// natras->bpp = 4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
natras->isCompressed = 0;
|
|
||||||
|
|
||||||
raster->stride = raster->width*natras->bpp;
|
raster->stride = raster->width*natras->bpp;
|
||||||
|
|
||||||
|
natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP);
|
||||||
|
|
||||||
glGenTextures(1, &natras->texid);
|
glGenTextures(1, &natras->texid);
|
||||||
uint32 prev = bindTexture(natras->texid);
|
uint32 prev = bindTexture(natras->texid);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
|
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
|
||||||
|
@ -156,10 +213,8 @@ rasterCreateCamera(Raster *raster)
|
||||||
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
||||||
|
|
||||||
// TODO: set/check width, height, depth, format?
|
// TODO: set/check width, height, depth, format?
|
||||||
raster->originalWidth = raster->width;
|
|
||||||
raster->originalHeight = raster->height;
|
natras->autogenMipmap = 0;
|
||||||
raster->stride = 0;
|
|
||||||
raster->pixels = nil;
|
|
||||||
|
|
||||||
natras->texid = 0;
|
natras->texid = 0;
|
||||||
natras->fbo = 0;
|
natras->fbo = 0;
|
||||||
|
@ -174,16 +229,12 @@ rasterCreateZbuffer(Raster *raster)
|
||||||
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
||||||
|
|
||||||
// TODO: set/check width, height, depth, format?
|
// TODO: set/check width, height, depth, format?
|
||||||
raster->originalWidth = raster->width;
|
|
||||||
raster->originalHeight = raster->height;
|
|
||||||
raster->stride = 0;
|
|
||||||
raster->pixels = nil;
|
|
||||||
|
|
||||||
natras->internalFormat = GL_DEPTH_COMPONENT;
|
natras->internalFormat = GL_DEPTH_COMPONENT;
|
||||||
natras->format = GL_DEPTH_COMPONENT;
|
natras->format = GL_DEPTH_COMPONENT;
|
||||||
natras->type = GL_UNSIGNED_BYTE;
|
natras->type = GL_UNSIGNED_BYTE;
|
||||||
|
|
||||||
natras->isCompressed = 0;
|
natras->autogenMipmap = 0;
|
||||||
|
|
||||||
glGenTextures(1, &natras->texid);
|
glGenTextures(1, &natras->texid);
|
||||||
uint32 prev = bindTexture(natras->texid);
|
uint32 prev = bindTexture(natras->texid);
|
||||||
|
@ -202,8 +253,75 @@ rasterCreateZbuffer(Raster *raster)
|
||||||
return raster;
|
return raster;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha)
|
||||||
|
{
|
||||||
|
#ifdef RW_OPENGL
|
||||||
|
assert(raster->type == Raster::TEXTURE);
|
||||||
|
|
||||||
|
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
||||||
|
switch(dxt){
|
||||||
|
case 1:
|
||||||
|
if(hasAlpha){
|
||||||
|
natras->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||||
|
natras->format = GL_RGBA;
|
||||||
|
}else{
|
||||||
|
natras->internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||||
|
natras->format = GL_RGB;
|
||||||
|
}
|
||||||
|
// bogus, but stride*height should be the size of the image
|
||||||
|
// 4x4 in 8 bytes
|
||||||
|
raster->stride = raster->width/2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
natras->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
natras->format = GL_RGBA;
|
||||||
|
// 4x4 in 16 bytes
|
||||||
|
raster->stride = raster->width;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
natras->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
natras->format = GL_RGBA;
|
||||||
|
// 4x4 in 16 bytes
|
||||||
|
raster->stride = raster->width;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0 && "invalid DXT format");
|
||||||
|
}
|
||||||
|
natras->type = GL_UNSIGNED_BYTE;
|
||||||
|
natras->hasAlpha = hasAlpha;
|
||||||
|
natras->bpp = 2;
|
||||||
|
raster->depth = 16;
|
||||||
|
|
||||||
|
natras->isCompressed = 1;
|
||||||
|
if(raster->format & Raster::MIPMAP)
|
||||||
|
natras->numLevels = numLevels;
|
||||||
|
natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP);
|
||||||
|
if(natras->autogenMipmap)
|
||||||
|
natras->numLevels = 1;
|
||||||
|
|
||||||
|
glGenTextures(1, &natras->texid);
|
||||||
|
uint32 prev = bindTexture(natras->texid);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
|
||||||
|
raster->width, raster->height,
|
||||||
|
0, natras->format, natras->type, nil);
|
||||||
|
// TODO: allocate other levels...probably
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, natras->numLevels-1);
|
||||||
|
natras->filterMode = 0;
|
||||||
|
natras->addressU = 0;
|
||||||
|
natras->addressV = 0;
|
||||||
|
|
||||||
|
bindTexture(prev);
|
||||||
|
|
||||||
|
raster->originalStride = raster->stride;
|
||||||
|
raster->flags &= ~Raster::DONTALLOCATE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
{ 0, 0, 0 },
|
{ 0, 0, 0 },
|
||||||
{ 16, 4, GL_RGBA }, // 1555
|
{ 16, 4, GL_RGBA }, // 1555
|
||||||
|
@ -233,31 +351,50 @@ GL_RGB5
|
||||||
Raster*
|
Raster*
|
||||||
rasterCreate(Raster *raster)
|
rasterCreate(Raster *raster)
|
||||||
{
|
{
|
||||||
|
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
||||||
|
|
||||||
|
natras->isCompressed = 0;
|
||||||
|
natras->hasAlpha = 0;
|
||||||
|
natras->numLevels = 1;
|
||||||
|
|
||||||
|
Raster *ret = raster;
|
||||||
|
|
||||||
if(raster->width == 0 || raster->height == 0){
|
if(raster->width == 0 || raster->height == 0){
|
||||||
raster->flags |= Raster::DONTALLOCATE;
|
raster->flags |= Raster::DONTALLOCATE;
|
||||||
raster->stride = 0;
|
raster->stride = 0;
|
||||||
return raster;
|
goto ret;
|
||||||
}
|
}
|
||||||
if(raster->flags & Raster::DONTALLOCATE)
|
if(raster->flags & Raster::DONTALLOCATE)
|
||||||
return raster;
|
goto ret;
|
||||||
|
|
||||||
switch(raster->type){
|
switch(raster->type){
|
||||||
#ifdef RW_OPENGL
|
#ifdef RW_OPENGL
|
||||||
case Raster::NORMAL:
|
case Raster::NORMAL:
|
||||||
case Raster::TEXTURE:
|
case Raster::TEXTURE:
|
||||||
return rasterCreateTexture(raster);
|
ret = rasterCreateTexture(raster);
|
||||||
|
break;
|
||||||
case Raster::CAMERATEXTURE:
|
case Raster::CAMERATEXTURE:
|
||||||
return rasterCreateCameraTexture(raster);
|
ret = rasterCreateCameraTexture(raster);
|
||||||
|
break;
|
||||||
case Raster::ZBUFFER:
|
case Raster::ZBUFFER:
|
||||||
return rasterCreateZbuffer(raster);
|
ret = rasterCreateZbuffer(raster);
|
||||||
|
break;
|
||||||
case Raster::CAMERA:
|
case Raster::CAMERA:
|
||||||
return rasterCreateCamera(raster);
|
ret = rasterCreateCamera(raster);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
RWERROR((ERR_INVRASTER));
|
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*
|
uint8*
|
||||||
|
@ -266,6 +403,7 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
|
||||||
#ifdef RW_OPENGL
|
#ifdef RW_OPENGL
|
||||||
Gl3Raster *natras GETGL3RASTEREXT(raster);
|
Gl3Raster *natras GETGL3RASTEREXT(raster);
|
||||||
uint8 *px;
|
uint8 *px;
|
||||||
|
int i;
|
||||||
|
|
||||||
assert(raster->privateFlags == 0);
|
assert(raster->privateFlags == 0);
|
||||||
|
|
||||||
|
@ -273,7 +411,16 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
|
||||||
case Raster::NORMAL:
|
case Raster::NORMAL:
|
||||||
case Raster::TEXTURE:
|
case Raster::TEXTURE:
|
||||||
case Raster::CAMERATEXTURE:
|
case Raster::CAMERATEXTURE:
|
||||||
px = (uint8*)rwMalloc(raster->stride*raster->height, MEMDUR_EVENT | ID_DRIVER);
|
for(i = 0; i < level; i++){
|
||||||
|
if(raster->width > 1){
|
||||||
|
raster->width /= 2;
|
||||||
|
raster->stride /= 2;
|
||||||
|
}
|
||||||
|
if(raster->height > 1)
|
||||||
|
raster->height /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
px = (uint8*)rwMalloc(getLevelSize(raster, level), MEMDUR_EVENT | ID_DRIVER);
|
||||||
assert(raster->pixels == nil);
|
assert(raster->pixels == nil);
|
||||||
raster->pixels = px;
|
raster->pixels = px;
|
||||||
|
|
||||||
|
@ -297,6 +444,7 @@ assert(natras->format == GL_RGBA);
|
||||||
glDeleteFramebuffers(1, &fbo);
|
glDeleteFramebuffers(1, &fbo);
|
||||||
#else
|
#else
|
||||||
uint32 prev = bindTexture(natras->texid);
|
uint32 prev = bindTexture(natras->texid);
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||||
glGetTexImage(GL_TEXTURE_2D, level, natras->format, natras->type, px);
|
glGetTexImage(GL_TEXTURE_2D, level, natras->format, natras->type, px);
|
||||||
bindTexture(prev);
|
bindTexture(prev);
|
||||||
#endif
|
#endif
|
||||||
|
@ -328,28 +476,35 @@ rasterUnlock(Raster *raster, int32 level)
|
||||||
if(raster->privateFlags & Raster::LOCKWRITE){
|
if(raster->privateFlags & Raster::LOCKWRITE){
|
||||||
uint32 prev = bindTexture(natras->texid);
|
uint32 prev = bindTexture(natras->texid);
|
||||||
if(natras->isCompressed)
|
if(natras->isCompressed)
|
||||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
|
glCompressedTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat,
|
||||||
raster->width, raster->height, 0,
|
raster->width, raster->height, 0,
|
||||||
raster->stride*raster->height,
|
getLevelSize(raster, level),
|
||||||
raster->pixels);
|
raster->pixels);
|
||||||
else
|
else{
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat,
|
glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat,
|
||||||
raster->width, raster->height,
|
raster->width, raster->height,
|
||||||
0, natras->format, natras->type, raster->pixels);
|
0, natras->format, natras->type, raster->pixels);
|
||||||
|
}
|
||||||
|
if(level == 0 && natras->autogenMipmap)
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
bindTexture(prev);
|
bindTexture(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
rwFree(raster->pixels);
|
rwFree(raster->pixels);
|
||||||
raster->pixels = nil;
|
raster->pixels = nil;
|
||||||
raster->privateFlags = 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
raster->width = raster->originalWidth;
|
||||||
|
raster->height = raster->originalHeight;
|
||||||
|
raster->stride = raster->originalStride;
|
||||||
|
raster->pixels = raster->originalPixels;
|
||||||
|
raster->privateFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32
|
int32
|
||||||
rasterNumLevels(Raster*)
|
rasterNumLevels(Raster *raster)
|
||||||
{
|
{
|
||||||
// TODO
|
return GETGL3RASTEREXT(raster)->numLevels;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Almost the same as d3d9 and ps2 function
|
// Almost the same as d3d9 and ps2 function
|
||||||
|
@ -425,14 +580,16 @@ rasterFromImage(Raster *raster, Image *image)
|
||||||
}
|
}
|
||||||
|
|
||||||
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
||||||
|
int32 format = raster->format&0xF00;
|
||||||
|
assert(!natras->isCompressed);
|
||||||
switch(image->depth){
|
switch(image->depth){
|
||||||
case 32:
|
case 32:
|
||||||
#ifdef RW_GLES
|
#ifdef RW_GLES
|
||||||
conv = conv_RGBA8888_from_RGBA8888;
|
conv = conv_RGBA8888_from_RGBA8888;
|
||||||
#else
|
#else
|
||||||
if(raster->format == Raster::C8888)
|
if(format == Raster::C8888)
|
||||||
conv = conv_RGBA8888_from_RGBA8888;
|
conv = conv_RGBA8888_from_RGBA8888;
|
||||||
else if(raster->format == Raster::C888)
|
else if(format == Raster::C888)
|
||||||
conv = conv_RGB888_from_RGB888;
|
conv = conv_RGB888_from_RGB888;
|
||||||
else
|
else
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -442,9 +599,9 @@ rasterFromImage(Raster *raster, Image *image)
|
||||||
#ifdef RW_GLES
|
#ifdef RW_GLES
|
||||||
conv = conv_RGBA8888_from_RGB888;
|
conv = conv_RGBA8888_from_RGB888;
|
||||||
#else
|
#else
|
||||||
if(raster->format == Raster::C8888)
|
if(format == Raster::C8888)
|
||||||
conv = conv_RGBA8888_from_RGB888;
|
conv = conv_RGBA8888_from_RGB888;
|
||||||
else if(raster->format == Raster::C888)
|
else if(format == Raster::C888)
|
||||||
conv = conv_RGB888_from_RGB888;
|
conv = conv_RGB888_from_RGB888;
|
||||||
else
|
else
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -454,7 +611,7 @@ rasterFromImage(Raster *raster, Image *image)
|
||||||
#ifdef RW_GLES
|
#ifdef RW_GLES
|
||||||
conv = conv_RGBA8888_from_ARGB1555;
|
conv = conv_RGBA8888_from_ARGB1555;
|
||||||
#else
|
#else
|
||||||
if(raster->format == Raster::C1555)
|
if(format == Raster::C1555)
|
||||||
conv = conv_RGBA5551_from_ARGB1555;
|
conv = conv_RGBA5551_from_ARGB1555;
|
||||||
else
|
else
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -471,7 +628,13 @@ rasterFromImage(Raster *raster, Image *image)
|
||||||
|
|
||||||
natras->hasAlpha = image->hasAlpha();
|
natras->hasAlpha = image->hasAlpha();
|
||||||
|
|
||||||
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);
|
assert(pixels);
|
||||||
uint8 *imgpixels = image->pixels + (image->height-1)*image->stride;
|
uint8 *imgpixels = image->pixels + (image->height-1)*image->stride;
|
||||||
|
|
||||||
|
@ -489,7 +652,8 @@ rasterFromImage(Raster *raster, Image *image)
|
||||||
imgpixels -= image->stride;
|
imgpixels -= image->stride;
|
||||||
pixels += raster->stride;
|
pixels += raster->stride;
|
||||||
}
|
}
|
||||||
raster->unlock(0);
|
if(unlock)
|
||||||
|
raster->unlock(0);
|
||||||
|
|
||||||
if(truecolimg)
|
if(truecolimg)
|
||||||
truecolimg->destroy();
|
truecolimg->destroy();
|
||||||
|
@ -497,61 +661,6 @@ rasterFromImage(Raster *raster, Image *image)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha)
|
|
||||||
{
|
|
||||||
#ifdef RW_OPENGL
|
|
||||||
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
|
||||||
switch(dxt){
|
|
||||||
case 1:
|
|
||||||
if(hasAlpha){
|
|
||||||
natras->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
|
||||||
natras->format = GL_RGBA;
|
|
||||||
}else{
|
|
||||||
natras->internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
||||||
natras->format = GL_RGB;
|
|
||||||
}
|
|
||||||
// bogus, but stride*height should be the size of the image
|
|
||||||
// 4x4 in 8 bytes
|
|
||||||
raster->stride = raster->width/2;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
natras->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
||||||
natras->format = GL_RGBA;
|
|
||||||
// 4x4 in 16 bytes
|
|
||||||
raster->stride = raster->width;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
natras->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
|
||||||
natras->format = GL_RGBA;
|
|
||||||
// 4x4 in 16 bytes
|
|
||||||
raster->stride = raster->width;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0 && "invalid DXT format");
|
|
||||||
}
|
|
||||||
natras->type = GL_UNSIGNED_BYTE;
|
|
||||||
natras->hasAlpha = hasAlpha;
|
|
||||||
natras->bpp = 2;
|
|
||||||
raster->depth = 16;
|
|
||||||
|
|
||||||
natras->isCompressed = 1;
|
|
||||||
|
|
||||||
glGenTextures(1, &natras->texid);
|
|
||||||
uint32 prev = bindTexture(natras->texid);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
|
|
||||||
raster->width, raster->height,
|
|
||||||
0, natras->format, natras->type, nil);
|
|
||||||
natras->filterMode = 0;
|
|
||||||
natras->addressU = 0;
|
|
||||||
natras->addressV = 0;
|
|
||||||
|
|
||||||
bindTexture(prev);
|
|
||||||
|
|
||||||
raster->flags &= ~Raster::DONTALLOCATE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void*
|
static void*
|
||||||
createNativeRaster(void *object, int32 offset, int32)
|
createNativeRaster(void *object, int32 offset, int32)
|
||||||
{
|
{
|
||||||
|
@ -624,16 +733,6 @@ copyNativeRaster(void *dst, void *, int32 offset, int32)
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32
|
|
||||||
getLevelSize(Raster *raster, int32 level)
|
|
||||||
{
|
|
||||||
Gl3Raster *natras = GETGL3RASTEREXT(raster);
|
|
||||||
uint32 size = raster->stride*raster->height;
|
|
||||||
while(level--)
|
|
||||||
size /= 4;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
Texture*
|
Texture*
|
||||||
readNativeTexture(Stream *stream)
|
readNativeTexture(Stream *stream)
|
||||||
{
|
{
|
||||||
|
@ -683,12 +782,9 @@ readNativeTexture(Stream *stream)
|
||||||
uint8 *data;
|
uint8 *data;
|
||||||
for(int32 i = 0; i < numLevels; i++){
|
for(int32 i = 0; i < numLevels; i++){
|
||||||
size = stream->readU32();
|
size = stream->readU32();
|
||||||
if(i < raster->getNumLevels()){
|
data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
|
||||||
data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
|
stream->read8(data, size);
|
||||||
stream->read8(data, size);
|
raster->unlock(i);
|
||||||
raster->unlock(i);
|
|
||||||
}else
|
|
||||||
stream->seek(size);
|
|
||||||
}
|
}
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
@ -709,7 +805,7 @@ writeNativeTexture(Texture *tex, Stream *stream)
|
||||||
stream->write8(tex->mask, 32);
|
stream->write8(tex->mask, 32);
|
||||||
|
|
||||||
// Raster
|
// Raster
|
||||||
int32 numLevels = raster->getNumLevels();
|
int32 numLevels = natras->numLevels;
|
||||||
stream->writeI32(raster->format);
|
stream->writeI32(raster->format);
|
||||||
stream->writeI32(raster->width);
|
stream->writeI32(raster->width);
|
||||||
stream->writeI32(raster->height);
|
stream->writeI32(raster->height);
|
||||||
|
@ -758,7 +854,7 @@ writeNativeTexture(Texture *tex, Stream *stream)
|
||||||
uint32
|
uint32
|
||||||
getSizeNativeTexture(Texture *tex)
|
getSizeNativeTexture(Texture *tex)
|
||||||
{
|
{
|
||||||
uint32 size = 12 + 72 + 20;
|
uint32 size = 12 + 72 + 28;
|
||||||
int32 levels = tex->raster->getNumLevels();
|
int32 levels = tex->raster->getNumLevels();
|
||||||
for(int32 i = 0; i < levels; i++)
|
for(int32 i = 0; i < levels; i++)
|
||||||
size += 4 + getLevelSize(tex->raster, i);
|
size += 4 + getLevelSize(tex->raster, i);
|
||||||
|
|
|
@ -233,8 +233,10 @@ struct Gl3Raster
|
||||||
// texture object
|
// texture object
|
||||||
uint32 texid;
|
uint32 texid;
|
||||||
|
|
||||||
bool32 isCompressed;
|
bool isCompressed;
|
||||||
bool32 hasAlpha;
|
bool hasAlpha;
|
||||||
|
bool autogenMipmap;
|
||||||
|
int8 numLevels;
|
||||||
// cached filtermode and addressing
|
// cached filtermode and addressing
|
||||||
uint8 filterMode;
|
uint8 filterMode;
|
||||||
uint8 addressU;
|
uint8 addressU;
|
||||||
|
|
124
src/image.cpp
124
src/image.cpp
|
@ -163,8 +163,8 @@ decompressDXT1(uint8 *adst, int32 w, int32 h, uint8 *src)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write bytes */
|
/* write bytes */
|
||||||
for(uint32 k = 0; k < 4; k++)
|
for(uint32 l = 0; l < 4; l++)
|
||||||
for(uint32 l = 0; l < 4; l++){
|
for(uint32 k = 0; k < 4; k++){
|
||||||
dst[(y+l)*w + x+k][0] = c[idx[l*4+k]][0];
|
dst[(y+l)*w + x+k][0] = c[idx[l*4+k]][0];
|
||||||
dst[(y+l)*w + x+k][1] = c[idx[l*4+k]][1];
|
dst[(y+l)*w + x+k][1] = c[idx[l*4+k]][1];
|
||||||
dst[(y+l)*w + x+k][2] = c[idx[l*4+k]][2];
|
dst[(y+l)*w + x+k][2] = c[idx[l*4+k]][2];
|
||||||
|
@ -221,8 +221,8 @@ decompressDXT3(uint8 *adst, int32 w, int32 h, uint8 *src)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write bytes */
|
/* write bytes */
|
||||||
for(uint32 k = 0; k < 4; k++)
|
for(uint32 l = 0; l < 4; l++)
|
||||||
for(uint32 l = 0; l < 4; l++){
|
for(uint32 k = 0; k < 4; k++){
|
||||||
dst[(y+l)*w + x+k][0] = c[idx[l*4+k]][0];
|
dst[(y+l)*w + x+k][0] = c[idx[l*4+k]][0];
|
||||||
dst[(y+l)*w + x+k][1] = c[idx[l*4+k]][1];
|
dst[(y+l)*w + x+k][1] = c[idx[l*4+k]][1];
|
||||||
dst[(y+l)*w + x+k][2] = c[idx[l*4+k]][2];
|
dst[(y+l)*w + x+k][2] = c[idx[l*4+k]][2];
|
||||||
|
@ -308,8 +308,8 @@ decompressDXT5(uint8 *adst, int32 w, int32 h, uint8 *src)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write bytes */
|
/* write bytes */
|
||||||
for(uint32 k = 0; k < 4; k++)
|
for(uint32 l = 0; l < 4; l++)
|
||||||
for(uint32 l = 0; l < 4; l++){
|
for(uint32 k = 0; k < 4; k++){
|
||||||
dst[(y+l)*w + x+k][0] = c[idx[l*4+k]][0];
|
dst[(y+l)*w + x+k][0] = c[idx[l*4+k]][0];
|
||||||
dst[(y+l)*w + x+k][1] = c[idx[l*4+k]][1];
|
dst[(y+l)*w + x+k][1] = c[idx[l*4+k]][1];
|
||||||
dst[(y+l)*w + x+k][2] = c[idx[l*4+k]][2];
|
dst[(y+l)*w + x+k][2] = c[idx[l*4+k]][2];
|
||||||
|
@ -341,6 +341,22 @@ flipBlock(uint8 *dst, uint8 *src)
|
||||||
dst[7] = src[4];
|
dst[7] = src[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// flip top 2 rows of a DXT 2-bit block
|
||||||
|
static void
|
||||||
|
flipBlock_half(uint8 *dst, uint8 *src)
|
||||||
|
{
|
||||||
|
// color
|
||||||
|
dst[0] = src[0];
|
||||||
|
dst[1] = src[1];
|
||||||
|
dst[2] = src[2];
|
||||||
|
dst[3] = src[3];
|
||||||
|
// bits
|
||||||
|
dst[4] = src[5];
|
||||||
|
dst[5] = src[4];
|
||||||
|
dst[6] = src[6];
|
||||||
|
dst[7] = src[7];
|
||||||
|
}
|
||||||
|
|
||||||
// flip a DXT3 4-bit alpha block
|
// flip a DXT3 4-bit alpha block
|
||||||
static void
|
static void
|
||||||
flipAlphaBlock3(uint8 *dst, uint8 *src)
|
flipAlphaBlock3(uint8 *dst, uint8 *src)
|
||||||
|
@ -355,6 +371,20 @@ flipAlphaBlock3(uint8 *dst, uint8 *src)
|
||||||
dst[1] = src[7];
|
dst[1] = src[7];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// flip top 2 rows of a DXT3 4-bit alpha block
|
||||||
|
static void
|
||||||
|
flipAlphaBlock3_half(uint8 *dst, uint8 *src)
|
||||||
|
{
|
||||||
|
dst[0] = src[2];
|
||||||
|
dst[1] = src[3];
|
||||||
|
dst[2] = src[0];
|
||||||
|
dst[3] = src[1];
|
||||||
|
dst[4] = src[4];
|
||||||
|
dst[5] = src[5];
|
||||||
|
dst[6] = src[6];
|
||||||
|
dst[7] = src[7];
|
||||||
|
}
|
||||||
|
|
||||||
// flip a DXT5 3-bit alpha block
|
// flip a DXT5 3-bit alpha block
|
||||||
static void
|
static void
|
||||||
flipAlphaBlock5(uint8 *dst, uint8 *src)
|
flipAlphaBlock5(uint8 *dst, uint8 *src)
|
||||||
|
@ -370,17 +400,45 @@ flipAlphaBlock5(uint8 *dst, uint8 *src)
|
||||||
flipbits |= bits & 0xFFF;
|
flipbits |= bits & 0xFFF;
|
||||||
bits >>= 12;
|
bits >>= 12;
|
||||||
}
|
}
|
||||||
memcpy(src+2, &flipbits, 6);
|
memcpy(dst+2, &flipbits, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// flip top 2 rows of a DXT5 3-bit alpha block
|
||||||
|
static void
|
||||||
|
flipAlphaBlock5_half(uint8 *dst, uint8 *src)
|
||||||
|
{
|
||||||
|
// color
|
||||||
|
dst[0] = src[0];
|
||||||
|
dst[1] = src[1];
|
||||||
|
// bits
|
||||||
|
uint64 bits = *(uint64*)&src[2];
|
||||||
|
uint64 flipbits = bits & 0xFFFFFF000000;
|
||||||
|
flipbits |= (bits>>12) & 0xFFF;
|
||||||
|
flipbits |= (bits<<12) & 0xFFF000;
|
||||||
|
memcpy(dst+2, &flipbits, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
flipDXT1(uint8 *dst, uint8 *src, uint32 width, uint32 height)
|
flipDXT1(uint8 *dst, uint8 *src, uint32 width, uint32 height)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
assert(width % 4 == 0);
|
int bw = (width+3)/4;
|
||||||
assert(height % 4 == 0);
|
int bh = (height+3)/4;
|
||||||
int bw = width/4;
|
if(height < 4){
|
||||||
int bh = height/4;
|
// used pixels are always at the top
|
||||||
|
// so don't swap the full 4 rows
|
||||||
|
if(height == 2){
|
||||||
|
uint8 *s = src;
|
||||||
|
uint8 *d = dst;
|
||||||
|
for(x = 0; x < bw; x++){
|
||||||
|
flipBlock_half(dst, src);
|
||||||
|
s += 8;
|
||||||
|
d += 8;
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
memcpy(dst, src, 8*bw);
|
||||||
|
return;
|
||||||
|
}
|
||||||
dst += 8*bw*bh;
|
dst += 8*bw*bh;
|
||||||
for(y = 0; y < bh; y++){
|
for(y = 0; y < bh; y++){
|
||||||
dst -= 8*bw;
|
dst -= 8*bw;
|
||||||
|
@ -399,10 +457,24 @@ void
|
||||||
flipDXT3(uint8 *dst, uint8 *src, uint32 width, uint32 height)
|
flipDXT3(uint8 *dst, uint8 *src, uint32 width, uint32 height)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
assert(width % 4 == 0);
|
int bw = (width+3)/4;
|
||||||
assert(height % 4 == 0);
|
int bh = (height+3)/4;
|
||||||
int bw = width/4;
|
if(height < 4){
|
||||||
int bh = height/4;
|
// used pixels are always at the top
|
||||||
|
// so don't swap the full 4 rows
|
||||||
|
if(height == 2){
|
||||||
|
uint8 *s = src;
|
||||||
|
uint8 *d = dst;
|
||||||
|
for(x = 0; x < bw; x++){
|
||||||
|
flipAlphaBlock3_half(d, s);
|
||||||
|
flipBlock_half(d+8, s+8);
|
||||||
|
s += 16;
|
||||||
|
d += 16;
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
memcpy(dst, src, 16*bw);
|
||||||
|
return;
|
||||||
|
}
|
||||||
dst += 16*bw*bh;
|
dst += 16*bw*bh;
|
||||||
for(y = 0; y < bh; y++){
|
for(y = 0; y < bh; y++){
|
||||||
dst -= 16*bw;
|
dst -= 16*bw;
|
||||||
|
@ -422,10 +494,24 @@ void
|
||||||
flipDXT5(uint8 *dst, uint8 *src, uint32 width, uint32 height)
|
flipDXT5(uint8 *dst, uint8 *src, uint32 width, uint32 height)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
assert(width % 4 == 0);
|
int bw = (width+3)/4;
|
||||||
assert(height % 4 == 0);
|
int bh = (height+3)/4;
|
||||||
int bw = width/4;
|
if(height < 4){
|
||||||
int bh = height/4;
|
// used pixels are always at the top
|
||||||
|
// so don't swap the full 4 rows
|
||||||
|
if(height == 2){
|
||||||
|
uint8 *s = src;
|
||||||
|
uint8 *d = dst;
|
||||||
|
for(x = 0; x < bw; x++){
|
||||||
|
flipAlphaBlock5_half(d, s);
|
||||||
|
flipBlock_half(d+8, s+8);
|
||||||
|
s += 16;
|
||||||
|
d += 16;
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
memcpy(dst, src, 16*bw);
|
||||||
|
return;
|
||||||
|
}
|
||||||
dst += 16*bw*bh;
|
dst += 16*bw*bh;
|
||||||
for(y = 0; y < bh; y++){
|
for(y = 0; y < bh; y++){
|
||||||
dst -= 16*bw;
|
dst -= 16*bw;
|
||||||
|
|
21
src/plg.cpp
21
src/plg.cpp
|
@ -95,6 +95,13 @@ PluginList::streamRead(Stream *stream, void *object)
|
||||||
cont:
|
cont:
|
||||||
length -= header.length;
|
length -= header.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now the always callbacks
|
||||||
|
FORLIST(lnk, this->plugins){
|
||||||
|
Plugin *p = PLG(lnk);
|
||||||
|
if(p->alwaysCallback)
|
||||||
|
p->alwaysCallback(object, p->offset, p->size);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,6 +183,7 @@ PluginList::registerPlugin(int32 size, uint32 id,
|
||||||
p->write = nil;
|
p->write = nil;
|
||||||
p->getSize = nil;
|
p->getSize = nil;
|
||||||
p->rightsCallback = nil;
|
p->rightsCallback = nil;
|
||||||
|
p->alwaysCallback = nil;
|
||||||
p->parentList = this;
|
p->parentList = this;
|
||||||
this->plugins.add(&p->inParentList);
|
this->plugins.add(&p->inParentList);
|
||||||
allPlugins.add(&p->inGlobalList);
|
allPlugins.add(&p->inGlobalList);
|
||||||
|
@ -211,6 +219,19 @@ PluginList::setStreamRightsCallback(uint32 id, RightsCallback cb)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
PluginList::setStreamAlwaysCallback(uint32 id, AlwaysCallback cb)
|
||||||
|
{
|
||||||
|
FORLIST(lnk, this->plugins){
|
||||||
|
Plugin *p = PLG(lnk);
|
||||||
|
if(p->id == id){
|
||||||
|
p->alwaysCallback = cb;
|
||||||
|
return p->offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int32
|
int32
|
||||||
PluginList::getPluginOffset(uint32 id)
|
PluginList::getPluginOffset(uint32 id)
|
||||||
{
|
{
|
||||||
|
|
178
src/raster.cpp
178
src/raster.cpp
|
@ -10,10 +10,11 @@
|
||||||
#include "rwobjects.h"
|
#include "rwobjects.h"
|
||||||
#include "rwengine.h"
|
#include "rwengine.h"
|
||||||
//#include "ps2/rwps2.h"
|
//#include "ps2/rwps2.h"
|
||||||
//#include "d3d/rwd3d.h"
|
#include "d3d/rwd3d.h"
|
||||||
//#include "d3d/rwxbox.h"
|
#include "d3d/rwxbox.h"
|
||||||
//#include "d3d/rwd3d8.h"
|
//#include "d3d/rwd3d8.h"
|
||||||
//#include "d3d/rwd3d9.h"
|
//#include "d3d/rwd3d9.h"
|
||||||
|
#include "gl/rwgl3.h"
|
||||||
|
|
||||||
#define PLUGIN_ID 0
|
#define PLUGIN_ID 0
|
||||||
|
|
||||||
|
@ -71,6 +72,7 @@ Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platf
|
||||||
raster->width = width;
|
raster->width = width;
|
||||||
raster->height = height;
|
raster->height = height;
|
||||||
raster->depth = depth;
|
raster->depth = depth;
|
||||||
|
raster->stride = 0;
|
||||||
raster->pixels = raster->palette = nil;
|
raster->pixels = raster->palette = nil;
|
||||||
s_plglist.construct(raster);
|
s_plglist.construct(raster);
|
||||||
|
|
||||||
|
@ -371,4 +373,176 @@ copyPal8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, in
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Platform conversion
|
||||||
|
|
||||||
|
static rw::Raster*
|
||||||
|
xbox_to_d3d(rw::Raster *ras)
|
||||||
|
{
|
||||||
|
#ifdef RW_D3D9
|
||||||
|
using namespace rw;
|
||||||
|
|
||||||
|
int dxt = 0;
|
||||||
|
xbox::XboxRaster *xboxras = GETXBOXRASTEREXT(ras);
|
||||||
|
if(xboxras->customFormat){
|
||||||
|
switch(xboxras->format){
|
||||||
|
case xbox::D3DFMT_DXT1: dxt = 1; break;
|
||||||
|
case xbox::D3DFMT_DXT3: dxt = 3; break;
|
||||||
|
case xbox::D3DFMT_DXT5: dxt = 5; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(dxt == 0)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
Raster *newras = Raster::create(ras->width, ras->height, ras->depth,
|
||||||
|
ras->format | Raster::TEXTURE | Raster::DONTALLOCATE);
|
||||||
|
int numLevels = ras->getNumLevels();
|
||||||
|
d3d::allocateDXT(newras, dxt, numLevels, xboxras->hasAlpha);
|
||||||
|
for(int i = 0; i < numLevels; i++){
|
||||||
|
uint8 *srcpx = ras->lock(i, Raster::LOCKREAD);
|
||||||
|
// uint8 *dstpx = newras->lock(i, Raster::LOCKWRITE | Raster::LOCKNOFETCH);
|
||||||
|
d3d::setTexels(newras, srcpx, i);
|
||||||
|
// flipDXT(dxt, dstpx, srcpx, ras->width, ras->height);
|
||||||
|
ras->unlock(i);
|
||||||
|
// newras->unlock(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newras;
|
||||||
|
#else
|
||||||
|
return nil;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static rw::Raster*
|
||||||
|
d3d_to_gl3(rw::Raster *ras)
|
||||||
|
{
|
||||||
|
#ifdef RW_GL3
|
||||||
|
using namespace rw;
|
||||||
|
|
||||||
|
int dxt = 0;
|
||||||
|
d3d::D3dRaster *d3dras = GETD3DRASTEREXT(ras);
|
||||||
|
if(d3dras->customFormat){
|
||||||
|
switch(d3dras->format){
|
||||||
|
case d3d::D3DFMT_DXT1: dxt = 1; break;
|
||||||
|
case d3d::D3DFMT_DXT3: dxt = 3; break;
|
||||||
|
case d3d::D3DFMT_DXT5: dxt = 5; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(dxt == 0)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
Raster *newras = Raster::create(ras->width, ras->height, ras->depth,
|
||||||
|
ras->format | Raster::TEXTURE | Raster::DONTALLOCATE);
|
||||||
|
int numLevels = ras->getNumLevels();
|
||||||
|
gl3::allocateDXT(newras, dxt, numLevels, d3dras->hasAlpha);
|
||||||
|
for(int i = 0; i < numLevels; i++){
|
||||||
|
uint8 *srcpx = ras->lock(i, Raster::LOCKREAD);
|
||||||
|
uint8 *dstpx = newras->lock(i, Raster::LOCKWRITE | Raster::LOCKNOFETCH);
|
||||||
|
flipDXT(dxt, dstpx, srcpx, ras->width, ras->height);
|
||||||
|
ras->unlock(i);
|
||||||
|
newras->unlock(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newras;
|
||||||
|
#else
|
||||||
|
return nil;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static rw::Raster*
|
||||||
|
xbox_to_gl3(rw::Raster *ras)
|
||||||
|
{
|
||||||
|
#ifdef RW_GL3
|
||||||
|
using namespace rw;
|
||||||
|
|
||||||
|
int dxt = 0;
|
||||||
|
xbox::XboxRaster *xboxras = GETXBOXRASTEREXT(ras);
|
||||||
|
if(xboxras->customFormat){
|
||||||
|
switch(xboxras->format){
|
||||||
|
case xbox::D3DFMT_DXT1: dxt = 1; break;
|
||||||
|
case xbox::D3DFMT_DXT3: dxt = 3; break;
|
||||||
|
case xbox::D3DFMT_DXT5: dxt = 5; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(dxt == 0)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
Raster *newras = Raster::create(ras->width, ras->height, ras->depth,
|
||||||
|
ras->format | Raster::TEXTURE | Raster::DONTALLOCATE);
|
||||||
|
int numLevels = ras->getNumLevels();
|
||||||
|
gl3::allocateDXT(newras, dxt, numLevels, xboxras->hasAlpha);
|
||||||
|
for(int i = 0; i < numLevels; i++){
|
||||||
|
uint8 *srcpx = ras->lock(i, Raster::LOCKREAD);
|
||||||
|
uint8 *dstpx = newras->lock(i, Raster::LOCKWRITE | Raster::LOCKNOFETCH);
|
||||||
|
flipDXT(dxt, dstpx, srcpx, ras->width, ras->height);
|
||||||
|
ras->unlock(i);
|
||||||
|
newras->unlock(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newras;
|
||||||
|
#else
|
||||||
|
return nil;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
rw::Raster*
|
||||||
|
Raster::convertTexToCurrentPlatform(rw::Raster *ras)
|
||||||
|
{
|
||||||
|
using namespace rw;
|
||||||
|
|
||||||
|
if(ras->platform == rw::platform)
|
||||||
|
return ras;
|
||||||
|
// compatible platforms
|
||||||
|
if(ras->platform == PLATFORM_D3D8 && rw::platform == PLATFORM_D3D9 ||
|
||||||
|
ras->platform == PLATFORM_D3D9 && rw::platform == PLATFORM_D3D8)
|
||||||
|
return ras;
|
||||||
|
|
||||||
|
// special cased conversion for DXT
|
||||||
|
if((ras->platform == PLATFORM_D3D8 || ras->platform == PLATFORM_D3D9) && rw::platform == PLATFORM_GL3){
|
||||||
|
Raster *newras = d3d_to_gl3(ras);
|
||||||
|
if(newras){
|
||||||
|
ras->destroy();
|
||||||
|
return newras;
|
||||||
|
}
|
||||||
|
}else if(ras->platform == PLATFORM_XBOX && (rw::platform == PLATFORM_D3D9 || rw::platform == PLATFORM_D3D8)){
|
||||||
|
Raster *newras = xbox_to_d3d(ras);
|
||||||
|
if(newras){
|
||||||
|
ras->destroy();
|
||||||
|
return newras;
|
||||||
|
}
|
||||||
|
}else if(ras->platform == PLATFORM_XBOX && rw::platform == PLATFORM_GL3){
|
||||||
|
Raster *newras = xbox_to_gl3(ras);
|
||||||
|
if(newras){
|
||||||
|
ras->destroy();
|
||||||
|
return newras;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall back to going through Image directly
|
||||||
|
int32 width, height, depth, format;
|
||||||
|
Image *img = ras->toImage();
|
||||||
|
// TODO: maybe don't *always* do this?
|
||||||
|
img->unpalettize();
|
||||||
|
Raster::imageFindRasterFormat(img, Raster::TEXTURE, &width, &height, &depth, &format);
|
||||||
|
format |= ras->format & (Raster::MIPMAP | Raster::AUTOMIPMAP);
|
||||||
|
Raster *newras = Raster::create(width, height, depth, format);
|
||||||
|
newras->setFromImage(img);
|
||||||
|
img->destroy();
|
||||||
|
int numLevels = ras->getNumLevels();
|
||||||
|
for(int i = 1; i < numLevels; i++){
|
||||||
|
ras->lock(i, Raster::LOCKREAD);
|
||||||
|
img = ras->toImage();
|
||||||
|
// TODO: maybe don't *always* do this?
|
||||||
|
img->unpalettize();
|
||||||
|
newras->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
|
||||||
|
newras->setFromImage(img);
|
||||||
|
newras->unlock(i);
|
||||||
|
ras->unlock(i);
|
||||||
|
}
|
||||||
|
ras->destroy();
|
||||||
|
ras = newras;
|
||||||
|
return ras;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,6 +268,7 @@ struct Raster
|
||||||
static Raster *getCurrentContext(void);
|
static Raster *getCurrentContext(void);
|
||||||
bool32 renderFast(int32 x, int32 y);
|
bool32 renderFast(int32 x, int32 y);
|
||||||
|
|
||||||
|
static Raster *convertTexToCurrentPlatform(Raster *ras);
|
||||||
#ifndef RWPUBLIC
|
#ifndef RWPUBLIC
|
||||||
static void registerModule(void);
|
static void registerModule(void);
|
||||||
#endif
|
#endif
|
||||||
|
@ -337,9 +338,6 @@ void expandPal4_BE(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, i
|
||||||
void compressPal4_BE(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
|
void compressPal4_BE(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
|
||||||
void copyPal8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
|
void copyPal8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
|
||||||
|
|
||||||
void flipDXT1(uint8 *dst, uint8 *src, uint32 width, uint32 height);
|
|
||||||
void flipDXT3(uint8 *dst, uint8 *src, uint32 width, uint32 height);
|
|
||||||
void flipDXT5(uint8 *dst, uint8 *src, uint32 width, uint32 height);
|
|
||||||
void flipDXT(int32 type, uint8 *dst, uint8 *src, uint32 width, uint32 height);
|
void flipDXT(int32 type, uint8 *dst, uint8 *src, uint32 width, uint32 height);
|
||||||
|
|
||||||
|
|
||||||
|
@ -352,9 +350,9 @@ struct Texture
|
||||||
enum FilterMode {
|
enum FilterMode {
|
||||||
NEAREST = 1,
|
NEAREST = 1,
|
||||||
LINEAR,
|
LINEAR,
|
||||||
MIPNEAREST,
|
MIPNEAREST, // one mipmap
|
||||||
MIPLINEAR,
|
MIPLINEAR,
|
||||||
LINEARMIPNEAREST,
|
LINEARMIPNEAREST, // mipmap interpolated
|
||||||
LINEARMIPLINEAR
|
LINEARMIPLINEAR
|
||||||
};
|
};
|
||||||
enum Addressing {
|
enum Addressing {
|
||||||
|
|
|
@ -10,6 +10,7 @@ typedef Stream *(*StreamRead)(Stream *stream, int32 length, void *object, int32
|
||||||
typedef Stream *(*StreamWrite)(Stream *stream, int32 length, void *object, int32 offset, int32 size);
|
typedef Stream *(*StreamWrite)(Stream *stream, int32 length, void *object, int32 offset, int32 size);
|
||||||
typedef int32 (*StreamGetSize)(void *object, int32 offset, int32 size);
|
typedef int32 (*StreamGetSize)(void *object, int32 offset, int32 size);
|
||||||
typedef void (*RightsCallback)(void *object, int32 offset, int32 size, uint32 data);
|
typedef void (*RightsCallback)(void *object, int32 offset, int32 size, uint32 data);
|
||||||
|
typedef void (*AlwaysCallback)(void *object, int32 offset, int32 size);
|
||||||
|
|
||||||
struct PluginList
|
struct PluginList
|
||||||
{
|
{
|
||||||
|
@ -38,6 +39,7 @@ struct PluginList
|
||||||
Constructor, Destructor, CopyConstructor);
|
Constructor, Destructor, CopyConstructor);
|
||||||
int32 registerStream(uint32 id, StreamRead, StreamWrite, StreamGetSize);
|
int32 registerStream(uint32 id, StreamRead, StreamWrite, StreamGetSize);
|
||||||
int32 setStreamRightsCallback(uint32 id, RightsCallback cb);
|
int32 setStreamRightsCallback(uint32 id, RightsCallback cb);
|
||||||
|
int32 setStreamAlwaysCallback(uint32 id, AlwaysCallback cb);
|
||||||
int32 getPluginOffset(uint32 id);
|
int32 getPluginOffset(uint32 id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,6 +55,7 @@ struct Plugin
|
||||||
StreamWrite write;
|
StreamWrite write;
|
||||||
StreamGetSize getSize;
|
StreamGetSize getSize;
|
||||||
RightsCallback rightsCallback;
|
RightsCallback rightsCallback;
|
||||||
|
AlwaysCallback alwaysCallback;
|
||||||
PluginList *parentList;
|
PluginList *parentList;
|
||||||
LLLink inParentList;
|
LLLink inParentList;
|
||||||
LLLink inGlobalList;
|
LLLink inGlobalList;
|
||||||
|
@ -71,6 +74,9 @@ struct Plugin
|
||||||
static int32 setStreamRightsCallback(uint32 id, RightsCallback cb){ \
|
static int32 setStreamRightsCallback(uint32 id, RightsCallback cb){ \
|
||||||
return s_plglist.setStreamRightsCallback(id, cb); \
|
return s_plglist.setStreamRightsCallback(id, cb); \
|
||||||
} \
|
} \
|
||||||
|
static int32 setStreamAlwaysCallback(uint32 id, AlwaysCallback cb){ \
|
||||||
|
return s_plglist.setStreamAlwaysCallback(id, cb); \
|
||||||
|
} \
|
||||||
static int32 getPluginOffset(uint32 id){ \
|
static int32 getPluginOffset(uint32 id){ \
|
||||||
return s_plglist.getPluginOffset(id); \
|
return s_plglist.getPluginOffset(id); \
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,6 +218,7 @@ struct Skin
|
||||||
|
|
||||||
uint8 *data; // only used by delete
|
uint8 *data; // only used by delete
|
||||||
void *platformData; // a place to store platform specific stuff
|
void *platformData; // a place to store platform specific stuff
|
||||||
|
bool32 legacyType; // old skin attached to atomic, needed for always CB
|
||||||
|
|
||||||
void init(int32 numBones, int32 numUsedBones, int32 numVertices);
|
void init(int32 numBones, int32 numUsedBones, int32 numVertices);
|
||||||
void findNumWeights(int32 numVertices);
|
void findNumWeights(int32 numVertices);
|
||||||
|
|
14
src/skin.cpp
14
src/skin.cpp
|
@ -265,6 +265,7 @@ readSkinLegacy(Stream *stream, int32 len, void *object, int32, int32)
|
||||||
Skin *skin = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN);
|
Skin *skin = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN);
|
||||||
*PLUGINOFFSET(Skin*, geometry, skinGlobals.geoOffset) = skin;
|
*PLUGINOFFSET(Skin*, geometry, skinGlobals.geoOffset) = skin;
|
||||||
skin->init(numBones, numBones, numVertices);
|
skin->init(numBones, numBones, numVertices);
|
||||||
|
skin->legacyType = 1;
|
||||||
skin->numWeights = 4;
|
skin->numWeights = 4;
|
||||||
|
|
||||||
stream->read8(skin->indices, numVertices*4);
|
stream->read8(skin->indices, numVertices*4);
|
||||||
|
@ -307,6 +308,17 @@ skinRights(void *object, int32, int32, uint32)
|
||||||
Skin::setPipeline((Atomic*)object, 1);
|
Skin::setPipeline((Atomic*)object, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
skinAlways(void *object, int32, int32)
|
||||||
|
{
|
||||||
|
Atomic *atomic = (Atomic*)object;
|
||||||
|
Geometry *geo = atomic->geometry;
|
||||||
|
if(geo == nil) return;
|
||||||
|
Skin *skin = Skin::get(geo);
|
||||||
|
if(skin == nil) return;
|
||||||
|
Skin::setPipeline((Atomic*)object, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void*
|
static void*
|
||||||
createSkinAtm(void *object, int32 offset, int32)
|
createSkinAtm(void *object, int32 offset, int32)
|
||||||
{
|
{
|
||||||
|
@ -373,6 +385,7 @@ registerSkinPlugin(void)
|
||||||
skinGlobals.atomicOffset = o;
|
skinGlobals.atomicOffset = o;
|
||||||
Atomic::registerPluginStream(ID_SKIN, readSkinLegacy, nil, nil);
|
Atomic::registerPluginStream(ID_SKIN, readSkinLegacy, nil, nil);
|
||||||
Atomic::setStreamRightsCallback(ID_SKIN, skinRights);
|
Atomic::setStreamRightsCallback(ID_SKIN, skinRights);
|
||||||
|
Atomic::setStreamAlwaysCallback(ID_SKIN, skinAlways);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -417,6 +430,7 @@ Skin::init(int32 numBones, int32 numUsedBones, int32 numVertices)
|
||||||
this->rle = nil;
|
this->rle = nil;
|
||||||
|
|
||||||
this->platformData = nil;
|
this->platformData = nil;
|
||||||
|
this->legacyType = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -243,7 +243,7 @@ InitRW(void)
|
||||||
|
|
||||||
rw::d3d::isP8supported = false;
|
rw::d3d::isP8supported = false;
|
||||||
|
|
||||||
postfxtest();
|
// postfxtest();
|
||||||
|
|
||||||
initFont();
|
initFont();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue