1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // FramebufferAttachment.h: Defines the wrapper class gl::FramebufferAttachment, as well as the
8 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
9
10 #ifndef LIBANGLE_FRAMEBUFFERATTACHMENT_H_
11 #define LIBANGLE_FRAMEBUFFERATTACHMENT_H_
12
13 #include "angle_gl.h"
14 #include "common/angleutils.h"
15 #include "libANGLE/Error.h"
16 #include "libANGLE/ImageIndex.h"
17 #include "libANGLE/Observer.h"
18 #include "libANGLE/formatutils.h"
19 #include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
20
21 namespace egl
22 {
23 class Surface;
24 }
25
26 namespace rx
27 {
28 // An implementation-specific object associated with an attachment.
29
30 class FramebufferAttachmentRenderTarget : angle::NonCopyable
31 {
32 public:
FramebufferAttachmentRenderTarget()33 FramebufferAttachmentRenderTarget() {}
~FramebufferAttachmentRenderTarget()34 virtual ~FramebufferAttachmentRenderTarget() {}
35 };
36
37 class FramebufferAttachmentObjectImpl;
38 } // namespace rx
39
40 namespace gl
41 {
42 class FramebufferAttachmentObject;
43 class Renderbuffer;
44 class Texture;
45
46 enum class InitState
47 {
48 MayNeedInit,
49 Initialized,
50 };
51
52 // FramebufferAttachment implements a GL framebuffer attachment.
53 // Attachments are "light" containers, which store pointers to ref-counted GL objects.
54 // We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments.
55 // Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for
56 // framebuffer attachments, which confused their usage.
57
58 class FramebufferAttachment final
59 {
60 public:
61 FramebufferAttachment();
62
63 FramebufferAttachment(const Context *context,
64 GLenum type,
65 GLenum binding,
66 const ImageIndex &textureIndex,
67 FramebufferAttachmentObject *resource);
68
69 FramebufferAttachment(FramebufferAttachment &&other);
70 FramebufferAttachment &operator=(FramebufferAttachment &&other);
71
72 ~FramebufferAttachment();
73
74 void detach(const Context *context);
75 void attach(const Context *context,
76 GLenum type,
77 GLenum binding,
78 const ImageIndex &textureIndex,
79 FramebufferAttachmentObject *resource,
80 GLsizei numViews,
81 GLuint baseViewIndex,
82 bool isMultiview,
83 GLsizei samples);
84
85 // Helper methods
86 GLuint getRedSize() const;
87 GLuint getGreenSize() const;
88 GLuint getBlueSize() const;
89 GLuint getAlphaSize() const;
90 GLuint getDepthSize() const;
91 GLuint getStencilSize() const;
92 GLenum getComponentType() const;
93 GLenum getColorEncoding() const;
94
95 bool isBoundAsSamplerOrImage(ContextID contextID) const;
96
isTextureWithId(TextureID textureId)97 bool isTextureWithId(TextureID textureId) const
98 {
99 return mType == GL_TEXTURE && id() == textureId.value;
100 }
isRenderbufferWithId(GLuint renderbufferId)101 bool isRenderbufferWithId(GLuint renderbufferId) const
102 {
103 return mType == GL_RENDERBUFFER && id() == renderbufferId;
104 }
105
getBinding()106 GLenum getBinding() const { return mTarget.binding(); }
107 GLuint id() const;
108
109 // These methods are only legal to call on Texture attachments
110 const ImageIndex &getTextureImageIndex() const;
111 TextureTarget cubeMapFace() const;
112 GLint mipLevel() const;
113 GLint layer() const;
114 bool isLayered() const;
115
getNumViews()116 GLsizei getNumViews() const { return mNumViews; }
117
118 bool isMultiview() const;
119 GLint getBaseViewIndex() const;
120
getRenderToTextureSamples()121 GLsizei getRenderToTextureSamples() const { return mRenderToTextureSamples; }
122
123 // The size of the underlying resource the attachment points to. The 'depth' value will
124 // correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and
125 // Renderbuffers, it will always be 1.
126 Extents getSize() const;
127 Format getFormat() const;
128 GLsizei getSamples() const;
129 // This will always return the actual sample count of the attachment even if
130 // render_to_texture extension is active on this FBattachment object.
131 GLsizei getResourceSamples() const;
type()132 GLenum type() const { return mType; }
isAttached()133 bool isAttached() const { return mType != GL_NONE; }
134 bool isRenderable(const Context *context) const;
135
136 Renderbuffer *getRenderbuffer() const;
137 Texture *getTexture() const;
138 const egl::Surface *getSurface() const;
139 FramebufferAttachmentObject *getResource() const;
140 InitState initState() const;
141 angle::Result initializeContents(const Context *context);
142 void setInitState(InitState initState) const;
143
144 // "T" must be static_castable from FramebufferAttachmentRenderTarget
145 template <typename T>
getRenderTarget(const Context * context,GLsizei samples,T ** rtOut)146 angle::Result getRenderTarget(const Context *context, GLsizei samples, T **rtOut) const
147 {
148 static_assert(std::is_base_of<rx::FramebufferAttachmentRenderTarget, T>(),
149 "Invalid RenderTarget class.");
150 return getRenderTargetImpl(
151 context, samples, reinterpret_cast<rx::FramebufferAttachmentRenderTarget **>(rtOut));
152 }
153
154 bool operator==(const FramebufferAttachment &other) const;
155 bool operator!=(const FramebufferAttachment &other) const;
156
157 static const GLsizei kDefaultNumViews;
158 static const GLint kDefaultBaseViewIndex;
159 static const GLint kDefaultRenderToTextureSamples;
160
161 private:
162 angle::Result getRenderTargetImpl(const Context *context,
163 GLsizei samples,
164 rx::FramebufferAttachmentRenderTarget **rtOut) const;
165
166 // A framebuffer attachment points to one of three types of resources: Renderbuffers,
167 // Textures and egl::Surface. The "Target" struct indicates which part of the
168 // object an attachment references. For the three types:
169 // - a Renderbuffer has a unique renderable target, and needs no target index
170 // - a Texture has targets for every image and uses an ImageIndex
171 // - a Surface has targets for Color and Depth/Stencil, and uses the attachment binding
172 class Target
173 {
174 public:
175 Target();
176 Target(GLenum binding, const ImageIndex &imageIndex);
177 Target(const Target &other);
178 Target &operator=(const Target &other);
179
binding()180 GLenum binding() const { return mBinding; }
textureIndex()181 const ImageIndex &textureIndex() const { return mTextureIndex; }
182
183 private:
184 GLenum mBinding;
185 ImageIndex mTextureIndex;
186 };
187
188 GLenum mType;
189 Target mTarget;
190 FramebufferAttachmentObject *mResource;
191 GLsizei mNumViews;
192 bool mIsMultiview;
193 GLint mBaseViewIndex;
194 GLsizei mRenderToTextureSamples;
195 };
196
197 // A base class for objects that FBO Attachments may point to.
198 class FramebufferAttachmentObject : public angle::Subject
199 {
200 public:
201 FramebufferAttachmentObject();
202 ~FramebufferAttachmentObject() override;
203
204 virtual Extents getAttachmentSize(const ImageIndex &imageIndex) const = 0;
205 virtual Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const = 0;
206 virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const = 0;
207 virtual bool isRenderable(const Context *context,
208 GLenum binding,
209 const ImageIndex &imageIndex) const = 0;
210
211 virtual void onAttach(const Context *context) = 0;
212 virtual void onDetach(const Context *context) = 0;
213 virtual GLuint getId() const = 0;
214
215 // These are used for robust resource initialization.
216 virtual InitState initState(const ImageIndex &imageIndex) const = 0;
217 virtual void setInitState(const ImageIndex &imageIndex, InitState initState) = 0;
218
219 angle::Result getAttachmentRenderTarget(const Context *context,
220 GLenum binding,
221 const ImageIndex &imageIndex,
222 GLsizei samples,
223 rx::FramebufferAttachmentRenderTarget **rtOut) const;
224
225 angle::Result initializeContents(const Context *context, const ImageIndex &imageIndex);
226
227 protected:
228 virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
229 };
230
getTextureImageIndex()231 inline const ImageIndex &FramebufferAttachment::getTextureImageIndex() const
232 {
233 ASSERT(type() == GL_TEXTURE);
234 return mTarget.textureIndex();
235 }
236
getSize()237 inline Extents FramebufferAttachment::getSize() const
238 {
239 ASSERT(mResource);
240 return mResource->getAttachmentSize(mTarget.textureIndex());
241 }
242
getFormat()243 inline Format FramebufferAttachment::getFormat() const
244 {
245 ASSERT(mResource);
246 return mResource->getAttachmentFormat(mTarget.binding(), mTarget.textureIndex());
247 }
248
getSamples()249 inline GLsizei FramebufferAttachment::getSamples() const
250 {
251 return (mRenderToTextureSamples != kDefaultRenderToTextureSamples) ? getRenderToTextureSamples()
252 : getResourceSamples();
253 }
254
getResourceSamples()255 inline GLsizei FramebufferAttachment::getResourceSamples() const
256 {
257 ASSERT(mResource);
258 return mResource->getAttachmentSamples(mTarget.textureIndex());
259 }
260
getRenderTargetImpl(const Context * context,GLsizei samples,rx::FramebufferAttachmentRenderTarget ** rtOut)261 inline angle::Result FramebufferAttachment::getRenderTargetImpl(
262 const Context *context,
263 GLsizei samples,
264 rx::FramebufferAttachmentRenderTarget **rtOut) const
265 {
266 ASSERT(mResource);
267 return mResource->getAttachmentRenderTarget(context, mTarget.binding(), mTarget.textureIndex(),
268 samples, rtOut);
269 }
270
isRenderable(const Context * context)271 inline bool FramebufferAttachment::isRenderable(const Context *context) const
272 {
273 ASSERT(mResource);
274 return mResource->isRenderable(context, mTarget.binding(), mTarget.textureIndex());
275 }
276
277 } // namespace gl
278
279 #endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_
280