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