summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc')
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc174
1 files changed, 148 insertions, 26 deletions
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
index 8c98c6f0eb4..fe282e25f17 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
@@ -4,14 +4,24 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_texture.h"
+#include "gpu/command_buffer/client/webgpu_interface.h"
+#include "media/base/video_frame.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_view_descriptor.h"
+#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_texture_usage.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_texture_view.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.h"
+#include "third_party/blink/renderer/platform/graphics/video_frame_image_util.h"
namespace blink {
+bool GPUTextureUsage::usedDeprecatedOutputAttachment = false;
+
namespace {
WGPUTextureDescriptor AsDawnType(const GPUTextureDescriptor* webgpu_desc,
@@ -21,20 +31,20 @@ WGPUTextureDescriptor AsDawnType(const GPUTextureDescriptor* webgpu_desc,
DCHECK(label);
DCHECK(device);
+ if (webgpu_desc->usage() & GPUTextureUsage::kRenderAttachment &&
+ GPUTextureUsage::usedDeprecatedOutputAttachment) {
+ GPUTextureUsage::usedDeprecatedOutputAttachment = false;
+ device->AddConsoleWarning(
+ "GPUTextureUsage.OUTPUT_ATTACHMENT has been "
+ "renamed to GPUTextureUsage.RENDER_ATTACHMENT.");
+ }
+
WGPUTextureDescriptor dawn_desc = {};
dawn_desc.nextInChain = nullptr;
dawn_desc.usage = static_cast<WGPUTextureUsage>(webgpu_desc->usage());
dawn_desc.dimension =
AsDawnEnum<WGPUTextureDimension>(webgpu_desc->dimension());
- dawn_desc.size = AsDawnType(&webgpu_desc->size());
- if (webgpu_desc->format() == "rg11b10float") {
- device->AddConsoleWarning(
- "rg11b10float is deprecated. Use rg11b10ufloat instead.");
- }
- if (webgpu_desc->format() == "bc6h-rgb-sfloat") {
- device->AddConsoleWarning(
- "bc6h-rgb-sfloat is deprecated. Use bc6h-rgb-float instead.");
- }
+ dawn_desc.size = AsDawnType(&webgpu_desc->size(), device);
dawn_desc.format = AsDawnEnum<WGPUTextureFormat>(webgpu_desc->format());
dawn_desc.mipLevelCount = webgpu_desc->mipLevelCount();
dawn_desc.sampleCount = webgpu_desc->sampleCount();
@@ -80,22 +90,131 @@ GPUTexture* GPUTexture::Create(GPUDevice* device,
DCHECK(device);
DCHECK(webgpu_desc);
- // Check size is correctly formatted before further processing.
- const UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& size =
- webgpu_desc->size();
- if (size.IsUnsignedLongEnforceRangeSequence() &&
- size.GetAsUnsignedLongEnforceRangeSequence().size() != 3) {
- exception_state.ThrowRangeError("size length must be 3");
- return nullptr;
- }
-
std::string label;
WGPUTextureDescriptor dawn_desc = AsDawnType(webgpu_desc, &label, device);
- return MakeGarbageCollected<GPUTexture>(
+ GPUTexture* texture = MakeGarbageCollected<GPUTexture>(
device,
device->GetProcs().deviceCreateTexture(device->GetHandle(), &dawn_desc),
dawn_desc.format);
+ texture->setLabel(webgpu_desc->label());
+ return texture;
+}
+
+// static
+GPUTexture* GPUTexture::FromVideo(GPUDevice* device,
+ HTMLVideoElement* video,
+ WGPUTextureUsage usage,
+ ExceptionState& exception_state) {
+ if (!video || !video->videoWidth() || !video->videoHeight()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Missing video source");
+ return nullptr;
+ }
+
+ if (video->WouldTaintOrigin()) {
+ exception_state.ThrowSecurityError(
+ "Video element contains cross-origin data and may not be loaded.");
+ return nullptr;
+ }
+
+ media::PaintCanvasVideoRenderer* video_renderer = nullptr;
+ scoped_refptr<media::VideoFrame> media_video_frame;
+ if (auto* wmp = video->GetWebMediaPlayer()) {
+ media_video_frame = wmp->GetCurrentFrame();
+ video_renderer = wmp->GetPaintCanvasVideoRenderer();
+ }
+
+ if (!media_video_frame || !video_renderer) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Failed to import texture from video");
+ return nullptr;
+ }
+
+ // Create a CanvasResourceProvider for producing WebGPU-compatible shared
+ // images.
+ // TODO(crbug.com/1174809): This should recycle resources instead of creating
+ // a new shared image every time.
+ const auto intrinsic_size = IntSize(media_video_frame->natural_size());
+ std::unique_ptr<CanvasResourceProvider> resource_provider =
+ CanvasResourceProvider::CreateWebGPUImageProvider(
+ intrinsic_size, kLow_SkFilterQuality,
+ CanvasResourceParams(CanvasColorSpace::kSRGB, kN32_SkColorType,
+ kPremul_SkAlphaType),
+ CanvasResourceProvider::ShouldInitialize::kNo,
+ SharedGpuContext::ContextProviderWrapper());
+
+ if (!resource_provider) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Failed to import texture from video");
+ return nullptr;
+ }
+
+ viz::RasterContextProvider* raster_context_provider = nullptr;
+ if (auto wrapper = SharedGpuContext::ContextProviderWrapper()) {
+ if (auto* context_provider = wrapper->ContextProvider())
+ raster_context_provider = context_provider->RasterContextProvider();
+ }
+
+ // TODO(crbug.com/1174809): This isn't efficient for VideoFrames which are
+ // already available as a shared image. A WebGPUMailboxTexture should be
+ // created directly from the VideoFrame instead.
+ const auto dest_rect = gfx::Rect(media_video_frame->natural_size());
+ if (!DrawVideoFrameIntoResourceProvider(
+ std::move(media_video_frame), resource_provider.get(),
+ raster_context_provider, dest_rect, video_renderer)) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ "Failed to import texture from video");
+ return nullptr;
+ }
+
+ // Acquire the CanvasResource wrapping the shared image.
+ scoped_refptr<CanvasResource> canvas_resource =
+ resource_provider->ProduceCanvasResource();
+ DCHECK(canvas_resource->IsValid());
+ DCHECK(canvas_resource->IsAccelerated());
+
+ // Extract the format. This is only used to validate copyImageBitmapToTexture
+ // right now. We may want to reflect it from this function or validate it
+ // against some input parameters.
+ WGPUTextureFormat format;
+ switch (canvas_resource->CreateSkImageInfo().colorType()) {
+ case SkColorType::kRGBA_8888_SkColorType:
+ format = WGPUTextureFormat_RGBA8Unorm;
+ break;
+ case SkColorType::kBGRA_8888_SkColorType:
+ format = WGPUTextureFormat_BGRA8Unorm;
+ break;
+ case SkColorType::kRGBA_1010102_SkColorType:
+ format = WGPUTextureFormat_RGB10A2Unorm;
+ break;
+ case SkColorType::kRGBA_F16_SkColorType:
+ format = WGPUTextureFormat_RGBA16Float;
+ break;
+ case SkColorType::kRGBA_F32_SkColorType:
+ format = WGPUTextureFormat_RGBA32Float;
+ break;
+ case SkColorType::kR8G8_unorm_SkColorType:
+ format = WGPUTextureFormat_RG8Unorm;
+ break;
+ case SkColorType::kR16G16_float_SkColorType:
+ format = WGPUTextureFormat_RG16Float;
+ break;
+ default:
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kOperationError,
+ "Failed to import texture from video. Unsupported format.");
+ return nullptr;
+ }
+
+ scoped_refptr<WebGPUMailboxTexture> mailbox_texture =
+ WebGPUMailboxTexture::FromCanvasResource(device->GetDawnControlClient(),
+ device->GetHandle(), usage,
+ std::move(canvas_resource));
+ DCHECK(mailbox_texture->GetTexture() != nullptr);
+
+ return MakeGarbageCollected<GPUTexture>(device, format,
+ std::move(mailbox_texture));
}
GPUTexture::GPUTexture(GPUDevice* device,
@@ -103,12 +222,12 @@ GPUTexture::GPUTexture(GPUDevice* device,
WGPUTextureFormat format)
: DawnObject<WGPUTexture>(device, texture), format_(format) {}
-GPUTexture::~GPUTexture() {
- if (IsDawnControlClientDestroyed()) {
- return;
- }
- GetProcs().textureRelease(GetHandle());
-}
+GPUTexture::GPUTexture(GPUDevice* device,
+ WGPUTextureFormat format,
+ scoped_refptr<WebGPUMailboxTexture> mailbox_texture)
+ : DawnObject<WGPUTexture>(device, mailbox_texture->GetTexture()),
+ format_(format),
+ mailbox_texture_(std::move(mailbox_texture)) {}
GPUTextureView* GPUTexture::createView(
const GPUTextureViewDescriptor* webgpu_desc) {
@@ -116,12 +235,15 @@ GPUTextureView* GPUTexture::createView(
std::string label;
WGPUTextureViewDescriptor dawn_desc = AsDawnType(webgpu_desc, &label);
- return MakeGarbageCollected<GPUTextureView>(
+ GPUTextureView* view = MakeGarbageCollected<GPUTextureView>(
device_, GetProcs().textureCreateView(GetHandle(), &dawn_desc));
+ view->setLabel(webgpu_desc->label());
+ return view;
}
void GPUTexture::destroy() {
GetProcs().textureDestroy(GetHandle());
+ mailbox_texture_.reset();
}
} // namespace blink