framebuffer read lock; gl raster to image

This commit is contained in:
aap 2021-01-21 02:23:28 +01:00
parent baa8666a03
commit 9260bddc66
7 changed files with 210 additions and 57 deletions

View File

@ -579,7 +579,7 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
if(lockMode & Raster::LOCKREAD) if(lockMode & Raster::LOCKREAD)
flags |= D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE; flags |= D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE;
IDirect3DTexture9 *tex = (IDirect3DTexture9*)natras->texture; IDirect3DTexture9 *tex = (IDirect3DTexture9*)natras->texture;
IDirect3DSurface9 *surf; IDirect3DSurface9 *surf, *rt;
D3DLOCKED_RECT lr; D3DLOCKED_RECT lr;
switch(raster->type){ switch(raster->type){
@ -592,6 +592,26 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
break; 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: default:
assert(0 && "can't lock this raster type (yet)"); assert(0 && "can't lock this raster type (yet)");
} }

View File

@ -35,6 +35,7 @@ driverOpen(void *o, int32, int32)
engine->driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels; engine->driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels;
engine->driver[PLATFORM_GL3]->imageFindRasterFormat = imageFindRasterFormat; engine->driver[PLATFORM_GL3]->imageFindRasterFormat = imageFindRasterFormat;
engine->driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage; engine->driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage;
engine->driver[PLATFORM_GL3]->rasterToImage = rasterToImage;
return o; return o;
} }

View File

@ -25,43 +25,8 @@
namespace rw { namespace rw {
namespace gl3 { namespace gl3 {
struct DisplayMode
{
#ifdef LIBRW_SDL2
SDL_DisplayMode mode;
#else
GLFWvidmode mode;
#endif
int32 depth;
uint32 flags;
};
struct GlGlobals GlGlobals 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;
Gl3Caps gl3Caps; Gl3Caps gl3Caps;
// terrible hack for GLES // terrible hack for GLES

View File

@ -14,6 +14,7 @@
#endif #endif
#include "rwgl3.h" #include "rwgl3.h"
#include "rwgl3shader.h" #include "rwgl3shader.h"
#include "rwgl3impl.h"
#define PLUGIN_ID ID_DRIVER #define PLUGIN_ID ID_DRIVER
@ -215,6 +216,14 @@ rasterCreateCamera(Raster *raster)
// TODO: set/check width, height, depth, format? // 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->autogenMipmap = 0;
natras->texid = 0; natras->texid = 0;
@ -437,7 +446,7 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
assert(raster->privateFlags == 0); assert(raster->privateFlags == 0);
switch(raster->type & 0xF00){ switch(raster->type){
case Raster::NORMAL: case Raster::NORMAL:
case Raster::TEXTURE: case Raster::TEXTURE:
case Raster::CAMERATEXTURE: case Raster::CAMERATEXTURE:
@ -489,6 +498,23 @@ assert(natras->format == GL_RGBA);
raster->privateFlags = lockMode; raster->privateFlags = lockMode;
break; 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: default:
assert(0 && "cannot lock this type of raster yet"); assert(0 && "cannot lock this type of raster yet");
return nil; return nil;
@ -508,27 +534,37 @@ rasterUnlock(Raster *raster, int32 level)
assert(raster->pixels); assert(raster->pixels);
if(raster->privateFlags & Raster::LOCKWRITE){ switch(raster->type){
uint32 prev = bindTexture(natras->texid); case Raster::NORMAL:
if(natras->isCompressed){ case Raster::TEXTURE:
glCompressedTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, case Raster::CAMERATEXTURE:
raster->width, raster->height, 0, if(raster->privateFlags & Raster::LOCKWRITE){
getLevelSize(raster, level), uint32 prev = bindTexture(natras->texid);
raster->pixels); if(natras->isCompressed){
if(natras->backingStore){ glCompressedTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat,
assert(level < natras->backingStore->numlevels); raster->width, raster->height, 0,
memcpy(natras->backingStore->levels[level].data, raster->pixels, getLevelSize(raster, level),
natras->backingStore->levels[level].size); 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{ if(level == 0 && natras->autogenMipmap)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenerateMipmap(GL_TEXTURE_2D);
glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, bindTexture(prev);
raster->width, raster->height,
0, natras->format, natras->type, raster->pixels);
} }
if(level == 0 && natras->autogenMipmap) break;
glGenerateMipmap(GL_TEXTURE_2D);
bindTexture(prev); case Raster::CAMERA:
// TODO: write?
break;
} }
rwFree(raster->pixels); rwFree(raster->pixels);
@ -695,6 +731,83 @@ rasterFromImage(Raster *raster, Image *image)
return 1; 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* static void*
createNativeRaster(void *object, int32 offset, int32) createNativeRaster(void *object, int32 offset, int32)
{ {

View File

@ -21,6 +21,46 @@ void im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flag
void im3DRenderPrimitive(PrimitiveType primType); void im3DRenderPrimitive(PrimitiveType primType);
void im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices); void im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices);
void im3DEnd(void); 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 #endif
Raster *rasterCreate(Raster *raster); Raster *rasterCreate(Raster *raster);
@ -30,6 +70,7 @@ int32 rasterNumLevels(Raster*);
bool32 imageFindRasterFormat(Image *img, int32 type, bool32 imageFindRasterFormat(Image *img, int32 type,
int32 *width, int32 *height, int32 *depth, int32 *format); int32 *width, int32 *height, int32 *depth, int32 *format);
bool32 rasterFromImage(Raster *raster, Image *image); bool32 rasterFromImage(Raster *raster, Image *image);
Image *rasterToImage(Raster *raster);
} }
} }

View File

@ -301,6 +301,18 @@ conv_RGBA5551_from_ARGB1555(uint8 *out, uint8 *in)
out[1] = g>>2 | r<<3; 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 void
conv_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in) conv_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in)
{ {

View File

@ -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_ARGB1555(uint8 *out, uint8 *in);
void conv_ARGB1555_from_RGB555(uint8 *out, uint8 *in); void conv_ARGB1555_from_RGB555(uint8 *out, uint8 *in);
void conv_RGBA5551_from_ARGB1555(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_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in);
void conv_ABGR1555_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; } inline void conv_8_from_8(uint8 *out, uint8 *in) { *out = *in; }