diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index 3063a9c..f14c317 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -579,7 +579,7 @@ rasterLock(Raster *raster, int32 level, int32 lockMode) if(lockMode & Raster::LOCKREAD) flags |= D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE; IDirect3DTexture9 *tex = (IDirect3DTexture9*)natras->texture; - IDirect3DSurface9 *surf; + IDirect3DSurface9 *surf, *rt; D3DLOCKED_RECT lr; switch(raster->type){ @@ -592,6 +592,26 @@ rasterLock(Raster *raster, int32 level, int32 lockMode) break; } + case Raster::CAMERATEXTURE: + case Raster::CAMERA: { + if(lockMode & Raster::PRIVATELOCK_WRITE) + assert(0 && "can't lock framebuffer for writing"); + if(raster->type == Raster::CAMERA) + rt = d3d9Globals.defaultRenderTarget; + else + tex->GetSurfaceLevel(level, &rt); + D3DSURFACE_DESC desc; + rt->GetDesc(&desc); + HRESULT res = d3ddevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &rt, nil); + if(res != D3D_OK) + return nil; + d3ddevice->GetRenderTargetData(rt, surf); + natras->lockedSurf = surf; + res = surf->LockRect(&lr, 0, flags); + assert(res == D3D_OK); + break; + } + default: assert(0 && "can't lock this raster type (yet)"); } diff --git a/src/gl/gl3.cpp b/src/gl/gl3.cpp index 7ec3f02..193cdd6 100644 --- a/src/gl/gl3.cpp +++ b/src/gl/gl3.cpp @@ -35,6 +35,7 @@ driverOpen(void *o, int32, int32) engine->driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels; engine->driver[PLATFORM_GL3]->imageFindRasterFormat = imageFindRasterFormat; engine->driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage; + engine->driver[PLATFORM_GL3]->rasterToImage = rasterToImage; return o; } diff --git a/src/gl/gl3device.cpp b/src/gl/gl3device.cpp index 087b1ac..90a3f35 100644 --- a/src/gl/gl3device.cpp +++ b/src/gl/gl3device.cpp @@ -25,43 +25,8 @@ namespace rw { namespace gl3 { -struct DisplayMode -{ -#ifdef LIBRW_SDL2 - SDL_DisplayMode mode; -#else - GLFWvidmode mode; -#endif - int32 depth; - uint32 flags; -}; -struct GlGlobals -{ -#ifdef LIBRW_SDL2 - SDL_Window **pWindow; - SDL_Window *window; - SDL_GLContext glcontext; -#else - GLFWwindow **pWindow; - GLFWwindow *window; - - GLFWmonitor *monitor; - int numMonitors; - int currentMonitor; -#endif - - DisplayMode *modes; - int numModes; - int currentMode; - int presentWidth, presentHeight; - int presentOffX, presentOffY; - - // for opening the window - int winWidth, winHeight; - const char *winTitle; - uint32 numSamples; -} glGlobals; +GlGlobals glGlobals; Gl3Caps gl3Caps; // terrible hack for GLES diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index abb0f98..2d84a53 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -14,6 +14,7 @@ #endif #include "rwgl3.h" #include "rwgl3shader.h" +#include "rwgl3impl.h" #define PLUGIN_ID ID_DRIVER @@ -215,6 +216,14 @@ rasterCreateCamera(Raster *raster) // TODO: set/check width, height, depth, format? + // used for locking right now + raster->format = Raster::C888; + natras->internalFormat = GL_RGB8; + natras->format = GL_RGB; + natras->type = GL_UNSIGNED_BYTE; + natras->hasAlpha = 0; + natras->bpp = 3; + natras->autogenMipmap = 0; natras->texid = 0; @@ -437,7 +446,7 @@ rasterLock(Raster *raster, int32 level, int32 lockMode) assert(raster->privateFlags == 0); - switch(raster->type & 0xF00){ + switch(raster->type){ case Raster::NORMAL: case Raster::TEXTURE: case Raster::CAMERATEXTURE: @@ -489,6 +498,23 @@ assert(natras->format == GL_RGBA); raster->privateFlags = lockMode; break; + case Raster::CAMERA: + if(lockMode & Raster::PRIVATELOCK_WRITE) + assert(0 && "can't lock framebuffer for writing"); + raster->width = glGlobals.presentWidth; + raster->height = glGlobals.presentHeight; + raster->stride = raster->width*natras->bpp; + assert(natras->bpp == 3); + allocSz = raster->height*raster->stride; + px = (uint8*)rwMalloc(allocSz, MEMDUR_EVENT | ID_DRIVER); + assert(raster->pixels == nil); + raster->pixels = px; + glReadBuffer(GL_BACK); + glReadPixels(0, 0, raster->width, raster->height, GL_RGB, GL_UNSIGNED_BYTE, px); + + raster->privateFlags = lockMode; + break; + default: assert(0 && "cannot lock this type of raster yet"); return nil; @@ -508,27 +534,37 @@ rasterUnlock(Raster *raster, int32 level) assert(raster->pixels); - if(raster->privateFlags & Raster::LOCKWRITE){ - uint32 prev = bindTexture(natras->texid); - if(natras->isCompressed){ - glCompressedTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, - raster->width, raster->height, 0, - getLevelSize(raster, level), - raster->pixels); - if(natras->backingStore){ - assert(level < natras->backingStore->numlevels); - memcpy(natras->backingStore->levels[level].data, raster->pixels, - natras->backingStore->levels[level].size); + switch(raster->type){ + case Raster::NORMAL: + case Raster::TEXTURE: + case Raster::CAMERATEXTURE: + if(raster->privateFlags & Raster::LOCKWRITE){ + uint32 prev = bindTexture(natras->texid); + if(natras->isCompressed){ + glCompressedTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, + raster->width, raster->height, 0, + getLevelSize(raster, level), + raster->pixels); + if(natras->backingStore){ + assert(level < natras->backingStore->numlevels); + memcpy(natras->backingStore->levels[level].data, raster->pixels, + natras->backingStore->levels[level].size); + } + }else{ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, + raster->width, raster->height, + 0, natras->format, natras->type, raster->pixels); } - }else{ - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, - raster->width, raster->height, - 0, natras->format, natras->type, raster->pixels); + if(level == 0 && natras->autogenMipmap) + glGenerateMipmap(GL_TEXTURE_2D); + bindTexture(prev); } - if(level == 0 && natras->autogenMipmap) - glGenerateMipmap(GL_TEXTURE_2D); - bindTexture(prev); + break; + + case Raster::CAMERA: + // TODO: write? + break; } rwFree(raster->pixels); @@ -695,6 +731,83 @@ rasterFromImage(Raster *raster, Image *image) return 1; } +Image* +rasterToImage(Raster *raster) +{ + int32 depth; + Image *image; + + bool unlock = false; + if(raster->pixels == nil){ + raster->lock(0, Raster::LOCKREAD); + unlock = true; + } + + Gl3Raster *natras = GETGL3RASTEREXT(raster); + if(natras->isCompressed){ + // TODO + RWERROR((ERR_INVRASTER)); + return nil; + } + + void (*conv)(uint8 *out, uint8 *in) = nil; + switch(raster->format & 0xF00){ + case Raster::C1555: + depth = 16; + conv = conv_ARGB1555_from_RGBA5551; + break; + case Raster::C8888: + depth = 32; + conv = conv_RGBA8888_from_RGBA8888; + break; + case Raster::C888: + depth = 24; + conv = conv_RGB888_from_RGB888; + break; + + default: + case Raster::C555: + case Raster::C565: + case Raster::C4444: + case Raster::LUM8: + RWERROR((ERR_INVRASTER)); + return nil; + } + + if(raster->format & Raster::PAL4 || + raster->format & Raster::PAL8){ + RWERROR((ERR_INVRASTER)); + return nil; + } + + uint8 *in, *out; + image = Image::create(raster->width, raster->height, depth); + image->allocate(); + + uint8 *imgpixels = image->pixels + (image->height-1)*image->stride; + uint8 *pixels = raster->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(imgrow, rasrow); + imgrow += image->bpp; + rasrow += natras->bpp; + } + imgpixels -= image->stride; + pixels += raster->stride; + } + + if(unlock) + raster->unlock(0); + + return image; +} + static void* createNativeRaster(void *object, int32 offset, int32) { diff --git a/src/gl/rwgl3impl.h b/src/gl/rwgl3impl.h index 8c5e428..39f0050 100644 --- a/src/gl/rwgl3impl.h +++ b/src/gl/rwgl3impl.h @@ -21,6 +21,46 @@ void im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flag void im3DRenderPrimitive(PrimitiveType primType); void im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices); void im3DEnd(void); + +struct DisplayMode +{ +#ifdef LIBRW_SDL2 + SDL_DisplayMode mode; +#else + GLFWvidmode mode; +#endif + int32 depth; + uint32 flags; +}; + +struct GlGlobals +{ +#ifdef LIBRW_SDL2 + SDL_Window **pWindow; + SDL_Window *window; + SDL_GLContext glcontext; +#else + GLFWwindow **pWindow; + GLFWwindow *window; + + GLFWmonitor *monitor; + int numMonitors; + int currentMonitor; +#endif + + DisplayMode *modes; + int numModes; + int currentMode; + int presentWidth, presentHeight; + int presentOffX, presentOffY; + + // for opening the window + int winWidth, winHeight; + const char *winTitle; + uint32 numSamples; +}; + +extern GlGlobals glGlobals; #endif Raster *rasterCreate(Raster *raster); @@ -30,6 +70,7 @@ int32 rasterNumLevels(Raster*); bool32 imageFindRasterFormat(Image *img, int32 type, int32 *width, int32 *height, int32 *depth, int32 *format); bool32 rasterFromImage(Raster *raster, Image *image); +Image *rasterToImage(Raster *raster); } } diff --git a/src/raster.cpp b/src/raster.cpp index e9007a0..346cb7b 100644 --- a/src/raster.cpp +++ b/src/raster.cpp @@ -301,6 +301,18 @@ conv_RGBA5551_from_ARGB1555(uint8 *out, uint8 *in) out[1] = g>>2 | r<<3; } +void +conv_ARGB1555_from_RGBA5551(uint8 *out, uint8 *in) +{ + uint32 r, g, b, a; + a = in[0] & 1; + b = (in[0]>>1) & 0x1F; + g = (in[1]&7)<<2 | ((in[0]>>6)&3); + r = (in[1]>>3) & 0x1F; + out[0] = b | g<<5; + out[1] = g>>3 | r<<2 | a<<7; +} + void conv_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in) { diff --git a/src/rwobjects.h b/src/rwobjects.h index 84435dc..71e0518 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -324,6 +324,7 @@ 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_ARGB1555_from_RGBA5551(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; }