forked from mirrors/gecko-dev
		
	Differential Revision: https://phabricator.services.mozilla.com/D36858 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			290 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
#ifndef WEBGL_FRAMEBUFFER_H_
 | 
						|
#define WEBGL_FRAMEBUFFER_H_
 | 
						|
 | 
						|
#include <vector>
 | 
						|
 | 
						|
#include "mozilla/LinkedList.h"
 | 
						|
#include "mozilla/WeakPtr.h"
 | 
						|
#include "nsWrapperCache.h"
 | 
						|
 | 
						|
#include "WebGLObjectModel.h"
 | 
						|
#include "WebGLRenderbuffer.h"
 | 
						|
#include "WebGLStrongTypes.h"
 | 
						|
#include "WebGLTexture.h"
 | 
						|
#include "WebGLTypes.h"
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
 | 
						|
class WebGLFramebuffer;
 | 
						|
class WebGLRenderbuffer;
 | 
						|
class WebGLTexture;
 | 
						|
 | 
						|
template <typename T>
 | 
						|
class PlacementArray;
 | 
						|
 | 
						|
namespace gl {
 | 
						|
class GLContext;
 | 
						|
}  // namespace gl
 | 
						|
 | 
						|
namespace webgl {
 | 
						|
struct FbAttachInfo final {
 | 
						|
  WebGLRenderbuffer* rb = nullptr;
 | 
						|
  WebGLTexture* tex = nullptr;
 | 
						|
  GLint mipLevel = 0;
 | 
						|
  GLint zLayer = 0;
 | 
						|
  GLsizei zLayerCount = 1;
 | 
						|
  bool isMultiview = false;
 | 
						|
};
 | 
						|
}  // namespace webgl
 | 
						|
 | 
						|
