1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef CLIENTWEBGLCONTEXT_H_
7 #define CLIENTWEBGLCONTEXT_H_
10 #include "mozilla/dom/ImageData.h"
11 #include "mozilla/Range.h"
12 #include "mozilla/RefCounted.h"
13 #include "nsICanvasRenderingContextInternal.h"
14 #include "nsWrapperCache.h"
15 #include "mozilla/dom/WebGLRenderingContextBinding.h"
16 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
17 #include "mozilla/layers/LayersSurfaces.h"
18 #include "WebGLFormats.h"
19 #include "WebGLStrongTypes.h"
20 #include "WebGLTypes.h"
22 #include "mozilla/Logging.h"
23 #include "WebGLCommandQueue.h"
26 #include <unordered_map>
27 #include <unordered_set>
32 class ClientWebGLExtensionBase
;
33 class HostWebGLContext
;
40 class AvailabilityRunnable
;
45 ////////////////////////////////////
47 class WebGLActiveInfoJS final
: public RefCounted
<WebGLActiveInfoJS
> {
49 MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLActiveInfoJS
)
51 const webgl::ActiveInfo mInfo
;
53 explicit WebGLActiveInfoJS(const webgl::ActiveInfo
& info
) : mInfo(info
) {}
55 virtual ~WebGLActiveInfoJS() = default;
60 GLint
Size() const { return static_cast<GLint
>(mInfo
.elemCount
); }
61 GLenum
Type() const { return mInfo
.elemType
; }
63 void GetName(nsString
& retval
) const { CopyUTF8toUTF16(mInfo
.name
, retval
); }
65 bool WrapObject(JSContext
*, JS::Handle
<JSObject
*>,
66 JS::MutableHandle
<JSObject
*>);
69 class WebGLShaderPrecisionFormatJS final
70 : public RefCounted
<WebGLShaderPrecisionFormatJS
> {
72 MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLShaderPrecisionFormatJS
)
74 const webgl::ShaderPrecisionFormat mInfo
;
76 explicit WebGLShaderPrecisionFormatJS(
77 const webgl::ShaderPrecisionFormat
& info
)
80 virtual ~WebGLShaderPrecisionFormatJS() = default;
82 GLint
RangeMin() const { return mInfo
.rangeMin
; }
83 GLint
RangeMax() const { return mInfo
.rangeMax
; }
84 GLint
Precision() const { return mInfo
.precision
; }
86 bool WrapObject(JSContext
*, JS::Handle
<JSObject
*>,
87 JS::MutableHandle
<JSObject
*>);
90 // -----------------------
92 class ClientWebGLContext
;
94 class WebGLFramebufferJS
;
97 class WebGLRenderbufferJS
;
100 class WebGLTextureJS
;
101 class WebGLTransformFeedbackJS
;
102 class WebGLVertexArrayJS
;
108 class ProgramKeepAlive final
{
109 friend class mozilla::WebGLProgramJS
;
111 WebGLProgramJS
* mParent
;
114 explicit ProgramKeepAlive(WebGLProgramJS
& parent
) : mParent(&parent
) {}
118 class ShaderKeepAlive final
{
119 friend class mozilla::WebGLShaderJS
;
121 const WebGLShaderJS
* mParent
;
124 explicit ShaderKeepAlive(const WebGLShaderJS
& parent
) : mParent(&parent
) {}
128 class ContextGenerationInfo final
{
130 ObjectId mLastId
= 0;
133 webgl::ExtensionBits mEnabledExtensions
;
134 RefPtr
<WebGLProgramJS
> mCurrentProgram
;
135 std::shared_ptr
<webgl::ProgramKeepAlive
> mProgramKeepAlive
;
136 mutable std::shared_ptr
<webgl::LinkResult
> mActiveLinkResult
;
138 RefPtr
<WebGLTransformFeedbackJS
> mDefaultTfo
;
139 RefPtr
<WebGLVertexArrayJS
> mDefaultVao
;
141 std::unordered_map
<GLenum
, RefPtr
<WebGLBufferJS
>> mBoundBufferByTarget
;
142 std::vector
<RefPtr
<WebGLBufferJS
>> mBoundUbos
;
143 RefPtr
<WebGLFramebufferJS
> mBoundDrawFb
;
144 RefPtr
<WebGLFramebufferJS
> mBoundReadFb
;
145 RefPtr
<WebGLRenderbufferJS
> mBoundRb
;
146 RefPtr
<WebGLTransformFeedbackJS
> mBoundTfo
;
147 RefPtr
<WebGLVertexArrayJS
> mBoundVao
;
148 std::unordered_map
<GLenum
, RefPtr
<WebGLQueryJS
>> mCurrentQueryByTarget
;
150 struct TexUnit final
{
151 RefPtr
<WebGLSamplerJS
> sampler
;
152 std::unordered_map
<GLenum
, RefPtr
<WebGLTextureJS
>> texByTarget
;
154 uint32_t mActiveTexUnit
= 0;
155 std::vector
<TexUnit
> mTexUnits
;
157 bool mTfActiveAndNotPaused
= false;
159 std::vector
<TypedQuad
> mGenericVertexAttribs
;
161 std::array
<bool, 4> mColorWriteMask
= {{true, true, true, true}};
162 std::array
<int32_t, 4> mScissor
= {};
163 std::array
<int32_t, 4> mViewport
= {};
164 std::array
<float, 4> mClearColor
= {{0, 0, 0, 0}};
165 std::array
<float, 4> mBlendColor
= {{0, 0, 0, 0}};
166 std::array
<float, 2> mDepthRange
= {{0, 1}};
167 webgl::PixelPackState mPixelPackState
;
168 WebGLPixelStore mPixelUnpackState
;
170 std::vector
<GLenum
> mCompressedTextureFormats
;
172 Maybe
<uvec2
> mDrawingBufferSize
;
174 ObjectId
NextId() { return mLastId
+= 1; }
179 // In the cross process case, the WebGL actor's ownership relationship looks
181 // ---------------------------------------------------------------------
182 // | ClientWebGLContext -> WebGLChild -> WebGLParent -> HostWebGLContext
183 // ---------------------------------------------------------------------
185 // where 'A -> B' means "A owns B"
187 struct NotLostData final
{
188 ClientWebGLContext
& context
;
189 webgl::InitContextResult info
;
191 RefPtr
<mozilla::dom::WebGLChild
> outOfProcess
;
192 UniquePtr
<HostWebGLContext
> inProcess
;
194 webgl::ContextGenerationInfo state
;
195 std::array
<RefPtr
<ClientWebGLExtensionBase
>,
196 UnderlyingValue(WebGLExtensionID::Max
)>
199 explicit NotLostData(ClientWebGLContext
& context
);
206 friend ClientWebGLContext
;
209 const std::weak_ptr
<NotLostData
> mGeneration
;
213 bool mDeleteRequested
= false;
215 explicit ObjectJS(const ClientWebGLContext
&);
216 virtual ~ObjectJS() = default;
219 ClientWebGLContext
* Context() const {
220 const auto locked
= mGeneration
.lock();
221 if (!locked
) return nullptr;
222 return &(locked
->context
);
225 ClientWebGLContext
* GetParentObject() const { return Context(); }
228 bool IsForContext(const ClientWebGLContext
&) const;
229 virtual bool IsDeleted() const { return mDeleteRequested
; }
231 bool IsUsable(const ClientWebGLContext
& context
) const {
232 return IsForContext(context
) && !IsDeleted();
236 bool ValidateUsable(const ClientWebGLContext
& context
,
237 const char* const argName
) const {
238 if (MOZ_LIKELY(IsUsable(context
))) return true;
239 WarnInvalidUse(context
, argName
);
244 bool ValidateForContext(const ClientWebGLContext
& context
,
245 const char* const argName
) const;
248 void WarnInvalidUse(const ClientWebGLContext
&, const char* argName
) const;
250 // The enum is INVALID_VALUE for Program/Shader :(
251 virtual GLenum
ErrorOnDeleted() const { return LOCAL_GL_INVALID_OPERATION
; }
256 // -------------------------
258 class WebGLBufferJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
259 friend class ClientWebGLContext
;
261 webgl::BufferKind mKind
=
262 webgl::BufferKind::Undefined
; // !IsBuffer until Bind
265 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLBufferJS
)
266 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLBufferJS
)
268 explicit WebGLBufferJS(const ClientWebGLContext
& webgl
)
269 : webgl::ObjectJS(webgl
) {}
272 ~WebGLBufferJS() = default;
275 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
280 class WebGLFramebufferJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
281 friend class ClientWebGLContext
;
284 struct Attachment final
{
285 RefPtr
<WebGLRenderbufferJS
> rb
;
286 RefPtr
<WebGLTextureJS
> tex
;
290 bool mHasBeenBound
= false; // !IsFramebuffer until Bind
291 std::unordered_map
<GLenum
, Attachment
> mAttachments
;
294 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebufferJS
)
295 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebufferJS
)
297 explicit WebGLFramebufferJS(const ClientWebGLContext
&, bool opaque
= false);
300 bool mInOpaqueRAF
= false;
303 ~WebGLFramebufferJS() = default;
305 void EnsureColorAttachments();
308 Attachment
* GetAttachment(const GLenum slotEnum
) {
309 auto ret
= MaybeFind(mAttachments
, slotEnum
);
311 EnsureColorAttachments();
312 ret
= MaybeFind(mAttachments
, slotEnum
);
317 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
322 class WebGLProgramJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
323 friend class ClientWebGLContext
;
326 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLProgramJS
)
327 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLProgramJS
)
329 // If the REFCOUNTING macro isn't declared first, the AddRef at
330 // mInnerRef->js will panic when REFCOUNTING's "owning thread" var is still
333 struct Attachment final
{
334 RefPtr
<WebGLShaderJS
> shader
;
335 std::shared_ptr
<webgl::ShaderKeepAlive
> keepAlive
;
339 std::shared_ptr
<webgl::ProgramKeepAlive
> mKeepAlive
;
340 const std::weak_ptr
<webgl::ProgramKeepAlive
> mKeepAliveWeak
;
342 std::unordered_map
<GLenum
, Attachment
> mNextLink_Shaders
;
343 bool mLastValidate
= false;
344 mutable std::shared_ptr
<webgl::LinkResult
>
345 mResult
; // Never null, often defaulted.
347 struct UniformLocInfo final
{
348 const uint32_t location
;
349 const GLenum elemType
;
352 mutable Maybe
<std::unordered_map
<std::string
, UniformLocInfo
>>
354 mutable std::vector
<uint32_t> mUniformBlockBindings
;
356 std::unordered_set
<const WebGLTransformFeedbackJS
*> mActiveTfos
;
358 explicit WebGLProgramJS(const ClientWebGLContext
&);
361 mKeepAlive
= nullptr; // Try to delete.
363 const auto& maybe
= mKeepAliveWeak
.lock();
365 maybe
->mParent
= nullptr;
370 bool IsDeleted() const override
{ return !mKeepAliveWeak
.lock(); }
371 GLenum
ErrorOnDeleted() const override
{ return LOCAL_GL_INVALID_VALUE
; }
373 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
378 class WebGLQueryJS final
: public nsWrapperCache
,
379 public webgl::ObjectJS
,
380 public SupportsWeakPtr
{
381 friend class ClientWebGLContext
;
382 friend class webgl::AvailabilityRunnable
;
384 GLenum mTarget
= 0; // !IsQuery until Bind
385 bool mCanBeAvailable
= false;
388 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLQueryJS
)
389 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLQueryJS
)
391 explicit WebGLQueryJS(const ClientWebGLContext
& webgl
)
392 : webgl::ObjectJS(webgl
) {}
395 ~WebGLQueryJS() = default;
398 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
403 class WebGLRenderbufferJS final
: public nsWrapperCache
,
404 public webgl::ObjectJS
{
405 friend class ClientWebGLContext
;
408 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLRenderbufferJS
)
409 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLRenderbufferJS
)
412 bool mHasBeenBound
= false; // !IsRenderbuffer until Bind
414 explicit WebGLRenderbufferJS(const ClientWebGLContext
& webgl
)
415 : webgl::ObjectJS(webgl
) {}
416 ~WebGLRenderbufferJS() = default;
419 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
424 class WebGLSamplerJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
425 // IsSampler without Bind
427 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSamplerJS
)
428 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSamplerJS
)
430 explicit WebGLSamplerJS(const ClientWebGLContext
& webgl
)
431 : webgl::ObjectJS(webgl
) {}
434 ~WebGLSamplerJS() = default;
437 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
442 class WebGLShaderJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
443 friend class ClientWebGLContext
;
446 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLShaderJS
)
447 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLShaderJS
)
452 std::shared_ptr
<webgl::ShaderKeepAlive
> mKeepAlive
;
453 const std::weak_ptr
<webgl::ShaderKeepAlive
> mKeepAliveWeak
;
455 mutable webgl::CompileResult mResult
;
457 WebGLShaderJS(const ClientWebGLContext
&, GLenum type
);
460 mKeepAlive
= nullptr; // Try to delete.
462 const auto& maybe
= mKeepAliveWeak
.lock();
464 maybe
->mParent
= nullptr;
469 bool IsDeleted() const override
{ return !mKeepAliveWeak
.lock(); }
470 GLenum
ErrorOnDeleted() const override
{ return LOCAL_GL_INVALID_VALUE
; }
472 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
477 class WebGLSyncJS final
: public nsWrapperCache
,
478 public webgl::ObjectJS
,
479 public SupportsWeakPtr
{
480 friend class ClientWebGLContext
;
481 friend class webgl::AvailabilityRunnable
;
483 bool mCanBeAvailable
= false;
484 bool mSignaled
= false;
487 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSyncJS
)
488 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSyncJS
)
490 explicit WebGLSyncJS(const ClientWebGLContext
& webgl
)
491 : webgl::ObjectJS(webgl
) {}
494 ~WebGLSyncJS() = default;
497 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
502 class WebGLTextureJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
503 friend class ClientWebGLContext
;
505 GLenum mTarget
= 0; // !IsTexture until Bind
508 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTextureJS
)
509 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTextureJS
)
511 explicit WebGLTextureJS(const ClientWebGLContext
& webgl
)
512 : webgl::ObjectJS(webgl
) {}
515 ~WebGLTextureJS() = default;
518 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
523 class WebGLTransformFeedbackJS final
: public nsWrapperCache
,
524 public webgl::ObjectJS
{
525 friend class ClientWebGLContext
;
527 bool mHasBeenBound
= false; // !IsTransformFeedback until Bind
528 bool mActiveOrPaused
= false;
529 std::vector
<RefPtr
<WebGLBufferJS
>> mAttribBuffers
;
530 RefPtr
<WebGLProgramJS
> mActiveProgram
;
531 std::shared_ptr
<webgl::ProgramKeepAlive
> mActiveProgramKeepAlive
;
534 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTransformFeedbackJS
)
535 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTransformFeedbackJS
)
537 explicit WebGLTransformFeedbackJS(const ClientWebGLContext
&);
540 ~WebGLTransformFeedbackJS() = default;
543 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
548 std::array
<uint16_t, 3> ValidUploadElemTypes(GLenum
);
550 class WebGLUniformLocationJS final
: public nsWrapperCache
,
551 public webgl::ObjectJS
{
552 friend class ClientWebGLContext
;
554 const std::weak_ptr
<webgl::LinkResult
> mParent
;
555 const uint32_t mLocation
;
556 const std::array
<uint16_t, 3> mValidUploadElemTypes
;
559 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLUniformLocationJS
)
560 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLUniformLocationJS
)
562 WebGLUniformLocationJS(const ClientWebGLContext
& webgl
,
563 std::weak_ptr
<webgl::LinkResult
> parent
, uint32_t loc
,
565 : webgl::ObjectJS(webgl
),
568 mValidUploadElemTypes(ValidUploadElemTypes(elemType
)) {}
571 ~WebGLUniformLocationJS() = default;
574 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
579 class WebGLVertexArrayJS final
: public nsWrapperCache
, public webgl::ObjectJS
{
580 friend class ClientWebGLContext
;
582 bool mHasBeenBound
= false; // !IsVertexArray until Bind
583 RefPtr
<WebGLBufferJS
> mIndexBuffer
;
584 std::vector
<RefPtr
<WebGLBufferJS
>> mAttribBuffers
;
587 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLVertexArrayJS
)
588 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLVertexArrayJS
)
590 explicit WebGLVertexArrayJS(const ClientWebGLContext
&);
593 ~WebGLVertexArrayJS() = default;
596 JSObject
* WrapObject(JSContext
*, JS::Handle
<JSObject
*>) override
;
599 ////////////////////////////////////
601 typedef dom::MaybeSharedFloat32ArrayOrUnrestrictedFloatSequence Float32ListU
;
602 typedef dom::MaybeSharedInt32ArrayOrLongSequence Int32ListU
;
603 typedef dom::MaybeSharedUint32ArrayOrUnsignedLongSequence Uint32ListU
;
605 inline Range
<const float> MakeRange(const Float32ListU
& list
) {
606 if (list
.IsFloat32Array()) return MakeRangeAbv(list
.GetAsFloat32Array());
608 return MakeRange(list
.GetAsUnrestrictedFloatSequence());
611 inline Range
<const int32_t> MakeRange(const Int32ListU
& list
) {
612 if (list
.IsInt32Array()) return MakeRangeAbv(list
.GetAsInt32Array());
614 return MakeRange(list
.GetAsLongSequence());
617 inline Range
<const uint32_t> MakeRange(const Uint32ListU
& list
) {
618 if (list
.IsUint32Array()) return MakeRangeAbv(list
.GetAsUint32Array());
620 return MakeRange(list
.GetAsUnsignedLongSequence());
623 template <typename T
>
624 inline Range
<const uint8_t> MakeByteRange(const T
& x
) {
625 const auto typed
= MakeRange(x
);
626 return Range
<const uint8_t>(
627 reinterpret_cast<const uint8_t*>(typed
.begin().get()),
628 typed
.length() * sizeof(typed
[0]));
633 struct TexImageSourceAdapter final
: public TexImageSource
{
634 TexImageSourceAdapter(const dom::Nullable
<dom::ArrayBufferView
>* maybeView
,
636 if (!maybeView
->IsNull()) {
637 mView
= &(maybeView
->Value());
641 TexImageSourceAdapter(const dom::Nullable
<dom::ArrayBufferView
>* maybeView
,
642 GLuint viewElemOffset
) {
643 if (!maybeView
->IsNull()) {
644 mView
= &(maybeView
->Value());
646 mViewElemOffset
= viewElemOffset
;
649 TexImageSourceAdapter(const dom::ArrayBufferView
* view
, ErrorResult
*) {
653 TexImageSourceAdapter(const dom::ArrayBufferView
* view
, GLuint viewElemOffset
,
654 GLuint viewElemLengthOverride
= 0) {
656 mViewElemOffset
= viewElemOffset
;
657 mViewElemLengthOverride
= viewElemLengthOverride
;
660 explicit TexImageSourceAdapter(const WebGLintptr
* pboOffset
,
661 GLuint ignored1
= 0, GLuint ignored2
= 0) {
662 mPboOffset
= pboOffset
;
665 TexImageSourceAdapter(const WebGLintptr
* pboOffset
, ErrorResult
* ignored
) {
666 mPboOffset
= pboOffset
;
669 TexImageSourceAdapter(const dom::ImageBitmap
* imageBitmap
,
670 ErrorResult
* out_error
) {
671 mImageBitmap
= imageBitmap
;
672 mOut_error
= out_error
;
675 TexImageSourceAdapter(const dom::ImageData
* imageData
, ErrorResult
*) {
676 mImageData
= imageData
;
679 TexImageSourceAdapter(const dom::Element
* domElem
,
680 ErrorResult
* const out_error
) {
682 mOut_error
= out_error
;
687 * Base class for all IDL implementations of WebGLContext
689 class ClientWebGLContext final
: public nsICanvasRenderingContextInternal
,
690 public nsWrapperCache
,
691 public SupportsWeakPtr
{
692 friend class webgl::AvailabilityRunnable
;
693 friend class webgl::ObjectJS
;
694 friend class webgl::ProgramKeepAlive
;
695 friend class webgl::ShaderKeepAlive
;
697 // ----------------------------- Lifetime and DOM ---------------------------
699 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
700 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ClientWebGLContext
)
702 JSObject
* WrapObject(JSContext
* cx
,
703 JS::Handle
<JSObject
*> givenProto
) override
{
705 return dom::WebGL2RenderingContext_Binding::Wrap(cx
, this, givenProto
);
707 return dom::WebGLRenderingContext_Binding::Wrap(cx
, this, givenProto
);
713 const bool mIsWebGL2
;
716 bool mIsCanvasDirty
= false;
717 uvec2 mRequestedSize
= {};
720 explicit ClientWebGLContext(bool webgl2
);
723 virtual ~ClientWebGLContext();
725 const RefPtr
<ClientWebGLExtensionLoseContext
> mExtLoseContext
;
727 mutable std::shared_ptr
<webgl::NotLostData
> mNotLost
;
728 mutable GLenum mNextError
= 0;
729 mutable webgl::LossStatus mLossStatus
= webgl::LossStatus::Ready
;
730 mutable bool mAwaitingRestore
= false;
735 const auto& Limits() const { return mNotLost
->info
.limits
; }
736 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#actual-context-parameters
737 const WebGLContextOptions
& ActualContextParameters() const {
738 MOZ_ASSERT(mNotLost
!= nullptr);
739 return mNotLost
->info
.options
;
742 auto& State() { return mNotLost
->state
; }
743 const auto& State() const {
744 return const_cast<ClientWebGLContext
*>(this)->State();
750 mutable RefPtr
<webgl::AvailabilityRunnable
> mAvailabilityRunnable
;
753 webgl::AvailabilityRunnable
& EnsureAvailabilityRunnable() const;
758 void EmulateLoseContext() const;
759 void OnContextLoss(webgl::ContextLossReason
) const;
760 void RestoreContext(webgl::LossStatus requiredStatus
) const;
763 bool DispatchEvent(const nsAString
&) const;
764 void Event_webglcontextlost() const;
765 void Event_webglcontextrestored() const;
767 bool CreateHostContext(const uvec2
& requestedSize
);
768 void ThrowEvent_WebGLContextCreationError(const std::string
&) const;
771 void MarkCanvasDirty();
773 void MarkContextClean() override
{}
775 void OnBeforePaintTransaction() override
;
776 ClientWebGLContext
* AsWebgl() override
{ return this; }
778 mozilla::dom::WebGLChild
* GetChild() const {
779 if (!mNotLost
) return nullptr;
780 if (!mNotLost
->outOfProcess
) return nullptr;
781 return mNotLost
->outOfProcess
.get();
784 // -------------------------------------------------------------------------
785 // Client WebGL API call tracking and error message reporting
786 // -------------------------------------------------------------------------
788 // Remembers the WebGL function that is lowest on the stack for client-side
790 class FuncScope final
{
792 const ClientWebGLContext
& mWebGL
;
793 const char* const mFuncName
;
794 const FuncScopeId mId
;
796 FuncScope(const ClientWebGLContext
& webgl
, const char* funcName
)
799 mId(FuncScopeId::FuncScopeIdError
) {
800 // Only set if an "outer" scope hasn't already been set.
801 if (!mWebGL
.mFuncScope
) {
802 mWebGL
.mFuncScope
= this;
806 FuncScope(const ClientWebGLContext
* webgl
, FuncScopeId aId
)
807 : mWebGL(*webgl
), mFuncName(GetFuncScopeName(aId
)), mId(aId
) {
808 mWebGL
.mFuncScope
= this;
812 if (this == mWebGL
.mFuncScope
) {
813 mWebGL
.mFuncScope
= nullptr;
819 // The scope of the function at the top of the current WebGL function call
821 mutable FuncScope
* mFuncScope
= nullptr;
823 const auto& CurFuncScope() const { return *mFuncScope
; }
824 FuncScopeId
GetFuncScopeId() const {
825 return mFuncScope
? mFuncScope
->mId
: FuncScopeId::FuncScopeIdError
;
827 const char* FuncName() const {
828 return mFuncScope
? mFuncScope
->mFuncName
: nullptr;
832 template <typename
... Args
>
833 void EnqueueError(const GLenum error
, const char* const format
,
834 const Args
&... args
) const {
835 MOZ_ASSERT(FuncName());
837 text
.AppendPrintf("WebGL warning: %s: ", FuncName());
840 # pragma clang diagnostic push
841 # pragma clang diagnostic ignored "-Wformat-security"
842 #elif defined(__GNUC__)
843 # pragma GCC diagnostic push
844 # pragma GCC diagnostic ignored "-Wformat-security"
846 text
.AppendPrintf(format
, args
...);
848 # pragma clang diagnostic pop
849 #elif defined(__GNUC__)
850 # pragma GCC diagnostic pop
853 EnqueueErrorImpl(error
, text
);
856 void EnqueueError(const webgl::ErrorInfo
& info
) const {
857 EnqueueError(info
.type
, "%s", info
.info
.c_str());
860 template <typename
... Args
>
861 void EnqueueWarning(const char* const format
, const Args
&... args
) const {
862 EnqueueError(0, format
, args
...);
865 template <typename
... Args
>
866 void EnqueuePerfWarning(const char* const format
, const Args
&... args
) const {
867 EnqueueError(webgl::kErrorPerfWarning
, format
, args
...);
870 void EnqueueError_ArgEnum(const char* argName
,
871 GLenum val
) const; // Cold code.
874 void EnqueueErrorImpl(GLenum errorOrZero
, const nsACString
&) const;
877 bool ValidateArrayBufferView(const dom::ArrayBufferView
& view
,
878 GLuint elemOffset
, GLuint elemCountOverride
,
879 const GLenum errorEnum
,
880 uint8_t** const out_bytes
,
881 size_t* const out_byteLen
) const;
884 template <typename T
>
885 bool ValidateNonNull(const char* const argName
,
886 const dom::Nullable
<T
>& maybe
) const {
887 if (maybe
.IsNull()) {
888 EnqueueError(LOCAL_GL_INVALID_VALUE
, "%s: Cannot be null.", argName
);
894 bool ValidateNonNegative(const char* argName
, int64_t val
) const {
895 if (MOZ_UNLIKELY(val
< 0)) {
896 EnqueueError(LOCAL_GL_INVALID_VALUE
, "`%s` must be non-negative.",
903 bool ValidateViewType(GLenum unpackType
, const TexImageSource
& src
) const;
905 Maybe
<uvec3
> ValidateExtents(GLsizei width
, GLsizei height
, GLsizei depth
,
908 // -------------------------------------------------------------------------
909 // nsICanvasRenderingContextInternal / nsAPostRefreshObserver
910 // -------------------------------------------------------------------------
912 already_AddRefed
<layers::Layer
> GetCanvasLayer(
913 nsDisplayListBuilder
* builder
, layers::Layer
* oldLayer
,
914 layers::LayerManager
* manager
) override
;
915 bool InitializeCanvasRenderer(nsDisplayListBuilder
* aBuilder
,
916 layers::CanvasRenderer
* aRenderer
) override
;
917 // Note that 'clean' here refers to its invalidation state, not the
918 // contents of the buffer.
919 bool IsContextCleanForFrameCapture() override
{
920 return !mCapturedFrameInvalidated
;
922 void MarkContextCleanForFrameCapture() override
{
923 mCapturedFrameInvalidated
= false;
926 void OnMemoryPressure() override
;
928 SetContextOptions(JSContext
* cx
, JS::Handle
<JS::Value
> options
,
929 ErrorResult
& aRvForDictionaryInit
) override
;
931 SetDimensions(int32_t width
, int32_t height
) override
;
932 bool UpdateWebRenderCanvasData(
933 nsDisplayListBuilder
* aBuilder
,
934 layers::WebRenderCanvasData
* aCanvasData
) override
;
938 int32_t GetWidth() override
{ return AutoAssertCast(DrawingBufferSize().x
); }
939 int32_t GetHeight() override
{ return AutoAssertCast(DrawingBufferSize().y
); }
941 NS_IMETHOD
InitializeWithDrawTarget(nsIDocShell
*,
942 NotNull
<gfx::DrawTarget
*>) override
{
943 return NS_ERROR_NOT_IMPLEMENTED
;
946 NS_IMETHOD
Reset() override
{
947 /* (InitializeWithSurface) */
948 return NS_ERROR_NOT_IMPLEMENTED
;
951 UniquePtr
<uint8_t[]> GetImageBuffer(int32_t* out_format
) override
;
952 NS_IMETHOD
GetInputStream(const char* mimeType
,
953 const nsAString
& encoderOptions
,
954 nsIInputStream
** out_stream
) override
;
956 already_AddRefed
<mozilla::gfx::SourceSurface
> GetSurfaceSnapshot(
957 gfxAlphaType
* out_alphaType
) override
;
959 void SetOpaqueValueFromOpaqueAttr(bool) override
{};
960 bool GetIsOpaque() override
{ return !mInitialOptions
->alpha
; }
962 NS_IMETHOD
SetIsIPC(bool) override
{ return NS_ERROR_NOT_IMPLEMENTED
; }
965 * An abstract base class to be implemented by callers wanting to be notified
966 * that a refresh has occurred. Callers must ensure an observer is removed
967 * before it is destroyed.
969 void DidRefresh() override
;
971 NS_IMETHOD
Redraw(const gfxRect
&) override
{
972 return NS_ERROR_NOT_IMPLEMENTED
;
978 layers::LayersBackend
GetCompositorBackendType() const;
980 bool mCapturedFrameInvalidated
= false;
982 // -------------------------------------------------------------------------
983 // WebGLRenderingContext Basic Properties and Methods
984 // -------------------------------------------------------------------------
986 dom::HTMLCanvasElement
* GetCanvas() const { return mCanvasElement
; }
989 dom::Nullable
<dom::OwningHTMLCanvasElementOrOffscreenCanvas
>& retval
);
991 GLsizei
DrawingBufferWidth() {
992 const FuncScope
funcScope(*this, "drawingBufferWidth");
993 return AutoAssertCast(DrawingBufferSize().x
);
995 GLsizei
DrawingBufferHeight() {
996 const FuncScope
funcScope(*this, "drawingBufferHeight");
997 return AutoAssertCast(DrawingBufferSize().y
);
999 void GetContextAttributes(dom::Nullable
<dom::WebGLContextAttributes
>& retval
);
1001 void Present(WebGLFramebufferJS
*, layers::TextureType
,
1002 const bool webvr
= false);
1003 Maybe
<layers::SurfaceDescriptor
> GetFrontBuffer(WebGLFramebufferJS
*,
1004 const bool webvr
= false);
1005 RefPtr
<gfx::SourceSurface
> GetFrontBufferSnapshot(
1006 bool requireAlphaPremult
= true) override
;
1008 void ClearVRSwapChain();
1011 RefPtr
<gfx::DataSourceSurface
> BackBufferSnapshot();
1012 void DoReadPixels(const webgl::ReadPixelsDesc
&, Range
<uint8_t>) const;
1013 uvec2
DrawingBufferSize();
1015 void AfterDrawCall() {
1016 if (!mNotLost
) return;
1017 const auto& state
= State();
1018 if (!state
.mBoundDrawFb
) {
1023 // -------------------------------------------------------------------------
1024 // Client-side helper methods. Dispatch to a Host method.
1025 // -------------------------------------------------------------------------
1027 // ------------------------- GL State -------------------------
1029 bool IsContextLost() const { return !mNotLost
; }
1031 void Disable(GLenum cap
) const;
1032 void Enable(GLenum cap
) const;
1033 bool IsEnabled(GLenum cap
) const;
1036 Maybe
<double> GetNumber(GLenum pname
);
1037 Maybe
<std::string
> GetString(GLenum pname
);
1040 void GetParameter(JSContext
* cx
, GLenum pname
,
1041 JS::MutableHandle
<JS::Value
> retval
, ErrorResult
& rv
,
1042 bool debug
= false);
1044 void GetBufferParameter(JSContext
* cx
, GLenum target
, GLenum pname
,
1045 JS::MutableHandle
<JS::Value
> retval
) const;
1047 void GetFramebufferAttachmentParameter(JSContext
* cx
, GLenum target
,
1048 GLenum attachment
, GLenum pname
,
1049 JS::MutableHandle
<JS::Value
> retval
,
1050 ErrorResult
& rv
) const;
1052 void GetRenderbufferParameter(JSContext
* cx
, GLenum target
, GLenum pname
,
1053 JS::MutableHandle
<JS::Value
> retval
) const;
1055 void GetIndexedParameter(JSContext
* cx
, GLenum target
, GLuint index
,
1056 JS::MutableHandleValue retval
,
1057 ErrorResult
& rv
) const;
1059 already_AddRefed
<WebGLShaderPrecisionFormatJS
> GetShaderPrecisionFormat(
1060 GLenum shadertype
, GLenum precisiontype
);
1062 void UseProgram(WebGLProgramJS
*);
1063 void ValidateProgram(WebGLProgramJS
&) const;
1067 already_AddRefed
<WebGLBufferJS
> CreateBuffer() const;
1068 already_AddRefed
<WebGLFramebufferJS
> CreateFramebuffer() const;
1069 already_AddRefed
<WebGLFramebufferJS
> CreateOpaqueFramebuffer(
1070 const webgl::OpaqueFramebufferOptions
&) const;
1071 already_AddRefed
<WebGLProgramJS
> CreateProgram() const;
1072 already_AddRefed
<WebGLQueryJS
> CreateQuery() const;
1073 already_AddRefed
<WebGLRenderbufferJS
> CreateRenderbuffer() const;
1074 already_AddRefed
<WebGLSamplerJS
> CreateSampler() const;
1075 already_AddRefed
<WebGLShaderJS
> CreateShader(GLenum type
) const;
1076 already_AddRefed
<WebGLSyncJS
> FenceSync(GLenum condition
,
1077 GLbitfield flags
) const;
1078 already_AddRefed
<WebGLTextureJS
> CreateTexture() const;
1079 already_AddRefed
<WebGLTransformFeedbackJS
> CreateTransformFeedback() const;
1080 already_AddRefed
<WebGLVertexArrayJS
> CreateVertexArray() const;
1082 void DeleteBuffer(WebGLBufferJS
*);
1083 void DeleteFramebuffer(WebGLFramebufferJS
*, bool canDeleteOpaque
= false);
1084 void DeleteProgram(WebGLProgramJS
*) const;
1085 void DeleteQuery(WebGLQueryJS
*);
1086 void DeleteRenderbuffer(WebGLRenderbufferJS
*);
1087 void DeleteSampler(WebGLSamplerJS
*);
1088 void DeleteShader(WebGLShaderJS
*) const;
1089 void DeleteSync(WebGLSyncJS
*) const;
1090 void DeleteTexture(WebGLTextureJS
*);
1091 void DeleteTransformFeedback(WebGLTransformFeedbackJS
*);
1092 void DeleteVertexArray(WebGLVertexArrayJS
*);
1095 void DoDeleteProgram(WebGLProgramJS
&) const;
1096 void DoDeleteShader(const WebGLShaderJS
&) const;
1101 bool IsBuffer(const WebGLBufferJS
*) const;
1102 bool IsFramebuffer(const WebGLFramebufferJS
*) const;
1103 bool IsProgram(const WebGLProgramJS
*) const;
1104 bool IsQuery(const WebGLQueryJS
*) const;
1105 bool IsRenderbuffer(const WebGLRenderbufferJS
*) const;
1106 bool IsSampler(const WebGLSamplerJS
*) const;
1107 bool IsShader(const WebGLShaderJS
*) const;
1108 bool IsSync(const WebGLSyncJS
*) const;
1109 bool IsTexture(const WebGLTextureJS
*) const;
1110 bool IsTransformFeedback(const WebGLTransformFeedbackJS
*) const;
1111 bool IsVertexArray(const WebGLVertexArrayJS
*) const;
1117 const webgl::LinkResult
& GetLinkResult(const WebGLProgramJS
&) const;
1120 void AttachShader(WebGLProgramJS
&, WebGLShaderJS
&) const;
1121 void BindAttribLocation(WebGLProgramJS
&, GLuint location
,
1122 const nsAString
& name
) const;
1123 void DetachShader(WebGLProgramJS
&, const WebGLShaderJS
&) const;
1124 void GetAttachedShaders(
1125 const WebGLProgramJS
&,
1126 dom::Nullable
<nsTArray
<RefPtr
<WebGLShaderJS
>>>& retval
) const;
1127 void LinkProgram(WebGLProgramJS
&) const;
1128 void TransformFeedbackVaryings(WebGLProgramJS
&,
1129 const dom::Sequence
<nsString
>& varyings
,
1130 GLenum bufferMode
) const;
1131 void UniformBlockBinding(WebGLProgramJS
&, GLuint blockIndex
,
1132 GLuint blockBinding
) const;
1134 // Link result reflection
1135 already_AddRefed
<WebGLActiveInfoJS
> GetActiveAttrib(const WebGLProgramJS
&,
1137 already_AddRefed
<WebGLActiveInfoJS
> GetActiveUniform(const WebGLProgramJS
&,
1139 void GetActiveUniformBlockName(const WebGLProgramJS
&,
1140 GLuint uniformBlockIndex
,
1141 nsAString
& retval
) const;
1142 void GetActiveUniformBlockParameter(JSContext
* cx
, const WebGLProgramJS
&,
1143 GLuint uniformBlockIndex
, GLenum pname
,
1144 JS::MutableHandle
<JS::Value
> retval
,
1146 void GetActiveUniforms(JSContext
*, const WebGLProgramJS
&,
1147 const dom::Sequence
<GLuint
>& uniformIndices
,
1149 JS::MutableHandle
<JS::Value
> retval
) const;
1150 GLint
GetAttribLocation(const WebGLProgramJS
&, const nsAString
& name
) const;
1151 GLint
GetFragDataLocation(const WebGLProgramJS
&, const nsAString
& name
) const;
1152 void GetProgramInfoLog(const WebGLProgramJS
& prog
, nsAString
& retval
) const;
1153 void GetProgramParameter(JSContext
*, const WebGLProgramJS
&, GLenum pname
,
1154 JS::MutableHandle
<JS::Value
> retval
) const;
1155 already_AddRefed
<WebGLActiveInfoJS
> GetTransformFeedbackVarying(
1156 const WebGLProgramJS
&, GLuint index
);
1157 GLuint
GetUniformBlockIndex(const WebGLProgramJS
&,
1158 const nsAString
& uniformBlockName
) const;
1159 void GetUniformIndices(const WebGLProgramJS
&,
1160 const dom::Sequence
<nsString
>& uniformNames
,
1161 dom::Nullable
<nsTArray
<GLuint
>>& retval
) const;
1163 // WebGLUniformLocationJS
1164 already_AddRefed
<WebGLUniformLocationJS
> GetUniformLocation(
1165 const WebGLProgramJS
&, const nsAString
& name
) const;
1166 void GetUniform(JSContext
*, const WebGLProgramJS
&,
1167 const WebGLUniformLocationJS
&,
1168 JS::MutableHandle
<JS::Value
> retval
);
1174 const webgl::CompileResult
& GetCompileResult(const WebGLShaderJS
&) const;
1177 void CompileShader(WebGLShaderJS
&) const;
1178 void GetShaderInfoLog(const WebGLShaderJS
&, nsAString
& retval
) const;
1179 void GetShaderParameter(JSContext
*, const WebGLShaderJS
&, GLenum pname
,
1180 JS::MutableHandle
<JS::Value
> retval
) const;
1181 void GetShaderSource(const WebGLShaderJS
&, nsAString
& retval
) const;
1182 void GetTranslatedShaderSource(const WebGLShaderJS
& shader
,
1183 nsAString
& retval
) const;
1184 void ShaderSource(WebGLShaderJS
&, const nsAString
&) const;
1188 void BindFramebuffer(GLenum target
, WebGLFramebufferJS
*);
1190 void BlendColor(GLclampf r
, GLclampf g
, GLclampf b
, GLclampf a
);
1194 void BlendEquation(GLenum mode
) { BlendEquationSeparate(mode
, mode
); }
1195 void BlendFunc(GLenum sfactor
, GLenum dfactor
) {
1196 BlendFuncSeparate(sfactor
, dfactor
, sfactor
, dfactor
);
1199 void BlendEquationSeparate(GLenum modeRGB
, GLenum modeAlpha
);
1200 void BlendFuncSeparate(GLenum srcRGB
, GLenum dstRGB
, GLenum srcAlpha
,
1205 GLenum
CheckFramebufferStatus(GLenum target
);
1207 void Clear(GLbitfield mask
);
1212 void ClearBufferTv(GLenum buffer
, GLint drawBuffer
, webgl::AttribBaseType
,
1213 const Range
<const uint8_t>& view
, GLuint srcElemOffset
);
1216 void ClearBufferfv(GLenum buffer
, GLint drawBuffer
, const Float32ListU
& list
,
1217 GLuint srcElemOffset
) {
1218 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Float
,
1219 MakeByteRange(list
), srcElemOffset
);
1221 void ClearBufferiv(GLenum buffer
, GLint drawBuffer
, const Int32ListU
& list
,
1222 GLuint srcElemOffset
) {
1223 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Int
,
1224 MakeByteRange(list
), srcElemOffset
);
1226 void ClearBufferuiv(GLenum buffer
, GLint drawBuffer
, const Uint32ListU
& list
,
1227 GLuint srcElemOffset
) {
1228 ClearBufferTv(buffer
, drawBuffer
, webgl::AttribBaseType::Uint
,
1229 MakeByteRange(list
), srcElemOffset
);
1234 void ClearBufferfi(GLenum buffer
, GLint drawBuffer
, GLfloat depth
,
1237 void ClearColor(GLclampf r
, GLclampf g
, GLclampf b
, GLclampf a
);
1239 void ClearDepth(GLclampf v
);
1241 void ClearStencil(GLint v
);
1243 void ColorMask(WebGLboolean r
, WebGLboolean g
, WebGLboolean b
,
1246 void CullFace(GLenum face
);
1248 void DepthFunc(GLenum func
);
1250 void DepthMask(WebGLboolean b
);
1252 void DepthRange(GLclampf zNear
, GLclampf zFar
);
1258 void FrontFace(GLenum mode
);
1262 void Hint(GLenum target
, GLenum mode
);
1264 void LineWidth(GLfloat width
);
1266 void PixelStorei(GLenum pname
, GLint param
);
1268 void PolygonOffset(GLfloat factor
, GLfloat units
);
1270 void SampleCoverage(GLclampf value
, WebGLboolean invert
);
1272 void Scissor(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1276 void StencilFunc(GLenum func
, GLint ref
, GLuint mask
) {
1277 StencilFuncSeparate(LOCAL_GL_FRONT_AND_BACK
, func
, ref
, mask
);
1279 void StencilMask(GLuint mask
) {
1280 StencilMaskSeparate(LOCAL_GL_FRONT_AND_BACK
, mask
);
1282 void StencilOp(GLenum sfail
, GLenum dpfail
, GLenum dppass
) {
1283 StencilOpSeparate(LOCAL_GL_FRONT_AND_BACK
, sfail
, dpfail
, dppass
);
1286 void StencilFuncSeparate(GLenum face
, GLenum func
, GLint ref
, GLuint mask
);
1287 void StencilMaskSeparate(GLenum face
, GLuint mask
);
1288 void StencilOpSeparate(GLenum face
, GLenum sfail
, GLenum dpfail
,
1293 void Viewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1295 // ------------------------- Buffer Objects -------------------------
1297 void BindBuffer(GLenum target
, WebGLBufferJS
*);
1302 void BindBufferRangeImpl(const GLenum target
, const GLuint index
,
1303 WebGLBufferJS
* const buffer
, const uint64_t offset
,
1304 const uint64_t size
);
1307 void BindBufferBase(const GLenum target
, const GLuint index
,
1308 WebGLBufferJS
* const buffer
) {
1309 const FuncScope
funcScope(*this, "bindBufferBase");
1310 if (IsContextLost()) return;
1312 BindBufferRangeImpl(target
, index
, buffer
, 0, 0);
1315 void BindBufferRange(const GLenum target
, const GLuint index
,
1316 WebGLBufferJS
* const buffer
, const WebGLintptr offset
,
1317 const WebGLsizeiptr size
) {
1318 const FuncScope
funcScope(*this, "bindBufferRange");
1319 if (IsContextLost()) return;
1322 if (!ValidateNonNegative("offset", offset
)) return;
1325 EnqueueError(LOCAL_GL_INVALID_VALUE
,
1326 "`size` must be positive for non-null `buffer`.");
1331 BindBufferRangeImpl(target
, index
, buffer
, static_cast<uint64_t>(offset
),
1332 static_cast<uint64_t>(size
));
1337 void CopyBufferSubData(GLenum readTarget
, GLenum writeTarget
,
1338 GLintptr readOffset
, GLintptr writeOffset
,
1341 void BufferData(GLenum target
, WebGLsizeiptr size
, GLenum usage
);
1342 void BufferData(GLenum target
,
1343 const dom::Nullable
<dom::ArrayBuffer
>& maybeSrc
,
1345 void BufferData(GLenum target
, const dom::ArrayBufferView
& srcData
,
1346 GLenum usage
, GLuint srcElemOffset
= 0,
1347 GLuint srcElemCountOverride
= 0);
1349 void BufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1350 const dom::ArrayBufferView
& src
, GLuint srcElemOffset
= 0,
1351 GLuint srcElemCountOverride
= 0);
1352 void BufferSubData(GLenum target
, WebGLsizeiptr dstByteOffset
,
1353 const dom::ArrayBuffer
& src
);
1355 void GetBufferSubData(GLenum target
, GLintptr srcByteOffset
,
1356 const dom::ArrayBufferView
& dstData
,
1357 GLuint dstElemOffset
, GLuint dstElemCountOverride
);
1359 // -------------------------- Framebuffer Objects --------------------------
1361 void BlitFramebuffer(GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1362 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1363 GLbitfield mask
, GLenum filter
);
1368 // `bindTarget` if non-zero allows initializing the rb/tex with that target.
1369 void FramebufferAttach(GLenum target
, GLenum attachEnum
, GLenum bindTarget
,
1370 WebGLRenderbufferJS
*, WebGLTextureJS
*,
1371 uint32_t mipLevel
, uint32_t zLayer
,
1372 uint32_t numViewLayers
) const;
1375 void FramebufferRenderbuffer(GLenum target
, GLenum attachSlot
,
1376 GLenum rbTarget
, WebGLRenderbufferJS
* rb
) const {
1377 const FuncScope
funcScope(*this, "framebufferRenderbuffer");
1378 if (IsContextLost()) return;
1379 if (rbTarget
!= LOCAL_GL_RENDERBUFFER
) {
1380 EnqueueError_ArgEnum("rbTarget", rbTarget
);
1383 FramebufferAttach(target
, attachSlot
, rbTarget
, rb
, nullptr, 0, 0, 0);
1386 void FramebufferTexture2D(GLenum target
, GLenum attachSlot
,
1387 GLenum texImageTarget
, WebGLTextureJS
*,
1388 GLint mipLevel
) const;
1390 void FramebufferTextureLayer(GLenum target
, GLenum attachSlot
,
1391 WebGLTextureJS
* tex
, GLint mipLevel
,
1392 GLint zLayer
) const {
1393 const FuncScope
funcScope(*this, "framebufferTextureLayer");
1394 if (IsContextLost()) return;
1395 FramebufferAttach(target
, attachSlot
, 0, nullptr, tex
,
1396 static_cast<uint32_t>(mipLevel
),
1397 static_cast<uint32_t>(zLayer
), 0);
1400 void FramebufferTextureMultiview(GLenum target
, GLenum attachSlot
,
1401 WebGLTextureJS
* tex
, GLint mipLevel
,
1403 GLsizei numViewLayers
) const {
1404 const FuncScope
funcScope(*this, "framebufferTextureMultiview");
1405 if (IsContextLost()) return;
1406 if (tex
&& numViewLayers
< 1) {
1407 EnqueueError(LOCAL_GL_INVALID_VALUE
, "`numViewLayers` must be >=1.");
1410 FramebufferAttach(target
, attachSlot
, 0, nullptr, tex
,
1411 static_cast<uint32_t>(mipLevel
),
1412 static_cast<uint32_t>(zLayerBase
),
1413 static_cast<uint32_t>(numViewLayers
));
1418 void InvalidateFramebuffer(GLenum target
,
1419 const dom::Sequence
<GLenum
>& attachments
,
1420 ErrorResult
& unused
);
1421 void InvalidateSubFramebuffer(GLenum target
,
1422 const dom::Sequence
<GLenum
>& attachments
,
1423 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1424 ErrorResult
& unused
);
1426 void ReadBuffer(GLenum mode
);
1428 // ----------------------- Renderbuffer objects -----------------------
1429 void GetInternalformatParameter(JSContext
* cx
, GLenum target
,
1430 GLenum internalformat
, GLenum pname
,
1431 JS::MutableHandleValue retval
,
1434 void BindRenderbuffer(GLenum target
, WebGLRenderbufferJS
*);
1436 void RenderbufferStorage(GLenum target
, GLenum internalFormat
, GLsizei width
,
1437 GLsizei height
) const {
1438 RenderbufferStorageMultisample(target
, 0, internalFormat
, width
, height
);
1441 void RenderbufferStorageMultisample(GLenum target
, GLsizei samples
,
1442 GLenum internalFormat
, GLsizei width
,
1443 GLsizei height
) const;
1445 // --------------------------- Texture objects ---------------------------
1447 void ActiveTexture(GLenum texUnit
);
1449 void BindTexture(GLenum texTarget
, WebGLTextureJS
*);
1451 void GenerateMipmap(GLenum texTarget
) const;
1453 void GetTexParameter(JSContext
* cx
, GLenum texTarget
, GLenum pname
,
1454 JS::MutableHandle
<JS::Value
> retval
) const;
1456 void TexParameterf(GLenum texTarget
, GLenum pname
, GLfloat param
);
1457 void TexParameteri(GLenum texTarget
, GLenum pname
, GLint param
);
1462 void TexStorage(uint8_t funcDims
, GLenum target
, GLsizei levels
,
1463 GLenum internalFormat
, const ivec3
& size
) const;
1465 // Primitive tex upload functions
1466 void TexImage(uint8_t funcDims
, GLenum target
, GLint level
,
1467 GLenum respecFormat
, const ivec3
& offset
, const ivec3
& size
,
1468 GLint border
, const webgl::PackingInfo
& pi
,
1469 const TexImageSource
& src
) const;
1470 void CompressedTexImage(bool sub
, uint8_t funcDims
, GLenum target
,
1471 GLint level
, GLenum format
, const ivec3
& offset
,
1472 const ivec3
& size
, GLint border
,
1473 const TexImageSource
& src
,
1474 GLsizei pboImageSize
) const;
1475 void CopyTexImage(uint8_t funcDims
, GLenum target
, GLint level
,
1476 GLenum respecFormat
, const ivec3
& dstOffset
,
1477 const ivec2
& srcOffset
, const ivec2
& size
,
1478 GLint border
) const;
1481 void TexStorage2D(GLenum target
, GLsizei levels
, GLenum internalFormat
,
1482 GLsizei width
, GLsizei height
) const {
1483 TexStorage(2, target
, levels
, internalFormat
, {width
, height
, 1});
1486 void TexStorage3D(GLenum target
, GLsizei levels
, GLenum internalFormat
,
1487 GLsizei width
, GLsizei height
, GLsizei depth
) const {
1488 TexStorage(3, target
, levels
, internalFormat
, {width
, height
, depth
});
1491 ////////////////////////////////////
1493 template <typename T
> // TexImageSource or WebGLintptr
1494 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1495 GLsizei width
, GLsizei height
, GLint border
,
1496 GLenum unpackFormat
, GLenum unpackType
, const T
& anySrc
,
1497 ErrorResult
& out_error
) const {
1498 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1499 TexImage(2, target
, level
, internalFormat
, {0, 0, 0}, {width
, height
, 1},
1500 border
, {unpackFormat
, unpackType
}, src
);
1503 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1504 GLsizei width
, GLsizei height
, GLint border
,
1505 GLenum unpackFormat
, GLenum unpackType
,
1506 const dom::ArrayBufferView
& view
, GLuint viewElemOffset
,
1507 ErrorResult
&) const {
1508 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1509 TexImage(2, target
, level
, internalFormat
, {0, 0, 0}, {width
, height
, 1},
1510 border
, {unpackFormat
, unpackType
}, src
);
1515 template <typename T
> // TexImageSource or WebGLintptr
1516 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1517 GLsizei width
, GLsizei height
, GLenum unpackFormat
,
1518 GLenum unpackType
, const T
& anySrc
,
1519 ErrorResult
& out_error
) const {
1520 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1521 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0,
1522 {unpackFormat
, unpackType
}, src
);
1525 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1526 GLsizei width
, GLsizei height
, GLenum unpackFormat
,
1527 GLenum unpackType
, const dom::ArrayBufferView
& view
,
1528 GLuint viewElemOffset
, ErrorResult
&) const {
1529 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1530 TexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0,
1531 {unpackFormat
, unpackType
}, src
);
1536 template <typename T
> // TexImageSource or WebGLintptr
1537 void TexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1538 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
,
1539 GLenum unpackFormat
, GLenum unpackType
, const T
& anySrc
,
1540 ErrorResult
& out_error
) const {
1541 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1542 TexImage(3, target
, level
, internalFormat
, {0, 0, 0},
1543 {width
, height
, depth
}, border
, {unpackFormat
, unpackType
}, src
);
1546 void TexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1547 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
,
1548 GLenum unpackFormat
, GLenum unpackType
,
1549 const dom::ArrayBufferView
& view
, GLuint viewElemOffset
,
1550 ErrorResult
&) const {
1551 const TexImageSourceAdapter
src(&view
, viewElemOffset
);
1552 TexImage(3, target
, level
, internalFormat
, {0, 0, 0},
1553 {width
, height
, depth
}, border
, {unpackFormat
, unpackType
}, src
);
1558 template <typename T
> // TexImageSource or WebGLintptr
1559 void TexSubImage3D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1560 GLint zOffset
, GLsizei width
, GLsizei height
,
1561 GLsizei depth
, GLenum unpackFormat
, GLenum unpackType
,
1562 const T
& anySrc
, ErrorResult
& out_error
) const {
1563 const TexImageSourceAdapter
src(&anySrc
, &out_error
);
1564 TexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
},
1565 {width
, height
, depth
}, 0, {unpackFormat
, unpackType
}, src
);
1568 void TexSubImage3D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1569 GLint zOffset
, GLsizei width
, GLsizei height
,
1570 GLsizei depth
, GLenum unpackFormat
, GLenum unpackType
,
1571 const dom::Nullable
<dom::ArrayBufferView
>& maybeSrcView
,
1572 GLuint srcElemOffset
, ErrorResult
&) const {
1573 const TexImageSourceAdapter
src(&maybeSrcView
, srcElemOffset
);
1574 TexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
},
1575 {width
, height
, depth
}, 0, {unpackFormat
, unpackType
}, src
);
1578 ////////////////////////////////////
1581 void CompressedTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1582 GLsizei width
, GLsizei height
, GLint border
,
1583 GLsizei imageSize
, WebGLintptr offset
) const {
1584 const TexImageSourceAdapter
src(&offset
);
1585 CompressedTexImage(false, 2, target
, level
, internalFormat
, {0, 0, 0},
1586 {width
, height
, 1}, border
, src
, imageSize
);
1589 void CompressedTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1590 GLsizei width
, GLsizei height
, GLint border
,
1591 const dom::ArrayBufferView
& view
,
1592 GLuint viewElemOffset
= 0,
1593 GLuint viewElemLengthOverride
= 0) const {
1594 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1595 viewElemLengthOverride
);
1596 CompressedTexImage(false, 2, target
, level
, internalFormat
, {0, 0, 0},
1597 {width
, height
, 1}, border
, src
, 0);
1602 void CompressedTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1603 GLint yOffset
, GLsizei width
, GLsizei height
,
1604 GLenum unpackFormat
, GLsizei imageSize
,
1605 WebGLintptr offset
) const {
1606 const TexImageSourceAdapter
src(&offset
);
1607 CompressedTexImage(true, 2, target
, level
, unpackFormat
,
1608 {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0, src
,
1612 void CompressedTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1613 GLint yOffset
, GLsizei width
, GLsizei height
,
1614 GLenum unpackFormat
,
1615 const dom::ArrayBufferView
& view
,
1616 GLuint viewElemOffset
= 0,
1617 GLuint viewElemLengthOverride
= 0) const {
1618 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1619 viewElemLengthOverride
);
1620 CompressedTexImage(true, 2, target
, level
, unpackFormat
,
1621 {xOffset
, yOffset
, 0}, {width
, height
, 1}, 0, src
, 0);
1626 void CompressedTexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1627 GLsizei width
, GLsizei height
, GLsizei depth
,
1628 GLint border
, GLsizei imageSize
,
1629 WebGLintptr offset
) const {
1630 const TexImageSourceAdapter
src(&offset
);
1631 CompressedTexImage(false, 3, target
, level
, internalFormat
, {0, 0, 0},
1632 {width
, height
, depth
}, border
, src
, imageSize
);
1635 void CompressedTexImage3D(GLenum target
, GLint level
, GLenum internalFormat
,
1636 GLsizei width
, GLsizei height
, GLsizei depth
,
1637 GLint border
, const dom::ArrayBufferView
& view
,
1638 GLuint viewElemOffset
= 0,
1639 GLuint viewElemLengthOverride
= 0) const {
1640 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1641 viewElemLengthOverride
);
1642 CompressedTexImage(false, 3, target
, level
, internalFormat
, {0, 0, 0},
1643 {width
, height
, depth
}, border
, src
, 0);
1648 void CompressedTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1649 GLint yOffset
, GLint zOffset
, GLsizei width
,
1650 GLsizei height
, GLsizei depth
,
1651 GLenum unpackFormat
, GLsizei imageSize
,
1652 WebGLintptr offset
) const {
1653 const TexImageSourceAdapter
src(&offset
);
1654 CompressedTexImage(true, 3, target
, level
, unpackFormat
,
1655 {xOffset
, yOffset
, zOffset
}, {width
, height
, depth
}, 0,
1659 void CompressedTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1660 GLint yOffset
, GLint zOffset
, GLsizei width
,
1661 GLsizei height
, GLsizei depth
,
1662 GLenum unpackFormat
,
1663 const dom::ArrayBufferView
& view
,
1664 GLuint viewElemOffset
= 0,
1665 GLuint viewElemLengthOverride
= 0) const {
1666 const TexImageSourceAdapter
src(&view
, viewElemOffset
,
1667 viewElemLengthOverride
);
1668 CompressedTexImage(true, 3, target
, level
, unpackFormat
,
1669 {xOffset
, yOffset
, zOffset
}, {width
, height
, depth
}, 0,
1673 // --------------------
1675 void CopyTexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1676 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1677 GLint border
) const {
1678 CopyTexImage(2, target
, level
, internalFormat
, {0, 0, 0}, {x
, y
},
1679 {width
, height
}, border
);
1682 void CopyTexSubImage2D(GLenum target
, GLint level
, GLint xOffset
,
1683 GLint yOffset
, GLint x
, GLint y
, GLsizei width
,
1684 GLsizei height
) const {
1685 CopyTexImage(2, target
, level
, 0, {xOffset
, yOffset
, 0}, {x
, y
},
1686 {width
, height
}, 0);
1689 void CopyTexSubImage3D(GLenum target
, GLint level
, GLint xOffset
,
1690 GLint yOffset
, GLint zOffset
, GLint x
, GLint y
,
1691 GLsizei width
, GLsizei height
) const {
1692 CopyTexImage(3, target
, level
, 0, {xOffset
, yOffset
, zOffset
}, {x
, y
},
1693 {width
, height
}, 0);
1696 // -------------------
1697 // Forward legacy TexImageSource uploads for default width/height
1699 template <typename TexImageSourceT
>
1700 void TexImage2D(GLenum target
, GLint level
, GLenum internalFormat
,
1701 GLenum unpackFormat
, GLenum unpackType
,
1702 const TexImageSourceT
& anySrc
, ErrorResult
& out_error
) const {
1703 TexImage2D(target
, level
, internalFormat
, 0, 0, 0, unpackFormat
, unpackType
,
1707 template <typename TexImageSourceT
>
1708 void TexSubImage2D(GLenum target
, GLint level
, GLint xOffset
, GLint yOffset
,
1709 GLenum unpackFormat
, GLenum unpackType
,
1710 const TexImageSourceT
& anySrc
,
1711 ErrorResult
& out_error
) const {
1712 TexSubImage2D(target
, level
, xOffset
, yOffset
, 0, 0, unpackFormat
,
1713 unpackType
, anySrc
, out_error
);
1716 // ------------------------ Uniforms and attributes ------------------------
1719 Maybe
<double> GetVertexAttribPriv(GLuint index
, GLenum pname
);
1722 void GetVertexAttrib(JSContext
* cx
, GLuint index
, GLenum pname
,
1723 JS::MutableHandle
<JS::Value
> retval
, ErrorResult
& rv
);
1726 const webgl::LinkResult
* GetActiveLinkResult() const {
1727 const auto& state
= State();
1728 if (state
.mCurrentProgram
) {
1729 (void)GetLinkResult(*state
.mCurrentProgram
);
1731 return state
.mActiveLinkResult
.get();
1734 void UniformData(GLenum funcElemType
, const WebGLUniformLocationJS
* const loc
,
1735 bool transpose
, const Range
<const uint8_t>& bytes
,
1736 GLuint elemOffset
= 0, GLuint elemCountOverride
= 0) const;
1740 template <typename T
>
1741 Maybe
<Range
<T
>> ValidateSubrange(const Range
<T
>& data
, size_t elemOffset
,
1742 size_t elemLengthOverride
= 0) const {
1744 if (elemOffset
> ret
.length()) {
1745 EnqueueError(LOCAL_GL_INVALID_VALUE
,
1746 "`elemOffset` too large for `data`.");
1749 ret
= {ret
.begin() + elemOffset
, ret
.end()};
1750 if (elemLengthOverride
) {
1751 if (elemLengthOverride
> ret
.length()) {
1753 LOCAL_GL_INVALID_VALUE
,
1754 "`elemLengthOverride` too large for `data` and `elemOffset`.");
1757 ret
= {ret
.begin().get(), elemLengthOverride
};
1763 #define _(T, type_t, TYPE) \
1764 void Uniform1##T(const WebGLUniformLocationJS* const loc, type_t x) const { \
1765 const type_t arr[] = {x}; \
1766 UniformData(TYPE, loc, false, MakeByteRange(arr)); \
1768 void Uniform2##T(const WebGLUniformLocationJS* const loc, type_t x, \
1770 const type_t arr[] = {x, y}; \
1771 UniformData(TYPE##_VEC2, loc, false, MakeByteRange(arr)); \
1773 void Uniform3##T(const WebGLUniformLocationJS* const loc, type_t x, \
1774 type_t y, type_t z) const { \
1775 const type_t arr[] = {x, y, z}; \
1776 UniformData(TYPE##_VEC3, loc, false, MakeByteRange(arr)); \
1778 void Uniform4##T(const WebGLUniformLocationJS* const loc, type_t x, \
1779 type_t y, type_t z, type_t w) const { \
1780 const type_t arr[] = {x, y, z, w}; \
1781 UniformData(TYPE##_VEC4, loc, false, MakeByteRange(arr)); \
1784 _(f
, float, LOCAL_GL_FLOAT
)
1785 _(i
, int32_t, LOCAL_GL_INT
)
1786 _(ui
, uint32_t, LOCAL_GL_UNSIGNED_INT
)
1792 #define _(NT, TypeListU, TYPE) \
1793 void Uniform##NT##v(const WebGLUniformLocationJS* const loc, \
1794 const TypeListU& list, GLuint elemOffset = 0, \
1795 GLuint elemCountOverride = 0) const { \
1796 UniformData(TYPE, loc, false, MakeByteRange(list), elemOffset, \
1797 elemCountOverride); \
1800 _(1f
, Float32ListU
, LOCAL_GL_FLOAT
)
1801 _(2f
, Float32ListU
, LOCAL_GL_FLOAT_VEC2
)
1802 _(3f
, Float32ListU
, LOCAL_GL_FLOAT_VEC3
)
1803 _(4f
, Float32ListU
, LOCAL_GL_FLOAT_VEC4
)
1804 _(1i
, Int32ListU
, LOCAL_GL_INT
)
1805 _(2i
, Int32ListU
, LOCAL_GL_INT_VEC2
)
1806 _(3i
, Int32ListU
, LOCAL_GL_INT_VEC3
)
1807 _(4i
, Int32ListU
, LOCAL_GL_INT_VEC4
)
1808 _(1ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT
)
1809 _(2ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC2
)
1810 _(3ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC3
)
1811 _(4ui
, Uint32ListU
, LOCAL_GL_UNSIGNED_INT_VEC4
)
1818 void UniformMatrix##X##fv(const WebGLUniformLocationJS* loc, bool transpose, \
1819 const Float32ListU& list, GLuint elemOffset = 0, \
1820 GLuint elemCountOverride = 0) const { \
1821 UniformData(LOCAL_GL_FLOAT_MAT##X, loc, transpose, MakeByteRange(list), \
1822 elemOffset, elemCountOverride); \
1841 void EnableVertexAttribArray(GLuint index
);
1843 void DisableVertexAttribArray(GLuint index
);
1845 WebGLsizeiptr
GetVertexAttribOffset(GLuint index
, GLenum pname
);
1850 void VertexAttrib4Tv(GLuint index
, webgl::AttribBaseType
,
1851 const Range
<const uint8_t>&);
1854 void VertexAttrib1f(GLuint index
, GLfloat x
) {
1855 VertexAttrib4f(index
, x
, 0, 0, 1);
1857 void VertexAttrib2f(GLuint index
, GLfloat x
, GLfloat y
) {
1858 VertexAttrib4f(index
, x
, y
, 0, 1);
1860 void VertexAttrib3f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
) {
1861 VertexAttrib4f(index
, x
, y
, z
, 1);
1864 void VertexAttrib4f(GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
,
1866 const float arr
[4] = {x
, y
, z
, w
};
1867 VertexAttrib4Tv(index
, webgl::AttribBaseType::Float
, MakeByteRange(arr
));
1872 void VertexAttrib1fv(const GLuint index
, const Float32ListU
& list
) {
1873 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1874 if (IsContextLost()) return;
1876 const auto range
= MakeRange(list
);
1877 if (range
.length() < 1) {
1878 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=1.");
1882 VertexAttrib1f(index
, range
[0]);
1885 void VertexAttrib2fv(const GLuint index
, const Float32ListU
& list
) {
1886 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1887 if (IsContextLost()) return;
1889 const auto range
= MakeRange(list
);
1890 if (range
.length() < 2) {
1891 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=2.");
1895 VertexAttrib2f(index
, range
[0], range
[1]);
1898 void VertexAttrib3fv(const GLuint index
, const Float32ListU
& list
) {
1899 const FuncScope
funcScope(*this, "vertexAttrib1fv");
1900 if (IsContextLost()) return;
1902 const auto range
= MakeRange(list
);
1903 if (range
.length() < 3) {
1904 EnqueueError(LOCAL_GL_INVALID_VALUE
, "Length of `list` must be >=3.");
1908 VertexAttrib3f(index
, range
[0], range
[1], range
[2]);
1911 void VertexAttrib4fv(GLuint index
, const Float32ListU
& list
) {
1912 VertexAttrib4Tv(index
, webgl::AttribBaseType::Float
, MakeByteRange(list
));
1914 void VertexAttribI4iv(GLuint index
, const Int32ListU
& list
) {
1915 VertexAttrib4Tv(index
, webgl::AttribBaseType::Int
, MakeByteRange(list
));
1917 void VertexAttribI4uiv(GLuint index
, const Uint32ListU
& list
) {
1918 VertexAttrib4Tv(index
, webgl::AttribBaseType::Uint
, MakeByteRange(list
));
1921 void VertexAttribI4i(GLuint index
, GLint x
, GLint y
, GLint z
, GLint w
) {
1922 const int32_t arr
[4] = {x
, y
, z
, w
};
1923 VertexAttrib4Tv(index
, webgl::AttribBaseType::Int
, MakeByteRange(arr
));
1925 void VertexAttribI4ui(GLuint index
, GLuint x
, GLuint y
, GLuint z
, GLuint w
) {
1926 const uint32_t arr
[4] = {x
, y
, z
, w
};
1927 VertexAttrib4Tv(index
, webgl::AttribBaseType::Uint
, MakeByteRange(arr
));
1931 void VertexAttribPointerImpl(bool isFuncInt
, GLuint index
, GLint size
,
1932 GLenum type
, WebGLboolean normalized
,
1933 GLsizei iStride
, WebGLintptr iByteOffset
);
1936 void VertexAttribIPointer(GLuint index
, GLint size
, GLenum type
,
1937 GLsizei stride
, WebGLintptr byteOffset
) {
1938 VertexAttribPointerImpl(true, index
, size
, type
, false, stride
, byteOffset
);
1941 void VertexAttribPointer(GLuint index
, GLint size
, GLenum type
,
1942 WebGLboolean normalized
, GLsizei stride
,
1943 WebGLintptr byteOffset
) {
1944 VertexAttribPointerImpl(false, index
, size
, type
, normalized
, stride
,
1948 // -------------------------------- Drawing -------------------------------
1950 void DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
1951 DrawArraysInstanced(mode
, first
, count
, 1, FuncScopeId::drawArrays
);
1954 void DrawElements(GLenum mode
, GLsizei count
, GLenum type
,
1955 WebGLintptr byteOffset
) {
1956 DrawElementsInstanced(mode
, count
, type
, byteOffset
, 1,
1957 FuncScopeId::drawElements
);
1960 void DrawRangeElements(GLenum mode
, GLuint start
, GLuint end
, GLsizei count
,
1961 GLenum type
, WebGLintptr byteOffset
) {
1962 const FuncScope
funcScope(*this, "drawRangeElements");
1964 EnqueueError(LOCAL_GL_INVALID_VALUE
, "end must be >= start.");
1967 DrawElementsInstanced(mode
, count
, type
, byteOffset
, 1,
1968 FuncScopeId::drawRangeElements
);
1971 // ------------------------------ Readback -------------------------------
1973 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1974 GLenum format
, GLenum type
,
1975 const dom::Nullable
<dom::ArrayBufferView
>& maybeView
,
1976 dom::CallerType aCallerType
, ErrorResult
& out_error
) const {
1977 const FuncScope
funcScope(*this, "readPixels");
1978 if (!ValidateNonNull("pixels", maybeView
)) return;
1979 ReadPixels(x
, y
, width
, height
, format
, type
, maybeView
.Value(), 0,
1980 aCallerType
, out_error
);
1983 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1984 GLenum format
, GLenum type
, WebGLsizeiptr offset
,
1985 dom::CallerType aCallerType
, ErrorResult
& out_error
) const;
1987 void ReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1988 GLenum format
, GLenum type
,
1989 const dom::ArrayBufferView
& dstData
, GLuint dstElemOffset
,
1990 dom::CallerType aCallerType
, ErrorResult
& out_error
) const;
1993 bool ReadPixels_SharedPrecheck(dom::CallerType aCallerType
,
1994 ErrorResult
& out_error
) const;
1996 // ------------------------------ Vertex Array ------------------------------
1998 void BindVertexArray(WebGLVertexArrayJS
*);
2000 void DrawArraysInstanced(GLenum mode
, GLint first
, GLsizei count
,
2002 FuncScopeId aFuncId
= FuncScopeId::drawArrays
);
2004 void DrawElementsInstanced(
2005 GLenum mode
, GLsizei count
, GLenum type
, WebGLintptr offset
,
2007 FuncScopeId aFuncId
= FuncScopeId::drawElementsInstanced
);
2009 void VertexAttribDivisor(GLuint index
, GLuint divisor
);
2011 // --------------------------------- GL Query
2012 // ---------------------------------
2014 void GetQuery(JSContext
*, GLenum target
, GLenum pname
,
2015 JS::MutableHandleValue retval
) const;
2016 void GetQueryParameter(JSContext
*, WebGLQueryJS
&, GLenum pname
,
2017 JS::MutableHandleValue retval
) const;
2018 void BeginQuery(GLenum target
, WebGLQueryJS
&);
2019 void EndQuery(GLenum target
);
2020 void QueryCounter(WebGLQueryJS
&, GLenum target
) const;
2022 // -------------------------------- Sampler -------------------------------
2024 void GetSamplerParameter(JSContext
*, const WebGLSamplerJS
&, GLenum pname
,
2025 JS::MutableHandleValue retval
) const;
2027 void BindSampler(GLuint unit
, WebGLSamplerJS
*);
2028 void SamplerParameteri(WebGLSamplerJS
&, GLenum pname
, GLint param
) const;
2029 void SamplerParameterf(WebGLSamplerJS
&, GLenum pname
, GLfloat param
) const;
2031 // ------------------------------- GL Sync ---------------------------------
2033 GLenum
ClientWaitSync(WebGLSyncJS
&, GLbitfield flags
, GLuint64 timeout
) const;
2034 void GetSyncParameter(JSContext
*, WebGLSyncJS
&, GLenum pname
,
2035 JS::MutableHandleValue retval
) const;
2036 void WaitSync(const WebGLSyncJS
&, GLbitfield flags
, GLint64 timeout
) const;
2038 // -------------------------- Transform Feedback ---------------------------
2040 void BindTransformFeedback(GLenum target
, WebGLTransformFeedbackJS
*);
2041 void BeginTransformFeedback(GLenum primitiveMode
);
2042 void EndTransformFeedback();
2043 void PauseTransformFeedback();
2044 void ResumeTransformFeedback();
2046 // -------------------------- Opaque Framebuffers ---------------------------
2048 void SetFramebufferIsInOpaqueRAF(WebGLFramebufferJS
*, bool);
2050 // ------------------------------ Extensions ------------------------------
2052 void GetSupportedExtensions(dom::Nullable
<nsTArray
<nsString
>>& retval
,
2053 dom::CallerType callerType
) const;
2055 bool IsSupported(WebGLExtensionID
, dom::CallerType callerType
=
2056 dom::CallerType::NonSystem
) const;
2058 void GetExtension(JSContext
* cx
, const nsAString
& name
,
2059 JS::MutableHandle
<JSObject
*> retval
,
2060 dom::CallerType callerType
, ErrorResult
& rv
);
2063 RefPtr
<ClientWebGLExtensionBase
> GetExtension(WebGLExtensionID ext
,
2064 dom::CallerType callerType
);
2065 void RequestExtension(WebGLExtensionID
) const;
2068 bool IsExtensionEnabled(const WebGLExtensionID id
) const {
2069 return bool(mNotLost
->extensions
[UnderlyingValue(id
)]);
2072 void AddCompressedFormat(GLenum
);
2074 // ---------------------------- Misc Extensions ----------------------------
2076 void DrawBuffers(const dom::Sequence
<GLenum
>& buffers
);
2078 void GetSupportedProfilesASTC(
2079 dom::Nullable
<nsTArray
<nsString
>>& retval
) const;
2081 void MOZDebugGetParameter(JSContext
* cx
, GLenum pname
,
2082 JS::MutableHandle
<JS::Value
> retval
,
2084 GetParameter(cx
, pname
, retval
, rv
, true);
2087 // -------------------------------------------------------------------------
2088 // Client-side methods. Calls in the Host are forwarded to the client.
2089 // -------------------------------------------------------------------------
2091 void JsWarning(const std::string
&) const;
2093 // -------------------------------------------------------------------------
2094 // The cross-process communication mechanism
2095 // -------------------------------------------------------------------------
2097 template <typename ReturnType
>
2098 friend struct WebGLClientDispatcher
;
2100 template <typename MethodType
, MethodType method
, typename ReturnType
,
2102 friend ReturnType
RunOn(const ClientWebGLContext
& context
, Args
&&... aArgs
);
2104 // If we are running WebGL in this process then call the HostWebGLContext
2105 // method directly. Otherwise, dispatch over IPC.
2106 template <typename MethodType
, MethodType method
, typename
... Args
>
2107 void Run(Args
&&... aArgs
) const;
2109 // -------------------------------------------------------------------------
2110 // Helpers for DOM operations, composition, actors, etc
2111 // -------------------------------------------------------------------------
2114 // https://immersive-web.github.io/webxr/#xr-compatible
2115 bool IsXRCompatible() const;
2116 already_AddRefed
<dom::Promise
> MakeXRCompatible(ErrorResult
& aRv
);
2119 bool ShouldResistFingerprinting() const;
2121 // Prepare the context for capture before compositing
2122 void BeginComposition();
2124 // Clean up the context after captured for compositing
2125 void EndComposition();
2127 mozilla::dom::Document
* GetOwnerDoc() const;
2129 bool mResetLayer
= true;
2130 Maybe
<const WebGLContextOptions
> mInitialOptions
;
2131 bool mXRCompatible
= false;
2134 // used by DOM bindings in conjunction with GetParentObject
2135 inline nsISupports
* ToSupports(ClientWebGLContext
* webgl
) {
2136 return static_cast<nsICanvasRenderingContextInternal
*>(webgl
);
2139 const char* GetExtensionName(WebGLExtensionID
);
2143 inline bool webgl::ObjectJS::IsForContext(
2144 const ClientWebGLContext
& context
) const {
2145 const auto& notLost
= context
.mNotLost
;
2146 if (!notLost
) return false;
2147 if (notLost
.get() != mGeneration
.lock().get()) return false;
2151 void AutoJsWarning(const std::string
& utf8
);
2153 } // namespace mozilla
2155 #endif // CLIENTWEBGLCONTEXT_H_