tor-browser

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

HostWebGLContext.h (27161B)


      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 HOSTWEBGLCONTEXT_H_
      7 #define HOSTWEBGLCONTEXT_H_
      8 
      9 #include <memory>
     10 #include <unordered_map>
     11 #include <unordered_set>
     12 #include <vector>
     13 
     14 #include "ClientWebGLContext.h"
     15 #include "GLContext.h"
     16 #include "WebGL2Context.h"
     17 #include "WebGLCommandQueue.h"
     18 #include "WebGLContext.h"
     19 #include "WebGLFramebuffer.h"
     20 #include "WebGLTypes.h"
     21 #include "mozilla/GfxMessageUtils.h"
     22 #include "mozilla/Maybe.h"
     23 #include "mozilla/dom/BindingUtils.h"
     24 
     25 namespace mozilla {
     26 
     27 namespace dom {
     28 class WebGLParent;
     29 }
     30 namespace layers {
     31 class CompositableHost;
     32 }
     33 
     34 struct LockedOutstandingContexts final {
     35 private:
     36  // StaticMutexAutoLock lock; // We can't use it directly (STACK_CLASS), but
     37  // this is effectively what we hold via RAII.
     38 
     39 public:
     40  const std::unordered_set<HostWebGLContext*>& contexts;
     41 
     42  LockedOutstandingContexts();
     43  ~LockedOutstandingContexts();
     44 };
     45 
     46 /**
     47 * Host endpoint of a WebGLContext.  HostWebGLContext owns a WebGLContext
     48 * that it uses to execute commands sent from its ClientWebGLContext.
     49 *
     50 * A HostWebGLContext continuously issues a Task to the Compositor thread that
     51 * causes it to drain its queue of commands.  It also maintains a map of WebGL
     52 * objects (e.g. ObjectIdMap<WebGLShader>) that it uses associate them with
     53 * their cross-process IDs.
     54 *
     55 * This class is not an implementation of the
     56 * nsICanvasRenderingContextInternal DOM class.  That is the
     57 * ClientWebGLContext.
     58 */
     59 class HostWebGLContext final : public SupportsWeakPtr {
     60  friend class WebGLContext;
     61  friend class WebGLMemoryTracker;
     62  friend class dom::WebGLParent;
     63 
     64  using ObjectId = webgl::ObjectId;
     65 
     66  static std::unique_ptr<LockedOutstandingContexts> OutstandingContexts() {
     67    return std::make_unique<LockedOutstandingContexts>();
     68  }
     69 
     70 public:
     71  struct OwnerData final {
     72    ClientWebGLContext* inProcess = nullptr;
     73    dom::WebGLParent* outOfProcess = nullptr;
     74  };
     75 
     76  static std::unique_ptr<HostWebGLContext> Create(
     77      const OwnerData&, const webgl::InitContextDesc&,
     78      webgl::InitContextResult* out);
     79 
     80 private:
     81  explicit HostWebGLContext(const OwnerData&);
     82 
     83 public:
     84  virtual ~HostWebGLContext();
     85 
     86  WebGLContext* GetWebGLContext() const { return mContext; }
     87 
     88 public:
     89  const OwnerData mOwnerData;
     90 
     91 private:
     92  RefPtr<WebGLContext> mContext;
     93 
     94 #define _(X) std::unordered_map<ObjectId, RefPtr<WebGL##X>> m##X##Map;
     95 
     96  _(Buffer)
     97  _(Framebuffer)
     98  _(Program)
     99  _(Query)
    100  _(Renderbuffer)
    101  _(Sampler)
    102  _(Shader)
    103  _(Sync)
    104  _(Texture)
    105  _(TransformFeedback)
    106  _(VertexArray)
    107 
    108 #undef _
    109 
    110  class AutoResolveT final {
    111    friend class HostWebGLContext;
    112 
    113    const HostWebGLContext& mParent;
    114    const ObjectId mId;
    115 
    116   public:
    117    AutoResolveT(const HostWebGLContext& parent, const ObjectId id)
    118        : mParent(parent), mId(id) {}
    119 
    120 #define _(X)                                              \
    121  WebGL##X* As(WebGL##X*) const {                         \
    122    const auto maybe = MaybeFind(mParent.m##X##Map, mId); \
    123    if (!maybe) return nullptr;                           \
    124    return maybe->get();                                  \
    125  }
    126 
    127    _(Buffer)
    128    _(Framebuffer)
    129    _(Program)
    130    _(Query)
    131    _(Renderbuffer)
    132    _(Sampler)
    133    _(Shader)
    134    _(Sync)
    135    _(Texture)
    136    _(TransformFeedback)
    137    _(VertexArray)
    138 
    139 #undef _
    140    template <typename T>
    141    MOZ_IMPLICIT operator T*() const {
    142      T* coercer = nullptr;
    143      return As(coercer);
    144    }
    145 
    146    template <typename T>
    147    MOZ_IMPLICIT operator const T*() const {
    148      T* coercer = nullptr;
    149      return As(coercer);
    150    }
    151  };
    152 
    153  AutoResolveT AutoResolve(const ObjectId id) const { return {*this, id}; }
    154  template <typename T>
    155  T* ById(const ObjectId id) const {
    156    T* coercer = nullptr;
    157    return AutoResolve(id).As(coercer);
    158  }
    159 
    160  // -------------------------------------------------------------------------
    161  // Host-side methods.  Calls in the client are forwarded to the host.
    162  // -------------------------------------------------------------------------
    163 
    164 public:
    165  // ------------------------- Composition -------------------------
    166 
    167  void SetCompositableHost(RefPtr<layers::CompositableHost>& compositableHost) {
    168    mContext->SetCompositableHost(compositableHost);
    169  }
    170 
    171  void Present(const ObjectId xrFb, const layers::TextureType t,
    172               const bool webvr, const webgl::SwapChainOptions& options) const {
    173    return (void)mContext->Present(AutoResolve(xrFb), t, webvr, options);
    174  }
    175  void CopyToSwapChain(const ObjectId fb, const layers::TextureType t,
    176                       const webgl::SwapChainOptions& options) const {
    177    return (void)mContext->CopyToSwapChain(AutoResolve(fb), t, options);
    178  }
    179  void WaitForTxn(const layers::RemoteTextureOwnerId aOwnerId,
    180                  const layers::RemoteTextureTxnType txnType,
    181                  const layers::RemoteTextureTxnId txnId) {
    182    mContext->WaitForTxn(aOwnerId, txnType, txnId);
    183  }
    184  void EndOfFrame() const { return (void)mContext->EndOfFrame(); }
    185  Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ObjectId xrFb,
    186                                                  const bool webvr) const;
    187 
    188  // -
    189 
    190  Maybe<uvec2> FrontBufferSnapshotInto(Maybe<Range<uint8_t>> dest) const {
    191    return mContext->FrontBufferSnapshotInto(dest);
    192  }
    193 
    194  Maybe<uvec2> FrontBufferSnapshotInto(
    195      std::shared_ptr<gl::SharedSurface>& front,
    196      Maybe<Range<uint8_t>> dest) const {
    197    return mContext->FrontBufferSnapshotInto(front, dest);
    198  }
    199 
    200  void ClearVRSwapChain() const { mContext->ClearVRSwapChain(); }
    201 
    202  // -
    203 
    204  void SetDrawingBufferColorSpace(const dom::PredefinedColorSpace val) const {
    205    mContext->SetDrawingBufferColorSpace(val);
    206  }
    207  void SetUnpackColorSpace(const dom::PredefinedColorSpace val) const {
    208    mContext->SetUnpackColorSpace(val);
    209  }
    210  void Resize(const uvec2& size) { return mContext->Resize(size); }
    211 
    212  uvec2 DrawingBufferSize() { return mContext->DrawingBufferSize(); }
    213 
    214  void OnMemoryPressure() { return mContext->OnMemoryPressure(); }
    215 
    216  void DidRefresh() { mContext->DidRefresh(); }
    217 
    218  void GenerateError(const GLenum error, const std::string& text) const {
    219    mContext->GenerateErrorImpl(error, text);
    220  }
    221 
    222  void OnContextLoss(webgl::ContextLossReason);
    223 
    224  void RequestExtension(const WebGLExtensionID ext) {
    225    mContext->RequestExtension(ext);
    226  }
    227 
    228  // -
    229  // Child-ward
    230 
    231  void JsWarning(const std::string&) const;
    232 
    233  // -
    234  // Creation and destruction
    235 
    236  void CreateBuffer(ObjectId);
    237  void CreateFramebuffer(ObjectId);
    238  bool CreateOpaqueFramebuffer(ObjectId,
    239                               const webgl::OpaqueFramebufferOptions& options);
    240  void CreateProgram(ObjectId);
    241  void CreateQuery(ObjectId);
    242  void CreateRenderbuffer(ObjectId);
    243  void CreateSampler(ObjectId);
    244  void CreateShader(ObjectId, GLenum type);
    245  void CreateSync(ObjectId);
    246  void CreateTexture(ObjectId);
    247  void CreateTransformFeedback(ObjectId);
    248  void CreateVertexArray(ObjectId);
    249 
    250  void DeleteBuffer(ObjectId);
    251  void DeleteFramebuffer(ObjectId);
    252  void DeleteProgram(ObjectId);
    253  void DeleteQuery(ObjectId);
    254  void DeleteRenderbuffer(ObjectId);
    255  void DeleteSampler(ObjectId);
    256  void DeleteShader(ObjectId);
    257  void DeleteSync(ObjectId);
    258  void DeleteTexture(ObjectId);
    259  void DeleteTransformFeedback(ObjectId);
    260  void DeleteVertexArray(ObjectId);
    261 
    262  // ------------------------- GL State -------------------------
    263  bool IsContextLost() const { return mContext->IsContextLost(); }
    264 
    265  void SetEnabled(GLenum cap, Maybe<GLuint> i, bool val) const {
    266    mContext->SetEnabled(cap, i, val);
    267  }
    268 
    269  Maybe<double> GetNumber(GLenum pname) const {
    270    return mContext->GetParameter(pname);
    271  }
    272 
    273  Maybe<std::string> GetString(GLenum pname) const {
    274    return mContext->GetString(pname);
    275  }
    276 
    277  void AttachShader(ObjectId prog, ObjectId shader) const {
    278    const auto pProg = ById<WebGLProgram>(prog);
    279    const auto pShader = ById<WebGLShader>(shader);
    280    if (!pProg || !pShader) return;
    281    mContext->AttachShader(*pProg, *pShader);
    282  }
    283 
    284  void BindAttribLocation(ObjectId id, GLuint location,
    285                          const std::string& name) const {
    286    const auto obj = ById<WebGLProgram>(id);
    287    if (!obj) return;
    288    mContext->BindAttribLocation(*obj, location, name);
    289  }
    290 
    291  void BindFramebuffer(GLenum target, ObjectId id) const {
    292    mContext->BindFramebuffer(target, AutoResolve(id));
    293  }
    294 
    295  void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) const {
    296    mContext->BlendColor(r, g, b, a);
    297  }
    298 
    299  void BlendEquationSeparate(Maybe<GLuint> i, GLenum modeRGB,
    300                             GLenum modeAlpha) const {
    301    mContext->BlendEquationSeparate(i, modeRGB, modeAlpha);
    302  }
    303 
    304  void BlendFuncSeparate(Maybe<GLuint> i, GLenum srcRGB, GLenum dstRGB,
    305                         GLenum srcAlpha, GLenum dstAlpha) const {
    306    mContext->BlendFuncSeparate(i, srcRGB, dstRGB, srcAlpha, dstAlpha);
    307  }
    308 
    309  GLenum CheckFramebufferStatus(GLenum target) const {
    310    return mContext->CheckFramebufferStatus(target);
    311  }
    312 
    313  void Clear(GLbitfield mask) const { mContext->Clear(mask); }
    314 
    315  void ClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) const {
    316    mContext->ClearColor(r, g, b, a);
    317  }
    318 
    319  void ClearDepth(GLclampf v) const { mContext->ClearDepth(v); }
    320 
    321  void ClearStencil(GLint v) const { mContext->ClearStencil(v); }
    322 
    323  void ColorMask(Maybe<GLuint> i, uint8_t mask) const {
    324    mContext->ColorMask(i, mask);
    325  }
    326 
    327  void CompileShader(const ObjectId id) const {
    328    const auto obj = ById<WebGLShader>(id);
    329    if (!obj) return;
    330    mContext->CompileShader(*obj);
    331  }
    332 
    333  void CullFace(GLenum face) const { mContext->CullFace(face); }
    334 
    335  void DepthFunc(GLenum func) const { mContext->DepthFunc(func); }
    336 
    337  void DepthMask(WebGLboolean b) const { mContext->DepthMask(b); }
    338 
    339  void DepthRange(GLclampf zNear, GLclampf zFar) const {
    340    mContext->DepthRange(zNear, zFar);
    341  }
    342 
    343  void DetachShader(const ObjectId prog, const ObjectId shader) const {
    344    const auto pProg = ById<WebGLProgram>(prog);
    345    const auto pShader = ById<WebGLShader>(shader);
    346    if (!pProg || !pShader) return;
    347    mContext->DetachShader(*pProg, *pShader);
    348  }
    349 
    350  void Flush() const { mContext->Flush(); }
    351 
    352  void Finish() const { mContext->Finish(); }
    353 
    354  void FramebufferAttach(const GLenum target, const GLenum attachSlot,
    355                         const GLenum bindImageTarget, const ObjectId id,
    356                         const GLint mipLevel, const GLint zLayerBase,
    357                         const GLsizei numViewLayers) const {
    358    webgl::FbAttachInfo toAttach;
    359    toAttach.rb = AutoResolve(id);
    360    toAttach.tex = AutoResolve(id);
    361    toAttach.mipLevel = mipLevel;
    362    toAttach.zLayer = zLayerBase;
    363    if (numViewLayers) {
    364      toAttach.zLayerCount = numViewLayers;
    365      toAttach.isMultiview = true;
    366    }
    367 
    368    mContext->FramebufferAttach(target, attachSlot, bindImageTarget, toAttach);
    369  }
    370 
    371  void FrontFace(GLenum mode) const { mContext->FrontFace(mode); }
    372 
    373  Maybe<double> GetBufferParameter(GLenum target, GLenum pname) const {
    374    return mContext->GetBufferParameter(target, pname);
    375  }
    376 
    377  webgl::CompileResult GetCompileResult(ObjectId id) const {
    378    const auto obj = ById<WebGLShader>(id);
    379    if (!obj) return {};
    380    return mContext->GetCompileResult(*obj);
    381  }
    382 
    383  GLenum GetError() const { return mContext->GetError(); }
    384 
    385  GLint GetFragDataLocation(ObjectId id, const std::string& name) const {
    386    const auto obj = ById<WebGLProgram>(id);
    387    if (!obj) return -1;
    388    return mContext->GetFragDataLocation(*obj, name);
    389  }
    390 
    391  Maybe<double> GetFramebufferAttachmentParameter(ObjectId id,
    392                                                  GLenum attachment,
    393                                                  GLenum pname) const {
    394    return mContext->GetFramebufferAttachmentParameter(AutoResolve(id),
    395                                                       attachment, pname);
    396  }
    397 
    398  webgl::LinkResult GetLinkResult(ObjectId id) const {
    399    const auto obj = ById<WebGLProgram>(id);
    400    if (!obj) return {};
    401    return mContext->GetLinkResult(*obj);
    402  }
    403 
    404  Maybe<double> GetRenderbufferParameter(ObjectId id, GLenum pname) const {
    405    const auto obj = ById<WebGLRenderbuffer>(id);
    406    if (!obj) return {};
    407    return mContext->GetRenderbufferParameter(*obj, pname);
    408  }
    409 
    410  webgl::GetUniformData GetUniform(ObjectId id, uint32_t loc) const {
    411    const auto obj = ById<WebGLProgram>(id);
    412    if (!obj) return {};
    413    return mContext->GetUniform(*obj, loc);
    414  }
    415 
    416  void Hint(GLenum target, GLenum mode) const { mContext->Hint(target, mode); }
    417 
    418  void LineWidth(GLfloat width) const { mContext->LineWidth(width); }
    419 
    420  void LinkProgram(const ObjectId id) const {
    421    const auto obj = ById<WebGLProgram>(id);
    422    if (!obj) return;
    423    mContext->LinkProgram(*obj);
    424  }
    425 
    426  void PolygonOffset(GLfloat factor, GLfloat units) const {
    427    mContext->PolygonOffset(factor, units);
    428  }
    429 
    430  void SampleCoverage(GLclampf value, bool invert) const {
    431    mContext->SampleCoverage(value, invert);
    432  }
    433 
    434  void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) const {
    435    mContext->Scissor(x, y, width, height);
    436  }
    437 
    438  // TODO: s/nsAString/std::string/
    439  void ShaderSource(const ObjectId id, const std::string& source) const {
    440    const auto obj = ById<WebGLShader>(id);
    441    if (!obj) return;
    442    mContext->ShaderSource(*obj, source);
    443  }
    444 
    445  void StencilFuncSeparate(GLenum face, GLenum func, GLint ref,
    446                           GLuint mask) const {
    447    mContext->StencilFuncSeparate(face, func, ref, mask);
    448  }
    449  void StencilMaskSeparate(GLenum face, GLuint mask) const {
    450    mContext->StencilMaskSeparate(face, mask);
    451  }
    452  void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
    453                         GLenum dppass) const {
    454    mContext->StencilOpSeparate(face, sfail, dpfail, dppass);
    455  }
    456 
    457  void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) const {
    458    mContext->Viewport(x, y, width, height);
    459  }
    460 
    461  // ------------------------- Buffer Objects -------------------------
    462  void BindBuffer(GLenum target, const ObjectId id) const {
    463    mContext->BindBuffer(target, AutoResolve(id));
    464  }
    465 
    466  void BindBufferRange(GLenum target, GLuint index, const ObjectId id,
    467                       uint64_t offset, uint64_t size) const {
    468    GetWebGL2Context()->BindBufferRange(target, index, AutoResolve(id), offset,
    469                                        size);
    470  }
    471 
    472  void CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
    473                         uint64_t readOffset, uint64_t writeOffset,
    474                         uint64_t size) const {
    475    GetWebGL2Context()->CopyBufferSubData(readTarget, writeTarget, readOffset,
    476                                          writeOffset, size);
    477  }
    478 
    479  bool GetBufferSubData(GLenum target, uint64_t srcByteOffset,
    480                        const Range<uint8_t>& dest) const {
    481    return GetWebGL2Context()->GetBufferSubData(target, srcByteOffset, dest);
    482  }
    483 
    484  void BufferData(GLenum target, const Span<const uint8_t>& srcData,
    485                  GLenum usage) const {
    486    mContext->BufferData(target, srcData.size(), srcData.data(), usage);
    487  }
    488 
    489  void BufferData_SizeOnly(GLenum target, size_t byteSize, GLenum usage) const {
    490    mContext->BufferData(target, byteSize, nullptr, usage);
    491  }
    492 
    493  void BufferSubData(GLenum target, uint64_t dstByteOffset,
    494                     const Span<const uint8_t>& srcData,
    495                     bool unsynchronized = false) const {
    496    mContext->BufferSubData(target, dstByteOffset, srcData.size(),
    497                            srcData.data(), unsynchronized);
    498  }
    499 
    500  // -------------------------- Framebuffer Objects --------------------------
    501  void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
    502                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
    503                       GLbitfield mask, GLenum filter) const {
    504    GetWebGL2Context()->BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0,
    505                                        dstY0, dstX1, dstY1, mask, filter);
    506  }
    507 
    508  void InvalidateFramebuffer(GLenum target,
    509                             const Span<const GLenum>& attachments) const {
    510    GetWebGL2Context()->InvalidateFramebuffer(target, attachments);
    511  }
    512 
    513  void InvalidateSubFramebuffer(GLenum target,
    514                                const Span<const GLenum>& attachments, GLint x,
    515                                GLint y, GLsizei width, GLsizei height) const {
    516    GetWebGL2Context()->InvalidateSubFramebuffer(target, attachments, x, y,
    517                                                 width, height);
    518  }
    519 
    520  void ReadBuffer(GLenum mode) const { GetWebGL2Context()->ReadBuffer(mode); }
    521 
    522  // ----------------------- Renderbuffer objects -----------------------
    523  Maybe<std::vector<int32_t>> GetInternalformatParameter(GLenum target,
    524                                                         GLenum internalformat,
    525                                                         GLenum pname) const {
    526    return GetWebGL2Context()->GetInternalformatParameter(
    527        target, internalformat, pname);
    528  }
    529 
    530  void RenderbufferStorageMultisample(ObjectId id, uint32_t samples,
    531                                      GLenum internalFormat, uint32_t width,
    532                                      uint32_t height) const {
    533    const auto obj = ById<WebGLRenderbuffer>(id);
    534    if (!obj) return;
    535    mContext->RenderbufferStorageMultisample(*obj, samples, internalFormat,
    536                                             width, height);
    537  }
    538 
    539  // --------------------------- Texture objects ---------------------------
    540  void ActiveTexture(uint32_t texUnit) const {
    541    mContext->ActiveTexture(texUnit);
    542  }
    543 
    544  void BindTexture(GLenum texTarget, const ObjectId id) const {
    545    mContext->BindTexture(texTarget, AutoResolve(id));
    546  }
    547 
    548  void GenerateMipmap(GLenum texTarget) const {
    549    mContext->GenerateMipmap(texTarget);
    550  }
    551 
    552  // CompressedTexSubImage if `sub`
    553  void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level,
    554                          GLenum format, const uvec3& offset, const uvec3& size,
    555                          const Span<const uint8_t>& src,
    556                          const uint32_t pboImageSize,
    557                          const Maybe<uint64_t>& pboOffset) const {
    558    mContext->CompressedTexImage(sub, imageTarget, level, format, offset, size,
    559                                 src, pboImageSize, pboOffset);
    560  }
    561 
    562  // CopyTexSubImage if `!respecFormat`
    563  void CopyTexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
    564                    const uvec3& dstOffset, const ivec2& srcOffset,
    565                    const uvec2& size) const {
    566    mContext->CopyTexImage(imageTarget, level, respecFormat, dstOffset,
    567                           srcOffset, size);
    568  }
    569 
    570  // TexSubImage if `!respecFormat`
    571  void TexImage(uint32_t level, GLenum respecFormat, const uvec3& offset,
    572                const webgl::PackingInfo& pi,
    573                const webgl::TexUnpackBlobDesc& src) const {
    574    mContext->TexImage(level, respecFormat, offset, pi, src);
    575  }
    576 
    577  void TexStorage(GLenum texTarget, uint32_t levels, GLenum internalFormat,
    578                  const uvec3& size) const {
    579    GetWebGL2Context()->TexStorage(texTarget, levels, internalFormat, size);
    580  }
    581 
    582  Maybe<double> GetTexParameter(ObjectId id, GLenum pname) const {
    583    const auto obj = ById<WebGLTexture>(id);
    584    if (!obj) return {};
    585    return mContext->GetTexParameter(*obj, pname);
    586  }
    587 
    588  void TexParameter_base(GLenum texTarget, GLenum pname,
    589                         const FloatOrInt& param) const {
    590    mContext->TexParameter_base(texTarget, pname, param);
    591  }
    592 
    593  // ------------------- Programs and shaders --------------------------------
    594  void UseProgram(ObjectId id) const { mContext->UseProgram(AutoResolve(id)); }
    595 
    596  bool ValidateProgram(ObjectId id) const {
    597    const auto obj = ById<WebGLProgram>(id);
    598    if (!obj) return false;
    599    return mContext->ValidateProgram(*obj);
    600  }
    601 
    602  // ------------------------ Uniforms and attributes ------------------------
    603 
    604  void UniformData(uint32_t loc, bool transpose,
    605                   const Span<const webgl::UniformDataVal>& data) const {
    606    mContext->UniformData(loc, transpose, data);
    607  }
    608 
    609  void VertexAttrib4T(GLuint index, const webgl::TypedQuad& data) const {
    610    mContext->VertexAttrib4T(index, data);
    611  }
    612 
    613  void VertexAttribDivisor(GLuint index, GLuint divisor) const {
    614    mContext->VertexAttribDivisor(index, divisor);
    615  }
    616 
    617  Maybe<double> GetIndexedParameter(GLenum target, GLuint index) const {
    618    return GetWebGL2Context()->GetIndexedParameter(target, index);
    619  }
    620 
    621  void UniformBlockBinding(const ObjectId id, GLuint uniformBlockIndex,
    622                           GLuint uniformBlockBinding) const {
    623    const auto obj = ById<WebGLProgram>(id);
    624    if (!obj) return;
    625    GetWebGL2Context()->UniformBlockBinding(*obj, uniformBlockIndex,
    626                                            uniformBlockBinding);
    627  }
    628 
    629  void EnableVertexAttribArray(GLuint index) const {
    630    mContext->EnableVertexAttribArray(index);
    631  }
    632 
    633  void DisableVertexAttribArray(GLuint index) const {
    634    mContext->DisableVertexAttribArray(index);
    635  }
    636 
    637  Maybe<double> GetVertexAttrib(GLuint index, GLenum pname) const {
    638    return mContext->GetVertexAttrib(index, pname);
    639  }
    640 
    641  void VertexAttribPointer(GLuint index,
    642                           const webgl::VertAttribPointerDesc& desc) const {
    643    mContext->VertexAttribPointer(index, desc);
    644  }
    645 
    646  // --------------------------- Buffer Operations --------------------------
    647  void ClearBufferTv(GLenum buffer, GLint drawBuffer,
    648                     const webgl::TypedQuad& data) const {
    649    GetWebGL2Context()->ClearBufferTv(buffer, drawBuffer, data);
    650  }
    651 
    652  void ClearBufferfi(GLenum buffer, GLint drawBuffer, GLfloat depth,
    653                     GLint stencil) const {
    654    GetWebGL2Context()->ClearBufferfi(buffer, drawBuffer, depth, stencil);
    655  }
    656 
    657  // ------------------------------ Readback -------------------------------
    658  void ReadPixelsPbo(const webgl::ReadPixelsDesc& desc,
    659                     const uint64_t offset) const {
    660    mContext->ReadPixelsPbo(desc, offset);
    661  }
    662 
    663  webgl::ReadPixelsResult ReadPixelsInto(const webgl::ReadPixelsDesc& desc,
    664                                         const Range<uint8_t>& dest) const {
    665    return mContext->ReadPixelsInto(desc, dest);
    666  }
    667 
    668  // ----------------------------- Sampler -----------------------------------
    669 
    670  void BindSampler(GLuint unit, ObjectId id) const {
    671    GetWebGL2Context()->BindSampler(unit, AutoResolve(id));
    672  }
    673 
    674  void SamplerParameteri(ObjectId id, GLenum pname, GLint param) const {
    675    const auto obj = ById<WebGLSampler>(id);
    676    if (!obj) return;
    677    GetWebGL2Context()->SamplerParameteri(*obj, pname, param);
    678  }
    679 
    680  void SamplerParameterf(ObjectId id, GLenum pname, GLfloat param) const {
    681    const auto obj = ById<WebGLSampler>(id);
    682    if (!obj) return;
    683    GetWebGL2Context()->SamplerParameterf(*obj, pname, param);
    684  }
    685 
    686  Maybe<double> GetSamplerParameter(ObjectId id, GLenum pname) const {
    687    const auto obj = ById<WebGLSampler>(id);
    688    if (!obj) return {};
    689    return GetWebGL2Context()->GetSamplerParameter(*obj, pname);
    690  }
    691 
    692  // ------------------------------- GL Sync ---------------------------------
    693 
    694  GLenum ClientWaitSync(ObjectId id, GLbitfield flags, GLuint64 timeout) const {
    695    const auto obj = ById<WebGLSync>(id);
    696    if (!obj) return LOCAL_GL_WAIT_FAILED;
    697    return GetWebGL2Context()->ClientWaitSync(*obj, flags, timeout);
    698  }
    699 
    700  // -------------------------- Transform Feedback ---------------------------
    701  void BindTransformFeedback(ObjectId id) const {
    702    GetWebGL2Context()->BindTransformFeedback(AutoResolve(id));
    703  }
    704 
    705  void BeginTransformFeedback(GLenum primitiveMode) const {
    706    GetWebGL2Context()->BeginTransformFeedback(primitiveMode);
    707  }
    708 
    709  void EndTransformFeedback() const {
    710    GetWebGL2Context()->EndTransformFeedback();
    711  }
    712 
    713  void PauseTransformFeedback() const {
    714    GetWebGL2Context()->PauseTransformFeedback();
    715  }
    716 
    717  void ResumeTransformFeedback() const {
    718    GetWebGL2Context()->ResumeTransformFeedback();
    719  }
    720 
    721  void TransformFeedbackVaryings(ObjectId id,
    722                                 const std::vector<std::string>& varyings,
    723                                 GLenum bufferMode) const {
    724    const auto obj = ById<WebGLProgram>(id);
    725    if (!obj) return;
    726    GetWebGL2Context()->TransformFeedbackVaryings(*obj, varyings, bufferMode);
    727  }
    728 
    729  // -------------------------- Opaque Framebuffers ---------------------------
    730  void SetFramebufferIsInOpaqueRAF(ObjectId id, bool value) {
    731    WebGLFramebuffer* fb = AutoResolve(id);
    732    if (fb) {
    733      fb->mInOpaqueRAF = value;
    734    }
    735  }
    736 
    737  // -------------------------------------------------------------------------
    738  // Host-side extension methods.  Calls in the client are forwarded to the
    739  // host. Some extension methods are also available in WebGL2 Contexts.  For
    740  // them, the final parameter is a boolean indicating if the call originated
    741  // from an extension.
    742  // -------------------------------------------------------------------------
    743 
    744  // Misc. Extensions
    745  void DrawBuffers(const std::vector<GLenum>& buffers) const {
    746    mContext->DrawBuffers(buffers);
    747  }
    748 
    749  // VertexArrayObjectEXT
    750  void BindVertexArray(ObjectId id) const {
    751    mContext->BindVertexArray(AutoResolve(id));
    752  }
    753 
    754  // InstancedElementsEXT
    755  void DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertCount,
    756                           GLsizei primCount) const {
    757    mContext->DrawArraysInstanced(mode, first, vertCount, primCount);
    758  }
    759 
    760  void DrawElementsInstanced(GLenum mode, GLsizei vertCount, GLenum type,
    761                             WebGLintptr offset, GLsizei primCount) const {
    762    mContext->DrawElementsInstanced(mode, vertCount, type, offset, primCount);
    763  }
    764 
    765  // GLQueryEXT
    766  void BeginQuery(GLenum target, ObjectId id) const {
    767    const auto obj = ById<WebGLQuery>(id);
    768    if (!obj) return;
    769    mContext->BeginQuery(target, *obj);
    770  }
    771 
    772  void EndQuery(GLenum target) const { mContext->EndQuery(target); }
    773 
    774  void QueryCounter(ObjectId id) const {
    775    const auto obj = ById<WebGLQuery>(id);
    776    if (!obj) return;
    777    mContext->QueryCounter(*obj);
    778  }
    779 
    780  Maybe<double> GetQueryParameter(ObjectId id, GLenum pname) const {
    781    const auto obj = ById<WebGLQuery>(id);
    782    if (!obj) return {};
    783    return mContext->GetQueryParameter(*obj, pname);
    784  }
    785 
    786  // WEBGL_provoking_vertex
    787  void ProvokingVertex(const webgl::ProvokingVertex mode) const {
    788    mContext->ProvokingVertex(mode);
    789  }
    790 
    791  // -------------------------------------------------------------------------
    792  // Client-side methods.  Calls in the Host are forwarded to the client.
    793  // -------------------------------------------------------------------------
    794 public:
    795  void OnLostContext();
    796  void OnRestoredContext();
    797 
    798 protected:
    799  WebGL2Context* GetWebGL2Context() const {
    800    MOZ_RELEASE_ASSERT(mContext->IsWebGL2(), "Requires WebGL2 context");
    801    return static_cast<WebGL2Context*>(mContext.get());
    802  }
    803 };
    804 
    805 }  // namespace mozilla
    806 
    807 #endif  // HOSTWEBGLCONTEXT_H_