зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1682612 - Check for ArrayBuffer Detach/Transfer in texImage2D(ImageData). r=gfx-reviewers,aosmond
Differential Revision: https://phabricator.services.mozilla.com/D141689
This commit is contained in:
Родитель
30bc9c7098
Коммит
e780e343c7
|
@ -3955,10 +3955,6 @@ Maybe<webgl::TexUnpackBlobDesc> FromImageBitmap(
|
|||
GLenum target, Maybe<uvec3> size, const dom::ImageBitmap& imageBitmap,
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
webgl::TexUnpackBlobDesc FromImageData(GLenum target, Maybe<uvec3> size,
|
||||
const dom::ImageData& imageData,
|
||||
dom::Uint8ClampedArray* const scopedArr);
|
||||
|
||||
Maybe<webgl::TexUnpackBlobDesc> FromOffscreenCanvas(
|
||||
const ClientWebGLContext&, GLenum target, Maybe<uvec3> size,
|
||||
const dom::OffscreenCanvas& src, ErrorResult* const out_error);
|
||||
|
@ -4075,8 +4071,51 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget,
|
|||
}
|
||||
|
||||
if (src.mImageData) {
|
||||
return Some(webgl::FromImageData(imageTarget, size, *(src.mImageData),
|
||||
&scopedArr));
|
||||
const auto& imageData = *src.mImageData;
|
||||
MOZ_RELEASE_ASSERT(scopedArr.Init(imageData.GetDataObject()));
|
||||
scopedArr.ComputeState();
|
||||
const auto dataSize = scopedArr.Length();
|
||||
const auto data = reinterpret_cast<uint8_t*>(scopedArr.Data());
|
||||
if (!data) {
|
||||
// Neutered, e.g. via Transfer
|
||||
EnqueueError(LOCAL_GL_INVALID_VALUE,
|
||||
"ImageData.data.buffer is Detached. (Maybe you Transfered "
|
||||
"it to a Worker?");
|
||||
return {};
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
const gfx::IntSize imageSize(imageData.Width(), imageData.Height());
|
||||
const auto sizeFromDims =
|
||||
CheckedInt<size_t>(imageSize.width) * imageSize.height * 4;
|
||||
MOZ_RELEASE_ASSERT(sizeFromDims.isValid() &&
|
||||
sizeFromDims.value() == dataSize);
|
||||
|
||||
const RefPtr<gfx::DataSourceSurface> surf =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(
|
||||
data, imageSize.width * 4, imageSize,
|
||||
gfx::SurfaceFormat::R8G8B8A8);
|
||||
MOZ_ASSERT(surf);
|
||||
|
||||
// -
|
||||
|
||||
const auto imageUSize = *uvec2::FromSize(imageSize);
|
||||
const auto concreteSize =
|
||||
size.valueOr(uvec3{imageUSize.x, imageUSize.y, 1});
|
||||
|
||||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned
|
||||
// as non-premultiplied alpha values."
|
||||
return Some(webgl::TexUnpackBlobDesc{imageTarget,
|
||||
concreteSize,
|
||||
gfxAlphaType::NonPremult,
|
||||
{},
|
||||
{},
|
||||
Some(imageUSize),
|
||||
nullptr,
|
||||
{},
|
||||
surf});
|
||||
}
|
||||
|
||||
if (src.mOffscreenCanvas) {
|
||||
|
|
|
@ -32,7 +32,15 @@ template <typename T>
|
|||
class Optional;
|
||||
|
||||
class ImageData final : public nsISupports {
|
||||
~ImageData() { DropData(); }
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ImageData)
|
||||
|
||||
const uint32_t mWidth;
|
||||
const uint32_t mHeight;
|
||||
|
||||
private:
|
||||
JS::Heap<JSObject*> mData;
|
||||
|
||||
public:
|
||||
ImageData(uint32_t aWidth, uint32_t aHeight, JSObject& aData)
|
||||
|
@ -40,9 +48,6 @@ class ImageData final : public nsISupports {
|
|||
HoldData();
|
||||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ImageData)
|
||||
|
||||
static already_AddRefed<ImageData> Constructor(const GlobalObject& aGlobal,
|
||||
const uint32_t aWidth,
|
||||
const uint32_t aHeight,
|
||||
|
@ -75,9 +80,7 @@ class ImageData final : public nsISupports {
|
|||
void DropData();
|
||||
|
||||
ImageData() = delete;
|
||||
|
||||
uint32_t mWidth, mHeight;
|
||||
JS::Heap<JSObject*> mData;
|
||||
~ImageData() { DropData(); }
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -72,41 +72,6 @@ Maybe<TexUnpackBlobDesc> FromImageBitmap(const GLenum target, Maybe<uvec3> size,
|
|||
false});
|
||||
}
|
||||
|
||||
TexUnpackBlobDesc FromImageData(const GLenum target, Maybe<uvec3> size,
|
||||
const dom::ImageData& imageData,
|
||||
dom::Uint8ClampedArray* const scopedArr) {
|
||||
MOZ_RELEASE_ASSERT(scopedArr->Init(imageData.GetDataObject()));
|
||||
scopedArr->ComputeState();
|
||||
const size_t dataSize = scopedArr->Length();
|
||||
const auto data = reinterpret_cast<uint8_t*>(scopedArr->Data());
|
||||
|
||||
const gfx::IntSize imageISize(imageData.Width(), imageData.Height());
|
||||
const auto imageUSize = *uvec2::FromSize(imageISize);
|
||||
const size_t stride = imageUSize.x * 4;
|
||||
const gfx::SurfaceFormat surfFormat = gfx::SurfaceFormat::R8G8B8A8;
|
||||
MOZ_ALWAYS_TRUE(dataSize == stride * imageUSize.y);
|
||||
|
||||
const RefPtr<gfx::DataSourceSurface> surf =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(data, stride, imageISize,
|
||||
surfFormat);
|
||||
MOZ_ASSERT(surf);
|
||||
|
||||
////
|
||||
|
||||
if (!size) {
|
||||
size.emplace(imageUSize.x, imageUSize.y, 1);
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
|
||||
// non-premultiplied alpha values."
|
||||
return {target, size.value(), gfxAlphaType::NonPremult,
|
||||
{}, {}, Some(imageUSize),
|
||||
nullptr, {}, surf};
|
||||
}
|
||||
|
||||
static layers::SurfaceDescriptor Flatten(const layers::SurfaceDescriptor& sd) {
|
||||
const auto sdType = sd.type();
|
||||
if (sdType != layers::SurfaceDescriptor::TSurfaceDescriptorGPUVideo) {
|
||||
|
|
|
@ -74,6 +74,7 @@ support-files = ../captureStream_common.js
|
|||
fail-if = (os == 'android') || (os == 'linux') || (os == 'mac')
|
||||
[test_hidden_alpha.html]
|
||||
[test_hidden_depth_stencil.html]
|
||||
[test_imagedata_transfered_arraybuffer.html]
|
||||
[test_implicit_color_buffer_float.html]
|
||||
[test_highp_fs.html]
|
||||
[test_no_arr_points.html]
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<script src='/tests/SimpleTest/SimpleTest.js'></script>
|
||||
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
'use strict';
|
||||
const ab = new ArrayBuffer(4);
|
||||
const ta = new Uint8ClampedArray(ab);
|
||||
const idata = new ImageData(ta, 1);
|
||||
const canvas = document.createElement('canvas');
|
||||
const gl = canvas.getContext('webgl2');
|
||||
const worker = new Worker('worker.js');
|
||||
worker.postMessage([ab], [ab]);
|
||||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 1, gl.RGB, idata.width, idata.height, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, idata);
|
||||
const err = gl.getError();
|
||||
window.ok = window.ok || console.log;
|
||||
ok(err == gl.INVALID_VALUE, 'texImage2D(ImageData) with Transferred ArrayBuffer is INVALID_VALUE');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче