1 /* -*- Mode: C++; tab-width: 20; 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/. */
6 #include "WebGLParent.h"
8 #include "WebGLChild.h"
9 #include "mozilla/layers/TextureClientSharedSurface.h"
10 #include "ImageContainer.h"
11 #include "HostWebGLContext.h"
12 #include "WebGLMethodDispatcher.h"
14 namespace mozilla::dom
{
16 mozilla::ipc::IPCResult
WebGLParent::RecvInitialize(
17 const webgl::InitContextDesc
& desc
, webgl::InitContextResult
* const out
) {
18 mHost
= HostWebGLContext::Create({nullptr, this}, desc
, out
);
21 MOZ_ASSERT(!out
->error
->empty());
27 WebGLParent::WebGLParent(const dom::ContentParentId
& aContentId
)
28 : mContentId(aContentId
) {}
30 WebGLParent::~WebGLParent() = default;
34 using IPCResult
= mozilla::ipc::IPCResult
;
36 IPCResult
WebGLParent::RecvDispatchCommands(BigBuffer
&& shmem
,
37 const uint64_t cmdsByteSize
) {
38 AUTO_PROFILER_LABEL("WebGLParent::RecvDispatchCommands", GRAPHICS
);
40 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
43 const auto& gl
= mHost
->mContext
->GL();
44 const gl::GLContext::TlsScope
tlsIsCurrent(gl
);
46 MOZ_ASSERT(cmdsByteSize
);
47 const auto shmemBytes
= Range
<uint8_t>{shmem
.AsSpan()};
48 const auto byteSize
= std::min
<uint64_t>(shmemBytes
.length(), cmdsByteSize
);
49 const auto cmdsBytes
=
50 Range
<const uint8_t>{shmemBytes
.begin(), shmemBytes
.begin() + byteSize
};
51 auto view
= webgl::RangeConsumerView
{cmdsBytes
};
54 const auto initialOffset
=
55 AlignmentOffset(kUniversalAlignment
, cmdsBytes
.begin().get());
56 MOZ_ALWAYS_TRUE(!initialOffset
);
60 view
.AlignTo(kUniversalAlignment
);
62 if (!view
.ReadParam(&id
)) break;
64 const auto ok
= WebGLMethodDispatcher
<0>::DispatchCommand(*mHost
, id
, view
);
66 const nsPrintfCString
cstr(
67 "DispatchCommand(id: %i) failed. Please file a bug!", int(id
));
68 const auto str
= ToString(cstr
);
69 gfxCriticalError() << str
;
70 mHost
->JsWarning(str
);
71 mHost
->OnContextLoss(webgl::ContextLossReason::None
);
79 IPCResult
WebGLParent::RecvTexImage(const uint32_t level
,
80 const uint32_t respecFormat
,
82 const webgl::PackingInfo
& pi
,
83 webgl::TexUnpackBlobDesc
&& desc
) {
85 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
88 mHost
->TexImage(level
, respecFormat
, offset
, pi
, desc
);
94 mozilla::ipc::IPCResult
WebGLParent::Recv__delete__() {
99 void WebGLParent::ActorDestroy(ActorDestroyReason aWhy
) { mHost
= nullptr; }
103 IPCResult
WebGLParent::RecvGetFrontBufferSnapshot(
104 webgl::FrontBufferSnapshotIpc
* const ret
) {
105 return GetFrontBufferSnapshot(ret
, this);
108 IPCResult
WebGLParent::GetFrontBufferSnapshot(
109 webgl::FrontBufferSnapshotIpc
* const ret
, IProtocol
* aProtocol
) {
110 AUTO_PROFILER_LABEL("WebGLParent::GetFrontBufferSnapshot", GRAPHICS
);
113 return IPC_FAIL(aProtocol
, "HostWebGLContext is not initialized.");
116 const bool ok
= [&]() {
117 const auto maybeSize
= mHost
->FrontBufferSnapshotInto({});
119 const auto& surfSize
= *maybeSize
;
120 const auto byteSize
= 4 * surfSize
.x
* surfSize
.y
;
122 auto shmem
= webgl::RaiiShmem::Alloc(aProtocol
, byteSize
);
124 NS_WARNING("Failed to alloc shmem for RecvGetFrontBufferSnapshot.");
127 const auto range
= shmem
.ByteRange();
128 *ret
= {surfSize
, Some(shmem
.Extract())};
130 if (!mHost
->FrontBufferSnapshotInto(Some(range
))) {
131 gfxCriticalNote
<< "WebGLParent::RecvGetFrontBufferSnapshot: "
132 "FrontBufferSnapshotInto(some) failed after "
133 "FrontBufferSnapshotInto(none)";
140 // Zero means failure, as we still need to send any shmem we alloc.
141 ret
->surfSize
= {0, 0};
146 IPCResult
WebGLParent::RecvGetBufferSubData(const GLenum target
,
147 const uint64_t srcByteOffset
,
148 const uint64_t byteSize
,
150 AUTO_PROFILER_LABEL("WebGLParent::RecvGetBufferSubData", GRAPHICS
);
152 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
155 const auto allocSize
= 1 + byteSize
;
156 auto shmem
= webgl::RaiiShmem::Alloc(this, allocSize
);
158 NS_WARNING("Failed to alloc shmem for RecvGetBufferSubData.");
162 const auto shmemRange
= shmem
.ByteRange();
163 const auto dataRange
=
164 Range
<uint8_t>{shmemRange
.begin() + 1, shmemRange
.end()};
166 // We need to always send the shmem:
167 // https://bugzilla.mozilla.org/show_bug.cgi?id=1463831#c2
168 const auto ok
= mHost
->GetBufferSubData(target
, srcByteOffset
, dataRange
);
169 *(shmemRange
.begin().get()) = ok
;
170 *ret
= shmem
.Extract();
174 IPCResult
WebGLParent::RecvReadPixels(const webgl::ReadPixelsDesc
& desc
,
175 ReadPixelsBuffer
&& buffer
,
176 webgl::ReadPixelsResultIpc
* const ret
) {
177 AUTO_PROFILER_LABEL("WebGLParent::RecvReadPixels", GRAPHICS
);
180 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
183 if (buffer
.type() == ReadPixelsBuffer::TShmem
) {
184 const auto& shmem
= buffer
.get_Shmem();
185 const auto range
= shmem
.Range
<uint8_t>();
186 const auto res
= mHost
->ReadPixelsInto(desc
, range
);
191 const uint64_t byteSize
= buffer
.get_uint64_t();
192 const auto allocSize
= std::max
<uint64_t>(1, byteSize
);
193 auto shmem
= webgl::RaiiShmem::Alloc(this, allocSize
);
195 NS_WARNING("Failed to alloc shmem for RecvReadPixels.");
199 const auto range
= shmem
.ByteRange();
201 const auto res
= mHost
->ReadPixelsInto(desc
, range
);
202 *ret
= {res
, Some(shmem
.Extract())};
208 IPCResult
WebGLParent::RecvCheckFramebufferStatus(GLenum target
,
211 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
214 *ret
= mHost
->CheckFramebufferStatus(target
);
218 IPCResult
WebGLParent::RecvClientWaitSync(ObjectId id
, GLbitfield flags
,
219 GLuint64 timeout
, GLenum
* const ret
) {
221 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
224 *ret
= mHost
->ClientWaitSync(id
, flags
, timeout
);
228 IPCResult
WebGLParent::RecvCreateOpaqueFramebuffer(
229 const ObjectId id
, const OpaqueFramebufferOptions
& options
,
232 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
235 *ret
= mHost
->CreateOpaqueFramebuffer(id
, options
);
239 IPCResult
WebGLParent::RecvDrawingBufferSize(uvec2
* const ret
) {
241 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
244 *ret
= mHost
->DrawingBufferSize();
248 IPCResult
WebGLParent::RecvFinish() {
250 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
257 IPCResult
WebGLParent::RecvGetBufferParameter(GLenum target
, GLenum pname
,
258 Maybe
<double>* const ret
) {
260 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
263 *ret
= mHost
->GetBufferParameter(target
, pname
);
267 IPCResult
WebGLParent::RecvGetCompileResult(ObjectId id
,
268 webgl::CompileResult
* const ret
) {
270 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
273 *ret
= mHost
->GetCompileResult(id
);
277 IPCResult
WebGLParent::RecvGetError(GLenum
* const ret
) {
279 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
282 *ret
= mHost
->GetError();
286 IPCResult
WebGLParent::RecvGetFragDataLocation(ObjectId id
,
287 const std::string
& name
,
290 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
293 *ret
= mHost
->GetFragDataLocation(id
, name
);
297 IPCResult
WebGLParent::RecvGetFramebufferAttachmentParameter(
298 ObjectId id
, GLenum attachment
, GLenum pname
, Maybe
<double>* const ret
) {
300 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
303 *ret
= mHost
->GetFramebufferAttachmentParameter(id
, attachment
, pname
);
307 IPCResult
WebGLParent::RecvGetFrontBuffer(
308 ObjectId fb
, const bool vr
, Maybe
<layers::SurfaceDescriptor
>* const ret
) {
310 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
313 *ret
= mHost
->GetFrontBuffer(fb
, vr
);
317 IPCResult
WebGLParent::RecvGetIndexedParameter(GLenum target
, GLuint index
,
318 Maybe
<double>* const ret
) {
320 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
323 *ret
= mHost
->GetIndexedParameter(target
, index
);
327 IPCResult
WebGLParent::RecvGetInternalformatParameter(
328 const GLenum target
, const GLuint format
, const GLuint pname
,
329 Maybe
<std::vector
<int32_t>>* const ret
) {
331 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
334 *ret
= mHost
->GetInternalformatParameter(target
, format
, pname
);
338 IPCResult
WebGLParent::RecvGetLinkResult(ObjectId id
,
339 webgl::LinkResult
* const ret
) {
341 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
344 *ret
= mHost
->GetLinkResult(id
);
348 IPCResult
WebGLParent::RecvGetNumber(GLenum pname
, Maybe
<double>* const ret
) {
350 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
353 *ret
= mHost
->GetNumber(pname
);
357 IPCResult
WebGLParent::RecvGetQueryParameter(ObjectId id
, GLenum pname
,
358 Maybe
<double>* const ret
) {
360 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
363 *ret
= mHost
->GetQueryParameter(id
, pname
);
367 IPCResult
WebGLParent::RecvGetRenderbufferParameter(ObjectId id
, GLenum pname
,
368 Maybe
<double>* const ret
) {
370 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
373 *ret
= mHost
->GetRenderbufferParameter(id
, pname
);
377 IPCResult
WebGLParent::RecvGetSamplerParameter(ObjectId id
, GLenum pname
,
378 Maybe
<double>* const ret
) {
380 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
383 *ret
= mHost
->GetSamplerParameter(id
, pname
);
387 IPCResult
WebGLParent::RecvGetShaderPrecisionFormat(
388 GLenum shaderType
, GLenum precisionType
,
389 Maybe
<webgl::ShaderPrecisionFormat
>* const ret
) {
391 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
394 *ret
= mHost
->GetShaderPrecisionFormat(shaderType
, precisionType
);
398 IPCResult
WebGLParent::RecvGetString(GLenum pname
,
399 Maybe
<std::string
>* const ret
) {
401 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
404 *ret
= mHost
->GetString(pname
);
408 IPCResult
WebGLParent::RecvGetTexParameter(ObjectId id
, GLenum pname
,
409 Maybe
<double>* const ret
) {
411 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
414 *ret
= mHost
->GetTexParameter(id
, pname
);
418 IPCResult
WebGLParent::RecvGetUniform(ObjectId id
, uint32_t loc
,
419 webgl::GetUniformData
* const ret
) {
421 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
424 *ret
= mHost
->GetUniform(id
, loc
);
428 IPCResult
WebGLParent::RecvGetVertexAttrib(GLuint index
, GLenum pname
,
429 Maybe
<double>* const ret
) {
431 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
434 *ret
= mHost
->GetVertexAttrib(index
, pname
);
438 IPCResult
WebGLParent::RecvIsEnabled(GLenum cap
, bool* const ret
) {
440 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
443 *ret
= mHost
->IsEnabled(cap
);
447 IPCResult
WebGLParent::RecvOnMemoryPressure() {
449 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
452 mHost
->OnMemoryPressure();
456 IPCResult
WebGLParent::RecvValidateProgram(ObjectId id
, bool* const ret
) {
458 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
461 *ret
= mHost
->ValidateProgram(id
);
465 } // namespace mozilla::dom