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.cpp: the gl::FramebufferAttachment class and its derived classes
8 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
9 
10 #include "libANGLE/FramebufferAttachment.h"
11 
12 #include "common/utilities.h"
13 #include "libANGLE/Config.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/Renderbuffer.h"
16 #include "libANGLE/Surface.h"
17 #include "libANGLE/Texture.h"
18 #include "libANGLE/formatutils.h"
19 #include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
20 #include "libANGLE/renderer/FramebufferImpl.h"
21 
22 namespace gl
23 {
24 
25 ////// FramebufferAttachment::Target Implementation //////
26 
27 const GLsizei FramebufferAttachment::kDefaultNumViews             = 1;
28 const GLint FramebufferAttachment::kDefaultBaseViewIndex          = 0;
29 const GLint FramebufferAttachment::kDefaultRenderToTextureSamples = 0;
30 
Target()31 FramebufferAttachment::Target::Target() : mBinding(GL_NONE), mTextureIndex() {}
32 
Target(GLenum binding,const ImageIndex & imageIndex)33 FramebufferAttachment::Target::Target(GLenum binding, const ImageIndex &imageIndex)
34     : mBinding(binding), mTextureIndex(imageIndex)
35 {}
36 
Target(const Target & other)37 FramebufferAttachment::Target::Target(const Target &other)
38     : mBinding(other.mBinding), mTextureIndex(other.mTextureIndex)
39 {}
40 
operator =(const Target & other)41 FramebufferAttachment::Target &FramebufferAttachment::Target::operator=(const Target &other)
42 {
43     this->mBinding      = other.mBinding;
44     this->mTextureIndex = other.mTextureIndex;
45     return *this;
46 }
47 
48 ////// FramebufferAttachment Implementation //////
49 
FramebufferAttachment()50 FramebufferAttachment::FramebufferAttachment()
51     : mType(GL_NONE),
52       mResource(nullptr),
53       mNumViews(kDefaultNumViews),
54       mIsMultiview(false),
55       mBaseViewIndex(kDefaultBaseViewIndex),
56       mRenderToTextureSamples(kDefaultRenderToTextureSamples)
57 {}
58 
FramebufferAttachment(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource,rx::Serial framebufferSerial)59 FramebufferAttachment::FramebufferAttachment(const Context *context,
60                                              GLenum type,
61                                              GLenum binding,
62                                              const ImageIndex &textureIndex,
63                                              FramebufferAttachmentObject *resource,
64                                              rx::Serial framebufferSerial)
65     : mResource(nullptr)
66 {
67     attach(context, type, binding, textureIndex, resource, kDefaultNumViews, kDefaultBaseViewIndex,
68            false, kDefaultRenderToTextureSamples, framebufferSerial);
69 }
70 
FramebufferAttachment(FramebufferAttachment && other)71 FramebufferAttachment::FramebufferAttachment(FramebufferAttachment &&other)
72     : FramebufferAttachment()
73 {
74     *this = std::move(other);
75 }
76 
operator =(FramebufferAttachment && other)77 FramebufferAttachment &FramebufferAttachment::operator=(FramebufferAttachment &&other)
78 {
79     std::swap(mType, other.mType);
80     std::swap(mTarget, other.mTarget);
81     std::swap(mResource, other.mResource);
82     std::swap(mNumViews, other.mNumViews);
83     std::swap(mIsMultiview, other.mIsMultiview);
84     std::swap(mBaseViewIndex, other.mBaseViewIndex);
85     std::swap(mRenderToTextureSamples, other.mRenderToTextureSamples);
86     return *this;
87 }
88 
~FramebufferAttachment()89 FramebufferAttachment::~FramebufferAttachment()
90 {
91     ASSERT(!isAttached());
92 }
93 
detach(const Context * context,rx::Serial framebufferSerial)94 void FramebufferAttachment::detach(const Context *context, rx::Serial framebufferSerial)
95 {
96     mType = GL_NONE;
97     if (mResource != nullptr)
98     {
99         mResource->onDetach(context, framebufferSerial);
100         mResource = nullptr;
101     }
102     mNumViews      = kDefaultNumViews;
103     mIsMultiview   = false;
104     mBaseViewIndex = kDefaultBaseViewIndex;
105 
106     // not technically necessary, could omit for performance
107     mTarget = Target();
108 }
109 
attach(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource,GLsizei numViews,GLuint baseViewIndex,bool isMultiview,GLsizei samples,rx::Serial framebufferSerial)110 void FramebufferAttachment::attach(const Context *context,
111                                    GLenum type,
112                                    GLenum binding,
113                                    const ImageIndex &textureIndex,
114                                    FramebufferAttachmentObject *resource,
115                                    GLsizei numViews,
116                                    GLuint baseViewIndex,
117                                    bool isMultiview,
118                                    GLsizei samples,
119                                    rx::Serial framebufferSerial)
120 {
121     if (resource == nullptr)
122     {
123         detach(context, framebufferSerial);
124         return;
125     }
126 
127     mType                   = type;
128     mTarget                 = Target(binding, textureIndex);
129     mNumViews               = numViews;
130     mBaseViewIndex          = baseViewIndex;
131     mIsMultiview            = isMultiview;
132     mRenderToTextureSamples = samples;
133     resource->onAttach(context, framebufferSerial);
134 
135     if (mResource != nullptr)
136     {
137         mResource->onDetach(context, framebufferSerial);
138     }
139 
140     mResource = resource;
141 }
142 
getRedSize() const143 GLuint FramebufferAttachment::getRedSize() const
144 {
145     return getSize().empty() ? 0 : getFormat().info->redBits;
146 }
147 
getGreenSize() const148 GLuint FramebufferAttachment::getGreenSize() const
149 {
150     return getSize().empty() ? 0 : getFormat().info->greenBits;
151 }
152 
getBlueSize() const153 GLuint FramebufferAttachment::getBlueSize() const
154 {
155     return getSize().empty() ? 0 : getFormat().info->blueBits;
156 }
157 
getAlphaSize() const158 GLuint FramebufferAttachment::getAlphaSize() const
159 {
160     return getSize().empty() ? 0 : getFormat().info->alphaBits;
161 }
162 
getDepthSize() const163 GLuint FramebufferAttachment::getDepthSize() const
164 {
165     return getSize().empty() ? 0 : getFormat().info->depthBits;
166 }
167 
getStencilSize() const168 GLuint FramebufferAttachment::getStencilSize() const
169 {
170     return getSize().empty() ? 0 : getFormat().info->stencilBits;
171 }
172 
getComponentType() const173 GLenum FramebufferAttachment::getComponentType() const
174 {
175     return getFormat().info->componentType;
176 }
177 
getColorEncoding() const178 GLenum FramebufferAttachment::getColorEncoding() const
179 {
180     return getFormat().info->colorEncoding;
181 }
182 
id() const183 GLuint FramebufferAttachment::id() const
184 {
185     return mResource->getId();
186 }
187 
cubeMapFace() const188 TextureTarget FramebufferAttachment::cubeMapFace() const
189 {
190     ASSERT(mType == GL_TEXTURE);
191 
192     const auto &index = mTarget.textureIndex();
193     return index.getType() == TextureType::CubeMap ? index.getTarget() : TextureTarget::InvalidEnum;
194 }
195 
mipLevel() const196 GLint FramebufferAttachment::mipLevel() const
197 {
198     ASSERT(type() == GL_TEXTURE);
199     return mTarget.textureIndex().getLevelIndex();
200 }
201 
layer() const202 GLint FramebufferAttachment::layer() const
203 {
204     ASSERT(mType == GL_TEXTURE);
205 
206     const gl::ImageIndex &index = mTarget.textureIndex();
207     return (index.has3DLayer() ? index.getLayerIndex() : 0);
208 }
209 
isLayered() const210 bool FramebufferAttachment::isLayered() const
211 {
212     return mTarget.textureIndex().isLayered();
213 }
214 
isMultiview() const215 bool FramebufferAttachment::isMultiview() const
216 {
217     return mIsMultiview;
218 }
219 
getBaseViewIndex() const220 GLint FramebufferAttachment::getBaseViewIndex() const
221 {
222     return mBaseViewIndex;
223 }
224 
getTexture() const225 Texture *FramebufferAttachment::getTexture() const
226 {
227     return rx::GetAs<Texture>(mResource);
228 }
229 
getRenderbuffer() const230 Renderbuffer *FramebufferAttachment::getRenderbuffer() const
231 {
232     return rx::GetAs<Renderbuffer>(mResource);
233 }
234 
getSurface() const235 const egl::Surface *FramebufferAttachment::getSurface() const
236 {
237     return rx::GetAs<egl::Surface>(mResource);
238 }
239 
getResource() const240 FramebufferAttachmentObject *FramebufferAttachment::getResource() const
241 {
242     return mResource;
243 }
244 
operator ==(const FramebufferAttachment & other) const245 bool FramebufferAttachment::operator==(const FramebufferAttachment &other) const
246 {
247     if (mResource != other.mResource || mType != other.mType || mNumViews != other.mNumViews ||
248         mIsMultiview != other.mIsMultiview || mBaseViewIndex != other.mBaseViewIndex ||
249         mRenderToTextureSamples != other.mRenderToTextureSamples)
250     {
251         return false;
252     }
253 
254     if (mType == GL_TEXTURE && getTextureImageIndex() != other.getTextureImageIndex())
255     {
256         return false;
257     }
258 
259     return true;
260 }
261 
operator !=(const FramebufferAttachment & other) const262 bool FramebufferAttachment::operator!=(const FramebufferAttachment &other) const
263 {
264     return !(*this == other);
265 }
266 
initState() const267 InitState FramebufferAttachment::initState() const
268 {
269     return mResource ? mResource->initState(mTarget.textureIndex()) : InitState::Initialized;
270 }
271 
initializeContents(const Context * context)272 angle::Result FramebufferAttachment::initializeContents(const Context *context)
273 {
274     ASSERT(mResource);
275     ANGLE_TRY(mResource->initializeContents(context, mTarget.textureIndex()));
276     setInitState(InitState::Initialized);
277     return angle::Result::Continue;
278 }
279 
setInitState(InitState initState) const280 void FramebufferAttachment::setInitState(InitState initState) const
281 {
282     ASSERT(mResource);
283     mResource->setInitState(mTarget.textureIndex(), initState);
284 }
285 
286 ////// FramebufferAttachmentObject Implementation //////
287 
FramebufferAttachmentObject()288 FramebufferAttachmentObject::FramebufferAttachmentObject() {}
289 
~FramebufferAttachmentObject()290 FramebufferAttachmentObject::~FramebufferAttachmentObject() {}
291 
getAttachmentRenderTarget(const Context * context,GLenum binding,const ImageIndex & imageIndex,GLsizei samples,rx::FramebufferAttachmentRenderTarget ** rtOut) const292 angle::Result FramebufferAttachmentObject::getAttachmentRenderTarget(
293     const Context *context,
294     GLenum binding,
295     const ImageIndex &imageIndex,
296     GLsizei samples,
297     rx::FramebufferAttachmentRenderTarget **rtOut) const
298 {
299     return getAttachmentImpl()->getAttachmentRenderTarget(context, binding, imageIndex, samples,
300                                                           rtOut);
301 }
302 
initializeContents(const Context * context,const ImageIndex & imageIndex)303 angle::Result FramebufferAttachmentObject::initializeContents(const Context *context,
304                                                               const ImageIndex &imageIndex)
305 {
306     ASSERT(context->isRobustResourceInitEnabled());
307 
308     // Because gl::Texture cannot support tracking individual layer dirtiness, we only handle
309     // initializing entire mip levels for textures with layers
310     if (imageIndex.usesTex3D() && imageIndex.hasLayer())
311     {
312         // Compute the layer count so we get a correct layer index.
313         const gl::Extents &size = getAttachmentSize(imageIndex);
314 
315         ImageIndex fullMipIndex = ImageIndex::MakeFromType(
316             imageIndex.getType(), imageIndex.getLevelIndex(), ImageIndex::kEntireLevel, size.depth);
317         return getAttachmentImpl()->initializeContents(context, fullMipIndex);
318     }
319     else
320     {
321         return getAttachmentImpl()->initializeContents(context, imageIndex);
322     }
323 }
324 
325 }  // namespace gl
326