class WebGLFBAttachPoint final {
 | 
						|
  friend class WebGLFramebuffer;
 | 
						|
 | 
						|
 public:
 | 
						|
  const GLenum mAttachmentPoint = 0;
 | 
						|
  const bool mDeferAttachment = false;
 | 
						|
 | 
						|
 private:
 | 
						|
  WebGLRefPtr<WebGLTexture> mTexturePtr;
 | 
						|
  WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
 | 
						|
  uint32_t mTexImageLayer = 0;
 | 
						|
  uint8_t mTexImageZLayerCount = 1;
 | 
						|
  uint8_t mTexImageLevel = 0;
 | 
						|
  bool mIsMultiview = false;
 | 
						|
 | 
						|
  ////
 | 
						|
 | 
						|
  WebGLFBAttachPoint() = default;
 | 
						|
  WebGLFBAttachPoint(const WebGLContext* webgl, GLenum attachmentPoint);
 | 
						|
 | 
						|
  explicit WebGLFBAttachPoint(WebGLFBAttachPoint&) =
 | 
						|
      default;  // Make this private.
 | 
						|
 | 
						|
 public:
 | 
						|
  ~WebGLFBAttachPoint();
 | 
						|
 | 
						|
  ////
 | 
						|
 | 
						|
  void Unlink() { Clear(); }
 | 
						|
 | 
						|
  bool HasAttachment() const {
 | 
						|
    return bool(mTexturePtr) | bool(mRenderbufferPtr);
 | 
						|
  }
 | 
						|
  bool IsDeleteRequested() const;
 | 
						|
 | 
						|
  void Clear();
 | 
						|
 | 
						|
  void Set(gl::GLContext* gl, const webgl::FbAttachInfo&);
 | 
						|
 | 
						|
  WebGLTexture* Texture() const { return mTexturePtr; }
 | 
						|
  WebGLRenderbuffer* Renderbuffer() const { return mRenderbufferPtr; }
 | 
						|
 | 
						|
  auto Layer() const { return mTexImageLayer; }
 | 
						|
  auto ZLayerCount() const { return mTexImageZLayerCount; }
 | 
						|
  auto MipLevel() const { return mTexImageLevel; }
 | 
						|
  const auto& IsMultiview() const { return mIsMultiview; }
 | 
						|
 | 
						|
  void AttachmentName(nsCString* out) const;
 | 
						|
 | 
						|
  const webgl::ImageInfo* GetImageInfo() const;
 | 
						|
 | 
						|
  bool IsComplete(WebGLContext* webgl, nsCString* const out_info) const;
 | 
						|
 | 
						|
  void DoAttachment(gl::GLContext* gl) const;
 | 
						|
 | 
						|
  JS::Value GetParameter(WebGLContext* webgl, JSContext* cx, GLenum target,
 | 
						|
                         GLenum attachment, GLenum pname,
 | 
						|
                         ErrorResult* const out_error) const;
 | 
						|
 | 
						|
  bool IsEquivalentForFeedback(const WebGLFBAttachPoint& other) const {
 | 
						|
    if (!HasAttachment() | !other.HasAttachment()) return false;
 | 
						|
 | 
						|
#define _(X) (X == other.X)
 | 
						|
    return (_(mRenderbufferPtr) && _(mTexturePtr) && _(mTexImageLevel) &&
 | 
						|
            _(mTexImageLayer) && _(mTexImageZLayerCount));
 | 
						|
#undef _
 | 
						|
  }
 | 
						|
 | 
						|
  ////
 | 
						|
 | 
						|
  struct Ordered {
 | 
						|
    const WebGLFBAttachPoint& mRef;
 | 
						|
 | 
						|
    explicit Ordered(const WebGLFBAttachPoint& ref) : mRef(ref) {}
 | 
						|
 | 
						|
    bool operator<(const Ordered& other) const {
 | 
						|
      MOZ_ASSERT(mRef.HasAttachment() && other.mRef.HasAttachment());
 | 
						|
 | 
						|
#define ORDER_BY(X) \
 | 
						|
  if (X != other.X) return X < other.X;
 | 
						|
 | 
						|
      ORDER_BY(mRef.mRenderbufferPtr)
 | 
						|
      ORDER_BY(mRef.mTexturePtr)
 | 
						|
      ORDER_BY(mRef.mTexImageLevel)
 | 
						|
      ORDER_BY(mRef.mTexImageLayer)
 | 
						|
      ORDER_BY(mRef.mTexImageZLayerCount)
 | 
						|
 | 
						|
#undef ORDER_BY
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  };
 | 
						|
};
 | 
						|
 | 
						|
class WebGLFramebuffer final : public nsWrapperCache,
 | 
						|
                               public WebGLRefCountedObject<WebGLFramebuffer>,
 | 
						|
                               public LinkedListElement<WebGLFramebuffer>,
 | 
						|
                               public SupportsWeakPtr<WebGLFramebuffer>,
 | 
						|
                               public CacheInvalidator {
 | 
						|
 public:
 | 
						|
  MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLFramebuffer)
 | 
						|
 | 
						|
  const GLuint mGLName;
 | 
						|
  bool mHasBeenBound = false;
 | 
						|
 | 
						|
 private:
 | 
						|
  mutable uint64_t mNumFBStatusInvals = 0;
 | 
						|
 | 
						|
  ////
 | 
						|
 | 
						|
 protected:
 | 
						|
  WebGLFBAttachPoint mDepthAttachment;
 | 
						|
  WebGLFBAttachPoint mStencilAttachment;
 | 
						|
  WebGLFBAttachPoint mDepthStencilAttachment;
 | 
						|
 | 
						|
  // In theory, this number can be unbounded based on the driver. However, no
 | 
						|
  // driver appears to expose more than 8. We might as well stop there too, for
 | 
						|
  // now.
 | 
						|
  // (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS)
 | 
						|
  static const size_t kMaxColorAttachments =
 | 
						|
      8;  // jgilbert's MacBook Pro exposes 8.
 | 
						|
  WebGLFBAttachPoint mColorAttachments[kMaxColorAttachments];
 | 
						|
 | 
						|
  ////
 | 
						|
 | 
						|
  std::vector<WebGLFBAttachPoint*> mAttachments;  // Non-null.
 | 
						|
 | 
						|
  std::vector<const WebGLFBAttachPoint*> mColorDrawBuffers;  // Non-null
 | 
						|
  const WebGLFBAttachPoint* mColorReadBuffer;                // Null if NONE
 | 
						|
 | 
						|
  ////
 | 
						|
 | 
						|
  struct CompletenessInfo final {
 | 
						|
    const WebGLFramebuffer* fb = nullptr;
 | 
						|
 | 
						|
    uint32_t width = 0;
 | 
						|
    uint32_t height = 0;
 | 
						|
    bool hasFloat32 = false;
 | 
						|
    uint8_t zLayerCount = 1;
 | 
						|
    bool isMultiview = false;
 | 
						|
 | 
						|
    // IsFeedback
 | 
						|
    std::vector<const WebGLFBAttachPoint*> texAttachments;  // Non-null
 | 
						|
 | 
						|
    ~CompletenessInfo();
 | 
						|
  };
 | 
						|
  friend struct CompletenessInfo;
 | 
						|
 | 
						|
  mutable CacheMaybe<const CompletenessInfo> mCompletenessInfo;
 | 
						|
 | 
						|
  ////
 | 
						|
 | 
						|
 public:
 | 
						|
  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer)
 | 
						|
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebuffer)
 | 
						|
 | 
						|
  WebGLFramebuffer(WebGLContext* webgl, GLuint fbo);
 | 
						|
 | 
						|
  WebGLContext* GetParentObject() const { return mContext; }
 | 
						|
  virtual JSObject* WrapObject(JSContext* cx,
 | 
						|
                               JS::Handle<JSObject*> givenProto) override;
 | 
						|
 | 
						|
 private:
 | 
						|
  ~WebGLFramebuffer() {
 | 
						|
    DeleteOnce();
 | 
						|
    InvalidateCaches();
 | 
						|
  }
 | 
						|
 | 
						|
 public:
 | 
						|
  void Delete();
 | 
						|
 | 
						|
  ////
 | 
						|
 | 
						|
  bool HasDuplicateAttachments() const;
 | 
						|
  bool HasDefinedAttachments() const;
 | 
						|
  bool HasIncompleteAttachments(nsCString* const out_info) const;
 | 
						|
  bool AllImageRectsMatch() const;
 | 
						|
  bool AllImageSamplesMatch() const;
 | 
						|
  FBStatus PrecheckFramebufferStatus(nsCString* const out_info) const;
 | 
						|
 | 
						|
 protected:
 | 
						|
  Maybe<WebGLFBAttachPoint*> GetAttachPoint(GLenum attachment);  // Fallible
 | 
						|
  Maybe<WebGLFBAttachPoint*> GetColorAttachPoint(
 | 
						|
      GLenum attachment);  // Fallible
 | 
						|
  void DoDeferredAttachments() const;
 | 
						|
  void RefreshDrawBuffers() const;
 | 
						|
  void RefreshReadBuffer() const;
 | 
						|
  void ResolveAttachmentData() const;
 | 
						|
 | 
						|
 public:
 | 
						|
  void DetachTexture(const WebGLTexture* tex);
 | 
						|
  void DetachRenderbuffer(const WebGLRenderbuffer* rb);
 | 
						|
  bool ValidateAndInitAttachments(GLenum incompleteFbError) const;
 | 
						|
  bool ValidateClearBufferType(GLenum buffer, uint32_t drawBuffer,
 | 
						|
                               GLenum funcType) const;
 | 
						|
 | 
						|
  bool ValidateForColorRead(const webgl::FormatUsageInfo** out_format,
 | 
						|
                            uint32_t* out_width, uint32_t* out_height) const;
 | 
						|
 | 
						|
  ////////////////
 | 
						|
  // Getters
 | 
						|
 | 
						|
