зеркало из https://github.com/mozilla/gecko-dev.git
785 строки
26 KiB
C++
785 строки
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 "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 "IpdlQueue.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 {
|
|
return (void)mContext->Present(AutoResolve(xrFb), t, webvr);
|
|
}
|
|
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ObjectId xrFb,
|
|
const bool webvr) const;
|
|
|
|
// -
|
|
|
|
Maybe<uvec2> FrontBufferSnapshotInto(Maybe<Range<uint8_t>> dest) const {
|
|
return mContext->FrontBufferSnapshotInto(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<>& data, GLenum usage) const {
|
|
const auto& beginOrNull = data.begin();
|
|
mContext->BufferData(target, data.size(), beginOrNull, usage);
|
|
}
|
|
|
|
void BufferSubData(GLenum target, uint64_t dstByteOffset,
|
|
const RawBuffer<>& srcData) const {
|
|
const auto& range = srcData.Data();
|
|
mContext->BufferSubData(target, dstByteOffset, range.length(),
|
|
range.begin().get());
|
|
}
|
|
|
|
// -------------------------- 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<>& 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);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 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_
|