blob: 3845e34a3ca15ee4a635bbf554952bab2a1f41dd [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_CANVAS_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_CANVAS_CONTEXT_H_
#include "base/containers/heap_array.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_canvas_tone_mapping_mode.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_canvas_alpha_mode.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_cpp.h"
#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h"
#include "third_party/blink/renderer/platform/graphics/predefined_color_space.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
namespace blink {
class ExceptionState;
class ExecutionContext;
class GPUDevice;
class GPUCanvasConfiguration;
class GPUSwapChain;
class GPUTexture;
class WebGPUTextureAlphaClearer;
class V8UnionHTMLCanvasElementOrOffscreenCanvas;
// A GPUCanvasContext does little by itself and basically just binds a canvas
// and a GPUSwapChain together and forwards calls from one to the other.
class GPUCanvasContext : public ScriptWrappable,
public CanvasRenderingContext,
public WebGPUSwapBufferProvider::Client {
DEFINE_WRAPPERTYPEINFO();
public:
class Factory : public CanvasRenderingContextFactory {
public:
Factory() = default;
Factory(const Factory&) = delete;
Factory& operator=(const Factory&) = delete;
~Factory() override;
CanvasRenderingContext* Create(
ExecutionContext*,
CanvasRenderingContextHost*,
const CanvasContextCreationAttributesCore&) override;
CanvasRenderingContext::CanvasRenderingAPI GetRenderingAPI() const override;
};
GPUCanvasContext(CanvasRenderingContextHost*,
const CanvasContextCreationAttributesCore&);
GPUCanvasContext(const GPUCanvasContext&) = delete;
GPUCanvasContext& operator=(const GPUCanvasContext&) = delete;
~GPUCanvasContext() override;
void Trace(Visitor*) const override;
// CanvasRenderingContext implementation
V8RenderingContext* AsV8RenderingContext() final;
V8OffscreenRenderingContext* AsV8OffscreenRenderingContext() final;
SkAlphaType GetAlphaType() const override;
viz::SharedImageFormat GetSharedImageFormat() const override;
gfx::ColorSpace GetColorSpace() const override;
// Produces a snapshot of the current contents of the swap chain if possible
// or else a snapshot of the most-recently presented contents.
scoped_refptr<StaticBitmapImage> GetImage(FlushReason) final;
scoped_refptr<StaticBitmapImage> PaintRenderingResultsToSnapshot(
SourceDrawingBuffer source_buffer,
FlushReason reason) override;
bool CopyRenderingResultsToVideoFrame(
WebGraphicsContext3DVideoFramePool* frame_pool,
SourceDrawingBuffer src_buffer,
const gfx::ColorSpace& dst_color_space,
VideoFrameCopyCompletedCallback callback) override;
void PageVisibilityChanged() override {}
void SizeChanged() override;
bool isContextLost() const override { return false; }
bool IsComposited() const final { return true; }
bool IsPaintable() const final { return true; }
void Stop() final;
cc::Layer* CcLayer() const final;
void Reshape(int width, int height) override;
void Dispose() override;
// OffscreenCanvas-specific methods
bool PushFrame() final;
// Returns a StaticBitmapImage backed by a texture containing the current
// contents of the front buffer. This is done without any pixel copies. The
// texture in the ImageBitmap is from the active ContextProvider on the
// WebGPUSwapBufferProvider.
ImageBitmap* TransferToImageBitmap(ScriptState*, ExceptionState&) final;
bool IsOffscreenCanvas() const {
if (Host())
return Host()->IsOffscreenCanvas();
return false;
}
// gpu_canvas_context.idl {{{
V8UnionHTMLCanvasElementOrOffscreenCanvas* getHTMLOrOffscreenCanvas() const;
void configure(const GPUCanvasConfiguration* descriptor, ExceptionState&);
void unconfigure();
GPUCanvasConfiguration* getConfiguration();
GPUTexture* getCurrentTexture(ScriptState*, ExceptionState&);
// }}} End of WebIDL binding implementation.
// WebGPUSwapBufferProvider::Client implementation
void OnTextureTransferred() override;
void InitializeLayer(cc::Layer* layer) override;
void SetNeedsCompositingUpdate() override;
bool IsGPUDeviceDestroyed() override;
private:
CanvasResourceProviderSharedImage* GetOrCreateCanvasResourceProvider();
CanvasResourceProviderSharedImage* PaintRenderingResultsToCanvas(
SourceDrawingBuffer);
scoped_refptr<WebGPUMailboxTexture> GetFrontBufferMailboxTexture();
void DetachSwapBuffers();
void ReplaceDrawingBuffer(bool destroy_swap_buffers);
void InitializeAlphaModePipeline(wgpu::TextureFormat format);
void FinalizeFrame(FlushReason) override;
scoped_refptr<StaticBitmapImage> SnapshotInternal(
const wgpu::Texture& texture) const;
bool CopyTextureToResourceProvider(
const wgpu::Texture& texture,
CanvasResourceProviderSharedImage* resource_provider) const;
void CopyToSwapTexture();
base::WeakPtr<WebGraphicsContext3DProviderWrapper> GetContextProviderWeakPtr()
const;
scoped_refptr<StaticBitmapImage> MakeFallbackStaticBitmapImage(
V8GPUCanvasAlphaMode::Enum alpha_mode);
Member<GPUDevice> device_;
std::unique_ptr<CanvasResourceProviderSharedImage> resource_provider_;
// `did_fail_to_create_resource_provider_` prevents repeated attempts in
// allocating resources after the first attempt failed.
bool did_fail_to_create_resource_provider_ = false;
// If the system doesn't support the requested format but it's one that WebGPU
// is required to offer, a texture_ will be allocated separately with the
// desired format and the will be copied to swap_texture_, allocated by the
// swap buffer provider with the system-supported format, when we're ready to
// present. Otherwise texture_ and swap_texture_ will point to the same
// texture, allocated by the swap buffer provider.
Member<GPUTexture> texture_;
Member<GPUTexture> swap_texture_;
PredefinedColorSpace color_space_ = PredefinedColorSpace::kSRGB;
V8GPUCanvasAlphaMode::Enum alpha_mode_;
V8CanvasToneMappingMode::Enum tone_mapping_mode_;
scoped_refptr<WebGPUTextureAlphaClearer> alpha_clearer_;
scoped_refptr<WebGPUSwapBufferProvider> swap_buffers_;
bool new_texture_required_ = true;
bool copy_to_swap_texture_required_ = false;
bool suppress_preferred_format_warning_ = false;
bool stopped_ = false;
// Matches [[configuration]] != null in the WebGPU specification.
bool configured_ = false;
// Matches [[texture_descriptor]] in the WebGPU specification except that it
// never becomes null.
wgpu::TextureDescriptor texture_descriptor_;
// The texture descriptor for the swap_texture is tracked separately, since
// it may have different usage in the case that a copy is required.
wgpu::TextureDescriptor swap_texture_descriptor_;
wgpu::DawnTextureInternalUsageDescriptor texture_internal_usage_;
base::HeapArray<wgpu::TextureFormat> view_formats_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_CANVAS_CONTEXT_H_