mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Adds support for the OnAcceleratedPaint callback. Verified to work on macOS and Windows. Linux support is present but not implemented for cefclient, so it is not verified to work. To test: Run `cefclient --off-screen-rendering-enabled --shared-texture-enabled`
This commit is contained in:
committed by
Marshall Greenblatt
parent
dca0435d2f
commit
260dd0ca24
@@ -58,10 +58,10 @@ std::unique_ptr<CefBrowserPlatformDelegateOsr> CreateOSRDelegate(
|
||||
std::move(native_delegate), use_shared_texture, use_external_begin_frame);
|
||||
#elif BUILDFLAG(IS_MAC)
|
||||
return std::make_unique<CefBrowserPlatformDelegateOsrMac>(
|
||||
std::move(native_delegate));
|
||||
std::move(native_delegate), use_shared_texture, use_external_begin_frame);
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
return std::make_unique<CefBrowserPlatformDelegateOsrLinux>(
|
||||
std::move(native_delegate), use_external_begin_frame);
|
||||
std::move(native_delegate), use_shared_texture, use_external_begin_frame);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -8,9 +8,10 @@
|
||||
|
||||
CefBrowserPlatformDelegateOsrLinux::CefBrowserPlatformDelegateOsrLinux(
|
||||
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
|
||||
bool use_shared_texture,
|
||||
bool use_external_begin_frame)
|
||||
: CefBrowserPlatformDelegateOsr(std::move(native_delegate),
|
||||
/*use_shared_texture=*/false,
|
||||
use_shared_texture,
|
||||
use_external_begin_frame) {}
|
||||
|
||||
CefWindowHandle CefBrowserPlatformDelegateOsrLinux::GetHostWindowHandle()
|
||||
|
@@ -13,6 +13,7 @@ class CefBrowserPlatformDelegateOsrLinux
|
||||
public:
|
||||
CefBrowserPlatformDelegateOsrLinux(
|
||||
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
|
||||
bool use_shared_texture,
|
||||
bool use_external_begin_frame);
|
||||
|
||||
// CefBrowserPlatformDelegate methods:
|
||||
|
@@ -11,7 +11,9 @@
|
||||
class CefBrowserPlatformDelegateOsrMac : public CefBrowserPlatformDelegateOsr {
|
||||
public:
|
||||
explicit CefBrowserPlatformDelegateOsrMac(
|
||||
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate);
|
||||
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
|
||||
bool use_shared_texture,
|
||||
bool use_external_begin_frame);
|
||||
|
||||
// CefBrowserPlatformDelegate methods:
|
||||
CefWindowHandle GetHostWindowHandle() const override;
|
||||
|
@@ -7,10 +7,12 @@
|
||||
#include <utility>
|
||||
|
||||
CefBrowserPlatformDelegateOsrMac::CefBrowserPlatformDelegateOsrMac(
|
||||
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate)
|
||||
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
|
||||
bool use_shared_texture,
|
||||
bool use_external_begin_frame)
|
||||
: CefBrowserPlatformDelegateOsr(std::move(native_delegate),
|
||||
/*use_shared_texture=*/false,
|
||||
/*use_external_begin_frame=*/false) {}
|
||||
use_shared_texture,
|
||||
use_external_begin_frame) {}
|
||||
|
||||
CefWindowHandle CefBrowserPlatformDelegateOsrMac::GetHostWindowHandle() const {
|
||||
return native_delegate_->window_info().parent_view;
|
||||
|
@@ -202,6 +202,7 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||
CefRenderWidgetHostViewOSR* parent_host_view)
|
||||
: content::RenderWidgetHostViewBase(widget),
|
||||
background_color_(background_color),
|
||||
use_shared_texture_(use_shared_texture),
|
||||
render_widget_host_(content::RenderWidgetHostImpl::From(widget)),
|
||||
has_parent_(parent_host_view != nullptr),
|
||||
parent_host_view_(parent_host_view),
|
||||
@@ -400,7 +401,8 @@ void CefRenderWidgetHostViewOSR::ShowWithVisibility(
|
||||
if (!content::GpuDataManagerImpl::GetInstance()->IsGpuCompositingDisabled()) {
|
||||
// Start generating frames when we're visible and at the correct size.
|
||||
if (!video_consumer_) {
|
||||
video_consumer_ = std::make_unique<CefVideoConsumerOSR>(this);
|
||||
video_consumer_ =
|
||||
std::make_unique<CefVideoConsumerOSR>(this, use_shared_texture_);
|
||||
UpdateFrameRate();
|
||||
} else {
|
||||
video_consumer_->SetActive(true);
|
||||
@@ -1565,7 +1567,7 @@ void CefRenderWidgetHostViewOSR::OnPaint(const gfx::Rect& damage_rect,
|
||||
const void* pixels) {
|
||||
TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::OnPaint");
|
||||
|
||||
// Workaround for https://github.com/chromiumembedded/cef/issues/2817
|
||||
// Workaround for issue #2817.
|
||||
if (!is_showing_) {
|
||||
return;
|
||||
}
|
||||
@@ -1599,6 +1601,43 @@ void CefRenderWidgetHostViewOSR::OnPaint(const gfx::Rect& damage_rect,
|
||||
}
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::OnAcceleratedPaint(
|
||||
const gfx::Rect& damage_rect,
|
||||
const gfx::Size& pixel_size,
|
||||
const CefAcceleratedPaintInfo& info) {
|
||||
TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::OnAcceleratedPaint");
|
||||
|
||||
// Workaround for https://github.com/chromiumembedded/cef/issues/2817
|
||||
if (!is_showing_) {
|
||||
return;
|
||||
}
|
||||
|
||||
CefRefPtr<CefRenderHandler> handler =
|
||||
browser_impl_->client()->GetRenderHandler();
|
||||
CHECK(handler);
|
||||
|
||||
gfx::Rect rect_in_pixels(0, 0, pixel_size.width(), pixel_size.height());
|
||||
rect_in_pixels.Intersect(damage_rect);
|
||||
|
||||
CefRenderHandler::RectList rcList;
|
||||
rcList.emplace_back(rect_in_pixels.x(), rect_in_pixels.y(),
|
||||
rect_in_pixels.width(), rect_in_pixels.height());
|
||||
|
||||
handler->OnAcceleratedPaint(browser_impl_.get(),
|
||||
IsPopupWidget() ? PET_POPUP : PET_VIEW, rcList,
|
||||
info);
|
||||
|
||||
// Release the resize hold when we reach the desired size.
|
||||
if (hold_resize_) {
|
||||
DCHECK_GT(cached_scale_factor_, 0);
|
||||
gfx::Size expected_size =
|
||||
gfx::ScaleToCeiledSize(GetViewBounds().size(), cached_scale_factor_);
|
||||
if (pixel_size == expected_size) {
|
||||
ReleaseResizeHold();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui::Layer* CefRenderWidgetHostViewOSR::GetRootLayer() const {
|
||||
return root_layer_.get();
|
||||
}
|
||||
|
@@ -254,6 +254,9 @@ class CefRenderWidgetHostViewOSR
|
||||
void OnPaint(const gfx::Rect& damage_rect,
|
||||
const gfx::Size& pixel_size,
|
||||
const void* pixels);
|
||||
void OnAcceleratedPaint(const gfx::Rect& damage_rect,
|
||||
const gfx::Size& pixel_size,
|
||||
const CefAcceleratedPaintInfo& info);
|
||||
|
||||
void OnBeginFame(base::TimeTicks frame_time);
|
||||
|
||||
@@ -401,6 +404,7 @@ class CefRenderWidgetHostViewOSR
|
||||
uint64_t begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
|
||||
bool begin_frame_pending_ = false;
|
||||
|
||||
bool use_shared_texture_ = false;
|
||||
bool sync_frame_rate_ = false;
|
||||
bool external_begin_frame_enabled_ = false;
|
||||
bool needs_external_begin_frames_ = false;
|
||||
|
@@ -11,6 +11,12 @@
|
||||
#include "media/capture/mojom/video_capture_types.mojom.h"
|
||||
#include "ui/gfx/skbitmap_operations.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "ipc/service/gpu_memory_buffer_factory_dxgi.h"
|
||||
#elif BUILDFLAG(IS_APPLE)
|
||||
#include "ipc/service/gpu_memory_buffer_factory_io_surface.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper to always call Done() at the end of OnFrameCaptured().
|
||||
@@ -28,8 +34,11 @@ class ScopedVideoFrameDone {
|
||||
|
||||
} // namespace
|
||||
|
||||
CefVideoConsumerOSR::CefVideoConsumerOSR(CefRenderWidgetHostViewOSR* view)
|
||||
: view_(view), video_capturer_(view->CreateVideoCapturer()) {
|
||||
CefVideoConsumerOSR::CefVideoConsumerOSR(CefRenderWidgetHostViewOSR* view,
|
||||
bool use_shared_texture)
|
||||
: use_shared_texture_(use_shared_texture),
|
||||
view_(view),
|
||||
video_capturer_(view->CreateVideoCapturer()) {
|
||||
video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB);
|
||||
|
||||
// Always use the highest resolution within constraints that doesn't exceed
|
||||
@@ -45,7 +54,10 @@ CefVideoConsumerOSR::~CefVideoConsumerOSR() = default;
|
||||
|
||||
void CefVideoConsumerOSR::SetActive(bool active) {
|
||||
if (active) {
|
||||
video_capturer_->Start(this, viz::mojom::BufferFormatPreference::kDefault);
|
||||
video_capturer_->Start(
|
||||
this, use_shared_texture_
|
||||
? viz::mojom::BufferFormatPreference::kPreferGpuMemoryBuffer
|
||||
: viz::mojom::BufferFormatPreference::kDefault);
|
||||
} else {
|
||||
video_capturer_->Stop();
|
||||
}
|
||||
@@ -88,6 +100,55 @@ void CefVideoConsumerOSR::OnFrameCaptured(
|
||||
callbacks) {
|
||||
ScopedVideoFrameDone scoped_done(std::move(callbacks));
|
||||
|
||||
// If it is GPU Texture OSR.
|
||||
if (use_shared_texture_) {
|
||||
CHECK(data->is_gpu_memory_buffer_handle() &&
|
||||
(info->pixel_format == media::PIXEL_FORMAT_ARGB ||
|
||||
info->pixel_format == media::PIXEL_FORMAT_ABGR));
|
||||
|
||||
// The info->pixel_format will tell if the texture is RGBA or BGRA
|
||||
// On Linux, X11 lacks support for RGBA_8888 so it might be BGRA.
|
||||
// On Windows and macOS, it should always be RGBA.
|
||||
auto pixel_format = info->pixel_format == media::PIXEL_FORMAT_ABGR
|
||||
? CEF_COLOR_TYPE_RGBA_8888
|
||||
: CEF_COLOR_TYPE_BGRA_8888;
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
auto& gmb_handle = data->get_gpu_memory_buffer_handle();
|
||||
cef_accelerated_paint_info_t paint_info;
|
||||
paint_info.shared_texture_handle = gmb_handle.dxgi_handle.Get();
|
||||
paint_info.format = pixel_format;
|
||||
view_->OnAcceleratedPaint(content_rect, info->coded_size, paint_info);
|
||||
#elif BUILDFLAG(IS_APPLE)
|
||||
auto& gmb_handle = data->get_gpu_memory_buffer_handle();
|
||||
cef_accelerated_paint_info_t paint_info;
|
||||
paint_info.shared_texture_io_surface = gmb_handle.io_surface.get();
|
||||
paint_info.format = pixel_format;
|
||||
view_->OnAcceleratedPaint(content_rect, info->coded_size, paint_info);
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
auto& gmb_handle = data->get_gpu_memory_buffer_handle();
|
||||
auto& native_pixmap = gmb_handle.native_pixmap_handle;
|
||||
CHECK(native_pixmap.planes.size() <= kAcceleratedPaintMaxPlanes);
|
||||
|
||||
cef_accelerated_paint_info_t paint_info;
|
||||
paint_info.plane_count = native_pixmap.planes.size();
|
||||
paint_info.modifier = native_pixmap.modifier;
|
||||
paint_info.format = pixel_format;
|
||||
|
||||
auto cef_plain_index = 0;
|
||||
for (const auto& plane : native_pixmap.planes) {
|
||||
cef_accelerated_paint_native_pixmap_plane_t cef_plane;
|
||||
cef_plane.stride = plane.stride;
|
||||
cef_plane.offset = plane.offset;
|
||||
cef_plane.size = plane.size;
|
||||
cef_plane.fd = plane.fd.get();
|
||||
paint_info.planes[cef_plain_index++] = cef_plane;
|
||||
}
|
||||
view_->OnAcceleratedPaint(content_rect, info->coded_size, paint_info);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->pixel_format != media::PIXEL_FORMAT_ARGB) {
|
||||
DLOG(ERROR) << "Unsupported pixel format " << info->pixel_format;
|
||||
return;
|
||||
|
@@ -11,7 +11,8 @@ class CefRenderWidgetHostViewOSR;
|
||||
|
||||
class CefVideoConsumerOSR : public viz::mojom::FrameSinkVideoConsumer {
|
||||
public:
|
||||
explicit CefVideoConsumerOSR(CefRenderWidgetHostViewOSR* view);
|
||||
CefVideoConsumerOSR(CefRenderWidgetHostViewOSR* view,
|
||||
bool use_shared_texture);
|
||||
|
||||
CefVideoConsumerOSR(const CefVideoConsumerOSR&) = delete;
|
||||
CefVideoConsumerOSR& operator=(const CefVideoConsumerOSR&) = delete;
|
||||
@@ -37,6 +38,8 @@ class CefVideoConsumerOSR : public viz::mojom::FrameSinkVideoConsumer {
|
||||
void OnNewSubCaptureTargetVersion(
|
||||
uint32_t sub_capture_target_version) override {}
|
||||
|
||||
const bool use_shared_texture_;
|
||||
|
||||
CefRenderWidgetHostViewOSR* const view_;
|
||||
std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer_;
|
||||
|
||||
|
Reference in New Issue
Block a user