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 CLIENTWEBGLCONTEXT_H_
7 #define CLIENTWEBGLCONTEXT_H_
10 #include "mozilla/dom/ImageData.h"
11 #include "mozilla/Range.h"
12 #include "mozilla/RefCounted.h"
13 #include "nsICanvasRenderingContextInternal.h"
14 #include "nsWrapperCache.h"
15 #include "mozilla/dom/WebGLRenderingContextBinding.h"
16 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
17 #include "mozilla/layers/LayersSurfaces.h"
18 #include "WebGLFormats.h"
19 #include "WebGLStrongTypes.h"
20 #include "WebGLTypes.h"
22 #include "mozilla/Logging.h"
23 #include "WebGLCrossProcessCommandQueue.h"
24 #include "WebGLCommandQueue.h"
27 #include <unordered_map>
28 #include <unordered_set>
31 #ifndef WEBGL_BRIDGE_LOG_
32 # define WEBGL_BRIDGE_LOG_(lvl, ...) \
33 MOZ_LOG(mozilla::gWebGLBridgeLog, lvl, (__VA_ARGS__))
34 # define WEBGL_BRIDGE_LOGV(...) \
35 WEBGL_BRIDGE_LOG_(LogLevel::Verbose, __VA_ARGS__)
36 # define WEBGL_BRIDGE_LOGD(...) WEBGL_BRIDGE_LOG_(LogLevel::Debug, __VA_ARGS__)
37 # define WEBGL_BRIDGE_LOGI(...) WEBGL_BRIDGE_LOG_(LogLevel::Info, __VA_ARGS__)
38 # define WEBGL_BRIDGE_LOGE(...) WEBGL_BRIDGE_LOG_(LogLevel::Error, __VA_ARGS__)
39 #endif // WEBGL_BRIDGE_LOG_
43 class ClientWebGLExtensionBase
;
50 class AvailabilityRunnable
;
55 ////////////////////////////////////
57 class WebGLActiveInfoJS final
: public RefCounted
<WebGLActiveInfoJS
> {
59 MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLActiveInfoJS
)
61 const webgl::ActiveInfo mInfo
;
63 explicit WebGLActiveInfoJS(const webgl::ActiveInfo
& info
) : mInfo(info
) {}
65 virtual ~WebGLActiveInfoJS() = default;
70 GLint
Size() const { return static_cast<GLint
>(mInfo
.elemCount
); }
71 GLenum
Type() const { return mInfo
.elemType
; }
73 void GetName(nsString
& retval
) const { CopyUTF8toUTF16(mInfo
.name
, retval
); }
75 bool WrapObject(JSContext
*, JS::Handle
<JSObject
*>,
76 JS::MutableHandle
<JSObject
*>);
79 class WebGLShaderPrecisionFormatJS final
80 : public RefCounted
<WebGLShaderPrecisionFormatJS
> {
82 MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLShaderPrecisionFormatJS
)
84 const webgl::ShaderPrecisionFormat mInfo
;
86 explicit WebGLShaderPrecisionFormatJS(
87 const webgl::ShaderPrecisionFormat
& info
)
90 virtual ~WebGLShaderPrecisionFormatJS() = default;
92 GLint
RangeMin() const { return mInfo
.rangeMin
; }
93 GLint
RangeMax() const { return mInfo
.rangeMax
; }
94 GLint
Precision() const { return mInfo
.precision
; }
96 bool WrapObject(JSContext
*, JS::Handle
<JSObject
*>,
97 JS::MutableHandle
<JSObject
*>);
100 // -----------------------
102 class ClientWebGLContext
;
104 class WebGLFramebufferJS
;
105 class WebGLProgramJS
;
107 class WebGLRenderbufferJS
;
108 class WebGLSamplerJS
;
110 class WebGLTextureJS
;
111 class WebGLTransformFeedbackJS
;
112 class WebGLVertexArrayJS
;
118 class ProgramKeepAlive final
{
119 friend class mozilla::WebGLProgramJS
;
121 WebGLProgramJS
* mParent
;
124 explicit ProgramKeepAlive(WebGLProgramJS
& parent
) : mParent(&parent
) {}
128 class ShaderKeepAlive final
{
129 friend class mozilla::WebGLShaderJS
;
131 const WebGLShaderJS
* mParent
;
134 explicit ShaderKeepAlive(const WebGLShaderJS
& parent
) : mParent(&parent
) {}
138 class ContextGenerationInfo final
{
140 ObjectId mLastId
= 0;
143 webgl::ExtensionBits mEnabledExtensions
;
144 RefPtr
<WebGLProgramJS
> mCurrentProgram
;
145 std::shared_ptr
<webgl::ProgramKeepAlive
> mProgramKeepAlive
;
146 mutable std::shared_ptr
<webgl::LinkResult
> mActiveLinkResult
;
148 RefPtr
<WebGLTransformFeedbackJS
> mDefaultTfo
;
149 RefPtr
<WebGLVertexArrayJS
> mDefaultVao
;
151 std::unordered_map
<GLenum
, RefPtr
<WebGLBufferJS
>> mBoundBufferByTarget
;
152 std::vector
<RefPtr
<WebGLBufferJS
>> mBoundUbos
;
153 RefPtr
<WebGLFramebufferJS
> mBoundDrawFb
;
154 RefPtr
<WebGLFramebufferJS
> mBoundReadFb
;
155 RefPtr
<WebGLRenderbufferJS
> mBoundRb
;
156 RefPtr
<WebGLTransformFeedbackJS
> mBoundTfo
;
157 RefPtr
<WebGLVertexArrayJS
> mBoundVao
;
158 std::unordered_map
<GLenum
, RefPtr
<WebGLQueryJS
>> mCurrentQueryByTarget
;
160 struct TexUnit final
{
161 RefPtr
<WebGLSamplerJS
> sampler
;
162 std::unordered_map
<GLenum
, RefPtr
<WebGLTextureJS
>> texByTarget
;
164 uint32_t mActiveTexUnit
= 0;
165 std::vector
<TexUnit
> mTexUnits
;
167 bool mTfActiveAndNotPaused
= false;
169 std::vector
<TypedQuad
> mGenericVertexAttribs
;
171 std::array
<bool, 4> mColorWriteMask
= {{true, true, true, true}};
172 std::array
<int32_t, 4> mScissor
= {};
173 std::array
<int32_t, 4> mViewport
= {};
174 std::array
<float, 4> mClearColor
= {{0, 0, 0, 0}};
175 std::array
<float, 4> mBlendColor
= {{0, 0, 0, 0}};
176 std::array
<float, 2> mDepthRange
= {{0, 1}};
177 webgl::PixelPackState mPixelPackState
;
178 WebGLPixelStore mPixelUnpackState
;
180 std::vector
<GLenum
> mCompressedTextureFormats
;
182 Maybe
<uvec2
> mDrawingBufferSize
;
184 ObjectId
NextId() { return mLastId
+= 1; }
189 struct RemotingData final
{
190 // In the cross process case, the WebGL actor's ownership relationship looks
192 // ---------------------------------------------------------------------
193 // | ClientWebGLContext -> WebGLChild -> WebGLParent -> HostWebGLContext
194 // ---------------------------------------------------------------------
196 // where 'A -> B' means "A owns B"
197 RefPtr
<mozilla::dom::WebGLChild
> mWebGLChild
;
198 UniquePtr
<ClientWebGLCommandSourceP
> mCommandSourcePcq
;
199 UniquePtr
<ClientWebGLCommandSourceI
> mCommandSourceIpdl
;
202 struct NotLostData final
{
203 ClientWebGLContext
& context
;
204 webgl::InitContextResult info
;
206 Maybe
<RemotingData
> outOfProcess
;
207 UniquePtr
<HostWebGLContext
> inProcess
;
209 webgl::ContextGenerationInfo state
;
210 std::array
<RefPtr
<ClientWebGLExtensionBase
>,
211 UnderlyingValue(WebGLExtensionID::Max
)>
214 explicit NotLostData(ClientWebGLContext
& context
);
221 friend ClientWebGLContext
;
224 const std::weak_ptr
<NotLostData
> mGeneration
;
228 bool mDeleteRequested
= false;
230 explicit ObjectJS(const ClientWebGLContext
&);
231 virtual ~ObjectJS() = default;
234 ClientWebGLContext
* Context() const {
235 const auto locked
= mGeneration
.lock();
236 if (!locked
) return nullptr;
237 return &(locked
->context
);
240 ClientWebGLContext
* GetParentObject() const { return Context(); }
243 bool IsForContext(const ClientWebGLContext
&) const;
244 virtual bool IsDeleted() const { return mDeleteRequested
; }
246 bool IsUsable(const ClientWebGLContext
& context
) const {
247 return IsForContext(context
) && !IsDeleted();
251 bool ValidateUsable(const ClientWebGLContext
& context
,
252 const char* const argName
) const {
253 if (MOZ_LIKELY(IsUsable(context
))) return true;
254 WarnInvalidUse(context
, argName
);
259 bool ValidateForContext(const ClientWebGLContext
& context
,
260 const char* const argName
) const;
263 void WarnInvalidUse(const ClientWebGLContext
&, const char* argName
) const;
265 // The enum is INVALID_VALUE for Program/Shader :(
266 virtual GLenum
ErrorOnDeleted() const { return LOCAL_GL_INVALID_OPERATION
; }
271 // -------------------------
273 class WebGLBufferJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
274 friend class ClientWebGLContext
;
276 webgl::BufferKind mKind
=
277 webgl::BufferKind::Undefined
; // !IsBuffer until Bind
280 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLBufferJS
)
281 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLBufferJS
)
283 explicit WebGLBufferJS(const ClientWebGLContext
& webgl
)
284 : webgl::ObjectJS(webgl
) {}
287 ~WebGLBufferJS() = default;
290 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
295 class WebGLFramebufferJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
296 friend class ClientWebGLContext
;
299 struct Attachment final
{
300 RefPtr
<WebGLRenderbufferJS
> rb
;
301 RefPtr
<WebGLTextureJS
> tex
;
305 bool mHasBeenBound
= false; // !IsFramebuffer until Bind
306 std::unordered_map
<GLenum
, Attachment
> mAttachments
;
309 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebufferJS
)
310 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebufferJS
)
312 explicit WebGLFramebufferJS(const ClientWebGLContext
&, bool opaque
= false);
315 bool mInOpaqueRAF
= false;
318 ~WebGLFramebufferJS() = default;
320 void EnsureColorAttachments();
323 Attachment
* GetAttachment(const GLenum slotEnum
) {
324 auto ret
= MaybeFind(mAttachments
, slotEnum
);
326 EnsureColorAttachments();
327 ret
= MaybeFind(mAttachments
, slotEnum
);
332 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
337 class WebGLProgramJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
338 friend class ClientWebGLContext
;
341 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLProgramJS
)
342 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLProgramJS
)
344 // If the REFCOUNTING macro isn't declared first, the AddRef at
345 // mInnerRef->js will panic when REFCOUNTING's "owning thread" var is still
348 struct Attachment final
{
349 RefPtr
<WebGLShaderJS
> shader
;
350 std::shared_ptr
<webgl::ShaderKeepAlive
> keepAlive
;
354 std::shared_ptr
<webgl::ProgramKeepAlive
> mKeepAlive
;
355 const std::weak_ptr
<webgl::ProgramKeepAlive
> mKeepAliveWeak
;
357 std::unordered_map
<GLenum
, Attachment
> mNextLink_Shaders
;
358 bool mLastValidate
= false;
359 mutable std::shared_ptr
<webgl::LinkResult
>
360 mResult
; // Never null, often defaulted.
362 struct UniformLocInfo final
{
363 const uint32_t location
;
364 const GLenum elemType
;
367 mutable Maybe
<std::unordered_map
<std::string
, UniformLocInfo
>>
369 mutable std::vector
<uint32_t> mUniformBlockBindings
;
371 std::unordered_set
<const WebGLTransformFeedbackJS
*> mActiveTfos
;
373 explicit WebGLProgramJS(const ClientWebGLContext
&);
376 mKeepAlive
= nullptr; // Try to delete.
378 const auto& maybe
= mKeepAliveWeak
.lock();
380 maybe
->mParent
= nullptr;
385 bool IsDeleted() const override
{ return !mKeepAliveWeak
.lock(); }
386 GLenum
ErrorOnDeleted() const override
{ return LOCAL_GL_INVALID_VALUE
; }
388 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
393 class WebGLQueryJS final
: public nsWrapperCache
,
394 public webgl::ObjectJS
,
395 public SupportsWeakPtr
{
396 friend class ClientWebGLContext
;
397 friend class webgl::AvailabilityRunnable
;
399 GLenum mTarget
= 0; // !IsQuery until Bind
400 bool mCanBeAvailable
= false;
403 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLQueryJS
)
404 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLQueryJS
)
406 explicit WebGLQueryJS(const ClientWebGLContext
& webgl
)
407 : webgl::ObjectJS(webgl
) {}
410 ~WebGLQueryJS() = default;
413 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
418 class WebGLRenderbufferJS final
: public nsWrapperCache
,
419 public webgl::ObjectJS
{
420 friend class ClientWebGLContext
;
423 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLRenderbufferJS
)
424 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLRenderbufferJS
)
427 bool mHasBeenBound
= false; // !IsRenderbuffer until Bind
429 explicit WebGLRenderbufferJS(const ClientWebGLContext
& webgl
)
430 : webgl::ObjectJS(webgl
) {}
431 ~WebGLRenderbufferJS() = default;
434 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
439 class WebGLSamplerJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
440 // IsSampler without Bind
442 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSamplerJS
)
443 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSamplerJS
)
445 explicit WebGLSamplerJS(const ClientWebGLContext
& webgl
)
446 : webgl::ObjectJS(webgl
) {}
449 ~WebGLSamplerJS() = default;
452 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
457 class WebGLShaderJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
458 friend class ClientWebGLContext
;
461 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLShaderJS
)
462 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLShaderJS
)
467 std::shared_ptr
<webgl::ShaderKeepAlive
> mKeepAlive
;
468 const std::weak_ptr
<webgl::ShaderKeepAlive
> mKeepAliveWeak
;
470 mutable webgl::CompileResult mResult
;
472 WebGLShaderJS(const ClientWebGLContext
&, GLenum type
);
475 mKeepAlive
= nullptr; // Try to delete.
477 const auto& maybe
= mKeepAliveWeak
.lock();
479 maybe
->mParent
= nullptr;
484 bool IsDeleted() const override
{ return !mKeepAliveWeak
.lock(); }
485 GLenum
ErrorOnDeleted() const override
{ return LOCAL_GL_INVALID_VALUE
; }
487 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
492 class WebGLSyncJS final
: public nsWrapperCache
,
493 public webgl::ObjectJS
,
494 public SupportsWeakPtr
{
495 friend class ClientWebGLContext
;
496 friend class webgl::AvailabilityRunnable
;
498 bool mCanBeAvailable
= false;
499 bool mSignaled
= false;
502 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSyncJS
)
503 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSyncJS
)
505 explicit WebGLSyncJS(const ClientWebGLContext
& webgl
)
506 : webgl::ObjectJS(webgl
) {}
509 ~WebGLSyncJS() = default;
512 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
517 class WebGLTextureJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
518 friend class ClientWebGLContext
;
520 GLenum mTarget
= 0; // !IsTexture until Bind
523 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTextureJS
)
524 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTextureJS
)
526 explicit WebGLTextureJS(const ClientWebGLContext
& webgl
)
527 : webgl::ObjectJS(webgl
) {}
530 ~WebGLTextureJS() = default;
533 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
538 class WebGLTransformFeedbackJS final
: public nsWrapperCache
,
539 public webgl::ObjectJS
{
540 friend class ClientWebGLContext
;
542 bool mHasBeenBound
= false; // !IsTransformFeedback until Bind
543 bool mActiveOrPaused
= false;
544 std::vector
<RefPtr
<WebGLBufferJS
>> mAttribBuffers
;
545 RefPtr
<WebGLProgramJS
> mActiveProgram
;
546 std::shared_ptr
<webgl::ProgramKeepAlive
> mActiveProgramKeepAlive
;
549 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTransformFeedbackJS
)
550 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTransformFeedbackJS
)
552 explicit WebGLTransformFeedbackJS(const ClientWebGLContext
&);
555 ~WebGLTransformFeedbackJS() = default;
558 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
563 std::array
<uint16_t, 3> ValidUploadElemTypes(GLenum
);
565 class WebGLUniformLocationJS final
: public nsWrapperCache
,
566 public webgl::ObjectJS
{
567 friend class ClientWebGLContext
;
569 const std::weak_ptr
<webgl::LinkResult
> mParent
;
570 const uint32_t mLocation
;
571 const std::array
<uint16_t, 3> mValidUploadElemTypes
;
574 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLUniformLocationJS
)
575 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLUniformLocationJS
)
577 WebGLUniformLocationJS(const ClientWebGLContext
& webgl
,
578 std::weak_ptr
<webgl::LinkResult
> parent
, uint32_t loc
,
580 : webgl::ObjectJS(webgl
),
583 mValidUploadElemTypes(ValidUploadElemTypes(elemType
)) {}
586 ~WebGLUniformLocationJS() = default;
589 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
594 class WebGLVertexArrayJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
595 friend class ClientWebGLContext
;
597 bool mHasBeenBound
= false; // !IsVertexArray until Bind
598 RefPtr
<WebGLBufferJS
> mIndexBuffer
;
599 std::vector
<RefPtr
<WebGLBufferJS
>> mAttribBuffers
;
602 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLVertexArrayJS
)
603 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLVertexArrayJS
)
605 explicit WebGLVertexArrayJS(const ClientWebGLContext
&);
608 ~WebGLVertexArrayJS() = default;
611 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
614 ////////////////////////////////////
616 typedef dom::MaybeSharedFloat32ArrayOrUnrestrictedFloatSequence Float32ListU
;
617 typedef dom::MaybeSharedInt32ArrayOrLongSequence Int32ListU
;
618 typedef dom::MaybeSharedUint32ArrayOrUnsignedLongSequence Uint32ListU
;
620 inline Range
<const float> MakeRange(const Float32ListU
& list
) {
621 if (list
.IsFloat32Array()) return MakeRangeAbv(list
.GetAsFloat32Array());
623 return MakeRange(list
.GetAsUnrestrictedFloatSequence());
626 inline Range
<const int32_t> MakeRange(const Int32ListU
& list
) {
627 if (list
.IsInt32Array()) return MakeRangeAbv(list
.GetAsInt32Array());
629 return MakeRange(list
.GetAsLongSequence());
632 inline Range
<const uint32_t> MakeRange(const Uint32ListU
& list
) {
633 if (list
.IsUint32Array()) return MakeRangeAbv(list
.GetAsUint32Array());
635 return MakeRange(list
.GetAsUnsignedLongSequence());
638 template <typename T
>
639 inline Range
<const uint8_t> MakeByteRange(const T
& x
) {
640 const auto typed
= MakeRange(x
);
641 return Range
<const uint8_t>(
642 reinterpret_cast<const uint8_t*>(typed
.begin().get()),
643 typed
.length() * sizeof(typed
[0]));
648 struct TexImageSourceAdapter final
: public TexImageSource
{
649 TexImageSourceAdapter(const dom::Nullable
<dom::ArrayBufferView
>* maybeView
,
651 if (!maybeView
->IsNull()) {
652 mView
= &(maybeView
->Value());
656 TexImageSourceAdapter(const dom::Nullable
<dom::ArrayBufferView
>* maybeView
,
657 GLuint viewElemOffset
) {
658 if (!maybeView
->IsNull()) {
659 mView
= &(maybeView
->Value());
661 mViewElemOffset
= viewElemOffset
;
664 TexImageSourceAdapter(const dom::ArrayBufferView
* view
, ErrorResult
*) {
668 TexImageSourceAdapter(const dom::ArrayBufferView
* view
, GLuint viewElemOffset
,
669 GLuint viewElemLengthOverride
= 0) {
671 mViewElemOffset
= viewElemOffset
;
672 mViewElemLengthOverride
= viewElemLengthOverride
;
675 explicit TexImageSourceAdapter(const WebGLintptr
* pboOffset
,
676 GLuint ignored1
= 0, GLuint ignored2
= 0) {
677 mPboOffset
= pboOffset
;
680 TexImageSourceAdapter(const WebGLintptr
* pboOffset
, ErrorResult
* ignored
) {
681 mPboOffset
= pboOffset
;
684 TexImageSourceAdapter(const dom::ImageBitmap
* imageBitmap
,
685 ErrorResult
* out_error
) {
686 mImageBitmap
= imageBitmap
;
687 mOut_error
= out_error
;
690 TexImageSourceAdapter(const dom::ImageData
* imageData
, ErrorResult
*) {
691 mImageData
= imageData
;
694 TexImageSourceAdapter(const dom::Element
* domElem
,
695 ErrorResult
* const out_error
) {
697 mOut_error
= out_error
;
702 * Base class for all IDL implementations of WebGLContext
704 class ClientWebGLContext final
: public nsICanvasRenderingContextInternal
,
705 public nsWrapperCache
,
706 public SupportsWeakPtr
{
707 friend class webgl::AvailabilityRunnable
;
708 friend class webgl::ObjectJS
;
709 friend class webgl::ProgramKeepAlive
;
710 friend class webgl::ShaderKeepAlive
;
712 // ----------------------------- Lifetime and DOM ---------------------------
714 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
715 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ClientWebGLContext
)
717 JSObject
* WrapObject(JSContext
* cx
,
718 JS::Handle
<JSObject
*> givenProto
) override
{
720 return dom::WebGL2RenderingContext_Binding::Wrap(cx
, this, givenProto
);
722 return dom::WebGLRenderingContext_Binding::Wrap(cx
, this, givenProto
);
728 const bool mIsWebGL2
;
731 bool mIsCanvasDirty
= false;
732 uvec2 mRequestedSize
= {};
735 explicit ClientWebGLContext(bool webgl2
);
738 virtual ~ClientWebGLContext();
740 const RefPtr
<ClientWebGLExtensionLoseContext
> mExtLoseContext
;
742 mutable std::shared_ptr
<webgl::NotLostData
> mNotLost
;
743 mutable GLenum mNextError
= 0;
744 mutable webgl::LossStatus mLossStatus
= webgl::LossStatus::Ready
;
745 mutable bool mAwaitingRestore
= false;
750 const auto& Limits() const { return mNotLost
->info
.limits
; }
751 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#actual-context-parameters
752 const WebGLContextOptions
& ActualContextParameters() const {
753 MOZ_ASSERT(mNotLost
!= nullptr);
754 return mNotLost
->info
.options
;
757 auto& State() { return mNotLost
->state
; }
758 const auto& State() const {
759 return const_cast<ClientWebGLContext
*>(this)->State();
765 mutable RefPtr
<webgl::AvailabilityRunnable
> mAvailabilityRunnable
;
768 webgl::AvailabilityRunnable
& EnsureAvailabilityRunnable() const;
773 void EmulateLoseContext() const;
774 void OnContextLoss(webgl::ContextLossReason
) const;
775 void RestoreContext(webgl::LossStatus requiredStatus
) const;
778 bool DispatchEvent(const nsAString
&) const;
779 void Event_webglcontextlost() const;
780 void Event_webglcontextrestored() const;
782 bool CreateHostContext(const uvec2
& requestedSize
);
783 void ThrowEvent_WebGLContextCreationError(const std::string
&) const;
786 void MarkCanvasDirty();
788 void MarkContextClean() override
{}
790 void OnBeforePaintTransaction() override
;
791 ClientWebGLContext
* AsWebgl() override
{ return this; }
793 mozilla::dom::WebGLChild
* GetChild() const {
794 if (!mNotLost
) return nullptr;
795 if (!mNotLost
->outOfProcess
) return nullptr;
796 return mNotLost
->outOfProcess
->mWebGLChild
.get();
799 // -------------------------------------------------------------------------
800 // Client WebGL API call tracking and error message reporting
801 // -------------------------------------------------------------------------
803 // Remembers the WebGL function that is lowest on the stack for client-side
805 class FuncScope final
{
807 const ClientWebGLContext
& mWebGL
;
808 const char* const mFuncName
;
809 const FuncScopeId mId
;
811 FuncScope(const ClientWebGLContext
& webgl
, const char* funcName
)
814 mId(FuncScopeId::FuncScopeIdError
) {
815 // Only set if an "outer" scope hasn't already been set.
816 if (!mWebGL
.mFuncScope
) {
817 mWebGL
.mFuncScope
= this;
821 FuncScope(const ClientWebGLContext
* webgl
, FuncScopeId aId
)
822 : mWebGL(*webgl
), mFuncName(GetFuncScopeName(aId
)), mId(aId
) {
823 mWebGL
.mFuncScope
= this;
827 if (this == mWebGL
.mFuncScope
) {
828 mWebGL
.mFuncScope
= nullptr;
834 // The scope of the function at the top of the current WebGL function call
836 mutable FuncScope
* mFuncScope
= nullptr;
838 const auto& CurFuncScope() const { return *mFuncScope
; }
839 FuncScopeId
GetFuncScopeId() const {
840 return mFuncScope
? mFuncScope
->mId
: FuncScopeId::FuncScopeIdError
;
842 const char* FuncName() const {
843 return mFuncScope
? mFuncScope
->mFuncName
: nullptr;
847 template <typename
... Args
>
848 void EnqueueError(const GLenum error
, const char* const format
,
849 const Args
&... args
) const {
850 MOZ_ASSERT(FuncName());
852 text
.AppendPrintf("WebGL warning: %s: ", FuncName());
855 # pragma clang diagnostic push
856 # pragma clang diagnostic ignored "-Wformat-security"
857 #elif defined(__GNUC__)
858 # pragma GCC diagnostic push
859 # pragma GCC diagnostic ignored "-Wformat-security"
861 text
.AppendPrintf(format
, args
...);
863 # pragma clang diagnostic pop
864 #elif defined(__GNUC__)
865 # pragma GCC diagnostic pop
868 EnqueueErrorImpl(error
, text
);
871 void EnqueueError(const webgl::ErrorInfo
& info
) const {
872 EnqueueError(info
.type
, "%s", info
.info
.c_str());
875 template <typename
... Args
>
876 void EnqueueWarning(const char* const format
, const Args
&... args
) const {
877 EnqueueError(0, format
, args
...);
880 template <typename
... Args
>
881 void EnqueuePerfWarning(const char* const format
, const Args
&... args
) const {
882 EnqueueError(webgl::kErrorPerfWarning
, format
, args
...);
885 void EnqueueError_ArgEnum(const char* argName
,
886 GLenum val
) const; // Cold code.
889 void EnqueueErrorImpl(GLenum errorOrZero
, const nsACString
&) const;
892 bool ValidateArrayBufferView(const dom::ArrayBufferView
& view
,
893 GLuint elemOffset
, GLuint elemCountOverride
,
894 const GLenum errorEnum
,
895 uint8_t** const out_bytes
,
896 size_t* const out_byteLen
) const;
899 template <typename T
>
900 bool ValidateNonNull(const char* const argName
,
901 const dom::Nullable
<T
>& maybe
) const {
902 if (maybe
.IsNull()) {
903 EnqueueError(LOCAL_GL_INVALID_VALUE
, "%s: Cannot be null.", argName
);
909 bool ValidateNonNegative(const char* argName
, int64_t val
) const {
910 if (MOZ_UNLIKELY(val
< 0)) {
911 EnqueueError(LOCAL_GL_INVALID_VALUE
, "`%s` must be non-negative.",
918 bool ValidateViewType(GLenum unpackType
, const TexImageSource
& src
) const;
920 Maybe
<uvec3
> ValidateExtents(GLsizei width
, GLsizei height
, GLsizei depth
,
923 // -------------------------------------------------------------------------
924 // nsICanvasRenderingContextInternal / nsAPostRefreshObserver
925 // -------------------------------------------------------------------------
927 already_AddRefed
<layers::Layer
> GetCanvasLayer(
928 nsDisplayListBuilder
* builder
, layers::Layer
* oldLayer
,
929 layers::LayerManager
* manager
) override
;
930 bool InitializeCanvasRenderer(nsDisplayListBuilder
* aBuilder
,
931 layers::CanvasRenderer
* aRenderer
) override
;
932 // Note that 'clean' here refers to its invalidation state, not the
933 // contents of the buffer.
934 bool IsContextCleanForFrameCapture() override
{
935 return !mCapturedFrameInvalidated
;
937 void MarkContextCleanForFrameCapture() override
{
938 mCapturedFrameInvalidated
= false;
941 void OnMemoryPressure() override
;
943 SetContextOptions(JSContext
* cx
, JS::Handle
<JS::Value
> options
,
944 ErrorResult
& aRvForDictionaryInit
) override
;
946 SetDimensions(int32_t width
, int32_t height
) override
;
947 bool UpdateWebRenderCanvasData(
948 nsDisplayListBuilder
* aBuilder
,
949 layers::WebRenderCanvasData
* aCanvasData
) override
;
953 int32_t GetWidth() override
{ return AutoAssertCast(DrawingBufferSize().x
); }
954 int32_t GetHeight() override
{ return AutoAssertCast(DrawingBufferSize().y
); }
956 NS_IMETHOD
InitializeWithDrawTarget(nsIDocShell
*,
957 NotNull
<gfx::DrawTarget
*>) override
{
958 return NS_ERROR_NOT_IMPLEMENTED
;
961 NS_IMETHOD
Reset() override
{
962 /* (InitializeWithSurface) */
963 return NS_ERROR_NOT_IMPLEMENTED
;
966 UniquePtr
<uint8_t[]> GetImageBuffer(int32_t* out_format
) override
;
967 NS_IMETHOD
GetInputStream(const char* mimeType
,
968 const nsAString
& encoderOptions
,
969 nsIInputStream
** out_stream
) override
;
971 already_AddRefed
<mozilla::gfx::SourceSurface
> GetSurfaceSnapshot(
972 gfxAlphaType
* out_alphaType
) override
;
974 void SetOpaqueValueFromOpaqueAttr(bool) override
{};
975 bool GetIsOpaque() override
{ return !mInitialOptions
->alpha
; }
977 NS_IMETHOD
SetIsIPC(bool) override
{ return NS_ERROR_NOT_IMPLEMENTED
; }
980 * An abstract base class to be implemented by callers wanting to be notified
981 * that a refresh has occurred. Callers must ensure an observer is removed
982 * before it is destroyed.
984 void DidRefresh() override
;
986 NS_IMETHOD
Redraw(const gfxRect
&) override
{
987 return NS_ERROR_NOT_IMPLEMENTED
;
993 layers::LayersBackend
GetCompositorBackendType() const;
995 bool mCapturedFrameInvalidated
= false;
997 // -------------------------------------------------------------------------
998 // WebGLRenderingContext Basic Properties and Methods
999 // -------------------------------------------------------------------------
1001 dom::HTMLCanvasElement
* GetCanvas() const { return mCanvasElement
; }
1004 dom::Nullable
<dom::OwningHTMLCanvasElementOrOffscreenCanvas
>& retval
);
1006 GLsizei
DrawingBufferWidth() {
1007 const FuncScope
funcScope(*this, "drawingBufferWidth");
1008 return AutoAssertCast(DrawingBufferSize().x
);
1010 GLsizei
DrawingBufferHeight() {
1011 const FuncScope
funcScope(*this, "drawingBufferHeight");
1012 return AutoAssertCast(DrawingBufferSize().y
);
1014 void GetContextAttributes(dom::Nullable
<dom::WebGLContextAttributes
>& retval
);
1016 void Present(WebGLFramebufferJS
*, layers::TextureType
,
1017 const bool webvr
= false);
1018 Maybe
<layers::SurfaceDescriptor
> GetFrontBuffer(WebGLFramebufferJS
*,
1019 const bool webvr
= false);
1020 RefPtr
<gfx::SourceSurface
> GetFrontBufferSnapshot(
1021 bool requireAlphaPremult
= true) override
;
1023 void ClearVRSwapChain();
1026 RefPtr
<gfx::DataSourceSurface
> BackBufferSnapshot();
1027 void DoReadPixels(const webgl::ReadPixelsDesc
&, Range
<uint8_t>) const;
1028 uvec2
DrawingBufferSize();
1030 void AfterDrawCall() {
1031 if (!mNotLost
) return;
1032 const auto& state
= State();
1033 if (!state
.mBoundDrawFb
) {
1038 // -------------------------------------------------------------------------
1039 // Client-side helper methods. Dispatch to a Host method.
1040 // -------------------------------------------------------------------------
1042 // ------------------------- GL State -------------------------
1044 bool IsContextLost() const { return !mNotLost
; }
1046 void Disable(GLenum cap
) const;
1047 void Enable(GLenum cap
) const;
1048 bool IsEnabled(GLenum cap
) const;
1051 Maybe
<double> GetNumber(GLenum pname
);
1052 Maybe
<std::string
> GetString(GLenum pname
);
1055 void GetParameter(JSContext
* cx
, GLenum pname
,
1056 JS::MutableHandle
<JS::Value
> retval
, ErrorResult
& rv
,
1057 bool debug
= false);
1059 void GetBufferParameter(JSContext
* cx
, GLenum target
, GLenum pname
,
1060 JS::MutableHandle
<JS::Value
> retval
) const;
1062 void GetFramebufferAttachmentParameter(JSContext
* cx
, GLenum target
,
1063 GLenum attachment
, GLenum pname
,
1064 JS::MutableHandle
<JS::Value
> retval
,
1065 ErrorResult
& rv
) const;
1067 void GetRenderbufferParameter(JSContext
* cx
, GLenum target
, GLenum pname
,
1068 JS::MutableHandle
<JS::Value
> retval
) const;
1070 void GetIndexedParameter(JSContext
* cx
, GLenum target
, GLuint index
,
1071 JS::MutableHandleValue retval
,
1072 ErrorResult
& rv
) const;
1074 already_AddRefed
<WebGLShaderPrecisionFormatJS
> GetShaderPrecisionFormat(
1075 GLenum shadertype
, GLenum precisiontype
);
1077 void UseProgram(WebGLProgramJS
*);
1078 void ValidateProgram(WebGLProgramJS
&) const;
1082 already_AddRefed
<WebGLBufferJS
> CreateBuffer() const;
1083 already_AddRefed
<WebGLFramebufferJS
> CreateFramebuffer() const;
1084 already_AddRefed
<WebGLFramebufferJS
> CreateOpaqueFramebuffer(
1085 const webgl::OpaqueFramebufferOptions
&) const;
1086 already_AddRefed
<WebGLProgramJS
> CreateProgram() const;
1087 already_AddRefed
<WebGLQueryJS
> CreateQuery() const;
1088 already_AddRefed
<WebGLRenderbufferJS
> CreateRenderbuffer() const;
1089 already_AddRefed
<WebGLSamplerJS
> CreateSampler() const;
1090 already_AddRefed
<WebGLShaderJS
> CreateShader(GLenum type
) const;
1091 already_AddRefed
<WebGLSyncJS
> FenceSync(GLenum condition
,
1092 GLbitfield flags
) const;
1093 already_AddRefed
<WebGLTextureJS
> CreateTexture() const;
1094 already_AddRefed
<WebGLTransformFeedbackJS
> CreateTransformFeedback() const;
1095 already_AddRefed
<WebGLVertexArrayJS
> CreateVertexArray() const;
1097 void DeleteBuffer(WebGLBufferJS
*);
1098 void DeleteFramebuffer(WebGLFramebufferJS
*, bool canDeleteOpaque
= false);
1099 void DeleteProgram(WebGLProgramJS
*) const;
1100 void DeleteQuery(WebGLQueryJS
*);
1101 void DeleteRenderbuffer(WebGLRenderbufferJS
*);
1102 void DeleteSampler(WebGLSamplerJS
*);
1103 void DeleteShader(WebGLShaderJS
*) const;
1104 void DeleteSync(WebGLSyncJS
*) const;
1105 void DeleteTexture(WebGLTextureJS
*);
1106 void DeleteTransformFeedback(WebGLTransformFeedbackJS
*);
1107 void DeleteVertexArray(WebGLVertexArrayJS
*);
1110 void DoDeleteProgram(WebGLProgramJS
&) const;
1111 void DoDeleteShader(const WebGLShaderJS
&) const;
1116 bool IsBuffer(const WebGLBufferJS
*) const;
1117 bool IsFramebuffer(const WebGLFramebufferJS
*) const;
1118 bool IsProgram(const WebGLProgramJS
*) const;
1119 bool IsQuery(const WebGLQueryJS
*) const;
1120 bool IsRenderbuffer(const WebGLRenderbufferJS
*) const;
1121 bool IsSampler(const WebGLSamplerJS
*) const;
1122 bool IsShader(const WebGLShaderJS
*) const;
1123 bool IsSync(const WebGLSyncJS
*) const;
1124 bool IsTexture(const WebGLTextureJS
*) const;
1125 bool IsTransformFeedback(const WebGLTransformFeedbackJS
*) const;
1126 bool IsVertexArray(const WebGLVertexArrayJS
*) const;
1132 const webgl::LinkResult
& GetLinkResult(const WebGLProgramJS
&) const;
1135 void AttachShader(WebGLProgramJS
&, WebGLShaderJS
&) const;
1136 void BindAttribLocation(WebGLProgramJS
&, GLuint location
,
1137 const nsAString
& name
) const;
1138 void DetachShader(WebGLProgramJS
&, const WebGLShaderJS
&) const;
1139 void GetAttachedShaders(
1140 const WebGLProgramJS
&,
1141 dom::Nullable
<nsTArray
<RefPtr
<WebGLShaderJS
>>>& retval
) const;
1142 void LinkProgram(WebGLProgramJS
&) const;
1143 void TransformFeedbackVaryings(WebGLProgramJS
&,
1144 const dom::Sequence
<nsString
>& varyings
,
1145 GLenum bufferMode
) const;
1146 void UniformBlockBinding(WebGLProgramJS
&, GLuint blockIndex
,
1147 GLuint blockBinding
) const;
1149 // Link result reflection
1150 already_AddRefed
<WebGLActiveInfoJS
> GetActiveAttrib(const WebGLProgramJS
&,
1152 already_AddRefed
<WebGLActiveInfoJS
> GetActiveUniform(const WebGLProgramJS
&,
1154 void GetActiveUniformBlockName(const WebGLProgramJS
&,
1155 GLuint uniformBlockIndex
,
1156 nsAString
& retval
) const;
1157 void GetActiveUniformBlockParameter(JSContext
* cx
, const WebGLProgramJS
&,
1158 GLuint uniformBlockIndex
, GLenum pname
,
1159 JS::MutableHandle
<JS::Value
> retval
,
1161 void GetActiveUniforms(JSContext
*, const WebGLProgramJS
&,
1162 const dom::Sequence
<GLuint
>& uniformIndices
,
1164 JS::MutableHandle
<JS::Value
> retval
) const;
1165 GLint
GetAttribLocation(const WebGLProgramJS
&, const nsAString
& name
) const;
1166 GLint
GetFragDataLocation(const WebGLProgramJS
&, const nsAString
& name
) const;
1167 void GetProgramInfoLog(const WebGLProgramJS
& prog
, nsAString
& retval
) const;
1168 void GetProgramParameter(JSContext
*, const WebGLProgramJS
&, GLenum pname
,
1169 JS::MutableHandle
<JS::Value
> retval
) const;
1170 already_AddRefed
<WebGLActiveInfoJS
> GetTransformFeedbackVarying(
1171 const WebGLProgramJS
&, GLuint index
);
1172 GLuint
GetUniformBlockIndex(const WebGLProgramJS
&,
1173 const nsAString
& uniformBlockName
) const;
1174 void GetUniformIndices(const WebGLProgramJS
&,
1175 const dom::Sequence
<nsString
>& uniformNames
,
1176 dom::Nullable
<nsTArray
<GLuint
>>& retval
) const;
1178 // WebGLUniformLocationJS
1179 already_AddRefed
<WebGLUniformLocationJS
> GetUniformLocation(
1180 const WebGLProgramJS
&, const nsAString
& name
) const;
1181 void GetUniform(JSContext
*, const WebGLProgramJS
&,
1182 const WebGLUniformLocationJS
&,
1183 JS::MutableHandle
<JS::Value
> retval
);
1189 const webgl::CompileResult
& GetCompileResult(const WebGLShaderJS
&) const;
1192 void CompileShader(WebGLShaderJS
&) const;
1193 void GetShaderInfoLog(const WebGLShaderJS
&, nsAString
& retval
) const;
1194 void GetShaderParameter(JSContext
*, const WebGLShaderJS
&, GLenum pname
,
1195 JS::MutableHandle
<JS::Value
> retval
) const;
1196 void GetShaderSource(const WebGLShaderJS
&, nsAString
& retval
) const;
1197 void GetTranslatedShaderSource(const WebGLShaderJS
& shader
,
1198 nsAString
& retval
) const;
1199 void ShaderSource(WebGLShaderJS
&, const nsAString
&) const;
1203 void BindFramebuffer(GLenum target
, WebGLFramebufferJS
*);
1205 void BlendColor(GLclampf r
, GLclampf g
, GLclampf b
, GLclampf a
);
1209 void BlendEquation(GLenum mode
) { BlendEquationSeparate(mode
, mode
); }
1210 void BlendFunc(GLenum sfactor
, GLenum dfactor
) {
1211 BlendFuncSeparate(sfactor
, dfactor
, sfactor
, dfactor
);
1214 void BlendEquationSeparate(GLenum modeRGB
, GLenum modeAlpha
);
1215 void BlendFuncSeparate(GLenum srcRGB
, GLenum dstRGB
, GLenum srcAlpha
,
1220 GLenum
CheckFramebufferStatus(GLenum target
);
1222 void Clear(GLbitfield mask
);
1227 void ClearBufferTv(GLenum buffer
, GLint drawBuffer
, webgl::AttribBaseType
,
1228 const Range
<const uint8_t>& view
, GLuint srcElemOffset
);
1231 void ClearBufferfv(GLenum buffer
, GLint drawBuffer
, const Float32ListU
& list
,
1232 GLuint srcElemOffset
) {
1233 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Float
,
1234 MakeByteRange(list
), srcElemOffset
);
1236 void ClearBufferiv(GLenum buffer
, GLint drawBuffer
, const Int32ListU
& list
,
1237 GLuint srcElemOffset
) {
1238 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Int
,
1239 MakeByteRange(list
), srcElemOffset
);
1241 void ClearBufferuiv(GLenum buffer
, GLint drawBuffer
, const Uint32ListU
& list
,
1242 GLuint srcElemOffset
) {
1243 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Uint
,
1244 MakeByteRange(list
), srcElemOffset
);
1249 void ClearBufferfi(GLenum buffer
, GLint drawBuffer
, GLfloat depth
,
1252 void ClearColor(GLclampf r
, GLclampf g
, GLclampf b
, GLclampf a
);
1254 void ClearDepth(GLclampf v
);
1256 void ClearStencil(GLint v
);
1258 void ColorMask(WebGLboolean r
, WebGLboolean g
, WebGLboolean b
,
1261 void CullFace(GLenum face
);
1263 void DepthFunc(GLenum func
);
1265 void DepthMask(WebGLboolean b
);
1267 void DepthRange(GLclampf zNear
, GLclampf zFar
);
1273 void FrontFace(GLenum mode
);
1277 void Hint(GLenum target
, GLenum mode
);
1279 void LineWidth(GLfloat width
);
1281 void PixelStorei(GLenum pname
, GLint param
);
1283 void PolygonOffset(GLfloat factor
, GLfloat units
);
1285 void SampleCoverage(GLclampf value
, WebGLboolean invert
);
1287 void Scissor(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1291 void StencilFunc(GLenum func
, GLint ref
, GLuint mask
) {
1292 StencilFuncSeparate(LOCAL_GL_FRONT_AND_BACK
, func
, ref
, mask
);
1294 void StencilMask(GLuint mask
) {
1295 StencilMaskSeparate(LOCAL_GL_FRONT_AND_BACK
, mask
);
1297 void StencilOp(GLenum sfail
, GLenum dpfail
, GLenum dppass
) {
1298 StencilOpSeparate(LOCAL_GL_FRONT_AND_BACK
, sfail
, dpfail
, dppass
);
1301 void StencilFuncSeparate(GLenum face
, GLenum func
, GLint ref
, GLuint mask
);
1302 void StencilMaskSeparate(GLenum face
, GLuint mask
);
1303 void StencilOpSeparate(GLenum face
, GLenum sfail
, GLenum dpfail
,
1308 void Viewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1310 // ------------------------- Buffer Objects -------------------------
1312 void BindBuffer(GLenum target
, WebGLBufferJS
*);
1317 void BindBufferRangeImpl(const GLenum target
, const GLuint index
,
1318 WebGLBufferJS
* const buffer
, const uint64_t offset
,
1319 const uint64_t size
);
1322 void BindBufferBase(const GLenum target
, const GLuint index
,
1323 WebGLBufferJS
* const buffer
) {
1324 const FuncScope
funcScope(*this, "bindBufferBase");
1325 if (IsContextLost()) return;
1327 BindBufferRangeImpl(target
, index
, buffer
, 0, 0);
1330 void BindBufferRange(const GLenum target
, const GLuint index
,
1331 WebGLBufferJS
* const buffer
, const WebGLintptr offset
,
1332 const WebGLsizeiptr size
) {
1333 const FuncScope
funcScope(*this, "bindBufferRange");
1334 if (IsContextLost()) return;
1337 if (!ValidateNonNegative("offset", offset
)) return;
1340 EnqueueError(LOCAL_GL_INVALID_VALUE
,
1341 "`size` must be positive for non-null `buffer`.");
1346 BindBufferRangeImpl(target
, index
, buffer
, static_cast<uint64_t>(offset
),
1347 static_cast<uint64_t>(size
));
1352 void CopyBufferSubData(GLenum readTarget
, GLenum writeTarget
,
1353 GLintptr readOffset
, GLintptr writeOffset
,
1356 void BufferData(GLenum target
, WebGLsizeiptr size
, GLenum usage
);
1357 void BufferData(GLenum target
,
1358 const dom::Nullable
<dom::ArrayBuffer
>& maybeSrc
,
1360 void BufferData(GLenum target
, const dom::ArrayBufferView
& srcData
,
1361 GLenum usage
, GLuint srcElemOffset
= 0,
1362 GLuint srcElemCountOverride
= 0);
1364 void BufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1365 const dom::ArrayBufferView
& src
, GLuint srcElemOffset
= 0,
1366 GLuint srcElemCountOverride
= 0);
1367 void BufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1368 const dom::ArrayBuffer
& src
);
1370 void GetBufferSubData(GLenum target
, GLintptr srcByteOffset
,
1371 const dom::ArrayBufferView
& dstData
,
1372 GLuint dstElemOffset
, GLuint dstElemCountOverride
);
1374 // -------------------------- Framebuffer Objects --------------------------
1376 void BlitFramebuffer(GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1377 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1378 GLbitfield mask
, GLenum filter
);
1383 // `bindTarget` if non-zero allows initializing the rb/tex with that target.
1384 void FramebufferAttach(GLenum target
, GLenum attachEnum
, GLenum bindTarget
,
1385 WebGLRenderbufferJS
*, WebGLTextureJS
*,
1386 uint32_t mipLevel
, uint32_t zLayer
,
1387 uint32_t numViewLayers
) const;
1390 void FramebufferRenderbuffer(GLenum target
, GLenum attachSlot
,
1391 GLenum rbTarget
, WebGLRenderbufferJS
* rb
) const {
1392 const FuncScope
funcScope(*this, "framebufferRenderbuffer");
1393 if (IsContextLost()) return;
1394 if (rbTarget
!= LOCAL_GL_RENDERBUFFER
) {
1395 EnqueueError_ArgEnum("rbTarget", rbTarget
);
1398 FramebufferAttach(target
, attachSlot
, rbTarget
, rb
, nullptr, 0, 0, 0);
1401 void FramebufferTexture2D(GLenum target
, GLenum attachSlot
,
1402 GLenum texImageTarget
, WebGLTextureJS
*,
1403 GLint mipLevel
) const;
1405 void FramebufferTextureLayer(GLenum target
, GLenum attachSlot
,
1406 WebGLTextureJS
* tex
, GLint mipLevel
,
1407 GLint zLayer
) const {
1408 const FuncScope
funcScope(*this, "framebufferTextureLayer");
1409 if (IsContextLost()) return;
1410 FramebufferAttach(target
, attachSlot
, 0, nullptr, tex
,
1411 static_cast<uint32_t>(mipLevel
),
1412 static_cast<uint32_t>(zLayer
), 0);
1415 void FramebufferTextureMultiview(GLenum target
, GLenum attachSlot
,
1416 WebGLTextureJS
* tex
, GLint mipLevel
,
1418 GLsizei numViewLayers
) const {
1419 const FuncScope
funcScope(*this, "framebufferTextureMultiview");
1420 if (IsContextLost()) return;
1421 if (tex
&& numViewLayers
< 1) {
1422 EnqueueError(LOCAL_GL_INVALID_VALUE
, "`numViewLayers` must be >=1.");
1425 FramebufferAttach(target
, attachSlot
, 0, nullptr, tex
,
1426 static_cast<uint32_t>(mipLevel
),
1427 static_cast<uint32_t>(zLayerBase
),
1428 static_cast<uint32_t>(numViewLayers
));
1433 void InvalidateFramebuffer(GLenum target
,
1434 const dom::Sequence
<GLenum
>& attachments
,
1435 ErrorResult
& unused
);
1436 void InvalidateSubFramebuffer(GLenum target
,
1437 const dom::Sequence
<GLenum
>& attachments
,
1438 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1439 ErrorResult
& unused
);
1441 void ReadBuffer(GLenum mode
);
1443 // ----------------------- Renderbuffer objects -----------------------
1444 void GetInternalformatParameter(JSContext
* cx
, GLenum target
,
1445 GLenum internalformat
, GLenum pname
,
1446 JS::MutableHandleValue retval
,
1449 void BindRenderbuffer(GLenum target
, WebGLRenderbufferJS
*);
1451 void RenderbufferStorage(GLenum target
, GLenum internalFormat
, GLsizei width
,
1452 GLsizei height
) const {
1453 RenderbufferStorageMultisample(target
, 0, internalFormat
, width
, height
);
1456 void RenderbufferStorageMultisample(GLenum target
, GLsizei samples
,
1457 GLenum internalFormat
, GLsizei width
,
1458 GLsizei height
) const;
1460 // --------------------------- Texture objects ---------------------------
1462 void ActiveTexture(GLenum texUnit
);
1464 void BindTexture(GLenum texTarget
, WebGLTextureJS
*);
1466 void GenerateMipmap(GLenum texTarget
) const;
1468 void GetTexParameter(JSContext
* cx
, GLenum texTarget
, GLenum pname
,
1469 JS::MutableHandle
<JS::Value
> retval
) const;
1471 void TexParameterf(GLenum texTarget
, GLenum pname
, GLfloat param
);
1472 void TexParameteri(GLenum texTarget
, GLenum pname
, GLint param
);
1477 void TexStorage(uint8_t funcDims
, GLenum target
, GLsizei levels
,
1478 GLenum internalFormat
, const ivec3
& size
) const;
1480 // Primitive tex upload functions
1481 void TexImage(uint8_t funcDims
, GLenum target
, GLint level
,
1482 GLenum respecFormat
, const ivec3
& offset
, const ivec3
& size
,
1483 GLint border
, const webgl::PackingInfo
& pi
,
1484 const TexImageSource
& src
) const;
1485 void CompressedTexImage(bool sub
, uint8_t funcDims
, GLenum target
,
1486 GLint level
, GLenum format
, const ivec3
& offset
,
1487 const ivec3
& size
, GLint border
,
1488 const TexImageSource
& src
,
1489 GLsizei pboImageSize
) const;
1490 void CopyTexImage(uint8_t funcDims
, GLenum target
, GLint level
,
1491 GLenum respecFormat
, const ivec3
& dstOffset
,
1492 const ivec2
& srcOffset
, const ivec2
& size
,
1493 GLint border
) const;
1496 void TexStorage2D(GLenum target
, GLsizei levels
, GLenum internalFormat
,
1497 GLsizei width
, GLsizei height
) const {
1498 TexStorage(2, target
, levels
, internalFormat
, {width
, height
, 1});
1501 void TexStorage3D(GLenum target
, GLsizei levels
, GLenum internalFormat
,
1502 GLsizei width
, GLsizei height
, GLsizei depth
) const {
1503 TexStorage(3, target
, levels
, internalFormat
, {width
, height
, depth
});
1506 ////////////////////////////////////
1508 template <typename T
> // TexImageSource or WebGLintptr
1509 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1510 GLsizei width
, GLsizei height
, GLint border
,
1511 GLenum unpackFormat
, GLenum unpackType
, const T
& anySrc
,
1512 ErrorResult
& out_error
) const {
1513 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1514 TexImage(2, target
, level
, internalFormat
, {0, 0, 0}, {width
, height
, 1},
1515 border
, {unpackFormat
, unpackType
}, src
);
1518 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1519 GLsizei width
, GLsizei height
, GLint border
,
1520 GLenum unpackFormat
, GLenum unpackType
,
1521 const dom::ArrayBufferView
& view
, GLuint viewElemOffset
,
1522 ErrorResult
&) const {
1523 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1524 TexImage(2, target
, level
, internalFormat
, {0, 0, 0}, {width
, height
, 1},
1525 border
, {unpackFormat
, unpackType
}, src
);
1530 template <typename T
> // TexImageSource or WebGLintptr
1531 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1532 GLsizei width
, GLsizei height
, GLenum unpackFormat
,
1533 GLenum unpackType
, const T
& anySrc
,
1534 ErrorResult
& out_error
) const {
1535 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1536 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0,
1537 {unpackFormat
, unpackType
}, src
);
1540 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1541 GLsizei width
, GLsizei height
, GLenum unpackFormat
,
1542 GLenum unpackType
, const dom::ArrayBufferView
& view
,
1543 GLuint viewElemOffset
, ErrorResult
&) const {
1544 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1545 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0,
1546 {unpackFormat
, unpackType
}, src
);
1551 template <typename T
> // TexImageSource or WebGLintptr
1552 void TexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1553 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
,
1554 GLenum unpackFormat
, GLenum unpackType
, const T
& anySrc
,
1555 ErrorResult
& out_error
) const {
1556 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1557 TexImage(3, target
, level
, internalFormat
, {0, 0, 0},
1558 {width
, height
, depth
}, border
, {unpackFormat
, unpackType
}, src
);
1561 void TexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1562 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
,
1563 GLenum unpackFormat
, GLenum unpackType
,
1564 const dom::ArrayBufferView
& view
, GLuint viewElemOffset
,
1565 ErrorResult
&) const {
1566 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1567 TexImage(3, target
, level
, internalFormat
, {0, 0, 0},
1568 {width
, height
, depth
}, border
, {unpackFormat
, unpackType
}, src
);
1573 template <typename T
> // TexImageSource or WebGLintptr
1574 void TexSubImage3D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1575 GLint zOffset
, GLsizei width
, GLsizei height
,
1576 GLsizei depth
, GLenum unpackFormat
, GLenum unpackType
,
1577 const T
& anySrc
, ErrorResult
& out_error
) const {
1578 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1579 TexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
},
1580 {width
, height
, depth
}, 0, {unpackFormat
, unpackType
}, src
);
1583 void TexSubImage3D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1584 GLint zOffset
, GLsizei width
, GLsizei height
,
1585 GLsizei depth
, GLenum unpackFormat
, GLenum unpackType
,
1586 const dom::Nullable
<dom::ArrayBufferView
>& maybeSrcView
,
1587 GLuint srcElemOffset
, ErrorResult
&) const {
1588 const TexImageSourceAdapter
src(&maybeSrcView
, srcElemOffset
);
1589 TexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
},
1590 {width
, height
, depth
}, 0, {unpackFormat
, unpackType
}, src
);
1593 ////////////////////////////////////
1596 void CompressedTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1597 GLsizei width
, GLsizei height
, GLint border
,
1598 GLsizei imageSize
, WebGLintptr offset
) const {
1599 const TexImageSourceAdapter
src(&offset
);
1600 CompressedTexImage(false, 2, target
, level
, internalFormat
, {0, 0, 0},
1601 {width
, height
, 1}, border
, src
, imageSize
);
1604 void CompressedTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1605 GLsizei width
, GLsizei height
, GLint border
,
1606 const dom::ArrayBufferView
& view
,
1607 GLuint viewElemOffset
= 0,
1608 GLuint viewElemLengthOverride
= 0) const {
1609 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1610 viewElemLengthOverride
);
1611 CompressedTexImage(false, 2, target
, level
, internalFormat
, {0, 0, 0},
1612 {width
, height
, 1}, border
, src
, 0);
1617 void CompressedTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1618 GLint yOffset
, GLsizei width
, GLsizei height
,
1619 GLenum unpackFormat
, GLsizei imageSize
,
1620 WebGLintptr offset
) const {
1621 const TexImageSourceAdapter
src(&offset
);
1622 CompressedTexImage(true, 2, target
, level
, unpackFormat
,
1623 {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0, src
,
1627 void CompressedTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1628 GLint yOffset
, GLsizei width
, GLsizei height
,
1629 GLenum unpackFormat
,
1630 const dom::ArrayBufferView
& view
,
1631 GLuint viewElemOffset
= 0,
1632 GLuint viewElemLengthOverride
= 0) const {
1633 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1634 viewElemLengthOverride
);
1635 CompressedTexImage(true, 2, target
, level
, unpackFormat
,
1636 {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0, src
, 0);
1641 void CompressedTexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1642 GLsizei width
, GLsizei height
, GLsizei depth
,
1643 GLint border
, GLsizei imageSize
,
1644 WebGLintptr offset
) const {
1645 const TexImageSourceAdapter
src(&offset
);
1646 CompressedTexImage(false, 3, target
, level
, internalFormat
, {0, 0, 0},
1647 {width
, height
, depth
}, border
, src
, imageSize
);
1650 void CompressedTexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1651 GLsizei width
, GLsizei height
, GLsizei depth
,
1652 GLint border
, const dom::ArrayBufferView
& view
,
1653 GLuint viewElemOffset
= 0,
1654 GLuint viewElemLengthOverride
= 0) const {
1655 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1656 viewElemLengthOverride
);
1657 CompressedTexImage(false, 3, target
, level
, internalFormat
, {0, 0, 0},
1658 {width
, height
, depth
}, border
, src
, 0);
1663 void CompressedTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1664 GLint yOffset
, GLint zOffset
, GLsizei width
,
1665 GLsizei height
, GLsizei depth
,
1666 GLenum unpackFormat
, GLsizei imageSize
,
1667 WebGLintptr offset
) const {
1668 const TexImageSourceAdapter
src(&offset
);
1669 CompressedTexImage(true, 3, target
, level
, unpackFormat
,
1670 {xOffset
, yOffset
, zOffset
}, {width
, height
, depth
}, 0,
1674 void CompressedTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1675 GLint yOffset
, GLint zOffset
, GLsizei width
,
1676 GLsizei height
, GLsizei depth
,
1677 GLenum unpackFormat
,
1678 const dom::ArrayBufferView
& view
,
1679 GLuint viewElemOffset
= 0,
1680 GLuint viewElemLengthOverride
= 0) const {
1681 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1682 viewElemLengthOverride
);
1683 CompressedTexImage(true, 3, target
, level
, unpackFormat
,
1684 {xOffset
, yOffset
, zOffset
}, {width
, height
, depth
}, 0,
1688 // --------------------
1690 void CopyTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1691 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1692 GLint border
) const {
1693 CopyTexImage(2, target
, level
, internalFormat
, {0, 0, 0}, {x
, y
},
1694 {width
, height
}, border
);
1697 void CopyTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1698 GLint yOffset
, GLint x
, GLint y
, GLsizei width
,
1699 GLsizei height
) const {
1700 CopyTexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {x
, y
},
1701 {width
, height
}, 0);
1704 void CopyTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1705 GLint yOffset
, GLint zOffset
, GLint x
, GLint y
,
1706 GLsizei width
, GLsizei height
) const {
1707 CopyTexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
}, {x
, y
},
1708 {width
, height
}, 0);
1711 // -------------------
1712 // Forward legacy TexImageSource uploads for default width/height
1714 template <typename TexImageSourceT
>
1715 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1716 GLenum unpackFormat
, GLenum unpackType
,
1717 const TexImageSourceT
& anySrc
, ErrorResult
& out_error
) const {
1718 TexImage2D(target
, level
, internalFormat
, 0, 0, 0, unpackFormat
, unpackType
,
1722 template <typename TexImageSourceT
>
1723 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1724 GLenum unpackFormat
, GLenum unpackType
,
1725 const TexImageSourceT
& anySrc
,
1726 ErrorResult
& out_error
) const {
1727 TexSubImage2D(target
, level
, xOffset
, yOffset
, 0, 0, unpackFormat
,
1728 unpackType
, anySrc
, out_error
);
1731 // ------------------------ Uniforms and attributes ------------------------
1734 Maybe
<double> GetVertexAttribPriv(GLuint index
, GLenum pname
);
1737 void GetVertexAttrib(JSContext
* cx
, GLuint index
, GLenum pname
,
1738 JS::MutableHandle
<JS::Value
> retval
, ErrorResult
& rv
);
1741 const webgl::LinkResult
* GetActiveLinkResult() const {
1742 const auto& state
= State();
1743 if (state
.mCurrentProgram
) {
1744 (void)GetLinkResult(*state
.mCurrentProgram
);
1746 return state
.mActiveLinkResult
.get();
1749 void UniformData(GLenum funcElemType
, const WebGLUniformLocationJS
* const loc
,
1750 bool transpose
, const Range
<const uint8_t>& bytes
,
1751 GLuint elemOffset
= 0, GLuint elemCountOverride
= 0) const;
1755 template <typename T
>
1756 Maybe
<Range
<T
>> ValidateSubrange(const Range
<T
>& data
, size_t elemOffset
,
1757 size_t elemLengthOverride
= 0) const {
1759 if (elemOffset
> ret
.length()) {
1760 EnqueueError(LOCAL_GL_INVALID_VALUE
,
1761 "`elemOffset` too large for `data`.");
1764 ret
= {ret
.begin() + elemOffset
, ret
.end()};
1765 if (elemLengthOverride
) {
1766 if (elemLengthOverride
> ret
.length()) {
1768 LOCAL_GL_INVALID_VALUE
,
1769 "`elemLengthOverride` too large for `data` and `elemOffset`.");
1772 ret
= {ret
.begin().get(), elemLengthOverride
};
1778 #define _(T, type_t, TYPE) \
1779 void Uniform1##T(const WebGLUniformLocationJS* const loc, type_t x) const { \
1780 const type_t arr[] = {x}; \
1781 UniformData(TYPE, loc, false, MakeByteRange(arr)); \
1783 void Uniform2##T(const WebGLUniformLocationJS* const loc, type_t x, \
1785 const type_t arr[] = {x, y}; \
1786 UniformData(TYPE##_VEC2, loc, false, MakeByteRange(arr)); \
1788 void Uniform3##T(const WebGLUniformLocationJS* const loc, type_t x, \
1789 type_t y, type_t z) const { \
1790 const type_t arr[] = {x, y, z}; \
1791 UniformData(TYPE##_VEC3, loc, false, MakeByteRange(arr)); \
1793 void Uniform4##T(const WebGLUniformLocationJS* const loc, type_t x, \
1794 type_t y, type_t z, type_t w) const { \
1795 const type_t arr[] = {x, y, z, w}; \
1796 UniformData(TYPE##_VEC4, loc, false, MakeByteRange(arr)); \
1799 _(f
, float, LOCAL_GL_FLOAT
)
1800 _(i
, int32_t, LOCAL_GL_INT
)
1801 _(ui
, uint32_t, LOCAL_GL_UNSIGNED_INT
)
1807 #define _(NT, TypeListU, TYPE) \
1808 void Uniform##NT##v(const WebGLUniformLocationJS* const loc, \
1809 const TypeListU& list, GLuint elemOffset = 0, \
1810 GLuint elemCountOverride = 0) const { \
1811 UniformData(TYPE, loc, false, MakeByteRange(list), elemOffset, \
1812 elemCountOverride); \
1815 _(1f
, Float32ListU
, LOCAL_GL_FLOAT
)
1816 _(2f
, Float32ListU
, LOCAL_GL_FLOAT_VEC2
)
1817 _(3f
, Float32ListU
, LOCAL_GL_FLOAT_VEC3
)
1818 _(4f
, Float32ListU
, LOCAL_GL_FLOAT_VEC4
)
1819 _(1i
, Int32ListU
, LOCAL_GL_INT
)
1820 _(2i
, Int32ListU
, LOCAL_GL_INT_VEC2
)
1821 _(3i
, Int32ListU
, LOCAL_GL_INT_VEC3
)
1822 _(4i
, Int32ListU
, LOCAL_GL_INT_VEC4
)
1823 _(1ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT
)
1824 _(2ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC2
)
1825 _(3ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC3
)
1826 _(4ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC4
)
1833 void UniformMatrix##X##fv(const WebGLUniformLocationJS* loc, bool transpose, \
1834 const Float32ListU& list, GLuint elemOffset = 0, \
1835 GLuint elemCountOverride = 0) const { \
1836 UniformData(LOCAL_GL_FLOAT_MAT##X, loc, transpose, MakeByteRange(list), \
1837 elemOffset, elemCountOverride); \
1856 void EnableVertexAttribArray(GLuint index
);
1858 void DisableVertexAttribArray(GLuint index
);
1860 WebGLsizeiptr
GetVertexAttribOffset(GLuint index
, GLenum pname
);
1865 void VertexAttrib4Tv(GLuint index
, webgl::AttribBaseType
,
1866 const Range
<const uint8_t>&);
1869 void VertexAttrib1f(GLuint index
, GLfloat x
) {
1870 VertexAttrib4f(index
, x
, 0, 0, 1);
1872 void VertexAttrib2f(GLuint index
, GLfloat x
, GLfloat y
) {
1873 VertexAttrib4f(index
, x
, y
, 0, 1);
1875 void VertexAttrib3f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
) {
1876 VertexAttrib4f(index
, x
, y
, z
, 1);
1879 void VertexAttrib4f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
,
1881 const float arr
[4] = {x
, y
, z
, w
};
1882 VertexAttrib4Tv(index
, webgl::AttribBaseType::Float
, MakeByteRange(arr
));
1887 void VertexAttrib1fv(const GLuint index
, const Float32ListU
& list
) {
1888 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1889 if (IsContextLost()) return;
1891 const auto range
= MakeRange(list
);
1892 if (range
.length() < 1) {
1893 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=1.");
1897 VertexAttrib1f(index
, range
[0]);
1900 void VertexAttrib2fv(const GLuint index
, const Float32ListU
& list
) {
1901 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1902 if (IsContextLost()) return;
1904 const auto range
= MakeRange(list
);
1905 if (range
.length() < 2) {
1906 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=2.");
1910 VertexAttrib2f(index
, range
[0], range
[1]);
1913 void VertexAttrib3fv(const GLuint index
, const Float32ListU
& list
) {
1914 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1915 if (IsContextLost()) return;
1917 const auto range
= MakeRange(list
);
1918 if (range
.length() < 3) {
1919 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=3.");
1923 VertexAttrib3f(index
, range
[0], range
[1], range
[2]);
1926 void VertexAttrib4fv(GLuint index
, const Float32ListU
& list
) {
1927 VertexAttrib4Tv(index
, webgl::AttribBaseType::Float
, MakeByteRange(list
));
1929 void VertexAttribI4iv(GLuint index
, const Int32ListU
& list
) {
1930 VertexAttrib4Tv(index
, webgl::AttribBaseType::Int
, MakeByteRange(list
));
1932 void VertexAttribI4uiv(GLuint index
, const Uint32ListU
& list
) {
1933 VertexAttrib4Tv(index
, webgl::AttribBaseType::Uint
, MakeByteRange(list
));
1936 void VertexAttribI4i(GLuint index
, GLint x
, GLint y
, GLint z
, GLint w
) {
1937 const int32_t arr
[4] = {x
, y
, z
, w
};
1938 VertexAttrib4Tv(index
, webgl::AttribBaseType::Int
, MakeByteRange(arr
));
1940 void VertexAttribI4ui(GLuint index
, GLuint x
, GLuint y
, GLuint z
, GLuint w
) {
1941 const uint32_t arr
[4] = {x
, y
, z
, w
};
1942 VertexAttrib4Tv(index
, webgl::AttribBaseType::Uint
, MakeByteRange(arr
));
1946 void VertexAttribPointerImpl(bool isFuncInt
, GLuint index
, GLint size
,
1947 GLenum type
, WebGLboolean normalized
,
1948 GLsizei iStride
, WebGLintptr iByteOffset
);
1951 void VertexAttribIPointer(GLuint index
, GLint size
, GLenum type
,
1952 GLsizei stride
, WebGLintptr byteOffset
) {
1953 VertexAttribPointerImpl(true, index
, size
, type
, false, stride
, byteOffset
);
1956 void VertexAttribPointer(GLuint index
, GLint size
, GLenum type
,
1957 WebGLboolean normalized
, GLsizei stride
,
1958 WebGLintptr byteOffset
) {
1959 VertexAttribPointerImpl(false, index
, size
, type
, normalized
, stride
,
1963 // -------------------------------- Drawing -------------------------------
1965 void DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
1966 DrawArraysInstanced(mode
, first
, count
, 1, FuncScopeId::drawArrays
);
1969 void DrawElements(GLenum mode
, GLsizei count
, GLenum type
,
1970 WebGLintptr byteOffset
) {
1971 DrawElementsInstanced(mode
, count
, type
, byteOffset
, 1,
1972 FuncScopeId::drawElements
);
1975 void DrawRangeElements(GLenum mode
, GLuint start
, GLuint end
, GLsizei count
,
1976 GLenum type
, WebGLintptr byteOffset
) {
1977 const FuncScope
funcScope(*this, "drawRangeElements");
1979 EnqueueError(LOCAL_GL_INVALID_VALUE
, "end must be >= start.");
1982 DrawElementsInstanced(mode
, count
, type
, byteOffset
, 1,
1983 FuncScopeId::drawRangeElements
);
1986 // ------------------------------ Readback -------------------------------
1988 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1989 GLenum format
, GLenum type
,
1990 const dom::Nullable
<dom::ArrayBufferView
>& maybeView
,
1991 dom::CallerType aCallerType
, ErrorResult
& out_error
) const {
1992 const FuncScope
funcScope(*this, "readPixels");
1993 if (!ValidateNonNull("pixels", maybeView
)) return;
1994 ReadPixels(x
, y
, width
, height
, format
, type
, maybeView
.Value(), 0,
1995 aCallerType
, out_error
);
1998 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1999 GLenum format
, GLenum type
, WebGLsizeiptr offset
,
2000 dom::CallerType aCallerType
, ErrorResult
& out_error
) const;
2002 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2003 GLenum format
, GLenum type
,
2004 const dom::ArrayBufferView
& dstData
, GLuint dstElemOffset
,
2005 dom::CallerType aCallerType
, ErrorResult
& out_error
) const;
2008 bool ReadPixels_SharedPrecheck(dom::CallerType aCallerType
,
2009 ErrorResult
& out_error
) const;
2011 // ------------------------------ Vertex Array ------------------------------
2013 void BindVertexArray(WebGLVertexArrayJS
*);
2015 void DrawArraysInstanced(GLenum mode
, GLint first
, GLsizei count
,
2017 FuncScopeId aFuncId
= FuncScopeId::drawArrays
);
2019 void DrawElementsInstanced(
2020 GLenum mode
, GLsizei count
, GLenum type
, WebGLintptr offset
,
2022 FuncScopeId aFuncId
= FuncScopeId::drawElementsInstanced
);
2024 void VertexAttribDivisor(GLuint index
, GLuint divisor
);
2026 // --------------------------------- GL Query
2027 // ---------------------------------
2029 void GetQuery(JSContext
*, GLenum target
, GLenum pname
,
2030 JS::MutableHandleValue retval
) const;
2031 void GetQueryParameter(JSContext
*, WebGLQueryJS
&, GLenum pname
,
2032 JS::MutableHandleValue retval
) const;
2033 void BeginQuery(GLenum target
, WebGLQueryJS
&);
2034 void EndQuery(GLenum target
);
2035 void QueryCounter(WebGLQueryJS
&, GLenum target
) const;
2037 // -------------------------------- Sampler -------------------------------
2039 void GetSamplerParameter(JSContext
*, const WebGLSamplerJS
&, GLenum pname
,
2040 JS::MutableHandleValue retval
) const;
2042 void BindSampler(GLuint unit
, WebGLSamplerJS
*);
2043 void SamplerParameteri(WebGLSamplerJS
&, GLenum pname
, GLint param
) const;
2044 void SamplerParameterf(WebGLSamplerJS
&, GLenum pname
, GLfloat param
) const;
2046 // ------------------------------- GL Sync ---------------------------------
2048 GLenum
ClientWaitSync(WebGLSyncJS
&, GLbitfield flags
, GLuint64 timeout
) const;
2049 void GetSyncParameter(JSContext
*, WebGLSyncJS
&, GLenum pname
,
2050 JS::MutableHandleValue retval
) const;
2051 void WaitSync(const WebGLSyncJS
&, GLbitfield flags
, GLint64 timeout
) const;
2053 // -------------------------- Transform Feedback ---------------------------
2055 void BindTransformFeedback(GLenum target
, WebGLTransformFeedbackJS
*);
2056 void BeginTransformFeedback(GLenum primitiveMode
);
2057 void EndTransformFeedback();
2058 void PauseTransformFeedback();
2059 void ResumeTransformFeedback();
2061 // -------------------------- Opaque Framebuffers ---------------------------
2063 void SetFramebufferIsInOpaqueRAF(WebGLFramebufferJS
*, bool);
2065 // ------------------------------ Extensions ------------------------------
2067 void GetSupportedExtensions(dom::Nullable
<nsTArray
<nsString
>>& retval
,
2068 dom::CallerType callerType
) const;
2070 bool IsSupported(WebGLExtensionID
, dom::CallerType callerType
=
2071 dom::CallerType::NonSystem
) const;
2073 void GetExtension(JSContext
* cx
, const nsAString
& name
,
2074 JS::MutableHandle
<JSObject
*> retval
,
2075 dom::CallerType callerType
, ErrorResult
& rv
);
2078 RefPtr
<ClientWebGLExtensionBase
> GetExtension(WebGLExtensionID ext
,
2079 dom::CallerType callerType
);
2080 void RequestExtension(WebGLExtensionID
) const;
2083 bool IsExtensionEnabled(const WebGLExtensionID id
) const {
2084 return bool(mNotLost
->extensions
[UnderlyingValue(id
)]);
2087 void AddCompressedFormat(GLenum
);
2089 // ---------------------------- Misc Extensions ----------------------------
2091 void DrawBuffers(const dom::Sequence
<GLenum
>& buffers
);
2093 void GetSupportedProfilesASTC(
2094 dom::Nullable
<nsTArray
<nsString
>>& retval
) const;
2096 void MOZDebugGetParameter(JSContext
* cx
, GLenum pname
,
2097 JS::MutableHandle
<JS::Value
> retval
,
2099 GetParameter(cx
, pname
, retval
, rv
, true);
2102 // -------------------------------------------------------------------------
2103 // Client-side methods. Calls in the Host are forwarded to the client.
2104 // -------------------------------------------------------------------------
2106 void JsWarning(const std::string
&) const;
2108 // -------------------------------------------------------------------------
2109 // The cross-process communication mechanism
2110 // -------------------------------------------------------------------------
2112 template <typename ReturnType
>
2113 friend struct WebGLClientDispatcher
;
2115 template <typename MethodType
, MethodType method
, typename ReturnType
,
2117 friend ReturnType
RunOn(const ClientWebGLContext
& context
, Args
&&... aArgs
);
2119 // If we are running WebGL in this process then call the HostWebGLContext
2120 // method directly. Otherwise, dispatch over IPC.
2121 template <typename MethodType
, MethodType method
, typename
... Args
>
2122 void Run(Args
&&... aArgs
) const;
2124 // -------------------------------------------------------------------------
2125 // Helpers for DOM operations, composition, actors, etc
2126 // -------------------------------------------------------------------------
2129 // https://immersive-web.github.io/webxr/#xr-compatible
2130 bool IsXRCompatible() const;
2131 already_AddRefed
<dom::Promise
> MakeXRCompatible(ErrorResult
& aRv
);
2134 bool ShouldResistFingerprinting() const;
2136 // Prepare the context for capture before compositing
2137 void BeginComposition();
2139 // Clean up the context after captured for compositing
2140 void EndComposition();
2142 mozilla::dom::Document
* GetOwnerDoc() const;
2144 bool mResetLayer
= true;
2145 Maybe
<const WebGLContextOptions
> mInitialOptions
;
2146 bool mXRCompatible
= false;
2149 // used by DOM bindings in conjunction with GetParentObject
2150 inline nsISupports
* ToSupports(ClientWebGLContext
* webgl
) {
2151 return static_cast<nsICanvasRenderingContextInternal
*>(webgl
);
2154 const char* GetExtensionName(WebGLExtensionID
);
2158 inline bool webgl::ObjectJS::IsForContext(
2159 const ClientWebGLContext
& context
) const {
2160 const auto& notLost
= context
.mNotLost
;
2161 if (!notLost
) return false;
2162 if (notLost
.get() != mGeneration
.lock().get()) return false;
2166 void AutoJsWarning(const std::string
& utf8
);
2168 } // namespace mozilla
2170 #endif // CLIENTWEBGLCONTEXT_H_