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