2 #include "framebuffer.h"
4 #include "texture2dmultisample.h"
6 #include "windowview.h"
13 framebuffer_incomplete::framebuffer_incomplete(const std::string &reason):
18 Framebuffer::Framebuffer(bool s):
19 FramebufferBackend(s),
24 format = get_system_format();
25 get_system_size(width, height);
29 Framebuffer::Framebuffer():
30 FramebufferBackend(false)
35 Framebuffer::Framebuffer(FrameAttachment fa):
36 FramebufferBackend(false)
42 Framebuffer::Framebuffer(const FrameFormat &f):
43 FramebufferBackend(false)
49 void Framebuffer::init()
56 void Framebuffer::set_format(const FrameFormat &fmt)
58 if(!format.empty() || !id)
59 throw invalid_operation("Framebuffer::set_format");
60 if(fmt.empty() || !is_format_supported(fmt))
61 throw invalid_argument("Framebuffer::set_format");
64 attachments.resize(format.size());
67 void Framebuffer::update() const
69 FramebufferBackend::update(dirty);
73 void Framebuffer::check_size()
76 for(Attachment &a: attachments)
81 if(const Texture2D *tex2d = dynamic_cast<const Texture2D *>(a.tex))
83 w = max(tex2d->get_width()>>a.level, 1U);
84 h = max(tex2d->get_height()>>a.level, 1U);
86 else if(const Texture2DMultisample *tex2d_ms = dynamic_cast<const Texture2DMultisample *>(a.tex))
88 w = tex2d_ms->get_width();
89 h = tex2d_ms->get_height();
91 else if(const Texture3D *tex3d = dynamic_cast<const Texture3D *>(a.tex))
93 w = max(tex3d->get_width()>>a.level, 1U);
94 h = max(tex3d->get_height()>>a.level, 1U);
96 else if(const TextureCube *tex_cube = dynamic_cast<const TextureCube *>(a.tex))
98 w = max(tex_cube->get_size()>>a.level, 1U);
110 width = min(width, w);
111 height = min(height, h);
116 void Framebuffer::set_attachment(FrameAttachment attch, Texture &tex, unsigned level, int layer, unsigned samples)
118 if(format.empty() || !id)
119 throw invalid_operation("Framebuffer::attach");
121 if((format.get_samples()>1 && samples!=format.get_samples()) || (format.get_samples()==1 && samples))
122 throw incompatible_data("Framebuffer::attach");
125 for(FrameAttachment a: format)
129 attachments[i].set(tex, level, layer);
137 throw incompatible_data("Framebuffer::attach");
140 void Framebuffer::attach(FrameAttachment attch, Texture2D &tex, unsigned level)
142 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, 0, 0);
145 void Framebuffer::attach(FrameAttachment attch, Texture2DMultisample &tex)
147 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, 0, 0, tex.get_samples());
150 void Framebuffer::attach(FrameAttachment attch, Texture3D &tex, unsigned layer, unsigned level)
152 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, layer, 0);
155 void Framebuffer::attach(FrameAttachment attch, TextureCube &tex, TextureCubeFace face, unsigned level)
157 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, face, 0);
160 void Framebuffer::attach_layered(FrameAttachment attch, Texture3D &tex, unsigned level)
163 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, -1, 0);
166 void Framebuffer::attach_layered(FrameAttachment attch, TextureCube &tex, unsigned level)
169 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, -1, 0);
172 void Framebuffer::detach(FrameAttachment attch)
175 throw invalid_operation("Framebuffer::detach");
177 int i = format.index(attch);
180 attachments[i].clear();
186 void Framebuffer::resize(const WindowView &view)
189 throw invalid_operation("Framebuffer::resize");
191 width = view.get_width();
192 height = view.get_height();
195 void Framebuffer::require_complete() const
200 bool layered = (!attachments.empty() && attachments.front().layer<0);
201 for(const Attachment &a: attachments)
204 throw framebuffer_incomplete("missing attachment");
205 if(layered!=(a.layer<0))
206 throw framebuffer_incomplete("inconsistent layering");
209 FramebufferBackend::require_complete();
212 Framebuffer &Framebuffer::system()
214 static Framebuffer sys_framebuf(true);
219 Framebuffer::Attachment::Attachment():
225 void Framebuffer::Attachment::set(Texture &t, unsigned l, int z)
232 void Framebuffer::Attachment::clear()