Bug 1890793: Assert CallArgs::newTarget is not gray. r=spidermonkey-reviewers,sfink...
[gecko.git] / dom / canvas / WebGLParent.cpp
blobe107d6cb5044d9106a900caffaa85fe90bec47aa
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);
20 if (!mHost) {
21 MOZ_ASSERT(!out->error->empty());
24 return IPC_OK();
27 WebGLParent::WebGLParent(const dom::ContentParentId& aContentId)
28 : mContentId(aContentId) {}
30 WebGLParent::~WebGLParent() = default;
32 // -
34 using IPCResult = mozilla::ipc::IPCResult;
36 IPCResult WebGLParent::RecvDispatchCommands(BigBuffer&& shmem,
37 const uint64_t cmdsByteSize) {
38 AUTO_PROFILER_LABEL("WebGLParent::RecvDispatchCommands", GRAPHICS);
39 if (!mHost) {
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};
53 if (kIsDebug) {
54 const auto initialOffset =
55 AlignmentOffset(kUniversalAlignment, cmdsBytes.begin().get());
56 MOZ_ALWAYS_TRUE(!initialOffset);
59 std::optional<std::string> fatalError;
61 while (true) {
62 view.AlignTo(kUniversalAlignment);
63 size_t id = 0;
64 if (!view.ReadParam(&id)) break;
66 // We split this up so that we don't end up in a long callstack chain of
67 // WebGLMethodDispatcher<i>|i=0->N. First get the lambda for dispatch, then
68 // invoke the lambda with our args.
69 const auto pfn =
70 WebGLMethodDispatcher<0>::DispatchCommandFuncById<HostWebGLContext>(id);
71 if (!pfn) {
72 const nsPrintfCString cstr(
73 "MethodDispatcher<%zu> not found. Please file a bug!", id);
74 fatalError = ToString(cstr);
75 gfxCriticalError() << *fatalError;
76 break;
79 const auto ok = (*pfn)(*mHost, view);
80 if (!ok) {
81 const nsPrintfCString cstr(
82 "DispatchCommand(id: %zu) failed. Please file a bug!", id);
83 fatalError = ToString(cstr);
84 gfxCriticalError() << *fatalError;
85 break;
89 if (fatalError) {
90 mHost->JsWarning(*fatalError);
91 mHost->OnContextLoss(webgl::ContextLossReason::None);
94 return IPC_OK();
97 IPCResult WebGLParent::RecvTexImage(const uint32_t level,
98 const uint32_t respecFormat,
99 const uvec3& offset,
100 const webgl::PackingInfo& pi,
101 webgl::TexUnpackBlobDesc&& desc) {
102 if (!mHost) {
103 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
106 mHost->TexImage(level, respecFormat, offset, pi, desc);
107 return IPC_OK();
110 // -
112 mozilla::ipc::IPCResult WebGLParent::Recv__delete__() {
113 mHost = nullptr;
114 return IPC_OK();
117 void WebGLParent::ActorDestroy(ActorDestroyReason aWhy) { mHost = nullptr; }
119 mozilla::ipc::IPCResult WebGLParent::RecvWaitForTxn(
120 layers::RemoteTextureOwnerId aOwnerId,
121 layers::RemoteTextureTxnType aTxnType, layers::RemoteTextureTxnId aTxnId) {
122 if (mHost) {
123 mHost->WaitForTxn(aOwnerId, aTxnType, aTxnId);
125 return IPC_OK();
128 // -
130 IPCResult WebGLParent::RecvGetFrontBufferSnapshot(
131 webgl::FrontBufferSnapshotIpc* const ret) {
132 return GetFrontBufferSnapshot(ret, this);
135 IPCResult WebGLParent::GetFrontBufferSnapshot(
136 webgl::FrontBufferSnapshotIpc* const ret, IProtocol* aProtocol) {
137 AUTO_PROFILER_LABEL("WebGLParent::GetFrontBufferSnapshot", GRAPHICS);
138 *ret = {};
139 if (!mHost) {
140 return IPC_FAIL(aProtocol, "HostWebGLContext is not initialized.");
143 const bool ok = [&]() {
144 const auto maybeSize = mHost->FrontBufferSnapshotInto({});
145 if (maybeSize) {
146 const auto& surfSize = *maybeSize;
147 const auto byteSize = 4 * surfSize.x * surfSize.y;
149 auto shmem = webgl::RaiiShmem::Alloc(aProtocol, byteSize);
150 if (!shmem) {
151 NS_WARNING("Failed to alloc shmem for RecvGetFrontBufferSnapshot.");
152 return false;
154 const auto range = shmem.ByteRange();
155 *ret = {surfSize, Some(shmem.Extract())};
157 if (!mHost->FrontBufferSnapshotInto(Some(range))) {
158 gfxCriticalNote << "WebGLParent::RecvGetFrontBufferSnapshot: "
159 "FrontBufferSnapshotInto(some) failed after "
160 "FrontBufferSnapshotInto(none)";
161 return false;
164 return true;
165 }();
166 if (!ok) {
167 // Zero means failure, as we still need to send any shmem we alloc.
168 ret->surfSize = {0, 0};
170 return IPC_OK();
173 IPCResult WebGLParent::RecvGetBufferSubData(const GLenum target,
174 const uint64_t srcByteOffset,
175 const uint64_t byteSize,
176 Shmem* const ret) {
177 AUTO_PROFILER_LABEL("WebGLParent::RecvGetBufferSubData", GRAPHICS);
178 if (!mHost) {
179 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
182 const auto allocSize = 1 + byteSize;
183 auto shmem = webgl::RaiiShmem::Alloc(this, allocSize);
184 if (!shmem) {
185 NS_WARNING("Failed to alloc shmem for RecvGetBufferSubData.");
186 return IPC_OK();
189 const auto shmemRange = shmem.ByteRange();
190 const auto dataRange =
191 Range<uint8_t>{shmemRange.begin() + 1, shmemRange.end()};
193 // We need to always send the shmem:
194 // https://bugzilla.mozilla.org/show_bug.cgi?id=1463831#c2
195 const auto ok = mHost->GetBufferSubData(target, srcByteOffset, dataRange);
196 *(shmemRange.begin().get()) = ok;
197 *ret = shmem.Extract();
198 return IPC_OK();
201 IPCResult WebGLParent::RecvReadPixels(const webgl::ReadPixelsDesc& desc,
202 ReadPixelsBuffer&& buffer,
203 webgl::ReadPixelsResultIpc* const ret) {
204 AUTO_PROFILER_LABEL("WebGLParent::RecvReadPixels", GRAPHICS);
205 *ret = {};
206 if (!mHost) {
207 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
210 if (buffer.type() == ReadPixelsBuffer::TShmem) {
211 const auto& shmem = buffer.get_Shmem();
212 const auto range = shmem.Range<uint8_t>();
213 const auto res = mHost->ReadPixelsInto(desc, range);
214 *ret = {res, {}};
215 return IPC_OK();
218 const uint64_t byteSize = buffer.get_uint64_t();
219 const auto allocSize = std::max<uint64_t>(1, byteSize);
220 auto shmem = webgl::RaiiShmem::Alloc(this, allocSize);
221 if (!shmem) {
222 NS_WARNING("Failed to alloc shmem for RecvReadPixels.");
223 return IPC_OK();
226 const auto range = shmem.ByteRange();
228 const auto res = mHost->ReadPixelsInto(desc, range);
229 *ret = {res, Some(shmem.Extract())};
230 return IPC_OK();
233 // -
235 IPCResult WebGLParent::RecvCheckFramebufferStatus(GLenum target,
236 GLenum* const ret) {
237 if (!mHost) {
238 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
241 *ret = mHost->CheckFramebufferStatus(target);
242 return IPC_OK();
245 IPCResult WebGLParent::RecvClientWaitSync(ObjectId id, GLbitfield flags,
246 GLuint64 timeout, GLenum* const ret) {
247 if (!mHost) {
248 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
251 *ret = mHost->ClientWaitSync(id, flags, timeout);
252 return IPC_OK();
255 IPCResult WebGLParent::RecvCreateOpaqueFramebuffer(
256 const ObjectId id, const OpaqueFramebufferOptions& options,
257 bool* const ret) {
258 if (!mHost) {
259 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
262 *ret = mHost->CreateOpaqueFramebuffer(id, options);
263 return IPC_OK();
266 IPCResult WebGLParent::RecvDrawingBufferSize(uvec2* const ret) {
267 if (!mHost) {
268 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
271 *ret = mHost->DrawingBufferSize();
272 return IPC_OK();
275 IPCResult WebGLParent::RecvFinish() {
276 if (!mHost) {
277 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
280 mHost->Finish();
281 return IPC_OK();
284 IPCResult WebGLParent::RecvGetBufferParameter(GLenum target, GLenum pname,
285 Maybe<double>* const ret) {
286 if (!mHost) {
287 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
290 *ret = mHost->GetBufferParameter(target, pname);
291 return IPC_OK();
294 IPCResult WebGLParent::RecvGetCompileResult(ObjectId id,
295 webgl::CompileResult* const ret) {
296 if (!mHost) {
297 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
300 *ret = mHost->GetCompileResult(id);
301 return IPC_OK();
304 IPCResult WebGLParent::RecvGetError(GLenum* const ret) {
305 if (!mHost) {
306 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
309 *ret = mHost->GetError();
310 return IPC_OK();
313 IPCResult WebGLParent::RecvGetFragDataLocation(ObjectId id,
314 const std::string& name,
315 GLint* const ret) {
316 if (!mHost) {
317 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
320 *ret = mHost->GetFragDataLocation(id, name);
321 return IPC_OK();
324 IPCResult WebGLParent::RecvGetFramebufferAttachmentParameter(
325 ObjectId id, GLenum attachment, GLenum pname, Maybe<double>* const ret) {
326 if (!mHost) {
327 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
330 *ret = mHost->GetFramebufferAttachmentParameter(id, attachment, pname);
331 return IPC_OK();
334 IPCResult WebGLParent::RecvGetFrontBuffer(
335 ObjectId fb, const bool vr, Maybe<layers::SurfaceDescriptor>* const ret) {
336 if (!mHost) {
337 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
340 *ret = mHost->GetFrontBuffer(fb, vr);
341 return IPC_OK();
344 IPCResult WebGLParent::RecvGetIndexedParameter(GLenum target, GLuint index,
345 Maybe<double>* const ret) {
346 if (!mHost) {
347 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
350 *ret = mHost->GetIndexedParameter(target, index);
351 return IPC_OK();
354 IPCResult WebGLParent::RecvGetInternalformatParameter(
355 const GLenum target, const GLuint format, const GLuint pname,
356 Maybe<std::vector<int32_t>>* const ret) {
357 if (!mHost) {
358 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
361 *ret = mHost->GetInternalformatParameter(target, format, pname);
362 return IPC_OK();
365 IPCResult WebGLParent::RecvGetLinkResult(ObjectId id,
366 webgl::LinkResult* const ret) {
367 if (!mHost) {
368 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
371 *ret = mHost->GetLinkResult(id);
372 return IPC_OK();
375 IPCResult WebGLParent::RecvGetNumber(GLenum pname, Maybe<double>* const ret) {
376 if (!mHost) {
377 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
380 *ret = mHost->GetNumber(pname);
381 return IPC_OK();
384 IPCResult WebGLParent::RecvGetQueryParameter(ObjectId id, GLenum pname,
385 Maybe<double>* const ret) {
386 if (!mHost) {
387 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
390 *ret = mHost->GetQueryParameter(id, pname);
391 return IPC_OK();
394 IPCResult WebGLParent::RecvGetRenderbufferParameter(ObjectId id, GLenum pname,
395 Maybe<double>* const ret) {
396 if (!mHost) {
397 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
400 *ret = mHost->GetRenderbufferParameter(id, pname);
401 return IPC_OK();
404 IPCResult WebGLParent::RecvGetSamplerParameter(ObjectId id, GLenum pname,
405 Maybe<double>* const ret) {
406 if (!mHost) {
407 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
410 *ret = mHost->GetSamplerParameter(id, pname);
411 return IPC_OK();
414 IPCResult WebGLParent::RecvGetShaderPrecisionFormat(
415 GLenum shaderType, GLenum precisionType,
416 Maybe<webgl::ShaderPrecisionFormat>* const ret) {
417 if (!mHost) {
418 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
421 *ret = mHost->GetShaderPrecisionFormat(shaderType, precisionType);
422 return IPC_OK();
425 IPCResult WebGLParent::RecvGetString(GLenum pname,
426 Maybe<std::string>* const ret) {
427 if (!mHost) {
428 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
431 *ret = mHost->GetString(pname);
432 return IPC_OK();
435 IPCResult WebGLParent::RecvGetTexParameter(ObjectId id, GLenum pname,
436 Maybe<double>* const ret) {
437 if (!mHost) {
438 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
441 *ret = mHost->GetTexParameter(id, pname);
442 return IPC_OK();
445 IPCResult WebGLParent::RecvGetUniform(ObjectId id, uint32_t loc,
446 webgl::GetUniformData* const ret) {
447 if (!mHost) {
448 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
451 *ret = mHost->GetUniform(id, loc);
452 return IPC_OK();
455 IPCResult WebGLParent::RecvGetVertexAttrib(GLuint index, GLenum pname,
456 Maybe<double>* const ret) {
457 if (!mHost) {
458 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
461 *ret = mHost->GetVertexAttrib(index, pname);
462 return IPC_OK();
465 IPCResult WebGLParent::RecvOnMemoryPressure() {
466 if (!mHost) {
467 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
470 mHost->OnMemoryPressure();
471 return IPC_OK();
474 IPCResult WebGLParent::RecvValidateProgram(ObjectId id, bool* const ret) {
475 if (!mHost) {
476 return IPC_FAIL(this, "HostWebGLContext is not initialized.");
479 *ret = mHost->ValidateProgram(id);
480 return IPC_OK();
483 } // namespace mozilla::dom