tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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