#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
{
class FramebufferAttachmentRenderTarget : angle::NonCopyable
{
public:
FramebufferAttachmentRenderTarget() {}
virtual ~FramebufferAttachmentRenderTarget() {}
};
class FramebufferAttachmentObjectImpl;
}
namespace gl
{
class FramebufferAttachmentObject;
class Renderbuffer;
class Texture;
class FramebufferAttachment final
{
public:
FramebufferAttachment();
FramebufferAttachment(const Context *context,
GLenum type,
GLenum binding,
const ImageIndex &textureIndex,
FramebufferAttachmentObject *resource,
rx::UniqueSerial framebufferSerial);
FramebufferAttachment(FramebufferAttachment &&other);
FramebufferAttachment &operator=(FramebufferAttachment &&other);
~FramebufferAttachment();
void detach(const Context *context, rx::UniqueSerial framebufferSerial);
void attach(const Context *context,
GLenum type,
GLenum binding,
const ImageIndex &textureIndex,
FramebufferAttachmentObject *resource,
GLsizei numViews,
GLuint baseViewIndex,
bool isMultiview,
GLsizei samples,
rx::UniqueSerial framebufferSerial);
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;
const ImageIndex &getTextureImageIndex() const;
TextureTarget cubeMapFace() const;
GLint mipLevel() const;
GLint layer() const;
bool hasLayer() const;
bool isLayered() const;
GLsizei getNumViews() const { return mNumViews; }
bool isMultiview() const;
GLint getBaseViewIndex() const;
bool isRenderToTexture() const;
GLsizei getRenderToTextureSamples() const;
angle::Result ensureSizeResolved(const Context *context) const;
Extents getSize() const;
Format getFormat() const;
GLsizei getSamples() const;
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 isExternalImageWithoutIndividualSync() const;
bool hasFrontBufferUsage() const;
bool hasFoveatedRendering() const;
const gl::FoveationState *getFoveationState() const;
Renderbuffer *getRenderbuffer() const;
Texture *getTexture() const;
const egl::Surface *getSurface() const;
FramebufferAttachmentObject *getResource() const;
InitState initState() const;
angle::Result initializeContents(const Context *context) const;
void setInitState(InitState initState) const;
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:
bool isSpecified() const;
angle::Result getRenderTargetImpl(const Context *context,
GLsizei samples,
rx::FramebufferAttachmentRenderTarget **rtOut) const;
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;
GLsizei mRenderToTextureSamples;
};
class FramebufferAttachmentObject : public angle::Subject, public angle::ObserverInterface
{
public:
FramebufferAttachmentObject();
~FramebufferAttachmentObject() override;
virtual angle::Result ensureSizeResolved(const Context *context) const = 0;
virtual bool isAttachmentSpecified(const ImageIndex &imageIndex) const = 0;
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 isExternalImageWithoutIndividualSync() const = 0;
virtual bool hasFrontBufferUsage() const = 0;
virtual bool hasProtectedContent() const = 0;
virtual bool hasFoveatedRendering() const = 0;
virtual const gl::FoveationState *getFoveationState() const = 0;
virtual void onAttach(const Context *context, rx::UniqueSerial framebufferSerial) = 0;
virtual void onDetach(const Context *context, rx::UniqueSerial framebufferSerial) = 0;
virtual GLuint getId() const = 0;
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 angle::Result FramebufferAttachment::ensureSizeResolved(const Context *context) const
{
ASSERT(mResource);
return mResource->ensureSizeResolved(context);
}
inline bool FramebufferAttachment::isSpecified() const
{
ASSERT(mResource);
return mResource->isAttachmentSpecified(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::isExternalImageWithoutIndividualSync() const
{
ASSERT(mResource);
return mResource->isExternalImageWithoutIndividualSync();
}
inline bool FramebufferAttachment::hasFrontBufferUsage() const
{
ASSERT(mResource);
return mResource->hasFrontBufferUsage();
}
inline bool FramebufferAttachment::hasFoveatedRendering() const
{
ASSERT(mResource);
return mResource->hasFoveatedRendering();
}
inline const gl::FoveationState *FramebufferAttachment::getFoveationState() const
{
ASSERT(mResource);
return mResource->getFoveationState();
}
}
#endif