diff --git a/BUILD.gn b/BUILD.gn index 9008c47b9..1a4fe8cc4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1986,6 +1986,7 @@ if (is_mac) { ] frameworks = [ "AppKit.framework", + "IOSurface.framework", "OpenGL.framework", ] defines = [ diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 8a93f4ea9..7890d98eb 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -54,6 +54,7 @@ 'include/internal/cef_time.h', 'include/internal/cef_trace_event_internal.h', 'include/internal/cef_types.h', + 'include/internal/cef_types_color.h', 'include/internal/cef_types_content_settings.h', 'include/internal/cef_types_geometry.h', ], diff --git a/cmake/cef_variables.cmake.in b/cmake/cef_variables.cmake.in index 9f10f1d9f..9c8d55e3e 100644 --- a/cmake/cef_variables.cmake.in +++ b/cmake/cef_variables.cmake.in @@ -304,8 +304,9 @@ if(OS_MAC) # Standard libraries. set(CEF_STANDARD_LIBS -lpthread - "-framework Cocoa" "-framework AppKit" + "-framework Cocoa" + "-framework IOSurface" ) # Find the newest available base SDK. diff --git a/include/capi/cef_render_handler_capi.h b/include/capi/cef_render_handler_capi.h index c61915a48..682e4bed5 100644 --- a/include/capi/cef_render_handler_capi.h +++ b/include/capi/cef_render_handler_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=5309b2f6da62526ed92c928c0918bc27898cf03b$ +// $hash=5151b6ea3c06e46a75f2cd7679044a2891063d29$ // #ifndef CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_ @@ -149,17 +149,27 @@ typedef struct _cef_render_handler_t { /// Called when an element has been rendered to the shared texture handle. /// |type| indicates whether the element is the view or the popup widget. /// |dirtyRects| contains the set of rectangles in pixel coordinates that need - /// to be repainted. |shared_handle| is the handle for a D3D11 Texture2D that - /// can be accessed via ID3D11Device using the OpenSharedResource function. - /// This function is only called when cef_window_tInfo::shared_texture_enabled - /// is set to true (1), and is currently only supported on Windows. + /// to be repainted. |info| contains the shared handle; on Windows it is a + /// HANDLE to a texture that can be opened with D3D11 OpenSharedResource, on + /// macOS it is an IOSurface pointer that can be opened with Metal or OpenGL, + /// and on Linux it contains several planes, each with an fd to the underlying + /// system native buffer. /// - void(CEF_CALLBACK* on_accelerated_paint)(struct _cef_render_handler_t* self, - struct _cef_browser_t* browser, - cef_paint_element_type_t type, - size_t dirtyRectsCount, - cef_rect_t const* dirtyRects, - void* shared_handle); + /// The underlying implementation uses a pool to deliver frames. As a result, + /// the handle may differ every frame depending on how many frames are in- + /// progress. The handle's resource cannot be cached and cannot be accessed + /// outside of this callback. It should be reopened each time this callback is + /// executed and the contents should be copied to a texture owned by the + /// client application. The contents of |info| will be released back to the + /// pool after this callback returns. + /// + void(CEF_CALLBACK* on_accelerated_paint)( + struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, + cef_paint_element_type_t type, + size_t dirtyRectsCount, + cef_rect_t const* dirtyRects, + const cef_accelerated_paint_info_t* info); /// /// Called to retrieve the size of the touch handle for the specified diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index 1ff10a15b..e8f63306a 100644 --- a/include/cef_api_hash.h +++ b/include/cef_api_hash.h @@ -42,13 +42,13 @@ // way that may cause binary incompatibility with other builds. The universal // hash value will change if any platform is affected whereas the platform hash // values will change only if that particular platform is affected. -#define CEF_API_HASH_UNIVERSAL "de72aee0623e568ded52b7075c7fda576844e8b3" +#define CEF_API_HASH_UNIVERSAL "35035b76d79ba0c7144aedb63d72b7988d372706" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "46bb69fe7038d7e9f8d4ee86e4a0825bb2d289b7" +#define CEF_API_HASH_PLATFORM "9227cf2e0abf4f378e31e6095d503a91b2da59af" #elif defined(OS_MAC) -#define CEF_API_HASH_PLATFORM "e3ef47d5541f5260eba70030386d692138315900" +#define CEF_API_HASH_PLATFORM "fe0bdc49d209ee3cf108bdb72faec21316f9d0e0" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "579ef9c5282456c7de906cf055aed0ff4ba0a5a3" +#define CEF_API_HASH_PLATFORM "df471096e6600c025ac0655b5eaa9818f075b8ba" #endif #ifdef __cplusplus diff --git a/include/cef_render_handler.h b/include/cef_render_handler.h index b27403f9a..9ac414a3a 100644 --- a/include/cef_render_handler.h +++ b/include/cef_render_handler.h @@ -152,16 +152,25 @@ class CefRenderHandler : public virtual CefBaseRefCounted { /// Called when an element has been rendered to the shared texture handle. /// |type| indicates whether the element is the view or the popup widget. /// |dirtyRects| contains the set of rectangles in pixel coordinates that need - /// to be repainted. |shared_handle| is the handle for a D3D11 Texture2D that - /// can be accessed via ID3D11Device using the OpenSharedResource method. This - /// method is only called when CefWindowInfo::shared_texture_enabled is set to - /// true, and is currently only supported on Windows. + /// to be repainted. |info| contains the shared handle; on Windows it is a + /// HANDLE to a texture that can be opened with D3D11 OpenSharedResource, on + /// macOS it is an IOSurface pointer that can be opened with Metal or OpenGL, + /// and on Linux it contains several planes, each with an fd to the underlying + /// system native buffer. + /// + /// The underlying implementation uses a pool to deliver frames. As a result, + /// the handle may differ every frame depending on how many frames are + /// in-progress. The handle's resource cannot be cached and cannot be accessed + /// outside of this callback. It should be reopened each time this callback is + /// executed and the contents should be copied to a texture owned by the + /// client application. The contents of |info| will be released back to the + /// pool after this callback returns. /// /*--cef()--*/ virtual void OnAcceleratedPaint(CefRefPtr browser, PaintElementType type, const RectList& dirtyRects, - void* shared_handle) {} + const CefAcceleratedPaintInfo& info) {} /// /// Called to retrieve the size of the touch handle for the specified diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index 231626c9c..6f8ed6817 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -2925,21 +2925,6 @@ typedef enum { RESPONSE_FILTER_ERROR } cef_response_filter_status_t; -/// -/// Describes how to interpret the components of a pixel. -/// -typedef enum { - /// - /// RGBA with 8 bits per pixel (32bits total). - /// - CEF_COLOR_TYPE_RGBA_8888, - - /// - /// BGRA with 8 bits per pixel (32bits total). - /// - CEF_COLOR_TYPE_BGRA_8888, -} cef_color_type_t; - /// /// Describes how to interpret the alpha component of a pixel. /// diff --git a/include/internal/cef_types_color.h b/include/internal/cef_types_color.h new file mode 100644 index 000000000..e01b25aae --- /dev/null +++ b/include/internal/cef_types_color.h @@ -0,0 +1,57 @@ +// Copyright (c) 2024 Marshall A. Greenblatt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_COLOR_H_ +#define CEF_INCLUDE_INTERNAL_CEF_TYPES_COLOR_H_ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/// +/// Describes how to interpret the components of a pixel. +/// +typedef enum { + /// + /// RGBA with 8 bits per pixel (32bits total). + /// + CEF_COLOR_TYPE_RGBA_8888, + + /// + /// BGRA with 8 bits per pixel (32bits total). + /// + CEF_COLOR_TYPE_BGRA_8888, +} cef_color_type_t; + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_COLOR_H_ diff --git a/include/internal/cef_types_linux.h b/include/internal/cef_types_linux.h index 171cda32d..8749b99bb 100644 --- a/include/internal/cef_types_linux.h +++ b/include/internal/cef_types_linux.h @@ -43,6 +43,7 @@ typedef struct _XDisplay XDisplay; #include "include/internal/cef_export.h" #include "include/internal/cef_string.h" +#include "include/internal/cef_types_color.h" #include "include/internal/cef_types_geometry.h" // Handle types. @@ -137,6 +138,56 @@ typedef struct _cef_window_info_t { cef_window_handle_t window; } cef_window_info_t; +/// +/// Structure containing the plane information of the shared texture. +/// Sync with native_pixmap_handle.h +/// +typedef struct _cef_accelerated_paint_native_pixmap_plane_info_t { + /// + /// The strides and offsets in bytes to be used when accessing the buffers via + /// a memory mapping. One per plane per entry. Size in bytes of the plane is + /// necessary to map the buffers. + /// + uint32_t stride; + uint64_t offset; + uint64_t size; + + /// + /// File descriptor for the underlying memory object (usually dmabuf). + /// + int fd; +} cef_accelerated_paint_native_pixmap_plane_t; + +#define kAcceleratedPaintMaxPlanes 4 + +/// +/// Structure containing shared texture information for the OnAcceleratedPaint +/// callback. Resources will be released to the underlying pool for reuse when +/// the callback returns from client code. +/// +typedef struct _cef_accelerated_paint_info_t { + /// + /// Planes of the shared texture, usually file descriptors of dmabufs. + /// + cef_accelerated_paint_native_pixmap_plane_t + planes[kAcceleratedPaintMaxPlanes]; + + /// + /// Plane count. + /// + int plane_count; + + /// + /// Modifier could be used with EGL driver. + /// + uint64_t modifier; + + /// + /// The pixel format of the texture. + /// + cef_color_type_t format; +} cef_accelerated_paint_info_t; + #ifdef __cplusplus } #endif diff --git a/include/internal/cef_types_mac.h b/include/internal/cef_types_mac.h index 8ee619e65..0252ec0db 100644 --- a/include/internal/cef_types_mac.h +++ b/include/internal/cef_types_mac.h @@ -35,6 +35,7 @@ #if defined(OS_MAC) #include "include/internal/cef_string.h" +#include "include/internal/cef_types_color.h" #include "include/internal/cef_types_geometry.h" // Handle types. @@ -44,6 +45,8 @@ #define cef_event_handle_t void* // Actually NSView* #define cef_window_handle_t void* +// Actually IOSurface* +#define cef_shared_texture_handle_t void* #define kNullCursorHandle NULL #define kNullEventHandle NULL @@ -136,6 +139,23 @@ typedef struct _cef_window_info_t { cef_window_handle_t view; } cef_window_info_t; +/// +/// Structure containing shared texture information for the OnAcceleratedPaint +/// callback. Resources will be released to the underlying pool for reuse when +/// the callback returns from client code. +/// +typedef struct _cef_accelerated_paint_info_t { + /// + /// Handle for the shared texture IOSurface. + /// + cef_shared_texture_handle_t shared_texture_io_surface; + + /// + /// The pixel format of the texture. + /// + cef_color_type_t format; +} cef_accelerated_paint_info_t; + #ifdef __cplusplus } #endif diff --git a/include/internal/cef_types_win.h b/include/internal/cef_types_win.h index abf80c7d3..f1c509f60 100644 --- a/include/internal/cef_types_win.h +++ b/include/internal/cef_types_win.h @@ -37,12 +37,14 @@ #include #include "include/internal/cef_string.h" +#include "include/internal/cef_types_color.h" #include "include/internal/cef_types_geometry.h" // Handle types. #define cef_cursor_handle_t HCURSOR #define cef_event_handle_t MSG* #define cef_window_handle_t HWND +#define cef_shared_texture_handle_t HANDLE #define kNullCursorHandle NULL #define kNullEventHandle NULL @@ -104,6 +106,24 @@ typedef struct _cef_window_info_t { cef_window_handle_t window; } cef_window_info_t; +/// +/// Structure containing shared texture information for the OnAcceleratedPaint +/// callback. Resources will be released to the underlying pool for reuse when +/// the callback returns from client code. +/// +typedef struct _cef_accelerated_paint_info_t { + /// + /// Handle for the shared texture. The shared texture is instantiated + /// without a keyed mutex. + /// + cef_shared_texture_handle_t shared_texture_handle; + + /// + /// The pixel format of the texture. + /// + cef_color_type_t format; +} cef_accelerated_paint_info_t; + #ifdef __cplusplus } #endif diff --git a/include/internal/cef_types_wrappers.h b/include/internal/cef_types_wrappers.h index a7343bbba..56b838fa0 100644 --- a/include/internal/cef_types_wrappers.h +++ b/include/internal/cef_types_wrappers.h @@ -750,4 +750,14 @@ struct CefMediaSinkDeviceInfoTraits { /// using CefMediaSinkDeviceInfo = CefStructBase; +/// +/// Class representing accelerated paint info. +/// +class CefAcceleratedPaintInfo : public cef_accelerated_paint_info_t { + public: + CefAcceleratedPaintInfo() : cef_accelerated_paint_info_t{} {} + CefAcceleratedPaintInfo(const cef_accelerated_paint_info_t& r) + : cef_accelerated_paint_info_t(r) {} +}; + #endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_WRAPPERS_H_ diff --git a/libcef/browser/browser_platform_delegate_create.cc b/libcef/browser/browser_platform_delegate_create.cc index 5e09068ba..98a790046 100644 --- a/libcef/browser/browser_platform_delegate_create.cc +++ b/libcef/browser/browser_platform_delegate_create.cc @@ -59,10 +59,10 @@ std::unique_ptr CreateOSRDelegate( std::move(native_delegate), use_shared_texture, use_external_begin_frame); #elif BUILDFLAG(IS_MAC) return std::make_unique( - std::move(native_delegate)); + std::move(native_delegate), use_shared_texture, use_external_begin_frame); #elif BUILDFLAG(IS_LINUX) return std::make_unique( - std::move(native_delegate), use_external_begin_frame); + std::move(native_delegate), use_shared_texture, use_external_begin_frame); #endif } diff --git a/libcef/browser/osr/browser_platform_delegate_osr_linux.cc b/libcef/browser/osr/browser_platform_delegate_osr_linux.cc index 0834e6456..062984453 100644 --- a/libcef/browser/osr/browser_platform_delegate_osr_linux.cc +++ b/libcef/browser/osr/browser_platform_delegate_osr_linux.cc @@ -8,9 +8,10 @@ CefBrowserPlatformDelegateOsrLinux::CefBrowserPlatformDelegateOsrLinux( std::unique_ptr 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() diff --git a/libcef/browser/osr/browser_platform_delegate_osr_linux.h b/libcef/browser/osr/browser_platform_delegate_osr_linux.h index 071a2cdd4..93f03ba83 100644 --- a/libcef/browser/osr/browser_platform_delegate_osr_linux.h +++ b/libcef/browser/osr/browser_platform_delegate_osr_linux.h @@ -13,6 +13,7 @@ class CefBrowserPlatformDelegateOsrLinux public: CefBrowserPlatformDelegateOsrLinux( std::unique_ptr native_delegate, + bool use_shared_texture, bool use_external_begin_frame); // CefBrowserPlatformDelegate methods: diff --git a/libcef/browser/osr/browser_platform_delegate_osr_mac.h b/libcef/browser/osr/browser_platform_delegate_osr_mac.h index 923e3c40b..43ed36aa2 100644 --- a/libcef/browser/osr/browser_platform_delegate_osr_mac.h +++ b/libcef/browser/osr/browser_platform_delegate_osr_mac.h @@ -11,7 +11,9 @@ class CefBrowserPlatformDelegateOsrMac : public CefBrowserPlatformDelegateOsr { public: explicit CefBrowserPlatformDelegateOsrMac( - std::unique_ptr native_delegate); + std::unique_ptr native_delegate, + bool use_shared_texture, + bool use_external_begin_frame); // CefBrowserPlatformDelegate methods: CefWindowHandle GetHostWindowHandle() const override; diff --git a/libcef/browser/osr/browser_platform_delegate_osr_mac.mm b/libcef/browser/osr/browser_platform_delegate_osr_mac.mm index d67734ff2..aebb71d6f 100644 --- a/libcef/browser/osr/browser_platform_delegate_osr_mac.mm +++ b/libcef/browser/osr/browser_platform_delegate_osr_mac.mm @@ -7,10 +7,12 @@ #include CefBrowserPlatformDelegateOsrMac::CefBrowserPlatformDelegateOsrMac( - std::unique_ptr native_delegate) + std::unique_ptr 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; diff --git a/libcef/browser/osr/render_widget_host_view_osr.cc b/libcef/browser/osr/render_widget_host_view_osr.cc index 02aa6585c..24e5625a2 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.cc +++ b/libcef/browser/osr/render_widget_host_view_osr.cc @@ -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), @@ -397,7 +398,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(this); + video_consumer_ = + std::make_unique(this, use_shared_texture_); UpdateFrameRate(); } else { video_consumer_->SetActive(true); @@ -1560,7 +1562,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; } @@ -1594,6 +1596,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 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(); } diff --git a/libcef/browser/osr/render_widget_host_view_osr.h b/libcef/browser/osr/render_widget_host_view_osr.h index 70afb20d4..b94875219 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.h +++ b/libcef/browser/osr/render_widget_host_view_osr.h @@ -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; diff --git a/libcef/browser/osr/video_consumer_osr.cc b/libcef/browser/osr/video_consumer_osr.cc index 98c7b5276..dc7e745c0 100644 --- a/libcef/browser/osr/video_consumer_osr.cc +++ b/libcef/browser/osr/video_consumer_osr.cc @@ -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; diff --git a/libcef/browser/osr/video_consumer_osr.h b/libcef/browser/osr/video_consumer_osr.h index 1b66c8890..921b50582 100644 --- a/libcef/browser/osr/video_consumer_osr.h +++ b/libcef/browser/osr/video_consumer_osr.h @@ -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 video_capturer_; diff --git a/libcef_dll/cpptoc/render_handler_cpptoc.cc b/libcef_dll/cpptoc/render_handler_cpptoc.cc index fa5729ff6..facc85805 100644 --- a/libcef_dll/cpptoc/render_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/render_handler_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=0b4a5f175a85d506a4ba6da1bbdb6bad2306d898$ +// $hash=fb10148445f36dc1712cf760b9754911bbbcdf13$ // #include "libcef_dll/cpptoc/render_handler_cpptoc.h" @@ -315,7 +315,7 @@ render_handler_on_accelerated_paint(struct _cef_render_handler_t* self, cef_paint_element_type_t type, size_t dirtyRectsCount, cef_rect_t const* dirtyRects, - void* shared_handle) { + const cef_accelerated_paint_info_t* info) { shutdown_checker::AssertNotShutdown(); // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -334,9 +334,9 @@ render_handler_on_accelerated_paint(struct _cef_render_handler_t* self, if (dirtyRectsCount > 0 && !dirtyRects) { return; } - // Verify param: shared_handle; type: simple_byaddr - DCHECK(shared_handle); - if (!shared_handle) { + // Verify param: info; type: simple_byref_const + DCHECK(info); + if (!info) { return; } @@ -348,10 +348,12 @@ render_handler_on_accelerated_paint(struct _cef_render_handler_t* self, dirtyRectsList.push_back(dirtyRectsVal); } } + // Translate param: info; type: simple_byref_const + CefAcceleratedPaintInfo infoVal = info ? *info : CefAcceleratedPaintInfo(); // Execute CefRenderHandlerCppToC::Get(self)->OnAcceleratedPaint( - CefBrowserCToCpp::Wrap(browser), type, dirtyRectsList, shared_handle); + CefBrowserCToCpp::Wrap(browser), type, dirtyRectsList, infoVal); } void CEF_CALLBACK diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.cc b/libcef_dll/ctocpp/render_handler_ctocpp.cc index cb54c4603..83786a496 100644 --- a/libcef_dll/ctocpp/render_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/render_handler_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=0a40603ce9d3cb6ee7758c4d8ebad8c2299256cf$ +// $hash=2ef28289570e9eba45c5e2bb87c94e7e8e51ed0e$ // #include "libcef_dll/ctocpp/render_handler_ctocpp.h" @@ -239,10 +239,11 @@ void CefRenderHandlerCToCpp::OnPaint(CefRefPtr browser, } NO_SANITIZE("cfi-icall") -void CefRenderHandlerCToCpp::OnAcceleratedPaint(CefRefPtr browser, - PaintElementType type, - const RectList& dirtyRects, - void* shared_handle) { +void CefRenderHandlerCToCpp::OnAcceleratedPaint( + CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) { shutdown_checker::AssertNotShutdown(); cef_render_handler_t* _struct = GetStruct(); @@ -257,11 +258,6 @@ void CefRenderHandlerCToCpp::OnAcceleratedPaint(CefRefPtr browser, if (!browser.get()) { return; } - // Verify param: shared_handle; type: simple_byaddr - DCHECK(shared_handle); - if (!shared_handle) { - return; - } // Translate param: dirtyRects; type: simple_vec_byref_const const size_t dirtyRectsCount = dirtyRects.size(); @@ -278,7 +274,7 @@ void CefRenderHandlerCToCpp::OnAcceleratedPaint(CefRefPtr browser, // Execute _struct->on_accelerated_paint(_struct, CefBrowserCppToC::Wrap(browser), type, - dirtyRectsCount, dirtyRectsList, shared_handle); + dirtyRectsCount, dirtyRectsList, &info); // Restore param:dirtyRects; type: simple_vec_byref_const if (dirtyRectsList) { diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.h b/libcef_dll/ctocpp/render_handler_ctocpp.h index c91a2e1f5..f15973fbb 100644 --- a/libcef_dll/ctocpp/render_handler_ctocpp.h +++ b/libcef_dll/ctocpp/render_handler_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=b1028055c90d484e6548009d8bb6e69e06ac1d17$ +// $hash=ae20df54c0accee56380672fa4c7e501a0037348$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_ @@ -56,7 +56,7 @@ class CefRenderHandlerCToCpp void OnAcceleratedPaint(CefRefPtr browser, PaintElementType type, const RectList& dirtyRects, - void* shared_handle) override; + const CefAcceleratedPaintInfo& info) override; void GetTouchHandleSize(CefRefPtr browser, cef_horizontal_alignment_t orientation, CefSize& size) override; diff --git a/patch/patch.cfg b/patch/patch.cfg index ae424e3fc..085677d58 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -757,5 +757,14 @@ patches = [ # views: mac: Add customization point to acceptsFirstMouse. # https://github.com/chromiumembedded/cef/issues/3680 'name': 'mac_render_widget_3680' + }, + { + # win: Remove keyed mutex with OSR for better performace and to avoid + # potential vendor driver bugs. + # https://bitbucket.org/chromiumembedded/cef/pull-requests/734 + # https://github.com/chromiumembedded/cef/issues/2575 + # It is a bit hacky, not suitable for merging into upstream. + # https://chromium-review.googlesource.com/c/chromium/src/+/5302103 + 'name': 'osr_win_remove_keyed_mutex_2575' } ] diff --git a/patch/patches/osr_win_remove_keyed_mutex_2575.patch b/patch/patches/osr_win_remove_keyed_mutex_2575.patch new file mode 100644 index 000000000..80c9ebf10 --- /dev/null +++ b/patch/patches/osr_win_remove_keyed_mutex_2575.patch @@ -0,0 +1,71 @@ +diff --git gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc +index ecabd51db586d..a7ae5e101ca02 100644 +--- gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc ++++ gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc +@@ -174,7 +174,8 @@ gfx::GpuMemoryBufferHandle GpuMemoryBufferFactoryDXGI::CreateGpuMemoryBuffer( + // so make sure that the usage is one that we support. + DCHECK(usage == gfx::BufferUsage::GPU_READ || + usage == gfx::BufferUsage::SCANOUT || +- usage == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE) ++ usage == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE || ++ usage == gfx::BufferUsage::SCANOUT_VEA_CPU_READ) + << "Incorrect usage, usage=" << gfx::BufferUsageToString(usage); + + D3D11_TEXTURE2D_DESC desc = { +@@ -188,7 +189,9 @@ gfx::GpuMemoryBufferHandle GpuMemoryBufferFactoryDXGI::CreateGpuMemoryBuffer( + D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, + 0, + D3D11_RESOURCE_MISC_SHARED_NTHANDLE | +- D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX}; ++ static_cast(usage == gfx::BufferUsage::SCANOUT_VEA_CPU_READ ++ ? D3D11_RESOURCE_MISC_SHARED ++ : D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX)}; + + Microsoft::WRL::ComPtr d3d11_texture; + +diff --git media/video/renderable_gpu_memory_buffer_video_frame_pool.cc media/video/renderable_gpu_memory_buffer_video_frame_pool.cc +index 245ea07c91037..27ec965fb9147 100644 +--- media/video/renderable_gpu_memory_buffer_video_frame_pool.cc ++++ media/video/renderable_gpu_memory_buffer_video_frame_pool.cc +@@ -205,7 +205,7 @@ gfx::Size GetBufferSizeInPixelsForVideoPixelFormat( + bool FrameResources::Initialize() { + auto* context = pool_->GetContext(); + +- constexpr gfx::BufferUsage kBufferUsage = ++ gfx::BufferUsage buffer_usage = + #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) + gfx::BufferUsage::SCANOUT_VEA_CPU_READ + #else +@@ -219,13 +219,30 @@ bool FrameResources::Initialize() { + const gfx::Size buffer_size_in_pixels = + GetBufferSizeInPixelsForVideoPixelFormat(format_, coded_size_); + ++#if BUILDFLAG(IS_WIN) ++ // For CEF OSR feature, currently there's no other place in chromium use RGBA. ++ // If the format is RGBA, currently CEF do not write to the texture anymore ++ // once the GMB is returned from CopyRequest. So there will be no race ++ // condition on that texture. We can request a GMB without a keyed mutex to ++ // accelerate and probably prevent some driver deadlock. ++ if (format_ == PIXEL_FORMAT_ARGB) { ++ // This value is 'borrowed', SCANOUT_VEA_CPU_READ is probably invalid ++ // cause there's no real SCANOUT on Windows. We simply use this enum as a ++ // flag to disable mutex in the GMBFactoryDXGI because this enum is also ++ // used above in macOS and CrOS for similar usage (claim no other one will ++ // concurrently use the resource). ++ // https://chromium-review.googlesource.com/c/chromium/src/+/5302103 ++ buffer_usage = gfx::BufferUsage::SCANOUT_VEA_CPU_READ; ++ } ++#endif ++ + // Create the GpuMemoryBuffer. + gpu_memory_buffer_ = context->CreateGpuMemoryBuffer( +- buffer_size_in_pixels, buffer_format, kBufferUsage); ++ buffer_size_in_pixels, buffer_format, buffer_usage); + if (!gpu_memory_buffer_) { + DLOG(ERROR) << "Failed to allocate GpuMemoryBuffer for frame: coded_size=" + << coded_size_.ToString() +- << ", usage=" << static_cast(kBufferUsage); ++ << ", usage=" << static_cast(buffer_usage); + return false; + } + diff --git a/tests/cefclient/browser/browser_window_osr_gtk.cc b/tests/cefclient/browser/browser_window_osr_gtk.cc index db5ce52f3..65dbdfef3 100644 --- a/tests/cefclient/browser/browser_window_osr_gtk.cc +++ b/tests/cefclient/browser/browser_window_osr_gtk.cc @@ -987,6 +987,11 @@ void BrowserWindowOsrGtk::CreateBrowser( CefWindowInfo window_info; window_info.SetAsWindowless(handle); + window_info.shared_texture_enabled = + renderer_.settings().shared_texture_enabled; + window_info.external_begin_frame_enabled = + renderer_.settings().external_begin_frame_enabled; + // Create the browser asynchronously. CefBrowserHost::CreateBrowser(window_info, client_handler_, client_handler_->startup_url(), settings, @@ -1000,6 +1005,12 @@ void BrowserWindowOsrGtk::GetPopupConfig(CefWindowHandle temp_handle, CEF_REQUIRE_UI_THREAD(); windowInfo.SetAsWindowless(temp_handle); + + windowInfo.shared_texture_enabled = + renderer_.settings().shared_texture_enabled; + windowInfo.external_begin_frame_enabled = + renderer_.settings().external_begin_frame_enabled; + client = client_handler_; } diff --git a/tests/cefclient/browser/browser_window_osr_mac.h b/tests/cefclient/browser/browser_window_osr_mac.h index 130a77c10..a1daad784 100644 --- a/tests/cefclient/browser/browser_window_osr_mac.h +++ b/tests/cefclient/browser/browser_window_osr_mac.h @@ -72,6 +72,10 @@ class BrowserWindowOsrMac : public BrowserWindow, const void* buffer, int width, int height) override; + void OnAcceleratedPaint(CefRefPtr browser, + CefRenderHandler::PaintElementType type, + const CefRenderHandler::RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) override; void OnCursorChange(CefRefPtr browser, CefCursorHandle cursor, cef_cursor_type_t type, diff --git a/tests/cefclient/browser/browser_window_osr_mac.mm b/tests/cefclient/browser/browser_window_osr_mac.mm index 884b18d1d..f868d2ade 100644 --- a/tests/cefclient/browser/browser_window_osr_mac.mm +++ b/tests/cefclient/browser/browser_window_osr_mac.mm @@ -78,6 +78,8 @@ class ScopedGLContext { } } + NSOpenGLContext* context() const { return context_; } + private: NSOpenGLContext* context_; const bool swap_buffers_; @@ -132,9 +134,6 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) { return self; } -// End disable NSOpenGL deprecation warnings. -#pragma clang diagnostic pop - - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self @@ -1388,6 +1387,10 @@ class BrowserWindowOsrMacImpl { const void* buffer, int width, int height); + void OnAcceleratedPaint(CefRefPtr browser, + CefRenderHandler::PaintElementType type, + const CefRenderHandler::RectList& dirtyRects, + const CefAcceleratedPaintInfo& info); void OnCursorChange(CefRefPtr browser, CefCursorHandle cursor, cef_cursor_type_t type, @@ -1453,6 +1456,11 @@ void BrowserWindowOsrMacImpl::CreateBrowser( window_info.SetAsWindowless( CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(native_browser_view_)); + window_info.shared_texture_enabled = + renderer_.settings().shared_texture_enabled; + window_info.external_begin_frame_enabled = + renderer_.settings().external_begin_frame_enabled; + // Create the browser asynchronously. CefBrowserHost::CreateBrowser(window_info, browser_window_.client_handler_, browser_window_.client_handler_->startup_url(), @@ -1466,6 +1474,12 @@ void BrowserWindowOsrMacImpl::GetPopupConfig(CefWindowHandle temp_handle, CEF_REQUIRE_UI_THREAD(); windowInfo.SetAsWindowless(temp_handle); + + windowInfo.shared_texture_enabled = + renderer_.settings().shared_texture_enabled; + windowInfo.external_begin_frame_enabled = + renderer_.settings().external_begin_frame_enabled; + client = browser_window_.client_handler_; } @@ -1730,6 +1744,46 @@ void BrowserWindowOsrMacImpl::OnPaint( renderer_.Render(); } +void BrowserWindowOsrMacImpl::OnAcceleratedPaint( + CefRefPtr browser, + CefRenderHandler::PaintElementType type, + const CefRenderHandler::RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + if (!native_browser_view_) { + return; + } + + ScopedGLContext scoped_gl_context(native_browser_view_, true); + + IOSurfaceRef io_surface = (IOSurfaceRef)info.shared_texture_io_surface; + + GLuint rectTexture; + glGenTextures(1, &rectTexture); + glEnable(GL_TEXTURE_RECTANGLE_ARB); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, rectTexture); + + CGLContextObj cgl_context = CGLGetCurrentContext(); + + GLsizei width = (GLsizei)IOSurfaceGetWidth(io_surface); + GLsizei height = (GLsizei)IOSurfaceGetHeight(io_surface); + + CGLTexImageIOSurface2D(cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA8, width, + height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, + io_surface, 0); + + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + renderer_.OnAcceleratedPaint(browser, type, dirtyRects, rectTexture, width, + height); + renderer_.Render(); +} + void BrowserWindowOsrMacImpl::OnCursorChange( CefRefPtr browser, CefCursorHandle cursor, @@ -1956,6 +2010,14 @@ void BrowserWindowOsrMac::OnPaint(CefRefPtr browser, impl_->OnPaint(browser, type, dirtyRects, buffer, width, height); } +void BrowserWindowOsrMac::OnAcceleratedPaint( + CefRefPtr browser, + CefRenderHandler::PaintElementType type, + const CefRenderHandler::RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) { + impl_->OnAcceleratedPaint(browser, type, dirtyRects, info); +} + void BrowserWindowOsrMac::OnCursorChange( CefRefPtr browser, CefCursorHandle cursor, @@ -1997,3 +2059,6 @@ void BrowserWindowOsrMac::UpdateAccessibilityLocation( } } // namespace client + +// End disable NSOpenGL deprecation warnings. +#pragma clang diagnostic pop diff --git a/tests/cefclient/browser/client_handler_osr.cc b/tests/cefclient/browser/client_handler_osr.cc index 2f36af9b4..27e8125b8 100644 --- a/tests/cefclient/browser/client_handler_osr.cc +++ b/tests/cefclient/browser/client_handler_osr.cc @@ -122,12 +122,12 @@ void ClientHandlerOsr::OnAcceleratedPaint( CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) { + const CefAcceleratedPaintInfo& info) { CEF_REQUIRE_UI_THREAD(); if (!osr_delegate_) { return; } - osr_delegate_->OnAcceleratedPaint(browser, type, dirtyRects, share_handle); + osr_delegate_->OnAcceleratedPaint(browser, type, dirtyRects, info); } bool ClientHandlerOsr::StartDragging( diff --git a/tests/cefclient/browser/client_handler_osr.h b/tests/cefclient/browser/client_handler_osr.h index 4ed713bb8..8d748ea38 100644 --- a/tests/cefclient/browser/client_handler_osr.h +++ b/tests/cefclient/browser/client_handler_osr.h @@ -48,7 +48,7 @@ class ClientHandlerOsr : public ClientHandler, CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) {} + const CefAcceleratedPaintInfo& info) {} virtual bool StartDragging(CefRefPtr browser, CefRefPtr drag_data, CefRenderHandler::DragOperationsMask allowed_ops, @@ -115,7 +115,7 @@ class ClientHandlerOsr : public ClientHandler, void OnAcceleratedPaint(CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) override; + const CefAcceleratedPaintInfo& info) override; bool StartDragging(CefRefPtr browser, CefRefPtr drag_data, CefRenderHandler::DragOperationsMask allowed_ops, diff --git a/tests/cefclient/browser/main_context_impl.cc b/tests/cefclient/browser/main_context_impl.cc index 345c74cfa..f53bf3054 100644 --- a/tests/cefclient/browser/main_context_impl.cc +++ b/tests/cefclient/browser/main_context_impl.cc @@ -64,24 +64,16 @@ MainContextImpl::MainContextImpl(CefRefPtr command_line, use_windowless_rendering_ && command_line_->HasSwitch(switches::kTransparentPaintingEnabled); -#if defined(OS_WIN) - // Shared texture is only supported on Windows. shared_texture_enabled_ = use_windowless_rendering_ && command_line_->HasSwitch(switches::kSharedTextureEnabled); -#endif external_begin_frame_enabled_ = use_windowless_rendering_ && command_line_->HasSwitch(switches::kExternalBeginFrameEnabled); if (windowless_frame_rate_ <= 0) { -// Choose a reasonable default rate based on the OSR mode. -#if defined(OS_WIN) windowless_frame_rate_ = shared_texture_enabled_ ? 60 : 30; -#else - windowless_frame_rate_ = 30; -#endif } // Enable experimental Chrome runtime. See issue #2969 for details. @@ -256,9 +248,7 @@ void MainContextImpl::PopulateOsrSettings(OsrRendererSettings* settings) { settings->show_update_rect = command_line_->HasSwitch(switches::kShowUpdateRect); -#if defined(OS_WIN) settings->shared_texture_enabled = shared_texture_enabled_; -#endif settings->external_begin_frame_enabled = external_begin_frame_enabled_; settings->begin_frame_rate = windowless_frame_rate_; diff --git a/tests/cefclient/browser/main_context_impl.h b/tests/cefclient/browser/main_context_impl.h index 6613cf6d9..15fdd76d5 100644 --- a/tests/cefclient/browser/main_context_impl.h +++ b/tests/cefclient/browser/main_context_impl.h @@ -80,9 +80,7 @@ class MainContextImpl : public MainContext { std::unique_ptr root_window_manager_; -#if defined(OS_WIN) bool shared_texture_enabled_; -#endif bool external_begin_frame_enabled_; diff --git a/tests/cefclient/browser/osr_d3d11_win.cc b/tests/cefclient/browser/osr_d3d11_win.cc index 0318c2fb1..97a329b2c 100644 --- a/tests/cefclient/browser/osr_d3d11_win.cc +++ b/tests/cefclient/browser/osr_d3d11_win.cc @@ -23,6 +23,7 @@ #endif #include #include +#include #include "include/base/cef_logging.h" #include "include/internal/cef_string.h" @@ -568,10 +569,18 @@ std::shared_ptr Device::create_quad(float x, } std::shared_ptr Device::open_shared_texture(void* handle) { - ID3D11Texture2D* tex = nullptr; - auto hr = device_->OpenSharedResource(handle, __uuidof(ID3D11Texture2D), - (void**)(&tex)); + Microsoft::WRL::ComPtr device1; + HRESULT hr = device_->QueryInterface(IID_PPV_ARGS(&device1)); if (FAILED(hr)) { + LOG(FATAL) << "Failed to open D3D11_1 device. hr=" << std::hex << hr; + return nullptr; + } + + // Open texture on device using shared handle + ID3D11Texture2D* tex = nullptr; + hr = device1->OpenSharedResource1(handle, IID_PPV_ARGS(&tex)); + if (FAILED(hr)) { + LOG(FATAL) << "Failed to open shared texture. hr=" << std::hex << hr; return nullptr; } diff --git a/tests/cefclient/browser/osr_render_handler_win.h b/tests/cefclient/browser/osr_render_handler_win.h index b7031d572..6981577d9 100644 --- a/tests/cefclient/browser/osr_render_handler_win.h +++ b/tests/cefclient/browser/osr_render_handler_win.h @@ -48,7 +48,7 @@ class OsrRenderHandlerWin { virtual void OnAcceleratedPaint(CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) = 0; + const CefAcceleratedPaintInfo& info) = 0; bool send_begin_frame() const { return settings_.external_begin_frame_enabled; diff --git a/tests/cefclient/browser/osr_render_handler_win_d3d11.cc b/tests/cefclient/browser/osr_render_handler_win_d3d11.cc index e85f4a699..c1f3033fa 100644 --- a/tests/cefclient/browser/osr_render_handler_win_d3d11.cc +++ b/tests/cefclient/browser/osr_render_handler_win_d3d11.cc @@ -12,7 +12,7 @@ namespace client { BrowserLayer::BrowserLayer(const std::shared_ptr& device) - : d3d11::Layer(device, true /* flip */) { + : d3d11::Layer(device, false /* flip */) { frame_buffer_ = std::make_shared(device_); } @@ -189,13 +189,13 @@ void OsrRenderHandlerWinD3D11::OnAcceleratedPaint( CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) { + const CefAcceleratedPaintInfo& info) { CEF_REQUIRE_UI_THREAD(); if (type == PET_POPUP) { - popup_layer_->on_paint(share_handle); + popup_layer_->on_paint(info.shared_texture_handle); } else { - browser_layer_->on_paint(share_handle); + browser_layer_->on_paint(info.shared_texture_handle); } Render(); diff --git a/tests/cefclient/browser/osr_render_handler_win_d3d11.h b/tests/cefclient/browser/osr_render_handler_win_d3d11.h index ef1935cad..1afd1b9d9 100644 --- a/tests/cefclient/browser/osr_render_handler_win_d3d11.h +++ b/tests/cefclient/browser/osr_render_handler_win_d3d11.h @@ -70,7 +70,7 @@ class OsrRenderHandlerWinD3D11 : public OsrRenderHandlerWin { void OnAcceleratedPaint(CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) override; + const CefAcceleratedPaintInfo& info) override; private: void Render() override; diff --git a/tests/cefclient/browser/osr_render_handler_win_gl.cc b/tests/cefclient/browser/osr_render_handler_win_gl.cc index a376cb6d2..909aac3e1 100644 --- a/tests/cefclient/browser/osr_render_handler_win_gl.cc +++ b/tests/cefclient/browser/osr_render_handler_win_gl.cc @@ -131,7 +131,7 @@ void OsrRenderHandlerWinGL::OnAcceleratedPaint( CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) { + const CefAcceleratedPaintInfo& info) { // Not used with this implementation. NOTREACHED(); } diff --git a/tests/cefclient/browser/osr_render_handler_win_gl.h b/tests/cefclient/browser/osr_render_handler_win_gl.h index 8f503012f..2b364cbab 100644 --- a/tests/cefclient/browser/osr_render_handler_win_gl.h +++ b/tests/cefclient/browser/osr_render_handler_win_gl.h @@ -35,7 +35,7 @@ class OsrRenderHandlerWinGL : public OsrRenderHandlerWin { void OnAcceleratedPaint(CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) override; + const CefAcceleratedPaintInfo& info) override; private: void Render() override; diff --git a/tests/cefclient/browser/osr_renderer.cc b/tests/cefclient/browser/osr_renderer.cc index f0e359756..22af81623 100644 --- a/tests/cefclient/browser/osr_renderer.cc +++ b/tests/cefclient/browser/osr_renderer.cc @@ -4,6 +4,12 @@ #include "tests/cefclient/browser/osr_renderer.h" +#if defined(__clang__) +// Begin disable NSOpenGL deprecation warnings. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + #if USE_SHADERS // Expose prototypes for OpenGL shader functions. #define GL_GLEXT_PROTOTYPES @@ -14,7 +20,6 @@ #if defined(OS_WIN) #include #elif defined(OS_MAC) -#define GL_SILENCE_DEPRECATION #if USE_SHADERS #include #else @@ -755,6 +760,210 @@ void OsrRenderer::ClearPopupRects() { original_popup_rect_.Set(0, 0, 0, 0); } +void OsrRenderer::OnAcceleratedPaint( + CefRefPtr browser, + CefRenderHandler::PaintElementType type, + const CefRenderHandler::RectList& dirtyRects, + unsigned int io_surface_tex, + int width, + int height) { + if (!initialized_) { + Initialize(); + } + +#if !defined(OS_WIN) + if (width != view_width_ || height != view_height_) { + // Width or height has changed, so proceed to update the texture + view_width_ = width; + view_height_ = height; + + // Rebind texture_id as the active texture + glBindTexture(GL_TEXTURE_2D, texture_id_); + VERIFY_NO_ERROR; + + // Allocate a new storage for texture_id with the new dimensions + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + VERIFY_NO_ERROR; + } + + if (IsTransparent()) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + VERIFY_NO_ERROR; + + // Enable alpha blending. + glEnable(GL_BLEND); + VERIFY_NO_ERROR; + } + + GLuint framebuffer; + glGenFramebuffers(1, &framebuffer); + VERIFY_NO_ERROR; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + VERIFY_NO_ERROR; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + texture_id_, 0); + VERIFY_NO_ERROR; + + // Check framebuffer status + DCHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); + + glPushAttrib(GL_ALL_ATTRIB_BITS); + VERIFY_NO_ERROR; + glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); + VERIFY_NO_ERROR; + + // Setup OpenGL states + glViewport(0, 0, width, height); + VERIFY_NO_ERROR; + + // Bind the GL_TEXTURE_RECTANGLE_ARB texture + glActiveTexture(GL_TEXTURE0); + VERIFY_NO_ERROR; + + glClientActiveTexture(GL_TEXTURE0); + VERIFY_NO_ERROR; + + glMatrixMode(GL_TEXTURE); + VERIFY_NO_ERROR; + glPushMatrix(); + VERIFY_NO_ERROR; + glLoadIdentity(); + VERIFY_NO_ERROR; + + glMatrixMode(GL_PROJECTION); + VERIFY_NO_ERROR; + glPushMatrix(); + VERIFY_NO_ERROR; + glLoadIdentity(); + VERIFY_NO_ERROR; + glOrtho(0, width, 0, height, -1, 1); + VERIFY_NO_ERROR; + + glMatrixMode(GL_MODELVIEW); + VERIFY_NO_ERROR; + glPushMatrix(); + VERIFY_NO_ERROR; + glLoadIdentity(); + VERIFY_NO_ERROR; + + // rectangleTexture is the GL_TEXTURE_RECTANGLE_ARB + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_tex); + VERIFY_NO_ERROR; + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + VERIFY_NO_ERROR; + glColor4f(1.0, 1.0, 1.0, 1.0); + VERIFY_NO_ERROR; + + bool isFlipped = false; + + GLfloat tex_coords[8]; + + GLfloat texOriginX = 0; + GLfloat texOriginY = 0; + GLfloat texExtentX = width; + GLfloat texExtentY = height; + + // X + tex_coords[0] = texOriginX; + tex_coords[2] = texOriginX; + tex_coords[4] = texExtentX; + tex_coords[6] = texExtentX; + + // Y + if (!isFlipped) { + tex_coords[1] = texOriginY; + tex_coords[3] = texExtentY; + tex_coords[5] = texExtentY; + tex_coords[7] = texOriginY; + } else { + tex_coords[1] = texExtentY; + tex_coords[3] = texOriginY; + tex_coords[5] = texOriginY; + tex_coords[7] = texExtentY; + } + + GLfloat verts[] = { + 0.0f, 0.0f, 0.0f, (float)height, + (float)width, (float)height, (float)width, 0.0f, + }; + + // Ought to cache the GL_ARRAY_BUFFER_BINDING, + // GL_ELEMENT_ARRAY_BUFFER_BINDING, set buffer to 0, and reset + GLint arrayBuffer, elementArrayBuffer; + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &elementArrayBuffer); + VERIFY_NO_ERROR; + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &arrayBuffer); + VERIFY_NO_ERROR; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + VERIFY_NO_ERROR; + glBindBuffer(GL_ARRAY_BUFFER, 0); + VERIFY_NO_ERROR; + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + VERIFY_NO_ERROR; + glTexCoordPointer(2, GL_FLOAT, 0, tex_coords); + VERIFY_NO_ERROR; + glEnableClientState(GL_VERTEX_ARRAY); + VERIFY_NO_ERROR; + glVertexPointer(2, GL_FLOAT, 0, verts); + VERIFY_NO_ERROR; + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + VERIFY_NO_ERROR; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer); + VERIFY_NO_ERROR; + glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); + VERIFY_NO_ERROR; + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + VERIFY_NO_ERROR; + + // Restore OpenGL states + glMatrixMode(GL_MODELVIEW); + VERIFY_NO_ERROR; + glPopMatrix(); + VERIFY_NO_ERROR; + + glMatrixMode(GL_PROJECTION); + VERIFY_NO_ERROR; + glPopMatrix(); + VERIFY_NO_ERROR; + + glMatrixMode(GL_TEXTURE); + VERIFY_NO_ERROR; + glPopMatrix(); + VERIFY_NO_ERROR; + + glPopClientAttrib(); + VERIFY_NO_ERROR; + glPopAttrib(); + VERIFY_NO_ERROR; + + if (IsTransparent()) { + // Enable alpha blending. + glDisable(GL_BLEND); + VERIFY_NO_ERROR; + } + + // 0 unbinds the FBO, reverting to the default buffer + glBindFramebuffer(GL_FRAMEBUFFER, 0); + VERIFY_NO_ERROR; + + glDeleteFramebuffers(1, &framebuffer); + VERIFY_NO_ERROR; + + // Delete the rectangle texture + glDeleteTextures(1, &io_surface_tex); + VERIFY_NO_ERROR; + + glDisable(GL_TEXTURE_RECTANGLE_ARB); + VERIFY_NO_ERROR; +#endif // !defined(OS_WIN) +} + void OsrRenderer::OnPaint(CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, @@ -882,3 +1091,8 @@ void OsrRenderer::IncrementSpin(float spinDX, float spinDY) { } } // namespace client + +#if defined(__clang__) +// End disable NSOpenGL deprecation warnings. +#pragma clang diagnostic pop +#endif diff --git a/tests/cefclient/browser/osr_renderer.h b/tests/cefclient/browser/osr_renderer.h index 9754deabd..4a089f154 100644 --- a/tests/cefclient/browser/osr_renderer.h +++ b/tests/cefclient/browser/osr_renderer.h @@ -49,6 +49,14 @@ class OsrRenderer { int width, int height); + // Used when rendering with shared textures. + void OnAcceleratedPaint(CefRefPtr browser, + CefRenderHandler::PaintElementType type, + const CefRenderHandler::RectList& dirtyRects, + unsigned int io_surface_tex, + int width, + int height); + // Apply spin. void SetSpin(float spinX, float spinY); void IncrementSpin(float spinDX, float spinDY); @@ -61,6 +69,8 @@ class OsrRenderer { void ClearPopupRects(); + const OsrRendererSettings& settings() const { return settings_; } + private: CefRect GetPopupRectInWebView(const CefRect& original_rect); diff --git a/tests/cefclient/browser/osr_window_win.cc b/tests/cefclient/browser/osr_window_win.cc index 74cb22811..38085e630 100644 --- a/tests/cefclient/browser/osr_window_win.cc +++ b/tests/cefclient/browser/osr_window_win.cc @@ -1043,9 +1043,9 @@ void OsrWindowWin::OnAcceleratedPaint( CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) { + const CefAcceleratedPaintInfo& info) { EnsureRenderHandler(); - render_handler_->OnAcceleratedPaint(browser, type, dirtyRects, share_handle); + render_handler_->OnAcceleratedPaint(browser, type, dirtyRects, info); } void OsrWindowWin::OnCursorChange(CefRefPtr browser, diff --git a/tests/cefclient/browser/osr_window_win.h b/tests/cefclient/browser/osr_window_win.h index 971de657f..04789b73b 100644 --- a/tests/cefclient/browser/osr_window_win.h +++ b/tests/cefclient/browser/osr_window_win.h @@ -130,7 +130,7 @@ class OsrWindowWin void OnAcceleratedPaint(CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, - void* share_handle) override; + const CefAcceleratedPaintInfo& info) override; void OnCursorChange(CefRefPtr browser, CefCursorHandle cursor, cef_cursor_type_t type, diff --git a/tools/cef_parser.py b/tools/cef_parser.py index 1cc0fb059..f4e7df19b 100644 --- a/tools/cef_parser.py +++ b/tools/cef_parser.py @@ -24,13 +24,16 @@ def wrap_text(text, indent='', maxchars=80, listitem=False): necessary a line will be broken and wrapped after a word. """ if listitem: - initial_indent=indent + '- ' - subsequent_indent=indent+' ' + initial_indent = indent + '- ' + subsequent_indent = indent + ' ' else: - initial_indent=indent - subsequent_indent=indent - lines = textwrap.wrap(text, maxchars, initial_indent=initial_indent, - subsequent_indent=subsequent_indent) + initial_indent = indent + subsequent_indent = indent + lines = textwrap.wrap( + text, + maxchars, + initial_indent=initial_indent, + subsequent_indent=subsequent_indent) return '\n'.join(lines) + '\n' @@ -187,7 +190,7 @@ def format_comment(comment, indent, translate_map=None, maxchars=80): else: result += line result += '\n' - listitem = False; + listitem = False else: if not listitem: # add to the current paragraph @@ -395,6 +398,9 @@ _simpletypes = { 'char* const': ['char* const', 'NULL'], 'cef_color_t': ['cef_color_t', '0'], 'cef_json_parser_error_t': ['cef_json_parser_error_t', 'JSON_NO_ERROR'], + 'CefAcceleratedPaintInfo': [ + 'cef_accelerated_paint_info_t', 'CefAcceleratedPaintInfo()' + ], 'CefAudioParameters': ['cef_audio_parameters_t', 'CefAudioParameters()'], 'CefBaseTime': ['cef_basetime_t', 'CefBaseTime()'], 'CefBoxLayoutSettings': [