1 //
2 // Copyright (c) 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/angletypes.h"
16 #include "libANGLE/Error.h"
17 #include "libANGLE/ImageIndex.h"
18 #include "libANGLE/signal_utils.h"
19 
20 namespace egl
21 {
22 class Surface;
23 }
24 
25 namespace rx
26 {
27 // An implementation-specific object associated with an attachment.
28 
29 class FramebufferAttachmentRenderTarget : angle::NonCopyable
30 {
31   public:
FramebufferAttachmentRenderTarget()32     FramebufferAttachmentRenderTarget() {}
~FramebufferAttachmentRenderTarget()33     virtual ~FramebufferAttachmentRenderTarget() {}
34 };
35 
36 class FramebufferAttachmentObjectImpl;
37 }
38 
39 namespace gl
40 {
41 class FramebufferAttachmentObject;
42 struct Format;
43 class Renderbuffer;
44 class Texture;
45 
46 enum class InitState
47 {
48     MayNeedInit,
49     Initialized,
50 };
51 
52 using OnAttachmentDirtyBinding  = angle::ChannelBinding<size_t, InitState>;
53 using OnAttachmentDirtyChannel  = angle::BroadcastChannel<size_t, InitState>;
54 using OnAttachmentDirtyReceiver = angle::SignalReceiver<size_t, InitState>;
55 
56 // FramebufferAttachment implements a GL framebuffer attachment.
57 // Attachments are "light" containers, which store pointers to ref-counted GL objects.
58 // We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments.
59 // Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for
60 // framebuffer attachments, which confused their usage.
61 
62 class FramebufferAttachment final
63 {
64   public:
65     FramebufferAttachment();
66 
67     FramebufferAttachment(const Context *context,
68                           GLenum type,
69                           GLenum binding,
70                           const ImageIndex &textureIndex,
71                           FramebufferAttachmentObject *resource);
72 
73     FramebufferAttachment(FramebufferAttachment &&other);
74     FramebufferAttachment &operator=(FramebufferAttachment &&other);
75 
76     ~FramebufferAttachment();
77 
78     void detach(const Context *context);
79     void attach(const Context *context,
80                 GLenum type,
81                 GLenum binding,
82                 const ImageIndex &textureIndex,
83                 FramebufferAttachmentObject *resource,
84                 GLsizei numViews,
85                 GLuint baseViewIndex,
86                 GLenum multiviewLayout,
87                 const GLint *viewportOffsets);
88 
89     // Helper methods
90     GLuint getRedSize() const;
91     GLuint getGreenSize() const;
92     GLuint getBlueSize() const;
93     GLuint getAlphaSize() const;
94     GLuint getDepthSize() const;
95     GLuint getStencilSize() const;
96     GLenum getComponentType() const;
97     GLenum getColorEncoding() const;
98 
isTextureWithId(GLuint textureId)99     bool isTextureWithId(GLuint textureId) const { return mType == GL_TEXTURE && id() == textureId; }
isRenderbufferWithId(GLuint renderbufferId)100     bool isRenderbufferWithId(GLuint renderbufferId) const { return mType == GL_RENDERBUFFER && id() == renderbufferId; }
101 
getBinding()102     GLenum getBinding() const { return mTarget.binding(); }
103     GLuint id() const;
104 
105     // These methods are only legal to call on Texture attachments
106     const ImageIndex &getTextureImageIndex() const;
107     GLenum cubeMapFace() const;
108     GLint mipLevel() const;
109     GLint layer() const;
110     GLsizei getNumViews() const;
111     GLenum getMultiviewLayout() const;
112     GLint getBaseViewIndex() const;
113     const std::vector<Offset> &getMultiviewViewportOffsets() const;
114 
115     // The size of the underlying resource the attachment points to. The 'depth' value will
116     // correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and
117     // Renderbuffers, it will always be 1.
118     Extents getSize() const;
119     const Format &getFormat() const;
120     GLsizei getSamples() const;
type()121     GLenum type() const { return mType; }
isAttached()122     bool isAttached() const { return mType != GL_NONE; }
123 
124     Renderbuffer *getRenderbuffer() const;
125     Texture *getTexture() const;
126     const egl::Surface *getSurface() const;
127     FramebufferAttachmentObject *getResource() const;
128     InitState initState() const;
129     Error initializeContents(const Context *context);
130     void setInitState(InitState initState) const;
131 
132     // "T" must be static_castable from FramebufferAttachmentRenderTarget
133     template <typename T>
getRenderTarget(const Context * context,T ** rtOut)134     gl::Error getRenderTarget(const Context *context, T **rtOut) const
135     {
136         static_assert(std::is_base_of<rx::FramebufferAttachmentRenderTarget, T>(),
137                       "Invalid RenderTarget class.");
138         return getRenderTargetImpl(
139             context, reinterpret_cast<rx::FramebufferAttachmentRenderTarget **>(rtOut));
140     }
141 
142     bool operator==(const FramebufferAttachment &other) const;
143     bool operator!=(const FramebufferAttachment &other) const;
144 
145     static std::vector<Offset> GetDefaultViewportOffsetVector();
146     static const GLsizei kDefaultNumViews;
147     static const GLenum kDefaultMultiviewLayout;
148     static const GLint kDefaultBaseViewIndex;
149     static const GLint kDefaultViewportOffsets[2];
150 
151   private:
152     gl::Error getRenderTargetImpl(const Context *context,
153                                   rx::FramebufferAttachmentRenderTarget **rtOut) const;
154 
155     // A framebuffer attachment points to one of three types of resources: Renderbuffers,
156     // Textures and egl::Surface. The "Target" struct indicates which part of the
157     // object an attachment references. For the three types:
158     //   - a Renderbuffer has a unique renderable target, and needs no target index
159     //   - a Texture has targets for every image and uses an ImageIndex
160     //   - a Surface has targets for Color and Depth/Stencil, and uses the attachment binding
161     class Target
162     {
163       public:
164         Target();
165         Target(GLenum binding, const ImageIndex &imageIndex);
166         Target(const Target &other);
167         Target &operator=(const Target &other);
168 
binding()169         GLenum binding() const { return mBinding; }
textureIndex()170         const ImageIndex &textureIndex() const { return mTextureIndex; }
171 
172       private:
173         GLenum mBinding;
174         ImageIndex mTextureIndex;
175     };
176 
177     GLenum mType;
178     Target mTarget;
179     FramebufferAttachmentObject *mResource;
180     GLsizei mNumViews;
181     GLenum mMultiviewLayout;
182     GLint mBaseViewIndex;
183     std::vector<Offset> mViewportOffsets;
184 };
185 
186 // A base class for objects that FBO Attachments may point to.
187 class FramebufferAttachmentObject
188 {
189   public:
190     FramebufferAttachmentObject();
191     virtual ~FramebufferAttachmentObject();
192 
193     virtual Extents getAttachmentSize(const ImageIndex &imageIndex) const = 0;
194     virtual const Format &getAttachmentFormat(GLenum binding,
195                                               const ImageIndex &imageIndex) const = 0;
196     virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const      = 0;
197 
198     virtual void onAttach(const Context *context) = 0;
199     virtual void onDetach(const Context *context) = 0;
200     virtual GLuint getId() const = 0;
201 
202     // These are used for robust resource initialization.
203     virtual InitState initState(const ImageIndex &imageIndex) const = 0;
204     virtual void setInitState(const ImageIndex &imageIndex, InitState initState) = 0;
205 
206     Error getAttachmentRenderTarget(const Context *context,
207                                     GLenum binding,
208                                     const ImageIndex &imageIndex,
209                                     rx::FramebufferAttachmentRenderTarget **rtOut) const;
210 
211     Error initializeContents(const Context *context, const ImageIndex &imageIndex);
212 
213     OnAttachmentDirtyChannel *getDirtyChannel();
214 
215   protected:
216     virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
217 
218     OnAttachmentDirtyChannel mDirtyChannel;
219 };
220 
getSize()221 inline Extents FramebufferAttachment::getSize() const
222 {
223     ASSERT(mResource);
224     return mResource->getAttachmentSize(mTarget.textureIndex());
225 }
226 
getFormat()227 inline const Format &FramebufferAttachment::getFormat() const
228 {
229     ASSERT(mResource);
230     return mResource->getAttachmentFormat(mTarget.binding(), mTarget.textureIndex());
231 }
232 
getSamples()233 inline GLsizei FramebufferAttachment::getSamples() const
234 {
235     ASSERT(mResource);
236     return mResource->getAttachmentSamples(mTarget.textureIndex());
237 }
238 
getRenderTargetImpl(const Context * context,rx::FramebufferAttachmentRenderTarget ** rtOut)239 inline gl::Error FramebufferAttachment::getRenderTargetImpl(
240     const Context *context,
241     rx::FramebufferAttachmentRenderTarget **rtOut) const
242 {
243     ASSERT(mResource);
244     return mResource->getAttachmentRenderTarget(context, mTarget.binding(), mTarget.textureIndex(),
245                                                 rtOut);
246 }
247 
248 } // namespace gl
249 
250 #endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_
251