WebGLFramebuffer.h (7787B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef WEBGL_FRAMEBUFFER_H_ 7 #define WEBGL_FRAMEBUFFER_H_ 8 9 #include <bitset> 10 #include <vector> 11 12 #include "GLScreenBuffer.h" 13 #include "WebGLObjectModel.h" 14 #include "WebGLStrongTypes.h" 15 #include "WebGLTexture.h" 16 #include "WebGLTypes.h" 17 #include "mozilla/WeakPtr.h" 18 19 namespace mozilla { 20 21 class WebGLFramebuffer; 22 class WebGLRenderbuffer; 23 class WebGLTexture; 24 25 template <typename T> 26 class PlacementArray; 27 28 namespace gl { 29 class GLContext; 30 class MozFramebuffer; 31 } // namespace gl 32 33 namespace webgl { 34 struct FbAttachInfo final { 35 WebGLRenderbuffer* rb = nullptr; 36 WebGLTexture* tex = nullptr; 37 uint32_t mipLevel = 0; 38 uint32_t zLayer = 0; 39 uint32_t zLayerCount = 1; 40 bool isMultiview = false; 41 }; 42 } // namespace webgl 43 44 class WebGLFBAttachPoint final { 45 friend class WebGLFramebuffer; 46 47 public: 48 const GLenum mAttachmentPoint = 0; 49 const bool mDeferAttachment = false; 50 51 private: 52 RefPtr<WebGLTexture> mTexturePtr; 53 RefPtr<WebGLRenderbuffer> mRenderbufferPtr; 54 uint32_t mTexImageLayer = 0; 55 uint8_t mTexImageZLayerCount = 1; 56 uint8_t mTexImageLevel = 0; 57 bool mIsMultiview = false; 58 59 //// 60 61 WebGLFBAttachPoint(); 62 explicit WebGLFBAttachPoint(WebGLFBAttachPoint&); // Make this private. 63 WebGLFBAttachPoint(const WebGLContext* webgl, GLenum attachmentPoint); 64 65 public: 66 ~WebGLFBAttachPoint(); 67 68 //// 69 70 bool HasAttachment() const { 71 return bool(mTexturePtr) || bool(mRenderbufferPtr); 72 } 73 74 void Clear(); 75 76 void Set(gl::GLContext* gl, const webgl::FbAttachInfo&); 77 78 WebGLTexture* Texture() const { return mTexturePtr; } 79 WebGLRenderbuffer* Renderbuffer() const { return mRenderbufferPtr; } 80 81 Maybe<size_t> ColorAttachmentId() const { 82 const size_t id = mAttachmentPoint - LOCAL_GL_COLOR_ATTACHMENT0; 83 if (id >= webgl::kMaxDrawBuffers) return {}; 84 return Some(id); 85 } 86 87 auto Layer() const { return mTexImageLayer; } 88 auto ZLayerCount() const { return mTexImageZLayerCount; } 89 auto MipLevel() const { return mTexImageLevel; } 90 const auto& IsMultiview() const { return mIsMultiview; } 91 92 void AttachmentName(nsCString* out) const; 93 94 const webgl::ImageInfo* GetImageInfo() const; 95 96 bool IsComplete(WebGLContext* webgl, nsCString* const out_info) const; 97 98 void DoAttachment(gl::GLContext* gl) const; 99 100 Maybe<double> GetParameter(WebGLContext* webgl, GLenum attachment, 101 GLenum pname) const; 102 103 bool IsEquivalentForFeedback(const WebGLFBAttachPoint& other) const { 104 if (!HasAttachment() || !other.HasAttachment()) return false; 105 106 #define _(X) (X == other.X) 107 return (_(mRenderbufferPtr) && _(mTexturePtr) && _(mTexImageLevel) && 108 _(mTexImageLayer) && _(mTexImageZLayerCount)); 109 #undef _ 110 } 111 112 //// 113 114 struct Ordered { 115 const WebGLFBAttachPoint& mRef; 116 117 explicit Ordered(const WebGLFBAttachPoint& ref) : mRef(ref) {} 118 119 bool operator<(const Ordered& other) const { 120 MOZ_ASSERT(mRef.HasAttachment() && other.mRef.HasAttachment()); 121 122 #define ORDER_BY(X) \ 123 if (X != other.X) return X < other.X; 124 125 ORDER_BY(mRef.mRenderbufferPtr) 126 ORDER_BY(mRef.mTexturePtr) 127 ORDER_BY(mRef.mTexImageLevel) 128 ORDER_BY(mRef.mTexImageLayer) 129 ORDER_BY(mRef.mTexImageZLayerCount) 130 131 #undef ORDER_BY 132 return false; 133 } 134 }; 135 }; 136 137 class WebGLFramebuffer final : public WebGLContextBoundObject, 138 public SupportsWeakPtr, 139 public CacheInvalidator { 140 public: 141 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(WebGLFramebuffer, override) 142 143 const GLuint mGLName; 144 bool mHasBeenBound = false; 145 const UniquePtr<gl::MozFramebuffer> mOpaque; 146 bool mInOpaqueRAF = false; 147 // Swap chain that may be used to present this framebuffer, for opaque 148 // framebuffers or other use cases. (e.g. DrawTargetWebgl) 149 gl::SwapChain mSwapChain; 150 151 private: 152 mutable uint64_t mNumFBStatusInvals = 0; 153 154 //// 155 156 protected: 157 WebGLFBAttachPoint mDepthAttachment; 158 WebGLFBAttachPoint mStencilAttachment; 159 WebGLFBAttachPoint mDepthStencilAttachment; 160 161 std::array<WebGLFBAttachPoint, webgl::kMaxDrawBuffers> mColorAttachments = {}; 162 std::bitset<webgl::kMaxDrawBuffers> mDrawBufferEnabled = {1}; 163 //// 164 165 std::vector<WebGLFBAttachPoint*> mAttachments; // Non-null. 166 167 std::vector<const WebGLFBAttachPoint*> mColorDrawBuffers; // Non-null 168 const WebGLFBAttachPoint* mColorReadBuffer; // Null if NONE 169 170 //// 171 172 struct CompletenessInfo final { 173 const WebGLFramebuffer* fb = nullptr; 174 175 uint32_t width = 0; 176 uint32_t height = 0; 177 std::bitset<webgl::kMaxDrawBuffers> hasAttachment = 0; 178 std::bitset<webgl::kMaxDrawBuffers> isAttachmentF32 = 0; 179 uint8_t zLayerCount = 1; 180 bool isMultiview = false; 181 182 // IsFeedback 183 std::vector<const WebGLFBAttachPoint*> texAttachments; // Non-null 184 185 ~CompletenessInfo(); 186 }; 187 friend struct CompletenessInfo; 188 189 mutable CacheMaybe<const CompletenessInfo> mCompletenessInfo; 190 191 //// 192 193 public: 194 WebGLFramebuffer(WebGLContext* webgl, GLuint fbo); 195 WebGLFramebuffer(WebGLContext* webgl, UniquePtr<gl::MozFramebuffer> fbo); 196 ~WebGLFramebuffer() override; 197 198 //// 199 200 bool HasDuplicateAttachments() const; 201 bool HasDefinedAttachments() const; 202 bool HasIncompleteAttachments(nsCString* const out_info) const; 203 bool AllImageRectsMatch() const; 204 bool AllImageSamplesMatch() const; 205 FBStatus PrecheckFramebufferStatus(nsCString* const out_info) const; 206 207 protected: 208 Maybe<WebGLFBAttachPoint*> GetAttachPoint(GLenum attachment); // Fallible 209 Maybe<WebGLFBAttachPoint*> GetColorAttachPoint( 210 GLenum attachment); // Fallible 211 void DoDeferredAttachments() const; 212 void RefreshDrawBuffers() const; 213 void RefreshReadBuffer() const; 214 void ResolveAttachmentData() const; 215 216 public: 217 void DetachTexture(const WebGLTexture* tex); 218 void DetachRenderbuffer(const WebGLRenderbuffer* rb); 219 bool ValidateAndInitAttachments(GLenum incompleteFbError) const; 220 bool ValidateClearBufferType(GLenum buffer, uint32_t drawBuffer, 221 webgl::AttribBaseType funcType) const; 222 223 bool ValidateForColorRead(const webgl::FormatUsageInfo** out_format, 224 uint32_t* out_width, uint32_t* out_height) const; 225 226 //////////////// 227 // Getters 228 229 #define GETTER(X) \ 230 const decltype(m##X)& X() const { return m##X; } 231 232 GETTER(DepthAttachment) 233 GETTER(StencilAttachment) 234 GETTER(DepthStencilAttachment) 235 GETTER(Attachments) 236 GETTER(ColorDrawBuffers) 237 GETTER(ColorReadBuffer) 238 239 #undef GETTER 240 241 const auto& ColorAttachment0() const { return mColorAttachments[0]; } 242 const auto& DrawBufferEnabled() const { return mDrawBufferEnabled; } 243 244 //////////////// 245 // Invalidation 246 247 const auto* GetCompletenessInfo() const { return mCompletenessInfo.get(); } 248 249 //////////////// 250 // WebGL funcs 251 252 bool IsCheckFramebufferStatusComplete() const { 253 return CheckFramebufferStatus() == LOCAL_GL_FRAMEBUFFER_COMPLETE; 254 } 255 256 FBStatus CheckFramebufferStatus() const; 257 bool FramebufferAttach(GLenum attachEnum, 258 const webgl::FbAttachInfo& toAttach); 259 void DrawBuffers(const std::vector<GLenum>& buffers); 260 void ReadBuffer(GLenum attachPoint); 261 262 Maybe<double> GetAttachmentParameter(GLenum attachment, GLenum pname); 263 264 static void BlitFramebuffer(WebGLContext* webgl, GLint srcX0, GLint srcY0, 265 GLint srcX1, GLint srcY1, GLint dstX0, 266 GLint dstY0, GLint dstX1, GLint dstY1, 267 GLbitfield mask, GLenum filter); 268 }; 269 270 } // namespace mozilla 271 272 #endif // WEBGL_FRAMEBUFFER_H_