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/angletypes.h"
19 #include "libANGLE/formatutils.h"
20 #include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
21
22 namespace egl
23 {
24 class Surface;
25 }
26
27 namespace rx
28 {
29 // An implementation-specific object associated with an attachment.
30
31 class FramebufferAttachmentRenderTarget : angle::NonCopyable
32 {
33 public:
FramebufferAttachmentRenderTarget()34 FramebufferAttachmentRenderTarget() {}
~FramebufferAttachmentRenderTarget()35 virtual ~FramebufferAttachmentRenderTarget() {}
36 };
37
38 class FramebufferAttachmentObjectImpl;
39 } // namespace rx
40
41 namespace gl
42 {
43 class FramebufferAttachmentObject;
44 class Renderbuffer;
45 class Texture;
46
47 // FramebufferAttachment implements a GL framebuffer attachment.
48 // Attachments are "light" containers, which store pointers to ref-counted GL objects.
49 // We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments.
50 // Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for
51 // framebuffer attachments, which confused their usage.
52
53 class FramebufferAttachment final
54 {
55 public:
56 FramebufferAttachment();
57
58 FramebufferAttachment(const Context *context,
59 GLenum type,
60 GLenum binding,
61 const ImageIndex &textureIndex,
62 FramebufferAttachmentObject *resource,
63 rx::UniqueSerial framebufferSerial);
64
65 FramebufferAttachment(FramebufferAttachment &&other);
66 FramebufferAttachment &operator=(FramebufferAttachment &&other);
67
68 ~FramebufferAttachment();
69
70 void detach(const Context *context, rx::UniqueSerial framebufferSerial);
71 void attach(const Context *context,
72 GLenum type,
73 GLenum binding,
74 const ImageIndex &textureIndex,
75 FramebufferAttachmentObject *resource,
76 GLsizei numViews,
77 GLuint baseViewIndex,
78 bool isMultiview,
79 GLsizei samples,
80 rx::UniqueSerial framebufferSerial);
81
82 // Helper methods
83 GLuint getRedSize() const;
84 GLuint getGreenSize() const;
85 GLuint getBlueSize() const;
86 GLuint getAlphaSize() const;
87 GLuint getDepthSize() const;
88 GLuint getStencilSize() const;
89 GLenum getComponentType() const;
90 GLenum getColorEncoding() const;
91
isTextureWithId(TextureID textureId)92 bool isTextureWithId(TextureID textureId) const
93 {
94 return mType == GL_TEXTURE && id() == textureId.value;
95 }
isExternalTexture()96 bool isExternalTexture() const
97 {
98 return mType == GL_TEXTURE && getTextureImageIndex().getType() == gl::TextureType::External;
99 }
isRenderbufferWithId(GLuint renderbufferId)100 bool isRenderbufferWithId(GLuint renderbufferId) const
101 {
102 return mType == GL_RENDERBUFFER && id() == renderbufferId;
103 }
104
getBinding()105 GLenum getBinding() const { return mTarget.binding(); }
106 GLuint id() const;
107
108 // These methods are only legal to call on Texture attachments
109 const ImageIndex &getTextureImageIndex() const;
110 TextureTarget cubeMapFace() const;
111 GLint mipLevel() const;
112 GLint layer() const;
113 bool isLayered() const;
114
getNumViews()115 GLsizei getNumViews() const { return mNumViews; }
116
117 bool isMultiview() const;
118 GLint getBaseViewIndex() const;
119
120 bool isRenderToTexture() const;
121 GLsizei getRenderToTextureSamples() const;
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 bool isYUV() const;
136 // Checks whether the attachment is an external image such as AHB or dmabuf, where
137 // synchronization is done without individually naming the objects that are involved. This
138 // excludes Vulkan images (EXT_external_objects) as they are individually listed during
139 // synchronization.
140 //
141 // This function is used to disable optimizations that involve deferring operations, as there is
142 // no efficient way to perform those deferred operations on sync if the specific objects are
143 // unknown.
144 bool isExternalImageWithoutIndividualSync() const;
145 bool hasFrontBufferUsage() const;
146 bool hasFoveatedRendering() const;
147 const gl::FoveationState *getFoveationState() const;
148
149 Renderbuffer *getRenderbuffer() const;
150 Texture *getTexture() const;
151 const egl::Surface *getSurface() const;
152 FramebufferAttachmentObject *getResource() const;
153 InitState initState() const;
154 angle::Result initializeContents(const Context *context) const;
155 void setInitState(InitState initState) const;
156
157 // "T" must be static_castable from FramebufferAttachmentRenderTarget
158 template <typename T>
getRenderTarget(const Context * context,GLsizei samples,T ** rtOut)159 angle::Result getRenderTarget(const Context *context, GLsizei samples, T **rtOut) const
160 {
161 static_assert(std::is_base_of<rx::FramebufferAttachmentRenderTarget, T>(),
162 "Invalid RenderTarget class.");
163 return getRenderTargetImpl(
164 context, samples, reinterpret_cast<rx::FramebufferAttachmentRenderTarget **>(rtOut));
165 }
166
167 bool operator==(const FramebufferAttachment &other) const;
168 bool operator!=(const FramebufferAttachment &other) const;
169
170 static const GLsizei kDefaultNumViews;
171 static const GLint kDefaultBaseViewIndex;
172 static const GLint kDefaultRenderToTextureSamples;
173
174 private:
175 bool isSpecified() const;
176
177 angle::Result getRenderTargetImpl(const Context *context,
178 GLsizei samples,
179 rx::FramebufferAttachmentRenderTarget **rtOut) const;
180
181 // A framebuffer attachment points to one of three types of resources: Renderbuffers,
182 // Textures and egl::Surface. The "Target" struct indicates which part of the
183 // object an attachment references. For the three types:
184 // - a Renderbuffer has a unique renderable target, and needs no target index
185 // - a Texture has targets for every image and uses an ImageIndex
186 // - a Surface has targets for Color and Depth/Stencil, and uses the attachment binding
187 class Target
188 {
189 public:
190 Target();
191 Target(GLenum binding, const ImageIndex &imageIndex);
192 Target(const Target &other);
193 Target &operator=(const Target &other);
194
binding()195 GLenum binding() const { return mBinding; }
textureIndex()196 const ImageIndex &textureIndex() const { return mTextureIndex; }
197
198 private:
199 GLenum mBinding;
200 ImageIndex mTextureIndex;
201 };
202
203 GLenum mType;
204 Target mTarget;
205 FramebufferAttachmentObject *mResource;
206 GLsizei mNumViews;
207 bool mIsMultiview;
208 GLint mBaseViewIndex;
209 // A single-sampled texture can be attached to a framebuffer either as single-sampled or as
210 // multisampled-render-to-texture. In the latter case, |mRenderToTextureSamples| will contain
211 // the number of samples. For renderbuffers, the number of samples is inherited from the
212 // renderbuffer itself.
213 //
214 // Note that textures cannot change storage between single and multisample once attached to a
215 // framebuffer. Renderbuffers instead can, and caching the number of renderbuffer samples here
216 // can lead to stale data.
217 GLsizei mRenderToTextureSamples;
218 };
219
220 // A base class for objects that FBO Attachments may point to.
221 class FramebufferAttachmentObject : public angle::Subject, public angle::ObserverInterface
222 {
223 public:
224 FramebufferAttachmentObject();
225 ~FramebufferAttachmentObject() override;
226
227 virtual bool isAttachmentSpecified(const ImageIndex &imageIndex) const = 0;
228 virtual Extents getAttachmentSize(const ImageIndex &imageIndex) const = 0;
229 virtual Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const = 0;
230 virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const = 0;
231 virtual bool isRenderable(const Context *context,
232 GLenum binding,
233 const ImageIndex &imageIndex) const = 0;
234 virtual bool isYUV() const = 0;
235 virtual bool isExternalImageWithoutIndividualSync() const = 0;
236 virtual bool hasFrontBufferUsage() const = 0;
237 virtual bool hasProtectedContent() const = 0;
238 virtual bool hasFoveatedRendering() const = 0;
239 virtual const gl::FoveationState *getFoveationState() const = 0;
240
241 virtual void onAttach(const Context *context, rx::UniqueSerial framebufferSerial) = 0;
242 virtual void onDetach(const Context *context, rx::UniqueSerial framebufferSerial) = 0;
243 virtual GLuint getId() const = 0;
244
245 // These are used for robust resource initialization.
246 virtual InitState initState(GLenum binding, const ImageIndex &imageIndex) const = 0;
247 virtual void setInitState(GLenum binding,
248 const ImageIndex &imageIndex,
249 InitState initState) = 0;
250
251 angle::Result getAttachmentRenderTarget(const Context *context,
252 GLenum binding,
253 const ImageIndex &imageIndex,
254 GLsizei samples,
255 rx::FramebufferAttachmentRenderTarget **rtOut) const;
256
257 angle::Result initializeContents(const Context *context,
258 GLenum binding,
259 const ImageIndex &imageIndex);
260
261 protected:
262 virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
263 };
264
getTextureImageIndex()265 inline const ImageIndex &FramebufferAttachment::getTextureImageIndex() const
266 {
267 ASSERT(type() == GL_TEXTURE);
268 return mTarget.textureIndex();
269 }
270
isSpecified()271 inline bool FramebufferAttachment::isSpecified() const
272 {
273 ASSERT(mResource);
274 return mResource->isAttachmentSpecified(mTarget.textureIndex());
275 }
276
getSize()277 inline Extents FramebufferAttachment::getSize() const
278 {
279 ASSERT(mResource);
280 return mResource->getAttachmentSize(mTarget.textureIndex());
281 }
282
getFormat()283 inline Format FramebufferAttachment::getFormat() const
284 {
285 ASSERT(mResource);
286 return mResource->getAttachmentFormat(mTarget.binding(), mTarget.textureIndex());
287 }
288
getSamples()289 inline GLsizei FramebufferAttachment::getSamples() const
290 {
291 return isRenderToTexture() ? getRenderToTextureSamples() : getResourceSamples();
292 }
293
getResourceSamples()294 inline GLsizei FramebufferAttachment::getResourceSamples() const
295 {
296 ASSERT(mResource);
297 return mResource->getAttachmentSamples(mTarget.textureIndex());
298 }
299
getRenderTargetImpl(const Context * context,GLsizei samples,rx::FramebufferAttachmentRenderTarget ** rtOut)300 inline angle::Result FramebufferAttachment::getRenderTargetImpl(
301 const Context *context,
302 GLsizei samples,
303 rx::FramebufferAttachmentRenderTarget **rtOut) const
304 {
305 ASSERT(mResource);
306 return mResource->getAttachmentRenderTarget(context, mTarget.binding(), mTarget.textureIndex(),
307 samples, rtOut);
308 }
309
isRenderable(const Context * context)310 inline bool FramebufferAttachment::isRenderable(const Context *context) const
311 {
312 ASSERT(mResource);
313 return mResource->isRenderable(context, mTarget.binding(), mTarget.textureIndex());
314 }
315
isYUV()316 inline bool FramebufferAttachment::isYUV() const
317 {
318 ASSERT(mResource);
319 return mResource->isYUV();
320 }
321
isExternalImageWithoutIndividualSync()322 inline bool FramebufferAttachment::isExternalImageWithoutIndividualSync() const
323 {
324 ASSERT(mResource);
325 return mResource->isExternalImageWithoutIndividualSync();
326 }
327
hasFrontBufferUsage()328 inline bool FramebufferAttachment::hasFrontBufferUsage() const
329 {
330 ASSERT(mResource);
331 return mResource->hasFrontBufferUsage();
332 }
333
hasFoveatedRendering()334 inline bool FramebufferAttachment::hasFoveatedRendering() const
335 {
336 ASSERT(mResource);
337 return mResource->hasFoveatedRendering();
338 }
339
getFoveationState()340 inline const gl::FoveationState *FramebufferAttachment::getFoveationState() const
341 {
342 ASSERT(mResource);
343 return mResource->getFoveationState();
344 }
345 } // namespace gl
346
347 #endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_
348