diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/Framebuffer.h')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/Framebuffer.h | 538 |
1 files changed, 538 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..024ad49687 --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/Framebuffer.h @@ -0,0 +1,538 @@ +// +// Copyright 2002 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" +#include "libANGLE/State.h" +#include "libANGLE/angletypes.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; +class PixelLocalStorage; +class Renderbuffer; +class TextureCapsMap; + +struct FramebufferStatus +{ + bool isComplete() const; + + static FramebufferStatus Complete(); + static FramebufferStatus Incomplete(GLenum status, const char *reason); + + GLenum status = GL_FRAMEBUFFER_COMPLETE; + const char *reason = nullptr; +}; + +class FramebufferState final : angle::NonCopyable +{ + public: + explicit FramebufferState(rx::Serial serial); + FramebufferState(const Caps &caps, FramebufferID id, rx::Serial serial); + ~FramebufferState(); + + const std::string &getLabel() const; + uint32_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 FramebufferAttachment *getReadPixelsAttachment(GLenum readFormat) const; + + const DrawBuffersVector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; } + DrawBufferMask getEnabledDrawBuffers() const { return mEnabledDrawBuffers; } + GLenum getReadBufferState() const { return mReadBufferState; } + + const DrawBuffersVector<FramebufferAttachment> &getColorAttachments() const + { + return mColorAttachments; + } + const DrawBufferMask getColorAttachmentsMask() const { return mColorAttachmentsMask; } + + const Extents getAttachmentExtentsIntersection() const; + 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 getFlipY() const { return mFlipY; } + + bool hasDepth() const; + bool hasStencil() const; + + bool hasExternalTextureAttachment() const; + bool hasYUVAttachment() 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; + + SrgbWriteControlMode getWriteControlMode() const { return mSrgbWriteControlMode; } + + FramebufferID id() const { return mId; } + + bool isDefault() const; + + const Offset &getSurfaceTextureOffset() const { return mSurfaceTextureOffset; } + + rx::Serial getFramebufferSerial() const { return mFramebufferSerial; } + + bool isBoundAsDrawFramebuffer(const Context *context) const; + + private: + const FramebufferAttachment *getWebGLDepthStencilAttachment() const; + const FramebufferAttachment *getWebGLDepthAttachment() const; + const FramebufferAttachment *getWebGLStencilAttachment() const; + + friend class Framebuffer; + + // The Framebuffer ID is unique to a Context. + // The Framebuffer Serial is unique to a Share Group. + FramebufferID mId; + rx::Serial mFramebufferSerial; + std::string mLabel; + + DrawBuffersVector<FramebufferAttachment> mColorAttachments; + FramebufferAttachment mDepthAttachment; + FramebufferAttachment mStencilAttachment; + + // Tracks all the color buffers attached to this FramebufferDesc + DrawBufferMask mColorAttachmentsMask; + + DrawBuffersVector<GLenum> mDrawBufferStates; + GLenum mReadBufferState; + DrawBufferMask mEnabledDrawBuffers; + ComponentTypeMask mDrawBufferTypeMask; + + GLint mDefaultWidth; + GLint mDefaultHeight; + GLint mDefaultSamples; + bool mDefaultFixedSampleLocations; + GLint mDefaultLayers; + bool mFlipY; + + // 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; + + bool mDefaultFramebufferReadAttachmentInitialized; + FramebufferAttachment mDefaultFramebufferReadAttachment; + + // EXT_sRGB_write_control + SrgbWriteControlMode mSrgbWriteControlMode; + + Offset mSurfaceTextureOffset; +}; + +class Framebuffer final : public angle::ObserverInterface, + public LabeledObject, + public angle::Subject +{ + public: + // Constructor to build default framebuffers. + Framebuffer(const Context *context, rx::GLImplFactory *factory); + // Constructor to build application-defined framebuffers + Framebuffer(const Context *context, rx::GLImplFactory *factory, FramebufferID id); + + ~Framebuffer() override; + void onDestroy(const Context *context); + + egl::Error setSurfaces(const Context *context, + egl::Surface *surface, + egl::Surface *readSurface); + void setReadSurface(const Context *context, egl::Surface *readSurface); + egl::Error unsetSurfaces(const Context *context); + angle::Result setLabel(const Context *context, const std::string &label) override; + const std::string &getLabel() const override; + + rx::FramebufferImpl *getImplementation() const { return mImpl; } + + FramebufferID id() const { return mState.mId; } + + void setAttachment(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource); + void setAttachmentMultisample(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource, + GLsizei samples); + 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, TextureID texture); + bool detachRenderbuffer(const Context *context, RenderbufferID 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 DrawBuffersVector<FramebufferAttachment> &getColorAttachments() const + { + return mState.mColorAttachments; + } + + const FramebufferState &getState() const { return mState; } + + 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 DrawBuffersVector<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 hasExternalTextureAttachment() const; + bool hasYUVAttachment() const; + + bool usingExtendedDrawBuffers() const; + + // This method calls checkStatus. + int getSamples(const Context *context) const; + int getReadBufferResourceSamples(const Context *context) const; + + 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; + bool getFlipY() 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 setFlipY(bool flipY); + + void invalidateCompletenessCache(); + ANGLE_INLINE bool cachedStatusValid() { return mCachedStatus.valid(); } + + ANGLE_INLINE const FramebufferStatus &checkStatus(const Context *context) const + { + // The default framebuffer is always complete except when it is surfaceless in which + // case it is always unsupported. + ASSERT(!isDefault() || mCachedStatus.valid()); + if (isDefault() || (!hasAnyDirtyBit() && mCachedStatus.valid())) + { + return mCachedStatus.value(); + } + + return checkStatusImpl(context); + } + + // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE. + ANGLE_INLINE bool isComplete(const Context *context) const + { + return checkStatus(context).isComplete(); + } + + bool hasValidDepthStencil() const; + + // Returns the offset into the texture backing the default framebuffer's surface if any. Returns + // zero offset otherwise. The renderer will apply the offset to scissor and viewport rects used + // for draws, clears, and blits. + const Offset &getSurfaceTextureOffset() 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); + + GLenum getImplementationColorReadFormat(const Context *context); + GLenum getImplementationColorReadType(const Context *context); + + angle::Result readPixels(const Context *context, + const Rectangle &area, + GLenum format, + GLenum type, + const PixelPackState &pack, + Buffer *packBuffer, + void *pixels); + + angle::Result blit(const Context *context, + const Rectangle &sourceArea, + const Rectangle &destArea, + GLbitfield mask, + GLenum filter); + bool isDefault() const { return mState.isDefault(); } + + enum DirtyBitType : size_t + { + DIRTY_BIT_COLOR_ATTACHMENT_0, + DIRTY_BIT_COLOR_ATTACHMENT_MAX = + DIRTY_BIT_COLOR_ATTACHMENT_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS, + 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_DRAW_BUFFERS, + DIRTY_BIT_DEPTH_BUFFER_CONTENTS = DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX, + 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_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE, + DIRTY_BIT_FLIP_Y, + DIRTY_BIT_UNKNOWN, + DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN + }; + + using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; + bool hasAnyDirtyBit() const { return mDirtyBits.any(); } + + DrawBufferMask getActiveFloat32ColorAttachmentDrawBufferMask() const + { + return mFloat32ColorAttachmentBits & getDrawBufferMask(); + } + + bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); } + + angle::Result syncState(const Context *context, + GLenum framebufferBinding, + Command command) const; + + void setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode); + + // Observer implementation + void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; + + bool formsRenderingFeedbackLoopWith(const Context *context) const; + bool formsCopyingFeedbackLoopWith(TextureID 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; + + // ANGLE_shader_pixel_local_storage. + // Lazily creates a PixelLocalStorage object for this Framebuffer. + PixelLocalStorage &getPixelLocalStorage(const Context *); + // Returns nullptr if the pixel local storage object has not been created yet. + const PixelLocalStorage *peekPixelLocalStorage() const { return mPixelLocalStorage.get(); } + // Detaches the the pixel local storage object so the Context can call deleteContextObjects(). + std::unique_ptr<PixelLocalStorage> detachPixelLocalStorage(); + + static const FramebufferID kDefaultDrawFramebufferHandle; + + private: + bool detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId); + bool detachMatchingAttachment(const Context *context, + FramebufferAttachment *attachment, + GLenum matchType, + GLuint matchId); + FramebufferStatus checkStatusWithGLFrontEnd(const Context *context) const; + const FramebufferStatus &checkStatusImpl(const Context *context) const; + void setAttachment(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource, + GLsizei numViews, + GLuint baseViewIndex, + bool isMultiview, + GLsizei samplesIn); + void commitWebGL1DepthStencilIfConsistent(const Context *context, + GLsizei numViews, + GLuint baseViewIndex, + bool isMultiview, + GLsizei samples); + void setAttachmentImpl(const Context *context, + GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource, + GLsizei numViews, + GLuint baseViewIndex, + bool isMultiview, + GLsizei samples); + 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, + GLsizei samples); + + 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 InternalFormat *format) + { + mFloat32ColorAttachmentBits.set(index, format->type == GL_FLOAT); + } + + FramebufferState mState; + rx::FramebufferImpl *mImpl; + + mutable Optional<FramebufferStatus> mCachedStatus; + DrawBuffersVector<angle::ObserverBinding> mDirtyColorAttachmentBindings; + angle::ObserverBinding mDirtyDepthAttachmentBinding; + angle::ObserverBinding mDirtyStencilAttachmentBinding; + + mutable DirtyBits mDirtyBits; + DrawBufferMask mFloat32ColorAttachmentBits; + + // 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. + mutable Optional<DirtyBits> mDirtyBitsGuard; + + // ANGLE_shader_pixel_local_storage + std::unique_ptr<PixelLocalStorage> mPixelLocalStorage; +}; + +using UniqueFramebufferPointer = angle::UniqueObjectPointer<Framebuffer, Context>; + +} // namespace gl + +#endif // LIBANGLE_FRAMEBUFFER_H_ |