summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/Framebuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/Framebuffer.h')
-rw-r--r--gfx/angle/checkout/src/libANGLE/Framebuffer.h538
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_