vrseasons

annotate src/rtarg.cc @ 2:eea1b91dc3d4

added is_complete() to framebuffer object and fixed GL_UNSUPPORTED_FRAMEBUFFER on intel
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 13 Apr 2015 16:51:52 +0300
parents 393ef1143c9c
children
rev   line source
nuclear@2 1 #include <stdio.h>
nuclear@0 2 #include "opengl.h"
nuclear@0 3 #include "rtarg.h"
nuclear@0 4
nuclear@0 5 static int next_pow2(int x);
nuclear@0 6
nuclear@0 7 RenderTarget::RenderTarget()
nuclear@0 8 {
nuclear@0 9 xsz = ysz = 0;
nuclear@0 10 fbo = color = depth = 0;
nuclear@0 11
nuclear@0 12 tex_fmt = 0;
nuclear@0 13 tex_xsz = tex_ysz = 0;
nuclear@0 14 }
nuclear@0 15
nuclear@0 16 RenderTarget::~RenderTarget()
nuclear@0 17 {
nuclear@0 18 destroy();
nuclear@0 19 }
nuclear@0 20
nuclear@0 21 bool RenderTarget::create(int xsz, int ysz)
nuclear@0 22 {
nuclear@0 23 destroy();
nuclear@0 24
nuclear@0 25 this->xsz = xsz;
nuclear@0 26 this->ysz = ysz;
nuclear@0 27
nuclear@0 28 tex_xsz = next_pow2(xsz);
nuclear@0 29 tex_ysz = next_pow2(ysz);
nuclear@2 30 tex_fmt = check_extension("GL_ARB_texture_float") ? GL_RGBA16F : GL_RGBA;
nuclear@0 31
nuclear@0 32 glGenFramebuffers(1, &fbo);
nuclear@0 33 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@0 34
nuclear@0 35 glGenTextures(1, &color);
nuclear@0 36 glBindTexture(GL_TEXTURE_2D, color);
nuclear@0 37 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@0 38 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@2 39 glTexImage2D(GL_TEXTURE_2D, 0, tex_fmt, tex_xsz, tex_ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
nuclear@0 40 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
nuclear@0 41
nuclear@0 42 glGenRenderbuffers(1, &depth);
nuclear@0 43 glBindRenderbuffer(GL_RENDERBUFFER, depth);
nuclear@0 44 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
nuclear@0 45 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
nuclear@0 46
nuclear@2 47 if(!is_complete()) {
nuclear@2 48 fprintf(stderr, "framebuffer incomplete\n");
nuclear@2 49 }
nuclear@2 50
nuclear@0 51 return true;
nuclear@0 52 }
nuclear@0 53
nuclear@0 54 bool RenderTarget::resize(int xsz, int ysz)
nuclear@0 55 {
nuclear@0 56 if(!fbo) {
nuclear@0 57 return create(xsz, ysz);
nuclear@0 58 }
nuclear@0 59
nuclear@0 60 this->xsz = xsz;
nuclear@0 61 this->ysz = ysz;
nuclear@0 62 int new_tex_xsz = next_pow2(xsz);
nuclear@0 63 int new_tex_ysz = next_pow2(ysz);
nuclear@0 64
nuclear@0 65 if(tex_xsz != new_tex_xsz || tex_ysz != new_tex_ysz) {
nuclear@0 66 glBindTexture(GL_TEXTURE_2D, color);
nuclear@0 67 glTexImage2D(GL_TEXTURE_2D, 0, tex_fmt, tex_xsz, tex_ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
nuclear@0 68
nuclear@0 69 glBindRenderbuffer(GL_RENDERBUFFER, depth);
nuclear@0 70 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
nuclear@0 71
nuclear@0 72 tex_xsz = new_tex_xsz;
nuclear@0 73 tex_ysz = new_tex_ysz;
nuclear@2 74
nuclear@2 75 if(!is_complete()) {
nuclear@2 76 fprintf(stderr, "framebuffer incomplete\n");
nuclear@2 77 }
nuclear@0 78 }
nuclear@0 79 return true;
nuclear@0 80 }
nuclear@0 81
nuclear@0 82 void RenderTarget::destroy()
nuclear@0 83 {
nuclear@0 84 if(fbo) {
nuclear@0 85 glDeleteFramebuffers(1, &fbo);
nuclear@0 86 }
nuclear@0 87 if(color) {
nuclear@0 88 glDeleteTextures(1, &color);
nuclear@0 89 }
nuclear@0 90 if(depth) {
nuclear@0 91 glDeleteRenderbuffers(1, &depth);
nuclear@0 92 }
nuclear@0 93 fbo = color = depth = 0;
nuclear@0 94 }
nuclear@0 95
nuclear@0 96 bool RenderTarget::is_valid() const
nuclear@0 97 {
nuclear@0 98 return fbo != 0;
nuclear@0 99 }
nuclear@0 100
nuclear@2 101 bool RenderTarget::is_complete() const
nuclear@2 102 {
nuclear@2 103 if(!fbo) return false;
nuclear@2 104
nuclear@2 105 unsigned int prev_fbo;
nuclear@2 106 glGetIntegerv(GL_FRAMEBUFFER_BINDING, (int*)&prev_fbo);
nuclear@2 107 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@2 108 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
nuclear@2 109 if(prev_fbo != fbo) {
nuclear@2 110 glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo);
nuclear@2 111 }
nuclear@2 112 return status == GL_FRAMEBUFFER_COMPLETE;
nuclear@2 113 }
nuclear@2 114
nuclear@0 115 unsigned int RenderTarget::get_texture() const
nuclear@0 116 {
nuclear@0 117 return color;
nuclear@0 118 }
nuclear@0 119
nuclear@0 120 int RenderTarget::get_width() const
nuclear@0 121 {
nuclear@0 122 return xsz;
nuclear@0 123 }
nuclear@0 124
nuclear@0 125 int RenderTarget::get_height() const
nuclear@0 126 {
nuclear@0 127 return ysz;
nuclear@0 128 }
nuclear@0 129
nuclear@0 130 int RenderTarget::get_tex_width() const
nuclear@0 131 {
nuclear@0 132 return tex_xsz;
nuclear@0 133 }
nuclear@0 134
nuclear@0 135 int RenderTarget::get_tex_height() const
nuclear@0 136 {
nuclear@0 137 return tex_ysz;
nuclear@0 138 }
nuclear@0 139
nuclear@0 140 void set_render_target(const RenderTarget *rtarg)
nuclear@0 141 {
nuclear@0 142 if(rtarg) {
nuclear@0 143 glBindFramebuffer(GL_FRAMEBUFFER, rtarg->color);
nuclear@0 144 } else {
nuclear@0 145 glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@0 146 }
nuclear@0 147 }
nuclear@0 148
nuclear@0 149 static int next_pow2(int x)
nuclear@0 150 {
nuclear@0 151 x--;
nuclear@0 152 x = (x >> 1) | x;
nuclear@0 153 x = (x >> 2) | x;
nuclear@0 154 x = (x >> 4) | x;
nuclear@0 155 x = (x >> 8) | x;
nuclear@0 156 x = (x >> 16) | x;
nuclear@0 157 return x + 1;
nuclear@0 158 }