blob: 915f3403cc8bd783df5992cbaabd66e937f5048b [file] [log] [blame]
// Copyright 2021 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_mailbox_texture.h"
#include "gpu/command_buffer/client/webgpu_interface.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
namespace blink {
// static
scoped_refptr<WebGPUMailboxTexture> WebGPUMailboxTexture::FromStaticBitmapImage(
scoped_refptr<DawnControlClientHolder> dawn_control_client,
WGPUDevice device,
WGPUTextureUsage usage,
scoped_refptr<StaticBitmapImage> image) {
DCHECK(image->IsTextureBacked());
auto finished_access_callback =
WTF::Bind(&StaticBitmapImage::UpdateSyncToken, WTF::RetainedRef(image));
return base::AdoptRef(new WebGPUMailboxTexture(
std::move(dawn_control_client), device, usage,
image->GetMailboxHolder().mailbox, image->GetMailboxHolder().sync_token,
std::move(finished_access_callback)));
}
// static
scoped_refptr<WebGPUMailboxTexture> WebGPUMailboxTexture::FromCanvasResource(
scoped_refptr<DawnControlClientHolder> dawn_control_client,
WGPUDevice device,
WGPUTextureUsage usage,
scoped_refptr<CanvasResource> canvas_resource) {
auto finished_access_callback = WTF::Bind(&CanvasResource::WaitSyncToken,
WTF::RetainedRef(canvas_resource));
const gpu::Mailbox& mailbox =
canvas_resource->GetOrCreateGpuMailbox(kUnverifiedSyncToken);
gpu::SyncToken sync_token = canvas_resource->GetSyncToken();
return base::AdoptRef(new WebGPUMailboxTexture(
std::move(dawn_control_client), device, usage, mailbox, sync_token,
std::move(finished_access_callback)));
}
WebGPUMailboxTexture::WebGPUMailboxTexture(
scoped_refptr<DawnControlClientHolder> dawn_control_client,
WGPUDevice device,
WGPUTextureUsage usage,
const gpu::Mailbox& mailbox,
const gpu::SyncToken& sync_token,
base::OnceCallback<void(const gpu::SyncToken&)> destroy_callback)
: dawn_control_client_(std::move(dawn_control_client)),
device_(device),
destroy_callback_(std::move(destroy_callback)) {
dawn_control_client_->GetProcs().deviceReference(device_);
gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
// Wait on any work using the image.
webgpu->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
// Produce and inject image to WebGPU texture
gpu::webgpu::ReservedTexture reservation = webgpu->ReserveTexture(device_);
DCHECK(reservation.texture);
wire_texture_id_ = reservation.id;
wire_texture_generation_ = reservation.generation;
texture_ = reservation.texture;
// This may fail because gl_backing resource cannot produce dawn
// representation.
webgpu->AssociateMailbox(reservation.deviceId, reservation.deviceGeneration,
wire_texture_id_, wire_texture_generation_, usage,
reinterpret_cast<const GLbyte*>(&mailbox));
}
WebGPUMailboxTexture::~WebGPUMailboxTexture() {
DCHECK_NE(wire_texture_id_, 0u);
gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
webgpu->DissociateMailbox(wire_texture_id_, wire_texture_generation_);
if (destroy_callback_) {
gpu::SyncToken finished_access_token;
webgpu->GenUnverifiedSyncTokenCHROMIUM(finished_access_token.GetData());
std::move(destroy_callback_).Run(finished_access_token);
}
dawn_control_client_->GetProcs().deviceRelease(device_);
}
} // namespace blink