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/. */
6 #ifndef WEBGL_FRAMEBUFFER_H_
7 #define WEBGL_FRAMEBUFFER_H_
11 #include "mozilla/LinkedList.h"
12 #include "mozilla/WeakPtr.h"
13 #include "nsWrapperCache.h"
15 #include "WebGLObjectModel.h"
16 #include "WebGLRenderbuffer.h"
17 #include "WebGLStrongTypes.h"
18 #include "WebGLTexture.h"
19 #include "WebGLTypes.h"
23 class WebGLFramebuffer
;
24 class WebGLRenderbuffer
;
34 class WebGLFBAttachPoint final
{
35 friend class WebGLFramebuffer
;
38 const GLenum mAttachmentPoint
= 0;
39 const bool mDeferAttachment
= false;
42 WebGLRefPtr
<WebGLTexture
> mTexturePtr
;
43 WebGLRefPtr
<WebGLRenderbuffer
> mRenderbufferPtr
;
44 TexImageTarget mTexImageTarget
= 0;
45 GLint mTexImageLayer
= 0;
46 uint32_t mTexImageLevel
= 0;
50 WebGLFBAttachPoint() = default;
51 WebGLFBAttachPoint(const WebGLContext
* webgl
, GLenum attachmentPoint
);
53 explicit WebGLFBAttachPoint(WebGLFBAttachPoint
&) =
54 default; // Make this private.
57 ~WebGLFBAttachPoint();
61 void Unlink() { Clear(); }
63 bool HasAttachment() const {
64 return bool(mTexturePtr
) | bool(mRenderbufferPtr
);
66 bool IsDeleteRequested() const;
70 void SetTexImage(gl::GLContext
* gl
, WebGLTexture
* tex
, TexImageTarget target
,
71 GLint level
, GLint layer
= 0);
72 void SetRenderbuffer(gl::GLContext
* gl
, WebGLRenderbuffer
* rb
);
74 WebGLTexture
* Texture() const { return mTexturePtr
; }
75 WebGLRenderbuffer
* Renderbuffer() const { return mRenderbufferPtr
; }
77 TexImageTarget
ImageTarget() const { return mTexImageTarget
; }
78 GLint
Layer() const { return mTexImageLayer
; }
79 uint32_t MipLevel() const { return mTexImageLevel
; }
80 void AttachmentName(nsCString
* out
) const;
82 const webgl::ImageInfo
* GetImageInfo() const;
84 bool IsComplete(WebGLContext
* webgl
, nsCString
* const out_info
) const;
86 void DoAttachment(gl::GLContext
* gl
) const;
88 JS::Value
GetParameter(WebGLContext
* webgl
, JSContext
* cx
, GLenum target
,
89 GLenum attachment
, GLenum pname
,
90 ErrorResult
* const out_error
) const;
92 bool IsEquivalentForFeedback(const WebGLFBAttachPoint
& other
) const {
93 if (!HasAttachment() | !other
.HasAttachment()) return false;
95 #define _(X) (X == other.X)
96 return (_(mRenderbufferPtr
) & _(mTexturePtr
) & _(mTexImageTarget
.get()) &
97 _(mTexImageLevel
) & _(mTexImageLayer
));
104 const WebGLFBAttachPoint
& mRef
;
106 explicit Ordered(const WebGLFBAttachPoint
& ref
) : mRef(ref
) {}
108 bool operator<(const Ordered
& other
) const {
109 MOZ_ASSERT(mRef
.HasAttachment() && other
.mRef
.HasAttachment());
111 #define ORDER_BY(X) \
112 if (X != other.X) return X < other.X;
114 ORDER_BY(mRef
.mRenderbufferPtr
)
115 ORDER_BY(mRef
.mTexturePtr
)
116 ORDER_BY(mRef
.mTexImageTarget
.get())
117 ORDER_BY(mRef
.mTexImageLevel
)
118 ORDER_BY(mRef
.mTexImageLayer
)
126 class WebGLFramebuffer final
: public nsWrapperCache
,
127 public WebGLRefCountedObject
<WebGLFramebuffer
>,
128 public LinkedListElement
<WebGLFramebuffer
>,
129 public SupportsWeakPtr
<WebGLFramebuffer
>,
130 public CacheInvalidator
{
132 MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLFramebuffer
)
134 const GLuint mGLName
;
135 bool mHasBeenBound
= false;
138 mutable uint64_t mNumFBStatusInvals
= 0;
143 WebGLFBAttachPoint mDepthAttachment
;
144 WebGLFBAttachPoint mStencilAttachment
;
145 WebGLFBAttachPoint mDepthStencilAttachment
;
147 // In theory, this number can be unbounded based on the driver. However, no
148 // driver appears to expose more than 8. We might as well stop there too, for
150 // (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS)
151 static const size_t kMaxColorAttachments
=
152 8; // jgilbert's MacBook Pro exposes 8.
153 WebGLFBAttachPoint mColorAttachments
[kMaxColorAttachments
];
157 std::vector
<WebGLFBAttachPoint
*> mAttachments
; // Non-null.
159 std::vector
<const WebGLFBAttachPoint
*> mColorDrawBuffers
; // Non-null
160 const WebGLFBAttachPoint
* mColorReadBuffer
; // Null if NONE
164 struct CompletenessInfo final
{
165 const WebGLFramebuffer
& fb
;
171 std::vector
<const WebGLFBAttachPoint
*> texAttachments
; // Non-null
175 friend struct CompletenessInfo
;
177 mutable CacheMaybe
<const CompletenessInfo
> mCompletenessInfo
;
182 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer
)
183 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebuffer
)
185 WebGLFramebuffer(WebGLContext
* webgl
, GLuint fbo
);
187 WebGLContext
* GetParentObject() const { return mContext
; }
188 virtual JSObject
* WrapObject(JSContext
* cx
,
189 JS::Handle
<JSObject
*> givenProto
) override
;
192 ~WebGLFramebuffer() {
202 bool HasDuplicateAttachments() const;
203 bool HasDefinedAttachments() const;
204 bool HasIncompleteAttachments(nsCString
* const out_info
) const;
205 bool AllImageRectsMatch() const;
206 bool AllImageSamplesMatch() const;
207 FBStatus
PrecheckFramebufferStatus(nsCString
* const out_info
) const;
210 Maybe
<WebGLFBAttachPoint
*> GetAttachPoint(GLenum attachment
); // Fallible
211 Maybe
<WebGLFBAttachPoint
*> GetColorAttachPoint(
212 GLenum attachment
); // Fallible
213 void DoDeferredAttachments() const;
214 void RefreshDrawBuffers() const;
215 void RefreshReadBuffer() const;
216 void ResolveAttachmentData() const;
219 void DetachTexture(const WebGLTexture
* tex
);
220 void DetachRenderbuffer(const WebGLRenderbuffer
* rb
);
221 bool ValidateAndInitAttachments() const;
222 bool ValidateClearBufferType(GLenum buffer
, uint32_t drawBuffer
,
223 GLenum funcType
) const;
225 bool ValidateForColorRead(const webgl::FormatUsageInfo
** out_format
,
226 uint32_t* out_width
, uint32_t* out_height
) const;
232 const decltype(m##X)& X() const { return m##X; }
234 GETTER(DepthAttachment
)
235 GETTER(StencilAttachment
)
236 GETTER(DepthStencilAttachment
)
238 GETTER(ColorDrawBuffers
)
239 GETTER(ColorReadBuffer
)
243 const auto& ColorAttachment0() const { return mColorAttachments
[0]; }
248 const auto* GetCompletenessInfo() const { return mCompletenessInfo
.get(); }
253 bool IsCheckFramebufferStatusComplete() const {
254 return CheckFramebufferStatus() == LOCAL_GL_FRAMEBUFFER_COMPLETE
;
257 FBStatus
CheckFramebufferStatus() const;
258 void FramebufferRenderbuffer(GLenum attachment
, GLenum rbtarget
,
259 WebGLRenderbuffer
* rb
);
260 void FramebufferTexture2D(GLenum attachment
, GLenum texImageTarget
,
261 WebGLTexture
* tex
, GLint level
);
262 void FramebufferTextureLayer(GLenum attachment
, WebGLTexture
* tex
,
263 GLint level
, GLint layer
);
264 void DrawBuffers(const dom::Sequence
<GLenum
>& buffers
);
265 void ReadBuffer(GLenum attachPoint
);
267 JS::Value
GetAttachmentParameter(JSContext
* cx
, GLenum target
,
268 GLenum attachment
, GLenum pname
,
269 ErrorResult
* const out_error
);
271 static void BlitFramebuffer(WebGLContext
* webgl
, GLint srcX0
, GLint srcY0
,
272 GLint srcX1
, GLint srcY1
, GLint dstX0
,
273 GLint dstY0
, GLint dstX1
, GLint dstY1
,
274 GLbitfield mask
, GLenum filter
);
277 } // namespace mozilla
279 #endif // WEBGL_FRAMEBUFFER_H_