| // |
| // Copyright 2014 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes |
| // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. |
| |
| #include "libANGLE/FramebufferAttachment.h" |
| |
| #include "common/utilities.h" |
| #include "libANGLE/Config.h" |
| #include "libANGLE/Context.h" |
| #include "libANGLE/Renderbuffer.h" |
| #include "libANGLE/Surface.h" |
| #include "libANGLE/Texture.h" |
| #include "libANGLE/formatutils.h" |
| #include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h" |
| #include "libANGLE/renderer/FramebufferImpl.h" |
| |
| namespace gl |
| { |
| |
| ////// FramebufferAttachment::Target Implementation ////// |
| |
| const GLsizei FramebufferAttachment::kDefaultNumViews = 1; |
| const GLint FramebufferAttachment::kDefaultBaseViewIndex = 0; |
| const GLint FramebufferAttachment::kDefaultRenderToTextureSamples = 0; |
| |
| FramebufferAttachment::Target::Target() : mBinding(GL_NONE), mTextureIndex() {} |
| |
| FramebufferAttachment::Target::Target(GLenum binding, const ImageIndex &imageIndex) |
| : mBinding(binding), mTextureIndex(imageIndex) |
| {} |
| |
| FramebufferAttachment::Target::Target(const Target &other) |
| : mBinding(other.mBinding), mTextureIndex(other.mTextureIndex) |
| {} |
| |
| FramebufferAttachment::Target &FramebufferAttachment::Target::operator=(const Target &other) |
| { |
| this->mBinding = other.mBinding; |
| this->mTextureIndex = other.mTextureIndex; |
| return *this; |
| } |
| |
| ////// FramebufferAttachment Implementation ////// |
| |
| FramebufferAttachment::FramebufferAttachment() |
| : mType(GL_NONE), |
| mResource(nullptr), |
| mNumViews(kDefaultNumViews), |
| mIsMultiview(false), |
| mBaseViewIndex(kDefaultBaseViewIndex), |
| mRenderToTextureSamples(kDefaultRenderToTextureSamples) |
| {} |
| |
| FramebufferAttachment::FramebufferAttachment(const Context *context, |
| GLenum type, |
| GLenum binding, |
| const ImageIndex &textureIndex, |
| FramebufferAttachmentObject *resource, |
| rx::Serial framebufferSerial) |
| : mResource(nullptr) |
| { |
| attach(context, type, binding, textureIndex, resource, kDefaultNumViews, kDefaultBaseViewIndex, |
| false, kDefaultRenderToTextureSamples, framebufferSerial); |
| } |
| |
| FramebufferAttachment::FramebufferAttachment(FramebufferAttachment &&other) |
| : FramebufferAttachment() |
| { |
| *this = std::move(other); |
| } |
| |
| FramebufferAttachment &FramebufferAttachment::operator=(FramebufferAttachment &&other) |
| { |
| std::swap(mType, other.mType); |
| std::swap(mTarget, other.mTarget); |
| std::swap(mResource, other.mResource); |
| std::swap(mNumViews, other.mNumViews); |
| std::swap(mIsMultiview, other.mIsMultiview); |
| std::swap(mBaseViewIndex, other.mBaseViewIndex); |
| std::swap(mRenderToTextureSamples, other.mRenderToTextureSamples); |
| return *this; |
| } |
| |
| FramebufferAttachment::~FramebufferAttachment() |
| { |
| ASSERT(!isAttached()); |
| } |
| |
| void FramebufferAttachment::detach(const Context *context, rx::Serial framebufferSerial) |
| { |
| mType = GL_NONE; |
| if (mResource != nullptr) |
| { |
| mResource->onDetach(context, framebufferSerial); |
| mResource = nullptr; |
| } |
| mNumViews = kDefaultNumViews; |
| mIsMultiview = false; |
| mBaseViewIndex = kDefaultBaseViewIndex; |
| |
| // not technically necessary, could omit for performance |
| mTarget = Target(); |
| } |
| |
| void FramebufferAttachment::attach(const Context *context, |
| GLenum type, |
| GLenum binding, |
| const ImageIndex &textureIndex, |
| FramebufferAttachmentObject *resource, |
| GLsizei numViews, |
| GLuint baseViewIndex, |
| bool isMultiview, |
| GLsizei samples, |
| rx::Serial framebufferSerial) |
| { |
| if (resource == nullptr) |
| { |
| detach(context, framebufferSerial); |
| return; |
| } |
| |
| mType = type; |
| mTarget = Target(binding, textureIndex); |
| mNumViews = numViews; |
| mBaseViewIndex = baseViewIndex; |
| mIsMultiview = isMultiview; |
| mRenderToTextureSamples = type == GL_RENDERBUFFER ? kDefaultRenderToTextureSamples : samples; |
| resource->onAttach(context, framebufferSerial); |
| |
| if (mResource != nullptr) |
| { |
| mResource->onDetach(context, framebufferSerial); |
| } |
| |
| mResource = resource; |
| } |
| |
| GLuint FramebufferAttachment::getRedSize() const |
| { |
| return getSize().empty() ? 0 : getFormat().info->redBits; |
| } |
| |
| GLuint FramebufferAttachment::getGreenSize() const |
| { |
| return getSize().empty() ? 0 : getFormat().info->greenBits; |
| } |
| |
| GLuint FramebufferAttachment::getBlueSize() const |
| { |
| return getSize().empty() ? 0 : getFormat().info->blueBits; |
| } |
| |
| GLuint FramebufferAttachment::getAlphaSize() const |
| { |
| return getSize().empty() ? 0 : getFormat().info->alphaBits; |
| } |
| |
| GLuint FramebufferAttachment::getDepthSize() const |
| { |
| return getSize().empty() ? 0 : getFormat().info->depthBits; |
| } |
| |
| GLuint FramebufferAttachment::getStencilSize() const |
| { |
| return getSize().empty() ? 0 : getFormat().info->stencilBits; |
| } |
| |
| GLenum FramebufferAttachment::getComponentType() const |
| { |
| return getFormat().info->componentType; |
| } |
| |
| GLenum FramebufferAttachment::getColorEncoding() const |
| { |
| return getFormat().info->colorEncoding; |
| } |
| |
| GLuint FramebufferAttachment::id() const |
| { |
| return mResource->getId(); |
| } |
| |
| TextureTarget FramebufferAttachment::cubeMapFace() const |
| { |
| ASSERT(mType == GL_TEXTURE); |
| |
| const auto &index = mTarget.textureIndex(); |
| return index.getType() == TextureType::CubeMap ? index.getTarget() : TextureTarget::InvalidEnum; |
| } |
| |
| GLint FramebufferAttachment::mipLevel() const |
| { |
| ASSERT(type() == GL_TEXTURE); |
| return mTarget.textureIndex().getLevelIndex(); |
| } |
| |
| GLint FramebufferAttachment::layer() const |
| { |
| ASSERT(mType == GL_TEXTURE); |
| |
| const gl::ImageIndex &index = mTarget.textureIndex(); |
| return (index.has3DLayer() ? index.getLayerIndex() : 0); |
| } |
| |
| bool FramebufferAttachment::isLayered() const |
| { |
| return mTarget.textureIndex().isLayered(); |
| } |
| |
| bool FramebufferAttachment::isMultiview() const |
| { |
| return mIsMultiview; |
| } |
| |
| GLint FramebufferAttachment::getBaseViewIndex() const |
| { |
| return mBaseViewIndex; |
| } |
| |
| bool FramebufferAttachment::isRenderToTexture() const |
| { |
| ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE); |
| |
| if (mType == GL_RENDERBUFFER) |
| { |
| return getRenderbuffer()->getMultisamplingMode() == |
| MultisamplingMode::MultisampledRenderToTexture; |
| } |
| return mRenderToTextureSamples != kDefaultRenderToTextureSamples; |
| } |
| |
| GLsizei FramebufferAttachment::getRenderToTextureSamples() const |
| { |
| ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE); |
| |
| if (mType == GL_RENDERBUFFER) |
| { |
| return getRenderbuffer()->getState().getSamples(); |
| } |
| return mRenderToTextureSamples; |
| } |
| |
| Texture *FramebufferAttachment::getTexture() const |
| { |
| return rx::GetAs<Texture>(mResource); |
| } |
| |
| Renderbuffer *FramebufferAttachment::getRenderbuffer() const |
| { |
| return rx::GetAs<Renderbuffer>(mResource); |
| } |
| |
| const egl::Surface *FramebufferAttachment::getSurface() const |
| { |
| return rx::GetAs<egl::Surface>(mResource); |
| } |
| |
| FramebufferAttachmentObject *FramebufferAttachment::getResource() const |
| { |
| return mResource; |
| } |
| |
| bool FramebufferAttachment::operator==(const FramebufferAttachment &other) const |
| { |
| if (mResource != other.mResource || mType != other.mType || mNumViews != other.mNumViews || |
| mIsMultiview != other.mIsMultiview || mBaseViewIndex != other.mBaseViewIndex || |
| mRenderToTextureSamples != other.mRenderToTextureSamples) |
| { |
| return false; |
| } |
| |
| if (mType == GL_TEXTURE && getTextureImageIndex() != other.getTextureImageIndex()) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool FramebufferAttachment::operator!=(const FramebufferAttachment &other) const |
| { |
| return !(*this == other); |
| } |
| |
| InitState FramebufferAttachment::initState() const |
| { |
| return mResource ? mResource->initState(mTarget.binding(), mTarget.textureIndex()) |
| : InitState::Initialized; |
| } |
| |
| angle::Result FramebufferAttachment::initializeContents(const Context *context) |
| { |
| ASSERT(mResource); |
| ANGLE_TRY(mResource->initializeContents(context, mTarget.binding(), mTarget.textureIndex())); |
| setInitState(InitState::Initialized); |
| return angle::Result::Continue; |
| } |
| |
| void FramebufferAttachment::setInitState(InitState initState) const |
| { |
| ASSERT(mResource); |
| mResource->setInitState(mTarget.binding(), mTarget.textureIndex(), initState); |
| } |
| |
| ////// FramebufferAttachmentObject Implementation ////// |
| |
| FramebufferAttachmentObject::FramebufferAttachmentObject() {} |
| |
| FramebufferAttachmentObject::~FramebufferAttachmentObject() {} |
| |
| angle::Result FramebufferAttachmentObject::getAttachmentRenderTarget( |
| const Context *context, |
| GLenum binding, |
| const ImageIndex &imageIndex, |
| GLsizei samples, |
| rx::FramebufferAttachmentRenderTarget **rtOut) const |
| { |
| return getAttachmentImpl()->getAttachmentRenderTarget(context, binding, imageIndex, samples, |
| rtOut); |
| } |
| |
| angle::Result FramebufferAttachmentObject::initializeContents(const Context *context, |
| GLenum binding, |
| const ImageIndex &imageIndex) |
| { |
| ASSERT(context->isRobustResourceInitEnabled()); |
| |
| // Because gl::Texture cannot support tracking individual layer dirtiness, we only handle |
| // initializing entire mip levels for textures with layers |
| if (imageIndex.usesTex3D() && imageIndex.hasLayer()) |
| { |
| // Compute the layer count so we get a correct layer index. |
| const gl::Extents &size = getAttachmentSize(imageIndex); |
| |
| ImageIndex fullMipIndex = ImageIndex::MakeFromType( |
| imageIndex.getType(), imageIndex.getLevelIndex(), ImageIndex::kEntireLevel, size.depth); |
| return getAttachmentImpl()->initializeContents(context, binding, fullMipIndex); |
| } |
| else |
| { |
| return getAttachmentImpl()->initializeContents(context, binding, imageIndex); |
| } |
| } |
| |
| } // namespace gl |