+#include <assert.h>
#include "rtarg.h"
struct RTStackItem {
return rstack[rtop].rt;
}
-bool push_render_target(RenderTarget *rt)
+bool push_render_target(RenderTarget *rt, unsigned int flags)
{
if(!rt) {
error_log("push_render_target(0) is invalid\n");
warning_log("push_render_target: overflow\n");
return false;
}
- int *vp = rstack[rtop + 1].saved_vp;
- RenderTarget *prev = current_render_target();
- if(prev) {
- vp[0] = vp[1] = 0;
- vp[2] = prev->get_width();
- vp[3] = prev->get_height();
- } else {
- memcpy(vp, rstack[rtop].saved_vp, 4 * sizeof(int));
+ if(!(flags & RT_NO_VPORT)) {
+ int *vp = rstack[rtop + 1].saved_vp;
+ glGetIntegerv(GL_VIEWPORT, vp);
}
rstack[++rtop].rt = rt;
+
+ if(!(flags & RT_NO_BIND)) {
+ rt->bind();
+ }
return true;
}
-bool pop_render_target()
+bool pop_render_target(unsigned int flags)
{
if(rtop <= 0) {
- error_log("pop_render_target: undeflow\n");
+ error_log("pop_render_target: underflow\n");
return false;
}
- int *vp = rstack[rtop].saved_vp;
- glViewport(vp[0], vp[1], vp[2], vp[3]);
+ if(!(flags & RT_NO_VPORT)) {
+ int *vp = rstack[rtop].saved_vp;
+ glViewport(vp[0], vp[1], vp[2], vp[3]);
+ }
+
+ --rtop;
- if(rstack[--rtop].rt) {
- rstack[rtop].rt->bind();
- } else {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ if(!(flags & RT_NO_BIND)) {
+ if(rstack[rtop].rt) {
+ rstack[rtop].rt->bind(RT_NO_VPORT);
+ } else {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
}
return true;
}
{
fbo = 0;
rbdepth = 0;
+ rbdepth_fmt = 0;
width = height = tex_width = tex_height = 0;
auto_vport = true;
rtcount = 0;
+ own_fbo = true;
for(int i=0; i<4; i++) {
tex[i] = 0;
own_texture[i] = true;
}
+ depth = 0;
}
RenderTarget::~RenderTarget()
{
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ own_fbo = true;
width = xsz;
height = ysz;
tex[i]->create(tex_width, tex_height, TEX_2D, fmt);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
tex[i]->get_id(), 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
own_texture[i] = true;
}
} else {
}
if(flags & (RT_DEPTH | RT_STENCIL)) {
- unsigned int fmt, attachment;
+ unsigned int attachment;
glGenRenderbuffers(1, &rbdepth);
glBindRenderbuffer(GL_RENDERBUFFER, rbdepth);
switch(flags & (RT_DEPTH | RT_STENCIL)) {
case RT_DEPTH:
- fmt = GL_DEPTH_COMPONENT24;
+ rbdepth_fmt = GL_DEPTH_COMPONENT24;
attachment = GL_DEPTH_ATTACHMENT;
break;
case RT_STENCIL:
- fmt = GL_STENCIL_INDEX8;
+ rbdepth_fmt = GL_STENCIL_INDEX8;
attachment = GL_STENCIL_ATTACHMENT;
break;
case RT_DEPTH | RT_STENCIL:
- fmt = GL_DEPTH24_STENCIL8;
+ rbdepth_fmt = GL_DEPTH24_STENCIL8;
attachment = GL_DEPTH_STENCIL_ATTACHMENT;
break;
}
- glRenderbufferStorage(GL_RENDERBUFFER, fmt, width, height);
+ glRenderbufferStorage(GL_RENDERBUFFER, rbdepth_fmt, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbdepth);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
} else if(depth) {
attach_depth_texture(depth);
return true;
}
+bool RenderTarget::create_wrap_fbo(unsigned int fbo, int xsz, int ysz)
+{
+ this->fbo = fbo;
+ own_fbo = false;
+
+ width = tex_width = xsz;
+ height = tex_height = ysz;
+ rtcount = 1;
+
+ texmat = Mat4::identity;
+
+ return true;
+}
+
void RenderTarget::destroy()
{
for(int i=0; i<4; i++) {
glDeleteRenderbuffers(1, &rbdepth);
rbdepth = 0;
}
- if(fbo) {
+ if(fbo && own_fbo) {
glDeleteFramebuffers(1, &fbo);
fbo = 0;
}
}
+bool RenderTarget::resize(int xsz, int ysz)
+{
+ if(!own_fbo) return false; /* TODO */
+
+ int new_tx = next_pow2(xsz);
+ int new_ty = next_pow2(ysz);
+
+ if(new_tx != tex_width || new_ty != tex_height) {
+ tex_width = new_tx;
+ tex_height = new_ty;
+
+ for(int i=0; i<4; i++) {
+ if(tex[i]) {
+ tex[i]->create(new_tx, new_ty, TEX_2D, tex[i]->get_format());
+ }
+ }
+
+ if(depth) {
+ depth->create(new_tx, new_ty, TEX_2D, depth->get_format());
+ }
+ }
+
+ if(rbdepth) {
+ glBindRenderbuffer(GL_RENDERBUFFER, rbdepth);
+ glRenderbufferStorage(GL_RENDERBUFFER, rbdepth_fmt, xsz, ysz);
+ }
+
+ width = xsz;
+ height = ysz;
+ return true;
+}
+
int RenderTarget::get_width() const
{
return width;
return auto_vport;
}
-void RenderTarget::bind() const
+void RenderTarget::bind(unsigned int flags) const
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- if(auto_vport) {
+ if(auto_vport && !(flags & RT_NO_VPORT)) {
glViewport(0, 0, width, height);
}
}
default:
error_log("failed to attach depth/stencil texture: unexpected texture format: %x\n", fmt);
- break;
+ return;
}
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex->get_id(), 0);