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