Commit 35c6236c authored by Yan, Shaobo's avatar Yan, Shaobo Committed by Commit Bot

copyImageBitmapToTexture: validate imageBitmap state and allow noop copy

- Add rule to check imageBitmap state and throw invalid state error
exception if imageBitmap has been closed.

- Add rule to check depth of copySize and throw range error exception
  if depth of copySize is larger than 1.

- Allow noop copy and modify validation rule to support on border
  source origin.

BUG=966582

Change-Id: I9ce4fa6ec152a538cf88c42bb0b9cee634f55b54
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2402584Reviewed-by: default avatarAustin Eng <enga@chromium.org>
Reviewed-by: default avatarCorentin Wallez <cwallez@chromium.org>
Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
Cr-Commit-Position: refs/heads/master@{#809682}
parent 2d956c00
......@@ -337,6 +337,13 @@ void GPUQueue::copyImageBitmapToTexture(
return;
}
// ImageBitmap shouldn't in closed state.
if (source->imageBitmap()->IsNeutered()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"ImageBitmap is closed.");
return;
}
scoped_refptr<StaticBitmapImage> image = source->imageBitmap()->BitmapImage();
......@@ -350,10 +357,18 @@ void GPUQueue::copyImageBitmapToTexture(
WGPUOrigin3D origin_in_image_bitmap =
GPUOrigin2DToWGPUOrigin3D(&(source->origin()));
// Validate copy depth
if (dawn_copy_size.depth > 1) {
GetProcs().deviceInjectError(device_->GetHandle(), WGPUErrorType_Validation,
"Copy depth is out of bounds of imageBitmap.");
return;
}
// Validate origin value
if (static_cast<uint32_t>(image->width()) <= origin_in_image_bitmap.x ||
static_cast<uint32_t>(image->height()) <= origin_in_image_bitmap.y) {
exception_state.ThrowRangeError(
if (static_cast<uint32_t>(image->width()) < origin_in_image_bitmap.x ||
static_cast<uint32_t>(image->height()) < origin_in_image_bitmap.y) {
GetProcs().deviceInjectError(
device_->GetHandle(), WGPUErrorType_Validation,
"Copy origin is out of bounds of imageBitmap.");
return;
}
......@@ -361,8 +376,8 @@ void GPUQueue::copyImageBitmapToTexture(
// Validate the copy rect is inside the imageBitmap
if (image->width() - origin_in_image_bitmap.x < dawn_copy_size.width ||
image->height() - origin_in_image_bitmap.y < dawn_copy_size.height) {
exception_state.ThrowRangeError(
"Copy rect is out of bounds of imageBitmap.");
GetProcs().deviceInjectError(device_->GetHandle(), WGPUErrorType_Validation,
"Copy rect is out of bounds of imageBitmap.");
return;
}
......@@ -373,9 +388,12 @@ void GPUQueue::copyImageBitmapToTexture(
return;
}
bool isNoopCopy = dawn_copy_size.width == 0 || dawn_copy_size.height == 0 ||
dawn_copy_size.depth == 0;
// TODO(shaobo.yan@intel.com): Implement GPU copy path
// Try GPU path first.
if (image->IsTextureBacked()) { // Try GPU uploading path.
// Try GPU path first and delegate noop copy to CPU path.
if (image->IsTextureBacked() && !isNoopCopy) { // Try GPU uploading path.
if (CanUploadThroughGPU(image.get(), destination->texture())) {
if (CopyContentFromGPU(image.get(), origin_in_image_bitmap,
dawn_copy_size, dawn_destination)) {
......@@ -405,11 +423,13 @@ bool GPUQueue::CopyContentFromCPU(StaticBitmapImage* image,
WebGPUImageUploadSizeInfo info = ComputeImageBitmapWebGPUUploadSizeInfo(
image_data_rect, dest_texture_format);
bool isNoopCopy = info.size_in_bytes == 0 || copy_size.depth == 0;
// Create a mapped buffer to receive image bitmap contents
WGPUBufferDescriptor buffer_desc = {};
buffer_desc.usage = WGPUBufferUsage_CopySrc;
buffer_desc.size = info.size_in_bytes;
buffer_desc.mappedAtCreation = true;
buffer_desc.mappedAtCreation = !isNoopCopy;
if (buffer_desc.size > uint64_t(std::numeric_limits<size_t>::max())) {
return false;
......@@ -418,17 +438,22 @@ bool GPUQueue::CopyContentFromCPU(StaticBitmapImage* image,
WGPUBuffer buffer =
GetProcs().deviceCreateBuffer(device_->GetHandle(), &buffer_desc);
void* data = GetProcs().bufferGetMappedRange(buffer, 0, size);
if (!CopyBytesFromImageBitmapForWebGPU(
image, base::span<uint8_t>(static_cast<uint8_t*>(data), size),
image_data_rect, dest_texture_format)) {
// Release the buffer.
GetProcs().bufferRelease(buffer);
return false;
}
// Bypass extract source content in noop copy but follow the copy path
// for validation.
if (!isNoopCopy) {
void* data = GetProcs().bufferGetMappedRange(buffer, 0, size);
GetProcs().bufferUnmap(buffer);
if (!CopyBytesFromImageBitmapForWebGPU(
image, base::span<uint8_t>(static_cast<uint8_t*>(data), size),
image_data_rect, dest_texture_format)) {
// Release the buffer.
GetProcs().bufferRelease(buffer);
return false;
}
GetProcs().bufferUnmap(buffer);
}
// Start a B2T copy to move contents from buffer to destination texture
WGPUBufferCopyView dawn_intermediate = {};
......
......@@ -80,6 +80,8 @@ bool CopyBytesFromImageBitmapForWebGPU(
DCHECK_GT(dst.size(), static_cast<size_t>(0));
DCHECK(image->width() - rect.X() >= rect.Width());
DCHECK(image->height() - rect.Y() >= rect.Height());
DCHECK(rect.Width());
DCHECK(rect.Height());
WebGPUImageUploadSizeInfo wgpu_info =
ComputeImageBitmapWebGPUUploadSizeInfo(rect, destination_format);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment