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 "mozilla/StaticPrefs_webgl.h"
19 #include "WebGLFormats.h"
20 #include "WebGLStrongTypes.h"
21 #include "WebGLTypes.h"
23 #include "mozilla/Logging.h"
24 #include "WebGLCommandQueue.h"
27 #include <unordered_map>
28 #include <unordered_set>
33 class ClientWebGLExtensionBase
;
34 class HostWebGLContext
;
37 class OwningHTMLCanvasElementOrOffscreenCanvas
;
42 class DrawTargetWebgl
;
46 class AvailabilityRunnable
;
51 ////////////////////////////////////
53 class WebGLActiveInfoJS final
: public RefCounted
<WebGLActiveInfoJS
> {
55 MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLActiveInfoJS
)
57 const webgl::ActiveInfo mInfo
;
59 explicit WebGLActiveInfoJS(const webgl::ActiveInfo
& info
) : mInfo(info
) {}
61 virtual ~WebGLActiveInfoJS() = default;
66 GLint
Size() const { return static_cast<GLint
>(mInfo
.elemCount
); }
67 GLenum
Type() const { return mInfo
.elemType
; }
69 void GetName(nsString
& retval
) const { CopyUTF8toUTF16(mInfo
.name
, retval
); }
71 bool WrapObject(JSContext
*, JS::Handle
<JSObject
*>,
72 JS::MutableHandle
<JSObject
*>);
75 class WebGLShaderPrecisionFormatJS final
76 : public RefCounted
<WebGLShaderPrecisionFormatJS
> {
78 MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLShaderPrecisionFormatJS
)
80 const webgl::ShaderPrecisionFormat mInfo
;
82 explicit WebGLShaderPrecisionFormatJS(
83 const webgl::ShaderPrecisionFormat
& info
)
86 virtual ~WebGLShaderPrecisionFormatJS() = default;
88 GLint
RangeMin() const { return mInfo
.rangeMin
; }
89 GLint
RangeMax() const { return mInfo
.rangeMax
; }
90 GLint
Precision() const { return mInfo
.precision
; }
92 bool WrapObject(JSContext
*, JS::Handle
<JSObject
*>,
93 JS::MutableHandle
<JSObject
*>);
96 // -----------------------
98 class ClientWebGLContext
;
100 class WebGLFramebufferJS
;
101 class WebGLProgramJS
;
103 class WebGLRenderbufferJS
;
104 class WebGLSamplerJS
;
106 class WebGLTextureJS
;
107 class WebGLTransformFeedbackJS
;
108 class WebGLVertexArrayJS
;
114 class ProgramKeepAlive final
{
115 friend class mozilla::WebGLProgramJS
;
117 WebGLProgramJS
* mParent
;
120 explicit ProgramKeepAlive(WebGLProgramJS
& parent
) : mParent(&parent
) {}
124 class ShaderKeepAlive final
{
125 friend class mozilla::WebGLShaderJS
;
127 const WebGLShaderJS
* mParent
;
130 explicit ShaderKeepAlive(const WebGLShaderJS
& parent
) : mParent(&parent
) {}
134 class ContextGenerationInfo final
{
136 ObjectId mLastId
= 0;
139 webgl::ExtensionBits mEnabledExtensions
;
140 RefPtr
<WebGLProgramJS
> mCurrentProgram
;
141 std::shared_ptr
<webgl::ProgramKeepAlive
> mProgramKeepAlive
;
142 mutable std::shared_ptr
<webgl::LinkResult
> mActiveLinkResult
;
144 RefPtr
<WebGLTransformFeedbackJS
> mDefaultTfo
;
145 RefPtr
<WebGLVertexArrayJS
> mDefaultVao
;
147 std::unordered_map
<GLenum
, RefPtr
<WebGLBufferJS
>> mBoundBufferByTarget
;
148 std::vector
<RefPtr
<WebGLBufferJS
>> mBoundUbos
;
149 RefPtr
<WebGLFramebufferJS
> mBoundDrawFb
;
150 RefPtr
<WebGLFramebufferJS
> mBoundReadFb
;
151 RefPtr
<WebGLRenderbufferJS
> mBoundRb
;
152 RefPtr
<WebGLTransformFeedbackJS
> mBoundTfo
;
153 RefPtr
<WebGLVertexArrayJS
> mBoundVao
;
154 std::unordered_map
<GLenum
, RefPtr
<WebGLQueryJS
>> mCurrentQueryByTarget
;
156 struct TexUnit final
{
157 RefPtr
<WebGLSamplerJS
> sampler
;
158 std::unordered_map
<GLenum
, RefPtr
<WebGLTextureJS
>> texByTarget
;
160 uint32_t mActiveTexUnit
= 0;
161 std::vector
<TexUnit
> mTexUnits
;
163 bool mTfActiveAndNotPaused
= false;
165 std::vector
<TypedQuad
> mGenericVertexAttribs
;
167 std::array
<int32_t, 4> mScissor
= {};
168 std::array
<int32_t, 4> mViewport
= {};
169 std::array
<float, 4> mClearColor
= {{0, 0, 0, 0}};
170 std::array
<float, 4> mBlendColor
= {{0, 0, 0, 0}};
171 std::array
<float, 2> mDepthRange
= {{0, 1}};
172 webgl::PixelPackingState mPixelPackState
;
173 webgl::PixelUnpackStateWebgl mPixelUnpackState
;
175 std::vector
<GLenum
> mCompressedTextureFormats
;
177 Maybe
<uvec2
> mDrawingBufferSize
;
179 webgl::ProvokingVertex mProvokingVertex
= webgl::ProvokingVertex::LastVertex
;
181 ObjectId
NextId() { return mLastId
+= 1; }
186 // In the cross process case, the WebGL actor's ownership relationship looks
188 // ---------------------------------------------------------------------
189 // | ClientWebGLContext -> WebGLChild -> WebGLParent -> HostWebGLContext
190 // ---------------------------------------------------------------------
192 // where 'A -> B' means "A owns B"
194 struct NotLostData final
{
195 ClientWebGLContext
& context
;
196 webgl::InitContextResult info
;
198 RefPtr
<mozilla::dom::WebGLChild
> outOfProcess
;
199 UniquePtr
<HostWebGLContext
> inProcess
;
201 webgl::ContextGenerationInfo state
;
202 std::array
<RefPtr
<ClientWebGLExtensionBase
>,
203 UnderlyingValue(WebGLExtensionID::Max
)>
206 RefPtr
<layers::CanvasRenderer
> mCanvasRenderer
;
208 explicit NotLostData(ClientWebGLContext
& context
);
215 friend ClientWebGLContext
;
218 const std::weak_ptr
<NotLostData
> mGeneration
;
222 bool mDeleteRequested
= false;
224 explicit ObjectJS(const ClientWebGLContext
&);
225 virtual ~ObjectJS() = default;
228 ClientWebGLContext
* Context() const {
229 const auto locked
= mGeneration
.lock();
230 if (!locked
) return nullptr;
231 return &(locked
->context
);
234 ClientWebGLContext
* GetParentObject() const { return Context(); }
237 bool IsForContext(const ClientWebGLContext
&) const;
238 virtual bool IsDeleted() const { return mDeleteRequested
; }
240 bool IsUsable(const ClientWebGLContext
& context
) const {
241 return IsForContext(context
) && !IsDeleted();
245 bool ValidateUsable(const ClientWebGLContext
& context
,
246 const char* const argName
) const {
247 if (MOZ_LIKELY(IsUsable(context
))) return true;
248 WarnInvalidUse(context
, argName
);
253 bool ValidateForContext(const ClientWebGLContext
& context
,
254 const char* const argName
) const;
257 void WarnInvalidUse(const ClientWebGLContext
&, const char* argName
) const;
259 // The enum is INVALID_VALUE for Program/Shader :(
260 virtual GLenum
ErrorOnDeleted() const { return LOCAL_GL_INVALID_OPERATION
; }
265 // -------------------------
267 class WebGLBufferJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
268 friend class ClientWebGLContext
;
270 webgl::BufferKind mKind
=
271 webgl::BufferKind::Undefined
; // !IsBuffer until Bind
274 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLBufferJS
)
275 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLBufferJS
)
277 explicit WebGLBufferJS(const ClientWebGLContext
& webgl
)
278 : webgl::ObjectJS(webgl
) {}
284 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
289 class WebGLFramebufferJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
290 friend class ClientWebGLContext
;
293 struct Attachment final
{
294 RefPtr
<WebGLRenderbufferJS
> rb
;
295 RefPtr
<WebGLTextureJS
> tex
;
299 bool mHasBeenBound
= false; // !IsFramebuffer until Bind
300 std::unordered_map
<GLenum
, Attachment
> mAttachments
;
301 // Holds Some Id if async present is used
302 Maybe
<layers::RemoteTextureId
> mLastRemoteTextureId
;
303 Maybe
<layers::RemoteTextureOwnerId
> mRemoteTextureOwnerId
;
304 // Needs sync IPC to ensure that the remote texture exists in the
306 bool mNeedsRemoteTextureSync
= true;
309 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebufferJS
)
310 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLFramebufferJS
)
312 explicit WebGLFramebufferJS(const ClientWebGLContext
&, bool opaque
= false);
315 bool mInOpaqueRAF
= false;
318 ~WebGLFramebufferJS();
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_NATIVE_WRAPPERCACHE_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_NATIVE_WRAPPERCACHE_CLASS(WebGLQueryJS
)
406 explicit WebGLQueryJS(const ClientWebGLContext
& webgl
)
407 : webgl::ObjectJS(webgl
) {}
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_NATIVE_WRAPPERCACHE_CLASS(WebGLRenderbufferJS
)
427 bool mHasBeenBound
= false; // !IsRenderbuffer until Bind
429 explicit WebGLRenderbufferJS(const ClientWebGLContext
& webgl
)
430 : webgl::ObjectJS(webgl
) {}
431 ~WebGLRenderbufferJS();
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_NATIVE_WRAPPERCACHE_CLASS(WebGLSamplerJS
)
445 explicit WebGLSamplerJS(const ClientWebGLContext
& webgl
)
446 : webgl::ObjectJS(webgl
) {}
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_NATIVE_WRAPPERCACHE_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 uint8_t mNumQueriesBeforeFirstFrameBoundary
= 0;
500 bool mSignaled
= false;
503 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSyncJS
)
504 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLSyncJS
)
506 explicit WebGLSyncJS(const ClientWebGLContext
& webgl
)
507 : webgl::ObjectJS(webgl
) {}
513 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
518 class WebGLTextureJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
519 friend class ClientWebGLContext
;
521 GLenum mTarget
= 0; // !IsTexture until Bind
524 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTextureJS
)
525 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLTextureJS
)
527 explicit WebGLTextureJS(const ClientWebGLContext
& webgl
)
528 : webgl::ObjectJS(webgl
) {}
534 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
539 class WebGLTransformFeedbackJS final
: public nsWrapperCache
,
540 public webgl::ObjectJS
{
541 friend class ClientWebGLContext
;
543 bool mHasBeenBound
= false; // !IsTransformFeedback until Bind
544 bool mActiveOrPaused
= false;
545 std::vector
<RefPtr
<WebGLBufferJS
>> mAttribBuffers
;
546 RefPtr
<WebGLProgramJS
> mActiveProgram
;
547 std::shared_ptr
<webgl::ProgramKeepAlive
> mActiveProgramKeepAlive
;
550 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTransformFeedbackJS
)
551 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLTransformFeedbackJS
)
553 explicit WebGLTransformFeedbackJS(const ClientWebGLContext
&);
556 ~WebGLTransformFeedbackJS();
559 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
564 std::array
<uint16_t, 3> ValidUploadElemTypes(GLenum
);
566 class WebGLUniformLocationJS final
: public nsWrapperCache
,
567 public webgl::ObjectJS
{
568 friend class ClientWebGLContext
;
570 const std::weak_ptr
<webgl::LinkResult
> mParent
;
571 const uint32_t mLocation
;
572 const std::array
<uint16_t, 3> mValidUploadElemTypes
;
575 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLUniformLocationJS
)
576 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLUniformLocationJS
)
578 WebGLUniformLocationJS(const ClientWebGLContext
& webgl
,
579 std::weak_ptr
<webgl::LinkResult
> parent
, uint32_t loc
,
581 : webgl::ObjectJS(webgl
),
584 mValidUploadElemTypes(ValidUploadElemTypes(elemType
)) {}
587 ~WebGLUniformLocationJS() = default;
590 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
595 class WebGLVertexArrayJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
596 friend class ClientWebGLContext
;
598 bool mHasBeenBound
= false; // !IsVertexArray until Bind
599 RefPtr
<WebGLBufferJS
> mIndexBuffer
;
600 std::vector
<RefPtr
<WebGLBufferJS
>> mAttribBuffers
;
603 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLVertexArrayJS
)
604 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLVertexArrayJS
)
606 explicit WebGLVertexArrayJS(const ClientWebGLContext
&);
609 ~WebGLVertexArrayJS();
612 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
615 ////////////////////////////////////
617 using Float32ListU
= dom::MaybeSharedFloat32ArrayOrUnrestrictedFloatSequence
;
618 using Int32ListU
= dom::MaybeSharedInt32ArrayOrLongSequence
;
619 using Uint32ListU
= dom::MaybeSharedUint32ArrayOrUnsignedLongSequence
;
621 inline Range
<const float> MakeRange(const Float32ListU
& list
) {
622 if (list
.IsFloat32Array()) return MakeRangeAbv(list
.GetAsFloat32Array());
624 return MakeRange(list
.GetAsUnrestrictedFloatSequence());
627 inline Range
<const int32_t> MakeRange(const Int32ListU
& list
) {
628 if (list
.IsInt32Array()) return MakeRangeAbv(list
.GetAsInt32Array());
630 return MakeRange(list
.GetAsLongSequence());
633 inline Range
<const uint32_t> MakeRange(const Uint32ListU
& list
) {
634 if (list
.IsUint32Array()) return MakeRangeAbv(list
.GetAsUint32Array());
636 return MakeRange(list
.GetAsUnsignedLongSequence());
639 template <typename T
>
640 inline Range
<const uint8_t> MakeByteRange(const T
& x
) {
641 const auto typed
= MakeRange(x
);
642 return Range
<const uint8_t>(
643 reinterpret_cast<const uint8_t*>(typed
.begin().get()),
644 typed
.length() * sizeof(typed
[0]));
649 struct TexImageSourceAdapter final
: public TexImageSource
{
650 TexImageSourceAdapter(const dom::Nullable
<dom::ArrayBufferView
>* maybeView
,
652 if (!maybeView
->IsNull()) {
653 mView
= &(maybeView
->Value());
657 TexImageSourceAdapter(const dom::Nullable
<dom::ArrayBufferView
>* maybeView
,
658 GLuint viewElemOffset
) {
659 if (!maybeView
->IsNull()) {
660 mView
= &(maybeView
->Value());
662 mViewElemOffset
= viewElemOffset
;
665 TexImageSourceAdapter(const dom::ArrayBufferView
* view
, ErrorResult
*) {
669 TexImageSourceAdapter(const dom::ArrayBufferView
* view
, GLuint viewElemOffset
,
670 GLuint viewElemLengthOverride
= 0) {
672 mViewElemOffset
= viewElemOffset
;
673 mViewElemLengthOverride
= viewElemLengthOverride
;
676 explicit TexImageSourceAdapter(const WebGLintptr
* pboOffset
,
677 GLuint ignored1
= 0, GLuint ignored2
= 0) {
678 mPboOffset
= pboOffset
;
681 TexImageSourceAdapter(const WebGLintptr
* pboOffset
, ErrorResult
* ignored
) {
682 mPboOffset
= pboOffset
;
685 TexImageSourceAdapter(const dom::ImageBitmap
* imageBitmap
,
686 ErrorResult
* out_error
) {
687 mImageBitmap
= imageBitmap
;
688 mOut_error
= out_error
;
691 TexImageSourceAdapter(const dom::ImageData
* imageData
, ErrorResult
*) {
692 mImageData
= imageData
;
695 TexImageSourceAdapter(const dom::OffscreenCanvas
* offscreenCanvas
,
696 ErrorResult
* const out_error
) {
697 mOffscreenCanvas
= offscreenCanvas
;
698 mOut_error
= out_error
;
701 TexImageSourceAdapter(const dom::Element
* domElem
,
702 ErrorResult
* const out_error
) {
704 mOut_error
= out_error
;
709 * Base class for all IDL implementations of WebGLContext
711 class ClientWebGLContext final
: public nsICanvasRenderingContextInternal
,
712 public nsWrapperCache
{
713 friend class webgl::AvailabilityRunnable
;
714 friend class webgl::ObjectJS
;
715 friend class webgl::ProgramKeepAlive
;
716 friend class webgl::ShaderKeepAlive
;
717 friend class gfx::DrawTargetWebgl
;
719 // ----------------------------- Lifetime and DOM ---------------------------
721 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
722 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ClientWebGLContext
)
724 JSObject
* WrapObject(JSContext
* cx
,
725 JS::Handle
<JSObject
*> givenProto
) override
{
727 return dom::WebGL2RenderingContext_Binding::Wrap(cx
, this, givenProto
);
729 return dom::WebGLRenderingContext_Binding::Wrap(cx
, this, givenProto
);
735 const bool mIsWebGL2
;
738 bool mIsCanvasDirty
= false;
739 uvec2 mRequestedSize
= {};
742 explicit ClientWebGLContext(bool webgl2
);
745 virtual ~ClientWebGLContext();
747 const RefPtr
<ClientWebGLExtensionLoseContext
> mExtLoseContext
;
749 mutable std::shared_ptr
<webgl::NotLostData
> mNotLost
;
750 mutable GLenum mNextError
= 0;
751 mutable webgl::LossStatus mLossStatus
= webgl::LossStatus::Ready
;
752 mutable bool mAwaitingRestore
= false;
753 // Holds Some Id if async present is used
754 mutable Maybe
<layers::RemoteTextureId
> mLastRemoteTextureId
;
755 mutable Maybe
<layers::RemoteTextureOwnerId
> mRemoteTextureOwnerId
;
756 // Needs sync IPC to ensure that the remote texture exists in the
758 bool mNeedsRemoteTextureSync
= true;
763 const auto& Limits() const { return mNotLost
->info
.limits
; }
764 const auto& Vendor() const { return mNotLost
->info
.vendor
; }
765 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#actual-context-parameters
766 const WebGLContextOptions
& ActualContextParameters() const {
767 MOZ_ASSERT(mNotLost
!= nullptr);
768 return mNotLost
->info
.options
;
771 auto& State() { return mNotLost
->state
; }
772 const auto& State() const {
773 return const_cast<ClientWebGLContext
*>(this)->State();
779 mutable RefPtr
<webgl::AvailabilityRunnable
> mAvailabilityRunnable
;
782 webgl::AvailabilityRunnable
& EnsureAvailabilityRunnable() const;
787 void EmulateLoseContext() const;
788 void OnContextLoss(webgl::ContextLossReason
) const;
789 void RestoreContext(webgl::LossStatus requiredStatus
) const;
792 bool DispatchEvent(const nsAString
&) const;
793 void Event_webglcontextlost() const;
794 void Event_webglcontextrestored() const;
796 bool CreateHostContext(const uvec2
& requestedSize
);
797 void ThrowEvent_WebGLContextCreationError(const std::string
&) const;
799 void UpdateCanvasParameters();
802 void MarkCanvasDirty();
804 void MarkContextClean() override
{}
806 void OnBeforePaintTransaction() override
;
808 mozilla::dom::WebGLChild
* GetChild() const {
809 if (!mNotLost
) return nullptr;
810 if (!mNotLost
->outOfProcess
) return nullptr;
811 return mNotLost
->outOfProcess
.get();
814 // -------------------------------------------------------------------------
815 // Client WebGL API call tracking and error message reporting
816 // -------------------------------------------------------------------------
818 // Remembers the WebGL function that is lowest on the stack for client-side
820 class FuncScope final
{
822 const ClientWebGLContext
& mWebGL
;
823 const std::shared_ptr
<webgl::NotLostData
> mKeepNotLostOrNull
;
824 const char* const mFuncName
;
826 FuncScope(const ClientWebGLContext
& webgl
, const char* funcName
)
828 mKeepNotLostOrNull(webgl
.mNotLost
),
829 mFuncName(funcName
) {
830 // Only set if an "outer" scope hasn't already been set.
831 if (!mWebGL
.mFuncScope
) {
832 mWebGL
.mFuncScope
= this;
837 if (this == mWebGL
.mFuncScope
) {
838 mWebGL
.mFuncScope
= nullptr;
842 FuncScope(const FuncScope
&) = delete;
843 FuncScope(FuncScope
&&) = delete;
847 // The scope of the function at the top of the current WebGL function call
849 mutable FuncScope
* mFuncScope
= nullptr;
851 const char* FuncName() const {
852 return mFuncScope
? mFuncScope
->mFuncName
: nullptr;
856 template <typename
... Args
>
857 void EnqueueError(const GLenum error
, const char* const format
,
858 const Args
&... args
) const {
859 MOZ_ASSERT(FuncName());
861 text
.AppendPrintf("WebGL warning: %s: ", FuncName());
864 # pragma clang diagnostic push
865 # pragma clang diagnostic ignored "-Wformat-security"
866 #elif defined(__GNUC__)
867 # pragma GCC diagnostic push
868 # pragma GCC diagnostic ignored "-Wformat-security"
870 text
.AppendPrintf(format
, args
...);
872 # pragma clang diagnostic pop
873 #elif defined(__GNUC__)
874 # pragma GCC diagnostic pop
877 EnqueueErrorImpl(error
, text
);
880 void EnqueueError(const webgl::ErrorInfo
& info
) const {
881 EnqueueError(info
.type
, "%s", info
.info
.c_str());
884 template <typename
... Args
>
885 void EnqueueWarning(const char* const format
, const Args
&... args
) const {
886 EnqueueError(0, format
, args
...);
889 template <typename
... Args
>
890 void EnqueuePerfWarning(const char* const format
, const Args
&... args
) const {
891 EnqueueError(webgl::kErrorPerfWarning
, format
, args
...);
894 void EnqueueError_ArgEnum(const char* argName
,
895 GLenum val
) const; // Cold code.
898 void EnqueueErrorImpl(GLenum errorOrZero
, const nsACString
&) const;
901 bool ValidateArrayBufferView(const dom::ArrayBufferView
& view
,
902 GLuint elemOffset
, GLuint elemCountOverride
,
903 const GLenum errorEnum
,
904 uint8_t** const out_bytes
,
905 size_t* const out_byteLen
) const;
908 template <typename T
>
909 bool ValidateNonNull(const char* const argName
,
910 const dom::Nullable
<T
>& maybe
) const {
911 if (maybe
.IsNull()) {
912 EnqueueError(LOCAL_GL_INVALID_VALUE
, "%s: Cannot be null.", argName
);
918 bool ValidateNonNegative(const char* argName
, int64_t val
) const {
919 if (MOZ_UNLIKELY(val
< 0)) {
920 EnqueueError(LOCAL_GL_INVALID_VALUE
, "`%s` must be non-negative.",
927 bool ValidateViewType(GLenum unpackType
, const TexImageSource
& src
) const;
929 Maybe
<uvec3
> ValidateExtents(GLsizei width
, GLsizei height
, GLsizei depth
,
932 // -------------------------------------------------------------------------
933 // nsICanvasRenderingContextInternal / nsAPostRefreshObserver
934 // -------------------------------------------------------------------------
936 bool InitializeCanvasRenderer(nsDisplayListBuilder
* aBuilder
,
937 layers::CanvasRenderer
* aRenderer
) override
;
939 void MarkContextCleanForFrameCapture() override
{
940 mFrameCaptureState
= FrameCaptureState::CLEAN
;
942 // Note that 'clean' here refers to its invalidation state, not the
943 // contents of the buffer.
944 Watchable
<FrameCaptureState
>* GetFrameCaptureState() override
{
945 return &mFrameCaptureState
;
948 void OnMemoryPressure() override
;
949 void SetContextOptions(const WebGLContextOptions
& aOptions
) {
950 mInitialOptions
.emplace(aOptions
);
952 const WebGLContextOptions
& GetContextOptions() const {
953 return mInitialOptions
.ref();
956 SetContextOptions(JSContext
* cx
, JS::Handle
<JS::Value
> options
,
957 ErrorResult
& aRvForDictionaryInit
) override
;
959 SetDimensions(int32_t width
, int32_t height
) override
;
960 bool UpdateWebRenderCanvasData(
961 nsDisplayListBuilder
* aBuilder
,
962 layers::WebRenderCanvasData
* aCanvasData
) override
;
966 int32_t GetWidth() override
{ return AutoAssertCast(DrawingBufferSize().x
); }
967 int32_t GetHeight() override
{ return AutoAssertCast(DrawingBufferSize().y
); }
969 NS_IMETHOD
InitializeWithDrawTarget(nsIDocShell
*,
970 NotNull
<gfx::DrawTarget
*>) override
{
971 return NS_ERROR_NOT_IMPLEMENTED
;
974 void ResetBitmap() override
;
976 UniquePtr
<uint8_t[]> GetImageBuffer(int32_t* out_format
,
977 gfx::IntSize
* out_imageSize
) override
;
978 NS_IMETHOD
GetInputStream(const char* mimeType
,
979 const nsAString
& encoderOptions
,
980 nsIInputStream
** out_stream
) override
;
982 already_AddRefed
<mozilla::gfx::SourceSurface
> GetSurfaceSnapshot(
983 gfxAlphaType
* out_alphaType
) override
;
985 void SetOpaqueValueFromOpaqueAttr(bool) override
{};
986 bool GetIsOpaque() override
{ return !mInitialOptions
->alpha
; }
989 * An abstract base class to be implemented by callers wanting to be notified
990 * that a refresh has occurred. Callers must ensure an observer is removed
991 * before it is destroyed.
993 void DidRefresh() override
;
995 NS_IMETHOD
Redraw(const gfxRect
&) override
{
996 return NS_ERROR_NOT_IMPLEMENTED
;
1002 layers::LayersBackend
GetCompositorBackendType() const;
1004 Watchable
<FrameCaptureState
> mFrameCaptureState
= {
1005 FrameCaptureState::CLEAN
, "ClientWebGLContext::mFrameCaptureState"};
1007 // -------------------------------------------------------------------------
1008 // WebGLRenderingContext Basic Properties and Methods
1009 // -------------------------------------------------------------------------
1011 dom::HTMLCanvasElement
* GetCanvas() const { return mCanvasElement
; }
1014 dom::Nullable
<dom::OwningHTMLCanvasElementOrOffscreenCanvas
>& retval
);
1016 GLsizei
DrawingBufferWidth() {
1017 const FuncScope
funcScope(*this, "drawingBufferWidth");
1018 return AutoAssertCast(DrawingBufferSize().x
);
1020 GLsizei
DrawingBufferHeight() {
1021 const FuncScope
funcScope(*this, "drawingBufferHeight");
1022 return AutoAssertCast(DrawingBufferSize().y
);
1024 void GetContextAttributes(dom::Nullable
<dom::WebGLContextAttributes
>& retval
);
1027 webgl::SwapChainOptions
PrepareAsyncSwapChainOptions(
1028 WebGLFramebufferJS
* fb
, bool webvr
,
1029 const webgl::SwapChainOptions
& options
= webgl::SwapChainOptions());
1032 layers::TextureType
GetTexTypeForSwapChain() const;
1034 WebGLFramebufferJS
*, const bool webvr
= false,
1035 const webgl::SwapChainOptions
& options
= webgl::SwapChainOptions());
1037 WebGLFramebufferJS
*, layers::TextureType
, const bool webvr
= false,
1038 const webgl::SwapChainOptions
& options
= webgl::SwapChainOptions());
1039 void CopyToSwapChain(
1040 WebGLFramebufferJS
*,
1041 const webgl::SwapChainOptions
& options
= webgl::SwapChainOptions());
1043 Maybe
<layers::SurfaceDescriptor
> GetFrontBuffer(
1044 WebGLFramebufferJS
*, const bool webvr
= false) override
;
1045 Maybe
<layers::SurfaceDescriptor
> PresentFrontBuffer(
1046 WebGLFramebufferJS
*, layers::TextureType
,
1047 const bool webvr
= false) override
;
1048 RefPtr
<gfx::SourceSurface
> GetFrontBufferSnapshot(
1049 bool requireAlphaPremult
= true) override
;
1051 void ClearVRSwapChain();
1054 RefPtr
<gfx::DataSourceSurface
> BackBufferSnapshot();
1055 [[nodiscard
]] bool DoReadPixels(const webgl::ReadPixelsDesc
&,
1056 Range
<uint8_t>) const;
1057 [[nodiscard
]] bool DoReadPixels(const webgl::ReadPixelsDesc
&,
1058 const mozilla::ipc::Shmem
&) const;
1059 uvec2
DrawingBufferSize();
1063 bool mAutoFlushPending
= false;
1065 void AutoEnqueueFlush() {
1066 if (MOZ_LIKELY(mAutoFlushPending
)) return;
1067 mAutoFlushPending
= true;
1069 const auto weak
= WeakPtr
<ClientWebGLContext
>(this);
1070 const auto DeferredFlush
= [weak
]() {
1071 const auto strong
= RefPtr
<ClientWebGLContext
>(weak
);
1072 if (!strong
) return;
1073 if (!strong
->mAutoFlushPending
) return;
1074 strong
->mAutoFlushPending
= false;
1076 if (!StaticPrefs::webgl_auto_flush()) return;
1077 const bool flushGl
= StaticPrefs::webgl_auto_flush_gl();
1078 strong
->Flush(flushGl
);
1081 already_AddRefed
<mozilla::CancelableRunnable
> runnable
=
1082 NS_NewCancelableRunnableFunction("enqueue Event_webglcontextrestored",
1084 NS_DispatchToCurrentThread(std::move(runnable
));
1087 void CancelAutoFlush() { mAutoFlushPending
= false; }
1091 void AfterDrawCall() {
1092 if (!mNotLost
) return;
1093 const auto& state
= State();
1094 if (!state
.mBoundDrawFb
) {
1101 // -------------------------------------------------------------------------
1102 // Client-side helper methods. Dispatch to a Host method.
1103 // -------------------------------------------------------------------------
1105 // ------------------------- GL State -------------------------
1107 bool IsContextLost() const { return !mNotLost
; }
1109 void Disable(GLenum cap
) const { SetEnabledI(cap
, {}, false); }
1110 void Enable(GLenum cap
) const { SetEnabledI(cap
, {}, true); }
1111 void SetEnabledI(GLenum cap
, Maybe
<GLuint
> i
, bool val
) const;
1112 bool IsEnabled(GLenum cap
) const;
1115 Maybe
<double> GetNumber(GLenum pname
);
1116 Maybe
<std::string
> GetString(GLenum pname
);
1119 void GetParameter(JSContext
* cx
, GLenum pname
,
1120 JS::MutableHandle
<JS::Value
> retval
, ErrorResult
& rv
,
1121 bool debug
= false);
1123 void GetBufferParameter(JSContext
* cx
, GLenum target
, GLenum pname
,
1124 JS::MutableHandle
<JS::Value
> retval
) const;
1126 void GetFramebufferAttachmentParameter(JSContext
* cx
, GLenum target
,
1127 GLenum attachment
, GLenum pname
,
1128 JS::MutableHandle
<JS::Value
> retval
,
1129 ErrorResult
& rv
) const;
1131 void GetRenderbufferParameter(JSContext
* cx
, GLenum target
, GLenum pname
,
1132 JS::MutableHandle
<JS::Value
> retval
) const;
1134 void GetIndexedParameter(JSContext
* cx
, GLenum target
, GLuint index
,
1135 JS::MutableHandle
<JS::Value
> retval
,
1136 ErrorResult
& rv
) const;
1138 already_AddRefed
<WebGLShaderPrecisionFormatJS
> GetShaderPrecisionFormat(
1139 GLenum shadertype
, GLenum precisiontype
);
1141 void UseProgram(WebGLProgramJS
*);
1142 void ValidateProgram(WebGLProgramJS
&) const;
1146 already_AddRefed
<WebGLBufferJS
> CreateBuffer() const;
1147 already_AddRefed
<WebGLFramebufferJS
> CreateFramebuffer() const;
1148 already_AddRefed
<WebGLFramebufferJS
> CreateOpaqueFramebuffer(
1149 const webgl::OpaqueFramebufferOptions
&) const;
1150 already_AddRefed
<WebGLProgramJS
> CreateProgram() const;
1151 already_AddRefed
<WebGLQueryJS
> CreateQuery() const;
1152 already_AddRefed
<WebGLRenderbufferJS
> CreateRenderbuffer() const;
1153 already_AddRefed
<WebGLSamplerJS
> CreateSampler() const;
1154 already_AddRefed
<WebGLShaderJS
> CreateShader(GLenum type
) const;
1155 already_AddRefed
<WebGLSyncJS
> FenceSync(GLenum condition
,
1156 GLbitfield flags
) const;
1157 already_AddRefed
<WebGLTextureJS
> CreateTexture() const;
1158 already_AddRefed
<WebGLTransformFeedbackJS
> CreateTransformFeedback() const;
1159 already_AddRefed
<WebGLVertexArrayJS
> CreateVertexArray() const;
1161 void DeleteBuffer(WebGLBufferJS
*);
1162 void DeleteFramebuffer(WebGLFramebufferJS
*, bool canDeleteOpaque
= false);
1163 void DeleteProgram(WebGLProgramJS
*) const;
1164 void DeleteQuery(WebGLQueryJS
*);
1165 void DeleteRenderbuffer(WebGLRenderbufferJS
*);
1166 void DeleteSampler(WebGLSamplerJS
*);
1167 void DeleteShader(WebGLShaderJS
*) const;
1168 void DeleteSync(WebGLSyncJS
*) const;
1169 void DeleteTexture(WebGLTextureJS
*);
1170 void DeleteTransformFeedback(WebGLTransformFeedbackJS
*);
1171 void DeleteVertexArray(WebGLVertexArrayJS
*);
1174 void DoDeleteProgram(WebGLProgramJS
&) const;
1175 void DoDeleteShader(const WebGLShaderJS
&) const;
1180 bool IsBuffer(const WebGLBufferJS
*) const;
1181 bool IsFramebuffer(const WebGLFramebufferJS
*) const;
1182 bool IsProgram(const WebGLProgramJS
*) const;
1183 bool IsQuery(const WebGLQueryJS
*) const;
1184 bool IsRenderbuffer(const WebGLRenderbufferJS
*) const;
1185 bool IsSampler(const WebGLSamplerJS
*) const;
1186 bool IsShader(const WebGLShaderJS
*) const;
1187 bool IsSync(const WebGLSyncJS
*) const;
1188 bool IsTexture(const WebGLTextureJS
*) const;
1189 bool IsTransformFeedback(const WebGLTransformFeedbackJS
*) const;
1190 bool IsVertexArray(const WebGLVertexArrayJS
*) const;
1196 const webgl::LinkResult
& GetLinkResult(const WebGLProgramJS
&) const;
1199 void AttachShader(WebGLProgramJS
&, WebGLShaderJS
&) const;
1200 void BindAttribLocation(WebGLProgramJS
&, GLuint location
,
1201 const nsAString
& name
) const;
1202 void DetachShader(WebGLProgramJS
&, const WebGLShaderJS
&) const;
1203 void GetAttachedShaders(
1204 const WebGLProgramJS
&,
1205 dom::Nullable
<nsTArray
<RefPtr
<WebGLShaderJS
>>>& retval
) const;
1206 void LinkProgram(WebGLProgramJS
&) const;
1207 void TransformFeedbackVaryings(WebGLProgramJS
&,
1208 const dom::Sequence
<nsString
>& varyings
,
1209 GLenum bufferMode
) const;
1210 void UniformBlockBinding(WebGLProgramJS
&, GLuint blockIndex
,
1211 GLuint blockBinding
) const;
1213 // Link result reflection
1214 already_AddRefed
<WebGLActiveInfoJS
> GetActiveAttrib(const WebGLProgramJS
&,
1216 already_AddRefed
<WebGLActiveInfoJS
> GetActiveUniform(const WebGLProgramJS
&,
1218 void GetActiveUniformBlockName(const WebGLProgramJS
&,
1219 GLuint uniformBlockIndex
,
1220 nsAString
& retval
) const;
1221 void GetActiveUniformBlockParameter(JSContext
* cx
, const WebGLProgramJS
&,
1222 GLuint uniformBlockIndex
, GLenum pname
,
1223 JS::MutableHandle
<JS::Value
> retval
,
1225 void GetActiveUniforms(JSContext
*, const WebGLProgramJS
&,
1226 const dom::Sequence
<GLuint
>& uniformIndices
,
1228 JS::MutableHandle
<JS::Value
> retval
) const;
1229 GLint
GetAttribLocation(const WebGLProgramJS
&, const nsAString
& name
) const;
1230 GLint
GetFragDataLocation(const WebGLProgramJS
&, const nsAString
& name
) const;
1231 void GetProgramInfoLog(const WebGLProgramJS
& prog
, nsAString
& retval
) const;
1232 void GetProgramParameter(JSContext
*, const WebGLProgramJS
&, GLenum pname
,
1233 JS::MutableHandle
<JS::Value
> retval
) const;
1234 already_AddRefed
<WebGLActiveInfoJS
> GetTransformFeedbackVarying(
1235 const WebGLProgramJS
&, GLuint index
);
1236 GLuint
GetUniformBlockIndex(const WebGLProgramJS
&,
1237 const nsAString
& uniformBlockName
) const;
1238 void GetUniformIndices(const WebGLProgramJS
&,
1239 const dom::Sequence
<nsString
>& uniformNames
,
1240 dom::Nullable
<nsTArray
<GLuint
>>& retval
) const;
1242 // WebGLUniformLocationJS
1243 already_AddRefed
<WebGLUniformLocationJS
> GetUniformLocation(
1244 const WebGLProgramJS
&, const nsAString
& name
) const;
1245 void GetUniform(JSContext
*, const WebGLProgramJS
&,
1246 const WebGLUniformLocationJS
&,
1247 JS::MutableHandle
<JS::Value
> retval
);
1253 const webgl::CompileResult
& GetCompileResult(const WebGLShaderJS
&) const;
1256 void CompileShader(WebGLShaderJS
&) const;
1257 void GetShaderInfoLog(const WebGLShaderJS
&, nsAString
& retval
) const;
1258 void GetShaderParameter(JSContext
*, const WebGLShaderJS
&, GLenum pname
,
1259 JS::MutableHandle
<JS::Value
> retval
) const;
1260 void GetShaderSource(const WebGLShaderJS
&, nsAString
& retval
) const;
1261 void GetTranslatedShaderSource(const WebGLShaderJS
& shader
,
1262 nsAString
& retval
) const;
1263 void ShaderSource(WebGLShaderJS
&, const nsAString
&) const;
1267 void BindFramebuffer(GLenum target
, WebGLFramebufferJS
*);
1269 void BlendColor(GLclampf r
, GLclampf g
, GLclampf b
, GLclampf a
);
1273 void BlendEquation(GLenum mode
) { BlendEquationSeparate(mode
, mode
); }
1274 void BlendFunc(GLenum sfactor
, GLenum dfactor
) {
1275 BlendFuncSeparate(sfactor
, dfactor
, sfactor
, dfactor
);
1278 void BlendEquationSeparate(GLenum modeRGB
, GLenum modeAlpha
) {
1279 BlendEquationSeparateI({}, modeRGB
, modeAlpha
);
1281 void BlendFuncSeparate(GLenum srcRGB
, GLenum dstRGB
, GLenum srcAlpha
,
1283 BlendFuncSeparateI({}, srcRGB
, dstRGB
, srcAlpha
, dstAlpha
);
1286 void BlendEquationSeparateI(Maybe
<GLuint
> buf
, GLenum modeRGB
,
1288 void BlendFuncSeparateI(Maybe
<GLuint
> buf
, GLenum srcRGB
, GLenum dstRGB
,
1289 GLenum srcAlpha
, GLenum dstAlpha
);
1293 GLenum
CheckFramebufferStatus(GLenum target
);
1295 void Clear(GLbitfield mask
);
1300 void ClearBufferTv(GLenum buffer
, GLint drawBuffer
, webgl::AttribBaseType
,
1301 const Range
<const uint8_t>& view
, GLuint srcElemOffset
);
1304 void ClearBufferfv(GLenum buffer
, GLint drawBuffer
, const Float32ListU
& list
,
1305 GLuint srcElemOffset
) {
1306 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Float
,
1307 MakeByteRange(list
), srcElemOffset
);
1309 void ClearBufferiv(GLenum buffer
, GLint drawBuffer
, const Int32ListU
& list
,
1310 GLuint srcElemOffset
) {
1311 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Int
,
1312 MakeByteRange(list
), srcElemOffset
);
1314 void ClearBufferuiv(GLenum buffer
, GLint drawBuffer
, const Uint32ListU
& list
,
1315 GLuint srcElemOffset
) {
1316 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Uint
,
1317 MakeByteRange(list
), srcElemOffset
);
1322 void ClearBufferfi(GLenum buffer
, GLint drawBuffer
, GLfloat depth
,
1325 void ClearColor(GLclampf r
, GLclampf g
, GLclampf b
, GLclampf a
);
1327 void ClearDepth(GLclampf v
);
1329 void ClearStencil(GLint v
);
1331 void ColorMask(bool r
, bool g
, bool b
, bool a
) const {
1332 ColorMaskI({}, r
, g
, b
, a
);
1334 void ColorMaskI(Maybe
<GLuint
> buf
, bool r
, bool g
, bool b
, bool a
) const;
1336 void CullFace(GLenum face
);
1338 void DepthFunc(GLenum func
);
1340 void DepthMask(WebGLboolean b
);
1342 void DepthRange(GLclampf zNear
, GLclampf zFar
);
1344 void Flush(bool flushGl
= true);
1348 void FrontFace(GLenum mode
);
1352 void Hint(GLenum target
, GLenum mode
);
1354 void LineWidth(GLfloat width
);
1356 void PixelStorei(GLenum pname
, GLint param
);
1358 void PolygonOffset(GLfloat factor
, GLfloat units
);
1360 void SampleCoverage(GLclampf value
, WebGLboolean invert
);
1362 void Scissor(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1366 void StencilFunc(GLenum func
, GLint ref
, GLuint mask
) {
1367 StencilFuncSeparate(LOCAL_GL_FRONT_AND_BACK
, func
, ref
, mask
);
1369 void StencilMask(GLuint mask
) {
1370 StencilMaskSeparate(LOCAL_GL_FRONT_AND_BACK
, mask
);
1372 void StencilOp(GLenum sfail
, GLenum dpfail
, GLenum dppass
) {
1373 StencilOpSeparate(LOCAL_GL_FRONT_AND_BACK
, sfail
, dpfail
, dppass
);
1376 void StencilFuncSeparate(GLenum face
, GLenum func
, GLint ref
, GLuint mask
);
1377 void StencilMaskSeparate(GLenum face
, GLuint mask
);
1378 void StencilOpSeparate(GLenum face
, GLenum sfail
, GLenum dpfail
,
1383 void Viewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1385 // ------------------------- Buffer Objects -------------------------
1387 void BindBuffer(GLenum target
, WebGLBufferJS
*);
1392 void BindBufferRangeImpl(const GLenum target
, const GLuint index
,
1393 WebGLBufferJS
* const buffer
, const uint64_t offset
,
1394 const uint64_t size
);
1397 void BindBufferBase(const GLenum target
, const GLuint index
,
1398 WebGLBufferJS
* const buffer
) {
1399 const FuncScope
funcScope(*this, "bindBufferBase");
1400 if (IsContextLost()) return;
1402 BindBufferRangeImpl(target
, index
, buffer
, 0, 0);
1405 void BindBufferRange(const GLenum target
, const GLuint index
,
1406 WebGLBufferJS
* const buffer
, const WebGLintptr offset
,
1407 const WebGLsizeiptr size
) {
1408 const FuncScope
funcScope(*this, "bindBufferRange");
1409 if (IsContextLost()) return;
1412 if (!ValidateNonNegative("offset", offset
)) return;
1415 EnqueueError(LOCAL_GL_INVALID_VALUE
,
1416 "`size` must be positive for non-null `buffer`.");
1421 BindBufferRangeImpl(target
, index
, buffer
, static_cast<uint64_t>(offset
),
1422 static_cast<uint64_t>(size
));
1427 void CopyBufferSubData(GLenum readTarget
, GLenum writeTarget
,
1428 GLintptr readOffset
, GLintptr writeOffset
,
1431 void BufferData(GLenum target
, WebGLsizeiptr size
, GLenum usage
);
1432 void BufferData(GLenum target
,
1433 const dom::Nullable
<dom::ArrayBuffer
>& maybeSrc
,
1435 void BufferData(GLenum target
, const dom::ArrayBufferView
& srcData
,
1436 GLenum usage
, GLuint srcElemOffset
= 0,
1437 GLuint srcElemCountOverride
= 0);
1439 void RawBufferData(GLenum target
, const uint8_t* srcBytes
, size_t srcLen
,
1441 void RawBufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1442 const uint8_t* srcBytes
, size_t srcLen
,
1443 bool unsynchronized
= false);
1445 void BufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1446 const dom::ArrayBufferView
& src
, GLuint srcElemOffset
= 0,
1447 GLuint srcElemCountOverride
= 0);
1448 void BufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1449 const dom::ArrayBuffer
& src
);
1451 void GetBufferSubData(GLenum target
, GLintptr srcByteOffset
,
1452 const dom::ArrayBufferView
& dstData
,
1453 GLuint dstElemOffset
, GLuint dstElemCountOverride
);
1455 // -------------------------- Framebuffer Objects --------------------------
1457 void BlitFramebuffer(GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1458 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1459 GLbitfield mask
, GLenum filter
);
1464 // `bindTarget` if non-zero allows initializing the rb/tex with that target.
1465 void FramebufferAttach(GLenum target
, GLenum attachEnum
, GLenum bindTarget
,
1466 WebGLRenderbufferJS
*, WebGLTextureJS
*,
1467 uint32_t mipLevel
, uint32_t zLayer
,
1468 uint32_t numViewLayers
) const;
1471 void FramebufferRenderbuffer(GLenum target
, GLenum attachSlot
,
1472 GLenum rbTarget
, WebGLRenderbufferJS
* rb
) const {
1473 const FuncScope
funcScope(*this, "framebufferRenderbuffer");
1474 if (IsContextLost()) return;
1475 if (rbTarget
!= LOCAL_GL_RENDERBUFFER
) {
1476 EnqueueError_ArgEnum("rbTarget", rbTarget
);
1479 FramebufferAttach(target
, attachSlot
, rbTarget
, rb
, nullptr, 0, 0, 0);
1482 void FramebufferTexture2D(GLenum target
, GLenum attachSlot
,
1483 GLenum texImageTarget
, WebGLTextureJS
*,
1484 GLint mipLevel
) const;
1486 void FramebufferTextureLayer(GLenum target
, GLenum attachSlot
,
1487 WebGLTextureJS
* tex
, GLint mipLevel
,
1488 GLint zLayer
) const {
1489 const FuncScope
funcScope(*this, "framebufferTextureLayer");
1490 if (IsContextLost()) return;
1491 FramebufferAttach(target
, attachSlot
, 0, nullptr, tex
,
1492 static_cast<uint32_t>(mipLevel
),
1493 static_cast<uint32_t>(zLayer
), 0);
1496 void FramebufferTextureMultiview(GLenum target
, GLenum attachSlot
,
1497 WebGLTextureJS
* tex
, GLint mipLevel
,
1499 GLsizei numViewLayers
) const {
1500 const FuncScope
funcScope(*this, "framebufferTextureMultiview");
1501 if (IsContextLost()) return;
1502 if (tex
&& numViewLayers
< 1) {
1503 EnqueueError(LOCAL_GL_INVALID_VALUE
, "`numViewLayers` must be >=1.");
1506 FramebufferAttach(target
, attachSlot
, 0, nullptr, tex
,
1507 static_cast<uint32_t>(mipLevel
),
1508 static_cast<uint32_t>(zLayerBase
),
1509 static_cast<uint32_t>(numViewLayers
));
1514 void InvalidateFramebuffer(GLenum target
,
1515 const dom::Sequence
<GLenum
>& attachments
,
1516 ErrorResult
& unused
);
1517 void InvalidateSubFramebuffer(GLenum target
,
1518 const dom::Sequence
<GLenum
>& attachments
,
1519 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1520 ErrorResult
& unused
);
1522 void ReadBuffer(GLenum mode
);
1524 // ----------------------- Renderbuffer objects -----------------------
1525 void GetInternalformatParameter(JSContext
* cx
, GLenum target
,
1526 GLenum internalformat
, GLenum pname
,
1527 JS::MutableHandle
<JS::Value
> retval
,
1530 void BindRenderbuffer(GLenum target
, WebGLRenderbufferJS
*);
1532 void RenderbufferStorage(GLenum target
, GLenum internalFormat
, GLsizei width
,
1533 GLsizei height
) const {
1534 RenderbufferStorageMultisample(target
, 0, internalFormat
, width
, height
);
1537 void RenderbufferStorageMultisample(GLenum target
, GLsizei samples
,
1538 GLenum internalFormat
, GLsizei width
,
1539 GLsizei height
) const;
1541 // --------------------------- Texture objects ---------------------------
1543 void ActiveTexture(GLenum texUnit
);
1545 void BindTexture(GLenum texTarget
, WebGLTextureJS
*);
1547 void GenerateMipmap(GLenum texTarget
) const;
1549 void GetTexParameter(JSContext
* cx
, GLenum texTarget
, GLenum pname
,
1550 JS::MutableHandle
<JS::Value
> retval
) const;
1552 void TexParameterf(GLenum texTarget
, GLenum pname
, GLfloat param
);
1553 void TexParameteri(GLenum texTarget
, GLenum pname
, GLint param
);
1558 void TexStorage(uint8_t funcDims
, GLenum target
, GLsizei levels
,
1559 GLenum internalFormat
, const ivec3
& size
) const;
1561 // Primitive tex upload functions
1562 void RawTexImage(uint32_t level
, GLenum respecFormat
, uvec3 offset
,
1563 const webgl::PackingInfo
& pi
,
1564 webgl::TexUnpackBlobDesc
&&) const;
1565 void TexImage(uint8_t funcDims
, GLenum target
, GLint level
,
1566 GLenum respecFormat
, const ivec3
& offset
,
1567 const Maybe
<ivec3
>& size
, GLint border
,
1568 const webgl::PackingInfo
& pi
, const TexImageSource
& src
) const;
1569 void CompressedTexImage(bool sub
, uint8_t funcDims
, GLenum target
,
1570 GLint level
, GLenum format
, const ivec3
& offset
,
1571 const ivec3
& size
, GLint border
,
1572 const TexImageSource
& src
,
1573 GLsizei pboImageSize
) const;
1574 void CopyTexImage(uint8_t funcDims
, GLenum target
, GLint level
,
1575 GLenum respecFormat
, const ivec3
& dstOffset
,
1576 const ivec2
& srcOffset
, const ivec2
& size
,
1577 GLint border
) const;
1580 void TexStorage2D(GLenum target
, GLsizei levels
, GLenum internalFormat
,
1581 GLsizei width
, GLsizei height
) const {
1582 TexStorage(2, target
, levels
, internalFormat
, {width
, height
, 1});
1585 void TexStorage3D(GLenum target
, GLsizei levels
, GLenum internalFormat
,
1586 GLsizei width
, GLsizei height
, GLsizei depth
) const {
1587 TexStorage(3, target
, levels
, internalFormat
, {width
, height
, depth
});
1590 ////////////////////////////////////
1592 template <typename T
> // TexImageSource or WebGLintptr
1593 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1594 GLsizei width
, GLsizei height
, GLint border
,
1595 GLenum unpackFormat
, GLenum unpackType
, const T
& anySrc
,
1596 ErrorResult
& out_error
) const {
1597 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1598 TexImage(2, target
, level
, internalFormat
, {0, 0, 0},
1599 Some(ivec3
{width
, height
, 1}), border
, {unpackFormat
, unpackType
},
1603 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1604 GLsizei width
, GLsizei height
, GLint border
,
1605 GLenum unpackFormat
, GLenum unpackType
,
1606 const dom::ArrayBufferView
& view
, GLuint viewElemOffset
,
1607 ErrorResult
&) const {
1608 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1609 TexImage(2, target
, level
, internalFormat
, {0, 0, 0},
1610 Some(ivec3
{width
, height
, 1}), border
, {unpackFormat
, unpackType
},
1616 template <typename T
> // TexImageSource or WebGLintptr
1617 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1618 GLsizei width
, GLsizei height
, GLenum unpackFormat
,
1619 GLenum unpackType
, const T
& anySrc
,
1620 ErrorResult
& out_error
) const {
1621 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1622 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0},
1623 Some(ivec3
{width
, height
, 1}), 0, {unpackFormat
, unpackType
}, src
);
1626 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1627 GLsizei width
, GLsizei height
, GLenum unpackFormat
,
1628 GLenum unpackType
, const dom::ArrayBufferView
& view
,
1629 GLuint viewElemOffset
, ErrorResult
&) const {
1630 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1631 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0},
1632 Some(ivec3
{width
, height
, 1}), 0, {unpackFormat
, unpackType
}, src
);
1637 template <typename T
> // TexImageSource or WebGLintptr
1638 void TexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1639 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
,
1640 GLenum unpackFormat
, GLenum unpackType
, const T
& anySrc
,
1641 ErrorResult
& out_error
) const {
1642 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1643 TexImage(3, target
, level
, internalFormat
, {0, 0, 0},
1644 Some(ivec3
{width
, height
, depth
}), border
,
1645 {unpackFormat
, unpackType
}, src
);
1648 void TexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1649 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
,
1650 GLenum unpackFormat
, GLenum unpackType
,
1651 const dom::ArrayBufferView
& view
, GLuint viewElemOffset
,
1652 ErrorResult
&) const {
1653 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1654 TexImage(3, target
, level
, internalFormat
, {0, 0, 0},
1655 Some(ivec3
{width
, height
, depth
}), border
,
1656 {unpackFormat
, unpackType
}, src
);
1661 template <typename T
> // TexImageSource or WebGLintptr
1662 void TexSubImage3D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1663 GLint zOffset
, GLsizei width
, GLsizei height
,
1664 GLsizei depth
, GLenum unpackFormat
, GLenum unpackType
,
1665 const T
& anySrc
, ErrorResult
& out_error
) const {
1666 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1667 TexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
},
1668 Some(ivec3
{width
, height
, depth
}), 0, {unpackFormat
, unpackType
},
1672 void TexSubImage3D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1673 GLint zOffset
, GLsizei width
, GLsizei height
,
1674 GLsizei depth
, GLenum unpackFormat
, GLenum unpackType
,
1675 const dom::Nullable
<dom::ArrayBufferView
>& maybeSrcView
,
1676 GLuint srcElemOffset
, ErrorResult
&) const {
1677 const TexImageSourceAdapter
src(&maybeSrcView
, srcElemOffset
);
1678 TexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
},
1679 Some(ivec3
{width
, height
, depth
}), 0, {unpackFormat
, unpackType
},
1683 ////////////////////////////////////
1686 void CompressedTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1687 GLsizei width
, GLsizei height
, GLint border
,
1688 GLsizei imageSize
, WebGLintptr offset
) const {
1689 const TexImageSourceAdapter
src(&offset
);
1690 CompressedTexImage(false, 2, target
, level
, internalFormat
, {0, 0, 0},
1691 {width
, height
, 1}, border
, src
, imageSize
);
1694 void CompressedTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1695 GLsizei width
, GLsizei height
, GLint border
,
1696 const dom::ArrayBufferView
& view
,
1697 GLuint viewElemOffset
= 0,
1698 GLuint viewElemLengthOverride
= 0) const {
1699 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1700 viewElemLengthOverride
);
1701 CompressedTexImage(false, 2, target
, level
, internalFormat
, {0, 0, 0},
1702 {width
, height
, 1}, border
, src
, 0);
1707 void CompressedTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1708 GLint yOffset
, GLsizei width
, GLsizei height
,
1709 GLenum unpackFormat
, GLsizei imageSize
,
1710 WebGLintptr offset
) const {
1711 const TexImageSourceAdapter
src(&offset
);
1712 CompressedTexImage(true, 2, target
, level
, unpackFormat
,
1713 {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0, src
,
1717 void CompressedTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1718 GLint yOffset
, GLsizei width
, GLsizei height
,
1719 GLenum unpackFormat
,
1720 const dom::ArrayBufferView
& view
,
1721 GLuint viewElemOffset
= 0,
1722 GLuint viewElemLengthOverride
= 0) const {
1723 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1724 viewElemLengthOverride
);
1725 CompressedTexImage(true, 2, target
, level
, unpackFormat
,
1726 {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0, src
, 0);
1731 void CompressedTexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1732 GLsizei width
, GLsizei height
, GLsizei depth
,
1733 GLint border
, GLsizei imageSize
,
1734 WebGLintptr offset
) const {
1735 const TexImageSourceAdapter
src(&offset
);
1736 CompressedTexImage(false, 3, target
, level
, internalFormat
, {0, 0, 0},
1737 {width
, height
, depth
}, border
, src
, imageSize
);
1740 void CompressedTexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1741 GLsizei width
, GLsizei height
, GLsizei depth
,
1742 GLint border
, const dom::ArrayBufferView
& view
,
1743 GLuint viewElemOffset
= 0,
1744 GLuint viewElemLengthOverride
= 0) const {
1745 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1746 viewElemLengthOverride
);
1747 CompressedTexImage(false, 3, target
, level
, internalFormat
, {0, 0, 0},
1748 {width
, height
, depth
}, border
, src
, 0);
1753 void CompressedTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1754 GLint yOffset
, GLint zOffset
, GLsizei width
,
1755 GLsizei height
, GLsizei depth
,
1756 GLenum unpackFormat
, GLsizei imageSize
,
1757 WebGLintptr offset
) const {
1758 const TexImageSourceAdapter
src(&offset
);
1759 CompressedTexImage(true, 3, target
, level
, unpackFormat
,
1760 {xOffset
, yOffset
, zOffset
}, {width
, height
, depth
}, 0,
1764 void CompressedTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1765 GLint yOffset
, GLint zOffset
, GLsizei width
,
1766 GLsizei height
, GLsizei depth
,
1767 GLenum unpackFormat
,
1768 const dom::ArrayBufferView
& view
,
1769 GLuint viewElemOffset
= 0,
1770 GLuint viewElemLengthOverride
= 0) const {
1771 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1772 viewElemLengthOverride
);
1773 CompressedTexImage(true, 3, target
, level
, unpackFormat
,
1774 {xOffset
, yOffset
, zOffset
}, {width
, height
, depth
}, 0,
1778 // --------------------
1780 void CopyTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1781 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1782 GLint border
) const {
1783 CopyTexImage(2, target
, level
, internalFormat
, {0, 0, 0}, {x
, y
},
1784 {width
, height
}, border
);
1787 void CopyTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1788 GLint yOffset
, GLint x
, GLint y
, GLsizei width
,
1789 GLsizei height
) const {
1790 CopyTexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {x
, y
},
1791 {width
, height
}, 0);
1794 void CopyTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1795 GLint yOffset
, GLint zOffset
, GLint x
, GLint y
,
1796 GLsizei width
, GLsizei height
) const {
1797 CopyTexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
}, {x
, y
},
1798 {width
, height
}, 0);
1801 // -------------------
1802 // legacy TexImageSource uploads without width/height.
1803 // The width/height params are webgl2 only, and let you do subrect
1804 // selection with e.g. width < UNPACK_ROW_LENGTH.
1806 template <typename TexImageSourceT
>
1807 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1808 GLenum unpackFormat
, GLenum unpackType
,
1809 const TexImageSourceT
& anySrc
, ErrorResult
& out_error
) const {
1810 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1811 TexImage(2, target
, level
, internalFormat
, {}, {}, 0,
1812 {unpackFormat
, unpackType
}, src
);
1815 template <typename TexImageSourceT
>
1816 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1817 GLenum unpackFormat
, GLenum unpackType
,
1818 const TexImageSourceT
& anySrc
,
1819 ErrorResult
& out_error
) const {
1820 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1821 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {}, 0,
1822 {unpackFormat
, unpackType
}, src
);
1825 // ------------------------ Uniforms and attributes ------------------------
1828 Maybe
<double> GetVertexAttribPriv(GLuint index
, GLenum pname
);
1831 void GetVertexAttrib(JSContext
* cx
, GLuint index
, GLenum pname
,
1832 JS::MutableHandle
<JS::Value
> retval
, ErrorResult
& rv
);
1835 const webgl::LinkResult
* GetActiveLinkResult() const {
1836 const auto& state
= State();
1837 if (state
.mCurrentProgram
) {
1838 (void)GetLinkResult(*state
.mCurrentProgram
);
1840 return state
.mActiveLinkResult
.get();
1843 void UniformData(GLenum funcElemType
, const WebGLUniformLocationJS
* const loc
,
1844 bool transpose
, const Range
<const uint8_t>& bytes
,
1845 GLuint elemOffset
= 0, GLuint elemCountOverride
= 0) const;
1849 template <typename T
>
1850 Maybe
<Range
<T
>> ValidateSubrange(const Range
<T
>& data
, size_t elemOffset
,
1851 size_t elemLengthOverride
= 0) const {
1853 if (elemOffset
> ret
.length()) {
1854 EnqueueError(LOCAL_GL_INVALID_VALUE
,
1855 "`elemOffset` too large for `data`.");
1858 ret
= {ret
.begin() + elemOffset
, ret
.end()};
1859 if (elemLengthOverride
) {
1860 if (elemLengthOverride
> ret
.length()) {
1862 LOCAL_GL_INVALID_VALUE
,
1863 "`elemLengthOverride` too large for `data` and `elemOffset`.");
1866 ret
= {ret
.begin().get(), elemLengthOverride
};
1872 #define _(T, type_t, TYPE) \
1873 void Uniform1##T(const WebGLUniformLocationJS* const loc, type_t x) const { \
1874 const type_t arr[] = {x}; \
1875 UniformData(TYPE, loc, false, MakeByteRange(arr)); \
1877 void Uniform2##T(const WebGLUniformLocationJS* const loc, type_t x, \
1879 const type_t arr[] = {x, y}; \
1880 UniformData(TYPE##_VEC2, loc, false, MakeByteRange(arr)); \
1882 void Uniform3##T(const WebGLUniformLocationJS* const loc, type_t x, \
1883 type_t y, type_t z) const { \
1884 const type_t arr[] = {x, y, z}; \
1885 UniformData(TYPE##_VEC3, loc, false, MakeByteRange(arr)); \
1887 void Uniform4##T(const WebGLUniformLocationJS* const loc, type_t x, \
1888 type_t y, type_t z, type_t w) const { \
1889 const type_t arr[] = {x, y, z, w}; \
1890 UniformData(TYPE##_VEC4, loc, false, MakeByteRange(arr)); \
1893 _(f
, float, LOCAL_GL_FLOAT
)
1894 _(i
, int32_t, LOCAL_GL_INT
)
1895 _(ui
, uint32_t, LOCAL_GL_UNSIGNED_INT
)
1901 #define _(NT, TypeListU, TYPE) \
1902 void Uniform##NT##v(const WebGLUniformLocationJS* const loc, \
1903 const TypeListU& list, GLuint elemOffset = 0, \
1904 GLuint elemCountOverride = 0) const { \
1905 UniformData(TYPE, loc, false, MakeByteRange(list), elemOffset, \
1906 elemCountOverride); \
1909 _(1f
, Float32ListU
, LOCAL_GL_FLOAT
)
1910 _(2f
, Float32ListU
, LOCAL_GL_FLOAT_VEC2
)
1911 _(3f
, Float32ListU
, LOCAL_GL_FLOAT_VEC3
)
1912 _(4f
, Float32ListU
, LOCAL_GL_FLOAT_VEC4
)
1913 _(1i
, Int32ListU
, LOCAL_GL_INT
)
1914 _(2i
, Int32ListU
, LOCAL_GL_INT_VEC2
)
1915 _(3i
, Int32ListU
, LOCAL_GL_INT_VEC3
)
1916 _(4i
, Int32ListU
, LOCAL_GL_INT_VEC4
)
1917 _(1ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT
)
1918 _(2ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC2
)
1919 _(3ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC3
)
1920 _(4ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC4
)
1927 void UniformMatrix##X##fv(const WebGLUniformLocationJS* loc, bool transpose, \
1928 const Float32ListU& list, GLuint elemOffset = 0, \
1929 GLuint elemCountOverride = 0) const { \
1930 UniformData(LOCAL_GL_FLOAT_MAT##X, loc, transpose, MakeByteRange(list), \
1931 elemOffset, elemCountOverride); \
1950 void EnableVertexAttribArray(GLuint index
);
1952 void DisableVertexAttribArray(GLuint index
);
1954 WebGLsizeiptr
GetVertexAttribOffset(GLuint index
, GLenum pname
);
1959 void VertexAttrib4Tv(GLuint index
, webgl::AttribBaseType
,
1960 const Range
<const uint8_t>&);
1963 void VertexAttrib1f(GLuint index
, GLfloat x
) {
1964 VertexAttrib4f(index
, x
, 0, 0, 1);
1966 void VertexAttrib2f(GLuint index
, GLfloat x
, GLfloat y
) {
1967 VertexAttrib4f(index
, x
, y
, 0, 1);
1969 void VertexAttrib3f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
) {
1970 VertexAttrib4f(index
, x
, y
, z
, 1);
1973 void VertexAttrib4f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
,
1975 const float arr
[4] = {x
, y
, z
, w
};
1976 VertexAttrib4Tv(index
, webgl::AttribBaseType::Float
, MakeByteRange(arr
));
1981 void VertexAttrib1fv(const GLuint index
, const Float32ListU
& list
) {
1982 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1983 if (IsContextLost()) return;
1985 const auto range
= MakeRange(list
);
1986 if (range
.length() < 1) {
1987 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=1.");
1991 VertexAttrib1f(index
, range
[0]);
1994 void VertexAttrib2fv(const GLuint index
, const Float32ListU
& list
) {
1995 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1996 if (IsContextLost()) return;
1998 const auto range
= MakeRange(list
);
1999 if (range
.length() < 2) {
2000 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=2.");
2004 VertexAttrib2f(index
, range
[0], range
[1]);
2007 void VertexAttrib3fv(const GLuint index
, const Float32ListU
& list
) {
2008 const FuncScope
funcScope(*this, "vertexAttrib1fv");
2009 if (IsContextLost()) return;
2011 const auto range
= MakeRange(list
);
2012 if (range
.length() < 3) {
2013 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=3.");
2017 VertexAttrib3f(index
, range
[0], range
[1], range
[2]);
2020 void VertexAttrib4fv(GLuint index
, const Float32ListU
& list
) {
2021 VertexAttrib4Tv(index
, webgl::AttribBaseType::Float
, MakeByteRange(list
));
2023 void VertexAttribI4iv(GLuint index
, const Int32ListU
& list
) {
2024 VertexAttrib4Tv(index
, webgl::AttribBaseType::Int
, MakeByteRange(list
));
2026 void VertexAttribI4uiv(GLuint index
, const Uint32ListU
& list
) {
2027 VertexAttrib4Tv(index
, webgl::AttribBaseType::Uint
, MakeByteRange(list
));
2030 void VertexAttribI4i(GLuint index
, GLint x
, GLint y
, GLint z
, GLint w
) {
2031 const int32_t arr
[4] = {x
, y
, z
, w
};
2032 VertexAttrib4Tv(index
, webgl::AttribBaseType::Int
, MakeByteRange(arr
));
2034 void VertexAttribI4ui(GLuint index
, GLuint x
, GLuint y
, GLuint z
, GLuint w
) {
2035 const uint32_t arr
[4] = {x
, y
, z
, w
};
2036 VertexAttrib4Tv(index
, webgl::AttribBaseType::Uint
, MakeByteRange(arr
));
2040 void VertexAttribPointerImpl(bool isFuncInt
, GLuint index
, GLint size
,
2041 GLenum type
, WebGLboolean normalized
,
2042 GLsizei iStride
, WebGLintptr iByteOffset
);
2045 void VertexAttribIPointer(GLuint index
, GLint size
, GLenum type
,
2046 GLsizei stride
, WebGLintptr byteOffset
) {
2047 VertexAttribPointerImpl(true, index
, size
, type
, false, stride
, byteOffset
);
2050 void VertexAttribPointer(GLuint index
, GLint size
, GLenum type
,
2051 WebGLboolean normalized
, GLsizei stride
,
2052 WebGLintptr byteOffset
) {
2053 VertexAttribPointerImpl(false, index
, size
, type
, normalized
, stride
,
2057 // -------------------------------- Drawing -------------------------------
2059 void DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
2060 DrawArraysInstanced(mode
, first
, count
, 1);
2063 void DrawElements(GLenum mode
, GLsizei count
, GLenum type
,
2064 WebGLintptr byteOffset
) {
2065 DrawElementsInstanced(mode
, count
, type
, byteOffset
, 1);
2068 void DrawRangeElements(GLenum mode
, GLuint start
, GLuint end
, GLsizei count
,
2069 GLenum type
, WebGLintptr byteOffset
) {
2070 const FuncScope
funcScope(*this, "drawRangeElements");
2072 EnqueueError(LOCAL_GL_INVALID_VALUE
, "end must be >= start.");
2075 DrawElementsInstanced(mode
, count
, type
, byteOffset
, 1);
2078 // ------------------------------ Readback -------------------------------
2080 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2081 GLenum format
, GLenum type
,
2082 const dom::Nullable
<dom::ArrayBufferView
>& maybeView
,
2083 dom::CallerType aCallerType
, ErrorResult
& out_error
) const {
2084 const FuncScope
funcScope(*this, "readPixels");
2085 if (!ValidateNonNull("pixels", maybeView
)) return;
2086 ReadPixels(x
, y
, width
, height
, format
, type
, maybeView
.Value(), 0,
2087 aCallerType
, out_error
);
2090 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2091 GLenum format
, GLenum type
, WebGLsizeiptr offset
,
2092 dom::CallerType aCallerType
, ErrorResult
& out_error
) const;
2094 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2095 GLenum format
, GLenum type
,
2096 const dom::ArrayBufferView
& dstData
, GLuint dstElemOffset
,
2097 dom::CallerType aCallerType
, ErrorResult
& out_error
) const;
2100 bool ReadPixels_SharedPrecheck(dom::CallerType aCallerType
,
2101 ErrorResult
& out_error
) const;
2103 // ------------------------------ Vertex Array ------------------------------
2105 void BindVertexArray(WebGLVertexArrayJS
*);
2107 void DrawArraysInstanced(GLenum mode
, GLint first
, GLsizei count
,
2110 void DrawElementsInstanced(GLenum mode
, GLsizei count
, GLenum type
,
2111 WebGLintptr offset
, GLsizei primcount
);
2113 void VertexAttribDivisor(GLuint index
, GLuint divisor
);
2115 // --------------------------------- GL Query
2116 // ---------------------------------
2118 void GetQuery(JSContext
*, GLenum target
, GLenum pname
,
2119 JS::MutableHandle
<JS::Value
> retval
) const;
2120 void GetQueryParameter(JSContext
*, WebGLQueryJS
&, GLenum pname
,
2121 JS::MutableHandle
<JS::Value
> retval
) const;
2122 void BeginQuery(GLenum target
, WebGLQueryJS
&);
2123 void EndQuery(GLenum target
);
2124 void QueryCounter(WebGLQueryJS
&, GLenum target
) const;
2126 // -------------------------------- Sampler -------------------------------
2128 void GetSamplerParameter(JSContext
*, const WebGLSamplerJS
&, GLenum pname
,
2129 JS::MutableHandle
<JS::Value
> retval
) const;
2131 void BindSampler(GLuint unit
, WebGLSamplerJS
*);
2132 void SamplerParameteri(WebGLSamplerJS
&, GLenum pname
, GLint param
) const;
2133 void SamplerParameterf(WebGLSamplerJS
&, GLenum pname
, GLfloat param
) const;
2135 // ------------------------------- GL Sync ---------------------------------
2137 GLenum
ClientWaitSync(WebGLSyncJS
&, GLbitfield flags
, GLuint64 timeout
) const;
2138 void GetSyncParameter(JSContext
*, WebGLSyncJS
&, GLenum pname
,
2139 JS::MutableHandle
<JS::Value
> retval
) const;
2140 void WaitSync(const WebGLSyncJS
&, GLbitfield flags
, GLint64 timeout
) const;
2142 // -------------------------- Transform Feedback ---------------------------
2144 void BindTransformFeedback(GLenum target
, WebGLTransformFeedbackJS
*);
2145 void BeginTransformFeedback(GLenum primitiveMode
);
2146 void EndTransformFeedback();
2147 void PauseTransformFeedback();
2148 void ResumeTransformFeedback();
2150 // -------------------------- Opaque Framebuffers ---------------------------
2152 void SetFramebufferIsInOpaqueRAF(WebGLFramebufferJS
*, bool);
2154 // ------------------------------ Extensions ------------------------------
2156 void GetSupportedExtensions(dom::Nullable
<nsTArray
<nsString
>>& retval
,
2157 dom::CallerType callerType
) const;
2159 bool IsSupported(WebGLExtensionID
, dom::CallerType callerType
=
2160 dom::CallerType::NonSystem
) const;
2162 void GetExtension(JSContext
* cx
, const nsAString
& name
,
2163 JS::MutableHandle
<JSObject
*> retval
,
2164 dom::CallerType callerType
, ErrorResult
& rv
);
2167 bool IsExtensionForbiddenForCaller(const WebGLExtensionID ext
,
2168 const dom::CallerType callerType
) const;
2170 RefPtr
<ClientWebGLExtensionBase
> GetExtension(WebGLExtensionID ext
,
2171 dom::CallerType callerType
);
2172 void RequestExtension(WebGLExtensionID
) const;
2175 bool IsExtensionEnabled(const WebGLExtensionID id
) const {
2176 return bool(mNotLost
->extensions
[UnderlyingValue(id
)]);
2179 void AddCompressedFormat(GLenum
);
2181 // ---------------------------- Misc Extensions ----------------------------
2183 void DrawBuffers(const dom::Sequence
<GLenum
>& buffers
);
2185 void GetSupportedProfilesASTC(
2186 dom::Nullable
<nsTArray
<nsString
>>& retval
) const;
2188 void MOZDebugGetParameter(JSContext
* cx
, GLenum pname
,
2189 JS::MutableHandle
<JS::Value
> retval
,
2191 GetParameter(cx
, pname
, retval
, rv
, true);
2194 void ProvokingVertex(GLenum rawMode
) const;
2196 // -------------------------------------------------------------------------
2197 // Client-side methods. Calls in the Host are forwarded to the client.
2198 // -------------------------------------------------------------------------
2200 void JsWarning(const std::string
&) const;
2202 // -------------------------------------------------------------------------
2203 // The cross-process communication mechanism
2204 // -------------------------------------------------------------------------
2206 template <typename ReturnType
>
2207 friend struct WebGLClientDispatcher
;
2209 template <typename MethodType
, MethodType method
, typename ReturnType
,
2211 friend ReturnType
RunOn(const ClientWebGLContext
& context
, Args
&&... aArgs
);
2213 // If we are running WebGL in this process then call the HostWebGLContext
2214 // method directly. Otherwise, dispatch over IPC.
2215 template <typename MethodType
, MethodType method
, typename
... Args
>
2216 void Run(Args
&&... aArgs
) const;
2218 // -------------------------------------------------------------------------
2219 // Helpers for DOM operations, composition, actors, etc
2220 // -------------------------------------------------------------------------
2223 // https://immersive-web.github.io/webxr/#xr-compatible
2224 bool IsXRCompatible() const;
2225 already_AddRefed
<dom::Promise
> MakeXRCompatible(ErrorResult
& aRv
);
2228 uint32_t GetPrincipalHashValue() const;
2230 // Prepare the context for capture before compositing
2231 void BeginComposition();
2233 // Clean up the context after captured for compositing
2234 void EndComposition();
2236 mozilla::dom::Document
* GetOwnerDoc() const;
2238 mutable bool mResetLayer
= true;
2239 Maybe
<const WebGLContextOptions
> mInitialOptions
;
2240 bool mXRCompatible
= false;
2243 // used by DOM bindings in conjunction with GetParentObject
2244 inline nsISupports
* ToSupports(ClientWebGLContext
* webgl
) {
2245 return static_cast<nsICanvasRenderingContextInternal
*>(webgl
);
2248 const char* GetExtensionName(WebGLExtensionID
);
2252 inline bool webgl::ObjectJS::IsForContext(
2253 const ClientWebGLContext
& context
) const {
2254 const auto& notLost
= context
.mNotLost
;
2255 if (!notLost
) return false;
2256 if (notLost
.get() != mGeneration
.lock().get()) return false;
2260 void AutoJsWarning(const std::string
& utf8
);
2262 } // namespace mozilla
2264 #endif // CLIENTWEBGLCONTEXT_H_