1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 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 <vector> 10 11 #include "mozilla/LinkedList.h" 12 #include "mozilla/WeakPtr.h" 13 #include "nsWrapperCache.h" 14 15 #include "WebGLObjectModel.h" 16 #include "WebGLRenderbuffer.h" 17 #include "WebGLStrongTypes.h" 18 #include "WebGLTexture.h" 19 #include "WebGLTypes.h" 20 21 namespace mozilla { 22 23 class WebGLFramebuffer; 24 class WebGLRenderbuffer; 25 class WebGLTexture; 26 27 template <typename T> 28 class PlacementArray; 29 30 namespace gl { 31 class GLContext; 32 } // namespace gl 33 34 class WebGLFBAttachPoint final { 35 friend class WebGLFramebuffer; 36 37 public: 38 WebGLFramebuffer* const mFB; 39 const GLenum mAttachmentPoint; 40 41 protected: 42 WebGLRefPtr<WebGLTexture> mTexturePtr; 43 WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr; 44 TexImageTarget mTexImageTarget; 45 GLint mTexImageLayer; 46 uint32_t mTexImageLevel; 47 48 //// 49 50 WebGLFBAttachPoint(); 51 WebGLFBAttachPoint(WebGLFramebuffer* fb, GLenum attachmentPoint); 52 53 public: 54 ~WebGLFBAttachPoint(); 55 56 //// 57 58 void Unlink(); 59 60 bool IsDefined() const; 61 bool IsDeleteRequested() const; 62 63 const webgl::FormatUsageInfo* Format() const; 64 uint32_t Samples() const; 65 66 bool HasAlpha() const; 67 bool IsReadableFloat() const; 68 69 void Clear(const char* funcName); 70 71 void SetTexImage(const char* funcName, WebGLTexture* tex, 72 TexImageTarget target, GLint level, GLint layer = 0); 73 void SetRenderbuffer(const char* funcName, WebGLRenderbuffer* rb); 74 Texture()75 WebGLTexture* Texture() const { return mTexturePtr; } Renderbuffer()76 WebGLRenderbuffer* Renderbuffer() const { return mRenderbufferPtr; } 77 ImageTarget()78 TexImageTarget ImageTarget() const { return mTexImageTarget; } Layer()79 GLint Layer() const { return mTexImageLayer; } MipLevel()80 uint32_t MipLevel() const { return mTexImageLevel; } 81 void AttachmentName(nsCString* out) const; 82 83 bool HasUninitializedImageData() const; 84 void SetImageDataStatus(WebGLImageDataStatus x) const; 85 86 void Size(uint32_t* const out_width, uint32_t* const out_height) const; 87 88 bool HasImage() const; 89 bool IsComplete(WebGLContext* webgl, nsCString* const out_info) const; 90 91 void Resolve(gl::GLContext* gl) const; 92 93 JS::Value GetParameter(const char* funcName, WebGLContext* webgl, 94 JSContext* cx, GLenum target, GLenum attachment, 95 GLenum pname, ErrorResult* const out_error) const; 96 97 void OnBackingStoreRespecified(const char* funcName) const; 98 IsEquivalentForFeedback(const WebGLFBAttachPoint & other)99 bool IsEquivalentForFeedback(const WebGLFBAttachPoint& other) const { 100 if (!IsDefined() || !other.IsDefined()) return false; 101 102 #define _(X) X == other.X 103 return (_(mRenderbufferPtr) && _(mTexturePtr) && _(mTexImageTarget.get()) && 104 _(mTexImageLevel) && _(mTexImageLayer)); 105 #undef _ 106 } 107 108 //// 109 110 struct Ordered { 111 const WebGLFBAttachPoint& mRef; 112 OrderedOrdered113 explicit Ordered(const WebGLFBAttachPoint& ref) : mRef(ref) {} 114 115 bool operator<(const Ordered& other) const { 116 MOZ_ASSERT(mRef.IsDefined() && other.mRef.IsDefined()); 117 118 #define ORDER_BY(X) \ 119 if (X != other.X) return X < other.X; 120 121 ORDER_BY(mRef.mRenderbufferPtr) 122 ORDER_BY(mRef.mTexturePtr) 123 ORDER_BY(mRef.mTexImageTarget.get()) 124 ORDER_BY(mRef.mTexImageLevel) 125 ORDER_BY(mRef.mTexImageLayer) 126 127 #undef ORDER_BY 128 return false; 129 } 130 }; 131 }; 132 133 class WebGLFramebuffer final : public nsWrapperCache, 134 public WebGLRefCountedObject<WebGLFramebuffer>, 135 public LinkedListElement<WebGLFramebuffer>, 136 public SupportsWeakPtr<WebGLFramebuffer> { 137 friend class WebGLContext; 138 139 public: 140 MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLFramebuffer) 141 142 const GLuint mGLName; 143 144 private: 145 uint64_t mNumFBStatusInvals; 146 147 protected: 148 #ifdef ANDROID 149 // Bug 1140459: Some drivers (including our test slaves!) don't 150 // give reasonable answers for IsRenderbuffer, maybe others. 151 // This shows up on Android 2.3 emulator. 152 // 153 // So we track the `is a Framebuffer` state ourselves. 154 bool mIsFB; 155 #endif 156 157 //// 158 159 WebGLFBAttachPoint mDepthAttachment; 160 WebGLFBAttachPoint mStencilAttachment; 161 WebGLFBAttachPoint mDepthStencilAttachment; 162 163 // In theory, this number can be unbounded based on the driver. However, no 164 // driver appears to expose more than 8. We might as well stop there too, for 165 // now. 166 // (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS) 167 static const size_t kMaxColorAttachments = 168 8; // jgilbert's MacBook Pro exposes 8. 169 WebGLFBAttachPoint mColorAttachments[kMaxColorAttachments]; 170 171 //// 172 173 std::vector<const WebGLFBAttachPoint*> mColorDrawBuffers; // Non-null 174 const WebGLFBAttachPoint* mColorReadBuffer; // Null if NONE 175 176 //// 177 178 struct ResolvedData { 179 // IsFeedback 180 std::vector<const WebGLFBAttachPoint*> texDrawBuffers; // Non-null 181 std::set<WebGLFBAttachPoint::Ordered> drawSet; 182 std::set<WebGLFBAttachPoint::Ordered> readSet; 183 184 explicit ResolvedData(const WebGLFramebuffer& parent); 185 }; 186 187 mutable UniquePtr<const ResolvedData> mResolvedCompleteData; 188 189 //// 190 191 public: 192 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer) 193 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebuffer) 194 195 WebGLFramebuffer(WebGLContext* webgl, GLuint fbo); 196 GetParentObject()197 WebGLContext* GetParentObject() const { return mContext; } 198 virtual JSObject* WrapObject(JSContext* cx, 199 JS::Handle<JSObject*> givenProto) override; 200 201 private: ~WebGLFramebuffer()202 ~WebGLFramebuffer() { DeleteOnce(); } 203 204 public: 205 void Delete(); 206 207 //// 208 209 bool HasDuplicateAttachments() const; 210 bool HasDefinedAttachments() const; 211 bool HasIncompleteAttachments(nsCString* const out_info) const; 212 bool AllImageRectsMatch() const; 213 bool AllImageSamplesMatch() const; 214 FBStatus PrecheckFramebufferStatus(nsCString* const out_info) const; 215 216 protected: 217 Maybe<WebGLFBAttachPoint*> GetAttachPoint(GLenum attachment); // Fallible 218 Maybe<WebGLFBAttachPoint*> GetColorAttachPoint( 219 GLenum attachment); // Fallible 220 void ResolveAttachments() const; 221 void RefreshDrawBuffers() const; 222 void RefreshReadBuffer() const; 223 bool ResolveAttachmentData(const char* funcName) const; 224 225 public: 226 void DetachTexture(const char* funcName, const WebGLTexture* tex); 227 void DetachRenderbuffer(const char* funcName, const WebGLRenderbuffer* rb); 228 bool ValidateAndInitAttachments(const char* funcName) const; 229 bool ValidateClearBufferType(const char* funcName, GLenum buffer, 230 uint32_t drawBuffer, GLenum funcType) const; 231 232 bool ValidateForColorRead(const char* funcName, 233 const webgl::FormatUsageInfo** out_format, 234 uint32_t* out_width, uint32_t* out_height) const; 235 236 //////////////// 237 // Getters 238 239 #define GETTER(X) \ 240 const decltype(m##X)& X() const { return m##X; } 241 242 GETTER(DepthAttachment) GETTER(StencilAttachment)243 GETTER(StencilAttachment) 244 GETTER(DepthStencilAttachment) 245 GETTER(ColorDrawBuffers) 246 GETTER(ColorReadBuffer) 247 GETTER(ResolvedCompleteData) 248 249 #undef GETTER 250 251 //////////////// 252 // Invalidation 253 254 bool IsResolvedComplete() const { return bool(mResolvedCompleteData); } 255 void InvalidateFramebufferStatus(const char* funcName); 256 void RefreshResolvedData(); 257 258 //////////////// 259 // WebGL funcs 260 IsCheckFramebufferStatusComplete(const char * const funcName)261 bool IsCheckFramebufferStatusComplete(const char* const funcName) const { 262 return CheckFramebufferStatus(funcName) == LOCAL_GL_FRAMEBUFFER_COMPLETE; 263 } 264 265 FBStatus CheckFramebufferStatus(const char* funcName) const; 266 void FramebufferRenderbuffer(const char* funcName, GLenum attachment, 267 GLenum rbtarget, WebGLRenderbuffer* rb); 268 void FramebufferTexture2D(const char* funcName, GLenum attachment, 269 GLenum texImageTarget, WebGLTexture* tex, 270 GLint level); 271 void FramebufferTextureLayer(const char* funcName, GLenum attachment, 272 WebGLTexture* tex, GLint level, GLint layer); 273 void DrawBuffers(const char* funcName, const dom::Sequence<GLenum>& buffers); 274 void ReadBuffer(const char* funcName, GLenum attachPoint); 275 276 JS::Value GetAttachmentParameter(const char* funcName, JSContext* cx, 277 GLenum target, GLenum attachment, 278 GLenum pname, ErrorResult* const out_error); 279 280 static void BlitFramebuffer(WebGLContext* webgl, GLint srcX0, GLint srcY0, 281 GLint srcX1, GLint srcY1, GLint dstX0, 282 GLint dstY0, GLint dstX1, GLint dstY1, 283 GLbitfield mask, GLenum filter); 284 }; 285 286 } // namespace mozilla 287 288 #endif // WEBGL_FRAMEBUFFER_H_ 289