mirror of https://github.com/aap/librw.git
custom rendertarget support for gl
This commit is contained in:
parent
a29bcef4d7
commit
b1507e5099
|
@ -235,6 +235,8 @@ static GlState curGlState, oldGlState;
|
|||
static int32 activeTexture;
|
||||
static uint32 boundTexture[MAXNUMSTAGES];
|
||||
|
||||
static uint32 currentFramebuffer;
|
||||
|
||||
static uint32 blendMap[] = {
|
||||
GL_ZERO, // actually invalid
|
||||
GL_ZERO,
|
||||
|
@ -415,6 +417,16 @@ bindTexture(uint32 texid)
|
|||
return prev;
|
||||
}
|
||||
|
||||
void
|
||||
bindFramebuffer(uint32 fbo)
|
||||
{
|
||||
//glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
if(currentFramebuffer != fbo){
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
currentFramebuffer = fbo;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: support mipmaps
|
||||
static GLint filterConvMap_NoMIP[] = {
|
||||
0, GL_NEAREST, GL_LINEAR,
|
||||
|
@ -990,62 +1002,44 @@ flushCache(void)
|
|||
}
|
||||
|
||||
static void
|
||||
clearCamera(Camera *cam, RGBA *col, uint32 mode)
|
||||
setFrameBuffer(Camera *cam)
|
||||
{
|
||||
RGBAf colf;
|
||||
GLbitfield mask;
|
||||
Raster *fbuf = cam->frameBuffer;
|
||||
Raster *zbuf = cam->zBuffer;
|
||||
assert(fbuf);
|
||||
|
||||
convColor(&colf, col);
|
||||
glClearColor(colf.red, colf.green, colf.blue, colf.alpha);
|
||||
mask = 0;
|
||||
if(mode & Camera::CLEARIMAGE)
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
if(mode & Camera::CLEARZ)
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
glDepthMask(GL_TRUE);
|
||||
glClear(mask);
|
||||
glDepthMask(rwStateCache.zwrite);
|
||||
}
|
||||
Gl3Raster *natfb = PLUGINOFFSET(Gl3Raster, fbuf, nativeRasterOffset);
|
||||
Gl3Raster *natzb = PLUGINOFFSET(Gl3Raster, zbuf, nativeRasterOffset);
|
||||
assert(fbuf->type == Raster::CAMERA || fbuf->type == Raster::CAMERATEXTURE);
|
||||
|
||||
static void
|
||||
showRaster(Raster *raster, uint32 flags)
|
||||
{
|
||||
// TODO: do this properly!
|
||||
#ifdef LIBRW_SDL2
|
||||
SDL_GL_SwapWindow(glGlobals.window);
|
||||
#else
|
||||
if(flags & Raster::FLIPWAITVSYNCH)
|
||||
glfwSwapInterval(1);
|
||||
else
|
||||
glfwSwapInterval(0);
|
||||
glfwSwapBuffers(glGlobals.window);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool32
|
||||
rasterRenderFast(Raster *raster, int32 x, int32 y)
|
||||
{
|
||||
Raster *src = raster;
|
||||
Raster *dst = Raster::getCurrentContext();
|
||||
Gl3Raster *natdst = PLUGINOFFSET(Gl3Raster, dst, nativeRasterOffset);
|
||||
Gl3Raster *natsrc = PLUGINOFFSET(Gl3Raster, src, nativeRasterOffset);
|
||||
|
||||
switch(dst->type){
|
||||
case Raster::NORMAL:
|
||||
case Raster::TEXTURE:
|
||||
case Raster::CAMERATEXTURE:
|
||||
switch(src->type){
|
||||
case Raster::CAMERA:
|
||||
setActiveTexture(0);
|
||||
glBindTexture(GL_TEXTURE_2D, natdst->texid);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, (dst->height-src->height)-y,
|
||||
0, 0, src->width, src->height);
|
||||
glBindTexture(GL_TEXTURE_2D, boundTexture[0]);
|
||||
return 1;
|
||||
// Have to make sure depth buffer is attached to FB's fbo
|
||||
bindFramebuffer(natfb->fbo);
|
||||
if(zbuf){
|
||||
if(natfb->fboMate == zbuf){
|
||||
// all good
|
||||
assert(natzb->fboMate == fbuf);
|
||||
}else{
|
||||
if(natzb->fboMate){
|
||||
// have to detatch from fbo first!
|
||||
Gl3Raster *oldfb = PLUGINOFFSET(Gl3Raster, natzb->fboMate, nativeRasterOffset);
|
||||
if(oldfb->fbo){
|
||||
bindFramebuffer(oldfb->fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
bindFramebuffer(natfb->fbo);
|
||||
}
|
||||
oldfb->fboMate = nil;
|
||||
}
|
||||
natfb->fboMate = zbuf;
|
||||
natzb->fboMate = fbuf;
|
||||
if(natfb->fbo)
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, natzb->texid, 0);
|
||||
}
|
||||
break;
|
||||
}else{
|
||||
// remove z-buffer
|
||||
if(natfb->fboMate && natfb->fbo)
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
natfb->fboMate = nil;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1105,7 +1099,7 @@ beginUpdate(Camera *cam)
|
|||
proj[10] = -(cam->farPlane+cam->nearPlane)*invz;
|
||||
proj[11] = 0.0f;
|
||||
|
||||
proj[14] = -2.0f*invz;
|
||||
proj[14] = 2.0f*invz;
|
||||
proj[15] = 1.0f;
|
||||
}
|
||||
memcpy(&cam->devProj, &proj, sizeof(RawMatrix));
|
||||
|
@ -1122,12 +1116,20 @@ beginUpdate(Camera *cam)
|
|||
stateDirty = 1;
|
||||
}
|
||||
|
||||
setFrameBuffer(cam);
|
||||
|
||||
int w, h;
|
||||
if(cam->frameBuffer->type == Raster::CAMERA){
|
||||
#ifdef LIBRW_SDL2
|
||||
SDL_GetWindowSize(glGlobals.window, &w, &h);
|
||||
SDL_GetWindowSize(glGlobals.window, &w, &h);
|
||||
#else
|
||||
glfwGetWindowSize(glGlobals.window, &w, &h);
|
||||
glfwGetWindowSize(glGlobals.window, &w, &h);
|
||||
#endif
|
||||
}else{
|
||||
w = cam->frameBuffer->width;
|
||||
h = cam->frameBuffer->height;
|
||||
}
|
||||
|
||||
if(w != glGlobals.presentWidth || h != glGlobals.presentHeight){
|
||||
glViewport(0, 0, w, h);
|
||||
glGlobals.presentWidth = w;
|
||||
|
@ -1135,6 +1137,67 @@ beginUpdate(Camera *cam)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clearCamera(Camera *cam, RGBA *col, uint32 mode)
|
||||
{
|
||||
RGBAf colf;
|
||||
GLbitfield mask;
|
||||
|
||||
setFrameBuffer(cam);
|
||||
|
||||
convColor(&colf, col);
|
||||
glClearColor(colf.red, colf.green, colf.blue, colf.alpha);
|
||||
mask = 0;
|
||||
if(mode & Camera::CLEARIMAGE)
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
if(mode & Camera::CLEARZ)
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
glDepthMask(GL_TRUE);
|
||||
glClear(mask);
|
||||
glDepthMask(rwStateCache.zwrite);
|
||||
}
|
||||
|
||||
static void
|
||||
showRaster(Raster *raster, uint32 flags)
|
||||
{
|
||||
// TODO: do this properly!
|
||||
#ifdef LIBRW_SDL2
|
||||
SDL_GL_SwapWindow(glGlobals.window);
|
||||
#else
|
||||
if(flags & Raster::FLIPWAITVSYNCH)
|
||||
glfwSwapInterval(1);
|
||||
else
|
||||
glfwSwapInterval(0);
|
||||
glfwSwapBuffers(glGlobals.window);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool32
|
||||
rasterRenderFast(Raster *raster, int32 x, int32 y)
|
||||
{
|
||||
Raster *src = raster;
|
||||
Raster *dst = Raster::getCurrentContext();
|
||||
Gl3Raster *natdst = PLUGINOFFSET(Gl3Raster, dst, nativeRasterOffset);
|
||||
Gl3Raster *natsrc = PLUGINOFFSET(Gl3Raster, src, nativeRasterOffset);
|
||||
|
||||
switch(dst->type){
|
||||
case Raster::NORMAL:
|
||||
case Raster::TEXTURE:
|
||||
case Raster::CAMERATEXTURE:
|
||||
switch(src->type){
|
||||
case Raster::CAMERA:
|
||||
setActiveTexture(0);
|
||||
glBindTexture(GL_TEXTURE_2D, natdst->texid);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, (dst->height-src->height)-y,
|
||||
0, 0, src->width, src->height);
|
||||
glBindTexture(GL_TEXTURE_2D, boundTexture[0]);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef LIBRW_SDL2
|
||||
static int
|
||||
openSDL2(EngineOpenParams *openparams)
|
||||
|
|
|
@ -80,9 +80,6 @@ rasterCreateTexture(Raster *raster)
|
|||
return raster;
|
||||
}
|
||||
|
||||
// This is totally fake right now, can't render to it. Only used to copy into from FB
|
||||
// For rendering the idea would probably be to render to the backbuffer and copy it here afterwards.
|
||||
// alternatively just use FBOs but that probably needs some more infrastructure.
|
||||
static Raster*
|
||||
rasterCreateCameraTexture(Raster *raster)
|
||||
{
|
||||
|
@ -138,26 +135,64 @@ rasterCreateCameraTexture(Raster *raster)
|
|||
natras->addressV = 0;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
glGenFramebuffers(1, &natras->fbo);
|
||||
bindFramebuffer(natras->fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, natras->texid, 0);
|
||||
bindFramebuffer(0);
|
||||
natras->fboMate = nil;
|
||||
|
||||
return raster;
|
||||
}
|
||||
|
||||
static Raster*
|
||||
rasterCreateCamera(Raster *raster)
|
||||
{
|
||||
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
|
||||
|
||||
// TODO: set/check width, height, depth, format?
|
||||
raster->flags |= Raster::DONTALLOCATE;
|
||||
raster->originalWidth = raster->width;
|
||||
raster->originalHeight = raster->height;
|
||||
raster->stride = 0;
|
||||
raster->pixels = nil;
|
||||
|
||||
natras->texid = 0;
|
||||
natras->fbo = 0;
|
||||
natras->fboMate = nil;
|
||||
|
||||
return raster;
|
||||
}
|
||||
|
||||
static Raster*
|
||||
rasterCreateZbuffer(Raster *raster)
|
||||
{
|
||||
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
|
||||
|
||||
// TODO: set/check width, height, depth, format?
|
||||
raster->flags |= Raster::DONTALLOCATE;
|
||||
raster->originalWidth = raster->width;
|
||||
raster->originalHeight = raster->height;
|
||||
raster->stride = 0;
|
||||
raster->pixels = nil;
|
||||
|
||||
natras->internalFormat = GL_DEPTH_COMPONENT;
|
||||
natras->format = GL_DEPTH_COMPONENT;
|
||||
natras->type = GL_UNSIGNED_BYTE;
|
||||
|
||||
glGenTextures(1, &natras->texid);
|
||||
glBindTexture(GL_TEXTURE_2D, 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;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
natras->fbo = 0;
|
||||
natras->fboMate = nil;
|
||||
|
||||
return raster;
|
||||
}
|
||||
|
||||
|
@ -192,27 +227,21 @@ GL_RGB5
|
|||
Raster*
|
||||
rasterCreate(Raster *raster)
|
||||
{
|
||||
if(raster->width == 0 || raster->height == 0){
|
||||
raster->flags |= Raster::DONTALLOCATE;
|
||||
raster->stride = 0;
|
||||
return raster;
|
||||
}
|
||||
if(raster->flags & Raster::DONTALLOCATE)
|
||||
return raster;
|
||||
|
||||
switch(raster->type){
|
||||
#ifdef RW_OPENGL
|
||||
case Raster::NORMAL:
|
||||
case Raster::TEXTURE:
|
||||
// Dummy to use as subraster
|
||||
// ^ what did i do there?
|
||||
if(raster->width == 0 || raster->height == 0){
|
||||
raster->flags |= Raster::DONTALLOCATE;
|
||||
raster->stride = 0;
|
||||
return raster;
|
||||
}
|
||||
|
||||
if(raster->flags & Raster::DONTALLOCATE)
|
||||
return raster;
|
||||
return rasterCreateTexture(raster);
|
||||
|
||||
case Raster::CAMERATEXTURE:
|
||||
if(raster->flags & Raster::DONTALLOCATE)
|
||||
return raster;
|
||||
return rasterCreateCameraTexture(raster);
|
||||
|
||||
case Raster::ZBUFFER:
|
||||
return rasterCreateZbuffer(raster);
|
||||
case Raster::CAMERA:
|
||||
|
@ -248,13 +277,13 @@ memset(px, 0, raster->stride*raster->height);
|
|||
GLuint fbo;
|
||||
GLenum e;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 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);
|
||||
//e = glGetError(); printf("GL err4 %x (%x)\n", e, natras->format);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
bindFramebuffer(0);
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
#else
|
||||
uint32 prev = bindTexture(natras->texid);
|
||||
|
@ -456,15 +485,53 @@ createNativeRaster(void *object, int32 offset, int32)
|
|||
{
|
||||
Gl3Raster *ras = PLUGINOFFSET(Gl3Raster, object, offset);
|
||||
ras->texid = 0;
|
||||
ras->fbo = 0;
|
||||
ras->fboMate = nil;
|
||||
return object;
|
||||
}
|
||||
|
||||
static void*
|
||||
destroyNativeRaster(void *object, int32 offset, int32)
|
||||
{
|
||||
Gl3Raster *ras = PLUGINOFFSET(Gl3Raster, object, offset);
|
||||
Raster *raster = (Raster*)object;
|
||||
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, object, offset);
|
||||
#ifdef RW_OPENGL
|
||||
glDeleteTextures(1, &ras->texid);
|
||||
switch(raster->type){
|
||||
case Raster::NORMAL:
|
||||
case Raster::TEXTURE:
|
||||
glDeleteTextures(1, &natras->texid);
|
||||
break;
|
||||
|
||||
case Raster::CAMERATEXTURE:
|
||||
if(natras->fboMate){
|
||||
// Break apart from currently associated zbuffer
|
||||
Gl3Raster *zras = PLUGINOFFSET(Gl3Raster, natras->fboMate, offset);
|
||||
zras->fboMate = nil;
|
||||
natras->fboMate = nil;
|
||||
}
|
||||
glDeleteFramebuffers(1, &natras->fbo);
|
||||
glDeleteTextures(1, &natras->texid);
|
||||
break;
|
||||
|
||||
case Raster::ZBUFFER:
|
||||
if(natras->fboMate){
|
||||
// Detatch from FBO we may be attached to
|
||||
Gl3Raster *oldfb = PLUGINOFFSET(Gl3Raster, natras->fboMate, nativeRasterOffset);
|
||||
if(oldfb->fbo){
|
||||
bindFramebuffer(oldfb->fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
oldfb->fboMate = nil;
|
||||
}
|
||||
glDeleteTextures(1, &natras->texid);
|
||||
break;
|
||||
|
||||
case Raster::CAMERA:
|
||||
break;
|
||||
}
|
||||
natras->texid = 0;
|
||||
natras->fbo = 0;
|
||||
|
||||
#endif
|
||||
return object;
|
||||
}
|
||||
|
@ -474,6 +541,8 @@ copyNativeRaster(void *dst, void *, int32 offset, int32)
|
|||
{
|
||||
Gl3Raster *d = PLUGINOFFSET(Gl3Raster, dst, offset);
|
||||
d->texid = 0;
|
||||
d->fbo = 0;
|
||||
d->fboMate = nil;
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
|
|
@ -184,6 +184,7 @@ void setTexture(int32 n, Texture *tex);
|
|||
void setAlphaBlend(bool32 enable);
|
||||
bool32 getAlphaBlend(void);
|
||||
|
||||
void bindFramebuffer(uint32 fbo);
|
||||
uint32 bindTexture(uint32 texid);
|
||||
|
||||
void flushCache(void);
|
||||
|
@ -235,6 +236,9 @@ struct Gl3Raster
|
|||
uint8 filterMode;
|
||||
uint8 addressU;
|
||||
uint8 addressV;
|
||||
|
||||
uint32 fbo; // used for camera texture only!
|
||||
Raster *fboMate; // color or zbuffer raster mate of this one
|
||||
};
|
||||
|
||||
Texture *readNativeTexture(Stream *stream);
|
||||
|
|
Loading…
Reference in New Issue