1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/viz/service/display_embedder/skia_output_device_dawn.h"
6
7 #include "base/logging.h"
8 #include "build/build_config.h"
9 #include "components/viz/common/gpu/dawn_context_provider.h"
10
11 #if defined(OS_WIN)
12 #include <dawn_native/D3D12Backend.h>
13 #elif defined(OS_LINUX)
14 #include <dawn_native/VulkanBackend.h>
15 #endif
16
17 namespace viz {
18
19 namespace {
20
21 // Some Vulkan drivers do not support kRGB_888x_SkColorType. Always use
22 // kRGBA_8888_SkColorType instead and initialize surface to opaque as necessary.
23 constexpr SkColorType kSurfaceColorType = kRGBA_8888_SkColorType;
24 constexpr wgpu::TextureFormat kSwapChainFormat =
25 wgpu::TextureFormat::RGBA8Unorm;
26
27 constexpr wgpu::TextureUsage kUsage =
28 wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::CopySrc;
29
30 } // namespace
31
SkiaOutputDeviceDawn(DawnContextProvider * context_provider,gfx::AcceleratedWidget widget,gfx::SurfaceOrigin origin,gpu::MemoryTracker * memory_tracker,DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)32 SkiaOutputDeviceDawn::SkiaOutputDeviceDawn(
33 DawnContextProvider* context_provider,
34 gfx::AcceleratedWidget widget,
35 gfx::SurfaceOrigin origin,
36 gpu::MemoryTracker* memory_tracker,
37 DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
38 : SkiaOutputDevice(memory_tracker, did_swap_buffer_complete_callback),
39 context_provider_(context_provider),
40 widget_(widget) {
41 capabilities_.output_surface_origin = origin;
42 capabilities_.uses_default_gl_framebuffer = false;
43 capabilities_.supports_post_sub_buffer = false;
44
45 capabilities_.sk_color_type = kSurfaceColorType;
46 capabilities_.gr_backend_format =
47 context_provider_->GetGrContext()->defaultBackendFormat(
48 kSurfaceColorType, GrRenderable::kYes);
49 }
50
51 SkiaOutputDeviceDawn::~SkiaOutputDeviceDawn() = default;
52
Reshape(const gfx::Size & size,float device_scale_factor,const gfx::ColorSpace & color_space,gfx::BufferFormat format,gfx::OverlayTransform transform)53 bool SkiaOutputDeviceDawn::Reshape(const gfx::Size& size,
54 float device_scale_factor,
55 const gfx::ColorSpace& color_space,
56 gfx::BufferFormat format,
57 gfx::OverlayTransform transform) {
58 DCHECK_EQ(transform, gfx::OVERLAY_TRANSFORM_NONE);
59
60 size_ = size;
61 sk_color_space_ = color_space.ToSkColorSpace();
62
63 CreateSwapChainImplementation();
64 wgpu::SwapChainDescriptor desc;
65 desc.implementation = reinterpret_cast<int64_t>(&swap_chain_implementation_);
66 // TODO(sgilhuly): Use a wgpu::Surface in this call once the Surface-based
67 // SwapChain API is ready.
68 swap_chain_ = context_provider_->GetDevice().CreateSwapChain(nullptr, &desc);
69 if (!swap_chain_)
70 return false;
71 swap_chain_.Configure(kSwapChainFormat, kUsage, size_.width(),
72 size_.height());
73 return true;
74 }
75
SwapBuffers(BufferPresentedCallback feedback,std::vector<ui::LatencyInfo> latency_info)76 void SkiaOutputDeviceDawn::SwapBuffers(
77 BufferPresentedCallback feedback,
78 std::vector<ui::LatencyInfo> latency_info) {
79 StartSwapBuffers(std::move(feedback));
80 swap_chain_.Present();
81 FinishSwapBuffers(gfx::SwapResult::SWAP_ACK,
82 gfx::Size(size_.width(), size_.height()),
83 std::move(latency_info));
84 }
85
BeginPaint(std::vector<GrBackendSemaphore> * end_semaphores)86 SkSurface* SkiaOutputDeviceDawn::BeginPaint(
87 std::vector<GrBackendSemaphore>* end_semaphores) {
88 GrDawnRenderTargetInfo info;
89 info.fTextureView = swap_chain_.GetCurrentTextureView();
90 info.fFormat = kSwapChainFormat;
91 info.fLevelCount = 1;
92 GrBackendRenderTarget backend_target(
93 size_.width(), size_.height(), /*sampleCnt=*/0, /*stencilBits=*/0, info);
94 DCHECK(backend_target.isValid());
95 // LegacyFontHost will get LCD text and skia figures out what type to use.
96 SkSurfaceProps surface_props(/*flags=*/0,
97 SkSurfaceProps::kLegacyFontHost_InitType);
98 sk_surface_ = SkSurface::MakeFromBackendRenderTarget(
99 context_provider_->GetGrContext(), backend_target,
100 capabilities_.output_surface_origin == gfx::SurfaceOrigin::kTopLeft
101 ? kTopLeft_GrSurfaceOrigin
102 : kBottomLeft_GrSurfaceOrigin,
103 kSurfaceColorType, sk_color_space_, &surface_props);
104 return sk_surface_.get();
105 }
106
EndPaint()107 void SkiaOutputDeviceDawn::EndPaint() {
108 GrFlushInfo flush_info;
109 sk_surface_->flush(SkSurface::BackendSurfaceAccess::kPresent, flush_info);
110 sk_surface_.reset();
111 }
112
CreateSwapChainImplementation()113 void SkiaOutputDeviceDawn::CreateSwapChainImplementation() {
114 #if defined(OS_WIN)
115 swap_chain_implementation_ = dawn_native::d3d12::CreateNativeSwapChainImpl(
116 context_provider_->GetDevice().Get(), widget_);
117 #else
118 NOTREACHED();
119 ALLOW_UNUSED_LOCAL(widget_);
120 #endif
121 }
122
123 } // namespace viz
124