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
Target()30 FramebufferAttachment::Target::Target() : mBinding(GL_NONE), mTextureIndex() {}
31
Target(GLenum binding,const ImageIndex & imageIndex)32 FramebufferAttachment::Target::Target(GLenum binding, const ImageIndex &imageIndex)
33 : mBinding(binding), mTextureIndex(imageIndex)
34 {}
35
Target(const Target & other)36 FramebufferAttachment::Target::Target(const Target &other)
37 : mBinding(other.mBinding), mTextureIndex(other.mTextureIndex)
38 {}
39
operator =(const Target & other)40 FramebufferAttachment::Target &FramebufferAttachment::Target::operator=(const Target &other)
41 {
42 this->mBinding = other.mBinding;
43 this->mTextureIndex = other.mTextureIndex;
44 return *this;
45 }
46
47 ////// FramebufferAttachment Implementation //////
48
FramebufferAttachment()49 FramebufferAttachment::FramebufferAttachment()
50 : mType(GL_NONE),
51 mResource(nullptr),
52 mNumViews(kDefaultNumViews),
53 mIsMultiview(false),
54 mBaseViewIndex(kDefaultBaseViewIndex)
55 {}
56
FramebufferAttachment(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource)57 FramebufferAttachment::FramebufferAttachment(const Context *context,
58 GLenum type,
59 GLenum binding,
60 const ImageIndex &textureIndex,
61 FramebufferAttachmentObject *resource)
62 : mResource(nullptr)
63 {
64 attach(context, type, binding, textureIndex, resource, kDefaultNumViews, kDefaultBaseViewIndex,
65 false);
66 }
67
FramebufferAttachment(FramebufferAttachment && other)68 FramebufferAttachment::FramebufferAttachment(FramebufferAttachment &&other)
69 : FramebufferAttachment()
70 {
71 *this = std::move(other);
72 }
73
operator =(FramebufferAttachment && other)74 FramebufferAttachment &FramebufferAttachment::operator=(FramebufferAttachment &&other)
75 {
76 std::swap(mType, other.mType);
77 std::swap(mTarget, other.mTarget);
78 std::swap(mResource, other.mResource);
79 std::swap(mNumViews, other.mNumViews);
80 std::swap(mIsMultiview, other.mIsMultiview);
81 std::swap(mBaseViewIndex, other.mBaseViewIndex);
82 return *this;
83 }
84
~FramebufferAttachment()85 FramebufferAttachment::~FramebufferAttachment()
86 {
87 ASSERT(!isAttached());
88 }
89
detach(const Context * context)90 void FramebufferAttachment::detach(const Context *context)
91 {
92 mType = GL_NONE;
93 if (mResource != nullptr)
94 {
95 mResource->onDetach(context);
96 mResource = nullptr;
97 }
98 mNumViews = kDefaultNumViews;
99 mIsMultiview = false;
100 mBaseViewIndex = kDefaultBaseViewIndex;
101
102 // not technically necessary, could omit for performance
103 mTarget = Target();
104 }
105
attach(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource,GLsizei numViews,GLuint baseViewIndex,bool isMultiview)106 void FramebufferAttachment::attach(const Context *context,
107 GLenum type,
108 GLenum binding,
109 const ImageIndex &textureIndex,
110 FramebufferAttachmentObject *resource,
111 GLsizei numViews,
112 GLuint baseViewIndex,
113 bool isMultiview)
114 {
115 if (resource == nullptr)
116 {
117 detach(context);
118 return;
119 }
120
121 mType = type;
122 mTarget = Target(binding, textureIndex);
123 mNumViews = numViews;
124 mBaseViewIndex = baseViewIndex;
125 mIsMultiview = isMultiview;
126 resource->onAttach(context);
127
128 if (mResource != nullptr)
129 {
130 mResource->onDetach(context);
131 }
132
133 mResource = resource;
134 }
135
getRedSize() const136 GLuint FramebufferAttachment::getRedSize() const
137 {
138 return getFormat().info->redBits;
139 }
140
getGreenSize() const141 GLuint FramebufferAttachment::getGreenSize() const
142 {
143 return getFormat().info->greenBits;
144 }
145
getBlueSize() const146 GLuint FramebufferAttachment::getBlueSize() const
147 {
148 return getFormat().info->blueBits;
149 }
150
getAlphaSize() const151 GLuint FramebufferAttachment::getAlphaSize() const
152 {
153 return getFormat().info->alphaBits;
154 }
155
getDepthSize() const156 GLuint FramebufferAttachment::getDepthSize() const
157 {
158 return getFormat().info->depthBits;
159 }
160
getStencilSize() const161 GLuint FramebufferAttachment::getStencilSize() const
162 {
163 return getFormat().info->stencilBits;
164 }
165
getComponentType() const166 GLenum FramebufferAttachment::getComponentType() const
167 {
168 return getFormat().info->componentType;
169 }
170
getColorEncoding() const171 GLenum FramebufferAttachment::getColorEncoding() const
172 {
173 return getFormat().info->colorEncoding;
174 }
175
id() const176 GLuint FramebufferAttachment::id() const
177 {
178 return mResource->getId();
179 }
180
cubeMapFace() const181 TextureTarget FramebufferAttachment::cubeMapFace() const
182 {
183 ASSERT(mType == GL_TEXTURE);
184
185 const auto &index = mTarget.textureIndex();
186 return index.getType() == TextureType::CubeMap ? index.getTarget() : TextureTarget::InvalidEnum;
187 }
188
mipLevel() const189 GLint FramebufferAttachment::mipLevel() const
190 {
191 ASSERT(type() == GL_TEXTURE);
192 return mTarget.textureIndex().getLevelIndex();
193 }
194
layer() const195 GLint FramebufferAttachment::layer() const
196 {
197 ASSERT(mType == GL_TEXTURE);
198
199 const gl::ImageIndex &index = mTarget.textureIndex();
200 return (index.has3DLayer() ? index.getLayerIndex() : 0);
201 }
202
isLayered() const203 bool FramebufferAttachment::isLayered() const
204 {
205 return mTarget.textureIndex().isLayered();
206 }
207
isMultiview() const208 bool FramebufferAttachment::isMultiview() const
209 {
210 return mIsMultiview;
211 }
212
getBaseViewIndex() const213 GLint FramebufferAttachment::getBaseViewIndex() const
214 {
215 return mBaseViewIndex;
216 }
217
getTexture() const218 Texture *FramebufferAttachment::getTexture() const
219 {
220 return rx::GetAs<Texture>(mResource);
221 }
222
getRenderbuffer() const223 Renderbuffer *FramebufferAttachment::getRenderbuffer() const
224 {
225 return rx::GetAs<Renderbuffer>(mResource);
226 }
227
getSurface() const228 const egl::Surface *FramebufferAttachment::getSurface() const
229 {
230 return rx::GetAs<egl::Surface>(mResource);
231 }
232
getResource() const233 FramebufferAttachmentObject *FramebufferAttachment::getResource() const
234 {
235 return mResource;
236 }
237
operator ==(const FramebufferAttachment & other) const238 bool FramebufferAttachment::operator==(const FramebufferAttachment &other) const
239 {
240 if (mResource != other.mResource || mType != other.mType || mNumViews != other.mNumViews ||
241 mIsMultiview != other.mIsMultiview || mBaseViewIndex != other.mBaseViewIndex)
242 {
243 return false;
244 }
245
246 if (mType == GL_TEXTURE && getTextureImageIndex() != other.getTextureImageIndex())
247 {
248 return false;
249 }
250
251 return true;
252 }
253
operator !=(const FramebufferAttachment & other) const254 bool FramebufferAttachment::operator!=(const FramebufferAttachment &other) const
255 {
256 return !(*this == other);
257 }
258
initState() const259 InitState FramebufferAttachment::initState() const
260 {
261 return mResource ? mResource->initState(mTarget.textureIndex()) : InitState::Initialized;
262 }
263
initializeContents(const Context * context)264 angle::Result FramebufferAttachment::initializeContents(const Context *context)
265 {
266 ASSERT(mResource);
267 ANGLE_TRY(mResource->initializeContents(context, mTarget.textureIndex()));
268 setInitState(InitState::Initialized);
269 return angle::Result::Continue;
270 }
271
setInitState(InitState initState) const272 void FramebufferAttachment::setInitState(InitState initState) const
273 {
274 ASSERT(mResource);
275 mResource->setInitState(mTarget.textureIndex(), initState);
276 }
277
278 ////// FramebufferAttachmentObject Implementation //////
279
FramebufferAttachmentObject()280 FramebufferAttachmentObject::FramebufferAttachmentObject() {}
281
~FramebufferAttachmentObject()282 FramebufferAttachmentObject::~FramebufferAttachmentObject() {}
283
getAttachmentRenderTarget(const Context * context,GLenum binding,const ImageIndex & imageIndex,rx::FramebufferAttachmentRenderTarget ** rtOut) const284 angle::Result FramebufferAttachmentObject::getAttachmentRenderTarget(
285 const Context *context,
286 GLenum binding,
287 const ImageIndex &imageIndex,
288 rx::FramebufferAttachmentRenderTarget **rtOut) const
289 {
290 return getAttachmentImpl()->getAttachmentRenderTarget(context, binding, imageIndex, rtOut);
291 }
292
initializeContents(const Context * context,const ImageIndex & imageIndex)293 angle::Result FramebufferAttachmentObject::initializeContents(const Context *context,
294 const ImageIndex &imageIndex)
295 {
296 ASSERT(context->isRobustResourceInitEnabled());
297
298 // Because gl::Texture cannot support tracking individual layer dirtiness, we only handle
299 // initializing entire mip levels for 2D array textures.
300 if (imageIndex.getType() == TextureType::_2DArray && imageIndex.hasLayer())
301 {
302 ImageIndex fullMipIndex =
303 ImageIndex::Make2DArray(imageIndex.getLevelIndex(), ImageIndex::kEntireLevel);
304 return getAttachmentImpl()->initializeContents(context, fullMipIndex);
305 }
306 else if (imageIndex.getType() == TextureType::_2DMultisampleArray && imageIndex.hasLayer())
307 {
308 ImageIndex fullMipIndex = ImageIndex::Make2DMultisampleArray(ImageIndex::kEntireLevel);
309 return getAttachmentImpl()->initializeContents(context, fullMipIndex);
310 }
311 else
312 {
313 return getAttachmentImpl()->initializeContents(context, imageIndex);
314 }
315 }
316
317 } // namespace gl
318