Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
framebufferobject.cc
Go to the documentation of this file.
1 
19 
20 #include "ion/base/invalid.h"
21 #include "ion/base/static_assert.h"
22 #include "ion/gfx/image.h"
23 #include "ion/portgfx/glheaders.h"
24 
25 namespace ion {
26 namespace gfx {
27 
28 namespace {
29 
30 static bool IsValid(Image::Format format) {
31  return static_cast<uint32>(format) < Image::kNumFormats;
32 }
33 
34 static bool IsColorFormatRenderable(Image::Format format) {
35  return IsValid(format)
37  Image::GetPixelFormat(format).internal_format) ||
38  format == Image::kEglImage
39  : false;
40 }
41 
42 static bool IsDepthFormatRenderable(Image::Format format) {
43  return IsValid(format)
45  Image::GetPixelFormat(format).internal_format) ||
46  format == Image::kEglImage
47  : false;
48 }
49 
50 static bool IsStencilFormatRenderable(Image::Format format) {
51  return IsValid(format)
53  Image::GetPixelFormat(format).internal_format) ||
54  format == Image::kEglImage
55  : false;
56 }
57 
60 static bool IsAttachmentNotifier(
61  const base::Notifier* notifier,
62  const FramebufferObject::Attachment& attachment) {
63  return notifier == attachment.GetTexture().Get() ||
64  notifier == attachment.GetCubeMapTexture().Get() ||
65  notifier == attachment.GetImage().Get();
66 }
67 
68 static CubeMapTexture::CubeFace kInvalidFace =
70 
71 } // anonymous namespace
72 
74  Construct(kUnbound, 0, kInvalidFace);
75 }
76 
78  Image::Format format, size_t samples) {
79  Construct(kRenderbuffer, 0, kInvalidFace);
80  format_ = format;
81  samples_ = samples;
82 }
83 
85  Construct(kRenderbuffer, 0, kInvalidFace);
86  format_ = format_in;
87 }
88 
90  const ImagePtr& image_in) : image_(image_in) {
91  Construct(image_.Get() && image_->GetFormat() == Image::kEglImage &&
92  (image_->GetType() == Image::kEgl ||
93  image_->GetType() == Image::kExternalEgl)
95  : kUnbound,
96  0, kInvalidFace);
97 }
98 
100  const TexturePtr& texture_in) : texture_(texture_in) {
101  Construct(texture_.Get() ? kTexture : kUnbound, 0, kInvalidFace);
102 }
103 
105  const TexturePtr& texture_in, size_t mip_level)
106  : texture_(texture_in) {
107  Construct(texture_.Get() ? kTexture : kUnbound, mip_level, kInvalidFace);
108 }
109 
111  const CubeMapTexturePtr& cubemap_in, CubeMapTexture::CubeFace face)
112  : cubemap_(cubemap_in) {
113  Construct(cubemap_.Get() ? kCubeMapTexture : kUnbound, 0, face);
114 }
115 
117  const CubeMapTexturePtr& cubemap_in,
119  size_t mip_level) : cubemap_(cubemap_in) {
120  Construct(cubemap_.Get() ? kCubeMapTexture : kUnbound, mip_level, face);
121 }
122 
123 ION_API void FramebufferObject::Attachment::Construct(
124  AttachmentBinding binding,
125  size_t mip_level,
127  binding_ = binding;
128  mip_level_ = mip_level;
129  face_ = face;
130  format_ = static_cast<Image::Format>(base::kInvalidIndex);
131  samples_ = 0;
132 }
133 
135  Image::Format format = format_;
136  if (Texture* tex = texture_.Get()) {
137  if (tex->HasImage(0))
138  format = tex->GetImage(0)->GetFormat();
139  else
140  format = Image::kRgba8888;
141  } else if (CubeMapTexture* tex = cubemap_.Get()) {
142  if (tex->HasImage(face_, 0))
143  format = tex->GetImage(face_, 0)->GetFormat();
144  else
145  format = Image::kRgba8888;
146  } else if (image_.Get()) {
147  format = image_->GetFormat();
148  }
149  return format;
150 }
151 
153  : width_(kDimensionsChanged, width, this),
154  height_(kDimensionsChanged, height, this),
155  color0_(kColorAttachmentChanged, Attachment(), this),
156  depth_(kDepthAttachmentChanged, Attachment(), this),
157  stencil_(kStencilAttachmentChanged, Attachment(), this) {
158  if (width_.Get() == 0 || height_.Get() == 0)
159  LOG(ERROR) << "Framebuffer created with zero width or height; it will be"
160  << " ignored if used for rendering.";
161 }
162 
164  SetAttachment(&color0_, IsColorFormatRenderable, Attachment(), "color");
165  SetAttachment(&depth_, IsDepthFormatRenderable, Attachment(), "depth");
166  SetAttachment(&stencil_, IsStencilFormatRenderable, Attachment(), "stencil");
167 }
168 
169 void FramebufferObject::Resize(uint32 width, uint32 height) {
170  width_.Set(width);
171  height_.Set(height);
172 }
173 
174 void FramebufferObject::SetColorAttachment(size_t i, const Attachment& color) {
175  DCHECK_EQ(0U, i) << "***ION: Only a single color attachment is supported";
176  SetAttachment(&color0_, IsColorFormatRenderable, color, "color");
177 }
178 
180  SetAttachment(&depth_, IsDepthFormatRenderable, depth, "depth");
181 }
182 
184  SetAttachment(&stencil_, IsStencilFormatRenderable, stencil, "stencil");
185 }
186 
188  bool renderable = false;
189  switch (format) {
190  case GL_RGB16F: case GL_RGB32F: case GL_RGBA16F: case GL_RGBA32F:
191  case GL_RGB: case GL_RGBA: case GL_R8: case GL_R8UI: case GL_R8I:
192  case GL_R16UI: case GL_R16I: case GL_R32UI: case GL_R32I: case GL_RG8:
193  case GL_RG8UI: case GL_RG8I: case GL_RG16UI: case GL_RG16I:
194  case GL_RG32UI: case GL_RG32I: case GL_RGB8: case GL_RGB565:
195  case GL_RGB5_A1: case GL_RGBA4: case GL_RGB10_A2: case GL_RGB10_A2UI:
196  case GL_RGBA8: case GL_SRGB8_ALPHA8: case GL_RGBA8UI: case GL_RGBA8I:
197  case GL_RGBA16UI: case GL_RGBA16I: case GL_RGBA32I: case GL_RGBA32UI:
198  renderable = true;
199  break;
200 
201  default:
202  break;
203  }
204  return renderable;
205 }
206 
208  return format == GL_DEPTH_COMPONENT || format == GL_DEPTH_COMPONENT16 ||
209  format == GL_DEPTH_COMPONENT24 || format == GL_DEPTH_COMPONENT32F ||
210  format == GL_DEPTH24_STENCIL8 || format == GL_DEPTH32F_STENCIL8;
211 }
212 
214  return format == GL_DEPTH24_STENCIL8 || format == GL_DEPTH32F_STENCIL8 ||
215  format == GL_STENCIL_INDEX8;
216 }
217 
218 void FramebufferObject::OnNotify(const base::Notifier* notifier) {
219  if (GetResourceCount()) {
220  if (IsAttachmentNotifier(notifier, color0_.Get())) {
222  } else if (IsAttachmentNotifier(notifier, depth_.Get())) {
224  } else if (IsAttachmentNotifier(notifier, stencil_.Get())) {
226  }
227  }
228 }
229 
230 void FramebufferObject::SetAttachment(Field<Attachment>* field,
231  bool (*validator)(Image::Format),
232  const Attachment& attachment,
233  const std::string& type_name) {
235  if (Texture* tex = field->Get().GetTexture().Get())
236  tex->RemoveReceiver(this);
237  else if (CubeMapTexture* tex = field->Get().GetCubeMapTexture().Get())
238  tex->RemoveReceiver(this);
239  else if (Image* img = field->Get().GetImage().Get())
240  img->RemoveReceiver(this);
241 
242  if (attachment.GetBinding() != kUnbound &&
243  !validator(attachment.GetFormat())) {
244  LOG(ERROR) << "Invalid " << type_name << " attachment format "
245  << Image::GetFormatString(attachment.GetFormat());
246  field->Set(Attachment());
247  } else {
248  if (Texture* tex = attachment.GetTexture().Get())
249  tex->AddReceiver(this);
250  else if (CubeMapTexture* tex = attachment.GetCubeMapTexture().Get())
251  tex->AddReceiver(this);
252  else if (Image* img = attachment.GetImage().Get())
253  img->AddReceiver(this);
254  field->Set(attachment);
255  }
256 }
257 
258 } // namespace gfx
259 } // namespace ion
A Texture object represents the image data and mipmaps associated with a single texture.
Definition: texture.h:264
Format
Supported image formats.
Definition: image.h:38
const size_t kInvalidIndex
kInvalidIndex is a size_t value that is very unlikely to be a valid index.
Definition: invalid.cc:23
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
Definition: logging.h:216
A Notifier both sends notifications to and receives notifications from other Notifiers.
Definition: notifier.h:35
CubeFace
The names of faces of the cube map.
void SetDepthAttachment(const Attachment &attachment)
~FramebufferObject() override
The destructor is protected because all base::Referent classes must have protected or private destruc...
AttachmentBinding
The type of binding for an Attachment.
static bool IsStencilRenderable(uint32 gl_format)
void OnChanged(int bit) const
Forwards OnChanged to all resources.
FramebufferObject(uint32 width, uint32 height)
Creates a FramebufferObject with the passed dimensions and unbound attachments.
T * Get() const
Returns a raw pointer to the instance, which may be NULL.
Definition: sharedptr.h:89
void Resize(uint32 width, uint32 height)
Resizes the FramebufferObject to the passed dimensions.
static const PixelFormat & GetPixelFormat(Format format)
Convenience function that returns a PixelFormat given a Format.
Definition: image.cc:76
4444 uint16 data.
Definition: image.h:166
void SetStencilAttachment(const Attachment &attachment)
static bool IsDepthRenderable(uint32 gl_format)
Attachment()
Creates an unbound Attachment.
int width
#define DCHECK_EQ(val1, val2)
Definition: logging.h:332
A CubeMapTexture object represents the image data and mipmaps associated with the six faces of a cube...
int GetResourceCount() const
Returns the number of resources that this holder holds.
void SetColorAttachment(size_t i, const Attachment &attachment)
An attachment represents a data store attached to one of the framebuffer's targets.
static bool IsColorRenderable(uint32 gl_format)
Returns whether the passed GL formats are renderable.
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
Definition: sharedptr.h:60
static const uint32 kNumFormats
Definition: image.h:198
static const char * GetFormatString(Format format)
Convenience function that returns a string representing the name of a given Format.
Definition: image.cc:221
Image::Format GetFormat() const
Gets the format of the attachment, which is the texture format if it is a texture attachment...