gecko-dev/dom/canvas/HostWebGLContext.h
David Parks cbf4e1a5cc Bug 1621762: Part 7 - Add IpdlQueue actor traits to WebGLParent/WebGLChild r=jgilbert,jld
Adds IpdlQueue capability to PWebGL actors.  The WebGLChild, used in content processes, implements SyncProducerActor and AsyncConsumerActor because it sends (sync and async) messages and receives responses to them that it reads as async messages.  The WebGLParent, used in the compositor process, is a SyncConsumerActor and AsyncProducerActor for dual reasons.

Differential Revision: https://phabricator.services.mozilla.com/D68264
2020-04-30 22:24:44 +00:00

805 lines
26 KiB
C++

/* -*- 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 "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
#include "WebGLContext.h"
#include "WebGL2Context.h"
#include "WebGLFramebuffer.h"
#include "WebGLTypes.h"
#include "WebGLCommandQueue.h"
#include "WebGLCrossProcessCommandQueue.h"
#include "ProducerConsumerQueue.h"
#include "IpdlQueue.h"
#include <unordered_map>
#include <unordered_set>
#include <vector>
#ifndef WEBGL_BRIDGE_LOG_
# define WEBGL_BRIDGE_LOG_(lvl, ...) \
MOZ_LOG(mozilla::gWebGLBridgeLog, lvl, (__VA_ARGS__))
# define WEBGL_BRIDGE_LOGD(...) WEBGL_BRIDGE_LOG_(LogLevel::Debug, __VA_ARGS__)
# define WEBGL_BRIDGE_LOGE(...) WEBGL_BRIDGE_LOG_(LogLevel::Error, __VA_ARGS__)
#endif // WEBGL_BRIDGE_LOG_
namespace mozilla {
extern LazyLogModule gWebGLBridgeLog;
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<HostWebGLContext> {
friend class WebGLContext;
friend class WebGLMemoryTracker;
using ObjectId = webgl::ObjectId;
static std::unique_ptr<LockedOutstandingContexts> OutstandingContexts() {
return std::make_unique<LockedOutstandingContexts>();
}
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(HostWebGLContext)
struct RemotingData final {
dom::WebGLParent& mParent;
UniquePtr<HostWebGLCommandSinkP> mCommandSinkP;
UniquePtr<HostWebGLCommandSinkI> mCommandSinkI;
};
struct OwnerData final {
Maybe<ClientWebGLContext*> inProcess;
Maybe<RemotingData> outOfProcess;
};
static UniquePtr<HostWebGLContext> Create(OwnerData&&,
const webgl::InitContextDesc&,
webgl::InitContextResult* out);
private:
explicit HostWebGLContext(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() { mContext->Present(); }
void ClearVRFrame() const { mContext->ClearVRFrame(); }
Maybe<ICRData> InitializeCanvasRenderer(layers::LayersBackend backend) {
return mContext->InitializeCanvasRenderer(backend);
}
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 Disable(GLenum cap) const { mContext->Disable(cap); }
void Enable(GLenum cap) const { mContext->Enable(cap); }
bool IsEnabled(GLenum cap) const { return mContext->IsEnabled(cap); }
Maybe<double> GetParameter(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(GLenum modeRGB, GLenum modeAlpha) const {
mContext->BlendEquationSeparate(modeRGB, modeAlpha);
}
void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha,
GLenum dstAlpha) const {
mContext->BlendFuncSeparate(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(WebGLboolean r, WebGLboolean g, WebGLboolean b,
WebGLboolean a) const {
mContext->ColorMask(r, g, b, a);
}
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 PixelStorei(GLenum pname, uint32_t param) const {
mContext->PixelStorei(pname, param);
}
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);
}
void GetBufferSubData(GLenum target, uint64_t srcByteOffset,
RawBuffer<uint8_t>& dest) const {
const auto range = MakeRange(dest);
GetWebGL2Context()->GetBufferSubData(target, srcByteOffset, range);
}
void BufferData(GLenum target, const RawBuffer<const uint8_t>& data,
GLenum usage) const {
mContext->BufferData(target, data.Length(), data.Data(), usage);
}
void BufferSubData(GLenum target, uint64_t dstByteOffset,
const RawBuffer<const uint8_t>& srcData) const {
mContext->BufferSubData(target, dstByteOffset, srcData.Length(),
srcData.Data());
}
// -------------------------- 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<const uint8_t>& 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(GLenum imageTarget, uint32_t level, GLenum respecFormat,
const uvec3& offset, const uvec3& size,
const webgl::PackingInfo& pi, const TexImageSource& src,
const dom::HTMLCanvasElement& canvas) const {
mContext->TexImage(imageTarget, level, respecFormat, offset, size, pi, src,
canvas);
}
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<const uint8_t>& data) const {
mContext->UniformData(loc, transpose, MakeRange(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);
}
void ReadPixels(const webgl::ReadPixelsDesc& desc,
RawBuffer<uint8_t>& dest) const {
const auto range = MakeRange(dest);
mContext->ReadPixels(desc, range);
}
// ----------------------------- 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);
}
// -------------------------------------------------------------------------
// Client-side methods. Calls in the Host are forwarded to the client.
// -------------------------------------------------------------------------
public:
void OnLostContext();
void OnRestoredContext();
// Etc
public:
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame(ObjectId id) const;
protected:
WebGL2Context* GetWebGL2Context() const {
MOZ_RELEASE_ASSERT(mContext->IsWebGL2(), "Requires WebGL2 context");
return static_cast<WebGL2Context*>(mContext.get());
}
// mozilla::ipc::Shmem PopShmem() { return mShmemStack.PopLastElement(); }
// nsTArray<mozilla::ipc::Shmem> mShmemStack;
};
} // namespace mozilla
#endif // HOSTWEBGLCONTEXT_H_