#define GETTER(X) \
 | 
						|
  const decltype(m##X)& X() const { return m##X; }
 | 
						|
 | 
						|
  GETTER(DepthAttachment)
 | 
						|
  GETTER(StencilAttachment)
 | 
						|
  GETTER(DepthStencilAttachment)
 | 
						|
  GETTER(Attachments)
 | 
						|
  GETTER(ColorDrawBuffers)
 | 
						|
  GETTER(ColorReadBuffer)
 | 
						|
 | 
						|
#undef GETTER
 | 
						|
 | 
						|
  const auto& ColorAttachment0() const { return mColorAttachments[0]; }
 | 
						|
 | 
						|
  ////////////////
 | 
						|
  // Invalidation
 | 
						|
 | 
						|
  const auto* GetCompletenessInfo() const { return mCompletenessInfo.get(); }
 | 
						|
 | 
						|
  ////////////////
 | 
						|
  // WebGL funcs
 | 
						|
 | 
						|
  bool IsCheckFramebufferStatusComplete() const {
 | 
						|
    return CheckFramebufferStatus() == LOCAL_GL_FRAMEBUFFER_COMPLETE;
 | 
						|
  }
 | 
						|
 | 
						|
  FBStatus CheckFramebufferStatus() const;
 | 
						|
  void FramebufferAttach(GLenum attachEnum,
 | 
						|
                         const webgl::FbAttachInfo& toAttach);
 | 
						|
  void DrawBuffers(const dom::Sequence<GLenum>& buffers);
 | 
						|
  void ReadBuffer(GLenum attachPoint);
 | 
						|
 | 
						|
  JS::Value GetAttachmentParameter(JSContext* cx, GLenum target,
 | 
						|
                                   GLenum attachment, GLenum pname,
 | 
						|
                                   ErrorResult* const out_error);
 | 
						|
 | 
						|
  static void BlitFramebuffer(WebGLContext* webgl, GLint srcX0, GLint srcY0,
 | 
						|
                              GLint srcX1, GLint srcY1, GLint dstX0,
 | 
						|
                              GLint dstY0, GLint dstX1, GLint dstY1,
 | 
						|
                              GLbitfield mask, GLenum filter);
 | 
						|
};
 | 
						|
 | 
						|
}  // namespace mozilla
 | 
						|
 | 
						|
#endif  // WEBGL_FRAMEBUFFER_H_
 |