]> git.tdb.fi Git - libs/gl.git/blob - source/framebuffer.cpp
Add get_width() / get_height() methods to Renderbuffer and Framebuffer
[libs/gl.git] / source / framebuffer.cpp
1 /* $Id$
2
3 This file is part of libmspgl
4 Copyright © 2007  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include "extension.h"
9 #include "ext_framebuffer_object.h"
10 #include "framebuffer.h"
11 #include "misc.h"
12 #include "renderbuffer.h"
13 #include "texture2d.h"
14
15 using namespace std;
16
17 namespace Msp {
18 namespace GL {
19
20 Framebuffer::Framebuffer():
21         width(0),
22         height(0)
23 {
24         static RequireExtension _ext("GL_EXT_framebuffer_object");
25
26         glGenFramebuffersEXT(1, &id);
27         bind();
28 }
29
30 Framebuffer::~Framebuffer()
31 {
32         glDeleteFramebuffersEXT(1, &id);
33 }
34
35 void Framebuffer::bind() const
36 {
37         if(!cur_fbo)
38                 get(GL_VIEWPORT, sys_viewport);
39         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
40         cur_fbo=this;
41         if(width && height)
42                 viewport(0, 0, width, height);
43 }
44
45 void Framebuffer::attach(FramebufferAttachment attch, Renderbuffer &rbuf)
46 {
47         maybe_bind();
48         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch, GL_RENDERBUFFER_EXT, rbuf.get_id());
49         get_or_create_attachment(attch)=rbuf;
50         check_size();
51 }
52
53 void Framebuffer::attach(FramebufferAttachment attch, Texture2D &tex, int level)
54 {
55         maybe_bind();
56         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch, tex.get_target(), tex.get_id(), level);
57         get_or_create_attachment(attch)=tex;
58         check_size();
59 }
60
61 void Framebuffer::detach(FramebufferAttachment attch)
62 {
63         maybe_bind();
64         for(vector<Attachment>::iterator i=attachments.begin(); i!=attachments.end(); ++i)
65                 if(i->attachment==attch)
66                 {
67                         if(i->type==GL_RENDERBUFFER_EXT)
68                                 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch, GL_RENDERBUFFER_EXT, 0);
69                         else if(i->type==GL_TEXTURE_2D)
70                                 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch, GL_TEXTURE_2D, 0, 0);
71                         attachments.erase(i);
72                         check_size();
73                         return;
74                 }
75 }
76
77 FramebufferStatus Framebuffer::check_status() const
78 {
79         maybe_bind();
80         return static_cast<FramebufferStatus>(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
81 }
82
83 const Framebuffer *Framebuffer::current()
84 {
85         return cur_fbo;
86 }
87
88 void Framebuffer::unbind()
89 {
90         if(cur_fbo)
91         {
92                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
93                 cur_fbo=0;
94                 viewport(sys_viewport[0], sys_viewport[1], sys_viewport[2], sys_viewport[3]);
95         }
96 }
97
98 void Framebuffer::maybe_bind() const
99 {
100         if(cur_fbo!=this)
101                 bind();
102 }
103
104 Framebuffer::Attachment &Framebuffer::get_or_create_attachment(FramebufferAttachment attch)
105 {
106         for(vector<Attachment>::iterator i=attachments.begin(); i!=attachments.end(); ++i)
107                 if(i->attachment==attch)
108                         return *i;
109         attachments.push_back(Attachment(attch));
110         return attachments.back();
111 }
112
113 void Framebuffer::check_size()
114 {
115         if(!attachments.empty())
116         {
117                 const Attachment &attch=attachments.front();
118                 if(attch.type==GL_RENDERBUFFER_EXT)
119                 {
120                         width=attch.rbuf->get_width();
121                         height=attch.rbuf->get_height();
122                 }
123                 else if(attch.type==GL_TEXTURE_2D)
124                 {
125                         Texture2D *tex=static_cast<Texture2D *>(attch.tex);
126                         width=tex->get_width();
127                         height=tex->get_height();
128                 }
129                 if(cur_fbo==this)
130                         viewport(0, 0, width, height);
131         }
132 }
133
134 const Framebuffer *Framebuffer::cur_fbo=0;
135 int Framebuffer::sys_viewport[4]={ 0, 0, 1, 1 };
136
137
138 Framebuffer::Attachment::Attachment(FramebufferAttachment a):
139         attachment(a),
140         type(0)
141 { }
142
143 Framebuffer::Attachment &Framebuffer::Attachment::operator=(Renderbuffer &r)
144 {
145         type=GL_RENDERBUFFER_EXT;
146         rbuf=&r;
147         return *this;
148 }
149
150 Framebuffer::Attachment &Framebuffer::Attachment::operator=(Texture &t)
151 {
152         type=t.get_target();
153         tex=&t;
154         return *this;
155 }
156
157
158 void viewport(int x, int y, unsigned w, unsigned h)
159 {
160         glViewport(x, y, w, h);
161 }
162
163 void clear(BufferBits bits)
164 {
165         glClear(bits);
166 }
167
168 void draw_buffer(RWBuffer buf)
169 {
170         glDrawBuffer(buf);
171 }
172
173 void read_buffer(RWBuffer buf)
174 {
175         glReadBuffer(buf);
176 }
177
178 } // namespace GL
179 } // namespace Msp