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
;
41 class DrawTargetWebgl
;
45 class AvailabilityRunnable
;
50 ////////////////////////////////////
52 class WebGLActiveInfoJS final
: public RefCounted
<WebGLActiveInfoJS
> {
54 MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLActiveInfoJS
)
56 const webgl::ActiveInfo mInfo
;
58 explicit WebGLActiveInfoJS(const webgl::ActiveInfo
& info
) : mInfo(info
) {}
60 virtual ~WebGLActiveInfoJS() = default;
65 GLint
Size() const { return static_cast<GLint
>(mInfo
.elemCount
); }
66 GLenum
Type() const { return mInfo
.elemType
; }
68 void GetName(nsString
& retval
) const { CopyUTF8toUTF16(mInfo
.name
, retval
); }
70 bool WrapObject(JSContext
*, JS::Handle
<JSObject
*>,
71 JS::MutableHandle
<JSObject
*>);
74 class WebGLShaderPrecisionFormatJS final
75 : public RefCounted
<WebGLShaderPrecisionFormatJS
> {
77 MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLShaderPrecisionFormatJS
)
79 const webgl::ShaderPrecisionFormat mInfo
;
81 explicit WebGLShaderPrecisionFormatJS(
82 const webgl::ShaderPrecisionFormat
& info
)
85 virtual ~WebGLShaderPrecisionFormatJS() = default;
87 GLint
RangeMin() const { return mInfo
.rangeMin
; }
88 GLint
RangeMax() const { return mInfo
.rangeMax
; }
89 GLint
Precision() const { return mInfo
.precision
; }
91 bool WrapObject(JSContext
*, JS::Handle
<JSObject
*>,
92 JS::MutableHandle
<JSObject
*>);
95 // -----------------------
97 class ClientWebGLContext
;
99 class WebGLFramebufferJS
;
100 class WebGLProgramJS
;
102 class WebGLRenderbufferJS
;
103 class WebGLSamplerJS
;
105 class WebGLTextureJS
;
106 class WebGLTransformFeedbackJS
;
107 class WebGLVertexArrayJS
;
113 class ProgramKeepAlive final
{
114 friend class mozilla::WebGLProgramJS
;
116 WebGLProgramJS
* mParent
;
119 explicit ProgramKeepAlive(WebGLProgramJS
& parent
) : mParent(&parent
) {}
123 class ShaderKeepAlive final
{
124 friend class mozilla::WebGLShaderJS
;
126 const WebGLShaderJS
* mParent
;
129 explicit ShaderKeepAlive(const WebGLShaderJS
& parent
) : mParent(&parent
) {}
133 class ContextGenerationInfo final
{
135 ObjectId mLastId
= 0;
138 webgl::ExtensionBits mEnabledExtensions
;
139 RefPtr
<WebGLProgramJS
> mCurrentProgram
;
140 std::shared_ptr
<webgl::ProgramKeepAlive
> mProgramKeepAlive
;
141 mutable std::shared_ptr
<webgl::LinkResult
> mActiveLinkResult
;
143 RefPtr
<WebGLTransformFeedbackJS
> mDefaultTfo
;
144 RefPtr
<WebGLVertexArrayJS
> mDefaultVao
;
146 std::unordered_map
<GLenum
, RefPtr
<WebGLBufferJS
>> mBoundBufferByTarget
;
147 std::vector
<RefPtr
<WebGLBufferJS
>> mBoundUbos
;
148 RefPtr
<WebGLFramebufferJS
> mBoundDrawFb
;
149 RefPtr
<WebGLFramebufferJS
> mBoundReadFb
;
150 RefPtr
<WebGLRenderbufferJS
> mBoundRb
;
151 RefPtr
<WebGLTransformFeedbackJS
> mBoundTfo
;
152 RefPtr
<WebGLVertexArrayJS
> mBoundVao
;
153 std::unordered_map
<GLenum
, RefPtr
<WebGLQueryJS
>> mCurrentQueryByTarget
;
155 struct TexUnit final
{
156 RefPtr
<WebGLSamplerJS
> sampler
;
157 std::unordered_map
<GLenum
, RefPtr
<WebGLTextureJS
>> texByTarget
;
159 uint32_t mActiveTexUnit
= 0;
160 std::vector
<TexUnit
> mTexUnits
;
162 bool mTfActiveAndNotPaused
= false;
164 std::vector
<TypedQuad
> mGenericVertexAttribs
;
166 std::array
<int32_t, 4> mScissor
= {};
167 std::array
<int32_t, 4> mViewport
= {};
168 std::array
<float, 4> mClearColor
= {{0, 0, 0, 0}};
169 std::array
<float, 4> mBlendColor
= {{0, 0, 0, 0}};
170 std::array
<float, 2> mDepthRange
= {{0, 1}};
171 webgl::PixelPackingState mPixelPackState
;
172 webgl::PixelUnpackStateWebgl mPixelUnpackState
;
174 std::vector
<GLenum
> mCompressedTextureFormats
;
176 Maybe
<uvec2
> mDrawingBufferSize
;
178 ObjectId
NextId() { return mLastId
+= 1; }
183 // In the cross process case, the WebGL actor's ownership relationship looks
185 // ---------------------------------------------------------------------
186 // | ClientWebGLContext -> WebGLChild -> WebGLParent -> HostWebGLContext
187 // ---------------------------------------------------------------------
189 // where 'A -> B' means "A owns B"
191 struct NotLostData final
{
192 ClientWebGLContext
& context
;
193 webgl::InitContextResult info
;
195 RefPtr
<mozilla::dom::WebGLChild
> outOfProcess
;
196 UniquePtr
<HostWebGLContext
> inProcess
;
198 webgl::ContextGenerationInfo state
;
199 std::array
<RefPtr
<ClientWebGLExtensionBase
>,
200 UnderlyingValue(WebGLExtensionID::Max
)>
203 RefPtr
<layers::CanvasRenderer
> mCanvasRenderer
;
205 explicit NotLostData(ClientWebGLContext
& context
);
212 friend ClientWebGLContext
;
215 const std::weak_ptr
<NotLostData
> mGeneration
;
219 bool mDeleteRequested
= false;
221 explicit ObjectJS(const ClientWebGLContext
&);
222 virtual ~ObjectJS() = default;
225 ClientWebGLContext
* Context() const {
226 const auto locked
= mGeneration
.lock();
227 if (!locked
) return nullptr;
228 return &(locked
->context
);
231 ClientWebGLContext
* GetParentObject() const { return Context(); }
234 bool IsForContext(const ClientWebGLContext
&) const;
235 virtual bool IsDeleted() const { return mDeleteRequested
; }
237 bool IsUsable(const ClientWebGLContext
& context
) const {
238 return IsForContext(context
) && !IsDeleted();
242 bool ValidateUsable(const ClientWebGLContext
& context
,
243 const char* const argName
) const {
244 if (MOZ_LIKELY(IsUsable(context
))) return true;
245 WarnInvalidUse(context
, argName
);
250 bool ValidateForContext(const ClientWebGLContext
& context
,
251 const char* const argName
) const;
254 void WarnInvalidUse(const ClientWebGLContext
&, const char* argName
) const;
256 // The enum is INVALID_VALUE for Program/Shader :(
257 virtual GLenum
ErrorOnDeleted() const { return LOCAL_GL_INVALID_OPERATION
; }
262 // -------------------------
264 class WebGLBufferJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
265 friend class ClientWebGLContext
;
267 webgl::BufferKind mKind
=
268 webgl::BufferKind::Undefined
; // !IsBuffer until Bind
271 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLBufferJS
)
272 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLBufferJS
)
274 explicit WebGLBufferJS(const ClientWebGLContext
& webgl
)
275 : webgl::ObjectJS(webgl
) {}
278 ~WebGLBufferJS() = default;
281 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
286 class WebGLFramebufferJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
287 friend class ClientWebGLContext
;
290 struct Attachment final
{
291 RefPtr
<WebGLRenderbufferJS
> rb
;
292 RefPtr
<WebGLTextureJS
> tex
;
296 bool mHasBeenBound
= false; // !IsFramebuffer until Bind
297 std::unordered_map
<GLenum
, Attachment
> mAttachments
;
298 // Holds Some Id if async present is used
299 Maybe
<layers::RemoteTextureId
> mLastRemoteTextureId
;
300 Maybe
<layers::RemoteTextureOwnerId
> mRemoteTextureOwnerId
;
301 // Needs sync IPC to ensure that the remote texture exists in the
303 bool mNeedsRemoteTextureSync
= true;
306 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebufferJS
)
307 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLFramebufferJS
)
309 explicit WebGLFramebufferJS(const ClientWebGLContext
&, bool opaque
= false);
312 bool mInOpaqueRAF
= false;
315 ~WebGLFramebufferJS() = default;
317 void EnsureColorAttachments();
320 Attachment
* GetAttachment(const GLenum slotEnum
) {
321 auto ret
= MaybeFind(mAttachments
, slotEnum
);
323 EnsureColorAttachments();
324 ret
= MaybeFind(mAttachments
, slotEnum
);
329 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
334 class WebGLProgramJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
335 friend class ClientWebGLContext
;
338 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLProgramJS
)
339 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLProgramJS
)
341 // If the REFCOUNTING macro isn't declared first, the AddRef at
342 // mInnerRef->js will panic when REFCOUNTING's "owning thread" var is still
345 struct Attachment final
{
346 RefPtr
<WebGLShaderJS
> shader
;
347 std::shared_ptr
<webgl::ShaderKeepAlive
> keepAlive
;
351 std::shared_ptr
<webgl::ProgramKeepAlive
> mKeepAlive
;
352 const std::weak_ptr
<webgl::ProgramKeepAlive
> mKeepAliveWeak
;
354 std::unordered_map
<GLenum
, Attachment
> mNextLink_Shaders
;
355 bool mLastValidate
= false;
356 mutable std::shared_ptr
<webgl::LinkResult
>
357 mResult
; // Never null, often defaulted.
359 struct UniformLocInfo final
{
360 const uint32_t location
;
361 const GLenum elemType
;
364 mutable Maybe
<std::unordered_map
<std::string
, UniformLocInfo
>>
366 mutable std::vector
<uint32_t> mUniformBlockBindings
;
368 std::unordered_set
<const WebGLTransformFeedbackJS
*> mActiveTfos
;
370 explicit WebGLProgramJS(const ClientWebGLContext
&);
373 mKeepAlive
= nullptr; // Try to delete.
375 const auto& maybe
= mKeepAliveWeak
.lock();
377 maybe
->mParent
= nullptr;
382 bool IsDeleted() const override
{ return !mKeepAliveWeak
.lock(); }
383 GLenum
ErrorOnDeleted() const override
{ return LOCAL_GL_INVALID_VALUE
; }
385 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
390 class WebGLQueryJS final
: public nsWrapperCache
,
391 public webgl::ObjectJS
,
392 public SupportsWeakPtr
{
393 friend class ClientWebGLContext
;
394 friend class webgl::AvailabilityRunnable
;
396 GLenum mTarget
= 0; // !IsQuery until Bind
397 bool mCanBeAvailable
= false;
400 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLQueryJS
)
401 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLQueryJS
)
403 explicit WebGLQueryJS(const ClientWebGLContext
& webgl
)
404 : webgl::ObjectJS(webgl
) {}
407 ~WebGLQueryJS() = default;
410 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
415 class WebGLRenderbufferJS final
: public nsWrapperCache
,
416 public webgl::ObjectJS
{
417 friend class ClientWebGLContext
;
420 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLRenderbufferJS
)
421 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLRenderbufferJS
)
424 bool mHasBeenBound
= false; // !IsRenderbuffer until Bind
426 explicit WebGLRenderbufferJS(const ClientWebGLContext
& webgl
)
427 : webgl::ObjectJS(webgl
) {}
428 ~WebGLRenderbufferJS() = default;
431 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
436 class WebGLSamplerJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
437 // IsSampler without Bind
439 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSamplerJS
)
440 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLSamplerJS
)
442 explicit WebGLSamplerJS(const ClientWebGLContext
& webgl
)
443 : webgl::ObjectJS(webgl
) {}
446 ~WebGLSamplerJS() = default;
449 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
454 class WebGLShaderJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
455 friend class ClientWebGLContext
;
458 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLShaderJS
)
459 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLShaderJS
)
464 std::shared_ptr
<webgl::ShaderKeepAlive
> mKeepAlive
;
465 const std::weak_ptr
<webgl::ShaderKeepAlive
> mKeepAliveWeak
;
467 mutable webgl::CompileResult mResult
;
469 WebGLShaderJS(const ClientWebGLContext
&, GLenum type
);
472 mKeepAlive
= nullptr; // Try to delete.
474 const auto& maybe
= mKeepAliveWeak
.lock();
476 maybe
->mParent
= nullptr;
481 bool IsDeleted() const override
{ return !mKeepAliveWeak
.lock(); }
482 GLenum
ErrorOnDeleted() const override
{ return LOCAL_GL_INVALID_VALUE
; }
484 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
489 class WebGLSyncJS final
: public nsWrapperCache
,
490 public webgl::ObjectJS
,
491 public SupportsWeakPtr
{
492 friend class ClientWebGLContext
;
493 friend class webgl::AvailabilityRunnable
;
495 bool mCanBeAvailable
= false;
496 bool mHasWarnedNotAvailable
= false;
497 bool mSignaled
= false;
500 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSyncJS
)
501 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLSyncJS
)
503 explicit WebGLSyncJS(const ClientWebGLContext
& webgl
)
504 : webgl::ObjectJS(webgl
) {}
507 ~WebGLSyncJS() = default;
510 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
515 class WebGLTextureJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
516 friend class ClientWebGLContext
;
518 GLenum mTarget
= 0; // !IsTexture until Bind
521 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTextureJS
)
522 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLTextureJS
)
524 explicit WebGLTextureJS(const ClientWebGLContext
& webgl
)
525 : webgl::ObjectJS(webgl
) {}
528 ~WebGLTextureJS() = default;
531 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
536 class WebGLTransformFeedbackJS final
: public nsWrapperCache
,
537 public webgl::ObjectJS
{
538 friend class ClientWebGLContext
;
540 bool mHasBeenBound
= false; // !IsTransformFeedback until Bind
541 bool mActiveOrPaused
= false;
542 std::vector
<RefPtr
<WebGLBufferJS
>> mAttribBuffers
;
543 RefPtr
<WebGLProgramJS
> mActiveProgram
;
544 std::shared_ptr
<webgl::ProgramKeepAlive
> mActiveProgramKeepAlive
;
547 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTransformFeedbackJS
)
548 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLTransformFeedbackJS
)
550 explicit WebGLTransformFeedbackJS(const ClientWebGLContext
&);
553 ~WebGLTransformFeedbackJS() = default;
556 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
561 std::array
<uint16_t, 3> ValidUploadElemTypes(GLenum
);
563 class WebGLUniformLocationJS final
: public nsWrapperCache
,
564 public webgl::ObjectJS
{
565 friend class ClientWebGLContext
;
567 const std::weak_ptr
<webgl::LinkResult
> mParent
;
568 const uint32_t mLocation
;
569 const std::array
<uint16_t, 3> mValidUploadElemTypes
;
572 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLUniformLocationJS
)
573 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLUniformLocationJS
)
575 WebGLUniformLocationJS(const ClientWebGLContext
& webgl
,
576 std::weak_ptr
<webgl::LinkResult
> parent
, uint32_t loc
,
578 : webgl::ObjectJS(webgl
),
581 mValidUploadElemTypes(ValidUploadElemTypes(elemType
)) {}
584 ~WebGLUniformLocationJS() = default;
587 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
592 class WebGLVertexArrayJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
593 friend class ClientWebGLContext
;
595 bool mHasBeenBound
= false; // !IsVertexArray until Bind
596 RefPtr
<WebGLBufferJS
> mIndexBuffer
;
597 std::vector
<RefPtr
<WebGLBufferJS
>> mAttribBuffers
;
600 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLVertexArrayJS
)
601 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebGLVertexArrayJS
)
603 explicit WebGLVertexArrayJS(const ClientWebGLContext
&);
606 ~WebGLVertexArrayJS() = default;
609 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
612 ////////////////////////////////////
614 using Float32ListU
= dom::MaybeSharedFloat32ArrayOrUnrestrictedFloatSequence
;
615 using Int32ListU
= dom::MaybeSharedInt32ArrayOrLongSequence
;
616 using Uint32ListU
= dom::MaybeSharedUint32ArrayOrUnsignedLongSequence
;
618 inline Range
<const float> MakeRange(const Float32ListU
& list
) {
619 if (list
.IsFloat32Array()) return MakeRangeAbv(list
.GetAsFloat32Array());
621 return MakeRange(list
.GetAsUnrestrictedFloatSequence());
624 inline Range
<const int32_t> MakeRange(const Int32ListU
& list
) {
625 if (list
.IsInt32Array()) return MakeRangeAbv(list
.GetAsInt32Array());
627 return MakeRange(list
.GetAsLongSequence());
630 inline Range
<const uint32_t> MakeRange(const Uint32ListU
& list
) {
631 if (list
.IsUint32Array()) return MakeRangeAbv(list
.GetAsUint32Array());
633 return MakeRange(list
.GetAsUnsignedLongSequence());
636 template <typename T
>
637 inline Range
<const uint8_t> MakeByteRange(const T
& x
) {
638 const auto typed
= MakeRange(x
);
639 return Range
<const uint8_t>(
640 reinterpret_cast<const uint8_t*>(typed
.begin().get()),
641 typed
.length() * sizeof(typed
[0]));
646 struct TexImageSourceAdapter final
: public TexImageSource
{
647 TexImageSourceAdapter(const dom::Nullable
<dom::ArrayBufferView
>* maybeView
,
649 if (!maybeView
->IsNull()) {
650 mView
= &(maybeView
->Value());
654 TexImageSourceAdapter(const dom::Nullable
<dom::ArrayBufferView
>* maybeView
,
655 GLuint viewElemOffset
) {
656 if (!maybeView
->IsNull()) {
657 mView
= &(maybeView
->Value());
659 mViewElemOffset
= viewElemOffset
;
662 TexImageSourceAdapter(const dom::ArrayBufferView
* view
, ErrorResult
*) {
666 TexImageSourceAdapter(const dom::ArrayBufferView
* view
, GLuint viewElemOffset
,
667 GLuint viewElemLengthOverride
= 0) {
669 mViewElemOffset
= viewElemOffset
;
670 mViewElemLengthOverride
= viewElemLengthOverride
;
673 explicit TexImageSourceAdapter(const WebGLintptr
* pboOffset
,
674 GLuint ignored1
= 0, GLuint ignored2
= 0) {
675 mPboOffset
= pboOffset
;
678 TexImageSourceAdapter(const WebGLintptr
* pboOffset
, ErrorResult
* ignored
) {
679 mPboOffset
= pboOffset
;
682 TexImageSourceAdapter(const dom::ImageBitmap
* imageBitmap
,
683 ErrorResult
* out_error
) {
684 mImageBitmap
= imageBitmap
;
685 mOut_error
= out_error
;
688 TexImageSourceAdapter(const dom::ImageData
* imageData
, ErrorResult
*) {
689 mImageData
= imageData
;
692 TexImageSourceAdapter(const dom::OffscreenCanvas
* offscreenCanvas
,
693 ErrorResult
* const out_error
) {
694 mOffscreenCanvas
= offscreenCanvas
;
695 mOut_error
= out_error
;
698 TexImageSourceAdapter(const dom::Element
* domElem
,
699 ErrorResult
* const out_error
) {
701 mOut_error
= out_error
;
706 * Base class for all IDL implementations of WebGLContext
708 class ClientWebGLContext final
: public nsICanvasRenderingContextInternal
,
709 public nsWrapperCache
{
710 friend class webgl::AvailabilityRunnable
;
711 friend class webgl::ObjectJS
;
712 friend class webgl::ProgramKeepAlive
;
713 friend class webgl::ShaderKeepAlive
;
714 friend class gfx::DrawTargetWebgl
;
716 // ----------------------------- Lifetime and DOM ---------------------------
718 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
719 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ClientWebGLContext
)
721 JSObject
* WrapObject(JSContext
* cx
,
722 JS::Handle
<JSObject
*> givenProto
) override
{
724 return dom::WebGL2RenderingContext_Binding::Wrap(cx
, this, givenProto
);
726 return dom::WebGLRenderingContext_Binding::Wrap(cx
, this, givenProto
);
732 const bool mIsWebGL2
;
735 bool mIsCanvasDirty
= false;
736 uvec2 mRequestedSize
= {};
739 explicit ClientWebGLContext(bool webgl2
);
742 virtual ~ClientWebGLContext();
744 const RefPtr
<ClientWebGLExtensionLoseContext
> mExtLoseContext
;
746 mutable std::shared_ptr
<webgl::NotLostData
> mNotLost
;
747 mutable GLenum mNextError
= 0;
748 mutable webgl::LossStatus mLossStatus
= webgl::LossStatus::Ready
;
749 mutable bool mAwaitingRestore
= false;
750 // Holds Some Id if async present is used
751 mutable Maybe
<layers::RemoteTextureId
> mLastRemoteTextureId
;
752 mutable Maybe
<layers::RemoteTextureOwnerId
> mRemoteTextureOwnerId
;
753 // Needs sync IPC to ensure that the remote texture exists in the
755 bool mNeedsRemoteTextureSync
= true;
760 const auto& Limits() const { return mNotLost
->info
.limits
; }
761 const auto& Vendor() const { return mNotLost
->info
.vendor
; }
762 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#actual-context-parameters
763 const WebGLContextOptions
& ActualContextParameters() const {
764 MOZ_ASSERT(mNotLost
!= nullptr);
765 return mNotLost
->info
.options
;
768 auto& State() { return mNotLost
->state
; }
769 const auto& State() const {
770 return const_cast<ClientWebGLContext
*>(this)->State();
776 mutable RefPtr
<webgl::AvailabilityRunnable
> mAvailabilityRunnable
;
779 webgl::AvailabilityRunnable
& EnsureAvailabilityRunnable() const;
784 void EmulateLoseContext() const;
785 void OnContextLoss(webgl::ContextLossReason
) const;
786 void RestoreContext(webgl::LossStatus requiredStatus
) const;
789 bool DispatchEvent(const nsAString
&) const;
790 void Event_webglcontextlost() const;
791 void Event_webglcontextrestored() const;
793 bool CreateHostContext(const uvec2
& requestedSize
);
794 void ThrowEvent_WebGLContextCreationError(const std::string
&) const;
796 void UpdateCanvasParameters();
799 void MarkCanvasDirty();
801 void MarkContextClean() override
{}
803 void OnBeforePaintTransaction() override
;
805 mozilla::dom::WebGLChild
* GetChild() const {
806 if (!mNotLost
) return nullptr;
807 if (!mNotLost
->outOfProcess
) return nullptr;
808 return mNotLost
->outOfProcess
.get();
811 // -------------------------------------------------------------------------
812 // Client WebGL API call tracking and error message reporting
813 // -------------------------------------------------------------------------
815 // Remembers the WebGL function that is lowest on the stack for client-side
817 class FuncScope final
{
819 const ClientWebGLContext
& mWebGL
;
820 const std::shared_ptr
<webgl::NotLostData
> mKeepNotLostOrNull
;
821 const char* const mFuncName
;
823 FuncScope(const ClientWebGLContext
& webgl
, const char* funcName
)
825 mKeepNotLostOrNull(webgl
.mNotLost
),
826 mFuncName(funcName
) {
827 // Only set if an "outer" scope hasn't already been set.
828 if (!mWebGL
.mFuncScope
) {
829 mWebGL
.mFuncScope
= this;
834 if (this == mWebGL
.mFuncScope
) {
835 mWebGL
.mFuncScope
= nullptr;
839 FuncScope(const FuncScope
&) = delete;
840 FuncScope(FuncScope
&&) = delete;
844 // The scope of the function at the top of the current WebGL function call
846 mutable FuncScope
* mFuncScope
= nullptr;
848 const char* FuncName() const {
849 return mFuncScope
? mFuncScope
->mFuncName
: nullptr;
853 template <typename
... Args
>
854 void EnqueueError(const GLenum error
, const char* const format
,
855 const Args
&... args
) const {
856 MOZ_ASSERT(FuncName());
858 text
.AppendPrintf("WebGL warning: %s: ", FuncName());
861 # pragma clang diagnostic push
862 # pragma clang diagnostic ignored "-Wformat-security"
863 #elif defined(__GNUC__)
864 # pragma GCC diagnostic push
865 # pragma GCC diagnostic ignored "-Wformat-security"
867 text
.AppendPrintf(format
, args
...);
869 # pragma clang diagnostic pop
870 #elif defined(__GNUC__)
871 # pragma GCC diagnostic pop
874 EnqueueErrorImpl(error
, text
);
877 void EnqueueError(const webgl::ErrorInfo
& info
) const {
878 EnqueueError(info
.type
, "%s", info
.info
.c_str());
881 template <typename
... Args
>
882 void EnqueueWarning(const char* const format
, const Args
&... args
) const {
883 EnqueueError(0, format
, args
...);
886 template <typename
... Args
>
887 void EnqueuePerfWarning(const char* const format
, const Args
&... args
) const {
888 EnqueueError(webgl::kErrorPerfWarning
, format
, args
...);
891 void EnqueueError_ArgEnum(const char* argName
,
892 GLenum val
) const; // Cold code.
895 void EnqueueErrorImpl(GLenum errorOrZero
, const nsACString
&) const;
898 bool ValidateArrayBufferView(const dom::ArrayBufferView
& view
,
899 GLuint elemOffset
, GLuint elemCountOverride
,
900 const GLenum errorEnum
,
901 uint8_t** const out_bytes
,
902 size_t* const out_byteLen
) const;
905 template <typename T
>
906 bool ValidateNonNull(const char* const argName
,
907 const dom::Nullable
<T
>& maybe
) const {
908 if (maybe
.IsNull()) {
909 EnqueueError(LOCAL_GL_INVALID_VALUE
, "%s: Cannot be null.", argName
);
915 bool ValidateNonNegative(const char* argName
, int64_t val
) const {
916 if (MOZ_UNLIKELY(val
< 0)) {
917 EnqueueError(LOCAL_GL_INVALID_VALUE
, "`%s` must be non-negative.",
924 bool ValidateViewType(GLenum unpackType
, const TexImageSource
& src
) const;
926 Maybe
<uvec3
> ValidateExtents(GLsizei width
, GLsizei height
, GLsizei depth
,
929 // -------------------------------------------------------------------------
930 // nsICanvasRenderingContextInternal / nsAPostRefreshObserver
931 // -------------------------------------------------------------------------
933 bool InitializeCanvasRenderer(nsDisplayListBuilder
* aBuilder
,
934 layers::CanvasRenderer
* aRenderer
) override
;
936 void MarkContextCleanForFrameCapture() override
{
937 mFrameCaptureState
= FrameCaptureState::CLEAN
;
939 // Note that 'clean' here refers to its invalidation state, not the
940 // contents of the buffer.
941 Watchable
<FrameCaptureState
>* GetFrameCaptureState() override
{
942 return &mFrameCaptureState
;
945 void OnMemoryPressure() override
;
946 void SetContextOptions(const WebGLContextOptions
& aOptions
) {
947 mInitialOptions
.emplace(aOptions
);
949 const WebGLContextOptions
& GetContextOptions() const {
950 return mInitialOptions
.ref();
953 SetContextOptions(JSContext
* cx
, JS::Handle
<JS::Value
> options
,
954 ErrorResult
& aRvForDictionaryInit
) override
;
956 SetDimensions(int32_t width
, int32_t height
) override
;
957 bool UpdateWebRenderCanvasData(
958 nsDisplayListBuilder
* aBuilder
,
959 layers::WebRenderCanvasData
* aCanvasData
) override
;
963 int32_t GetWidth() override
{ return AutoAssertCast(DrawingBufferSize().x
); }
964 int32_t GetHeight() override
{ return AutoAssertCast(DrawingBufferSize().y
); }
966 NS_IMETHOD
InitializeWithDrawTarget(nsIDocShell
*,
967 NotNull
<gfx::DrawTarget
*>) override
{
968 return NS_ERROR_NOT_IMPLEMENTED
;
971 void ResetBitmap() override
;
973 UniquePtr
<uint8_t[]> GetImageBuffer(int32_t* out_format
,
974 gfx::IntSize
* out_imageSize
) override
;
975 NS_IMETHOD
GetInputStream(const char* mimeType
,
976 const nsAString
& encoderOptions
,
977 nsIInputStream
** out_stream
) override
;
979 already_AddRefed
<mozilla::gfx::SourceSurface
> GetSurfaceSnapshot(
980 gfxAlphaType
* out_alphaType
) override
;
982 void SetOpaqueValueFromOpaqueAttr(bool) override
{};
983 bool GetIsOpaque() override
{ return !mInitialOptions
->alpha
; }
986 * An abstract base class to be implemented by callers wanting to be notified
987 * that a refresh has occurred. Callers must ensure an observer is removed
988 * before it is destroyed.
990 void DidRefresh() override
;
992 NS_IMETHOD
Redraw(const gfxRect
&) override
{
993 return NS_ERROR_NOT_IMPLEMENTED
;
999 layers::LayersBackend
GetCompositorBackendType() const;
1001 Watchable
<FrameCaptureState
> mFrameCaptureState
= {
1002 FrameCaptureState::CLEAN
, "ClientWebGLContext::mFrameCaptureState"};
1004 // -------------------------------------------------------------------------
1005 // WebGLRenderingContext Basic Properties and Methods
1006 // -------------------------------------------------------------------------
1008 dom::HTMLCanvasElement
* GetCanvas() const { return mCanvasElement
; }
1011 dom::Nullable
<dom::OwningHTMLCanvasElementOrOffscreenCanvas
>& retval
);
1013 GLsizei
DrawingBufferWidth() {
1014 const FuncScope
funcScope(*this, "drawingBufferWidth");
1015 return AutoAssertCast(DrawingBufferSize().x
);
1017 GLsizei
DrawingBufferHeight() {
1018 const FuncScope
funcScope(*this, "drawingBufferHeight");
1019 return AutoAssertCast(DrawingBufferSize().y
);
1021 void GetContextAttributes(dom::Nullable
<dom::WebGLContextAttributes
>& retval
);
1024 webgl::SwapChainOptions
PrepareAsyncSwapChainOptions(
1025 WebGLFramebufferJS
* fb
, bool webvr
,
1026 const webgl::SwapChainOptions
& options
= webgl::SwapChainOptions());
1029 layers::TextureType
GetTexTypeForSwapChain() const;
1031 WebGLFramebufferJS
*, const bool webvr
= false,
1032 const webgl::SwapChainOptions
& options
= webgl::SwapChainOptions());
1034 WebGLFramebufferJS
*, layers::TextureType
, const bool webvr
= false,
1035 const webgl::SwapChainOptions
& options
= webgl::SwapChainOptions());
1036 void CopyToSwapChain(
1037 WebGLFramebufferJS
*,
1038 const webgl::SwapChainOptions
& options
= webgl::SwapChainOptions());
1040 Maybe
<layers::SurfaceDescriptor
> GetFrontBuffer(
1041 WebGLFramebufferJS
*, const bool webvr
= false) override
;
1042 Maybe
<layers::SurfaceDescriptor
> PresentFrontBuffer(
1043 WebGLFramebufferJS
*, layers::TextureType
,
1044 const bool webvr
= false) override
;
1045 RefPtr
<gfx::SourceSurface
> GetFrontBufferSnapshot(
1046 bool requireAlphaPremult
= true) override
;
1048 void ClearVRSwapChain();
1051 RefPtr
<gfx::DataSourceSurface
> BackBufferSnapshot();
1052 [[nodiscard
]] bool DoReadPixels(const webgl::ReadPixelsDesc
&,
1053 Range
<uint8_t>) const;
1054 [[nodiscard
]] bool DoReadPixels(const webgl::ReadPixelsDesc
&,
1055 const mozilla::ipc::Shmem
&) const;
1056 uvec2
DrawingBufferSize();
1060 bool mAutoFlushPending
= false;
1062 void AutoEnqueueFlush() {
1063 if (MOZ_LIKELY(mAutoFlushPending
)) return;
1064 mAutoFlushPending
= true;
1066 const auto weak
= WeakPtr
<ClientWebGLContext
>(this);
1067 const auto DeferredFlush
= [weak
]() {
1068 const auto strong
= RefPtr
<ClientWebGLContext
>(weak
);
1069 if (!strong
) return;
1070 if (!strong
->mAutoFlushPending
) return;
1071 strong
->mAutoFlushPending
= false;
1073 if (!StaticPrefs::webgl_auto_flush()) return;
1074 const bool flushGl
= StaticPrefs::webgl_auto_flush_gl();
1075 strong
->Flush(flushGl
);
1078 already_AddRefed
<mozilla::CancelableRunnable
> runnable
=
1079 NS_NewCancelableRunnableFunction("enqueue Event_webglcontextrestored",
1081 NS_DispatchToCurrentThread(std::move(runnable
));
1084 void CancelAutoFlush() { mAutoFlushPending
= false; }
1088 void AfterDrawCall() {
1089 if (!mNotLost
) return;
1090 const auto& state
= State();
1091 if (!state
.mBoundDrawFb
) {
1098 // -------------------------------------------------------------------------
1099 // Client-side helper methods. Dispatch to a Host method.
1100 // -------------------------------------------------------------------------
1102 // ------------------------- GL State -------------------------
1104 bool IsContextLost() const { return !mNotLost
; }
1106 void Disable(GLenum cap
) const { SetEnabledI(cap
, {}, false); }
1107 void Enable(GLenum cap
) const { SetEnabledI(cap
, {}, true); }
1108 void SetEnabledI(GLenum cap
, Maybe
<GLuint
> i
, bool val
) const;
1109 bool IsEnabled(GLenum cap
) const;
1112 Maybe
<double> GetNumber(GLenum pname
);
1113 Maybe
<std::string
> GetString(GLenum pname
);
1116 void GetParameter(JSContext
* cx
, GLenum pname
,
1117 JS::MutableHandle
<JS::Value
> retval
, ErrorResult
& rv
,
1118 bool debug
= false);
1120 void GetBufferParameter(JSContext
* cx
, GLenum target
, GLenum pname
,
1121 JS::MutableHandle
<JS::Value
> retval
) const;
1123 void GetFramebufferAttachmentParameter(JSContext
* cx
, GLenum target
,
1124 GLenum attachment
, GLenum pname
,
1125 JS::MutableHandle
<JS::Value
> retval
,
1126 ErrorResult
& rv
) const;
1128 void GetRenderbufferParameter(JSContext
* cx
, GLenum target
, GLenum pname
,
1129 JS::MutableHandle
<JS::Value
> retval
) const;
1131 void GetIndexedParameter(JSContext
* cx
, GLenum target
, GLuint index
,
1132 JS::MutableHandle
<JS::Value
> retval
,
1133 ErrorResult
& rv
) const;
1135 already_AddRefed
<WebGLShaderPrecisionFormatJS
> GetShaderPrecisionFormat(
1136 GLenum shadertype
, GLenum precisiontype
);
1138 void UseProgram(WebGLProgramJS
*);
1139 void ValidateProgram(WebGLProgramJS
&) const;
1143 already_AddRefed
<WebGLBufferJS
> CreateBuffer() const;
1144 already_AddRefed
<WebGLFramebufferJS
> CreateFramebuffer() const;
1145 already_AddRefed
<WebGLFramebufferJS
> CreateOpaqueFramebuffer(
1146 const webgl::OpaqueFramebufferOptions
&) const;
1147 already_AddRefed
<WebGLProgramJS
> CreateProgram() const;
1148 already_AddRefed
<WebGLQueryJS
> CreateQuery() const;
1149 already_AddRefed
<WebGLRenderbufferJS
> CreateRenderbuffer() const;
1150 already_AddRefed
<WebGLSamplerJS
> CreateSampler() const;
1151 already_AddRefed
<WebGLShaderJS
> CreateShader(GLenum type
) const;
1152 already_AddRefed
<WebGLSyncJS
> FenceSync(GLenum condition
,
1153 GLbitfield flags
) const;
1154 already_AddRefed
<WebGLTextureJS
> CreateTexture() const;
1155 already_AddRefed
<WebGLTransformFeedbackJS
> CreateTransformFeedback() const;
1156 already_AddRefed
<WebGLVertexArrayJS
> CreateVertexArray() const;
1158 void DeleteBuffer(WebGLBufferJS
*);
1159 void DeleteFramebuffer(WebGLFramebufferJS
*, bool canDeleteOpaque
= false);
1160 void DeleteProgram(WebGLProgramJS
*) const;
1161 void DeleteQuery(WebGLQueryJS
*);
1162 void DeleteRenderbuffer(WebGLRenderbufferJS
*);
1163 void DeleteSampler(WebGLSamplerJS
*);
1164 void DeleteShader(WebGLShaderJS
*) const;
1165 void DeleteSync(WebGLSyncJS
*) const;
1166 void DeleteTexture(WebGLTextureJS
*);
1167 void DeleteTransformFeedback(WebGLTransformFeedbackJS
*);
1168 void DeleteVertexArray(WebGLVertexArrayJS
*);
1171 void DoDeleteProgram(WebGLProgramJS
&) const;
1172 void DoDeleteShader(const WebGLShaderJS
&) const;
1177 bool IsBuffer(const WebGLBufferJS
*) const;
1178 bool IsFramebuffer(const WebGLFramebufferJS
*) const;
1179 bool IsProgram(const WebGLProgramJS
*) const;
1180 bool IsQuery(const WebGLQueryJS
*) const;
1181 bool IsRenderbuffer(const WebGLRenderbufferJS
*) const;
1182 bool IsSampler(const WebGLSamplerJS
*) const;
1183 bool IsShader(const WebGLShaderJS
*) const;
1184 bool IsSync(const WebGLSyncJS
*) const;
1185 bool IsTexture(const WebGLTextureJS
*) const;
1186 bool IsTransformFeedback(const WebGLTransformFeedbackJS
*) const;
1187 bool IsVertexArray(const WebGLVertexArrayJS
*) const;
1193 const webgl::LinkResult
& GetLinkResult(const WebGLProgramJS
&) const;
1196 void AttachShader(WebGLProgramJS
&, WebGLShaderJS
&) const;
1197 void BindAttribLocation(WebGLProgramJS
&, GLuint location
,
1198 const nsAString
& name
) const;
1199 void DetachShader(WebGLProgramJS
&, const WebGLShaderJS
&) const;
1200 void GetAttachedShaders(
1201 const WebGLProgramJS
&,
1202 dom::Nullable
<nsTArray
<RefPtr
<WebGLShaderJS
>>>& retval
) const;
1203 void LinkProgram(WebGLProgramJS
&) const;
1204 void TransformFeedbackVaryings(WebGLProgramJS
&,
1205 const dom::Sequence
<nsString
>& varyings
,
1206 GLenum bufferMode
) const;
1207 void UniformBlockBinding(WebGLProgramJS
&, GLuint blockIndex
,
1208 GLuint blockBinding
) const;
1210 // Link result reflection
1211 already_AddRefed
<WebGLActiveInfoJS
> GetActiveAttrib(const WebGLProgramJS
&,
1213 already_AddRefed
<WebGLActiveInfoJS
> GetActiveUniform(const WebGLProgramJS
&,
1215 void GetActiveUniformBlockName(const WebGLProgramJS
&,
1216 GLuint uniformBlockIndex
,
1217 nsAString
& retval
) const;
1218 void GetActiveUniformBlockParameter(JSContext
* cx
, const WebGLProgramJS
&,
1219 GLuint uniformBlockIndex
, GLenum pname
,
1220 JS::MutableHandle
<JS::Value
> retval
,
1222 void GetActiveUniforms(JSContext
*, const WebGLProgramJS
&,
1223 const dom::Sequence
<GLuint
>& uniformIndices
,
1225 JS::MutableHandle
<JS::Value
> retval
) const;
1226 GLint
GetAttribLocation(const WebGLProgramJS
&, const nsAString
& name
) const;
1227 GLint
GetFragDataLocation(const WebGLProgramJS
&, const nsAString
& name
) const;
1228 void GetProgramInfoLog(const WebGLProgramJS
& prog
, nsAString
& retval
) const;
1229 void GetProgramParameter(JSContext
*, const WebGLProgramJS
&, GLenum pname
,
1230 JS::MutableHandle
<JS::Value
> retval
) const;
1231 already_AddRefed
<WebGLActiveInfoJS
> GetTransformFeedbackVarying(
1232 const WebGLProgramJS
&, GLuint index
);
1233 GLuint
GetUniformBlockIndex(const WebGLProgramJS
&,
1234 const nsAString
& uniformBlockName
) const;
1235 void GetUniformIndices(const WebGLProgramJS
&,
1236 const dom::Sequence
<nsString
>& uniformNames
,
1237 dom::Nullable
<nsTArray
<GLuint
>>& retval
) const;
1239 // WebGLUniformLocationJS
1240 already_AddRefed
<WebGLUniformLocationJS
> GetUniformLocation(
1241 const WebGLProgramJS
&, const nsAString
& name
) const;
1242 void GetUniform(JSContext
*, const WebGLProgramJS
&,
1243 const WebGLUniformLocationJS
&,
1244 JS::MutableHandle
<JS::Value
> retval
);
1250 const webgl::CompileResult
& GetCompileResult(const WebGLShaderJS
&) const;
1253 void CompileShader(WebGLShaderJS
&) const;
1254 void GetShaderInfoLog(const WebGLShaderJS
&, nsAString
& retval
) const;
1255 void GetShaderParameter(JSContext
*, const WebGLShaderJS
&, GLenum pname
,
1256 JS::MutableHandle
<JS::Value
> retval
) const;
1257 void GetShaderSource(const WebGLShaderJS
&, nsAString
& retval
) const;
1258 void GetTranslatedShaderSource(const WebGLShaderJS
& shader
,
1259 nsAString
& retval
) const;
1260 void ShaderSource(WebGLShaderJS
&, const nsAString
&) const;
1264 void BindFramebuffer(GLenum target
, WebGLFramebufferJS
*);
1266 void BlendColor(GLclampf r
, GLclampf g
, GLclampf b
, GLclampf a
);
1270 void BlendEquation(GLenum mode
) { BlendEquationSeparate(mode
, mode
); }
1271 void BlendFunc(GLenum sfactor
, GLenum dfactor
) {
1272 BlendFuncSeparate(sfactor
, dfactor
, sfactor
, dfactor
);
1275 void BlendEquationSeparate(GLenum modeRGB
, GLenum modeAlpha
) {
1276 BlendEquationSeparateI({}, modeRGB
, modeAlpha
);
1278 void BlendFuncSeparate(GLenum srcRGB
, GLenum dstRGB
, GLenum srcAlpha
,
1280 BlendFuncSeparateI({}, srcRGB
, dstRGB
, srcAlpha
, dstAlpha
);
1283 void BlendEquationSeparateI(Maybe
<GLuint
> buf
, GLenum modeRGB
,
1285 void BlendFuncSeparateI(Maybe
<GLuint
> buf
, GLenum srcRGB
, GLenum dstRGB
,
1286 GLenum srcAlpha
, GLenum dstAlpha
);
1290 GLenum
CheckFramebufferStatus(GLenum target
);
1292 void Clear(GLbitfield mask
);
1297 void ClearBufferTv(GLenum buffer
, GLint drawBuffer
, webgl::AttribBaseType
,
1298 const Range
<const uint8_t>& view
, GLuint srcElemOffset
);
1301 void ClearBufferfv(GLenum buffer
, GLint drawBuffer
, const Float32ListU
& list
,
1302 GLuint srcElemOffset
) {
1303 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Float
,
1304 MakeByteRange(list
), srcElemOffset
);
1306 void ClearBufferiv(GLenum buffer
, GLint drawBuffer
, const Int32ListU
& list
,
1307 GLuint srcElemOffset
) {
1308 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Int
,
1309 MakeByteRange(list
), srcElemOffset
);
1311 void ClearBufferuiv(GLenum buffer
, GLint drawBuffer
, const Uint32ListU
& list
,
1312 GLuint srcElemOffset
) {
1313 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Uint
,
1314 MakeByteRange(list
), srcElemOffset
);
1319 void ClearBufferfi(GLenum buffer
, GLint drawBuffer
, GLfloat depth
,
1322 void ClearColor(GLclampf r
, GLclampf g
, GLclampf b
, GLclampf a
);
1324 void ClearDepth(GLclampf v
);
1326 void ClearStencil(GLint v
);
1328 void ColorMask(bool r
, bool g
, bool b
, bool a
) const {
1329 ColorMaskI({}, r
, g
, b
, a
);
1331 void ColorMaskI(Maybe
<GLuint
> buf
, bool r
, bool g
, bool b
, bool a
) const;
1333 void CullFace(GLenum face
);
1335 void DepthFunc(GLenum func
);
1337 void DepthMask(WebGLboolean b
);
1339 void DepthRange(GLclampf zNear
, GLclampf zFar
);
1341 void Flush(bool flushGl
= true);
1345 void FrontFace(GLenum mode
);
1349 void Hint(GLenum target
, GLenum mode
);
1351 void LineWidth(GLfloat width
);
1353 void PixelStorei(GLenum pname
, GLint param
);
1355 void PolygonOffset(GLfloat factor
, GLfloat units
);
1357 void SampleCoverage(GLclampf value
, WebGLboolean invert
);
1359 void Scissor(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1363 void StencilFunc(GLenum func
, GLint ref
, GLuint mask
) {
1364 StencilFuncSeparate(LOCAL_GL_FRONT_AND_BACK
, func
, ref
, mask
);
1366 void StencilMask(GLuint mask
) {
1367 StencilMaskSeparate(LOCAL_GL_FRONT_AND_BACK
, mask
);
1369 void StencilOp(GLenum sfail
, GLenum dpfail
, GLenum dppass
) {
1370 StencilOpSeparate(LOCAL_GL_FRONT_AND_BACK
, sfail
, dpfail
, dppass
);
1373 void StencilFuncSeparate(GLenum face
, GLenum func
, GLint ref
, GLuint mask
);
1374 void StencilMaskSeparate(GLenum face
, GLuint mask
);
1375 void StencilOpSeparate(GLenum face
, GLenum sfail
, GLenum dpfail
,
1380 void Viewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1382 // ------------------------- Buffer Objects -------------------------
1384 void BindBuffer(GLenum target
, WebGLBufferJS
*);
1389 void BindBufferRangeImpl(const GLenum target
, const GLuint index
,
1390 WebGLBufferJS
* const buffer
, const uint64_t offset
,
1391 const uint64_t size
);
1394 void BindBufferBase(const GLenum target
, const GLuint index
,
1395 WebGLBufferJS
* const buffer
) {
1396 const FuncScope
funcScope(*this, "bindBufferBase");
1397 if (IsContextLost()) return;
1399 BindBufferRangeImpl(target
, index
, buffer
, 0, 0);
1402 void BindBufferRange(const GLenum target
, const GLuint index
,
1403 WebGLBufferJS
* const buffer
, const WebGLintptr offset
,
1404 const WebGLsizeiptr size
) {
1405 const FuncScope
funcScope(*this, "bindBufferRange");
1406 if (IsContextLost()) return;
1409 if (!ValidateNonNegative("offset", offset
)) return;
1412 EnqueueError(LOCAL_GL_INVALID_VALUE
,
1413 "`size` must be positive for non-null `buffer`.");
1418 BindBufferRangeImpl(target
, index
, buffer
, static_cast<uint64_t>(offset
),
1419 static_cast<uint64_t>(size
));
1424 void CopyBufferSubData(GLenum readTarget
, GLenum writeTarget
,
1425 GLintptr readOffset
, GLintptr writeOffset
,
1428 void BufferData(GLenum target
, WebGLsizeiptr size
, GLenum usage
);
1429 void BufferData(GLenum target
,
1430 const dom::Nullable
<dom::ArrayBuffer
>& maybeSrc
,
1432 void BufferData(GLenum target
, const dom::ArrayBufferView
& srcData
,
1433 GLenum usage
, GLuint srcElemOffset
= 0,
1434 GLuint srcElemCountOverride
= 0);
1436 void RawBufferData(GLenum target
, const uint8_t* srcBytes
, size_t srcLen
,
1438 void RawBufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1439 const uint8_t* srcBytes
, size_t srcLen
);
1441 void BufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1442 const dom::ArrayBufferView
& src
, GLuint srcElemOffset
= 0,
1443 GLuint srcElemCountOverride
= 0);
1444 void BufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1445 const dom::ArrayBuffer
& src
);
1447 void GetBufferSubData(GLenum target
, GLintptr srcByteOffset
,
1448 const dom::ArrayBufferView
& dstData
,
1449 GLuint dstElemOffset
, GLuint dstElemCountOverride
);
1451 // -------------------------- Framebuffer Objects --------------------------
1453 void BlitFramebuffer(GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1454 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1455 GLbitfield mask
, GLenum filter
);
1460 // `bindTarget` if non-zero allows initializing the rb/tex with that target.
1461 void FramebufferAttach(GLenum target
, GLenum attachEnum
, GLenum bindTarget
,
1462 WebGLRenderbufferJS
*, WebGLTextureJS
*,
1463 uint32_t mipLevel
, uint32_t zLayer
,
1464 uint32_t numViewLayers
) const;
1467 void FramebufferRenderbuffer(GLenum target
, GLenum attachSlot
,
1468 GLenum rbTarget
, WebGLRenderbufferJS
* rb
) const {
1469 const FuncScope
funcScope(*this, "framebufferRenderbuffer");
1470 if (IsContextLost()) return;
1471 if (rbTarget
!= LOCAL_GL_RENDERBUFFER
) {
1472 EnqueueError_ArgEnum("rbTarget", rbTarget
);
1475 FramebufferAttach(target
, attachSlot
, rbTarget
, rb
, nullptr, 0, 0, 0);
1478 void FramebufferTexture2D(GLenum target
, GLenum attachSlot
,
1479 GLenum texImageTarget
, WebGLTextureJS
*,
1480 GLint mipLevel
) const;
1482 void FramebufferTextureLayer(GLenum target
, GLenum attachSlot
,
1483 WebGLTextureJS
* tex
, GLint mipLevel
,
1484 GLint zLayer
) const {
1485 const FuncScope
funcScope(*this, "framebufferTextureLayer");
1486 if (IsContextLost()) return;
1487 FramebufferAttach(target
, attachSlot
, 0, nullptr, tex
,
1488 static_cast<uint32_t>(mipLevel
),
1489 static_cast<uint32_t>(zLayer
), 0);
1492 void FramebufferTextureMultiview(GLenum target
, GLenum attachSlot
,
1493 WebGLTextureJS
* tex
, GLint mipLevel
,
1495 GLsizei numViewLayers
) const {
1496 const FuncScope
funcScope(*this, "framebufferTextureMultiview");
1497 if (IsContextLost()) return;
1498 if (tex
&& numViewLayers
< 1) {
1499 EnqueueError(LOCAL_GL_INVALID_VALUE
, "`numViewLayers` must be >=1.");
1502 FramebufferAttach(target
, attachSlot
, 0, nullptr, tex
,
1503 static_cast<uint32_t>(mipLevel
),
1504 static_cast<uint32_t>(zLayerBase
),
1505 static_cast<uint32_t>(numViewLayers
));
1510 void InvalidateFramebuffer(GLenum target
,
1511 const dom::Sequence
<GLenum
>& attachments
,
1512 ErrorResult
& unused
);
1513 void InvalidateSubFramebuffer(GLenum target
,
1514 const dom::Sequence
<GLenum
>& attachments
,
1515 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1516 ErrorResult
& unused
);
1518 void ReadBuffer(GLenum mode
);
1520 // ----------------------- Renderbuffer objects -----------------------
1521 void GetInternalformatParameter(JSContext
* cx
, GLenum target
,
1522 GLenum internalformat
, GLenum pname
,
1523 JS::MutableHandle
<JS::Value
> retval
,
1526 void BindRenderbuffer(GLenum target
, WebGLRenderbufferJS
*);
1528 void RenderbufferStorage(GLenum target
, GLenum internalFormat
, GLsizei width
,
1529 GLsizei height
) const {
1530 RenderbufferStorageMultisample(target
, 0, internalFormat
, width
, height
);
1533 void RenderbufferStorageMultisample(GLenum target
, GLsizei samples
,
1534 GLenum internalFormat
, GLsizei width
,
1535 GLsizei height
) const;
1537 // --------------------------- Texture objects ---------------------------
1539 void ActiveTexture(GLenum texUnit
);
1541 void BindTexture(GLenum texTarget
, WebGLTextureJS
*);
1543 void GenerateMipmap(GLenum texTarget
) const;
1545 void GetTexParameter(JSContext
* cx
, GLenum texTarget
, GLenum pname
,
1546 JS::MutableHandle
<JS::Value
> retval
) const;
1548 void TexParameterf(GLenum texTarget
, GLenum pname
, GLfloat param
);
1549 void TexParameteri(GLenum texTarget
, GLenum pname
, GLint param
);
1554 void TexStorage(uint8_t funcDims
, GLenum target
, GLsizei levels
,
1555 GLenum internalFormat
, const ivec3
& size
) const;
1557 // Primitive tex upload functions
1558 void RawTexImage(uint32_t level
, GLenum respecFormat
, uvec3 offset
,
1559 const webgl::PackingInfo
& pi
,
1560 webgl::TexUnpackBlobDesc
&&) const;
1561 void TexImage(uint8_t funcDims
, GLenum target
, GLint level
,
1562 GLenum respecFormat
, const ivec3
& offset
,
1563 const Maybe
<ivec3
>& size
, GLint border
,
1564 const webgl::PackingInfo
& pi
, const TexImageSource
& src
) const;
1565 void CompressedTexImage(bool sub
, uint8_t funcDims
, GLenum target
,
1566 GLint level
, GLenum format
, const ivec3
& offset
,
1567 const ivec3
& size
, GLint border
,
1568 const TexImageSource
& src
,
1569 GLsizei pboImageSize
) const;
1570 void CopyTexImage(uint8_t funcDims
, GLenum target
, GLint level
,
1571 GLenum respecFormat
, const ivec3
& dstOffset
,
1572 const ivec2
& srcOffset
, const ivec2
& size
,
1573 GLint border
) const;
1576 void TexStorage2D(GLenum target
, GLsizei levels
, GLenum internalFormat
,
1577 GLsizei width
, GLsizei height
) const {
1578 TexStorage(2, target
, levels
, internalFormat
, {width
, height
, 1});
1581 void TexStorage3D(GLenum target
, GLsizei levels
, GLenum internalFormat
,
1582 GLsizei width
, GLsizei height
, GLsizei depth
) const {
1583 TexStorage(3, target
, levels
, internalFormat
, {width
, height
, depth
});
1586 ////////////////////////////////////
1588 template <typename T
> // TexImageSource or WebGLintptr
1589 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1590 GLsizei width
, GLsizei height
, GLint border
,
1591 GLenum unpackFormat
, GLenum unpackType
, const T
& anySrc
,
1592 ErrorResult
& out_error
) const {
1593 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1594 TexImage(2, target
, level
, internalFormat
, {0, 0, 0},
1595 Some(ivec3
{width
, height
, 1}), border
, {unpackFormat
, unpackType
},
1599 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1600 GLsizei width
, GLsizei height
, GLint border
,
1601 GLenum unpackFormat
, GLenum unpackType
,
1602 const dom::ArrayBufferView
& view
, GLuint viewElemOffset
,
1603 ErrorResult
&) const {
1604 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1605 TexImage(2, target
, level
, internalFormat
, {0, 0, 0},
1606 Some(ivec3
{width
, height
, 1}), border
, {unpackFormat
, unpackType
},
1612 template <typename T
> // TexImageSource or WebGLintptr
1613 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1614 GLsizei width
, GLsizei height
, GLenum unpackFormat
,
1615 GLenum unpackType
, const T
& anySrc
,
1616 ErrorResult
& out_error
) const {
1617 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1618 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0},
1619 Some(ivec3
{width
, height
, 1}), 0, {unpackFormat
, unpackType
}, src
);
1622 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1623 GLsizei width
, GLsizei height
, GLenum unpackFormat
,
1624 GLenum unpackType
, const dom::ArrayBufferView
& view
,
1625 GLuint viewElemOffset
, ErrorResult
&) const {
1626 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1627 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0},
1628 Some(ivec3
{width
, height
, 1}), 0, {unpackFormat
, unpackType
}, src
);
1633 template <typename T
> // TexImageSource or WebGLintptr
1634 void TexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1635 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
,
1636 GLenum unpackFormat
, GLenum unpackType
, const T
& anySrc
,
1637 ErrorResult
& out_error
) const {
1638 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1639 TexImage(3, target
, level
, internalFormat
, {0, 0, 0},
1640 Some(ivec3
{width
, height
, depth
}), border
,
1641 {unpackFormat
, unpackType
}, src
);
1644 void TexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1645 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
,
1646 GLenum unpackFormat
, GLenum unpackType
,
1647 const dom::ArrayBufferView
& view
, GLuint viewElemOffset
,
1648 ErrorResult
&) const {
1649 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1650 TexImage(3, target
, level
, internalFormat
, {0, 0, 0},
1651 Some(ivec3
{width
, height
, depth
}), border
,
1652 {unpackFormat
, unpackType
}, src
);
1657 template <typename T
> // TexImageSource or WebGLintptr
1658 void TexSubImage3D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1659 GLint zOffset
, GLsizei width
, GLsizei height
,
1660 GLsizei depth
, GLenum unpackFormat
, GLenum unpackType
,
1661 const T
& anySrc
, ErrorResult
& out_error
) const {
1662 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1663 TexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
},
1664 Some(ivec3
{width
, height
, depth
}), 0, {unpackFormat
, unpackType
},
1668 void TexSubImage3D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1669 GLint zOffset
, GLsizei width
, GLsizei height
,
1670 GLsizei depth
, GLenum unpackFormat
, GLenum unpackType
,
1671 const dom::Nullable
<dom::ArrayBufferView
>& maybeSrcView
,
1672 GLuint srcElemOffset
, ErrorResult
&) const {
1673 const TexImageSourceAdapter
src(&maybeSrcView
, srcElemOffset
);
1674 TexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
},
1675 Some(ivec3
{width
, height
, depth
}), 0, {unpackFormat
, unpackType
},
1679 ////////////////////////////////////
1682 void CompressedTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1683 GLsizei width
, GLsizei height
, GLint border
,
1684 GLsizei imageSize
, WebGLintptr offset
) const {
1685 const TexImageSourceAdapter
src(&offset
);
1686 CompressedTexImage(false, 2, target
, level
, internalFormat
, {0, 0, 0},
1687 {width
, height
, 1}, border
, src
, imageSize
);
1690 void CompressedTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1691 GLsizei width
, GLsizei height
, GLint border
,
1692 const dom::ArrayBufferView
& view
,
1693 GLuint viewElemOffset
= 0,
1694 GLuint viewElemLengthOverride
= 0) const {
1695 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1696 viewElemLengthOverride
);
1697 CompressedTexImage(false, 2, target
, level
, internalFormat
, {0, 0, 0},
1698 {width
, height
, 1}, border
, src
, 0);
1703 void CompressedTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1704 GLint yOffset
, GLsizei width
, GLsizei height
,
1705 GLenum unpackFormat
, GLsizei imageSize
,
1706 WebGLintptr offset
) const {
1707 const TexImageSourceAdapter
src(&offset
);
1708 CompressedTexImage(true, 2, target
, level
, unpackFormat
,
1709 {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0, src
,
1713 void CompressedTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1714 GLint yOffset
, GLsizei width
, GLsizei height
,
1715 GLenum unpackFormat
,
1716 const dom::ArrayBufferView
& view
,
1717 GLuint viewElemOffset
= 0,
1718 GLuint viewElemLengthOverride
= 0) const {
1719 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1720 viewElemLengthOverride
);
1721 CompressedTexImage(true, 2, target
, level
, unpackFormat
,
1722 {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0, src
, 0);
1727 void CompressedTexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1728 GLsizei width
, GLsizei height
, GLsizei depth
,
1729 GLint border
, GLsizei imageSize
,
1730 WebGLintptr offset
) const {
1731 const TexImageSourceAdapter
src(&offset
);
1732 CompressedTexImage(false, 3, target
, level
, internalFormat
, {0, 0, 0},
1733 {width
, height
, depth
}, border
, src
, imageSize
);
1736 void CompressedTexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1737 GLsizei width
, GLsizei height
, GLsizei depth
,
1738 GLint border
, const dom::ArrayBufferView
& view
,
1739 GLuint viewElemOffset
= 0,
1740 GLuint viewElemLengthOverride
= 0) const {
1741 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1742 viewElemLengthOverride
);
1743 CompressedTexImage(false, 3, target
, level
, internalFormat
, {0, 0, 0},
1744 {width
, height
, depth
}, border
, src
, 0);
1749 void CompressedTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1750 GLint yOffset
, GLint zOffset
, GLsizei width
,
1751 GLsizei height
, GLsizei depth
,
1752 GLenum unpackFormat
, GLsizei imageSize
,
1753 WebGLintptr offset
) const {
1754 const TexImageSourceAdapter
src(&offset
);
1755 CompressedTexImage(true, 3, target
, level
, unpackFormat
,
1756 {xOffset
, yOffset
, zOffset
}, {width
, height
, depth
}, 0,
1760 void CompressedTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1761 GLint yOffset
, GLint zOffset
, GLsizei width
,
1762 GLsizei height
, GLsizei depth
,
1763 GLenum unpackFormat
,
1764 const dom::ArrayBufferView
& view
,
1765 GLuint viewElemOffset
= 0,
1766 GLuint viewElemLengthOverride
= 0) const {
1767 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1768 viewElemLengthOverride
);
1769 CompressedTexImage(true, 3, target
, level
, unpackFormat
,
1770 {xOffset
, yOffset
, zOffset
}, {width
, height
, depth
}, 0,
1774 // --------------------
1776 void CopyTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1777 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1778 GLint border
) const {
1779 CopyTexImage(2, target
, level
, internalFormat
, {0, 0, 0}, {x
, y
},
1780 {width
, height
}, border
);
1783 void CopyTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1784 GLint yOffset
, GLint x
, GLint y
, GLsizei width
,
1785 GLsizei height
) const {
1786 CopyTexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {x
, y
},
1787 {width
, height
}, 0);
1790 void CopyTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1791 GLint yOffset
, GLint zOffset
, GLint x
, GLint y
,
1792 GLsizei width
, GLsizei height
) const {
1793 CopyTexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
}, {x
, y
},
1794 {width
, height
}, 0);
1797 // -------------------
1798 // legacy TexImageSource uploads without width/height.
1799 // The width/height params are webgl2 only, and let you do subrect
1800 // selection with e.g. width < UNPACK_ROW_LENGTH.
1802 template <typename TexImageSourceT
>
1803 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1804 GLenum unpackFormat
, GLenum unpackType
,
1805 const TexImageSourceT
& anySrc
, ErrorResult
& out_error
) const {
1806 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1807 TexImage(2, target
, level
, internalFormat
, {}, {}, 0,
1808 {unpackFormat
, unpackType
}, src
);
1811 template <typename TexImageSourceT
>
1812 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1813 GLenum unpackFormat
, GLenum unpackType
,
1814 const TexImageSourceT
& anySrc
,
1815 ErrorResult
& out_error
) const {
1816 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1817 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {}, 0,
1818 {unpackFormat
, unpackType
}, src
);
1821 // ------------------------ Uniforms and attributes ------------------------
1824 Maybe
<double> GetVertexAttribPriv(GLuint index
, GLenum pname
);
1827 void GetVertexAttrib(JSContext
* cx
, GLuint index
, GLenum pname
,
1828 JS::MutableHandle
<JS::Value
> retval
, ErrorResult
& rv
);
1831 const webgl::LinkResult
* GetActiveLinkResult() const {
1832 const auto& state
= State();
1833 if (state
.mCurrentProgram
) {
1834 (void)GetLinkResult(*state
.mCurrentProgram
);
1836 return state
.mActiveLinkResult
.get();
1839 void UniformData(GLenum funcElemType
, const WebGLUniformLocationJS
* const loc
,
1840 bool transpose
, const Range
<const uint8_t>& bytes
,
1841 GLuint elemOffset
= 0, GLuint elemCountOverride
= 0) const;
1845 template <typename T
>
1846 Maybe
<Range
<T
>> ValidateSubrange(const Range
<T
>& data
, size_t elemOffset
,
1847 size_t elemLengthOverride
= 0) const {
1849 if (elemOffset
> ret
.length()) {
1850 EnqueueError(LOCAL_GL_INVALID_VALUE
,
1851 "`elemOffset` too large for `data`.");
1854 ret
= {ret
.begin() + elemOffset
, ret
.end()};
1855 if (elemLengthOverride
) {
1856 if (elemLengthOverride
> ret
.length()) {
1858 LOCAL_GL_INVALID_VALUE
,
1859 "`elemLengthOverride` too large for `data` and `elemOffset`.");
1862 ret
= {ret
.begin().get(), elemLengthOverride
};
1868 #define _(T, type_t, TYPE) \
1869 void Uniform1##T(const WebGLUniformLocationJS* const loc, type_t x) const { \
1870 const type_t arr[] = {x}; \
1871 UniformData(TYPE, loc, false, MakeByteRange(arr)); \
1873 void Uniform2##T(const WebGLUniformLocationJS* const loc, type_t x, \
1875 const type_t arr[] = {x, y}; \
1876 UniformData(TYPE##_VEC2, loc, false, MakeByteRange(arr)); \
1878 void Uniform3##T(const WebGLUniformLocationJS* const loc, type_t x, \
1879 type_t y, type_t z) const { \
1880 const type_t arr[] = {x, y, z}; \
1881 UniformData(TYPE##_VEC3, loc, false, MakeByteRange(arr)); \
1883 void Uniform4##T(const WebGLUniformLocationJS* const loc, type_t x, \
1884 type_t y, type_t z, type_t w) const { \
1885 const type_t arr[] = {x, y, z, w}; \
1886 UniformData(TYPE##_VEC4, loc, false, MakeByteRange(arr)); \
1889 _(f
, float, LOCAL_GL_FLOAT
)
1890 _(i
, int32_t, LOCAL_GL_INT
)
1891 _(ui
, uint32_t, LOCAL_GL_UNSIGNED_INT
)
1897 #define _(NT, TypeListU, TYPE) \
1898 void Uniform##NT##v(const WebGLUniformLocationJS* const loc, \
1899 const TypeListU& list, GLuint elemOffset = 0, \
1900 GLuint elemCountOverride = 0) const { \
1901 UniformData(TYPE, loc, false, MakeByteRange(list), elemOffset, \
1902 elemCountOverride); \
1905 _(1f
, Float32ListU
, LOCAL_GL_FLOAT
)
1906 _(2f
, Float32ListU
, LOCAL_GL_FLOAT_VEC2
)
1907 _(3f
, Float32ListU
, LOCAL_GL_FLOAT_VEC3
)
1908 _(4f
, Float32ListU
, LOCAL_GL_FLOAT_VEC4
)
1909 _(1i
, Int32ListU
, LOCAL_GL_INT
)
1910 _(2i
, Int32ListU
, LOCAL_GL_INT_VEC2
)
1911 _(3i
, Int32ListU
, LOCAL_GL_INT_VEC3
)
1912 _(4i
, Int32ListU
, LOCAL_GL_INT_VEC4
)
1913 _(1ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT
)
1914 _(2ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC2
)
1915 _(3ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC3
)
1916 _(4ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC4
)
1923 void UniformMatrix##X##fv(const WebGLUniformLocationJS* loc, bool transpose, \
1924 const Float32ListU& list, GLuint elemOffset = 0, \
1925 GLuint elemCountOverride = 0) const { \
1926 UniformData(LOCAL_GL_FLOAT_MAT##X, loc, transpose, MakeByteRange(list), \
1927 elemOffset, elemCountOverride); \
1946 void EnableVertexAttribArray(GLuint index
);
1948 void DisableVertexAttribArray(GLuint index
);
1950 WebGLsizeiptr
GetVertexAttribOffset(GLuint index
, GLenum pname
);
1955 void VertexAttrib4Tv(GLuint index
, webgl::AttribBaseType
,
1956 const Range
<const uint8_t>&);
1959 void VertexAttrib1f(GLuint index
, GLfloat x
) {
1960 VertexAttrib4f(index
, x
, 0, 0, 1);
1962 void VertexAttrib2f(GLuint index
, GLfloat x
, GLfloat y
) {
1963 VertexAttrib4f(index
, x
, y
, 0, 1);
1965 void VertexAttrib3f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
) {
1966 VertexAttrib4f(index
, x
, y
, z
, 1);
1969 void VertexAttrib4f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
,
1971 const float arr
[4] = {x
, y
, z
, w
};
1972 VertexAttrib4Tv(index
, webgl::AttribBaseType::Float
, MakeByteRange(arr
));
1977 void VertexAttrib1fv(const GLuint index
, const Float32ListU
& list
) {
1978 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1979 if (IsContextLost()) return;
1981 const auto range
= MakeRange(list
);
1982 if (range
.length() < 1) {
1983 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=1.");
1987 VertexAttrib1f(index
, range
[0]);
1990 void VertexAttrib2fv(const GLuint index
, const Float32ListU
& list
) {
1991 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1992 if (IsContextLost()) return;
1994 const auto range
= MakeRange(list
);
1995 if (range
.length() < 2) {
1996 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=2.");
2000 VertexAttrib2f(index
, range
[0], range
[1]);
2003 void VertexAttrib3fv(const GLuint index
, const Float32ListU
& list
) {
2004 const FuncScope
funcScope(*this, "vertexAttrib1fv");
2005 if (IsContextLost()) return;
2007 const auto range
= MakeRange(list
);
2008 if (range
.length() < 3) {
2009 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=3.");
2013 VertexAttrib3f(index
, range
[0], range
[1], range
[2]);
2016 void VertexAttrib4fv(GLuint index
, const Float32ListU
& list
) {
2017 VertexAttrib4Tv(index
, webgl::AttribBaseType::Float
, MakeByteRange(list
));
2019 void VertexAttribI4iv(GLuint index
, const Int32ListU
& list
) {
2020 VertexAttrib4Tv(index
, webgl::AttribBaseType::Int
, MakeByteRange(list
));
2022 void VertexAttribI4uiv(GLuint index
, const Uint32ListU
& list
) {
2023 VertexAttrib4Tv(index
, webgl::AttribBaseType::Uint
, MakeByteRange(list
));
2026 void VertexAttribI4i(GLuint index
, GLint x
, GLint y
, GLint z
, GLint w
) {
2027 const int32_t arr
[4] = {x
, y
, z
, w
};
2028 VertexAttrib4Tv(index
, webgl::AttribBaseType::Int
, MakeByteRange(arr
));
2030 void VertexAttribI4ui(GLuint index
, GLuint x
, GLuint y
, GLuint z
, GLuint w
) {
2031 const uint32_t arr
[4] = {x
, y
, z
, w
};
2032 VertexAttrib4Tv(index
, webgl::AttribBaseType::Uint
, MakeByteRange(arr
));
2036 void VertexAttribPointerImpl(bool isFuncInt
, GLuint index
, GLint size
,
2037 GLenum type
, WebGLboolean normalized
,
2038 GLsizei iStride
, WebGLintptr iByteOffset
);
2041 void VertexAttribIPointer(GLuint index
, GLint size
, GLenum type
,
2042 GLsizei stride
, WebGLintptr byteOffset
) {
2043 VertexAttribPointerImpl(true, index
, size
, type
, false, stride
, byteOffset
);
2046 void VertexAttribPointer(GLuint index
, GLint size
, GLenum type
,
2047 WebGLboolean normalized
, GLsizei stride
,
2048 WebGLintptr byteOffset
) {
2049 VertexAttribPointerImpl(false, index
, size
, type
, normalized
, stride
,
2053 // -------------------------------- Drawing -------------------------------
2055 void DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
2056 DrawArraysInstanced(mode
, first
, count
, 1);
2059 void DrawElements(GLenum mode
, GLsizei count
, GLenum type
,
2060 WebGLintptr byteOffset
) {
2061 DrawElementsInstanced(mode
, count
, type
, byteOffset
, 1);
2064 void DrawRangeElements(GLenum mode
, GLuint start
, GLuint end
, GLsizei count
,
2065 GLenum type
, WebGLintptr byteOffset
) {
2066 const FuncScope
funcScope(*this, "drawRangeElements");
2068 EnqueueError(LOCAL_GL_INVALID_VALUE
, "end must be >= start.");
2071 DrawElementsInstanced(mode
, count
, type
, byteOffset
, 1);
2074 // ------------------------------ Readback -------------------------------
2076 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2077 GLenum format
, GLenum type
,
2078 const dom::Nullable
<dom::ArrayBufferView
>& maybeView
,
2079 dom::CallerType aCallerType
, ErrorResult
& out_error
) const {
2080 const FuncScope
funcScope(*this, "readPixels");
2081 if (!ValidateNonNull("pixels", maybeView
)) return;
2082 ReadPixels(x
, y
, width
, height
, format
, type
, maybeView
.Value(), 0,
2083 aCallerType
, out_error
);
2086 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2087 GLenum format
, GLenum type
, WebGLsizeiptr offset
,
2088 dom::CallerType aCallerType
, ErrorResult
& out_error
) const;
2090 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2091 GLenum format
, GLenum type
,
2092 const dom::ArrayBufferView
& dstData
, GLuint dstElemOffset
,
2093 dom::CallerType aCallerType
, ErrorResult
& out_error
) const;
2096 bool ReadPixels_SharedPrecheck(dom::CallerType aCallerType
,
2097 ErrorResult
& out_error
) const;
2099 // ------------------------------ Vertex Array ------------------------------
2101 void BindVertexArray(WebGLVertexArrayJS
*);
2103 void DrawArraysInstanced(GLenum mode
, GLint first
, GLsizei count
,
2106 void DrawElementsInstanced(GLenum mode
, GLsizei count
, GLenum type
,
2107 WebGLintptr offset
, GLsizei primcount
);
2109 void VertexAttribDivisor(GLuint index
, GLuint divisor
);
2111 // --------------------------------- GL Query
2112 // ---------------------------------
2114 void GetQuery(JSContext
*, GLenum target
, GLenum pname
,
2115 JS::MutableHandle
<JS::Value
> retval
) const;
2116 void GetQueryParameter(JSContext
*, WebGLQueryJS
&, GLenum pname
,
2117 JS::MutableHandle
<JS::Value
> retval
) const;
2118 void BeginQuery(GLenum target
, WebGLQueryJS
&);
2119 void EndQuery(GLenum target
);
2120 void QueryCounter(WebGLQueryJS
&, GLenum target
) const;
2122 // -------------------------------- Sampler -------------------------------
2124 void GetSamplerParameter(JSContext
*, const WebGLSamplerJS
&, GLenum pname
,
2125 JS::MutableHandle
<JS::Value
> retval
) const;
2127 void BindSampler(GLuint unit
, WebGLSamplerJS
*);
2128 void SamplerParameteri(WebGLSamplerJS
&, GLenum pname
, GLint param
) const;
2129 void SamplerParameterf(WebGLSamplerJS
&, GLenum pname
, GLfloat param
) const;
2131 // ------------------------------- GL Sync ---------------------------------
2133 GLenum
ClientWaitSync(WebGLSyncJS
&, GLbitfield flags
, GLuint64 timeout
) const;
2134 void GetSyncParameter(JSContext
*, WebGLSyncJS
&, GLenum pname
,
2135 JS::MutableHandle
<JS::Value
> retval
) const;
2136 void WaitSync(const WebGLSyncJS
&, GLbitfield flags
, GLint64 timeout
) const;
2138 // -------------------------- Transform Feedback ---------------------------
2140 void BindTransformFeedback(GLenum target
, WebGLTransformFeedbackJS
*);
2141 void BeginTransformFeedback(GLenum primitiveMode
);
2142 void EndTransformFeedback();
2143 void PauseTransformFeedback();
2144 void ResumeTransformFeedback();
2146 // -------------------------- Opaque Framebuffers ---------------------------
2148 void SetFramebufferIsInOpaqueRAF(WebGLFramebufferJS
*, bool);
2150 // ------------------------------ Extensions ------------------------------
2152 void GetSupportedExtensions(dom::Nullable
<nsTArray
<nsString
>>& retval
,
2153 dom::CallerType callerType
) const;
2155 bool IsSupported(WebGLExtensionID
, dom::CallerType callerType
=
2156 dom::CallerType::NonSystem
) const;
2158 void GetExtension(JSContext
* cx
, const nsAString
& name
,
2159 JS::MutableHandle
<JSObject
*> retval
,
2160 dom::CallerType callerType
, ErrorResult
& rv
);
2163 bool IsExtensionForbiddenForCaller(const WebGLExtensionID ext
,
2164 const dom::CallerType callerType
) const;
2166 RefPtr
<ClientWebGLExtensionBase
> GetExtension(WebGLExtensionID ext
,
2167 dom::CallerType callerType
);
2168 void RequestExtension(WebGLExtensionID
) const;
2171 bool IsExtensionEnabled(const WebGLExtensionID id
) const {
2172 return bool(mNotLost
->extensions
[UnderlyingValue(id
)]);
2175 void AddCompressedFormat(GLenum
);
2177 // ---------------------------- Misc Extensions ----------------------------
2179 void DrawBuffers(const dom::Sequence
<GLenum
>& buffers
);
2181 void GetSupportedProfilesASTC(
2182 dom::Nullable
<nsTArray
<nsString
>>& retval
) const;
2184 void MOZDebugGetParameter(JSContext
* cx
, GLenum pname
,
2185 JS::MutableHandle
<JS::Value
> retval
,
2187 GetParameter(cx
, pname
, retval
, rv
, true);
2190 // -------------------------------------------------------------------------
2191 // Client-side methods. Calls in the Host are forwarded to the client.
2192 // -------------------------------------------------------------------------
2194 void JsWarning(const std::string
&) const;
2196 // -------------------------------------------------------------------------
2197 // The cross-process communication mechanism
2198 // -------------------------------------------------------------------------
2200 template <typename ReturnType
>
2201 friend struct WebGLClientDispatcher
;
2203 template <typename MethodType
, MethodType method
, typename ReturnType
,
2205 friend ReturnType
RunOn(const ClientWebGLContext
& context
, Args
&&... aArgs
);
2207 // If we are running WebGL in this process then call the HostWebGLContext
2208 // method directly. Otherwise, dispatch over IPC.
2209 template <typename MethodType
, MethodType method
, typename
... Args
>
2210 void Run(Args
&&... aArgs
) const;
2212 // -------------------------------------------------------------------------
2213 // Helpers for DOM operations, composition, actors, etc
2214 // -------------------------------------------------------------------------
2217 // https://immersive-web.github.io/webxr/#xr-compatible
2218 bool IsXRCompatible() const;
2219 already_AddRefed
<dom::Promise
> MakeXRCompatible(ErrorResult
& aRv
);
2222 bool ShouldResistFingerprinting() const;
2224 uint32_t GetPrincipalHashValue() const;
2226 // Prepare the context for capture before compositing
2227 void BeginComposition();
2229 // Clean up the context after captured for compositing
2230 void EndComposition();
2232 mozilla::dom::Document
* GetOwnerDoc() const;
2234 mutable bool mResetLayer
= true;
2235 Maybe
<const WebGLContextOptions
> mInitialOptions
;
2236 bool mXRCompatible
= false;
2239 // used by DOM bindings in conjunction with GetParentObject
2240 inline nsISupports
* ToSupports(ClientWebGLContext
* webgl
) {
2241 return static_cast<nsICanvasRenderingContextInternal
*>(webgl
);
2244 const char* GetExtensionName(WebGLExtensionID
);
2248 inline bool webgl::ObjectJS::IsForContext(
2249 const ClientWebGLContext
& context
) const {
2250 const auto& notLost
= context
.mNotLost
;
2251 if (!notLost
) return false;
2252 if (notLost
.get() != mGeneration
.lock().get()) return false;
2256 void AutoJsWarning(const std::string
& utf8
);
2258 } // namespace mozilla
2260 #endif // CLIENTWEBGLCONTEXT_H_