| // | |
| // 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.h: Defines the wrapper class gl::FramebufferAttachment, as well as the | |
| // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. | |
| #ifndef LIBANGLE_FRAMEBUFFERATTACHMENT_H_ | |
| #define LIBANGLE_FRAMEBUFFERATTACHMENT_H_ | |
| #include "angle_gl.h" | |
| #include "common/angleutils.h" | |
| #include "libANGLE/Error.h" | |
| #include "libANGLE/ImageIndex.h" | |
| #include "libANGLE/Observer.h" | |
| #include "libANGLE/angletypes.h" | |
| #include "libANGLE/formatutils.h" | |
| #include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h" | |
| namespace egl | |
| { | |
| class Surface; | |
| } | |
| namespace rx | |
| { | |
| // An implementation-specific object associated with an attachment. | |
| class FramebufferAttachmentRenderTarget : angle::NonCopyable | |
| { | |
| public: | |
| FramebufferAttachmentRenderTarget() {} | |
| virtual ~FramebufferAttachmentRenderTarget() {} | |
| }; | |
| class FramebufferAttachmentObjectImpl; | |
| } // namespace rx | |
| namespace gl | |
| { | |
| class FramebufferAttachmentObject; | |
| class Renderbuffer; | |
| class Texture; | |
| // FramebufferAttachment implements a GL framebuffer attachment. | |
| // Attachments are "light" containers, which store pointers to ref-counted GL objects. | |
| // We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments. | |
| // Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for | |
| // framebuffer attachments, which confused their usage. | |
| class FramebufferAttachment final | |
| { | |
| public: | |
| FramebufferAttachment(); | |
| FramebufferAttachment(const Context *context, | |
| GLenum type, | |
| GLenum binding, | |
| const ImageIndex &textureIndex, | |
| FramebufferAttachmentObject *resource, | |
| rx::Serial framebufferSerial); | |
| FramebufferAttachment(FramebufferAttachment &&other); | |
| FramebufferAttachment &operator=(FramebufferAttachment &&other); | |
| ~FramebufferAttachment(); | |
| void detach(const Context *context, rx::Serial framebufferSerial); | |
| void attach(const Context *context, | |
| GLenum type, | |
| GLenum binding, | |
| const ImageIndex &textureIndex, | |
| FramebufferAttachmentObject *resource, | |
| GLsizei numViews, | |
| GLuint baseViewIndex, | |
| bool isMultiview, | |
| GLsizei samples, | |
| rx::Serial framebufferSerial); | |
| // Helper methods | |
| GLuint getRedSize() const; | |
| GLuint getGreenSize() const; | |
| GLuint getBlueSize() const; | |
| GLuint getAlphaSize() const; | |
| GLuint getDepthSize() const; | |
| GLuint getStencilSize() const; | |
| GLenum getComponentType() const; | |
| GLenum getColorEncoding() const; | |
| bool isTextureWithId(TextureID textureId) const | |
| { | |
| return mType == GL_TEXTURE && id() == textureId.value; | |
| } | |
| bool isExternalTexture() const | |
| { | |
| return mType == GL_TEXTURE && getTextureImageIndex().getType() == gl::TextureType::External; | |
| } | |
| bool isRenderbufferWithId(GLuint renderbufferId) const | |
| { | |
| return mType == GL_RENDERBUFFER && id() == renderbufferId; | |
| } | |
| GLenum getBinding() const { return mTarget.binding(); } | |
| GLuint id() const; | |
| // These methods are only legal to call on Texture attachments | |
| const ImageIndex &getTextureImageIndex() const; | |
| TextureTarget cubeMapFace() const; | |
| GLint mipLevel() const; | |
| GLint layer() const; | |
| bool isLayered() const; | |
| GLsizei getNumViews() const { return mNumViews; } | |
| bool isMultiview() const; | |
| GLint getBaseViewIndex() const; | |
| bool isRenderToTexture() const; | |
| GLsizei getRenderToTextureSamples() const; | |
| // The size of the underlying resource the attachment points to. The 'depth' value will | |
| // correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and | |
| // Renderbuffers, it will always be 1. | |
| Extents getSize() const; | |
| Format getFormat() const; | |
| GLsizei getSamples() const; | |
| // This will always return the actual sample count of the attachment even if | |
| // render_to_texture extension is active on this FBattachment object. | |
| GLsizei getResourceSamples() const; | |
| GLenum type() const { return mType; } | |
| bool isAttached() const { return mType != GL_NONE; } | |
| bool isRenderable(const Context *context) const; | |
| bool isYUV() const; | |
| bool isCreatedWithAHB() const; | |
| Renderbuffer *getRenderbuffer() const; | |
| Texture *getTexture() const; | |
| const egl::Surface *getSurface() const; | |
| FramebufferAttachmentObject *getResource() const; | |
| InitState initState() const; | |
| angle::Result initializeContents(const Context *context); | |
| void setInitState(InitState initState) const; | |
| // "T" must be static_castable from FramebufferAttachmentRenderTarget | |
| template <typename T> | |
| angle::Result getRenderTarget(const Context *context, GLsizei samples, T **rtOut) const | |
| { | |
| static_assert(std::is_base_of<rx::FramebufferAttachmentRenderTarget, T>(), | |
| "Invalid RenderTarget class."); | |
| return getRenderTargetImpl( | |
| context, samples, reinterpret_cast<rx::FramebufferAttachmentRenderTarget **>(rtOut)); | |
| } | |
| bool operator==(const FramebufferAttachment &other) const; | |
| bool operator!=(const FramebufferAttachment &other) const; | |
| static const GLsizei kDefaultNumViews; | |
| static const GLint kDefaultBaseViewIndex; | |
| static const GLint kDefaultRenderToTextureSamples; | |
| private: | |
| angle::Result getRenderTargetImpl(const Context *context, | |
| GLsizei samples, | |
| rx::FramebufferAttachmentRenderTarget **rtOut) const; | |
| // A framebuffer attachment points to one of three types of resources: Renderbuffers, | |
| // Textures and egl::Surface. The "Target" struct indicates which part of the | |
| // object an attachment references. For the three types: | |
| // - a Renderbuffer has a unique renderable target, and needs no target index | |
| // - a Texture has targets for every image and uses an ImageIndex | |
| // - a Surface has targets for Color and Depth/Stencil, and uses the attachment binding | |
| class Target | |
| { | |
| public: | |
| Target(); | |
| Target(GLenum binding, const ImageIndex &imageIndex); | |
| Target(const Target &other); | |
| Target &operator=(const Target &other); | |
| GLenum binding() const { return mBinding; } | |
| const ImageIndex &textureIndex() const { return mTextureIndex; } | |
| private: | |
| GLenum mBinding; | |
| ImageIndex mTextureIndex; | |
| }; | |
| GLenum mType; | |
| Target mTarget; | |
| FramebufferAttachmentObject *mResource; | |
| GLsizei mNumViews; | |
| bool mIsMultiview; | |
| GLint mBaseViewIndex; | |
| // A single-sampled texture can be attached to a framebuffer either as single-sampled or as | |
| // multisampled-render-to-texture. In the latter case, |mRenderToTextureSamples| will contain | |
| // the number of samples. For renderbuffers, the number of samples is inherited from the | |
| // renderbuffer itself. | |
| // | |
| // Note that textures cannot change storage between single and multisample once attached to a | |
| // framebuffer. Renderbuffers instead can, and caching the number of renderbuffer samples here | |
| // can lead to stale data. | |
| GLsizei mRenderToTextureSamples; | |
| }; | |
| // A base class for objects that FBO Attachments may point to. | |
| class FramebufferAttachmentObject : public angle::Subject, public angle::ObserverInterface | |
| { | |
| public: | |
| FramebufferAttachmentObject(); | |
| ~FramebufferAttachmentObject() override; | |
| virtual Extents getAttachmentSize(const ImageIndex &imageIndex) const = 0; | |
| virtual Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const = 0; | |
| virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const = 0; | |
| virtual bool isRenderable(const Context *context, | |
| GLenum binding, | |
| const ImageIndex &imageIndex) const = 0; | |
| virtual bool isYUV() const = 0; | |
| virtual bool isCreatedWithAHB() const = 0; | |
| virtual bool hasProtectedContent() const = 0; | |
| virtual void onAttach(const Context *context, rx::Serial framebufferSerial) = 0; | |
| virtual void onDetach(const Context *context, rx::Serial framebufferSerial) = 0; | |
| virtual GLuint getId() const = 0; | |
| // These are used for robust resource initialization. | |
| virtual InitState initState(GLenum binding, const ImageIndex &imageIndex) const = 0; | |
| virtual void setInitState(GLenum binding, | |
| const ImageIndex &imageIndex, | |
| InitState initState) = 0; | |
| angle::Result getAttachmentRenderTarget(const Context *context, | |
| GLenum binding, | |
| const ImageIndex &imageIndex, | |
| GLsizei samples, | |
| rx::FramebufferAttachmentRenderTarget **rtOut) const; | |
| angle::Result initializeContents(const Context *context, | |
| GLenum binding, | |
| const ImageIndex &imageIndex); | |
| protected: | |
| virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0; | |
| }; | |
| inline const ImageIndex &FramebufferAttachment::getTextureImageIndex() const | |
| { | |
| ASSERT(type() == GL_TEXTURE); | |
| return mTarget.textureIndex(); | |
| } | |
| inline Extents FramebufferAttachment::getSize() const | |
| { | |
| ASSERT(mResource); | |
| return mResource->getAttachmentSize(mTarget.textureIndex()); | |
| } | |
| inline Format FramebufferAttachment::getFormat() const | |
| { | |
| ASSERT(mResource); | |
| return mResource->getAttachmentFormat(mTarget.binding(), mTarget.textureIndex()); | |
| } | |
| inline GLsizei FramebufferAttachment::getSamples() const | |
| { | |
| return isRenderToTexture() ? getRenderToTextureSamples() : getResourceSamples(); | |
| } | |
| inline GLsizei FramebufferAttachment::getResourceSamples() const | |
| { | |
| ASSERT(mResource); | |
| return mResource->getAttachmentSamples(mTarget.textureIndex()); | |
| } | |
| inline angle::Result FramebufferAttachment::getRenderTargetImpl( | |
| const Context *context, | |
| GLsizei samples, | |
| rx::FramebufferAttachmentRenderTarget **rtOut) const | |
| { | |
| ASSERT(mResource); | |
| return mResource->getAttachmentRenderTarget(context, mTarget.binding(), mTarget.textureIndex(), | |
| samples, rtOut); | |
| } | |
| inline bool FramebufferAttachment::isRenderable(const Context *context) const | |
| { | |
| ASSERT(mResource); | |
| return mResource->isRenderable(context, mTarget.binding(), mTarget.textureIndex()); | |
| } | |
| inline bool FramebufferAttachment::isYUV() const | |
| { | |
| ASSERT(mResource); | |
| return mResource->isYUV(); | |
| } | |
| inline bool FramebufferAttachment::isCreatedWithAHB() const | |
| { | |
| ASSERT(mResource); | |
| return mResource->isCreatedWithAHB(); | |
| } | |
| } // namespace gl | |
| #endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_ |