From 40fc1e24fc231ffa5e5b8cbb0f1add2967ec10fa Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 15 Jul 2016 11:55:52 +0200 Subject: [PATCH] rasters --- src/d3d/d3d.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++- src/d3d/d3d8.cpp | 3 +- src/d3d/d3d9.cpp | 3 +- src/d3d/rwd3dimpl.h | 1 + src/engine.cpp | 8 ++++ src/gl/gl3driver.cpp | 3 +- src/gl/gl3raster.cpp | 45 +++++++++++++++----- src/gl/rwgl3.h | 6 +++ src/image.cpp | 13 ++++-- src/rwengine.h | 8 ++-- src/rwobjects.h | 6 ++- 11 files changed, 171 insertions(+), 23 deletions(-) diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index 2f11105..db0f6d6 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -443,7 +443,7 @@ rasterFromImage(Raster *raster, Image *image) default: return; } - format |= 4; + format |= Raster::TEXTURE; raster->type = format & 0x7; raster->flags = format & 0xF8; @@ -505,6 +505,102 @@ rasterFromImage(Raster *raster, Image *image) raster->unlock(0); } +Image* +rasterToImage(Raster *raster) +{ + int32 depth; + Image *image; + D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); + if(natras->format) + assert(0 && "no custom formats yet"); + switch(raster->format & 0xF00){ + case Raster::C1555: + depth = 16; + break; + case Raster::C8888: + depth = 32; + break; + case Raster::C888: + depth = 24; + break; + case Raster::C555: + depth = 16; + break; + + default: + case Raster::C565: + case Raster::C4444: + case Raster::LUM8: + assert(0 && "unsupported raster format"); + } + int32 pallength = 0; + if((raster->format & Raster::PAL4) == Raster::PAL4){ + depth = 4; + pallength = 16; + }else if((raster->format & Raster::PAL4) == Raster::PAL8){ + depth = 8; + pallength = 256; + } + + uint8 *in, *out; + image = Image::create(raster->width, raster->height, depth); + image->allocate(); + + if(pallength){ + out = image->palette; + in = (uint8*)natras->palette; + for(int32 i = 0; i < pallength; i++){ + out[0] = in[2]; + out[1] = in[1]; + out[2] = in[0]; + out[3] = in[3]; + in += 4; + out += 4; + } + } + + out = image->pixels; + in = raster->lock(0); + 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 += 4; + out += 4; + break; + case Raster::C888: + out[0] = in[2]; + out[1] = in[1]; + out[2] = in[0]; + in += 4; + out += 3; + break; + case Raster::C1555: + out[0] = in[0]; + out[1] = in[1]; + in += 2; + out += 2; + break; + case Raster::C555: + out[0] = in[0]; + out[1] = in[1] | 0x80; + in += 2; + out += 2; + break; + } + raster->unlock(0); + + return image; +} + int32 getLevelSize(Raster *raster, int32 level) { diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index 9195873..daad949 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -31,6 +31,7 @@ driverOpen(void *o, int32, int32) driver[PLATFORM_D3D8]->rasterUnlock = rasterUnlock; driver[PLATFORM_D3D8]->rasterNumLevels = rasterNumLevels; driver[PLATFORM_D3D8]->rasterFromImage = rasterFromImage; + driver[PLATFORM_D3D8]->rasterToImage = rasterToImage; return o; } @@ -470,7 +471,7 @@ readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format } delete[] data; - Raster *ras = Raster::createFromImage(img); + Raster *ras = Raster::createFromImage(img, PLATFORM_D3D8); img->destroy(); return ras; } diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp index 4c41077..472abea 100644 --- a/src/d3d/d3d9.cpp +++ b/src/d3d/d3d9.cpp @@ -38,6 +38,7 @@ driverOpen(void *o, int32, int32) driver[PLATFORM_D3D9]->rasterUnlock = rasterUnlock; driver[PLATFORM_D3D9]->rasterNumLevels = rasterNumLevels; driver[PLATFORM_D3D9]->rasterFromImage = rasterFromImage; + driver[PLATFORM_D3D9]->rasterToImage = rasterToImage; return o; } @@ -177,7 +178,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) for(int i = 0; i < 2; i++){ stream->read(p, 16); s = &header->vertexStream[i]; - s->vertexBuffer = (void*)*(uint32*)p; p += 4; + s->vertexBuffer = (void*)(uintptr)*(uint32*)p; p += 4; s->offset = 0; p += 4; s->stride = *(uint32*)p; p += 4; s->geometryFlags = *(uint16*)p; p += 2; diff --git a/src/d3d/rwd3dimpl.h b/src/d3d/rwd3dimpl.h index 9259d81..0053181 100644 --- a/src/d3d/rwd3dimpl.h +++ b/src/d3d/rwd3dimpl.h @@ -6,6 +6,7 @@ uint8 *rasterLock(Raster *raster, int32 level); void rasterUnlock(Raster *raster, int32 level); int32 rasterNumLevels(Raster *raster); void rasterFromImage(Raster *raster, Image *image); +Image *rasterToImage(Raster *raster); } } diff --git a/src/engine.cpp b/src/engine.cpp index 2b4fde3..15561fe 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -63,6 +63,7 @@ Driver::open(void) driver[i]->rasterUnlock = null::rasterUnlock; driver[i]->rasterNumLevels = null::rasterNumLevels; driver[i]->rasterFromImage = null::rasterFromImage; + driver[i]->rasterToImage = null::rasterToImage; s_plglist[i].construct(rw::driver[i]); } @@ -109,5 +110,12 @@ rasterFromImage(Raster*, Image*) assert(0 && "rasterFromImage not implemented"); } +Image* +rasterToImage(Raster*) +{ + assert(0 && "rasterToImage not implemented"); + return nil; +} + } } diff --git a/src/gl/gl3driver.cpp b/src/gl/gl3driver.cpp index 1e4aea2..4748a4a 100644 --- a/src/gl/gl3driver.cpp +++ b/src/gl/gl3driver.cpp @@ -279,7 +279,8 @@ setTexture(int32 n, Texture *tex) { bool32 alpha; glActiveTexture(GL_TEXTURE0+n); - if(tex == nil){ + if(tex == nil || tex->raster->platform != PLATFORM_GL3 || + tex->raster->width == 0){ glBindTexture(GL_TEXTURE_2D, whitetex); alpha = 0; }else{ diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index 2e0f50d..5dc19b7 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -23,19 +23,34 @@ int32 nativeRasterOffset; void rasterCreate(Raster *raster) { - Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); if(raster->flags & Raster::DONTALLOCATE) return; - assert(raster->depth == 32); - #ifdef RW_OPENGL + Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); + switch(raster->format & 0xF00){ + case Raster::C8888: + natras->internalFormat = GL_RGBA; + natras->format = GL_RGBA; + natras->hasAlpha = 1; + break; + case Raster::C888: + natras->internalFormat = GL_RGB; + natras->format = GL_RGB; + natras->hasAlpha = 0; + break; + default: + assert(0 && "unsupported raster format"); + } + natras->type = GL_UNSIGNED_BYTE; + glGenTextures(1, &natras->texid); glBindTexture(GL_TEXTURE_2D, natras->texid); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, raster->width, raster->height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, nil); + glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, + raster->width, raster->height, + 0, natras->format, natras->type, nil); glBindTexture(GL_TEXTURE_2D, 0); #endif @@ -67,22 +82,30 @@ rasterFromImage(Raster *raster, Image *image) int32 format; Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); - format = Raster::C8888; - format |= 4; + switch(image->depth){ + case 32: + format = Raster::C8888; + break; + case 24: + format = Raster::C888; + break; + default: + assert(0 && "image depth\n"); + } + format |= Raster::TEXTURE; raster->type = format & 0x7; raster->flags = format & 0xF8; raster->format = format & 0xFF00; rasterCreate(raster); - assert(image->depth == 32); - natras->hasAlpha = image->hasAlpha(); #ifdef RW_OPENGL glBindTexture(GL_TEXTURE_2D, natras->texid); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, raster->width, raster->height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels); + glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, + raster->width, raster->height, + 0, natras->format, natras->type, image->pixels); glBindTexture(GL_TEXTURE_2D, 0); #endif } diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index a1c9040..8fc702c 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -100,7 +100,13 @@ extern int32 nativeRasterOffset; struct Gl3Raster { + // arguments to glTexImage2D + int32 internalFormat; + int32 type; + int32 format; + // texture object uint32 texid; + bool32 hasAlpha; }; diff --git a/src/image.cpp b/src/image.cpp index 9548845..170b8dd 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -216,7 +216,7 @@ Texture::read(const char *name, const char *mask) strncpy(tex->name, name, 32); if(mask) strncpy(tex->mask, mask, 32); - raster = Raster::create(0, 0, 0, 0x80); + raster = Raster::create(0, 0, 0, Raster::DONTALLOCATE); tex->raster = raster; } if(currentTexDictionary){ @@ -733,12 +733,19 @@ Raster::calculateNumLevels(int32 width, int32 height) } Raster* -Raster::createFromImage(Image *image) +Raster::createFromImage(Image *image, int32 platform) { Raster *raster = Raster::create(image->width, image->height, - image->depth, 4 | 0x80); + image->depth, TEXTURE | DONTALLOCATE, + platform); driver[raster->platform]->rasterFromImage(raster, image); return raster; } +Image* +Raster::toImage(void) +{ + return driver[this->platform]->rasterToImage(this); +} + } diff --git a/src/rwengine.h b/src/rwengine.h index 7430831..d9b2fee 100644 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -53,9 +53,9 @@ struct Engine // Device float32 zNear, zFar; - void (*beginUpdate)(Camera*); - void (*endUpdate)(Camera*); - void (*clearCamera)(Camera*, RGBA *col, uint32 mode); + void (*beginUpdate)(Camera*); + void (*endUpdate)(Camera*); + void (*clearCamera)(Camera*, RGBA *col, uint32 mode); void (*setRenderState)(int32 state, uint32 value); uint32 (*getRenderState)(int32 state); @@ -76,6 +76,7 @@ struct Driver void (*rasterUnlock)(Raster*, int32 level); int32 (*rasterNumLevels)(Raster*); void (*rasterFromImage)(Raster*, Image*); + Image *(*rasterToImage)(Raster*); static PluginList s_plglist[NUM_PLATFORMS]; static void open(void); @@ -108,6 +109,7 @@ namespace null { void rasterUnlock(Raster*, int32 level); int32 rasterNumLevels(Raster*); void rasterFromImage(Raster*, Image*); + Image *rasterToImage(Raster*); } } diff --git a/src/rwobjects.h b/src/rwobjects.h index dbc8e0e..8944eb3 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -214,9 +214,11 @@ struct Raster : PluginBase uint8 *texels; uint8 *palette; - static Raster *create(int32 width, int32 height, int32 depth, int32 format, int32 platform = 0); + static Raster *create(int32 width, int32 height, int32 depth, + int32 format, int32 platform = 0); void destroy(void); - static Raster *createFromImage(Image *image); + static Raster *createFromImage(Image *image, int32 platform = 0); + Image *toImage(void); uint8 *lock(int32 level); void unlock(int32 level); int32 getNumLevels(void);