]> git.tdb.fi Git - libs/gl.git/blob - source/framebuffer.cpp
Rework Bind and enable it to restore the old binding
[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         const Framebuffer *old = current();
38         if(set_current(this))
39         {
40                 if(!old)
41                         get(GL_VIEWPORT, sys_viewport);
42                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
43                 if(width && height)
44                         viewport(0, 0, width, height);
45         }
46 }
47
48 void Framebuffer::attach(FramebufferAttachment attch, Renderbuffer &rbuf)
49 {
50         bind();
51         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch, GL_RENDERBUFFER_EXT, rbuf.get_id());
52         get_or_create_attachment(attch) = rbuf;
53         check_size();
54 }
55
56 void Framebuffer::attach(FramebufferAttachment attch, Texture2D &tex, int level)
57 {
58         bind();
59         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch, tex.get_target(), tex.get_id(), level);
60         get_or_create_attachment(attch) = tex;
61         check_size();
62 }
63
64 void Framebuffer::detach(FramebufferAttachment attch)
65 {
66         bind();
67         for(vector<Attachment>::iterator i=attachments.begin(); i!=attachments.end(); ++i)
68                 if(i->attachment==attch)
69                 {
70                         if(i->type==GL_RENDERBUFFER_EXT)
71                                 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch, GL_RENDERBUFFER_EXT, 0);
72                         else if(i->type==GL_TEXTURE_2D)
73                                 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch, GL_TEXTURE_2D, 0, 0);
74                         attachments.erase(i);
75                         check_size();
76                         return;
77                 }
78 }
79
80 FramebufferStatus Framebuffer::check_status() const
81 {
82         bind();
83         return static_cast<FramebufferStatus>(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
84 }
85
86 void Framebuffer::unbind()
87 {
88         if(set_current(0))
89         {
90                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
91                 viewport(sys_viewport[0], sys_viewport[1], sys_viewport[2], sys_viewport[3]);
92         }
93 }
94
95 Framebuffer::Attachment &Framebuffer::get_or_create_attachment(FramebufferAttachment attch)
96 {
97         for(vector<Attachment>::iterator i=attachments.begin(); i!=attachments.end(); ++i)
98                 if(i->attachment==attch)
99                         return *i;
100         attachments.push_back(Attachment(attch));
101         return attachments.back();
102 }
103
104 void Framebuffer::check_size()
105 {
106         if(!attachments.empty())
107         {
108                 const Attachment &attch = attachments.front();
109                 if(attch.type==GL_RENDERBUFFER_EXT)
110                 {
111                         width = attch.rbuf->get_width();
112                         height = attch.rbuf->get_height();
113                 }
114                 else if(attch.type==GL_TEXTURE_2D)
115                 {
116                         Texture2D *tex = static_cast<Texture2D *>(attch.tex);
117                         width = tex->get_width();
118                         height = tex->get_height();
119                 }
120                 if(current()==this)
121                         viewport(0, 0, width, height);
122         }
123 }
124
125 int Framebuffer::sys_viewport[4] = { 0, 0, 1, 1 };
126
127
128 Framebuffer::Attachment::Attachment(FramebufferAttachment a):
129         attachment(a),
130         type(0)
131 { }
132
133 Framebuffer::Attachment &Framebuffer::Attachment::operator=(Renderbuffer &r)
134 {
135         type = GL_RENDERBUFFER_EXT;
136         rbuf = &r;
137         return *this;
138 }
139
140 Framebuffer::Attachment &Framebuffer::Attachment::operator=(Texture &t)
141 {
142         type = t.get_target();
143         tex = &t;
144         return *this;
145 }
146
147
148 void viewport(int x, int y, unsigned w, unsigned h)
149 {
150         glViewport(x, y, w, h);
151 }
152
153 void clear(BufferBits bits)
154 {
155         glClear(bits);
156 }
157
158 void draw_buffer(RWBuffer buf)
159 {
160         glDrawBuffer(buf);
161 }
162
163 void read_buffer(RWBuffer buf)
164 {
165         glReadBuffer(buf);
166 }
167
168 } // namespace GL
169 } // namespace Msp