diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index 0344585..a5e65a6 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -527,7 +527,9 @@ rasterSetFormat(Raster *raster) 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* @@ -684,8 +686,11 @@ imageFindRasterFormat(Image *img, int32 type, assert((type&0xF) == Raster::TEXTURE); - for(width = 1; width < img->width; width <<= 1); - for(height = 1; height < img->height; height <<= 1); +// for(width = 1; width < img->width; width <<= 1); +// for(height = 1; height < img->height; height <<= 1); + // Perhaps non-power-of-2 textures are acceptable? + width = img->width; + height = img->height; depth = img->depth; @@ -734,6 +739,8 @@ rasterFromImage(Raster *raster, Image *image) if((raster->type&0xF) != Raster::TEXTURE) return 0; + void (*conv)(uint8 *out, uint8 *in) = nil; + // Unpalettize image if necessary but don't change original Image *truecolimg = nil; if(image->depth <= 8 && !isP8supported){ @@ -748,22 +755,39 @@ rasterFromImage(Raster *raster, Image *image) D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); switch(image->depth){ case 32: - if(raster->format != Raster::C8888 && - raster->format != Raster::C888) + if(raster->format == Raster::C8888) + conv = conv_BGRA8888_from_RGBA8888; + else if(raster->format == Raster::C888) + conv = conv_BGR888_from_RGB888; + else goto err; break; case 24: - if(raster->format != Raster::C888) goto err; + if(raster->format == Raster::C8888) + conv = conv_BGRA8888_from_RGB888; + else if(raster->format == Raster::C888) + conv = conv_BGR888_from_RGB888; + else + goto err; break; case 16: - if(raster->format != Raster::C1555) goto err; + if(raster->format == Raster::C1555) + conv = conv_ARGB1555_from_ARGB1555; + else + goto err; break; case 8: - if(raster->format != (Raster::PAL8 | Raster::C8888)) goto err; + if(raster->format == (Raster::PAL8 | Raster::C8888)) + conv = conv_8_from_8; + else + goto err; break; case 4: - if(raster->format != (Raster::PAL4 | Raster::C8888)) goto err; - break; + if(raster->format == (Raster::PAL4 | Raster::C8888) || + raster->format == (Raster::PAL8 | Raster::C8888)) + conv = conv_8_from_8; + else + goto err; default: err: RWERROR((ERR_INVRASTER)); @@ -780,48 +804,30 @@ rasterFromImage(Raster *raster, Image *image) in = image->palette; out = (uint8*)natras->palette; for(int32 i = 0; i < pallength; i++){ - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; + conv_RGBA8888_from_RGBA8888(out, in); in += 4; out += 4; } } - int32 inc = image->bpp; - in = image->pixels; - out = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH); - if(pallength) - memcpy(out, in, raster->width*raster->height); - else - // TODO: stride - for(int32 y = 0; y < image->height; y++) - for(int32 x = 0; x < image->width; x++) - switch(raster->format & 0xF00){ - case Raster::C8888: - out[0] = in[2]; - out[1] = in[1]; - out[2] = in[0]; - out[3] = in[3]; - in += inc; - out += 4; - break; - case Raster::C888: - out[0] = in[2]; - out[1] = in[1]; - out[2] = in[0]; - out[3] = 0xFF; - in += inc; - out += 4; - break; - case Raster::C1555: - out[0] = in[0]; - out[1] = in[1]; - in += inc; - out += 2; - break; - } + uint8 *pixels = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH); + assert(pixels); + uint8 *imgpixels = image->pixels; + + int x, y; + assert(image->width == raster->width); + assert(image->height == raster->height); + for(y = 0; y < image->height; y++){ + uint8 *imgrow = imgpixels; + uint8 *rasrow = pixels; + for(x = 0; x < image->width; x++){ + conv(rasrow, imgrow); + imgrow += image->bpp; + rasrow += natras->bpp; + } + imgpixels += image->stride; + pixels += raster->stride; + } raster->unlock(0); if(truecolimg) @@ -860,18 +866,24 @@ rasterToImage(Raster *raster) raster->unlock(0); return image; } + + void (*conv)(uint8 *out, uint8 *in) = nil; switch(raster->format & 0xF00){ case Raster::C1555: depth = 16; + conv = conv_ARGB1555_from_ARGB1555; break; case Raster::C8888: depth = 32; + conv = conv_RGBA8888_from_BGRA8888; break; case Raster::C888: depth = 24; + conv = conv_RGB888_from_BGR888; break; case Raster::C555: depth = 16; + conv = conv_ARGB1555_from_RGB555; break; default: @@ -898,52 +910,28 @@ rasterToImage(Raster *raster) out = image->palette; in = (uint8*)natras->palette; for(int32 i = 0; i < pallength; i++){ - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; + conv_RGBA8888_from_RGBA8888(out, in); in += 4; out += 4; } } - uint8 *dst = image->pixels; - in = raster->lock(0, Raster::LOCKREAD); - if(pallength) - memcpy(dst, in, raster->width*raster->height); - else{ - for(int32 y = 0; y < image->height; y++){ - out = dst; - for(int32 x = 0; x < image->width; x++){ - switch(raster->format & 0xF00){ - case Raster::C8888: - out[0] = in[2]; - out[1] = in[1]; - out[2] = in[0]; - out[3] = in[3]; - in += 4; - break; - case Raster::C888: - out[0] = in[2]; - out[1] = in[1]; - out[2] = in[0]; - in += 4; - break; - case Raster::C1555: - out[0] = in[0]; - out[1] = in[1]; - in += 2; - break; - case Raster::C555: - out[0] = in[0]; - out[1] = in[1] | 0x80; - in += 2; - break; - } - out += image->bpp; - } - dst += image->stride; + uint8 *imgpixels = image->pixels; + uint8 *pixels = raster->lock(0, Raster::LOCKREAD); + + int x, y; + assert(image->width == raster->width); + assert(image->height == raster->height); + for(y = 0; y < image->height; y++){ + uint8 *imgrow = imgpixels; + uint8 *rasrow = pixels; + for(x = 0; x < image->width; x++){ + conv(imgrow, rasrow); + imgrow += image->bpp; + rasrow += natras->bpp; } + imgpixels += image->stride; + pixels += raster->stride; } raster->unlock(0); diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h index 178a644..00cab50 100644 --- a/src/d3d/rwd3d.h +++ b/src/d3d/rwd3d.h @@ -162,6 +162,7 @@ struct D3dRaster void *texture; void *palette; uint32 format; + uint32 bpp; // bytes per pixel bool32 hasAlpha; bool32 customFormat; }; diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index 85d12e5..f5800bf 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -315,8 +315,11 @@ imageFindRasterFormat(Image *img, int32 type, assert((type&0xF) == Raster::TEXTURE); - for(width = 1; width < img->width; width <<= 1); - for(height = 1; height < img->height; height <<= 1); +// for(width = 1; width < img->width; width <<= 1); +// for(height = 1; height < img->height; height <<= 1); + // Perhaps non-power-of-2 textures are acceptable? + width = img->width; + height = img->height; depth = img->depth; @@ -440,8 +443,11 @@ rasterFromImage(Raster *raster, Image *image) imgpixels -= image->stride; pixels += raster->stride; } - raster->unlock(0); + + if(truecolimg) + truecolimg->destroy(); + return 1; } diff --git a/src/raster.cpp b/src/raster.cpp index eb3ac19..183ec6b 100644 --- a/src/raster.cpp +++ b/src/raster.cpp @@ -230,6 +230,15 @@ conv_RGBA8888_from_RGBA8888(uint8 *out, uint8 *in) out[3] = in[3]; } +void +conv_BGRA8888_from_RGBA8888(uint8 *out, uint8 *in) +{ + out[2] = in[0]; + out[1] = in[1]; + out[0] = in[2]; + out[3] = in[3]; +} + void conv_RGBA8888_from_RGB888(uint8 *out, uint8 *in) { @@ -239,6 +248,15 @@ conv_RGBA8888_from_RGB888(uint8 *out, uint8 *in) out[3] = 0xFF; } +void +conv_BGRA8888_from_RGB888(uint8 *out, uint8 *in) +{ + out[2] = in[0]; + out[1] = in[1]; + out[0] = in[2]; + out[3] = 0xFF; +} + void conv_RGB888_from_RGB888(uint8 *out, uint8 *in) { @@ -247,6 +265,28 @@ conv_RGB888_from_RGB888(uint8 *out, uint8 *in) out[2] = in[2]; } +void +conv_BGR888_from_RGB888(uint8 *out, uint8 *in) +{ + out[2] = in[0]; + out[1] = in[1]; + out[0] = in[2]; +} + +void +conv_ARGB1555_from_ARGB1555(uint8 *out, uint8 *in) +{ + out[0] = in[0]; + out[1] = in[1]; +} + +void +conv_ARGB1555_from_RGB555(uint8 *out, uint8 *in) +{ + out[0] = in[0]; + out[1] = in[1] | 0x80; +} + void conv_RGBA5551_from_ARGB1555(uint8 *out, uint8 *in) { diff --git a/src/rwbase.h b/src/rwbase.h index d9cec4b..2c67ab8 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -74,6 +74,16 @@ typedef uint32 uint; #define nelem(A) (sizeof(A) / sizeof A[0]) +#ifdef __GNUC__ +#define RWALIGN(n) __attribute__ ((aligned (n))) +#else +#ifdef _MSC_VER +#define RWALIGN(n) __declspec(align(n)) +#else +#define RWALIGN(n) // unknown compiler...ignore +#endif +#endif + // Lists struct LLLink @@ -286,7 +296,7 @@ inline V3d rotate(const V3d &v, const Quat &q) { return mult(mult(q, makeQuat(0. Quat lerp(const Quat &q, const Quat &p, float32 r); Quat slerp(const Quat &q, const Quat &p, float32 a); -struct RawMatrix +struct RWALIGN(16) RawMatrix { V3d right; float32 rightw; @@ -302,7 +312,7 @@ struct RawMatrix static void setIdentity(RawMatrix *dst); }; -struct Matrix +struct RWALIGN(16) Matrix { enum Type { TYPENORMAL = 1, diff --git a/src/rwobjects.h b/src/rwobjects.h index 7476054..fd0a09f 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -306,11 +306,20 @@ struct Raster }; void conv_RGBA8888_from_RGBA8888(uint8 *out, uint8 *in); +void conv_BGRA8888_from_RGBA8888(uint8 *out, uint8 *in); void conv_RGBA8888_from_RGB888(uint8 *out, uint8 *in); +void conv_BGRA8888_from_RGB888(uint8 *out, uint8 *in); void conv_RGB888_from_RGB888(uint8 *out, uint8 *in); +void conv_BGR888_from_RGB888(uint8 *out, uint8 *in); +void conv_ARGB1555_from_ARGB1555(uint8 *out, uint8 *in); +void conv_ARGB1555_from_RGB555(uint8 *out, uint8 *in); void conv_RGBA5551_from_ARGB1555(uint8 *out, uint8 *in); void conv_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in); void conv_ABGR1555_from_ARGB1555(uint8 *out, uint8 *in); +inline void conv_8_from_8(uint8 *out, uint8 *in) { *out = *in; } +// some swaps are the same, so these are just more descriptive names +inline void conv_RGBA8888_from_BGRA8888(uint8 *out, uint8 *in) { conv_BGRA8888_from_RGBA8888(out, in); } +inline void conv_RGB888_from_BGR888(uint8 *out, uint8 *in) { conv_BGR888_from_RGB888(out, in); } inline void conv_ARGB1555_from_ABGR1555(uint8 *out, uint8 *in) { conv_ABGR1555_from_ARGB1555(out, in); } void expandPal4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);