blob: 3fe8fd7b0715c5aeb0c2302831f70a42bd653ded [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/client/webgpu_interface.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
namespace blink {
namespace {
static constexpr uint64_t kDawnBytesPerRowAlignmentBits = 8;
// Calculate bytes per row for T2B/B2T copy
// TODO(shaobo.yan@intel.com): Using Dawn's constants once they are exposed
uint64_t AlignWebGPUBytesPerRow(uint64_t bytesPerRow) {
return (((bytesPerRow - 1) >> kDawnBytesPerRowAlignmentBits) + 1)
<< kDawnBytesPerRowAlignmentBits;
}
SkColorType DawnColorTypeToSkColorType(WGPUTextureFormat dawn_format) {
switch (dawn_format) {
case WGPUTextureFormat_RGBA8Unorm:
// According to WebGPU spec, format with -srgb suffix will do color
// space conversion when reading and writing in shader. In this uploading
// path, we should keep the conversion happening in canvas color space and
// leave the srgb color space conversion to the GPU.
case WGPUTextureFormat_RGBA8UnormSrgb:
return SkColorType::kRGBA_8888_SkColorType;
case WGPUTextureFormat_BGRA8Unorm:
case WGPUTextureFormat_BGRA8UnormSrgb:
return SkColorType::kBGRA_8888_SkColorType;
case WGPUTextureFormat_RGB10A2Unorm:
return SkColorType::kRGBA_1010102_SkColorType;
case WGPUTextureFormat_RGBA16Float:
return SkColorType::kRGBA_F16_SkColorType;
case WGPUTextureFormat_RGBA32Float:
return SkColorType::kRGBA_F32_SkColorType;
case WGPUTextureFormat_RG8Unorm:
return SkColorType::kR8G8_unorm_SkColorType;
case WGPUTextureFormat_RG16Float:
return SkColorType::kR16G16_float_SkColorType;
default:
return SkColorType::kUnknown_SkColorType;
}
}
} // anonymous namespace
WebGPUImageUploadSizeInfo ComputeImageBitmapWebGPUUploadSizeInfo(
const IntRect& rect,
const WGPUTextureFormat& destination_format) {
WebGPUImageUploadSizeInfo info;
uint64_t bytes_per_pixel = DawnTextureFormatBytesPerPixel(destination_format);
DCHECK_NE(bytes_per_pixel, 0u);
uint64_t bytes_per_row =
AlignWebGPUBytesPerRow(rect.Width() * bytes_per_pixel);
// Currently, bytes per row for buffer copy view in WebGPU is an uint32_t type
// value and the maximum value is std::numeric_limits<uint32_t>::max().
DCHECK(bytes_per_row <= std::numeric_limits<uint32_t>::max());
info.wgpu_bytes_per_row = static_cast<uint32_t>(bytes_per_row);
info.size_in_bytes = bytes_per_row * rect.Height();
return info;
}
bool CopyBytesFromImageBitmapForWebGPU(
scoped_refptr<StaticBitmapImage> image,
base::span<uint8_t> dst,
const IntRect& rect,
const WGPUTextureFormat destination_format) {
DCHECK(image);
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);
DCHECK_EQ(static_cast<uint64_t>(dst.size()), wgpu_info.size_in_bytes);
// Prepare extract data from SkImage.
SkColorType sk_color_type = DawnColorTypeToSkColorType(destination_format);
if (sk_color_type == kUnknown_SkColorType) {
return false;
}
PaintImage paint_image = image->PaintImageForCurrentFrame();
// Read pixel request dst info.
// Keep premulalpha config and color space from imageBitmap and using dest
// texture color type. This can help do conversions in ReadPixels.
SkImageInfo info = SkImageInfo::Make(
rect.Width(), rect.Height(), sk_color_type,
image->IsPremultiplied() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType,
paint_image.GetSkImageInfo().refColorSpace());
bool read_pixels_successful = paint_image.readPixels(
info, dst.data(), wgpu_info.wgpu_bytes_per_row, rect.X(), rect.Y());
if (!read_pixels_successful) {
return false;
}
return true;
}
uint64_t DawnTextureFormatBytesPerPixel(const WGPUTextureFormat color_type) {
switch (color_type) {
case WGPUTextureFormat_RG8Unorm:
return 2;
case WGPUTextureFormat_RGBA8Unorm:
case WGPUTextureFormat_RGBA8UnormSrgb:
case WGPUTextureFormat_BGRA8Unorm:
case WGPUTextureFormat_BGRA8UnormSrgb:
case WGPUTextureFormat_RGB10A2Unorm:
case WGPUTextureFormat_RG16Float:
return 4;
case WGPUTextureFormat_RGBA16Float:
return 8;
case WGPUTextureFormat_RGBA32Float:
return 16;
default:
NOTREACHED();
return 0;
}
}
} // namespace blink