summaryrefslogtreecommitdiffstats
path: root/dom/canvas/HostWebGLContext.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/HostWebGLContext.h')
-rw-r--r--dom/canvas/HostWebGLContext.h808
1 files changed, 808 insertions, 0 deletions
diff --git a/dom/canvas/HostWebGLContext.h b/dom/canvas/HostWebGLContext.h
new file mode 100644
index 0000000000..c508a164c8
--- /dev/null
+++ b/dom/canvas/HostWebGLContext.h
@@ -0,0 +1,808 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef HOSTWEBGLCONTEXT_H_
+#define HOSTWEBGLCONTEXT_H_
+
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/GfxMessageUtils.h"
+#include "ClientWebGLContext.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/UniquePtr.h"
+#include "GLContext.h"
+#include "WebGLContext.h"
+#include "WebGL2Context.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLTypes.h"
+#include "WebGLCommandQueue.h"
+
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+namespace mozilla {
+
+namespace dom {
+class WebGLParent;
+}
+namespace layers {
+class CompositableHost;
+}
+
+struct LockedOutstandingContexts final {
+ private:
+ // StaticMutexAutoLock lock; // We can't use it directly (STACK_CLASS), but
+ // this is effectively what we hold via RAII.
+
+ public:
+ const std::unordered_set<HostWebGLContext*>& contexts;
+
+ LockedOutstandingContexts();
+ ~LockedOutstandingContexts();
+};
+
+/**
+ * Host endpoint of a WebGLContext. HostWebGLContext owns a WebGLContext
+ * that it uses to execute commands sent from its ClientWebGLContext.
+ *
+ * A HostWebGLContext continuously issues a Task to the Compositor thread that
+ * causes it to drain its queue of commands. It also maintains a map of WebGL
+ * objects (e.g. ObjectIdMap<WebGLShader>) that it uses associate them with
+ * their cross-process IDs.
+ *
+ * This class is not an implementation of the
+ * nsICanvasRenderingContextInternal DOM class. That is the
+ * ClientWebGLContext.
+ */
+class HostWebGLContext final : public SupportsWeakPtr {
+ friend class WebGLContext;
+ friend class WebGLMemoryTracker;
+ friend class dom::WebGLParent;
+
+ using ObjectId = webgl::ObjectId;
+
+ static std::unique_ptr<LockedOutstandingContexts> OutstandingContexts() {
+ return std::make_unique<LockedOutstandingContexts>();
+ }
+
+ public:
+ struct OwnerData final {
+ ClientWebGLContext* inProcess = nullptr;
+ dom::WebGLParent* outOfProcess = nullptr;
+ };
+
+ static UniquePtr<HostWebGLContext> Create(const OwnerData&,
+ const webgl::InitContextDesc&,
+ webgl::InitContextResult* out);
+
+ private:
+ explicit HostWebGLContext(const OwnerData&);
+
+ public:
+ virtual ~HostWebGLContext();
+
+ WebGLContext* GetWebGLContext() const { return mContext; }
+
+ public:
+ const OwnerData mOwnerData;
+
+ private:
+ RefPtr<WebGLContext> mContext;
+
+#define _(X) std::unordered_map<ObjectId, RefPtr<WebGL##X>> m##X##Map;
+
+ _(Buffer)
+ _(Framebuffer)
+ _(Program)
+ _(Query)
+ _(Renderbuffer)
+ _(Sampler)
+ _(Shader)
+ _(Sync)
+ _(Texture)
+ _(TransformFeedback)
+ _(VertexArray)
+
+#undef _
+
+ class AutoResolveT final {
+ friend class HostWebGLContext;
+
+ const HostWebGLContext& mParent;
+ const ObjectId mId;
+
+ public:
+ AutoResolveT(const HostWebGLContext& parent, const ObjectId id)
+ : mParent(parent), mId(id) {}
+
+#define _(X) \
+ WebGL##X* As(WebGL##X*) const { \
+ const auto maybe = MaybeFind(mParent.m##X##Map, mId); \
+ if (!maybe) return nullptr; \
+ return maybe->get(); \
+ }
+
+ _(Buffer)
+ _(Framebuffer)
+ _(Program)
+ _(Query)
+ _(Renderbuffer)
+ _(Sampler)
+ _(Shader)
+ _(Sync)
+ _(Texture)
+ _(TransformFeedback)
+ _(VertexArray)
+
+#undef _
+ template <typename T>
+ MOZ_IMPLICIT operator T*() const {
+ T* coercer = nullptr;
+ return As(coercer);
+ }
+
+ template <typename T>
+ MOZ_IMPLICIT operator const T*() const {
+ T* coercer = nullptr;
+ return As(coercer);
+ }
+ };
+
+ AutoResolveT AutoResolve(const ObjectId id) const { return {*this, id}; }
+ template <typename T>
+ T* ById(const ObjectId id) const {
+ T* coercer = nullptr;
+ return AutoResolve(id).As(coercer);
+ }
+
+ // -------------------------------------------------------------------------
+ // Host-side methods. Calls in the client are forwarded to the host.
+ // -------------------------------------------------------------------------
+
+ public:
+ // ------------------------- Composition -------------------------
+
+ void SetCompositableHost(RefPtr<layers::CompositableHost>& compositableHost) {
+ mContext->SetCompositableHost(compositableHost);
+ }
+
+ void Present(const ObjectId xrFb, const layers::TextureType t,
+ const bool webvr, const webgl::SwapChainOptions& options) const {
+ return (void)mContext->Present(AutoResolve(xrFb), t, webvr, options);
+ }
+ void CopyToSwapChain(const ObjectId fb, const layers::TextureType t,
+ const webgl::SwapChainOptions& options) const {
+ return (void)mContext->CopyToSwapChain(AutoResolve(fb), t, options);
+ }
+ void WaitForTxn(const layers::RemoteTextureOwnerId aOwnerId,
+ const layers::RemoteTextureTxnType txnType,
+ const layers::RemoteTextureTxnId txnId) {
+ mContext->WaitForTxn(aOwnerId, txnType, txnId);
+ }
+ void EndOfFrame() const { return (void)mContext->EndOfFrame(); }
+ Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ObjectId xrFb,
+ const bool webvr) const;
+
+ // -
+
+ Maybe<uvec2> FrontBufferSnapshotInto(Maybe<Range<uint8_t>> dest) const {
+ return mContext->FrontBufferSnapshotInto(dest);
+ }
+
+ Maybe<uvec2> FrontBufferSnapshotInto(
+ std::shared_ptr<gl::SharedSurface>& front,
+ Maybe<Range<uint8_t>> dest) const {
+ return mContext->FrontBufferSnapshotInto(front, dest);
+ }
+
+ void ClearVRSwapChain() const { mContext->ClearVRSwapChain(); }
+
+ // -
+
+ void Resize(const uvec2& size) { return mContext->Resize(size); }
+
+ uvec2 DrawingBufferSize() { return mContext->DrawingBufferSize(); }
+
+ void OnMemoryPressure() { return mContext->OnMemoryPressure(); }
+
+ void DidRefresh() { mContext->DidRefresh(); }
+
+ void GenerateError(const GLenum error, const std::string& text) const {
+ mContext->GenerateErrorImpl(error, text);
+ }
+
+ void OnContextLoss(webgl::ContextLossReason);
+
+ void RequestExtension(const WebGLExtensionID ext) {
+ mContext->RequestExtension(ext);
+ }
+
+ // -
+ // Child-ward
+
+ void JsWarning(const std::string&) const;
+
+ // -
+ // Creation and destruction
+
+ void CreateBuffer(ObjectId);
+ void CreateFramebuffer(ObjectId);
+ bool CreateOpaqueFramebuffer(ObjectId,
+ const webgl::OpaqueFramebufferOptions& options);
+ void CreateProgram(ObjectId);
+ void CreateQuery(ObjectId);
+ void CreateRenderbuffer(ObjectId);
+ void CreateSampler(ObjectId);
+ void CreateShader(ObjectId, GLenum type);
+ void CreateSync(ObjectId);
+ void CreateTexture(ObjectId);
+ void CreateTransformFeedback(ObjectId);
+ void CreateVertexArray(ObjectId);
+
+ void DeleteBuffer(ObjectId);
+ void DeleteFramebuffer(ObjectId);
+ void DeleteProgram(ObjectId);
+ void DeleteQuery(ObjectId);
+ void DeleteRenderbuffer(ObjectId);
+ void DeleteSampler(ObjectId);
+ void DeleteShader(ObjectId);
+ void DeleteSync(ObjectId);
+ void DeleteTexture(ObjectId);
+ void DeleteTransformFeedback(ObjectId);
+ void DeleteVertexArray(ObjectId);
+
+ // ------------------------- GL State -------------------------
+ bool IsContextLost() const { return mContext->IsContextLost(); }
+
+ void SetEnabled(GLenum cap, Maybe<GLuint> i, bool val) const {
+ mContext->SetEnabled(cap, i, val);
+ }
+
+ bool IsEnabled(GLenum cap) const { return mContext->IsEnabled(cap); }
+
+ Maybe<double> GetNumber(GLenum pname) const {
+ return mContext->GetParameter(pname);
+ }
+
+ Maybe<std::string> GetString(GLenum pname) const {
+ return mContext->GetString(pname);
+ }
+
+ void AttachShader(ObjectId prog, ObjectId shader) const {
+ const auto pProg = ById<WebGLProgram>(prog);
+ const auto pShader = ById<WebGLShader>(shader);
+ if (!pProg || !pShader) return;
+ mContext->AttachShader(*pProg, *pShader);
+ }
+
+ void BindAttribLocation(ObjectId id, GLuint location,
+ const std::string& name) const {
+ const auto obj = ById<WebGLProgram>(id);
+ if (!obj) return;
+ mContext->BindAttribLocation(*obj, location, name);
+ }
+
+ void BindFramebuffer(GLenum target, ObjectId id) const {
+ mContext->BindFramebuffer(target, AutoResolve(id));
+ }
+
+ void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) const {
+ mContext->BlendColor(r, g, b, a);
+ }
+
+ void BlendEquationSeparate(Maybe<GLuint> i, GLenum modeRGB,
+ GLenum modeAlpha) const {
+ mContext->BlendEquationSeparate(i, modeRGB, modeAlpha);
+ }
+
+ void BlendFuncSeparate(Maybe<GLuint> i, GLenum srcRGB, GLenum dstRGB,
+ GLenum srcAlpha, GLenum dstAlpha) const {
+ mContext->BlendFuncSeparate(i, srcRGB, dstRGB, srcAlpha, dstAlpha);
+ }
+
+ GLenum CheckFramebufferStatus(GLenum target) const {
+ return mContext->CheckFramebufferStatus(target);
+ }
+
+ void Clear(GLbitfield mask) const { mContext->Clear(mask); }
+
+ void ClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) const {
+ mContext->ClearColor(r, g, b, a);
+ }
+
+ void ClearDepth(GLclampf v) const { mContext->ClearDepth(v); }
+
+ void ClearStencil(GLint v) const { mContext->ClearStencil(v); }
+
+ void ColorMask(Maybe<GLuint> i, uint8_t mask) const {
+ mContext->ColorMask(i, mask);
+ }
+
+ void CompileShader(const ObjectId id) const {
+ const auto obj = ById<WebGLShader>(id);
+ if (!obj) return;
+ mContext->CompileShader(*obj);
+ }
+
+ void CullFace(GLenum face) const { mContext->CullFace(face); }
+
+ void DepthFunc(GLenum func) const { mContext->DepthFunc(func); }
+
+ void DepthMask(WebGLboolean b) const { mContext->DepthMask(b); }
+
+ void DepthRange(GLclampf zNear, GLclampf zFar) const {
+ mContext->DepthRange(zNear, zFar);
+ }
+
+ void DetachShader(const ObjectId prog, const ObjectId shader) const {
+ const auto pProg = ById<WebGLProgram>(prog);
+ const auto pShader = ById<WebGLShader>(shader);
+ if (!pProg || !pShader) return;
+ mContext->DetachShader(*pProg, *pShader);
+ }
+
+ void Flush() const { mContext->Flush(); }
+
+ void Finish() const { mContext->Finish(); }
+
+ void FramebufferAttach(const GLenum target, const GLenum attachSlot,
+ const GLenum bindImageTarget, const ObjectId id,
+ const GLint mipLevel, const GLint zLayerBase,
+ const GLsizei numViewLayers) const {
+ webgl::FbAttachInfo toAttach;
+ toAttach.rb = AutoResolve(id);
+ toAttach.tex = AutoResolve(id);
+ toAttach.mipLevel = mipLevel;
+ toAttach.zLayer = zLayerBase;
+ if (numViewLayers) {
+ toAttach.zLayerCount = numViewLayers;
+ toAttach.isMultiview = true;
+ }
+
+ mContext->FramebufferAttach(target, attachSlot, bindImageTarget, toAttach);
+ }
+
+ void FrontFace(GLenum mode) const { mContext->FrontFace(mode); }
+
+ Maybe<double> GetBufferParameter(GLenum target, GLenum pname) const {
+ return mContext->GetBufferParameter(target, pname);
+ }
+
+ webgl::CompileResult GetCompileResult(ObjectId id) const {
+ const auto obj = ById<WebGLShader>(id);
+ if (!obj) return {};
+ return mContext->GetCompileResult(*obj);
+ }
+
+ GLenum GetError() const { return mContext->GetError(); }
+
+ GLint GetFragDataLocation(ObjectId id, const std::string& name) const {
+ const auto obj = ById<WebGLProgram>(id);
+ if (!obj) return -1;
+ return mContext->GetFragDataLocation(*obj, name);
+ }
+
+ Maybe<double> GetFramebufferAttachmentParameter(ObjectId id,
+ GLenum attachment,
+ GLenum pname) const {
+ return mContext->GetFramebufferAttachmentParameter(AutoResolve(id),
+ attachment, pname);
+ }
+
+ webgl::LinkResult GetLinkResult(ObjectId id) const {
+ const auto obj = ById<WebGLProgram>(id);
+ if (!obj) return {};
+ return mContext->GetLinkResult(*obj);
+ }
+
+ Maybe<double> GetRenderbufferParameter(ObjectId id, GLenum pname) const {
+ const auto obj = ById<WebGLRenderbuffer>(id);
+ if (!obj) return {};
+ return mContext->GetRenderbufferParameter(*obj, pname);
+ }
+
+ Maybe<webgl::ShaderPrecisionFormat> GetShaderPrecisionFormat(
+ GLenum shaderType, GLenum precisionType) const {
+ return mContext->GetShaderPrecisionFormat(shaderType, precisionType);
+ }
+
+ webgl::GetUniformData GetUniform(ObjectId id, uint32_t loc) const {
+ const auto obj = ById<WebGLProgram>(id);
+ if (!obj) return {};
+ return mContext->GetUniform(*obj, loc);
+ }
+
+ void Hint(GLenum target, GLenum mode) const { mContext->Hint(target, mode); }
+
+ void LineWidth(GLfloat width) const { mContext->LineWidth(width); }
+
+ void LinkProgram(const ObjectId id) const {
+ const auto obj = ById<WebGLProgram>(id);
+ if (!obj) return;
+ mContext->LinkProgram(*obj);
+ }
+
+ void PolygonOffset(GLfloat factor, GLfloat units) const {
+ mContext->PolygonOffset(factor, units);
+ }
+
+ void SampleCoverage(GLclampf value, bool invert) const {
+ mContext->SampleCoverage(value, invert);
+ }
+
+ void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) const {
+ mContext->Scissor(x, y, width, height);
+ }
+
+ // TODO: s/nsAString/std::string/
+ void ShaderSource(const ObjectId id, const std::string& source) const {
+ const auto obj = ById<WebGLShader>(id);
+ if (!obj) return;
+ mContext->ShaderSource(*obj, source);
+ }
+
+ void StencilFuncSeparate(GLenum face, GLenum func, GLint ref,
+ GLuint mask) const {
+ mContext->StencilFuncSeparate(face, func, ref, mask);
+ }
+ void StencilMaskSeparate(GLenum face, GLuint mask) const {
+ mContext->StencilMaskSeparate(face, mask);
+ }
+ void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
+ GLenum dppass) const {
+ mContext->StencilOpSeparate(face, sfail, dpfail, dppass);
+ }
+
+ void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) const {
+ mContext->Viewport(x, y, width, height);
+ }
+
+ // ------------------------- Buffer Objects -------------------------
+ void BindBuffer(GLenum target, const ObjectId id) const {
+ mContext->BindBuffer(target, AutoResolve(id));
+ }
+
+ void BindBufferRange(GLenum target, GLuint index, const ObjectId id,
+ uint64_t offset, uint64_t size) const {
+ GetWebGL2Context()->BindBufferRange(target, index, AutoResolve(id), offset,
+ size);
+ }
+
+ void CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
+ uint64_t readOffset, uint64_t writeOffset,
+ uint64_t size) const {
+ GetWebGL2Context()->CopyBufferSubData(readTarget, writeTarget, readOffset,
+ writeOffset, size);
+ }
+
+ bool GetBufferSubData(GLenum target, uint64_t srcByteOffset,
+ const Range<uint8_t>& dest) const {
+ return GetWebGL2Context()->GetBufferSubData(target, srcByteOffset, dest);
+ }
+
+ void BufferData(GLenum target, const RawBuffer<>& srcData, GLenum usage) const {
+ mContext->BufferData(target, srcData.size(), srcData.begin(), usage);
+ }
+
+ void BufferData_SizeOnly(GLenum target, size_t byteSize, GLenum usage) const {
+ mContext->BufferData(target, byteSize, nullptr, usage);
+ }
+
+ void BufferSubData(GLenum target, uint64_t dstByteOffset,
+ const RawBuffer<>& srcData,
+ bool unsynchronized = false) const {
+ const auto& range = srcData.Data();
+ mContext->BufferSubData(target, dstByteOffset, range.length(),
+ range.begin().get(), unsynchronized);
+ }
+
+ // -------------------------- Framebuffer Objects --------------------------
+ void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter) const {
+ GetWebGL2Context()->BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0,
+ dstY0, dstX1, dstY1, mask, filter);
+ }
+
+ void InvalidateFramebuffer(GLenum target,
+ const RawBuffer<const GLenum>& attachments) const {
+ GetWebGL2Context()->InvalidateFramebuffer(target, MakeRange(attachments));
+ }
+
+ void InvalidateSubFramebuffer(GLenum target,
+ const RawBuffer<const GLenum>& attachments,
+ GLint x, GLint y, GLsizei width,
+ GLsizei height) const {
+ GetWebGL2Context()->InvalidateSubFramebuffer(target, MakeRange(attachments),
+ x, y, width, height);
+ }
+
+ void ReadBuffer(GLenum mode) const { GetWebGL2Context()->ReadBuffer(mode); }
+
+ // ----------------------- Renderbuffer objects -----------------------
+ Maybe<std::vector<int32_t>> GetInternalformatParameter(GLenum target,
+ GLenum internalformat,
+ GLenum pname) const {
+ return GetWebGL2Context()->GetInternalformatParameter(
+ target, internalformat, pname);
+ }
+
+ void RenderbufferStorageMultisample(ObjectId id, uint32_t samples,
+ GLenum internalFormat, uint32_t width,
+ uint32_t height) const {
+ const auto obj = ById<WebGLRenderbuffer>(id);
+ if (!obj) return;
+ mContext->RenderbufferStorageMultisample(*obj, samples, internalFormat,
+ width, height);
+ }
+
+ // --------------------------- Texture objects ---------------------------
+ void ActiveTexture(uint32_t texUnit) const {
+ mContext->ActiveTexture(texUnit);
+ }
+
+ void BindTexture(GLenum texTarget, const ObjectId id) const {
+ mContext->BindTexture(texTarget, AutoResolve(id));
+ }
+
+ void GenerateMipmap(GLenum texTarget) const {
+ mContext->GenerateMipmap(texTarget);
+ }
+
+ // CompressedTexSubImage if `sub`
+ void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level,
+ GLenum format, const uvec3& offset, const uvec3& size,
+ const RawBuffer<>& src, const uint32_t pboImageSize,
+ const Maybe<uint64_t>& pboOffset) const {
+ mContext->CompressedTexImage(sub, imageTarget, level, format, offset, size,
+ MakeRange(src), pboImageSize, pboOffset);
+ }
+
+ // CopyTexSubImage if `!respecFormat`
+ void CopyTexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
+ const uvec3& dstOffset, const ivec2& srcOffset,
+ const uvec2& size) const {
+ mContext->CopyTexImage(imageTarget, level, respecFormat, dstOffset,
+ srcOffset, size);
+ }
+
+ // TexSubImage if `!respecFormat`
+ void TexImage(uint32_t level, GLenum respecFormat, const uvec3& offset,
+ const webgl::PackingInfo& pi,
+ const webgl::TexUnpackBlobDesc& src) const {
+ mContext->TexImage(level, respecFormat, offset, pi, src);
+ }
+
+ void TexStorage(GLenum texTarget, uint32_t levels, GLenum internalFormat,
+ const uvec3& size) const {
+ GetWebGL2Context()->TexStorage(texTarget, levels, internalFormat, size);
+ }
+
+ Maybe<double> GetTexParameter(ObjectId id, GLenum pname) const {
+ const auto obj = ById<WebGLTexture>(id);
+ if (!obj) return {};
+ return mContext->GetTexParameter(*obj, pname);
+ }
+
+ void TexParameter_base(GLenum texTarget, GLenum pname,
+ const FloatOrInt& param) const {
+ mContext->TexParameter_base(texTarget, pname, param);
+ }
+
+ // ------------------- Programs and shaders --------------------------------
+ void UseProgram(ObjectId id) const { mContext->UseProgram(AutoResolve(id)); }
+
+ bool ValidateProgram(ObjectId id) const {
+ const auto obj = ById<WebGLProgram>(id);
+ if (!obj) return false;
+ return mContext->ValidateProgram(*obj);
+ }
+
+ // ------------------------ Uniforms and attributes ------------------------
+
+ void UniformData(uint32_t loc, bool transpose,
+ const RawBuffer<webgl::UniformDataVal>& data) const {
+ mContext->UniformData(loc, transpose, data.Data());
+ }
+
+ void VertexAttrib4T(GLuint index, const webgl::TypedQuad& data) const {
+ mContext->VertexAttrib4T(index, data);
+ }
+
+ void VertexAttribDivisor(GLuint index, GLuint divisor) const {
+ mContext->VertexAttribDivisor(index, divisor);
+ }
+
+ Maybe<double> GetIndexedParameter(GLenum target, GLuint index) const {
+ return GetWebGL2Context()->GetIndexedParameter(target, index);
+ }
+
+ void UniformBlockBinding(const ObjectId id, GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding) const {
+ const auto obj = ById<WebGLProgram>(id);
+ if (!obj) return;
+ GetWebGL2Context()->UniformBlockBinding(*obj, uniformBlockIndex,
+ uniformBlockBinding);
+ }
+
+ void EnableVertexAttribArray(GLuint index) const {
+ mContext->EnableVertexAttribArray(index);
+ }
+
+ void DisableVertexAttribArray(GLuint index) const {
+ mContext->DisableVertexAttribArray(index);
+ }
+
+ Maybe<double> GetVertexAttrib(GLuint index, GLenum pname) const {
+ return mContext->GetVertexAttrib(index, pname);
+ }
+
+ void VertexAttribPointer(GLuint index,
+ const webgl::VertAttribPointerDesc& desc) const {
+ mContext->VertexAttribPointer(index, desc);
+ }
+
+ // --------------------------- Buffer Operations --------------------------
+ void ClearBufferTv(GLenum buffer, GLint drawBuffer,
+ const webgl::TypedQuad& data) const {
+ GetWebGL2Context()->ClearBufferTv(buffer, drawBuffer, data);
+ }
+
+ void ClearBufferfi(GLenum buffer, GLint drawBuffer, GLfloat depth,
+ GLint stencil) const {
+ GetWebGL2Context()->ClearBufferfi(buffer, drawBuffer, depth, stencil);
+ }
+
+ // ------------------------------ Readback -------------------------------
+ void ReadPixelsPbo(const webgl::ReadPixelsDesc& desc,
+ const uint64_t offset) const {
+ mContext->ReadPixelsPbo(desc, offset);
+ }
+
+ webgl::ReadPixelsResult ReadPixelsInto(const webgl::ReadPixelsDesc& desc,
+ const Range<uint8_t>& dest) const {
+ return mContext->ReadPixelsInto(desc, dest);
+ }
+
+ // ----------------------------- Sampler -----------------------------------
+
+ void BindSampler(GLuint unit, ObjectId id) const {
+ GetWebGL2Context()->BindSampler(unit, AutoResolve(id));
+ }
+
+ void SamplerParameteri(ObjectId id, GLenum pname, GLint param) const {
+ const auto obj = ById<WebGLSampler>(id);
+ if (!obj) return;
+ GetWebGL2Context()->SamplerParameteri(*obj, pname, param);
+ }
+
+ void SamplerParameterf(ObjectId id, GLenum pname, GLfloat param) const {
+ const auto obj = ById<WebGLSampler>(id);
+ if (!obj) return;
+ GetWebGL2Context()->SamplerParameterf(*obj, pname, param);
+ }
+
+ Maybe<double> GetSamplerParameter(ObjectId id, GLenum pname) const {
+ const auto obj = ById<WebGLSampler>(id);
+ if (!obj) return {};
+ return GetWebGL2Context()->GetSamplerParameter(*obj, pname);
+ }
+
+ // ------------------------------- GL Sync ---------------------------------
+
+ GLenum ClientWaitSync(ObjectId id, GLbitfield flags, GLuint64 timeout) const {
+ const auto obj = ById<WebGLSync>(id);
+ if (!obj) return LOCAL_GL_WAIT_FAILED;
+ return GetWebGL2Context()->ClientWaitSync(*obj, flags, timeout);
+ }
+
+ // -------------------------- Transform Feedback ---------------------------
+ void BindTransformFeedback(ObjectId id) const {
+ GetWebGL2Context()->BindTransformFeedback(AutoResolve(id));
+ }
+
+ void BeginTransformFeedback(GLenum primitiveMode) const {
+ GetWebGL2Context()->BeginTransformFeedback(primitiveMode);
+ }
+
+ void EndTransformFeedback() const {
+ GetWebGL2Context()->EndTransformFeedback();
+ }
+
+ void PauseTransformFeedback() const {
+ GetWebGL2Context()->PauseTransformFeedback();
+ }
+
+ void ResumeTransformFeedback() const {
+ GetWebGL2Context()->ResumeTransformFeedback();
+ }
+
+ void TransformFeedbackVaryings(ObjectId id,
+ const std::vector<std::string>& varyings,
+ GLenum bufferMode) const {
+ const auto obj = ById<WebGLProgram>(id);
+ if (!obj) return;
+ GetWebGL2Context()->TransformFeedbackVaryings(*obj, varyings, bufferMode);
+ }
+
+ // -------------------------- Opaque Framebuffers ---------------------------
+ void SetFramebufferIsInOpaqueRAF(ObjectId id, bool value) {
+ WebGLFramebuffer* fb = AutoResolve(id);
+ if (fb) {
+ fb->mInOpaqueRAF = value;
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Host-side extension methods. Calls in the client are forwarded to the
+ // host. Some extension methods are also available in WebGL2 Contexts. For
+ // them, the final parameter is a boolean indicating if the call originated
+ // from an extension.
+ // -------------------------------------------------------------------------
+
+ // Misc. Extensions
+ void DrawBuffers(const std::vector<GLenum>& buffers) const {
+ mContext->DrawBuffers(buffers);
+ }
+
+ // VertexArrayObjectEXT
+ void BindVertexArray(ObjectId id) const {
+ mContext->BindVertexArray(AutoResolve(id));
+ }
+
+ // InstancedElementsEXT
+ void DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertCount,
+ GLsizei primCount) const {
+ mContext->DrawArraysInstanced(mode, first, vertCount, primCount);
+ }
+
+ void DrawElementsInstanced(GLenum mode, GLsizei vertCount, GLenum type,
+ WebGLintptr offset, GLsizei primCount) const {
+ mContext->DrawElementsInstanced(mode, vertCount, type, offset, primCount);
+ }
+
+ // GLQueryEXT
+ void BeginQuery(GLenum target, ObjectId id) const {
+ const auto obj = ById<WebGLQuery>(id);
+ if (!obj) return;
+ mContext->BeginQuery(target, *obj);
+ }
+
+ void EndQuery(GLenum target) const { mContext->EndQuery(target); }
+
+ void QueryCounter(ObjectId id) const {
+ const auto obj = ById<WebGLQuery>(id);
+ if (!obj) return;
+ mContext->QueryCounter(*obj);
+ }
+
+ Maybe<double> GetQueryParameter(ObjectId id, GLenum pname) const {
+ const auto obj = ById<WebGLQuery>(id);
+ if (!obj) return {};
+ return mContext->GetQueryParameter(*obj, pname);
+ }
+
+ // WEBGL_provoking_vertex
+ void ProvokingVertex(const webgl::ProvokingVertex mode) const {
+ mContext->ProvokingVertex(mode);
+ }
+
+ // -------------------------------------------------------------------------
+ // Client-side methods. Calls in the Host are forwarded to the client.
+ // -------------------------------------------------------------------------
+ public:
+ void OnLostContext();
+ void OnRestoredContext();
+
+ protected:
+ WebGL2Context* GetWebGL2Context() const {
+ MOZ_RELEASE_ASSERT(mContext->IsWebGL2(), "Requires WebGL2 context");
+ return static_cast<WebGL2Context*>(mContext.get());
+ }
+};
+
+} // namespace mozilla
+
+#endif // HOSTWEBGLCONTEXT_H_