mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			147 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2014 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 "cef/libcef/browser/osr/software_output_device_proxy.h"
 | |
| 
 | |
| #include "base/memory/shared_memory_mapping.h"
 | |
| #include "base/trace_event/trace_event.h"
 | |
| #include "components/viz/common/resources/resource_sizes.h"
 | |
| #include "mojo/public/cpp/system/platform_handle.h"
 | |
| #include "skia/ext/platform_canvas.h"
 | |
| #include "third_party/skia/include/core/SkCanvas.h"
 | |
| #include "ui/gfx/skia_util.h"
 | |
| 
 | |
| #if defined(OS_WIN)
 | |
| #include <windows.h>
 | |
| #include "skia/ext/skia_utils_win.h"
 | |
| #include "ui/gfx/gdi_util.h"
 | |
| #include "ui/gfx/win/hwnd_util.h"
 | |
| #endif
 | |
| 
 | |
| namespace viz {
 | |
| 
 | |
| SoftwareOutputDeviceProxy::~SoftwareOutputDeviceProxy() = default;
 | |
| 
 | |
| SoftwareOutputDeviceProxy::SoftwareOutputDeviceProxy(
 | |
|     mojom::LayeredWindowUpdaterPtr layered_window_updater)
 | |
|     : layered_window_updater_(std::move(layered_window_updater)) {
 | |
|   DCHECK(layered_window_updater_.is_bound());
 | |
| }
 | |
| 
 | |
| void SoftwareOutputDeviceProxy::OnSwapBuffers(
 | |
|     SwapBuffersCallback swap_ack_callback) {
 | |
|   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 | |
|   DCHECK(swap_ack_callback_.is_null());
 | |
| 
 | |
|   // We aren't waiting on DrawAck() and can immediately run the callback.
 | |
|   if (!waiting_on_draw_ack_) {
 | |
|     task_runner_->PostTask(
 | |
|         FROM_HERE,
 | |
|         base::BindOnce(std::move(swap_ack_callback), viewport_pixel_size_));
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   swap_ack_callback_ =
 | |
|       base::BindOnce(std::move(swap_ack_callback), viewport_pixel_size_);
 | |
| }
 | |
| 
 | |
| void SoftwareOutputDeviceProxy::Resize(const gfx::Size& viewport_pixel_size,
 | |
|                                        float scale_factor) {
 | |
|   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 | |
|   DCHECK(!in_paint_);
 | |
| 
 | |
|   if (viewport_pixel_size_ == viewport_pixel_size)
 | |
|     return;
 | |
| 
 | |
|   viewport_pixel_size_ = viewport_pixel_size;
 | |
| 
 | |
|   canvas_.reset();
 | |
| 
 | |
|   size_t required_bytes;
 | |
|   if (!ResourceSizes::MaybeSizeInBytes(
 | |
|           viewport_pixel_size_, ResourceFormat::RGBA_8888, &required_bytes)) {
 | |
|     DLOG(ERROR) << "Invalid viewport size " << viewport_pixel_size_.ToString();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   base::UnsafeSharedMemoryRegion region =
 | |
|       base::UnsafeSharedMemoryRegion::Create(required_bytes);
 | |
|   if (!region.IsValid()) {
 | |
|     DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes";
 | |
|     return;
 | |
|   }
 | |
| 
 | |
| #if !defined(OS_WIN)
 | |
|   auto shm = base::ReadOnlySharedMemoryRegion::Create(required_bytes);
 | |
|   if (!shm.IsValid()) {
 | |
|     DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes";
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   shm_ = region.Map();
 | |
|   if (!shm_.IsValid()) {
 | |
|     DLOG(ERROR) << "Failed to map " << required_bytes << " bytes";
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   canvas_ = skia::CreatePlatformCanvasWithPixels(
 | |
|       viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
 | |
|       static_cast<uint8_t*>(shm_.memory()), skia::CRASH_ON_FAILURE);
 | |
| #else
 | |
|   canvas_ = skia::CreatePlatformCanvasWithSharedSection(
 | |
|       viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
 | |
|       region.GetPlatformHandle(), skia::CRASH_ON_FAILURE);
 | |
| #endif
 | |
| 
 | |
|   // Transfer region ownership to the browser process.
 | |
|   layered_window_updater_->OnAllocatedSharedMemory(viewport_pixel_size_,
 | |
|                                                    std::move(region));
 | |
| }
 | |
| 
 | |
| SkCanvas* SoftwareOutputDeviceProxy::BeginPaint(const gfx::Rect& damage_rect) {
 | |
|   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 | |
|   DCHECK(!in_paint_);
 | |
| 
 | |
|   damage_rect_ = damage_rect;
 | |
|   in_paint_ = true;
 | |
| 
 | |
|   return canvas_.get();
 | |
| }
 | |
| 
 | |
| void SoftwareOutputDeviceProxy::EndPaint() {
 | |
|   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 | |
|   DCHECK(in_paint_);
 | |
|   DCHECK(!waiting_on_draw_ack_);
 | |
| 
 | |
|   in_paint_ = false;
 | |
| 
 | |
|   gfx::Rect intersected_damage_rect = damage_rect_;
 | |
|   intersected_damage_rect.Intersect(gfx::Rect(viewport_pixel_size_));
 | |
|   if (intersected_damage_rect.IsEmpty())
 | |
|     return;
 | |
| 
 | |
|   if (!canvas_)
 | |
|     return;
 | |
| 
 | |
|   layered_window_updater_->Draw(
 | |
|       damage_rect_, base::BindOnce(&SoftwareOutputDeviceProxy::DrawAck,
 | |
|                                    base::Unretained(this)));
 | |
|   waiting_on_draw_ack_ = true;
 | |
| 
 | |
|   TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceProxy::Draw", this);
 | |
| }
 | |
| 
 | |
| void SoftwareOutputDeviceProxy::DrawAck() {
 | |
|   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 | |
|   DCHECK(waiting_on_draw_ack_);
 | |
|   DCHECK(!swap_ack_callback_.is_null());
 | |
| 
 | |
|   TRACE_EVENT_ASYNC_END0("viz", "SoftwareOutputDeviceProxy::Draw", this);
 | |
| 
 | |
|   waiting_on_draw_ack_ = false;
 | |
|   std::move(swap_ack_callback_).Run();
 | |
| }
 | |
| 
 | |
| }  // namespace viz
 |