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.h445
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_