From 3e2080ad566ded9c44ecc3e0bbccc020dbb8f116 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 7 Nov 2020 11:11:36 +0100 Subject: [PATCH] DXT support for gl3. txd format changed!! --- src/d3d/d3d.cpp | 127 ++++--------------------------- src/d3d/d3d8.cpp | 6 +- src/d3d/d3d9.cpp | 6 +- src/d3d/d3d9matfx.cpp | 2 +- src/d3d/d3ddevice.cpp | 18 ++--- src/d3d/rwd3d.h | 100 +++++++++++++++++++++++++ src/gl/gl3raster.cpp | 168 ++++++++++++++++++++++++++++++++++-------- src/gl/rwgl3.h | 7 +- src/image.cpp | 134 +++++++++++++++++++++++++++++++++ src/rwobjects.h | 4 + 10 files changed, 411 insertions(+), 161 deletions(-) diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index 1545934..453cb36 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -20,105 +20,6 @@ namespace d3d { bool32 isP8supported = 1; -#ifndef RW_D3D9 -#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ - ((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | \ - ((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 )) -enum { - D3DFMT_UNKNOWN = 0, - - D3DFMT_R8G8B8 = 20, - D3DFMT_A8R8G8B8 = 21, - D3DFMT_X8R8G8B8 = 22, - D3DFMT_R5G6B5 = 23, - D3DFMT_X1R5G5B5 = 24, - D3DFMT_A1R5G5B5 = 25, - D3DFMT_A4R4G4B4 = 26, - D3DFMT_R3G3B2 = 27, - D3DFMT_A8 = 28, - D3DFMT_A8R3G3B2 = 29, - D3DFMT_X4R4G4B4 = 30, - D3DFMT_A2B10G10R10 = 31, - D3DFMT_A8B8G8R8 = 32, - D3DFMT_X8B8G8R8 = 33, - D3DFMT_G16R16 = 34, - D3DFMT_A2R10G10B10 = 35, - D3DFMT_A16B16G16R16 = 36, - - D3DFMT_A8P8 = 40, - D3DFMT_P8 = 41, - - D3DFMT_L8 = 50, - D3DFMT_A8L8 = 51, - D3DFMT_A4L4 = 52, - - D3DFMT_V8U8 = 60, - D3DFMT_L6V5U5 = 61, - D3DFMT_X8L8V8U8 = 62, - D3DFMT_Q8W8V8U8 = 63, - D3DFMT_V16U16 = 64, - D3DFMT_A2W10V10U10 = 67, - - D3DFMT_UYVY = MAKEFOURCC('U', 'Y', 'V', 'Y'), - D3DFMT_R8G8_B8G8 = MAKEFOURCC('R', 'G', 'B', 'G'), - D3DFMT_YUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'), - D3DFMT_G8R8_G8B8 = MAKEFOURCC('G', 'R', 'G', 'B'), - D3DFMT_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'), - D3DFMT_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'), - D3DFMT_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'), - D3DFMT_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'), - D3DFMT_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'), - - D3DFMT_D16_LOCKABLE = 70, - D3DFMT_D32 = 71, - D3DFMT_D15S1 = 73, - D3DFMT_D24S8 = 75, - D3DFMT_D24X8 = 77, - D3DFMT_D24X4S4 = 79, - D3DFMT_D16 = 80, - - D3DFMT_D32F_LOCKABLE = 82, - D3DFMT_D24FS8 = 83, - - // d3d9ex only - /* Z-Stencil formats valid for CPU access */ - D3DFMT_D32_LOCKABLE = 84, - D3DFMT_S8_LOCKABLE = 85, - - D3DFMT_L16 = 81, - - D3DFMT_VERTEXDATA =100, - D3DFMT_INDEX16 =101, - D3DFMT_INDEX32 =102, - - D3DFMT_Q16W16V16U16 =110, - - D3DFMT_MULTI2_ARGB8 = MAKEFOURCC('M','E','T','1'), - - // Floating point surface formats - - // s10e5 formats (16-bits per channel) - D3DFMT_R16F = 111, - D3DFMT_G16R16F = 112, - D3DFMT_A16B16G16R16F = 113, - - // IEEE s23e8 formats (32-bits per channel) - D3DFMT_R32F = 114, - D3DFMT_G32R32F = 115, - D3DFMT_A32B32G32R32F = 116, - - D3DFMT_CxV8U8 = 117, - - // d3d9ex only - // Monochrome 1 bit per pixel format - D3DFMT_A1 = 118, - // 2.8 biased fixed point - D3DFMT_A2B10G10R10_XR_BIAS = 119, - // Binary format indicating that the data has no inherent type - D3DFMT_BINARYBUFFER = 199 -}; -#endif - // stolen from d3d8to9 static uint32 calculateTextureSize(uint32 width, uint32 height, uint32 depth, uint32 format) @@ -492,7 +393,7 @@ rasterSetFormat(Raster *raster) } - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); if(raster->format & (Raster::PAL4 | Raster::PAL8)){ // TODO: do we even allow PAL4? natras->format = D3DFMT_P8; @@ -516,7 +417,7 @@ static Raster* rasterCreateTexture(Raster *raster) { int32 levels; - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); if(natras->format == D3DFMT_P8) natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER); @@ -543,7 +444,7 @@ rasterCreateCameraTexture(Raster *raster) } int32 levels; - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); levels = Raster::calculateNumLevels(raster->width, raster->height); IDirect3DTexture9 *tex; @@ -565,7 +466,7 @@ rasterCreateCameraTexture(Raster *raster) static Raster* rasterCreateCamera(Raster *raster) { - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); raster->originalWidth = raster->width; raster->originalHeight = raster->height; raster->originalStride = raster->stride = 0; @@ -581,7 +482,7 @@ rasterCreateCamera(Raster *raster) static Raster* rasterCreateZbuffer(Raster *raster) { - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); raster->originalWidth = raster->width; raster->originalHeight = raster->height; raster->originalStride = raster->stride = 0; @@ -617,7 +518,7 @@ rasterCreateZbuffer(Raster *raster) Raster* rasterCreate(Raster *raster) { - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); rasterSetFormat(raster); @@ -649,7 +550,7 @@ rasterCreate(Raster *raster) uint8* rasterLock(Raster *raster, int32 level, int32 lockMode) { - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); // check if already locked if(raster->privateFlags & (Raster::PRIVATELOCK_READ|Raster::PRIVATELOCK_WRITE)) @@ -697,7 +598,7 @@ void rasterUnlock(Raster *raster, int32 level) { #if RW_D3D9 - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); IDirect3DSurface9 *surf = (IDirect3DSurface9*)natras->lockedSurf; surf->UnlockRect(); surf->Release(); @@ -714,7 +615,7 @@ rasterUnlock(Raster *raster, int32 level) int32 rasterNumLevels(Raster *raster) { - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); #ifdef RW_D3D9 IDirect3DTexture9 *tex = (IDirect3DTexture9*)natras->texture; return tex->GetLevelCount(); @@ -799,7 +700,7 @@ rasterFromImage(Raster *raster, Image *image) image = truecolimg; } - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); switch(image->depth){ case 32: if(raster->format == Raster::C8888) @@ -888,7 +789,7 @@ rasterToImage(Raster *raster) { int32 depth; Image *image; - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); if(natras->customFormat){ image = Image::create(raster->width, raster->height, 32); image->allocate(); @@ -990,7 +891,7 @@ rasterToImage(Raster *raster) int32 getLevelSize(Raster *raster, int32 level) { - D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *ras = GETD3DRASTEREXT(raster); #ifdef RW_D3D9 IDirect3DTexture9 *tex = (IDirect3DTexture9*)ras->texture; D3DSURFACE_DESC desc; @@ -1012,7 +913,7 @@ allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha) 0x34545844, // DXT4 0x35545844, // DXT5 }; - D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *ras = GETD3DRASTEREXT(raster); ras->format = dxtMap[dxt-1]; ras->hasAlpha = hasAlpha; ras->texture = createTexture(raster->width, raster->height, @@ -1024,7 +925,7 @@ allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha) void setPalette(Raster *raster, void *palette, int32 size) { - D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *ras = GETD3DRASTEREXT(raster); memcpy(ras->palette, palette, 4*size); } diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index 8932620..d360eb5 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -546,12 +546,12 @@ readNativeTexture(Stream *stream) D3dRaster *ras; if(compression){ raster = Raster::create(width, height, depth, format | type | 0x80, PLATFORM_D3D8); - ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + ras = GETD3DRASTEREXT(raster); allocateDXT(raster, compression, numLevels, hasAlpha); ras->customFormat = 1; }else{ raster = Raster::create(width, height, depth, format | type, PLATFORM_D3D8); - ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + ras = GETD3DRASTEREXT(raster); } tex->raster = raster; @@ -588,7 +588,7 @@ writeNativeTexture(Texture *tex, Stream *stream) // Raster Raster *raster = tex->raster; - D3dRaster *ras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *ras = GETD3DRASTEREXT(raster); int32 numLevels = raster->getNumLevels(); stream->writeI32(raster->format); stream->writeI32(ras->hasAlpha); diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp index 3abe111..7f7bc35 100644 --- a/src/d3d/d3d9.cpp +++ b/src/d3d/d3d9.cpp @@ -746,7 +746,7 @@ readNativeTexture(Stream *stream) assert((flags & 2) == 0 && "Can't have cube maps yet"); raster = Raster::create(width, height, depth, format | type | Raster::DONTALLOCATE, PLATFORM_D3D9); assert(raster); - ext = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + ext = GETD3DRASTEREXT(raster); ext->format = d3dformat; ext->hasAlpha = flags & 1; ext->texture = createTexture(raster->width, raster->height, @@ -760,7 +760,7 @@ readNativeTexture(Stream *stream) }else{ raster = Raster::create(width, height, depth, format | type, PLATFORM_D3D9); assert(raster); - ext = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + ext = GETD3DRASTEREXT(raster); } tex->raster = raster; @@ -799,7 +799,7 @@ writeNativeTexture(Texture *tex, Stream *stream) // Raster Raster *raster = tex->raster; - D3dRaster *ext = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *ext = GETD3DRASTEREXT(raster); int32 numLevels = raster->getNumLevels(); stream->writeI32(raster->format); stream->writeU32(ext->format); diff --git a/src/d3d/d3d9matfx.cpp b/src/d3d/d3d9matfx.cpp index e85540d..70009eb 100644 --- a/src/d3d/d3d9matfx.cpp +++ b/src/d3d/d3d9matfx.cpp @@ -130,7 +130,7 @@ matfxRender_EnvMap(InstanceDataHeader *header, InstanceData *inst, int32 lightBi else setVertexShader(matfx_env_all_VS); - bool32 texAlpha = PLUGINOFFSET(D3dRaster, env->tex->raster, nativeRasterOffset)->hasAlpha; + bool32 texAlpha = GETD3DRASTEREXT(env->tex->raster)->hasAlpha; if(inst->material->texture){ d3d::setTexture(0, m->texture); diff --git a/src/d3d/d3ddevice.cpp b/src/d3d/d3ddevice.cpp index 95ab256..17b1e22 100644 --- a/src/d3d/d3ddevice.cpp +++ b/src/d3d/d3ddevice.cpp @@ -298,7 +298,7 @@ restoreD3d9Device(void) for(i = 0; i < MAXNUMSTAGES; i++){ Raster *raster = rwStateCache.texstage[i].raster; if(raster){ - D3dRaster *d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *d3draster = GETD3DRASTEREXT(raster); d3ddevice->SetTexture(i, (IDirect3DTexture9*)d3draster->texture); }else d3ddevice->SetTexture(i, nil); @@ -342,7 +342,7 @@ evictD3D9Raster(Raster *raster) { int i; // Make sure we're not still referencing this raster - D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(raster); switch(raster->type){ case Raster::CAMERATEXTURE: for(i = 0; i < MAXNUMRENDERTARGETS; i++) @@ -416,7 +416,7 @@ setRasterStage(uint32 stage, Raster *raster) if(raster){ assert(raster->platform == PLATFORM_D3D8 || raster->platform == PLATFORM_D3D9); - d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + d3draster = GETD3DRASTEREXT(raster); d3ddevice->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture); alpha = d3draster->hasAlpha; }else{ @@ -807,7 +807,7 @@ setRenderSurfaces(Camera *cam) Raster *fbuf = cam->frameBuffer; assert(fbuf); { - D3dRaster *natras = PLUGINOFFSET(D3dRaster, fbuf, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(fbuf); assert(fbuf->type == Raster::CAMERA || fbuf->type == Raster::CAMERATEXTURE); if(natras->texture == nil) setRenderTarget(0, d3d9Globals.defaultRenderTarget); @@ -822,7 +822,7 @@ setRenderSurfaces(Camera *cam) Raster *zbuf = cam->zBuffer; if(zbuf){ - D3dRaster *natras = PLUGINOFFSET(D3dRaster, zbuf, nativeRasterOffset); + D3dRaster *natras = GETD3DRASTEREXT(zbuf); assert(zbuf->type == Raster::ZBUFFER); setDepthSurface(natras->texture); }else @@ -962,7 +962,7 @@ releaseVidmemRasters(void) D3dRaster *natras; for(vmr = vidmemRasters; vmr; vmr = vmr->next){ raster = vmr->raster; - natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + natras = GETD3DRASTEREXT(raster); switch(raster->type){ case Raster::CAMERATEXTURE: destroyTexture(natras->texture); @@ -988,7 +988,7 @@ recreateVidmemRasters(void) D3dRaster *natras; for(vmr = vidmemRasters; vmr; vmr = vmr->next){ raster = vmr->raster; - natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + natras = GETD3DRASTEREXT(raster); switch(raster->type){ case Raster::CAMERATEXTURE: { int32 levels = Raster::calculateNumLevels(raster->width, raster->height); @@ -1230,8 +1230,8 @@ rasterRenderFast(Raster *raster, int32 x, int32 y) Raster *src = raster; Raster *dst = Raster::getCurrentContext(); - D3dRaster *natdst = PLUGINOFFSET(D3dRaster, dst, nativeRasterOffset); - D3dRaster *natsrc = PLUGINOFFSET(D3dRaster, src, nativeRasterOffset); + D3dRaster *natdst = GETD3DRASTEREXT(dst); + D3dRaster *natsrc = GETD3DRASTEREXT(src); switch(dst->type){ case Raster::CAMERATEXTURE: diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h index 94e618a..523fe82 100644 --- a/src/d3d/rwd3d.h +++ b/src/d3d/rwd3d.h @@ -89,6 +89,105 @@ struct Im2DVertex }; #else +#ifndef MAKEFOURCC +#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | \ + ((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 )) +#endif +enum { + D3DFMT_UNKNOWN = 0, + + D3DFMT_R8G8B8 = 20, + D3DFMT_A8R8G8B8 = 21, + D3DFMT_X8R8G8B8 = 22, + D3DFMT_R5G6B5 = 23, + D3DFMT_X1R5G5B5 = 24, + D3DFMT_A1R5G5B5 = 25, + D3DFMT_A4R4G4B4 = 26, + D3DFMT_R3G3B2 = 27, + D3DFMT_A8 = 28, + D3DFMT_A8R3G3B2 = 29, + D3DFMT_X4R4G4B4 = 30, + D3DFMT_A2B10G10R10 = 31, + D3DFMT_A8B8G8R8 = 32, + D3DFMT_X8B8G8R8 = 33, + D3DFMT_G16R16 = 34, + D3DFMT_A2R10G10B10 = 35, + D3DFMT_A16B16G16R16 = 36, + + D3DFMT_A8P8 = 40, + D3DFMT_P8 = 41, + + D3DFMT_L8 = 50, + D3DFMT_A8L8 = 51, + D3DFMT_A4L4 = 52, + + D3DFMT_V8U8 = 60, + D3DFMT_L6V5U5 = 61, + D3DFMT_X8L8V8U8 = 62, + D3DFMT_Q8W8V8U8 = 63, + D3DFMT_V16U16 = 64, + D3DFMT_A2W10V10U10 = 67, + + D3DFMT_UYVY = MAKEFOURCC('U', 'Y', 'V', 'Y'), + D3DFMT_R8G8_B8G8 = MAKEFOURCC('R', 'G', 'B', 'G'), + D3DFMT_YUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'), + D3DFMT_G8R8_G8B8 = MAKEFOURCC('G', 'R', 'G', 'B'), + D3DFMT_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'), + D3DFMT_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'), + D3DFMT_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'), + D3DFMT_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'), + D3DFMT_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'), + + D3DFMT_D16_LOCKABLE = 70, + D3DFMT_D32 = 71, + D3DFMT_D15S1 = 73, + D3DFMT_D24S8 = 75, + D3DFMT_D24X8 = 77, + D3DFMT_D24X4S4 = 79, + D3DFMT_D16 = 80, + + D3DFMT_D32F_LOCKABLE = 82, + D3DFMT_D24FS8 = 83, + + // d3d9ex only + /* Z-Stencil formats valid for CPU access */ + D3DFMT_D32_LOCKABLE = 84, + D3DFMT_S8_LOCKABLE = 85, + + D3DFMT_L16 = 81, + + D3DFMT_VERTEXDATA =100, + D3DFMT_INDEX16 =101, + D3DFMT_INDEX32 =102, + + D3DFMT_Q16W16V16U16 =110, + + D3DFMT_MULTI2_ARGB8 = MAKEFOURCC('M','E','T','1'), + + // Floating point surface formats + + // s10e5 formats (16-bits per channel) + D3DFMT_R16F = 111, + D3DFMT_G16R16F = 112, + D3DFMT_A16B16G16R16F = 113, + + // IEEE s23e8 formats (32-bits per channel) + D3DFMT_R32F = 114, + D3DFMT_G32R32F = 115, + D3DFMT_A32B32G32R32F = 116, + + D3DFMT_CxV8U8 = 117, + + // d3d9ex only + // Monochrome 1 bit per pixel format + D3DFMT_A1 = 118, + // 2.8 biased fixed point + D3DFMT_A2B10G10R10_XR_BIAS = 119, + // Binary format indicating that the data has no inherent type + D3DFMT_BINARYBUFFER = 199 +}; + enum { D3DLOCK_NOSYSLOCK = 0, // ignored D3DPOOL_MANAGED = 0, // ignored @@ -175,6 +274,7 @@ void setTexels(Raster *raster, void *texels, int32 level); extern int32 nativeRasterOffset; void registerNativeRaster(void); +#define GETD3DRASTEREXT(raster) PLUGINOFFSET(rw::d3d::D3dRaster, raster, rw::d3d::nativeRasterOffset) // Rendering diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index d684042..6e8cecc 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -26,7 +26,7 @@ int32 nativeRasterOffset; static Raster* rasterCreateTexture(Raster *raster) { - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + Gl3Raster *natras = GETGL3RASTEREXT(raster); switch(raster->format & 0xF00){ case Raster::C8888: natras->internalFormat = GL_RGBA8; @@ -65,6 +65,8 @@ rasterCreateTexture(Raster *raster) natras->bpp = 4; #endif + natras->isCompressed = 0; + raster->stride = raster->width*natras->bpp; glGenTextures(1, &natras->texid); @@ -89,7 +91,7 @@ rasterCreateCameraTexture(Raster *raster) } // TODO: figure out what the backbuffer is and use that as a default - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + Gl3Raster *natras = GETGL3RASTEREXT(raster); switch(raster->format & 0xF00){ case Raster::C8888: natras->internalFormat = GL_RGBA8; @@ -123,6 +125,8 @@ rasterCreateCameraTexture(Raster *raster) // natras->bpp = 4; #endif + natras->isCompressed = 0; + raster->stride = raster->width*natras->bpp; glGenTextures(1, &natras->texid); @@ -149,7 +153,7 @@ rasterCreateCameraTexture(Raster *raster) static Raster* rasterCreateCamera(Raster *raster) { - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + Gl3Raster *natras = GETGL3RASTEREXT(raster); // TODO: set/check width, height, depth, format? raster->originalWidth = raster->width; @@ -167,7 +171,7 @@ rasterCreateCamera(Raster *raster) static Raster* rasterCreateZbuffer(Raster *raster) { - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + Gl3Raster *natras = GETGL3RASTEREXT(raster); // TODO: set/check width, height, depth, format? raster->originalWidth = raster->width; @@ -179,6 +183,8 @@ rasterCreateZbuffer(Raster *raster) natras->format = GL_DEPTH_COMPONENT; natras->type = GL_UNSIGNED_BYTE; + natras->isCompressed = 0; + glGenTextures(1, &natras->texid); uint32 prev = bindTexture(natras->texid); glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, @@ -258,7 +264,7 @@ uint8* rasterLock(Raster *raster, int32 level, int32 lockMode) { #ifdef RW_OPENGL - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + Gl3Raster *natras GETGL3RASTEREXT(raster); uint8 *px; assert(raster->privateFlags == 0); @@ -268,28 +274,33 @@ rasterLock(Raster *raster, int32 level, int32 lockMode) case Raster::TEXTURE: case Raster::CAMERATEXTURE: px = (uint8*)rwMalloc(raster->stride*raster->height, MEMDUR_EVENT | ID_DRIVER); -memset(px, 0, raster->stride*raster->height); assert(raster->pixels == nil); raster->pixels = px; if(lockMode & Raster::LOCKREAD || !(lockMode & Raster::LOCKNOFETCH)){ + if(natras->isCompressed){ + uint32 prev = bindTexture(natras->texid); + glGetCompressedTexImage(GL_TEXTURE_2D, level, px); + bindTexture(prev); + }else{ #ifdef RW_GLES - GLuint fbo; + GLuint fbo; GLenum e; - glGenFramebuffers(1, &fbo); - bindFramebuffer(fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, natras->texid, 0); - e = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glGenFramebuffers(1, &fbo); + bindFramebuffer(fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, natras->texid, 0); + e = glCheckFramebufferStatus(GL_FRAMEBUFFER); assert(natras->format == GL_RGBA); - glReadPixels(0, 0, raster->width, raster->height, natras->format, natras->type, px); + glReadPixels(0, 0, raster->width, raster->height, natras->format, natras->type, px); //e = glGetError(); printf("GL err4 %x (%x)\n", e, natras->format); - bindFramebuffer(0); - glDeleteFramebuffers(1, &fbo); + bindFramebuffer(0); + glDeleteFramebuffers(1, &fbo); #else - uint32 prev = bindTexture(natras->texid); - glGetTexImage(GL_TEXTURE_2D, level, natras->format, natras->type, px); - bindTexture(prev); + uint32 prev = bindTexture(natras->texid); + glGetTexImage(GL_TEXTURE_2D, level, natras->format, natras->type, px); + bindTexture(prev); #endif + } } raster->privateFlags = lockMode; @@ -310,15 +321,21 @@ void rasterUnlock(Raster *raster, int32 level) { #ifdef RW_OPENGL - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + Gl3Raster *natras = GETGL3RASTEREXT(raster); assert(raster->pixels); if(raster->privateFlags & Raster::LOCKWRITE){ uint32 prev = bindTexture(natras->texid); - glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, - raster->width, raster->height, - 0, natras->format, natras->type, raster->pixels); + if(natras->isCompressed) + glCompressedTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, + raster->width, raster->height, 0, + raster->stride*raster->height, + raster->pixels); + else + glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, + raster->width, raster->height, + 0, natras->format, natras->type, raster->pixels); bindTexture(prev); } @@ -407,7 +424,7 @@ rasterFromImage(Raster *raster, Image *image) image = truecolimg; } - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + Gl3Raster *natras = GETGL3RASTEREXT(raster); switch(image->depth){ case 32: #ifdef RW_GLES @@ -480,6 +497,61 @@ rasterFromImage(Raster *raster, Image *image) 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* createNativeRaster(void *object, int32 offset, int32) { @@ -505,7 +577,7 @@ destroyNativeRaster(void *object, int32 offset, int32) case Raster::CAMERATEXTURE: if(natras->fboMate){ // Break apart from currently associated zbuffer - Gl3Raster *zras = PLUGINOFFSET(Gl3Raster, natras->fboMate, offset); + Gl3Raster *zras = GETGL3RASTEREXT(natras->fboMate); zras->fboMate = nil; natras->fboMate = nil; } @@ -516,7 +588,7 @@ destroyNativeRaster(void *object, int32 offset, int32) case Raster::ZBUFFER: if(natras->fboMate){ // Detatch from FBO we may be attached to - Gl3Raster *oldfb = PLUGINOFFSET(Gl3Raster, natras->fboMate, nativeRasterOffset); + Gl3Raster *oldfb = GETGL3RASTEREXT(natras->fboMate); if(oldfb->fbo){ bindFramebuffer(oldfb->fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); @@ -529,7 +601,7 @@ destroyNativeRaster(void *object, int32 offset, int32) case Raster::CAMERA: if(natras->fboMate){ // Break apart from currently associated zbuffer - Gl3Raster *zras = PLUGINOFFSET(Gl3Raster, natras->fboMate, offset); + Gl3Raster *zras = GETGL3RASTEREXT(natras->fboMate); zras->fboMate = nil; natras->fboMate = nil; } @@ -555,7 +627,7 @@ copyNativeRaster(void *dst, void *, int32 offset, int32) static uint32 getLevelSize(Raster *raster, int32 level) { - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + Gl3Raster *natras = GETGL3RASTEREXT(raster); uint32 size = raster->stride*raster->height; while(level--) size /= 4; @@ -591,11 +663,20 @@ readNativeTexture(Stream *stream) int32 depth = stream->readI32(); int32 numLevels = stream->readI32(); + // Native raster + int32 flags = stream->readI32(); + int32 compression = stream->readI32(); + Raster *raster; Gl3Raster *natras; - raster = Raster::create(width, height, depth, format | Raster::TEXTURE, PLATFORM_GL3); + if(flags & 2){ + raster = Raster::create(width, height, depth, format | Raster::TEXTURE | Raster::DONTALLOCATE, PLATFORM_GL3); + allocateDXT(raster, compression, numLevels, flags & 1); + }else{ + raster = Raster::create(width, height, depth, format | Raster::TEXTURE, PLATFORM_GL3); + } assert(raster); - natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + natras = GETGL3RASTEREXT(raster); tex->raster = raster; uint32 size; @@ -616,7 +697,7 @@ void writeNativeTexture(Texture *tex, Stream *stream) { Raster *raster = tex->raster; - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + Gl3Raster *natras = GETGL3RASTEREXT(raster); int32 chunksize = getSizeNativeTexture(tex); writeChunkHeader(stream, ID_STRUCT, chunksize-12); @@ -634,7 +715,34 @@ writeNativeTexture(Texture *tex, Stream *stream) stream->writeI32(raster->height); stream->writeI32(raster->depth); stream->writeI32(numLevels); - // TODO: compression? auto mipmaps? + + // Native raster + int32 flags = 0; + int32 compression = 0; + if(natras->hasAlpha) + flags |= 1; + if(natras->isCompressed){ + flags |= 2; + switch(natras->internalFormat){ +#ifdef RW_OPENGL + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + compression = 1; + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + compression = 3; + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + compression = 5; + break; +#endif + default: + assert(0 && "unknown compression"); + } + } + stream->writeI32(flags); + stream->writeI32(compression); + // TODO: auto mipmaps? uint32 size; uint8 *data; diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index b223f1e..7c01f9b 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -223,8 +223,6 @@ ObjPipeline *makeDefaultPipeline(void); // Native Texture and Raster -extern int32 nativeRasterOffset; - struct Gl3Raster { // arguments to glTexImage2D @@ -235,6 +233,7 @@ struct Gl3Raster // texture object uint32 texid; + bool32 isCompressed; bool32 hasAlpha; // cached filtermode and addressing uint8 filterMode; @@ -245,11 +244,15 @@ struct Gl3Raster Raster *fboMate; // color or zbuffer raster mate of this one }; +void allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha); + Texture *readNativeTexture(Stream *stream); void writeNativeTexture(Texture *tex, Stream *stream); uint32 getSizeNativeTexture(Texture *tex); +extern int32 nativeRasterOffset; void registerNativeRaster(void); +#define GETGL3RASTEREXT(raster) PLUGINOFFSET(Gl3Raster, raster, rw::gl3::nativeRasterOffset) } } diff --git a/src/image.cpp b/src/image.cpp index 632ca97..ce071b5 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -323,6 +323,140 @@ decompressDXT5(uint8 *adst, int32 w, int32 h, uint8 *src) } } +// not strictly image but related + +// flip a DXT 2-bit block +static void +flipBlock(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[7]; + dst[5] = src[6]; + dst[6] = src[5]; + dst[7] = src[4]; +} + +// flip a DXT3 4-bit alpha block +static void +flipAlphaBlock3(uint8 *dst, uint8 *src) +{ + dst[6] = src[0]; + dst[7] = src[1]; + dst[4] = src[2]; + dst[5] = src[3]; + dst[2] = src[4]; + dst[3] = src[5]; + dst[0] = src[6]; + dst[1] = src[7]; +} + +// flip a DXT5 3-bit alpha block +static void +flipAlphaBlock5(uint8 *dst, uint8 *src) +{ + // color + dst[0] = src[0]; + dst[1] = src[1]; + // bits + uint64 bits = *(uint64*)&src[2]; + uint64 flipbits = 0; + for(int i = 0; i < 4; i++){ + flipbits <<= 12; + flipbits |= bits & 0xFFF; + bits >>= 12; + } + memcpy(src+2, &flipbits, 6); +} + +void +flipDXT1(uint8 *dst, uint8 *src, uint32 width, uint32 height) +{ + int x, y; + assert(width % 4 == 0); + assert(height % 4 == 0); + int bw = width/4; + int bh = height/4; + dst += 8*bw*bh; + for(y = 0; y < bh; y++){ + dst -= 8*bw; + uint8 *s = src; + uint8 *d = dst; + for(x = 0; x < bw; x++){ + flipBlock(d, s); + s += 8; + d += 8; + } + src += 8*bw; + } +} + +void +flipDXT3(uint8 *dst, uint8 *src, uint32 width, uint32 height) +{ + int x, y; + assert(width % 4 == 0); + assert(height % 4 == 0); + int bw = width/4; + int bh = height/4; + dst += 16*bw*bh; + for(y = 0; y < bh; y++){ + dst -= 16*bw; + uint8 *s = src; + uint8 *d = dst; + for(x = 0; x < bw; x++){ + flipAlphaBlock3(d, s); + flipBlock(d+8, s+8); + s += 16; + d += 16; + } + src += 16*bw; + } +} + +void +flipDXT5(uint8 *dst, uint8 *src, uint32 width, uint32 height) +{ + int x, y; + assert(width % 4 == 0); + assert(height % 4 == 0); + int bw = width/4; + int bh = height/4; + dst += 16*bw*bh; + for(y = 0; y < bh; y++){ + dst -= 16*bw; + uint8 *s = src; + uint8 *d = dst; + for(x = 0; x < bw; x++){ + flipAlphaBlock5(d, s); + flipBlock(d+8, s+8); + s += 16; + d += 16; + } + src += 16*bw; + } +} + +void +flipDXT(int32 type, uint8 *dst, uint8 *src, uint32 width, uint32 height) +{ + switch(type){ + case 1: + flipDXT1(dst, src, width, height); + break; + case 3: + flipDXT3(dst, src, width, height); + break; + case 5: + flipDXT5(dst, src, width, height); + break; + } +} + void Image::setPixelsDXT(int32 type, uint8 *pixels) { diff --git a/src/rwobjects.h b/src/rwobjects.h index 333e42d..bf83cbd 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -337,6 +337,10 @@ 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 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); #define IGNORERASTERIMP 0