/* -*- 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/. */
void Queue::WriteBuffer(const Buffer& aBuffer, uint64_t aBufferOffset, const dom::ArrayBufferViewOrArrayBuffer& aData,
uint64_t aDataOffset, const dom::Optional<uint64_t>& aSize,
ErrorResult& aRv) { if (!aBuffer.mId) { // Invalid buffers are unknown to the parent -- don't try to write // to them. return;
}
size_t elementByteSize = 1; if (aData.IsArrayBufferView()) { auto type = aData.GetAsArrayBufferView().Type(); if (type != JS::Scalar::MaxTypedArrayViewType) {
elementByteSize = byteSize(type);
}
}
dom::ProcessTypedArraysFixed(
aData, [&, elementByteSize](const Span<const uint8_t>& aData) {
uint64_t byteLength = aData.Length();
auto checkedByteOffset =
CheckedInt<uint64_t>(aDataOffset) * elementByteSize; if (!checkedByteOffset.isValid()) {
aRv.ThrowOperationError("offset x element size overflows"); return;
} auto offset = checkedByteOffset.value();
size_t size; if (aSize.WasPassed()) { constauto checkedByteSize =
CheckedInt<size_t>(aSize.Value()) * elementByteSize; if (!checkedByteSize.isValid()) {
aRv.ThrowOperationError("write size x element size overflows"); return;
}
size = checkedByteSize.value();
} else { constauto checkedByteSize = CheckedInt<size_t>(byteLength) - offset; if (!checkedByteSize.isValid()) {
aRv.ThrowOperationError("data byte length - offset underflows"); return;
}
size = checkedByteSize.value();
}
auto checkedByteEnd = CheckedInt<uint64_t>(offset) + size; if (!checkedByteEnd.isValid() || checkedByteEnd.value() > byteLength) {
aRv.ThrowOperationError(
nsPrintfCString("Wrong data size %" PRIuPTR, size)); return;
}
if (size % 4 != 0) {
aRv.ThrowOperationError("Byte size must be a multiple of 4"); return;
}
auto alloc = mozilla::ipc::UnsafeSharedMemoryHandle::CreateAndMap(size); if (alloc.isNothing()) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return;
}
auto handle = std::move(alloc.ref().first); auto mapping = std::move(alloc.ref().second);
static WebGLTexelFormat ToWebGLTexelFormat(gfx::SurfaceFormat aFormat) { switch (aFormat) { case gfx::SurfaceFormat::B8G8R8A8: case gfx::SurfaceFormat::B8G8R8X8: return WebGLTexelFormat::BGRA8; case gfx::SurfaceFormat::R8G8B8A8: case gfx::SurfaceFormat::R8G8B8X8: return WebGLTexelFormat::RGBA8; default: return WebGLTexelFormat::FormatNotSupportingAnyConversion;
}
}
static WebGLTexelFormat ToWebGLTexelFormat(dom::GPUTextureFormat aFormat) { // TODO: We need support for Rbg10a2unorm as well. switch (aFormat) { case dom::GPUTextureFormat::R8unorm: return WebGLTexelFormat::R8; case dom::GPUTextureFormat::R16float: return WebGLTexelFormat::R16F; case dom::GPUTextureFormat::R32float: return WebGLTexelFormat::R32F; case dom::GPUTextureFormat::Rg8unorm: return WebGLTexelFormat::RG8; case dom::GPUTextureFormat::Rg16float: return WebGLTexelFormat::RG16F; case dom::GPUTextureFormat::Rg32float: return WebGLTexelFormat::RG32F; case dom::GPUTextureFormat::Rgba8unorm: case dom::GPUTextureFormat::Rgba8unorm_srgb: return WebGLTexelFormat::RGBA8; case dom::GPUTextureFormat::Bgra8unorm: case dom::GPUTextureFormat::Bgra8unorm_srgb: return WebGLTexelFormat::BGRA8; case dom::GPUTextureFormat::Rgba16float: return WebGLTexelFormat::RGBA16F; case dom::GPUTextureFormat::Rgba32float: return WebGLTexelFormat::RGBA32F; default: return WebGLTexelFormat::FormatNotSupportingAnyConversion;
}
}
if (!sfeResult.mCORSUsed) {
nsIGlobalObject* global = mParent->GetOwnerGlobal();
nsIPrincipal* dstPrincipal = global ? global->PrincipalOrNull() : nullptr; if (!sfeResult.mPrincipal || !dstPrincipal ||
!dstPrincipal->Subsumes(sfeResult.mPrincipal)) {
aRv.ThrowSecurityError("Cross-origin elements require CORS!"); return;
}
}
if (sfeResult.mIsWriteOnly) {
aRv.ThrowSecurityError("Write only source data not supported!"); return;
}
RefPtr<gfx::SourceSurface> surface = sfeResult.GetSourceSurface(); if (!surface) {
aRv.ThrowInvalidStateError("No surface available from source"); return;
}
RefPtr<gfx::DataSourceSurface> dataSurface = surface->GetDataSurface(); if (!dataSurface) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return;
}
bool srcPremultiplied; switch (sfeResult.mAlphaType) { case gfxAlphaType::Premult:
srcPremultiplied = true; break; case gfxAlphaType::NonPremult:
srcPremultiplied = false; break; case gfxAlphaType::Opaque: // No (un)premultiplication necessary so match the output.
srcPremultiplied = aDestination.mPremultipliedAlpha; break;
}
constauto surfaceFormat = dataSurface->GetFormat(); constauto srcFormat = ToWebGLTexelFormat(surfaceFormat); if (srcFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion) {
gfxCriticalError() << "Unsupported surface format from source "
<< surfaceFormat;
MOZ_CRASH();
}
gfx::DataSourceSurface::ScopedMap map(dataSurface,
gfx::DataSourceSurface::READ); if (!map.IsMapped()) {
aRv.ThrowInvalidStateError("Cannot map surface from source"); return;
}
if (!aSource.mOrigin.IsGPUOrigin2DDict()) {
aRv.ThrowInvalidStateError("Cannot get origin from source"); return;
}
ffi::WGPUExtent3d extent = {};
ConvertExtent3DToFFI(aCopySize, &extent); if (extent.depth_or_array_layers > 1) {
aRv.ThrowOperationError("Depth is greater than 1"); return;
}
if (!aDestination.mTexture->mBytesPerBlock) { // TODO(bug 1781071) This should emmit a GPUValidationError on the device // timeline.
aRv.ThrowInvalidStateError("Invalid destination format"); return;
}
// Note: This assumes bytes per block == bytes per pixel which is the case // here because the spec only allows non-compressed texture formats for the // destination. constauto dstStride = CheckedInt<uint32_t>(extent.width) *
aDestination.mTexture->mBytesPerBlock.value(); constauto dstByteLength = dstStride * extent.height; if (!dstStride.isValid() || !dstByteLength.isValid()) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return;
}
auto alloc = mozilla::ipc::UnsafeSharedMemoryHandle::CreateAndMap(
dstByteLength.value()); if (alloc.isNothing()) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return;
}
auto handle = std::move(alloc.ref().first); auto mapping = std::move(alloc.ref().second);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.