vrseasons

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