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)59 FramebufferAttachment::FramebufferAttachment(const Context *context,
60 GLenum type,
61 GLenum binding,
62 const ImageIndex &textureIndex,
63 FramebufferAttachmentObject *resource)
64 : mResource(nullptr)
65 {
66 attach(context, type, binding, textureIndex, resource, kDefaultNumViews, kDefaultBaseViewIndex,
67 false, kDefaultRenderToTextureSamples);
68 }
69
FramebufferAttachment(FramebufferAttachment && other)70 FramebufferAttachment::FramebufferAttachment(FramebufferAttachment &&other)
71 : FramebufferAttachment()
72 {
73 *this = std::move(other);
74 }
75
operator =(FramebufferAttachment && other)76 FramebufferAttachment &FramebufferAttachment::operator=(FramebufferAttachment &&other)
77 {
78 std::swap(mType, other.mType);
79 std::swap(mTarget, other.mTarget);
80 std::swap(mResource, other.mResource);
81 std::swap(mNumViews, other.mNumViews);
82 std::swap(mIsMultiview, other.mIsMultiview);
83 std::swap(mBaseViewIndex, other.mBaseViewIndex);
84 std::swap(mRenderToTextureSamples, other.mRenderToTextureSamples);
85 return *this;
86 }
87
~FramebufferAttachment()88 FramebufferAttachment::~FramebufferAttachment()
89 {
90 ASSERT(!isAttached());
91 }
92
detach(const Context * context)93 void FramebufferAttachment::detach(const Context *context)
94 {
95 mType = GL_NONE;
96 if (mResource != nullptr)
97 {
98 mResource->onDetach(context);
99 mResource = nullptr;
100 }
101 mNumViews = kDefaultNumViews;
102 mIsMultiview = false;
103 mBaseViewIndex = kDefaultBaseViewIndex;
104
105 // not technically necessary, could omit for performance
106 mTarget = Target();
107 }
108
attach(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource,GLsizei numViews,GLuint baseViewIndex,bool isMultiview,GLsizei samples)109 void FramebufferAttachment::attach(const Context *context,
110 GLenum type,
111 GLenum binding,
112 const ImageIndex &textureIndex,
113 FramebufferAttachmentObject *resource,
114 GLsizei numViews,
115 GLuint baseViewIndex,
116 bool isMultiview,
117 GLsizei samples)
118 {
119 if (resource == nullptr)
120 {
121 detach(context);
122 return;
123 }
124
125 mType = type;
126 mTarget = Target(binding, textureIndex);
127 mNumViews = numViews;
128 mBaseViewIndex = baseViewIndex;
129 mIsMultiview = isMultiview;
130 mRenderToTextureSamples = samples;
131 resource->onAttach(context);
132
133 if (mResource != nullptr)
134 {
135 mResource->onDetach(context);
136 }
137
138 mResource = resource;
139 }
140
getRedSize() const141 GLuint FramebufferAttachment::getRedSize() const
142 {
143 return getSize().empty() ? 0 : getFormat().info->redBits;
144 }
145
getGreenSize() const146 GLuint FramebufferAttachment::getGreenSize() const
147 {
148 return getSize().empty() ? 0 : getFormat().info->greenBits;
149 }
150
getBlueSize() const151 GLuint FramebufferAttachment::getBlueSize() const
152 {
153 return getSize().empty() ? 0 : getFormat().info->blueBits;
154 }
155
getAlphaSize() const156 GLuint FramebufferAttachment::getAlphaSize() const
157 {
158 return getSize().empty() ? 0 : getFormat().info->alphaBits;
159 }
160
getDepthSize() const161 GLuint FramebufferAttachment::getDepthSize() const
162 {
163 return getSize().empty() ? 0 : getFormat().info->depthBits;
164 }
165
getStencilSize() const166 GLuint FramebufferAttachment::getStencilSize() const
167 {
168 return getSize().empty() ? 0 : getFormat().info->stencilBits;
169 }
170
getComponentType() const171 GLenum FramebufferAttachment::getComponentType() const
172 {
173 return getFormat().info->componentType;
174 }
175
getColorEncoding() const176 GLenum FramebufferAttachment::getColorEncoding() const
177 {
178 return getFormat().info->colorEncoding;
179 }
180
id() const181 GLuint FramebufferAttachment::id() const
182 {
183 return mResource->getId();
184 }
185
cubeMapFace() const186 TextureTarget FramebufferAttachment::cubeMapFace() const
187 {
188 ASSERT(mType == GL_TEXTURE);
189
190 const auto &index = mTarget.textureIndex();
191 return index.getType() == TextureType::CubeMap ? index.getTarget() : TextureTarget::InvalidEnum;
192 }
193
mipLevel() const194 GLint FramebufferAttachment::mipLevel() const
195 {
196 ASSERT(type() == GL_TEXTURE);
197 return mTarget.textureIndex().getLevelIndex();
198 }
199
layer() const200 GLint FramebufferAttachment::layer() const
201 {
202 ASSERT(mType == GL_TEXTURE);
203
204 const gl::ImageIndex &index = mTarget.textureIndex();
205 return (index.has3DLayer() ? index.getLayerIndex() : 0);
206 }
207
isLayered() const208 bool FramebufferAttachment::isLayered() const
209 {
210 return mTarget.textureIndex().isLayered();
211 }
212
isMultiview() const213 bool FramebufferAttachment::isMultiview() const
214 {
215 return mIsMultiview;
216 }
217
getBaseViewIndex() const218 GLint FramebufferAttachment::getBaseViewIndex() const
219 {
220 return mBaseViewIndex;
221 }
222
getTexture() const223 Texture *FramebufferAttachment::getTexture() const
224 {
225 return rx::GetAs<Texture>(mResource);
226 }
227
getRenderbuffer() const228 Renderbuffer *FramebufferAttachment::getRenderbuffer() const
229 {
230 return rx::GetAs<Renderbuffer>(mResource);
231 }
232
getSurface() const233 const egl::Surface *FramebufferAttachment::getSurface() const
234 {
235 return rx::GetAs<egl::Surface>(mResource);
236 }
237
getResource() const238 FramebufferAttachmentObject *FramebufferAttachment::getResource() const
239 {
240 return mResource;
241 }
242
operator ==(const FramebufferAttachment & other) const243 bool FramebufferAttachment::operator==(const FramebufferAttachment &other) const
244 {
245 if (mResource != other.mResource || mType != other.mType || mNumViews != other.mNumViews ||
246 mIsMultiview != other.mIsMultiview || mBaseViewIndex != other.mBaseViewIndex ||
247 mRenderToTextureSamples != other.mRenderToTextureSamples)
248 {
249 return false;
250 }
251
252 if (mType == GL_TEXTURE && getTextureImageIndex() != other.getTextureImageIndex())
253 {
254 return false;
255 }
256
257 return true;
258 }
259
operator !=(const FramebufferAttachment & other) const260 bool FramebufferAttachment::operator!=(const FramebufferAttachment &other) const
261 {
262 return !(*this == other);
263 }
264
initState() const265 InitState FramebufferAttachment::initState() const
266 {
267 return mResource ? mResource->initState(mTarget.textureIndex()) : InitState::Initialized;
268 }
269
initializeContents(const Context * context)270 angle::Result FramebufferAttachment::initializeContents(const Context *context)
271 {
272 ASSERT(mResource);
273 ANGLE_TRY(mResource->initializeContents(context, mTarget.textureIndex()));
274 setInitState(InitState::Initialized);
275 return angle::Result::Continue;
276 }
277
setInitState(InitState initState) const278 void FramebufferAttachment::setInitState(InitState initState) const
279 {
280 ASSERT(mResource);
281 mResource->setInitState(mTarget.textureIndex(), initState);
282 }
283
isBoundAsSamplerOrImage(ContextID contextID) const284 bool FramebufferAttachment::isBoundAsSamplerOrImage(ContextID contextID) const
285 {
286 if (mType != GL_TEXTURE)
287 {
288 return false;
289 }
290
291 const gl::TextureState &textureState = getTexture()->getTextureState();
292 return textureState.isBoundAsImageTexture(contextID) ||
293 textureState.isBoundAsSamplerTexture(contextID);
294 }
295
296 ////// FramebufferAttachmentObject Implementation //////
297
FramebufferAttachmentObject()298 FramebufferAttachmentObject::FramebufferAttachmentObject() {}
299
~FramebufferAttachmentObject()300 FramebufferAttachmentObject::~FramebufferAttachmentObject() {}
301
getAttachmentRenderTarget(const Context * context,GLenum binding,const ImageIndex & imageIndex,GLsizei samples,rx::FramebufferAttachmentRenderTarget ** rtOut) const302 angle::Result FramebufferAttachmentObject::getAttachmentRenderTarget(
303 const Context *context,
304 GLenum binding,
305 const ImageIndex &imageIndex,
306 GLsizei samples,
307 rx::FramebufferAttachmentRenderTarget **rtOut) const
308 {
309 return getAttachmentImpl()->getAttachmentRenderTarget(context, binding, imageIndex, samples,
310 rtOut);
311 }
312
initializeContents(const Context * context,const ImageIndex & imageIndex)313 angle::Result FramebufferAttachmentObject::initializeContents(const Context *context,
314 const ImageIndex &imageIndex)
315 {
316 ASSERT(context->isRobustResourceInitEnabled());
317
318 // Because gl::Texture cannot support tracking individual layer dirtiness, we only handle
319 // initializing entire mip levels for textures with layers
320 if (imageIndex.usesTex3D() && imageIndex.hasLayer())
321 {
322 // Compute the layer count so we get a correct layer index.
323 const gl::Extents &size = getAttachmentSize(imageIndex);
324
325 ImageIndex fullMipIndex = ImageIndex::MakeFromType(
326 imageIndex.getType(), imageIndex.getLevelIndex(), ImageIndex::kEntireLevel, size.depth);
327 return getAttachmentImpl()->initializeContents(context, fullMipIndex);
328 }
329 else
330 {
331 return getAttachmentImpl()->initializeContents(context, imageIndex);
332 }
333 }
334
335 } // namespace gl
336