WebGLContext.h (51229B)
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/. */ 5 6 #ifndef WEBGLCONTEXT_H_ 7 #define WEBGLCONTEXT_H_ 8 9 #include <bitset> 10 #include <memory> 11 12 #include "Colorspaces.h" 13 #include "GLContextTypes.h" 14 #include "GLDefs.h" 15 #include "GLScreenBuffer.h" 16 #include "ScopedGLHelpers.h" 17 #include "SurfaceTypes.h" 18 #include "TexUnpackBlob.h" 19 #include "js/ScalarType.h" // js::Scalar::Type 20 #include "mozilla/Atomics.h" 21 #include "mozilla/EnumeratedArray.h" 22 #include "mozilla/Mutex.h" 23 #include "mozilla/StaticMutex.h" 24 #include "mozilla/StaticPrefs_webgl.h" 25 #include "mozilla/WeakPtr.h" 26 #include "mozilla/dom/BindingDeclarations.h" 27 #include "mozilla/dom/HTMLCanvasElement.h" 28 #include "mozilla/dom/Nullable.h" 29 #include "mozilla/dom/TypedArray.h" 30 #include "mozilla/dom/ipc/IdType.h" 31 #include "mozilla/gfx/2D.h" 32 #include "nsICanvasRenderingContextInternal.h" 33 #include "nsTArray.h" 34 35 // Local 36 #include "CacheInvalidator.h" 37 #include "WebGLContextLossHandler.h" 38 #include "WebGLExtensions.h" 39 #include "WebGLObjectModel.h" 40 #include "WebGLStrongTypes.h" 41 #include "WebGLTypes.h" 42 43 // Generated 44 #include <list> 45 46 #include "mozilla/dom/WebGL2RenderingContextBinding.h" 47 #include "mozilla/dom/WebGLRenderingContextBinding.h" 48 49 class nsIDocShell; 50 51 // WebGL-only GLenums 52 // clang-format off 53 #define LOCAL_GL_BROWSER_DEFAULT_WEBGL 0x9244 54 #define LOCAL_GL_CONTEXT_LOST_WEBGL 0x9242 55 #define LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL 0x9247 56 #define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243 57 #define LOCAL_GL_UNPACK_FLIP_Y_WEBGL 0x9240 58 #define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241 59 // clang-format on 60 61 namespace mozilla { 62 class HostWebGLContext; 63 class ScopedCopyTexImageSource; 64 class ScopedDrawCallWrapper; 65 class ScopedResolveTexturesForDraw; 66 class WebGLBuffer; 67 class WebGLExtensionBase; 68 class WebGLFramebuffer; 69 class WebGLProgram; 70 class WebGLQuery; 71 class WebGLRenderbuffer; 72 class WebGLSampler; 73 class WebGLShader; 74 class WebGLSync; 75 class WebGLTexture; 76 class WebGLTransformFeedback; 77 class WebGLVertexArray; 78 class WebGL2Context; 79 80 namespace dom { 81 class Document; 82 class Element; 83 class ImageData; 84 class OwningHTMLCanvasElementOrOffscreenCanvas; 85 struct WebGLContextAttributes; 86 } // namespace dom 87 88 namespace gfx { 89 class SourceSurface; 90 class VRLayerChild; 91 } // namespace gfx 92 93 namespace gl { 94 class GLScreenBuffer; 95 class MozFramebuffer; 96 class SharedSurface; 97 class Sampler; 98 class Texture; 99 } // namespace gl 100 101 namespace layers { 102 class CompositableHost; 103 class RemoteTextureOwnerClient; 104 class SharedSurfacesHolder; 105 class SurfaceDescriptor; 106 } // namespace layers 107 108 namespace webgl { 109 class AvailabilityRunnable; 110 struct CachedDrawFetchLimits; 111 struct FbAttachInfo; 112 struct FormatInfo; 113 class FormatUsageAuthority; 114 struct FormatUsageInfo; 115 struct ImageInfo; 116 struct LinkedProgramInfo; 117 struct SamplerUniformInfo; 118 struct SamplingState; 119 class ScopedPrepForResourceClear; 120 class ShaderValidator; 121 class TexUnpackBlob; 122 struct UniformInfo; 123 struct UniformBlockInfo; 124 struct VertAttribPointerDesc; 125 } // namespace webgl 126 127 struct WebGLTexImageData { 128 TexImageTarget mTarget; 129 int32_t mRowLength; 130 uint32_t mWidth; 131 uint32_t mHeight; 132 uint32_t mDepth; 133 gfxAlphaType mSrcAlphaType; 134 }; 135 136 struct WebGLTexPboOffset { 137 TexImageTarget mTarget; 138 uint32_t mWidth; 139 uint32_t mHeight; 140 uint32_t mDepth; 141 WebGLsizeiptr mPboOffset; 142 bool mHasExpectedImageSize; 143 GLsizei mExpectedImageSize; 144 }; 145 146 WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format); 147 148 void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow); 149 150 // From WebGLContextUtils 151 TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget); 152 153 struct WebGLIntOrFloat { 154 const enum { Int, Float, Uint } mType; 155 156 union { 157 GLint i; 158 GLfloat f; 159 GLuint u; 160 } mValue; 161 162 explicit WebGLIntOrFloat(GLint i) : mType(Int) { mValue.i = i; } 163 explicit WebGLIntOrFloat(GLfloat f) : mType(Float) { mValue.f = f; } 164 165 GLint AsInt() const { 166 return (mType == Int) ? mValue.i : NS_lroundf(mValue.f); 167 } 168 GLfloat AsFloat() const { 169 return (mType == Float) ? mValue.f : GLfloat(mValue.i); 170 } 171 }; 172 173 //////////////////////////////////// 174 175 namespace webgl { 176 177 class AvailabilityRunnable final : public DiscardableRunnable { 178 public: 179 const WeakPtr<const ClientWebGLContext> mWebGL; 180 std::vector<WeakPtr<WebGLQueryJS>> mQueries; 181 std::vector<WeakPtr<WebGLSyncJS>> mSyncs; 182 183 explicit AvailabilityRunnable(const ClientWebGLContext* webgl); 184 ~AvailabilityRunnable(); 185 186 NS_IMETHOD Run() override; 187 }; 188 189 } // namespace webgl 190 191 //////////////////////////////////////////////////////////////////////////////// 192 193 class WebGLContext : public VRefCounted, public SupportsWeakPtr { 194 friend class ScopedDrawCallWrapper; 195 friend class ScopedDrawWithTransformFeedback; 196 friend class ScopedFakeVertexAttrib0; 197 friend class ScopedFBRebinder; 198 friend class WebGL2Context; 199 friend class WebGLContextUserData; 200 friend class WebGLExtensionCompressedTextureASTC; 201 friend class WebGLExtensionCompressedTextureBPTC; 202 friend class WebGLExtensionCompressedTextureES3; 203 friend class WebGLExtensionCompressedTextureETC1; 204 friend class WebGLExtensionCompressedTexturePVRTC; 205 friend class WebGLExtensionCompressedTextureRGTC; 206 friend class WebGLExtensionCompressedTextureS3TC; 207 friend class WebGLExtensionCompressedTextureS3TC_SRGB; 208 friend class WebGLExtensionDepthClamp; 209 friend class WebGLExtensionDepthTexture; 210 friend class WebGLExtensionDisjointTimerQuery; 211 friend class WebGLExtensionDrawBuffers; 212 friend class WebGLExtensionFragDepth; 213 friend class WebGLExtensionLoseContext; 214 friend class WebGLExtensionMOZDebug; 215 friend class WebGLExtensionShaderTextureLod; 216 friend class WebGLExtensionVertexArray; 217 friend class WebGLMemoryTracker; 218 friend class webgl::AvailabilityRunnable; 219 friend struct webgl::LinkedProgramInfo; 220 friend struct webgl::SamplerUniformInfo; 221 friend class webgl::ScopedPrepForResourceClear; 222 friend struct webgl::UniformBlockInfo; 223 224 friend const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext*, GLenum, 225 uint32_t); 226 friend RefPtr<const webgl::LinkedProgramInfo> QueryProgramInfo( 227 WebGLProgram* prog, gl::GLContext* gl); 228 229 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(WebGLContext, override) 230 231 enum { 232 UNPACK_FLIP_Y_WEBGL = 0x9240, 233 UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241, 234 // We throw InvalidOperation in TexImage if we fail to use GPU fast-path 235 // for texture copy when it is set to true, only for debug purpose. 236 UNPACK_REQUIRE_FASTPATH = 0x10001, 237 CONTEXT_LOST_WEBGL = 0x9242, 238 UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243, 239 BROWSER_DEFAULT_WEBGL = 0x9244, 240 UNMASKED_VENDOR_WEBGL = 0x9245, 241 UNMASKED_RENDERER_WEBGL = 0x9246 242 }; 243 244 private: 245 class LruPosition final { 246 std::list<WebGLContext*>::iterator mItr; 247 248 LruPosition(const LruPosition&) = delete; 249 LruPosition(LruPosition&&) = delete; 250 LruPosition& operator=(const LruPosition&) = delete; 251 LruPosition& operator=(LruPosition&&) = delete; 252 253 public: 254 void AssignLocked(WebGLContext& aContext) MOZ_REQUIRES(sLruMutex); 255 void Reset(); 256 void ResetLocked() MOZ_REQUIRES(sLruMutex); 257 bool IsInsertedLocked() const MOZ_REQUIRES(sLruMutex); 258 259 LruPosition(); 260 explicit LruPosition(WebGLContext&); 261 262 ~LruPosition() { Reset(); } 263 }; 264 265 mutable LruPosition mLruPosition MOZ_GUARDED_BY(sLruMutex); 266 267 void BumpLruLocked() MOZ_REQUIRES(sLruMutex); 268 269 public: 270 void BumpLru(); 271 void LoseLruContextIfLimitExceeded(); 272 273 // - 274 275 // We've had issues in the past with nulling `gl` without actually releasing 276 // all of our resources. This construction ensures that we are aware that we 277 // should only null `gl` in DestroyResourcesAndContext. 278 RefPtr<gl::GLContext> mGL_OnlyClearInDestroyResourcesAndContext; 279 280 public: 281 // Grab a const reference so we can see changes, but can't make changes. 282 const decltype(mGL_OnlyClearInDestroyResourcesAndContext)& gl; 283 284 public: 285 void CheckForInactivity(); 286 287 protected: 288 const WeakPtr<HostWebGLContext> mHost; 289 const bool mResistFingerprinting; 290 WebGLContextOptions mOptions; 291 const uint32_t mPrincipalKey; 292 Maybe<webgl::Limits> mLimits; 293 const uint32_t mMaxVertIdsPerDraw = 294 StaticPrefs::webgl_max_vert_ids_per_draw(); 295 296 bool mIsContextLost = false; 297 Atomic<bool> mPendingContextLoss = Atomic<bool>{false}; 298 webgl::ContextLossReason mPendingContextLossReason = 299 webgl::ContextLossReason::None; 300 const uint32_t mMaxPerfWarnings = StaticPrefs::webgl_perf_max_warnings(); 301 mutable uint64_t mNumPerfWarnings = 0; 302 const uint32_t mMaxAcceptableFBStatusInvals = 303 StaticPrefs::webgl_perf_max_acceptable_fb_status_invals(); 304 bool mWarnOnce_DepthTexCompareFilterable = true; 305 306 mutable std::optional<bool> mIsSupportedCache_DrawBuffers; 307 mutable std::optional<bool> mIsSupportedCache_FragDepth; 308 mutable std::optional<bool> mIsSupportedCache_ShaderTextureLod; 309 310 // - 311 312 uint64_t mNextFenceId = 1; 313 uint64_t mCompletedFenceId = 0; 314 315 mutable std::list<WeakPtr<WebGLSync>> mPendingSyncs; 316 mutable RefPtr<nsIRunnable> mPollPendingSyncs_Pending; 317 static constexpr uint32_t kPollPendingSyncs_DelayMs = 318 4; // Four times a frame. 319 public: 320 void EnsurePollPendingSyncs_Pending() const; 321 void PollPendingSyncs() const; 322 323 protected: 324 std::unique_ptr<gl::Texture> mIncompleteTexOverride; 325 326 public: 327 class FuncScope; 328 329 private: 330 mutable FuncScope* mFuncScope = nullptr; 331 332 public: 333 static RefPtr<WebGLContext> Create(HostWebGLContext*, 334 const webgl::InitContextDesc&, 335 webgl::InitContextResult* out); 336 337 private: 338 webgl::OptionalRenderableFormatBits mOptionalRenderableFormatBits = 339 webgl::OptionalRenderableFormatBits{0}; 340 void FinishInit(); 341 342 protected: 343 WebGLContext(HostWebGLContext*, const webgl::InitContextDesc&); 344 virtual ~WebGLContext(); 345 346 RefPtr<layers::CompositableHost> mCompositableHost; 347 348 layers::LayersBackend mBackend = layers::LayersBackend::LAYERS_NONE; 349 350 public: 351 void Resize(uvec2 size); 352 353 void SetCompositableHost(RefPtr<layers::CompositableHost>& aCompositableHost); 354 355 /** 356 * An abstract base class to be implemented by callers wanting to be notified 357 * that a refresh has occurred. Callers must ensure an observer is removed 358 * before it is destroyed. 359 */ 360 virtual void DidRefresh(); 361 362 void OnMemoryPressure(); 363 364 // - 365 366 /* 367 368 Here are the bind calls that are supposed to be fully-validated client side, 369 so that client's binding state doesn't diverge: 370 * AttachShader 371 * DetachShader 372 * BindFramebuffer 373 * FramebufferAttach 374 * BindBuffer 375 * BindBufferRange 376 * BindTexture 377 * UseProgram 378 * BindSampler 379 * BindTransformFeedback 380 * BindVertexArray 381 * BeginQuery 382 * EndQuery 383 * ActiveTexture 384 385 */ 386 387 const auto& CurFuncScope() const { return *mFuncScope; } 388 const char* FuncName() const; 389 390 class FuncScope final { 391 public: 392 const WebGLContext& mWebGL; 393 const char* const mFuncName; 394 bool mBindFailureGuard = false; 395 396 public: 397 FuncScope(const WebGLContext& webgl, const char* funcName); 398 ~FuncScope(); 399 }; 400 401 void GenerateErrorImpl(const GLenum err, const nsACString& text) const { 402 GenerateErrorImpl(err, std::string(text.BeginReading())); 403 } 404 void GenerateErrorImpl(const GLenum err, const std::string& text) const; 405 406 void GenerateError(const webgl::ErrorInfo& err) { 407 GenerateError(err.type, "%s", err.info.c_str()); 408 } 409 410 template <typename... Args> 411 void GenerateError(const GLenum err, const char* const fmt, 412 const Args&... args) const { 413 MOZ_ASSERT(FuncName()); 414 415 nsCString text; 416 text.AppendPrintf("WebGL warning: %s: ", FuncName()); 417 418 #ifdef __clang__ 419 # pragma clang diagnostic push 420 # pragma clang diagnostic ignored "-Wformat-security" 421 #elif defined(__GNUC__) 422 # pragma GCC diagnostic push 423 # pragma GCC diagnostic ignored "-Wformat-security" 424 #endif 425 text.AppendPrintf(fmt, args...); 426 #ifdef __clang__ 427 # pragma clang diagnostic pop 428 #elif defined(__GNUC__) 429 # pragma GCC diagnostic pop 430 #endif 431 432 GenerateErrorImpl(err, text); 433 } 434 435 template <typename... Args> 436 void ErrorInvalidEnum(const char* const fmt, const Args&... args) const { 437 GenerateError(LOCAL_GL_INVALID_ENUM, fmt, args...); 438 } 439 template <typename... Args> 440 void ErrorInvalidOperation(const char* const fmt, const Args&... args) const { 441 GenerateError(LOCAL_GL_INVALID_OPERATION, fmt, args...); 442 } 443 template <typename... Args> 444 void ErrorInvalidValue(const char* const fmt, const Args&... args) const { 445 GenerateError(LOCAL_GL_INVALID_VALUE, fmt, args...); 446 } 447 template <typename... Args> 448 void ErrorInvalidFramebufferOperation(const char* const fmt, 449 const Args&... args) const { 450 GenerateError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION, fmt, args...); 451 } 452 template <typename... Args> 453 void ErrorOutOfMemory(const char* const fmt, const Args&... args) const { 454 GenerateError(LOCAL_GL_OUT_OF_MEMORY, fmt, args...); 455 } 456 457 template <typename... Args> 458 void ErrorImplementationBug(const char* const fmt, 459 const Args&... args) const { 460 const nsPrintfCString newFmt( 461 "Implementation bug, please file at %s! %s", 462 "https://bugzilla.mozilla.org/" 463 "enter_bug.cgi?product=Core&component=Canvas%3A+WebGL", 464 fmt); 465 GenerateError(LOCAL_GL_OUT_OF_MEMORY, newFmt.BeginReading(), args...); 466 MOZ_ASSERT(false, "WebGLContext::ErrorImplementationBug"); 467 NS_ERROR("WebGLContext::ErrorImplementationBug"); 468 } 469 470 void ErrorInvalidEnumInfo(const char* info, GLenum enumValue) const; 471 void ErrorInvalidEnumArg(const char* argName, GLenum val) const; 472 473 static const char* ErrorName(GLenum error); 474 475 void JsWarning(const std::string& text) const; 476 477 /** 478 * Return displayable name for GLenum. 479 * This version is like gl::GLenumToStr but with out the GL_ prefix to 480 * keep consistency with how errors are reported from WebGL. 481 * Returns hex formatted version of glenum if glenum is unknown. 482 */ 483 static void EnumName(GLenum val, nsCString* out_name); 484 485 void DummyReadFramebufferOperation(); 486 487 layers::SharedSurfacesHolder* GetSharedSurfacesHolder() const; 488 489 dom::ContentParentId GetContentId() const; 490 491 WebGLTexture* GetActiveTex(const GLenum texTarget) const; 492 493 gl::GLContext* GL() const { return gl; } 494 495 bool IsPremultAlpha() const { return mOptions.premultipliedAlpha; } 496 497 bool IsPreservingDrawingBuffer() const { 498 return mOptions.preserveDrawingBuffer; 499 } 500 501 // Present to compositor 502 private: 503 bool PresentInto(gl::SwapChain& swapChain); 504 bool PresentIntoXR(gl::SwapChain& swapChain, const gl::MozFramebuffer& xrFb); 505 506 public: 507 // Present swaps the front and back buffers of the swap chain for compositing. 508 // This assumes the framebuffer may directly alias with the back buffer, 509 // dependent on remoting state or other concerns. Framebuffer and swap chain 510 // surface formats are assumed to be similar to enable this aliasing. As such, 511 // the back buffer may be invalidated by this swap with the front buffer, 512 // unless overriden by explicitly setting the preserveDrawingBuffer option, 513 // which may incur a further copy to preserve the back buffer. 514 void Present( 515 WebGLFramebuffer*, layers::TextureType, const bool webvr, 516 const webgl::SwapChainOptions& options = webgl::SwapChainOptions()); 517 // CopyToSwapChain forces a copy from the supplied framebuffer into the back 518 // buffer before swapping the front and back buffers of the swap chain for 519 // compositing. The formats of the framebuffer and the swap chain buffers 520 // may differ subject to available format conversion options. Since this 521 // operation uses an explicit copy, it inherently preserves the framebuffer 522 // without need to set the preserveDrawingBuffer option. 523 bool CopyToSwapChain( 524 WebGLFramebuffer*, layers::TextureType, 525 const webgl::SwapChainOptions& options = webgl::SwapChainOptions(), 526 layers::RemoteTextureOwnerClient* ownerClient = nullptr); 527 // In use cases where a framebuffer is used as an offscreen framebuffer and 528 // does not need to be committed to the swap chain, it may still be useful 529 // for the implementation to delineate distinct frames, such as when sharing 530 // a single WebGLContext amongst many distinct users. EndOfFrame signals that 531 // frame rendering is complete so that any implementation side-effects such 532 // as resetting internal profile counters or resource queues may be handled 533 // appropriately. 534 void EndOfFrame(); 535 RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot(); 536 Maybe<uvec2> FrontBufferSnapshotInto( 537 const Maybe<Range<uint8_t>> dest, 538 const Maybe<size_t> destStride = Nothing()); 539 Maybe<uvec2> FrontBufferSnapshotInto( 540 const std::shared_ptr<gl::SharedSurface>& front, 541 const Maybe<Range<uint8_t>> dest, 542 const Maybe<size_t> destStride = Nothing()); 543 Maybe<uvec2> SnapshotInto(GLuint srcFb, const gfx::IntSize& size, 544 const Range<uint8_t>& dest, 545 const Maybe<size_t> destStride = Nothing()); 546 already_AddRefed<gfx::SourceSurface> GetBackBufferSnapshot( 547 const bool requireAlphaPremult); 548 std::shared_ptr<gl::SharedSurface> GetBackBufferSnapshotSharedSurface( 549 layers::TextureType texType, bool bgra = false, bool yFlip = false, 550 bool requireAlphaPremult = false); 551 void RecycleSnapshotSharedSurface(std::shared_ptr<gl::SharedSurface>); 552 gl::SwapChain* GetSwapChain(WebGLFramebuffer*, const bool webvr); 553 Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebuffer*, 554 const bool webvr); 555 556 std::optional<dom::PredefinedColorSpace> mDrawingBufferColorSpace; 557 std::optional<dom::PredefinedColorSpace> mUnpackColorSpace; 558 std::optional<color::ColorProfileDesc> mDisplayProfile; 559 560 void SetDrawingBufferColorSpace(const dom::PredefinedColorSpace val) { 561 mDrawingBufferColorSpace = val; 562 } 563 564 void SetUnpackColorSpace(const dom::PredefinedColorSpace val) { 565 mUnpackColorSpace = val; 566 } 567 568 void ClearVRSwapChain(); 569 570 void RunContextLossTimer(); 571 void CheckForContextLoss(); 572 void HandlePendingContextLoss(); 573 574 bool TryToRestoreContext(); 575 576 void AssertCachedBindings() const; 577 void AssertCachedGlobalState() const; 578 579 // WebIDL WebGLRenderingContext API 580 void Commit(); 581 582 uvec2 DrawingBufferSize(); 583 584 public: 585 void GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval); 586 587 // This is the entrypoint. Don't test against it directly. 588 bool IsContextLost() const { 589 auto* self = const_cast<WebGLContext*>(this); 590 if (self->mPendingContextLoss.exchange(false)) { 591 self->HandlePendingContextLoss(); 592 } 593 return mIsContextLost; 594 } 595 596 // - 597 598 RefPtr<WebGLBuffer> CreateBuffer(); 599 RefPtr<WebGLFramebuffer> CreateFramebuffer(); 600 RefPtr<WebGLFramebuffer> CreateOpaqueFramebuffer( 601 const webgl::OpaqueFramebufferOptions& options); 602 RefPtr<WebGLProgram> CreateProgram(); 603 RefPtr<WebGLQuery> CreateQuery(); 604 RefPtr<WebGLRenderbuffer> CreateRenderbuffer(); 605 RefPtr<WebGLShader> CreateShader(GLenum type); 606 RefPtr<WebGLTexture> CreateTexture(); 607 RefPtr<WebGLVertexArray> CreateVertexArray(); 608 609 // - 610 611 void AttachShader(WebGLProgram& prog, WebGLShader& shader); 612 void BindAttribLocation(WebGLProgram& prog, GLuint location, 613 const std::string& name) const; 614 void BindFramebuffer(GLenum target, WebGLFramebuffer* fb); 615 void BindRenderbuffer(GLenum target, WebGLRenderbuffer* fb); 616 void BindVertexArray(WebGLVertexArray* vao); 617 void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a); 618 void BlendEquationSeparate(Maybe<GLuint> i, GLenum modeRGB, GLenum modeAlpha); 619 void BlendFuncSeparate(Maybe<GLuint> i, GLenum srcRGB, GLenum dstRGB, 620 GLenum srcAlpha, GLenum dstAlpha); 621 GLenum CheckFramebufferStatus(GLenum target); 622 void Clear(GLbitfield mask); 623 void ClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a); 624 void ClearDepth(GLclampf v); 625 void ClearStencil(GLint v); 626 void ColorMask(Maybe<GLuint> i, uint8_t mask); 627 void CompileShader(WebGLShader& shader); 628 629 private: 630 void CompileShaderANGLE(WebGLShader* shader); 631 void CompileShaderBypass(WebGLShader* shader, const nsCString& shaderSource); 632 633 public: 634 void CullFace(GLenum face); 635 void DepthFunc(GLenum func); 636 void DepthMask(WebGLboolean b); 637 void DepthRange(GLclampf zNear, GLclampf zFar); 638 void DetachShader(WebGLProgram& prog, const WebGLShader& shader); 639 void DrawBuffers(const std::vector<GLenum>& buffers); 640 void Flush(); 641 void Finish(); 642 643 void FramebufferAttach(GLenum target, GLenum attachSlot, 644 GLenum bindImageTarget, 645 const webgl::FbAttachInfo& toAttach); 646 647 void FrontFace(GLenum mode); 648 649 Maybe<double> GetBufferParameter(GLenum target, GLenum pname); 650 webgl::CompileResult GetCompileResult(const WebGLShader&) const; 651 GLenum GetError(); 652 GLint GetFragDataLocation(const WebGLProgram&, const std::string& name) const; 653 654 Maybe<double> GetFramebufferAttachmentParameter(WebGLFramebuffer*, 655 GLenum attachment, 656 GLenum pname) const; 657 658 Maybe<double> GetRenderbufferParameter(const WebGLRenderbuffer&, 659 GLenum pname) const; 660 webgl::LinkResult GetLinkResult(const WebGLProgram&) const; 661 662 webgl::GetUniformData GetUniform(const WebGLProgram&, uint32_t loc) const; 663 664 void Hint(GLenum target, GLenum mode); 665 666 void LineWidth(GLfloat width); 667 void LinkProgram(WebGLProgram& prog); 668 void PolygonOffset(GLfloat factor, GLfloat units); 669 void ProvokingVertex(webgl::ProvokingVertex) const; 670 671 //// 672 673 webgl::PackingInfo ValidImplementationColorReadPI( 674 const webgl::FormatUsageInfo* usage) const; 675 676 protected: 677 webgl::ReadPixelsResult ReadPixelsImpl(const webgl::ReadPixelsDesc&, 678 uintptr_t dest, uint64_t availBytes); 679 bool DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat, 680 const webgl::ReadPixelsDesc&, uintptr_t dest, 681 uint64_t dataLen, uint32_t rowStride); 682 683 public: 684 void ReadPixelsPbo(const webgl::ReadPixelsDesc&, uint64_t offset); 685 webgl::ReadPixelsResult ReadPixelsInto(const webgl::ReadPixelsDesc&, 686 const Range<uint8_t>& dest); 687 688 //// 689 690 void RenderbufferStorageMultisample(WebGLRenderbuffer&, uint32_t samples, 691 GLenum internalformat, uint32_t width, 692 uint32_t height) const; 693 694 public: 695 void SampleCoverage(GLclampf value, WebGLboolean invert); 696 void Scissor(GLint x, GLint y, GLsizei width, GLsizei height); 697 void ShaderSource(WebGLShader& shader, const std::string& source) const; 698 void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); 699 void StencilMaskSeparate(GLenum face, GLuint mask); 700 void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, 701 GLenum dppass); 702 703 ////////////////////////// 704 705 void UniformData(uint32_t loc, bool transpose, 706 const Span<const webgl::UniformDataVal>& data) const; 707 708 //////////////////////////////////// 709 710 void UseProgram(WebGLProgram* prog); 711 712 bool ValidateAttribArraySetter(uint32_t count, uint32_t arrayLength); 713 bool ValidateProgram(const WebGLProgram& prog) const; 714 void Viewport(GLint x, GLint y, GLsizei width, GLsizei height); 715 716 // ----------------------------------------------------------------------------- 717 // Buffer Objects (WebGLContextBuffers.cpp) 718 void BindBuffer(GLenum target, WebGLBuffer* buffer); 719 void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buf, 720 uint64_t offset, uint64_t size); 721 722 void BufferData(GLenum target, uint64_t dataLen, const uint8_t* data, 723 GLenum usage) const; 724 void UninitializedBufferData_SizeOnly(GLenum target, uint64_t dataLen, 725 GLenum usage) const; 726 // The unsynchronized flag may allow for better performance when 727 // interleaving buffer updates with draw calls. However, care must 728 // be taken. This has similar semantics to glMapBufferRange's 729 // GL_MAP_UNSYNCHRONIZED_BIT: the results of any pending operations 730 // that reference the region of the buffer being updated are 731 // undefined. 732 void BufferSubData(GLenum target, uint64_t dstByteOffset, uint64_t srcDataLen, 733 const uint8_t* srcData, bool unsynchronized = false) const; 734 735 protected: 736 // bound buffer state 737 RefPtr<WebGLBuffer> mBoundArrayBuffer; 738 RefPtr<WebGLBuffer> mBoundCopyReadBuffer; 739 RefPtr<WebGLBuffer> mBoundCopyWriteBuffer; 740 RefPtr<WebGLBuffer> mBoundPixelPackBuffer; 741 RefPtr<WebGLBuffer> mBoundPixelUnpackBuffer; 742 RefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer; 743 RefPtr<WebGLBuffer> mBoundUniformBuffer; 744 745 std::vector<IndexedBufferBinding> mIndexedUniformBufferBindings; 746 747 RefPtr<WebGLBuffer>& GetBufferSlotByTarget(GLenum target); 748 RefPtr<WebGLBuffer>& GetBufferSlotByTargetIndexed(GLenum target, 749 GLuint index); 750 751 // - 752 753 void GenErrorIllegalUse(GLenum useTarget, uint32_t useId, GLenum boundTarget, 754 uint32_t boundId) const; 755 756 bool ValidateBufferForNonTf(const WebGLBuffer&, GLenum nonTfTarget, 757 uint32_t nonTfId) const; 758 759 bool ValidateBufferForNonTf(const WebGLBuffer* const nonTfBuffer, 760 const GLenum nonTfTarget, 761 const uint32_t nonTfId = -1) const { 762 if (!nonTfBuffer) return true; 763 return ValidateBufferForNonTf(*nonTfBuffer, nonTfTarget, nonTfId); 764 } 765 766 bool ValidateBuffersForTf(const WebGLTransformFeedback&, 767 const webgl::LinkedProgramInfo&) const; 768 bool ValidateBuffersForTf( 769 const std::vector<webgl::BufferAndIndex>& tfBuffers) const; 770 771 // ----------------------------------------------------------------------------- 772 // Queries (WebGL2ContextQueries.cpp) 773 protected: 774 RefPtr<WebGLQuery> mQuerySlot_SamplesPassed; 775 RefPtr<WebGLQuery> mQuerySlot_TFPrimsWritten; 776 RefPtr<WebGLQuery> mQuerySlot_TimeElapsed; 777 778 RefPtr<WebGLQuery>* ValidateQuerySlotByTarget(GLenum target); 779 780 public: 781 void BeginQuery(GLenum target, WebGLQuery& query); 782 void EndQuery(GLenum target); 783 Maybe<double> GetQueryParameter(const WebGLQuery& query, GLenum pname) const; 784 void QueryCounter(WebGLQuery&) const; 785 786 // ----------------------------------------------------------------------------- 787 // State and State Requests (WebGLContextState.cpp) 788 void SetEnabled(GLenum cap, Maybe<GLuint> i, bool enabled); 789 bool GetStencilBits(GLint* const out_stencilBits) const; 790 791 virtual Maybe<double> GetParameter(GLenum pname); 792 Maybe<std::string> GetString(GLenum pname) const; 793 794 private: 795 static StaticMutex sLruMutex; 796 static std::list<WebGLContext*> sLru MOZ_GUARDED_BY(sLruMutex); 797 798 // State tracking slots 799 bool mDitherEnabled = true; 800 bool mRasterizerDiscardEnabled = false; 801 bool mScissorTestEnabled = false; 802 bool mDepthTestEnabled = false; 803 bool mStencilTestEnabled = false; 804 GLenum mGenerateMipmapHint = LOCAL_GL_DONT_CARE; 805 806 struct ScissorRect final { 807 GLint x; 808 GLint y; 809 GLsizei w; 810 GLsizei h; 811 812 void Apply(gl::GLContext&) const; 813 }; 814 ScissorRect mScissorRect = {}; 815 816 bool* GetStateTrackingSlot(GLenum cap); 817 818 // Allocation debugging variables 819 mutable uint64_t mDataAllocGLCallCount = 0; 820 821 void OnDataAllocCall() const { mDataAllocGLCallCount++; } 822 823 uint64_t GetNumGLDataAllocCalls() const { return mDataAllocGLCallCount; } 824 825 void OnEndOfFrame(); 826 827 // ----------------------------------------------------------------------------- 828 // Texture funcions (WebGLContextTextures.cpp) 829 public: 830 void ActiveTexture(uint32_t texUnit); 831 void BindTexture(GLenum texTarget, WebGLTexture* tex); 832 void GenerateMipmap(GLenum texTarget); 833 834 Maybe<double> GetTexParameter(const WebGLTexture&, GLenum pname) const; 835 void TexParameter_base(GLenum texTarget, GLenum pname, 836 const FloatOrInt& param); 837 838 virtual bool IsTexParamValid(GLenum pname) const; 839 840 //////////////////////////////////// 841 // Uploads 842 843 // CompressedTexSubImage if `sub` 844 void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level, 845 GLenum format, uvec3 offset, uvec3 size, 846 const Range<const uint8_t>& src, 847 const uint32_t pboImageSize, 848 const Maybe<uint64_t>& pboOffset) const; 849 850 // CopyTexSubImage if `!respectFormat` 851 void CopyTexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat, 852 uvec3 dstOffset, const ivec2& srcOffset, 853 const uvec2& size) const; 854 855 // TexSubImage if `!respectFormat` 856 void TexImage(uint32_t level, GLenum respecFormat, uvec3 offset, 857 const webgl::PackingInfo& pi, 858 const webgl::TexUnpackBlobDesc&) const; 859 860 void TexStorage(GLenum texTarget, uint32_t levels, GLenum sizedFormat, 861 uvec3 size) const; 862 863 std::unique_ptr<webgl::TexUnpackBlob> ToTexUnpackBytes( 864 const WebGLTexImageData& imageData); 865 866 std::unique_ptr<webgl::TexUnpackBytes> ToTexUnpackBytes( 867 WebGLTexPboOffset& aPbo); 868 869 //////////////////////////////////// 870 // WebGLTextureUpload.cpp 871 protected: 872 bool ValidateTexImageSpecification(uint8_t funcDims, GLenum texImageTarget, 873 GLint level, GLsizei width, GLsizei height, 874 GLsizei depth, GLint border, 875 TexImageTarget* const out_target, 876 WebGLTexture** const out_texture, 877 webgl::ImageInfo** const out_imageInfo); 878 bool ValidateTexImageSelection(uint8_t funcDims, GLenum texImageTarget, 879 GLint level, GLint xOffset, GLint yOffset, 880 GLint zOffset, GLsizei width, GLsizei height, 881 GLsizei depth, 882 TexImageTarget* const out_target, 883 WebGLTexture** const out_texture, 884 webgl::ImageInfo** const out_imageInfo); 885 bool ValidateUnpackInfo(bool usePBOs, GLenum format, GLenum type, 886 webgl::PackingInfo* const out); 887 888 // ----------------------------------------------------------------------------- 889 // Vertices Feature (WebGLContextVertices.cpp) 890 GLenum mPrimRestartTypeBytes = 0; 891 892 public: 893 void DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertexCount, 894 GLsizei instanceCount); 895 void DrawElementsInstanced(GLenum mode, GLsizei vertexCount, GLenum type, 896 WebGLintptr byteOffset, GLsizei instanceCount); 897 898 void EnableVertexAttribArray(GLuint index); 899 void DisableVertexAttribArray(GLuint index); 900 901 Maybe<double> GetVertexAttrib(GLuint index, GLenum pname); 902 903 //// 904 905 void VertexAttrib4T(GLuint index, const webgl::TypedQuad&); 906 907 //// 908 909 void VertexAttribPointer(uint32_t index, const webgl::VertAttribPointerDesc&); 910 911 void VertexAttribDivisor(GLuint index, GLuint divisor); 912 913 private: 914 WebGLBuffer* DrawElements_check(GLsizei indexCount, GLenum type, 915 WebGLintptr byteOffset, 916 GLsizei instanceCount); 917 void Draw_cleanup(); 918 919 void VertexAttrib1fv_base(GLuint index, uint32_t arrayLength, 920 const GLfloat* ptr); 921 void VertexAttrib2fv_base(GLuint index, uint32_t arrayLength, 922 const GLfloat* ptr); 923 void VertexAttrib3fv_base(GLuint index, uint32_t arrayLength, 924 const GLfloat* ptr); 925 void VertexAttrib4fv_base(GLuint index, uint32_t arrayLength, 926 const GLfloat* ptr); 927 928 bool BindArrayAttribToLocation0(WebGLProgram* prog); 929 930 // ----------------------------------------------------------------------------- 931 // PROTECTED 932 protected: 933 WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need() const; 934 bool DoFakeVertexAttrib0(uint64_t fakeVertexCount, 935 WebGLVertexAttrib0Status whatDoesAttrib0Need); 936 937 bool mResetLayer = true; 938 bool mOptionsFrozen = false; 939 bool mIsMesa = false; 940 bool mLoseContextOnMemoryPressure = false; 941 bool mCanLoseContextInForeground = true; 942 bool mShouldPresent = false; 943 bool mDisableFragHighP = false; 944 bool mForceResizeOnPresent = false; 945 bool mVRReady = false; 946 947 template <typename WebGLObjectType> 948 void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array); 949 950 GLuint mActiveTexture = 0; 951 GLenum mDefaultFB_DrawBuffer0 = LOCAL_GL_BACK; 952 GLenum mDefaultFB_ReadBuffer = LOCAL_GL_BACK; 953 954 mutable GLenum mWebGLError = 0; 955 956 std::unique_ptr<webgl::ShaderValidator> CreateShaderValidator( 957 GLenum shaderType) const; 958 959 // some GL constants 960 uint32_t mGLMaxFragmentUniformVectors = 0; 961 uint32_t mGLMaxVertexUniformVectors = 0; 962 uint32_t mGLMaxVertexOutputVectors = 0; 963 uint32_t mGLMaxFragmentInputVectors = 0; 964 965 uint32_t mGLMaxVertexTextureImageUnits = 0; 966 uint32_t mGLMaxFragmentTextureImageUnits = 0; 967 uint32_t mGLMaxCombinedTextureImageUnits = 0; 968 969 // ES3: 970 uint32_t mGLMinProgramTexelOffset = 0; 971 uint32_t mGLMaxProgramTexelOffset = 0; 972 973 public: 974 auto GLMaxDrawBuffers() const { return mLimits->maxColorDrawBuffers; } 975 976 uint32_t MaxValidDrawBuffers() const { 977 if (IsWebGL2() || 978 IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) { 979 return GLMaxDrawBuffers(); 980 } 981 return 1; 982 } 983 984 GLenum LastColorAttachmentEnum() const { 985 return LOCAL_GL_COLOR_ATTACHMENT0 + MaxValidDrawBuffers() - 1; 986 } 987 988 const auto& Options() const { return mOptions; } 989 990 protected: 991 uint32_t mGLMaxRenderbufferSize = 0; 992 993 public: 994 const auto& Limits() const { return *mLimits; } 995 auto MaxVertexAttribs() const { return mLimits->maxVertexAttribs; } 996 auto GLMaxTextureUnits() const { return mLimits->maxTexUnits; } 997 998 bool IsFormatValidForFB(TexInternalFormat format) const; 999 1000 protected: 1001 // ------------------------------------------------------------------------- 1002 // WebGL extensions (implemented in WebGLContextExtensions.cpp) 1003 1004 EnumeratedArray<WebGLExtensionID, std::unique_ptr<WebGLExtensionBase>, 1005 size_t(WebGLExtensionID::Max)> 1006 mExtensions; 1007 1008 public: 1009 void RequestExtension(WebGLExtensionID, bool explicitly = true); 1010 1011 // returns true if the extension has been enabled by calling getExtension. 1012 bool IsExtensionEnabled(const WebGLExtensionID id) const { 1013 return bool(mExtensions[id]); 1014 } 1015 1016 bool IsExtensionExplicit(WebGLExtensionID) const; 1017 void WarnIfImplicit(WebGLExtensionID) const; 1018 1019 bool IsExtensionSupported(WebGLExtensionID) const; 1020 1021 // ------------------------------------------------------------------------- 1022 // WebGL 2 specifics (implemented in WebGL2Context.cpp) 1023 public: 1024 virtual bool IsWebGL2() const { return false; } 1025 1026 virtual WebGL2Context* AsWebGL2() { return nullptr; } 1027 1028 struct FailureReason { 1029 nsCString key; // For reporting. 1030 nsCString info; 1031 1032 FailureReason() = default; 1033 1034 template <typename A, typename B> 1035 FailureReason(const A& _key, const B& _info) 1036 : key(nsCString(_key)), info(nsCString(_info)) {} 1037 }; 1038 1039 protected: 1040 bool InitWebGL2(FailureReason* const out_failReason); 1041 1042 bool CreateAndInitGL(bool forceEnabled, 1043 std::vector<FailureReason>* const out_failReasons); 1044 1045 // ------------------------------------------------------------------------- 1046 // Validation functions (implemented in WebGLContextValidate.cpp) 1047 bool InitAndValidateGL(FailureReason* const out_failReason); 1048 1049 bool ValidateBlendEquationEnum(GLenum cap, const char* info); 1050 bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor, 1051 const char* info); 1052 bool ValidateStencilOpEnum(GLenum action, const char* info); 1053 bool ValidateFaceEnum(GLenum face); 1054 bool ValidateTexInputData(GLenum type, js::Scalar::Type jsArrayType, 1055 WebGLTexImageFunc func, WebGLTexDimensions dims); 1056 bool ValidateAttribPointer(bool integerMode, GLuint index, GLint size, 1057 GLenum type, WebGLboolean normalized, 1058 GLsizei stride, WebGLintptr byteOffset, 1059 const char* info); 1060 bool ValidateStencilParamsForDrawCall() const; 1061 1062 bool ValidateCopyTexImage(TexInternalFormat srcFormat, 1063 TexInternalFormat dstformat, WebGLTexImageFunc func, 1064 WebGLTexDimensions dims); 1065 1066 bool ValidateTexImage(TexImageTarget texImageTarget, GLint level, 1067 GLenum internalFormat, GLint xoffset, GLint yoffset, 1068 GLint zoffset, GLint width, GLint height, GLint depth, 1069 GLint border, GLenum format, GLenum type, 1070 WebGLTexImageFunc func, WebGLTexDimensions dims); 1071 bool ValidateTexImageFormat(GLenum internalFormat, WebGLTexImageFunc func, 1072 WebGLTexDimensions dims); 1073 bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func, 1074 WebGLTexDimensions dims); 1075 bool ValidateTexImageFormatAndType(GLenum format, GLenum type, 1076 WebGLTexImageFunc func, 1077 WebGLTexDimensions dims); 1078 bool ValidateCompTexImageInternalFormat(GLenum format, WebGLTexImageFunc func, 1079 WebGLTexDimensions dims); 1080 bool ValidateCopyTexImageInternalFormat(GLenum format, WebGLTexImageFunc func, 1081 WebGLTexDimensions dims); 1082 bool ValidateTexImageSize(TexImageTarget texImageTarget, GLint level, 1083 GLint width, GLint height, GLint depth, 1084 WebGLTexImageFunc func, WebGLTexDimensions dims); 1085 bool ValidateTexSubImageSize(GLint x, GLint y, GLint z, GLsizei width, 1086 GLsizei height, GLsizei depth, GLsizei baseWidth, 1087 GLsizei baseHeight, GLsizei baseDepth, 1088 WebGLTexImageFunc func, WebGLTexDimensions dims); 1089 bool ValidateCompTexImageSize(GLint level, GLenum internalFormat, 1090 GLint xoffset, GLint yoffset, GLsizei width, 1091 GLsizei height, GLsizei levelWidth, 1092 GLsizei levelHeight, WebGLTexImageFunc func, 1093 WebGLTexDimensions dims); 1094 bool ValidateCompTexImageDataSize(GLint level, GLenum internalFormat, 1095 GLsizei width, GLsizei height, 1096 uint32_t byteLength, WebGLTexImageFunc func, 1097 WebGLTexDimensions dims); 1098 1099 bool HasDrawBuffers() const { 1100 return IsWebGL2() || 1101 IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers); 1102 } 1103 1104 RefPtr<WebGLBuffer>* ValidateBufferSlot(GLenum target); 1105 1106 public: 1107 WebGLBuffer* ValidateBufferSelection(GLenum target) const; 1108 1109 protected: 1110 IndexedBufferBinding* ValidateIndexedBufferSlot(GLenum target, GLuint index); 1111 1112 bool ValidateIndexedBufferBinding( 1113 GLenum target, GLuint index, 1114 RefPtr<WebGLBuffer>** const out_genericBinding, 1115 IndexedBufferBinding** const out_indexedBinding); 1116 1117 public: 1118 bool ValidateNonNegative(const char* argName, int64_t val) const { 1119 if (MOZ_UNLIKELY(val < 0)) { 1120 ErrorInvalidValue("`%s` must be non-negative.", argName); 1121 return false; 1122 } 1123 return true; 1124 } 1125 1126 template <typename T> 1127 bool ValidateNonNull(const char* const argName, 1128 const dom::Nullable<T>& maybe) const { 1129 if (maybe.IsNull()) { 1130 ErrorInvalidValue("%s: Cannot be null.", argName); 1131 return false; 1132 } 1133 return true; 1134 } 1135 1136 //// 1137 1138 protected: 1139 void DestroyResourcesAndContext(); 1140 1141 // helpers 1142 1143 bool ConvertImage(size_t width, size_t height, size_t srcStride, 1144 size_t dstStride, const uint8_t* src, uint8_t* dst, 1145 WebGLTexelFormat srcFormat, bool srcPremultiplied, 1146 WebGLTexelFormat dstFormat, bool dstPremultiplied, 1147 size_t dstTexelSize); 1148 1149 ////// 1150 public: 1151 template <typename T> 1152 bool ValidateObject(const char* const argName, const T& object) const { 1153 // Todo: Remove all callers. 1154 return true; 1155 } 1156 1157 template <typename T> 1158 bool ValidateObject(const char* const argName, const T* const object) const { 1159 // Todo: Remove most (all?) callers. 1160 if (!object) { 1161 ErrorInvalidOperation( 1162 "%s: Object argument cannot have been marked for" 1163 " deletion.", 1164 argName); 1165 return false; 1166 } 1167 return true; 1168 } 1169 1170 //// 1171 1172 private: 1173 void LoseContextLruLocked(webgl::ContextLossReason reason) 1174 MOZ_REQUIRES(sLruMutex); 1175 1176 public: 1177 void LoseContext( 1178 webgl::ContextLossReason reason = webgl::ContextLossReason::None); 1179 1180 protected: 1181 nsTArray<RefPtr<WebGLTexture>> mBound2DTextures; 1182 nsTArray<RefPtr<WebGLTexture>> mBoundCubeMapTextures; 1183 nsTArray<RefPtr<WebGLTexture>> mBound3DTextures; 1184 nsTArray<RefPtr<WebGLTexture>> mBound2DArrayTextures; 1185 nsTArray<RefPtr<WebGLSampler>> mBoundSamplers; 1186 1187 mutable std::unique_ptr<gl::Sampler> mSamplerLinear; 1188 1189 GLuint SamplerLinear() const; 1190 1191 void ResolveTexturesForDraw() const; 1192 1193 RefPtr<WebGLProgram> mCurrentProgram; 1194 RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo; 1195 1196 bool ValidateFramebufferTarget(GLenum target) const; 1197 bool ValidateInvalidateFramebuffer(GLenum target, 1198 const Span<const GLenum>& attachments, 1199 std::vector<GLenum>* const scopedVector, 1200 GLsizei* const out_glNumAttachments, 1201 const GLenum** const out_glAttachments); 1202 1203 RefPtr<WebGLFramebuffer> mBoundDrawFramebuffer; 1204 RefPtr<WebGLFramebuffer> mBoundReadFramebuffer; 1205 RefPtr<WebGLTransformFeedback> mBoundTransformFeedback; 1206 RefPtr<WebGLVertexArray> mBoundVertexArray; 1207 1208 public: 1209 const auto& BoundReadFb() const { return mBoundReadFramebuffer; } 1210 1211 protected: 1212 RefPtr<WebGLTransformFeedback> mDefaultTransformFeedback; 1213 RefPtr<WebGLVertexArray> mDefaultVertexArray; 1214 1215 //////////////////////////////////// 1216 1217 protected: 1218 GLuint mEmptyTFO = 0; 1219 1220 // Generic Vertex Attributes 1221 // Though CURRENT_VERTEX_ATTRIB is listed under "Vertex Shader State" in the 1222 // spec state tables, this isn't vertex shader /object/ state. This array is 1223 // merely state useful to vertex shaders, but is global state. 1224 std::vector<webgl::AttribBaseType> mGenericVertexAttribTypes; 1225 CacheInvalidator mGenericVertexAttribTypeInvalidator; 1226 1227 GLuint mFakeVertexAttrib0BufferObject = 0; 1228 intptr_t mFakeVertexAttrib0BufferAllocSize = 0; 1229 intptr_t mFakeVertexAttrib0BufferInitializedSize = 0; 1230 alignas(alignof(float)) uint8_t 1231 mGenericVertexAttrib0Data[sizeof(float) * 4] = {}; 1232 alignas(alignof(float)) uint8_t 1233 mFakeVertexAttrib0Data[sizeof(float) * 4] = {}; 1234 1235 GLint mStencilRefFront = 0; 1236 GLint mStencilRefBack = 0; 1237 GLuint mStencilValueMaskFront = 0; 1238 GLuint mStencilValueMaskBack = 0; 1239 GLuint mStencilWriteMaskFront = 0; 1240 GLuint mStencilWriteMaskBack = 0; 1241 uint8_t mColorWriteMask0 = 0xf; // bitmask 1242 mutable uint8_t mDriverColorMask0 = 0xf; 1243 bool mDepthWriteMask = true; 1244 GLfloat mColorClearValue[4] = {0, 0, 0, 0}; 1245 GLint mStencilClearValue = 0; 1246 GLfloat mDepthClearValue = 1.0f; 1247 1248 std::bitset<webgl::kMaxDrawBuffers> mColorWriteMaskNonzero = -1; 1249 std::bitset<webgl::kMaxDrawBuffers> mBlendEnabled = 0; 1250 1251 std::unordered_set<GLenum> mIsEnabledMapKeys; 1252 1253 GLint mViewportX = 0; 1254 GLint mViewportY = 0; 1255 GLsizei mViewportWidth = 0; 1256 GLsizei mViewportHeight = 0; 1257 bool mAlreadyWarnedAboutViewportLargerThanDest = false; 1258 1259 GLfloat mLineWidth = 1.0; 1260 1261 WebGLContextLossHandler mContextLossHandler; 1262 1263 // Used for some hardware (particularly Tegra 2 and 4) that likes to 1264 // be Flushed while doing hundreds of draw calls. 1265 mutable uint64_t mDrawCallsSinceLastFlush = 0; 1266 1267 mutable uint64_t mWarningCount = 0; 1268 const uint64_t mMaxWarnings = StaticPrefs::webgl_max_warnings_per_context(); 1269 bool mAlreadyWarnedAboutFakeVertexAttrib0 = false; 1270 1271 bool ShouldGenerateWarnings() const { return mWarningCount < mMaxWarnings; } 1272 1273 bool ShouldGeneratePerfWarnings() const { 1274 return mNumPerfWarnings < mMaxPerfWarnings; 1275 } 1276 1277 bool mNeedsFakeNoAlpha = false; 1278 bool mNeedsFakeNoDepth = false; 1279 bool mNeedsFakeNoStencil = false; 1280 1281 bool mDriverDepthTest = false; 1282 bool mDriverStencilTest = false; 1283 1284 bool mNeedsLegacyVertexAttrib0Handling = false; 1285 bool mMaybeNeedsLegacyVertexAttrib0Handling = false; 1286 bool mNeedsIndexValidation = false; 1287 bool mBug_DrawArraysInstancedUserAttribFetchAffectedByFirst = false; 1288 1289 const bool mAllowFBInvalidation = StaticPrefs::webgl_allow_fb_invalidation(); 1290 1291 bool Has64BitTimestamps() const; 1292 1293 // -- 1294 1295 const uint8_t mMsaaSamples = 1296 static_cast<uint8_t>(StaticPrefs::webgl_msaa_samples()); 1297 mutable uvec2 mRequestedSize; 1298 mutable UniquePtr<gl::MozFramebuffer> mDefaultFB; 1299 mutable bool mDefaultFB_IsInvalid = false; 1300 mutable UniquePtr<gl::MozFramebuffer> mResolvedDefaultFB; 1301 1302 mutable std::unordered_map<std::tuple<gfx::ColorSpace2, gfx::ColorSpace2>, 1303 std::shared_ptr<gl::Texture>> 1304 mLutTexByColorMapping; 1305 1306 gl::SwapChain mSwapChain; 1307 gl::SwapChain mWebVRSwapChain; 1308 gl::SwapChain mSnapshotSwapChain; 1309 1310 RefPtr<layers::RemoteTextureOwnerClient> mRemoteTextureOwner; 1311 1312 bool PushRemoteTexture( 1313 WebGLFramebuffer*, gl::SwapChain&, std::shared_ptr<gl::SharedSurface>, 1314 const webgl::SwapChainOptions& options, 1315 layers::RemoteTextureOwnerClient* ownerClient = nullptr); 1316 1317 void EnsureContextLostRemoteTextureOwner( 1318 const webgl::SwapChainOptions& options); 1319 1320 public: 1321 void WaitForTxn(layers::RemoteTextureOwnerId ownerId, 1322 layers::RemoteTextureTxnType txnType, 1323 layers::RemoteTextureTxnId txnId); 1324 1325 // -- 1326 1327 protected: 1328 bool EnsureDefaultFB(); 1329 bool ValidateAndInitFB( 1330 const WebGLFramebuffer* fb, 1331 GLenum incompleteFbError = LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION); 1332 void DoBindFB(const WebGLFramebuffer* fb, 1333 GLenum target = LOCAL_GL_FRAMEBUFFER) const; 1334 1335 bool BindCurFBForDraw(); 1336 bool BindCurFBForColorRead( 1337 const webgl::FormatUsageInfo** out_format, uint32_t* out_width, 1338 uint32_t* out_height, 1339 GLenum incompleteFbError = LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION); 1340 void DoColorMask(Maybe<GLuint> i, uint8_t bitmask) const; 1341 void BlitBackbufferToCurDriverFB( 1342 WebGLFramebuffer* const srcAsWebglFb = nullptr, 1343 const gl::MozFramebuffer* const srcAsMozFb = nullptr, 1344 bool srcIsBGRA = false, bool yFlip = false, 1345 Maybe<gfxAlphaType> convertAlpha = {}) const; 1346 1347 struct GetDefaultFBForReadDesc { 1348 bool endOfFrame = false; 1349 }; 1350 const gl::MozFramebuffer* GetDefaultFBForRead(const GetDefaultFBForReadDesc&); 1351 const gl::MozFramebuffer* GetDefaultFBForRead() { 1352 return GetDefaultFBForRead({}); 1353 } 1354 1355 bool BindDefaultFBForRead(); 1356 1357 // -- 1358 1359 public: 1360 // console logging helpers 1361 template <typename... Args> 1362 void GenerateWarning(const char* const fmt, const Args&... args) const { 1363 GenerateError(0, fmt, args...); 1364 } 1365 1366 template <typename... Args> 1367 void GeneratePerfWarning(const char* const fmt, const Args&... args) const { 1368 if (ShouldGeneratePerfWarnings()) { 1369 GenerateError(webgl::kErrorPerfWarning, fmt, args...); 1370 } 1371 } 1372 1373 public: 1374 std::unique_ptr<webgl::FormatUsageAuthority> mFormatUsage; 1375 1376 virtual std::unique_ptr<webgl::FormatUsageAuthority> CreateFormatUsage( 1377 gl::GLContext* gl) const; 1378 1379 const decltype(mBound2DTextures)* TexListForElemType(GLenum elemType) const; 1380 1381 // Friend list 1382 friend class ScopedCopyTexImageSource; 1383 friend class ScopedResolveTexturesForDraw; 1384 friend class webgl::TexUnpackBlob; 1385 friend class webgl::TexUnpackBytes; 1386 friend class webgl::TexUnpackSurface; 1387 friend struct webgl::UniformInfo; 1388 friend class WebGLTexture; 1389 friend class WebGLFBAttachPoint; 1390 friend class WebGLFramebuffer; 1391 friend class WebGLRenderbuffer; 1392 friend class WebGLProgram; 1393 friend class WebGLQuery; 1394 friend class WebGLBuffer; 1395 friend class WebGLSampler; 1396 friend class WebGLShader; 1397 friend class WebGLSync; 1398 friend class WebGLTransformFeedback; 1399 friend class WebGLVertexArray; 1400 friend class WebGLVertexArrayFake; 1401 friend class WebGLVertexArrayGL; 1402 }; 1403 1404 // Returns `value` rounded to the next highest multiple of `multiple`. 1405 // AKA PadToAlignment, StrideForAlignment. 1406 template <typename V, typename M> 1407 V RoundUpToMultipleOf(const V& value, const M& multiple) { 1408 return ((value + multiple - 1) / multiple) * multiple; 1409 } 1410 1411 class ScopedFBRebinder final { 1412 private: 1413 const WebGLContext* const mWebGL; 1414 1415 public: 1416 explicit ScopedFBRebinder(const WebGLContext* const webgl) : mWebGL(webgl) {} 1417 ~ScopedFBRebinder(); 1418 }; 1419 1420 // - 1421 1422 constexpr inline bool IsBufferTargetLazilyBound(const GLenum target) { 1423 return target != LOCAL_GL_ELEMENT_ARRAY_BUFFER; 1424 } 1425 1426 void DoBindBuffer(gl::GLContext&, GLenum target, const WebGLBuffer*); 1427 1428 class ScopedLazyBind final { 1429 private: 1430 gl::GLContext& mGL; 1431 const GLenum mTarget; 1432 1433 public: 1434 ScopedLazyBind(gl::GLContext* const gl, const GLenum target, 1435 const WebGLBuffer* const buf) 1436 : mGL(*gl), mTarget(IsBufferTargetLazilyBound(target) ? target : 0) { 1437 if (mTarget) { 1438 DoBindBuffer(mGL, mTarget, buf); 1439 } 1440 } 1441 1442 ~ScopedLazyBind() { 1443 if (mTarget) { 1444 DoBindBuffer(mGL, mTarget, nullptr); 1445 } 1446 } 1447 }; 1448 1449 //// 1450 1451 bool Intersect(int32_t srcSize, int32_t read0, int32_t readSize, 1452 int32_t* out_intRead0, int32_t* out_intWrite0, 1453 int32_t* out_intSize); 1454 1455 uint64_t AvailGroups(uint64_t totalAvailItems, uint64_t firstItemOffset, 1456 uint32_t groupSize, uint32_t groupStride); 1457 1458 //// 1459 1460 class ScopedDrawCallWrapper final { 1461 public: 1462 WebGLContext& mWebGL; 1463 1464 explicit ScopedDrawCallWrapper(WebGLContext& webgl); 1465 ~ScopedDrawCallWrapper(); 1466 }; 1467 1468 namespace webgl { 1469 1470 class ScopedPrepForResourceClear final { 1471 const WebGLContext& webgl; 1472 1473 public: 1474 explicit ScopedPrepForResourceClear(const WebGLContext&); 1475 ~ScopedPrepForResourceClear(); 1476 }; 1477 1478 struct IndexedName final { 1479 std::string name; 1480 uint64_t index; 1481 }; 1482 Maybe<IndexedName> ParseIndexed(const std::string& str); 1483 1484 } // namespace webgl 1485 1486 webgl::LinkActiveInfo GetLinkActiveInfo( 1487 gl::GLContext& gl, const GLuint prog, const bool webgl2, 1488 const std::unordered_map<std::string, std::string>& nameUnmap); 1489 1490 } // namespace mozilla 1491 1492 #endif