buldthensnip/src/lua_fbo.h

188 lines
5.2 KiB
C

/*
This file is part of Iceball.
Iceball is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Iceball is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
*/
int fbo_gc_lua(lua_State *L)
{
fbo_t *fbo = lua_touserdata(L, 1);
if(fbo != NULL)
{
printf("Freeing fbo @ %p\n", fbo);
#ifndef DEDI
if(fbo->ctex != 0)
glDeleteTextures(1, &(fbo->ctex));
if(fbo->dstex != 0)
glDeleteTextures(1, &(fbo->dstex));
if(fbo->handle != 0)
glDeleteFramebuffers(1, &(fbo->handle));
#endif
}
return 0;
}
int icelua_fn_client_gfx_fbo_available(lua_State *L)
{
int top = icelua_assert_stack(L, 0, 0);
#ifdef DEDI
return luaL_error(L, "EDOOFUS: why the hell is this being called in the dedi version?");
#else
// XXX: We will only cover the EXT version if someone needs it.
// I suspect GLEW ends up wrapping it to the ARB version anyway.
lua_pushboolean(L, gl_use_fbo && (GLAD_GL_ARB_framebuffer_object));
return 1;
#endif
}
int icelua_fn_client_fbo_create(lua_State *L)
{
int top = icelua_assert_stack(L, 3, 3);
int w = lua_tointeger(L, 1);
int h = lua_tointeger(L, 2);
int use_stencil = lua_toboolean(L, 3);
#ifdef DEDI
return luaL_error(L, "EDOOFUS: why the hell is this being called in the dedi version?");
#else
if(!gl_use_fbo)
return luaL_error(L, "FBOs not enabled!");
if(!(GLAD_GL_ARB_framebuffer_object))
return luaL_error(L, "FBOs not supported by this GPU!");
// Generate object handles
GLuint handle;
GLuint ctex, dstex;
glGenTextures(1, &ctex);
glGenTextures(1, &dstex);
glGenFramebuffers(1, &handle);
// Create FBO and textures
glBindFramebuffer(GL_FRAMEBUFFER, handle);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, ctex);
glGetError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if(GLAD_GL_ARB_texture_storage)
{
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
glFinish();
int err_ctex = glGetError();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ctex, 0);
glBindTexture(GL_TEXTURE_2D, dstex);
glGetError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if(GLAD_GL_ARB_texture_storage)
{
if(use_stencil)
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, w, h);
else
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT24, w, h);
} else {
if(use_stencil)
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, w, h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
}
glFinish();
int err_dstex = glGetError();
printf("FBO tex err results: %i %i\n", err_ctex, err_dstex);
if(use_stencil)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dstex, 0);
else
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dstex, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
printf("FBO validation: %04X (%04X == complete)\n", status, GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
printf("FRAMEBUFFER NOT COMPLETE - cleaning up and returning nil\n");
// Clean up
glDeleteTextures(1, &ctex);
glDeleteTextures(1, &dstex);
glDeleteFramebuffers(1, &handle);
lua_pushnil(L);
return 1;
}
// Create fbo_t
fbo_t *fbo = lua_newuserdata(L, sizeof(fbo_t));
fbo->udtype = UD_FBO;
fbo->handle = handle;
fbo->ctex = ctex;
fbo->dstex = dstex;
fbo->width = w;
fbo->height = h;
lua_newtable(L);
lua_pushcfunction(L, fbo_gc_lua);
lua_setfield(L, -2, "__gc");
lua_setmetatable(L, -2);
// Return!
return 1;
#endif
}
int icelua_fn_client_fbo_use(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 1);
#ifdef DEDI
return luaL_error(L, "EDOOFUS: why the hell is this being called in the dedi version?");
#else
if(!gl_use_fbo)
return luaL_error(L, "FBOs not enabled!");
if(!(GLAD_GL_ARB_framebuffer_object))
return luaL_error(L, "FBOs not supported by this GPU!");
if(lua_isnil(L, 1))
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glFinish();
return 0;
}
fbo_t *fbo = lua_touserdata(L, 1);
if(fbo == NULL || fbo->udtype != UD_FBO)
return luaL_error(L, "not an FBO");
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
//glFinish();
return 0;
#endif
}