// Copyright 2019 The Chromium Embedded Framework 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 "libcef/browser/osr/host_display_client_osr.h" #include #include "libcef/browser/browser_host_impl.h" #include "libcef/browser/osr/render_widget_host_view_osr.h" #include "base/memory/shared_memory.h" #include "components/viz/common/resources/resource_format.h" #include "components/viz/common/resources/resource_sizes.h" #include "mojo/public/cpp/system/platform_handle.h" #include "services/viz/privileged/interfaces/compositing/layered_window_updater.mojom.h" #include "skia/ext/platform_canvas.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/src/core/SkDevice.h" #include "ui/gfx/skia_util.h" #if defined(OS_WIN) #include "skia/ext/skia_utils_win.h" #endif class CefLayeredWindowUpdaterOSR : public viz::mojom::LayeredWindowUpdater { public: CefLayeredWindowUpdaterOSR(CefRenderWidgetHostViewOSR* const view, viz::mojom::LayeredWindowUpdaterRequest request); ~CefLayeredWindowUpdaterOSR() override; void SetActive(bool active); const void* GetPixelMemory() const; gfx::Size GetPixelSize() const; // viz::mojom::LayeredWindowUpdater implementation. void OnAllocatedSharedMemory( const gfx::Size& pixel_size, mojo::ScopedSharedBufferHandle scoped_buffer_handle) override; void Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) override; private: CefRenderWidgetHostViewOSR* const view_; mojo::Binding binding_; bool active_ = false; base::ReadOnlySharedMemoryMapping shared_memory_; gfx::Size pixel_size_; DISALLOW_COPY_AND_ASSIGN(CefLayeredWindowUpdaterOSR); }; CefLayeredWindowUpdaterOSR::CefLayeredWindowUpdaterOSR( CefRenderWidgetHostViewOSR* const view, viz::mojom::LayeredWindowUpdaterRequest request) : view_(view), binding_(this, std::move(request)) {} CefLayeredWindowUpdaterOSR::~CefLayeredWindowUpdaterOSR() = default; void CefLayeredWindowUpdaterOSR::SetActive(bool active) { active_ = active; } const void* CefLayeredWindowUpdaterOSR::GetPixelMemory() const { return shared_memory_.memory(); } gfx::Size CefLayeredWindowUpdaterOSR::GetPixelSize() const { return pixel_size_; } void CefLayeredWindowUpdaterOSR::OnAllocatedSharedMemory( const gfx::Size& pixel_size, mojo::ScopedSharedBufferHandle scoped_buffer_handle) { // Make sure |pixel_size| is sane. size_t expected_bytes; bool size_result = viz::ResourceSizes::MaybeSizeInBytes( pixel_size, viz::ResourceFormat::RGBA_8888, &expected_bytes); if (!size_result) return; #if !defined(OS_WIN) base::ReadOnlySharedMemoryRegion shm = mojo::UnwrapReadOnlySharedMemoryRegion(std::move(scoped_buffer_handle)); if (!shm.IsValid()) { LOG(ERROR) << "Shared memory region is invalid"; return; } #else // !defined(OS_WIN) base::SharedMemoryHandle shm_handle; MojoResult unwrap_result = mojo::UnwrapSharedMemoryHandle( std::move(scoped_buffer_handle), &shm_handle, nullptr, nullptr); if (unwrap_result != MOJO_RESULT_OK) return; base::ReadOnlySharedMemoryRegion shm = base::ReadOnlySharedMemoryRegion::Deserialize( base::subtle::PlatformSharedMemoryRegion::TakeFromSharedMemoryHandle( shm_handle, base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly)); #endif // !defined(OS_WIN) pixel_size_ = pixel_size; shared_memory_ = shm.Map(); DCHECK(shared_memory_.IsValid()); } void CefLayeredWindowUpdaterOSR::Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) { if (active_) { const void* memory = GetPixelMemory(); if (memory) { view_->OnPaint(damage_rect, pixel_size_, memory); } else { LOG(WARNING) << "Failed to read pixels"; } } std::move(draw_callback).Run(); } CefHostDisplayClientOSR::CefHostDisplayClientOSR( CefRenderWidgetHostViewOSR* const view, gfx::AcceleratedWidget widget) : viz::HostDisplayClient(widget), view_(view) {} CefHostDisplayClientOSR::~CefHostDisplayClientOSR() {} void CefHostDisplayClientOSR::SetActive(bool active) { active_ = active; if (layered_window_updater_) { layered_window_updater_->SetActive(active_); } } const void* CefHostDisplayClientOSR::GetPixelMemory() const { return layered_window_updater_ ? layered_window_updater_->GetPixelMemory() : nullptr; } gfx::Size CefHostDisplayClientOSR::GetPixelSize() const { return layered_window_updater_ ? layered_window_updater_->GetPixelSize() : gfx::Size{}; } void CefHostDisplayClientOSR::UseProxyOutputDevice( UseProxyOutputDeviceCallback callback) { std::move(callback).Run(true); } void CefHostDisplayClientOSR::CreateLayeredWindowUpdater( viz::mojom::LayeredWindowUpdaterRequest request) { layered_window_updater_ = std::make_unique(view_, std::move(request)); layered_window_updater_->SetActive(active_); }