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):
22 Framebuffer::Framebuffer():
23 FramebufferBackend(false)
26 Framebuffer::Framebuffer(FrameAttachment fa):
32 Framebuffer::Framebuffer(const FrameFormat &f):
38 void Framebuffer::set_format(const FrameFormat &fmt)
41 throw invalid_operation("Framebuffer::set_format");
42 if(fmt.empty() || !is_format_supported(fmt))
43 throw invalid_argument("Framebuffer::set_format");
46 attachments.resize(format.size());
47 format_changed(format);
50 void Framebuffer::update() const
52 FramebufferBackend::update(dirty);
56 void Framebuffer::check_size()
59 for(Attachment &a: attachments)
65 if(const Texture2D *tex2d = dynamic_cast<const Texture2D *>(a.tex))
67 w = max(tex2d->get_width()>>a.level, 1U);
68 h = max(tex2d->get_height()>>a.level, 1U);
70 else if(const Texture2DMultisample *tex2d_ms = dynamic_cast<const Texture2DMultisample *>(a.tex))
72 w = tex2d_ms->get_width();
73 h = tex2d_ms->get_height();
75 else if(const Texture3D *tex3d = dynamic_cast<const Texture3D *>(a.tex))
77 w = max(tex3d->get_width()>>a.level, 1U);
78 h = max(tex3d->get_height()>>a.level, 1U);
79 l = (a.layer<0 ? tex3d->get_depth() : 1);
81 else if(const TextureCube *tex_cube = dynamic_cast<const TextureCube *>(a.tex))
83 w = max(tex_cube->get_size()>>a.level, 1U);
85 l = (a.layer<0 ? 6 : 1);
97 width = min(width, w);
98 height = min(height, h);
99 layers = min(layers, l);
104 void Framebuffer::set_attachment(FrameAttachment attch, Texture &tex, Texture *res, unsigned level, int layer, unsigned samples)
106 if(format.empty() || attachments.empty())
107 throw invalid_operation("Framebuffer::attach");
109 if((format.get_samples()>1 && samples!=format.get_samples()) || (format.get_samples()==1 && samples))
110 throw incompatible_data("Framebuffer::attach");
113 for(FrameAttachment a: format)
117 attachments[i].set(tex, res, level, layer);
125 throw incompatible_data("Framebuffer::attach");
128 void Framebuffer::attach(FrameAttachment attch, Texture2D &tex, unsigned level)
130 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, 0, level, 0, 0);
133 void Framebuffer::attach(FrameAttachment attch, Texture2DMultisample &tex, Texture2D *res)
135 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, res, 0, 0, tex.get_samples());
138 void Framebuffer::attach(FrameAttachment attch, Texture3D &tex, unsigned layer, unsigned level)
140 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, 0, level, layer, 0);
143 void Framebuffer::attach(FrameAttachment attch, TextureCube &tex, TextureCubeFace face, unsigned level)
145 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, 0, level, face, 0);
148 void Framebuffer::attach_layered(FrameAttachment attch, Texture3D &tex, unsigned level)
151 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, 0, level, -1, 0);
154 void Framebuffer::attach_layered(FrameAttachment attch, TextureCube &tex, unsigned level)
157 set_attachment(make_typed_attachment(attch, tex.get_format()), tex, 0, level, -1, 0);
160 void Framebuffer::detach(FrameAttachment attch)
162 if(attachments.empty())
163 throw invalid_operation("Framebuffer::detach");
165 int i = format.index(attch);
168 attachments[i].clear();
174 const Texture *Framebuffer::get_attachment(FrameAttachment attch) const
176 if(attachments.empty())
179 int i = format.index(attch);
180 return (i>=0 ? attachments[i].tex : 0);
183 const Texture *Framebuffer::get_attachment(unsigned i) const
185 return (i<attachments.size() ? attachments[i].tex : 0);
188 const Texture *Framebuffer::get_resolve_attachment(FrameAttachment attch) const
190 if(attachments.empty())
193 int i = format.index(attch);
194 return (i>=0 ? attachments[i].resolve : 0);
197 const Texture *Framebuffer::get_resolve_attachment(unsigned i) const
199 return (i<attachments.size() ? attachments[i].resolve : 0);
202 bool Framebuffer::has_resolve_attachments() const
204 for(const Attachment &a: attachments)
210 void Framebuffer::require_complete() const
212 bool layered = (!attachments.empty() && attachments.front().layer<0);
213 for(const Attachment &a: attachments)
216 throw framebuffer_incomplete("missing attachment");
217 if(layered!=(a.layer<0))
218 throw framebuffer_incomplete("inconsistent layering");
221 FramebufferBackend::require_complete();
225 void Framebuffer::Attachment::set(Texture &t, Texture *r, unsigned l, int z)
233 void Framebuffer::Attachment::clear()