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