mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 13:58:49 +00:00
Issue #2546 - Part 1: Remove BufferSource support in CreateImageBitmap.
This commit is contained in:
@@ -14614,11 +14614,6 @@ already_AddRefed<Promise>
|
||||
nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ImageBitmap::Create(this, aImage, Nothing(), aRv);
|
||||
}
|
||||
|
||||
@@ -14627,11 +14622,6 @@ nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage,
|
||||
int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
|
||||
}
|
||||
|
||||
@@ -14646,13 +14636,8 @@ nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage,
|
||||
aRv.Throw(NS_ERROR_TYPE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
||||
return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
|
||||
aRv);
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_TYPE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
aRv.Throw(NS_ERROR_TYPE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#structured-cloning
|
||||
|
||||
+1
-274
@@ -1867,217 +1867,6 @@ ImageBitmap::MapDataInto(JSContext* aCx,
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// ImageBitmapFactories extensions.
|
||||
static SurfaceFormat
|
||||
ImageFormatToSurfaceFromat(mozilla::dom::ImageBitmapFormat aFormat)
|
||||
{
|
||||
switch(aFormat) {
|
||||
case ImageBitmapFormat::RGBA32:
|
||||
return SurfaceFormat::R8G8B8A8;
|
||||
case ImageBitmapFormat::BGRA32:
|
||||
return SurfaceFormat::B8G8R8A8;
|
||||
case ImageBitmapFormat::RGB24:
|
||||
return SurfaceFormat::R8G8B8;
|
||||
case ImageBitmapFormat::BGR24:
|
||||
return SurfaceFormat::B8G8R8;
|
||||
case ImageBitmapFormat::GRAY8:
|
||||
return SurfaceFormat::A8;
|
||||
case ImageBitmapFormat::HSV:
|
||||
return SurfaceFormat::HSV;
|
||||
case ImageBitmapFormat::Lab:
|
||||
return SurfaceFormat::Lab;
|
||||
case ImageBitmapFormat::DEPTH:
|
||||
return SurfaceFormat::Depth;
|
||||
default:
|
||||
return SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<layers::Image>
|
||||
CreateImageFromBufferSourceRawData(const uint8_t*aBufferData,
|
||||
uint32_t aBufferLength,
|
||||
mozilla::dom::ImageBitmapFormat aFormat,
|
||||
const Sequence<ChannelPixelLayout>& aLayout)
|
||||
{
|
||||
MOZ_ASSERT(aBufferData);
|
||||
MOZ_ASSERT(aBufferLength > 0);
|
||||
|
||||
switch(aFormat) {
|
||||
case ImageBitmapFormat::RGBA32:
|
||||
case ImageBitmapFormat::BGRA32:
|
||||
case ImageBitmapFormat::RGB24:
|
||||
case ImageBitmapFormat::BGR24:
|
||||
case ImageBitmapFormat::GRAY8:
|
||||
case ImageBitmapFormat::HSV:
|
||||
case ImageBitmapFormat::Lab:
|
||||
case ImageBitmapFormat::DEPTH:
|
||||
{
|
||||
const nsTArray<ChannelPixelLayout>& channels = aLayout;
|
||||
MOZ_ASSERT(channels.Length() != 0, "Empty Channels.");
|
||||
|
||||
const SurfaceFormat srcFormat = ImageFormatToSurfaceFromat(aFormat);
|
||||
const uint32_t srcStride = channels[0].mStride;
|
||||
const IntSize srcSize(channels[0].mWidth, channels[0].mHeight);
|
||||
|
||||
RefPtr<DataSourceSurface> dstDataSurface =
|
||||
Factory::CreateDataSourceSurfaceWithStride(srcSize, srcFormat, srcStride);
|
||||
|
||||
if (NS_WARN_IF(!dstDataSurface)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Copy the raw data into the newly created DataSourceSurface.
|
||||
DataSourceSurface::ScopedMap dstMap(dstDataSurface, DataSourceSurface::WRITE);
|
||||
if (NS_WARN_IF(!dstMap.IsMapped())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint8_t* srcBufferPtr = aBufferData;
|
||||
uint8_t* dstBufferPtr = dstMap.GetData();
|
||||
|
||||
for (int i = 0; i < srcSize.height; ++i) {
|
||||
memcpy(dstBufferPtr, srcBufferPtr, srcStride);
|
||||
srcBufferPtr += srcStride;
|
||||
dstBufferPtr += dstMap.GetStride();
|
||||
}
|
||||
|
||||
// Create an Image from the BGRA SourceSurface.
|
||||
RefPtr<SourceSurface> surface = dstDataSurface;
|
||||
RefPtr<layers::Image> image = CreateImageFromSurface(surface);
|
||||
|
||||
if (NS_WARN_IF(!image)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return image.forget();
|
||||
}
|
||||
case ImageBitmapFormat::YUV444P:
|
||||
case ImageBitmapFormat::YUV422P:
|
||||
case ImageBitmapFormat::YUV420P:
|
||||
case ImageBitmapFormat::YUV420SP_NV12:
|
||||
case ImageBitmapFormat::YUV420SP_NV21:
|
||||
{
|
||||
// Prepare the PlanarYCbCrData.
|
||||
const ChannelPixelLayout& yLayout = aLayout[0];
|
||||
const ChannelPixelLayout& uLayout = aFormat != ImageBitmapFormat::YUV420SP_NV21 ? aLayout[1] : aLayout[2];
|
||||
const ChannelPixelLayout& vLayout = aFormat != ImageBitmapFormat::YUV420SP_NV21 ? aLayout[2] : aLayout[1];
|
||||
|
||||
layers::PlanarYCbCrData data;
|
||||
|
||||
// Luminance buffer
|
||||
data.mYChannel = const_cast<uint8_t*>(aBufferData + yLayout.mOffset);
|
||||
data.mYStride = yLayout.mStride;
|
||||
data.mYSize = gfx::IntSize(yLayout.mWidth, yLayout.mHeight);
|
||||
data.mYSkip = yLayout.mSkip;
|
||||
|
||||
// Chroma buffers
|
||||
data.mCbChannel = const_cast<uint8_t*>(aBufferData + uLayout.mOffset);
|
||||
data.mCrChannel = const_cast<uint8_t*>(aBufferData + vLayout.mOffset);
|
||||
data.mCbCrStride = uLayout.mStride;
|
||||
data.mCbCrSize = gfx::IntSize(uLayout.mWidth, uLayout.mHeight);
|
||||
data.mCbSkip = uLayout.mSkip;
|
||||
data.mCrSkip = vLayout.mSkip;
|
||||
|
||||
// Picture rectangle.
|
||||
// We set the picture rectangle to exactly the size of the source image to
|
||||
// keep the full original data.
|
||||
data.mPicX = 0;
|
||||
data.mPicY = 0;
|
||||
data.mPicSize = data.mYSize;
|
||||
|
||||
// Create a layers::Image and set data.
|
||||
if (aFormat == ImageBitmapFormat::YUV444P ||
|
||||
aFormat == ImageBitmapFormat::YUV422P ||
|
||||
aFormat == ImageBitmapFormat::YUV420P) {
|
||||
RefPtr<layers::PlanarYCbCrImage> image =
|
||||
new layers::RecyclingPlanarYCbCrImage(new layers::BufferRecycleBin());
|
||||
|
||||
if (NS_WARN_IF(!image)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set Data.
|
||||
if (NS_WARN_IF(!image->CopyData(data))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return image.forget();
|
||||
} else {
|
||||
RefPtr<layers::NVImage>image = new layers::NVImage();
|
||||
|
||||
if (NS_WARN_IF(!image)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set Data.
|
||||
if (NS_WARN_IF(!image->SetData(data))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return image.forget();
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a synchronous task.
|
||||
* This class is used to create a layers::CairoImage from raw data in the main
|
||||
* thread. While creating an ImageBitmap from an BufferSource, we need to create
|
||||
* a SouceSurface from the BufferSource raw data and then set the SourceSurface
|
||||
* into a layers::CairoImage. However, the layers::CairoImage asserts the
|
||||
* setting operation in the main thread, so if we are going to create an
|
||||
* ImageBitmap from an BufferSource off the main thread, we post an event to the
|
||||
* main thread to create a layers::CairoImage from an BufferSource raw data.
|
||||
*
|
||||
* TODO: Once the layers::CairoImage is constructible off the main thread, which
|
||||
* means the SouceSurface could be released anywhere, we do not need this
|
||||
* task anymore.
|
||||
*/
|
||||
class CreateImageFromBufferSourceRawDataInMainThreadSyncTask final :
|
||||
public WorkerMainThreadRunnable
|
||||
{
|
||||
public:
|
||||
CreateImageFromBufferSourceRawDataInMainThreadSyncTask(const uint8_t* aBuffer,
|
||||
uint32_t aBufferLength,
|
||||
mozilla::dom::ImageBitmapFormat aFormat,
|
||||
const Sequence<ChannelPixelLayout>& aLayout,
|
||||
/*output*/ layers::Image** aImage)
|
||||
: WorkerMainThreadRunnable(GetCurrentThreadWorkerPrivate(),
|
||||
NS_LITERAL_CSTRING("ImageBitmap-extensions :: Create Image from BufferSource Raw Data"))
|
||||
, mImage(aImage)
|
||||
, mBuffer(aBuffer)
|
||||
, mBufferLength(aBufferLength)
|
||||
, mFormat(aFormat)
|
||||
, mLayout(aLayout)
|
||||
{
|
||||
MOZ_ASSERT(!(*aImage), "Don't pass an existing Image into CreateImageFromBufferSourceRawDataInMainThreadSyncTask.");
|
||||
}
|
||||
|
||||
bool MainThreadRun() override
|
||||
{
|
||||
RefPtr<layers::Image> image =
|
||||
CreateImageFromBufferSourceRawData(mBuffer, mBufferLength, mFormat, mLayout);
|
||||
|
||||
if (NS_WARN_IF(!image)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
image.forget(mImage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
layers::Image** mImage;
|
||||
const uint8_t* mBuffer;
|
||||
uint32_t mBufferLength;
|
||||
mozilla::dom::ImageBitmapFormat mFormat;
|
||||
const Sequence<ChannelPixelLayout>& mLayout;
|
||||
};
|
||||
|
||||
/*static*/ already_AddRefed<Promise>
|
||||
ImageBitmap::Create(nsIGlobalObject* aGlobal,
|
||||
const ImageBitmapSource& aBuffer,
|
||||
@@ -2094,69 +1883,7 @@ ImageBitmap::Create(nsIGlobalObject* aGlobal,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t* bufferData = nullptr;
|
||||
uint32_t bufferLength = 0;
|
||||
|
||||
if (aBuffer.IsArrayBuffer()) {
|
||||
const ArrayBuffer& buffer = aBuffer.GetAsArrayBuffer();
|
||||
buffer.ComputeLengthAndData();
|
||||
bufferData = buffer.Data();
|
||||
bufferLength = buffer.Length();
|
||||
} else if (aBuffer.IsArrayBufferView()) {
|
||||
const ArrayBufferView& bufferView = aBuffer.GetAsArrayBufferView();
|
||||
bufferView.ComputeLengthAndData();
|
||||
bufferData = bufferView.Data();
|
||||
bufferLength = bufferView.Length();
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(bufferData && bufferLength > 0, "Cannot read data from BufferSource.");
|
||||
|
||||
// Check the buffer.
|
||||
if (((uint32_t)(aOffset + aLength) > bufferLength)) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Create and Crop the raw data into a layers::Image
|
||||
RefPtr<layers::Image> data;
|
||||
if (NS_IsMainThread()) {
|
||||
data = CreateImageFromBufferSourceRawData(bufferData + aOffset, bufferLength,
|
||||
aFormat, aLayout);
|
||||
} else {
|
||||
RefPtr<CreateImageFromBufferSourceRawDataInMainThreadSyncTask> task =
|
||||
new CreateImageFromBufferSourceRawDataInMainThreadSyncTask(bufferData + aOffset,
|
||||
bufferLength,
|
||||
aFormat,
|
||||
aLayout,
|
||||
getter_AddRefs(data));
|
||||
task->Dispatch(Terminating, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return promise.forget();
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!data)) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Create an ImageBimtap.
|
||||
// Assume the data from an external buffer is not alpha-premultiplied.
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(aGlobal, data, false);
|
||||
|
||||
// We don't need to call SetPictureRect() here because there is no cropping
|
||||
// supported and the ImageBitmap's mPictureRect is the size of the source
|
||||
// image in default
|
||||
|
||||
// We don't need to set mIsCroppingAreaOutSideOfSourceImage here because there
|
||||
// is no cropping supported and the mIsCroppingAreaOutSideOfSourceImage is
|
||||
// false in default.
|
||||
|
||||
AsyncFulfillImageBitmapPromise(promise, imageBitmap);
|
||||
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ class WorkerStructuredCloneClosure;
|
||||
|
||||
class ArrayBufferViewOrArrayBuffer;
|
||||
class CanvasRenderingContext2D;
|
||||
struct ChannelPixelLayout;
|
||||
class CreateImageBitmapFromBlob;
|
||||
class CreateImageBitmapFromBlobTask;
|
||||
class CreateImageBitmapFromBlobWorkerTask;
|
||||
|
||||
@@ -10,9 +10,8 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// So we don't have to forward declare this elsewhere.
|
||||
class HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrCanvasRenderingContext2DOrImageBitmapOrArrayBufferViewOrArrayBuffer;
|
||||
typedef HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrCanvasRenderingContext2DOrImageBitmapOrArrayBufferViewOrArrayBuffer
|
||||
ImageBitmapSource;
|
||||
class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmapOrBlobOrCanvasRenderingContext2DOrImageData;
|
||||
typedef HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmapOrBlobOrCanvasRenderingContext2DOrImageData ImageBitmapSource;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,25 +10,17 @@
|
||||
* http://w3c.github.io/mediacapture-worker/#imagebitmap-extensions
|
||||
*/
|
||||
|
||||
// Extensions
|
||||
// Bug 1141979 - [FoxEye] Extend ImageBitmap with interfaces to access its
|
||||
// underlying image data
|
||||
//
|
||||
// Note:
|
||||
// Our overload resolution implementation doesn't deal with a union as the
|
||||
// distinguishing argument which means we cannot overload functions via union
|
||||
// types, a.k.a. we cannot overload createImageBitmap() via ImageBitmapSource
|
||||
// and BufferSource. Here, we work around this issue by adding the BufferSource
|
||||
// into ImageBitmapSource.
|
||||
|
||||
// This is needed because we don't support SVG element as canvas image source.
|
||||
// See bug 1500768.
|
||||
typedef (HTMLImageElement or
|
||||
HTMLVideoElement or
|
||||
HTMLCanvasElement or
|
||||
HTMLVideoElement or
|
||||
ImageBitmap) CanvasImageSourceExcludedSVG;
|
||||
|
||||
typedef (CanvasImageSourceExcludedSVG or
|
||||
Blob or
|
||||
ImageData or
|
||||
CanvasRenderingContext2D or
|
||||
ImageBitmap or
|
||||
BufferSource) ImageBitmapSource;
|
||||
CanvasRenderingContext2D or // This is out of spec.
|
||||
ImageData) ImageBitmapSource;
|
||||
|
||||
[Exposed=(Window,Worker)]
|
||||
interface ImageBitmap {
|
||||
|
||||
@@ -450,11 +450,6 @@ already_AddRefed<Promise>
|
||||
WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ImageBitmap::Create(this, aImage, Nothing(), aRv);
|
||||
}
|
||||
|
||||
@@ -463,11 +458,6 @@ WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
|
||||
int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
|
||||
}
|
||||
|
||||
@@ -486,13 +476,8 @@ WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
||||
return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
|
||||
aRv);
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_TYPE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
aRv.Throw(NS_ERROR_TYPE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#structured-cloning
|
||||
|
||||
Reference in New Issue
Block a user