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() = default;
28 WebGLParent::~WebGLParent() = default;
32 using IPCResult
= mozilla::ipc::IPCResult
;
34 IPCResult
WebGLParent::RecvDispatchCommands(BigBuffer
&& shmem
,
35 const uint64_t cmdsByteSize
) {
36 AUTO_PROFILER_LABEL("WebGLParent::RecvDispatchCommands", GRAPHICS
);
38 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
41 const auto& gl
= mHost
->mContext
->GL();
42 const gl::GLContext::TlsScope
tlsIsCurrent(gl
);
44 MOZ_ASSERT(cmdsByteSize
);
45 const auto shmemBytes
= Range
<uint8_t>{shmem
.AsSpan()};
46 const auto byteSize
= std::min
<uint64_t>(shmemBytes
.length(), cmdsByteSize
);
47 const auto cmdsBytes
=
48 Range
<const uint8_t>{shmemBytes
.begin(), shmemBytes
.begin() + byteSize
};
49 auto view
= webgl::RangeConsumerView
{cmdsBytes
};
52 const auto initialOffset
=
53 AlignmentOffset(kUniversalAlignment
, cmdsBytes
.begin().get());
54 MOZ_ALWAYS_TRUE(!initialOffset
);
58 view
.AlignTo(kUniversalAlignment
);
60 if (!view
.ReadParam(&id
)) break;
62 const auto ok
= WebGLMethodDispatcher
<0>::DispatchCommand(*mHost
, id
, view
);
64 const nsPrintfCString
cstr(
65 "DispatchCommand(id: %i) failed. Please file a bug!", int(id
));
66 const auto str
= ToString(cstr
);
67 gfxCriticalError() << str
;
68 mHost
->JsWarning(str
);
69 mHost
->OnContextLoss(webgl::ContextLossReason::None
);
77 IPCResult
WebGLParent::RecvTexImage(const uint32_t level
,
78 const uint32_t respecFormat
,
80 const webgl::PackingInfo
& pi
,
81 webgl::TexUnpackBlobDesc
&& desc
) {
83 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
86 mHost
->TexImage(level
, respecFormat
, offset
, pi
, desc
);
92 mozilla::ipc::IPCResult
WebGLParent::Recv__delete__() {
97 void WebGLParent::ActorDestroy(ActorDestroyReason aWhy
) { mHost
= nullptr; }
101 IPCResult
WebGLParent::RecvGetFrontBufferSnapshot(
102 webgl::FrontBufferSnapshotIpc
* const ret
) {
103 return GetFrontBufferSnapshot(ret
, this);
106 IPCResult
WebGLParent::GetFrontBufferSnapshot(
107 webgl::FrontBufferSnapshotIpc
* const ret
, IProtocol
* aProtocol
) {
108 AUTO_PROFILER_LABEL("WebGLParent::GetFrontBufferSnapshot", GRAPHICS
);
111 return IPC_FAIL(aProtocol
, "HostWebGLContext is not initialized.");
114 const bool ok
= [&]() {
115 const auto maybeSize
= mHost
->FrontBufferSnapshotInto({});
117 const auto& surfSize
= *maybeSize
;
118 const auto byteSize
= 4 * surfSize
.x
* surfSize
.y
;
120 auto shmem
= webgl::RaiiShmem::Alloc(aProtocol
, byteSize
);
122 NS_WARNING("Failed to alloc shmem for RecvGetFrontBufferSnapshot.");
125 const auto range
= shmem
.ByteRange();
126 *ret
= {surfSize
, Some(shmem
.Extract())};
128 if (!mHost
->FrontBufferSnapshotInto(Some(range
))) {
129 gfxCriticalNote
<< "WebGLParent::RecvGetFrontBufferSnapshot: "
130 "FrontBufferSnapshotInto(some) failed after "
131 "FrontBufferSnapshotInto(none)";
138 // Zero means failure, as we still need to send any shmem we alloc.
139 ret
->surfSize
= {0, 0};
144 IPCResult
WebGLParent::RecvGetBufferSubData(const GLenum target
,
145 const uint64_t srcByteOffset
,
146 const uint64_t byteSize
,
148 AUTO_PROFILER_LABEL("WebGLParent::RecvGetBufferSubData", GRAPHICS
);
150 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
153 const auto allocSize
= 1 + byteSize
;
154 auto shmem
= webgl::RaiiShmem::Alloc(this, allocSize
);
156 NS_WARNING("Failed to alloc shmem for RecvGetBufferSubData.");
160 const auto shmemRange
= shmem
.ByteRange();
161 const auto dataRange
=
162 Range
<uint8_t>{shmemRange
.begin() + 1, shmemRange
.end()};
164 // We need to always send the shmem:
165 // https://bugzilla.mozilla.org/show_bug.cgi?id=1463831#c2
166 const auto ok
= mHost
->GetBufferSubData(target
, srcByteOffset
, dataRange
);
167 *(shmemRange
.begin().get()) = ok
;
168 *ret
= shmem
.Extract();
172 IPCResult
WebGLParent::RecvReadPixels(const webgl::ReadPixelsDesc
& desc
,
173 ReadPixelsBuffer
&& buffer
,
174 webgl::ReadPixelsResultIpc
* const ret
) {
175 AUTO_PROFILER_LABEL("WebGLParent::RecvReadPixels", GRAPHICS
);
178 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
181 if (buffer
.type() == ReadPixelsBuffer::TShmem
) {
182 const auto& shmem
= buffer
.get_Shmem();
183 const auto range
= shmem
.Range
<uint8_t>();
184 const auto res
= mHost
->ReadPixelsInto(desc
, range
);
189 const uint64_t byteSize
= buffer
.get_uint64_t();
190 const auto allocSize
= std::max
<uint64_t>(1, byteSize
);
191 auto shmem
= webgl::RaiiShmem::Alloc(this, allocSize
);
193 NS_WARNING("Failed to alloc shmem for RecvReadPixels.");
197 const auto range
= shmem
.ByteRange();
199 const auto res
= mHost
->ReadPixelsInto(desc
, range
);
200 *ret
= {res
, Some(shmem
.Extract())};
206 IPCResult
WebGLParent::RecvCheckFramebufferStatus(GLenum target
,
209 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
212 *ret
= mHost
->CheckFramebufferStatus(target
);
216 IPCResult
WebGLParent::RecvClientWaitSync(ObjectId id
, GLbitfield flags
,
217 GLuint64 timeout
, GLenum
* const ret
) {
219 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
222 *ret
= mHost
->ClientWaitSync(id
, flags
, timeout
);
226 IPCResult
WebGLParent::RecvCreateOpaqueFramebuffer(
227 const ObjectId id
, const OpaqueFramebufferOptions
& options
,
230 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
233 *ret
= mHost
->CreateOpaqueFramebuffer(id
, options
);
237 IPCResult
WebGLParent::RecvDrawingBufferSize(uvec2
* const ret
) {
239 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
242 *ret
= mHost
->DrawingBufferSize();
246 IPCResult
WebGLParent::RecvFinish() {
248 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
255 IPCResult
WebGLParent::RecvGetBufferParameter(GLenum target
, GLenum pname
,
256 Maybe
<double>* const ret
) {
258 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
261 *ret
= mHost
->GetBufferParameter(target
, pname
);
265 IPCResult
WebGLParent::RecvGetCompileResult(ObjectId id
,
266 webgl::CompileResult
* const ret
) {
268 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
271 *ret
= mHost
->GetCompileResult(id
);
275 IPCResult
WebGLParent::RecvGetError(GLenum
* const ret
) {
277 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
280 *ret
= mHost
->GetError();
284 IPCResult
WebGLParent::RecvGetFragDataLocation(ObjectId id
,
285 const std::string
& name
,
288 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
291 *ret
= mHost
->GetFragDataLocation(id
, name
);
295 IPCResult
WebGLParent::RecvGetFramebufferAttachmentParameter(
296 ObjectId id
, GLenum attachment
, GLenum pname
, Maybe
<double>* const ret
) {
298 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
301 *ret
= mHost
->GetFramebufferAttachmentParameter(id
, attachment
, pname
);
305 IPCResult
WebGLParent::RecvGetFrontBuffer(
306 ObjectId fb
, const bool vr
, Maybe
<layers::SurfaceDescriptor
>* const ret
) {
308 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
311 *ret
= mHost
->GetFrontBuffer(fb
, vr
);
315 IPCResult
WebGLParent::RecvGetIndexedParameter(GLenum target
, GLuint index
,
316 Maybe
<double>* const ret
) {
318 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
321 *ret
= mHost
->GetIndexedParameter(target
, index
);
325 IPCResult
WebGLParent::RecvGetInternalformatParameter(
326 const GLenum target
, const GLuint format
, const GLuint pname
,
327 Maybe
<std::vector
<int32_t>>* const ret
) {
329 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
332 *ret
= mHost
->GetInternalformatParameter(target
, format
, pname
);
336 IPCResult
WebGLParent::RecvGetLinkResult(ObjectId id
,
337 webgl::LinkResult
* const ret
) {
339 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
342 *ret
= mHost
->GetLinkResult(id
);
346 IPCResult
WebGLParent::RecvGetNumber(GLenum pname
, Maybe
<double>* const ret
) {
348 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
351 *ret
= mHost
->GetNumber(pname
);
355 IPCResult
WebGLParent::RecvGetQueryParameter(ObjectId id
, GLenum pname
,
356 Maybe
<double>* const ret
) {
358 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
361 *ret
= mHost
->GetQueryParameter(id
, pname
);
365 IPCResult
WebGLParent::RecvGetRenderbufferParameter(ObjectId id
, GLenum pname
,
366 Maybe
<double>* const ret
) {
368 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
371 *ret
= mHost
->GetRenderbufferParameter(id
, pname
);
375 IPCResult
WebGLParent::RecvGetSamplerParameter(ObjectId id
, GLenum pname
,
376 Maybe
<double>* const ret
) {
378 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
381 *ret
= mHost
->GetSamplerParameter(id
, pname
);
385 IPCResult
WebGLParent::RecvGetShaderPrecisionFormat(
386 GLenum shaderType
, GLenum precisionType
,
387 Maybe
<webgl::ShaderPrecisionFormat
>* const ret
) {
389 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
392 *ret
= mHost
->GetShaderPrecisionFormat(shaderType
, precisionType
);
396 IPCResult
WebGLParent::RecvGetString(GLenum pname
,
397 Maybe
<std::string
>* const ret
) {
399 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
402 *ret
= mHost
->GetString(pname
);
406 IPCResult
WebGLParent::RecvGetTexParameter(ObjectId id
, GLenum pname
,
407 Maybe
<double>* const ret
) {
409 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
412 *ret
= mHost
->GetTexParameter(id
, pname
);
416 IPCResult
WebGLParent::RecvGetUniform(ObjectId id
, uint32_t loc
,
417 webgl::GetUniformData
* const ret
) {
419 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
422 *ret
= mHost
->GetUniform(id
, loc
);
426 IPCResult
WebGLParent::RecvGetVertexAttrib(GLuint index
, GLenum pname
,
427 Maybe
<double>* const ret
) {
429 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
432 *ret
= mHost
->GetVertexAttrib(index
, pname
);
436 IPCResult
WebGLParent::RecvIsEnabled(GLenum cap
, bool* const ret
) {
438 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
441 *ret
= mHost
->IsEnabled(cap
);
445 IPCResult
WebGLParent::RecvOnMemoryPressure() {
447 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
450 mHost
->OnMemoryPressure();
454 IPCResult
WebGLParent::RecvValidateProgram(ObjectId id
, bool* const ret
) {
456 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
459 *ret
= mHost
->ValidateProgram(id
);
463 } // namespace mozilla::dom