diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/Framebuffer.h')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/Framebuffer.h | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/Framebuffer.h b/gfx/angle/checkout/src/libANGLE/Framebuffer.h new file mode 100644 index 0000000000..3d38cb2570 --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/Framebuffer.h @@ -0,0 +1,445 @@ +// +// Copyright (c) 2002-2013 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. +// + +// Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. + +#ifndef LIBANGLE_FRAMEBUFFER_H_ +#define LIBANGLE_FRAMEBUFFER_H_ + +#include <vector> + +#include "common/FixedVector.h" +#include "common/Optional.h" +#include "common/angleutils.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Debug.h" +#include "libANGLE/Error.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Observer.h" +#include "libANGLE/RefCountObject.h" + +namespace rx +{ +class GLImplFactory; +class FramebufferImpl; +class RenderbufferImpl; +class SurfaceImpl; +} // namespace rx + +namespace egl +{ +class Display; +class Surface; +} // namespace egl + +namespace gl +{ +struct Caps; +class Context; +struct Extensions; +class Framebuffer; +class ImageIndex; +struct Rectangle; +class Renderbuffer; +class State; +class Texture; +class TextureCapsMap; + +class FramebufferState final : angle::NonCopyable +{ + public: + FramebufferState(); + explicit FramebufferState(const Caps &caps, GLuint id); + ~FramebufferState(); + + const std::string &getLabel(); + size_t getReadIndex() const; + + const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const; + const FramebufferAttachment *getReadAttachment() const; + const FramebufferAttachment *getFirstNonNullAttachment() const; + const FramebufferAttachment *getFirstColorAttachment() const; + const FramebufferAttachment *getDepthOrStencilAttachment() const; + const FramebufferAttachment *getStencilOrDepthStencilAttachment() const; + const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const; + const FramebufferAttachment *getDepthAttachment() const; + const FramebufferAttachment *getStencilAttachment() const; + const FramebufferAttachment *getDepthStencilAttachment() const; + + const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; } + DrawBufferMask getEnabledDrawBuffers() const { return mEnabledDrawBuffers; } + GLenum getReadBufferState() const { return mReadBufferState; } + const std::vector<FramebufferAttachment> &getColorAttachments() const + { + return mColorAttachments; + } + + bool attachmentsHaveSameDimensions() const; + bool hasSeparateDepthAndStencilAttachments() const; + bool colorAttachmentsAreUniqueImages() const; + Box getDimensions() const; + Extents getExtents() const; + + const FramebufferAttachment *getDrawBuffer(size_t drawBufferIdx) const; + size_t getDrawBufferCount() const; + + GLint getDefaultWidth() const { return mDefaultWidth; } + GLint getDefaultHeight() const { return mDefaultHeight; } + GLint getDefaultSamples() const { return mDefaultSamples; } + bool getDefaultFixedSampleLocations() const { return mDefaultFixedSampleLocations; } + GLint getDefaultLayers() const { return mDefaultLayers; } + + bool hasDepth() const; + bool hasStencil() const; + + bool isMultiview() const; + + ANGLE_INLINE GLsizei getNumViews() const + { + const FramebufferAttachment *attachment = getFirstNonNullAttachment(); + if (attachment == nullptr) + { + return FramebufferAttachment::kDefaultNumViews; + } + return attachment->getNumViews(); + } + + GLint getBaseViewIndex() const; + + GLuint id() const { return mId; } + + private: + const FramebufferAttachment *getWebGLDepthStencilAttachment() const; + const FramebufferAttachment *getWebGLDepthAttachment() const; + const FramebufferAttachment *getWebGLStencilAttachment() const; + + friend class Framebuffer; + + GLuint mId; + std::string mLabel; + + std::vector<FramebufferAttachment> mColorAttachments; + FramebufferAttachment mDepthAttachment; + FramebufferAttachment mStencilAttachment; + + std::vector<GLenum> mDrawBufferStates; + GLenum mReadBufferState; + DrawBufferMask mEnabledDrawBuffers; + ComponentTypeMask mDrawBufferTypeMask; + + GLint mDefaultWidth; + GLint mDefaultHeight; + GLint mDefaultSamples; + bool mDefaultFixedSampleLocations; + GLint mDefaultLayers; + + // It's necessary to store all this extra state so we can restore attachments + // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1. + FramebufferAttachment mWebGLDepthStencilAttachment; + FramebufferAttachment mWebGLDepthAttachment; + FramebufferAttachment mWebGLStencilAttachment; + bool mWebGLDepthStencilConsistent; + + // Tracks if we need to initialize the resources for each attachment. + angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit; +}; + +class Framebuffer final : public angle::ObserverInterface, + public LabeledObject, + public angle::Subject +{ + public: + // Constructor to build application-defined framebuffers + Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id); + // Constructor to build default framebuffers for a surface and context pair + Framebuffer(const Context *context, egl::Surface *surface); + // Constructor to build a fake default framebuffer when surfaceless + Framebuffer(rx::GLImplFactory *factory); + + ~Framebuffer() override; + void onDestroy(const Context *context); + + void setLabel(const Context *context, const std::string &label) override; + const std::string &getLabel() const override; + + rx::FramebufferImpl *getImplementation() const { return mImpl; } + + GLuint id() const { return mState.mId; } + + void setAttachment(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource); + void setAttachmentMultiview(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource, + GLsizei numViews, + GLint baseViewIndex); + void resetAttachment(const Context *context, GLenum binding); + + bool detachTexture(const Context *context, GLuint texture); + bool detachRenderbuffer(const Context *context, GLuint renderbuffer); + + const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const; + const FramebufferAttachment *getDepthAttachment() const; + const FramebufferAttachment *getStencilAttachment() const; + const FramebufferAttachment *getDepthStencilAttachment() const; + const FramebufferAttachment *getDepthOrStencilAttachment() const; + const FramebufferAttachment *getStencilOrDepthStencilAttachment() const; + const FramebufferAttachment *getReadColorAttachment() const; + GLenum getReadColorAttachmentType() const; + const FramebufferAttachment *getFirstColorAttachment() const; + const FramebufferAttachment *getFirstNonNullAttachment() const; + + const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const; + bool isMultiview() const; + bool readDisallowedByMultiview() const; + GLsizei getNumViews() const; + GLint getBaseViewIndex() const; + Extents getExtents() const; + + size_t getDrawbufferStateCount() const; + GLenum getDrawBufferState(size_t drawBuffer) const; + const std::vector<GLenum> &getDrawBufferStates() const; + void setDrawBuffers(size_t count, const GLenum *buffers); + const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const; + ComponentType getDrawbufferWriteType(size_t drawBuffer) const; + ComponentTypeMask getDrawBufferTypeMask() const; + DrawBufferMask getDrawBufferMask() const; + bool hasEnabledDrawBuffer() const; + + GLenum getReadBufferState() const; + void setReadBuffer(GLenum buffer); + + size_t getNumColorAttachments() const; + bool hasDepth() const; + bool hasStencil() const; + + bool usingExtendedDrawBuffers() const; + + // This method calls checkStatus. + int getSamples(const Context *context); + + angle::Result getSamplePosition(const Context *context, size_t index, GLfloat *xy) const; + + GLint getDefaultWidth() const; + GLint getDefaultHeight() const; + GLint getDefaultSamples() const; + bool getDefaultFixedSampleLocations() const; + GLint getDefaultLayers() const; + void setDefaultWidth(const Context *context, GLint defaultWidth); + void setDefaultHeight(const Context *context, GLint defaultHeight); + void setDefaultSamples(const Context *context, GLint defaultSamples); + void setDefaultFixedSampleLocations(const Context *context, bool defaultFixedSampleLocations); + void setDefaultLayers(GLint defaultLayers); + + void invalidateCompletenessCache(); + + ANGLE_INLINE GLenum checkStatus(const Context *context) + { + // The default framebuffer is always complete except when it is surfaceless in which + // case it is always unsupported. + ASSERT(mState.mId != 0 || mCachedStatus.valid()); + if (mState.mId == 0 || (!hasAnyDirtyBit() && mCachedStatus.valid())) + { + return mCachedStatus.value(); + } + + return checkStatusImpl(context); + } + + // For when we don't want to check completeness in getSamples(). + int getCachedSamples(const Context *context) const; + + // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE. + ANGLE_INLINE bool isComplete(const Context *context) + { + return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE); + } + + bool hasValidDepthStencil() const; + + angle::Result discard(const Context *context, size_t count, const GLenum *attachments); + angle::Result invalidate(const Context *context, size_t count, const GLenum *attachments); + angle::Result invalidateSub(const Context *context, + size_t count, + const GLenum *attachments, + const Rectangle &area); + + angle::Result clear(const Context *context, GLbitfield mask); + angle::Result clearBufferfv(const Context *context, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values); + angle::Result clearBufferuiv(const Context *context, + GLenum buffer, + GLint drawbuffer, + const GLuint *values); + angle::Result clearBufferiv(const Context *context, + GLenum buffer, + GLint drawbuffer, + const GLint *values); + angle::Result clearBufferfi(const Context *context, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil); + + // These two methods call syncState() internally. + angle::Result getImplementationColorReadFormat(const Context *context, GLenum *formatOut); + angle::Result getImplementationColorReadType(const Context *context, GLenum *typeOut); + + angle::Result readPixels(const Context *context, + const Rectangle &area, + GLenum format, + GLenum type, + void *pixels); + + angle::Result blit(const Context *context, + const Rectangle &sourceArea, + const Rectangle &destArea, + GLbitfield mask, + GLenum filter); + bool isDefault() const; + + enum DirtyBitType : size_t + { + DIRTY_BIT_COLOR_ATTACHMENT_0, + DIRTY_BIT_COLOR_ATTACHMENT_MAX = + DIRTY_BIT_COLOR_ATTACHMENT_0 + IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS, + DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX, + DIRTY_BIT_STENCIL_ATTACHMENT, + DIRTY_BIT_COLOR_BUFFER_CONTENTS_0, + DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX = + DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS, + DIRTY_BIT_DEPTH_BUFFER_CONTENTS, + DIRTY_BIT_STENCIL_BUFFER_CONTENTS, + DIRTY_BIT_DRAW_BUFFERS, + DIRTY_BIT_READ_BUFFER, + DIRTY_BIT_DEFAULT_WIDTH, + DIRTY_BIT_DEFAULT_HEIGHT, + DIRTY_BIT_DEFAULT_SAMPLES, + DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS, + DIRTY_BIT_DEFAULT_LAYERS, + DIRTY_BIT_UNKNOWN, + DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN + }; + + using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; + bool hasAnyDirtyBit() const { return mDirtyBits.any(); } + + bool hasActiveFloat32ColorAttachment() const + { + return (mFloat32ColorAttachmentBits & getDrawBufferMask()).any(); + } + + bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); } + + angle::Result syncState(const Context *context); + + // Observer implementation + void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; + + bool formsRenderingFeedbackLoopWith(const Context *context) const; + bool formsCopyingFeedbackLoopWith(GLuint copyTextureID, + GLint copyTextureLevel, + GLint copyTextureLayer) const; + + angle::Result ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask); + angle::Result ensureClearBufferAttachmentsInitialized(const Context *context, + GLenum buffer, + GLint drawbuffer); + angle::Result ensureDrawAttachmentsInitialized(const Context *context); + + // Conservatively initializes both read color and depth. Blit can access the depth buffer. + angle::Result ensureReadAttachmentsInitialized(const Context *context); + Box getDimensions() const; + + private: + bool detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId); + bool detachMatchingAttachment(const Context *context, + FramebufferAttachment *attachment, + GLenum matchType, + GLuint matchId); + GLenum checkStatusWithGLFrontEnd(const Context *context); + GLenum checkStatusImpl(const Context *context); + void setAttachment(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource, + GLsizei numViews, + GLuint baseViewIndex, + bool isMultiview); + void commitWebGL1DepthStencilIfConsistent(const Context *context, + GLsizei numViews, + GLuint baseViewIndex, + bool isMultiview); + void setAttachmentImpl(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource, + GLsizei numViews, + GLuint baseViewIndex, + bool isMultiview); + void updateAttachment(const Context *context, + FramebufferAttachment *attachment, + size_t dirtyBit, + angle::ObserverBinding *onDirtyBinding, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource, + GLsizei numViews, + GLuint baseViewIndex, + bool isMultiview); + + void markDrawAttachmentsInitialized(bool color, bool depth, bool stencil); + void markBufferInitialized(GLenum bufferType, GLint bufferIndex); + angle::Result ensureBufferInitialized(const Context *context, + GLenum bufferType, + GLint bufferIndex); + + // Checks that we have a partially masked clear: + // * some color channels are masked out + // * some stencil values are masked out + // * scissor test partially overlaps the framebuffer + bool partialClearNeedsInit(const Context *context, bool color, bool depth, bool stencil); + bool partialBufferClearNeedsInit(const Context *context, GLenum bufferType); + + FramebufferAttachment *getAttachmentFromSubjectIndex(angle::SubjectIndex index); + + ANGLE_INLINE void updateFloat32ColorAttachmentBits(size_t index, + const gl::InternalFormat *format) + { + mFloat32ColorAttachmentBits.set(index, format->type == GL_FLOAT); + } + + FramebufferState mState; + rx::FramebufferImpl *mImpl; + + Optional<GLenum> mCachedStatus; + std::vector<angle::ObserverBinding> mDirtyColorAttachmentBindings; + angle::ObserverBinding mDirtyDepthAttachmentBinding; + angle::ObserverBinding mDirtyStencilAttachmentBinding; + + DirtyBits mDirtyBits; + DrawBufferMask mFloat32ColorAttachmentBits; + DrawBufferMask mColorAttachmentBits; + + // The dirty bits guard is checked when we get a dependent state change message. We verify that + // we don't set a dirty bit that isn't already set, when inside the dirty bits syncState. + Optional<DirtyBits> mDirtyBitsGuard; +}; + +} // namespace gl + +#endif // LIBANGLE_FRAMEBUFFER_H_ |