diff --git a/BUILD.gn b/BUILD.gn index 508ee10bd..8b801e82e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -423,6 +423,8 @@ static_library("libcef_static") { "libcef/browser/origin_whitelist_impl.h", "libcef/browser/osr/browser_platform_delegate_osr.cc", "libcef/browser/osr/browser_platform_delegate_osr.h", + "libcef/browser/osr/host_display_client_osr.cc", + "libcef/browser/osr/host_display_client_osr.h", "libcef/browser/osr/motion_event_osr.cc", "libcef/browser/osr/motion_event_osr.h", "libcef/browser/osr/osr_accessibility_util.cc", @@ -431,10 +433,10 @@ static_library("libcef_static") { "libcef/browser/osr/osr_util.h", "libcef/browser/osr/render_widget_host_view_osr.cc", "libcef/browser/osr/render_widget_host_view_osr.h", - "libcef/browser/osr/software_output_device_osr.cc", - "libcef/browser/osr/software_output_device_osr.h", "libcef/browser/osr/synthetic_gesture_target_osr.cc", "libcef/browser/osr/synthetic_gesture_target_osr.h", + "libcef/browser/osr/video_consumer_osr.cc", + "libcef/browser/osr/video_consumer_osr.h", "libcef/browser/osr/web_contents_view_osr.cc", "libcef/browser/osr/web_contents_view_osr.h", "libcef/browser/path_util_impl.cc", @@ -825,7 +827,6 @@ static_library("libcef_static") { "libcef/browser/native/menu_runner_mac.mm", "libcef/browser/osr/browser_platform_delegate_osr_mac.h", "libcef/browser/osr/browser_platform_delegate_osr_mac.mm", - "libcef/browser/osr/render_widget_host_view_osr_mac.mm", "libcef/common/util_mac.h", "libcef/common/util_mac.mm", ] diff --git a/libcef/browser/native/window_x11.cc b/libcef/browser/native/window_x11.cc index fa76b9812..5ce95c522 100644 --- a/libcef/browser/native/window_x11.cc +++ b/libcef/browser/native/window_x11.cc @@ -6,16 +6,16 @@ #include "libcef/browser/native/window_x11.h" #include "libcef/browser/thread_util.h" -#include -#include -#include -#include - #include "ui/base/x/x11_util.h" #include "ui/events/platform/platform_event_source.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" +#include +#include +#include +#include + namespace { const char kAtom[] = "ATOM"; diff --git a/libcef/browser/osr/host_display_client_osr.cc b/libcef/browser/osr/host_display_client_osr.cc new file mode 100644 index 000000000..b634c1704 --- /dev/null +++ b/libcef/browser/osr/host_display_client_osr.cc @@ -0,0 +1,155 @@ +// 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_); +} diff --git a/libcef/browser/osr/host_display_client_osr.h b/libcef/browser/osr/host_display_client_osr.h new file mode 100644 index 000000000..68103fe00 --- /dev/null +++ b/libcef/browser/osr/host_display_client_osr.h @@ -0,0 +1,42 @@ +// 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. + +#ifndef CEF_LIBCEF_BROWSER_OSR_HOST_DISPLAY_CLIENT_OSR_H_ +#define CEF_LIBCEF_BROWSER_OSR_HOST_DISPLAY_CLIENT_OSR_H_ + +#include + +#include "base/callback.h" +#include "base/memory/shared_memory.h" +#include "components/viz/host/host_display_client.h" +#include "ui/gfx/native_widget_types.h" + +class CefLayeredWindowUpdaterOSR; +class CefRenderWidgetHostViewOSR; + +class CefHostDisplayClientOSR : public viz::HostDisplayClient { + public: + CefHostDisplayClientOSR(CefRenderWidgetHostViewOSR* const view, + gfx::AcceleratedWidget widget); + ~CefHostDisplayClientOSR() override; + + void SetActive(bool active); + const void* GetPixelMemory() const; + gfx::Size GetPixelSize() const; + + private: + // mojom::DisplayClient implementation. + void UseProxyOutputDevice(UseProxyOutputDeviceCallback callback) override; + + void CreateLayeredWindowUpdater( + viz::mojom::LayeredWindowUpdaterRequest request) override; + + CefRenderWidgetHostViewOSR* const view_; + std::unique_ptr layered_window_updater_; + bool active_ = false; + + DISALLOW_COPY_AND_ASSIGN(CefHostDisplayClientOSR); +}; + +#endif // CEF_LIBCEF_BROWSER_OSR_HOST_DISPLAY_CLIENT_OSR_H_ diff --git a/libcef/browser/osr/render_widget_host_view_osr.cc b/libcef/browser/osr/render_widget_host_view_osr.cc index 0c443d51f..43a2c9e1d 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.cc +++ b/libcef/browser/osr/render_widget_host_view_osr.cc @@ -9,9 +9,10 @@ #include +#include "libcef/browser/browser_host_impl.h" #include "libcef/browser/osr/osr_util.h" -#include "libcef/browser/osr/software_output_device_osr.h" #include "libcef/browser/osr/synthetic_gesture_target_osr.h" +#include "libcef/browser/osr/video_consumer_osr.h" #include "libcef/browser/thread_util.h" #include "base/callback_helpers.h" @@ -61,9 +62,6 @@ const size_t kMaxDamageRects = 10; const float kDefaultScaleFactor = 1.0; -// The maximum number of retry counts if frame capture fails. -const int kFrameRetryLimit = 2; - static content::ScreenInfo ScreenInfoFrom(const CefScreenInfo& src) { content::ScreenInfo screenInfo; screenInfo.device_scale_factor = src.device_scale_factor; @@ -79,43 +77,6 @@ static content::ScreenInfo ScreenInfoFrom(const CefScreenInfo& src) { return screenInfo; } -class CefCompositorFrameSinkClient - : public viz::mojom::CompositorFrameSinkClient { - public: - CefCompositorFrameSinkClient(viz::mojom::CompositorFrameSinkClient* forward, - CefRenderWidgetHostViewOSR* rwhv) - : forward_(forward), render_widget_host_view_(rwhv) {} - - void DidReceiveCompositorFrameAck( - const std::vector& resources) override { - forward_->DidReceiveCompositorFrameAck(resources); - } - - void OnBeginFrame(const viz::BeginFrameArgs& args, - const base::flat_map& - feedbacks) override { - if (render_widget_host_view_) { - render_widget_host_view_->OnPresentCompositorFrame(); - } - forward_->OnBeginFrame(args, feedbacks); - } - - void OnBeginFramePausedChanged(bool paused) override { - forward_->OnBeginFramePausedChanged(paused); - } - - void ReclaimResources( - const std::vector& resources) override { - forward_->ReclaimResources(resources); - } - - private: - viz::mojom::CompositorFrameSinkClient* const forward_; - CefRenderWidgetHostViewOSR* const render_widget_host_view_; -}; - -#if !defined(OS_MACOSX) - class CefDelegatedFrameHostClient : public content::DelegatedFrameHostClient { public: explicit CefDelegatedFrameHostClient(CefRenderWidgetHostViewOSR* view) @@ -169,8 +130,6 @@ class CefDelegatedFrameHostClient : public content::DelegatedFrameHostClient { DISALLOW_COPY_AND_ASSIGN(CefDelegatedFrameHostClient); }; -#endif // !defined(OS_MACOSX) - ui::GestureProvider::Config CreateGestureProviderConfig() { ui::GestureProvider::Config config = ui::GetGestureProviderConfig( ui::GestureProviderConfigType::CURRENT_PLATFORM); @@ -190,143 +149,6 @@ ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) { } // namespace -// Used for managing copy requests when GPU compositing is enabled. Based on -// RendererOverridesHandler::InnerSwapCompositorFrame and -// DelegatedFrameHost::CopyFromCompositingSurface. -class CefCopyFrameGenerator { - public: - CefCopyFrameGenerator(int frame_rate_threshold_us, - CefRenderWidgetHostViewOSR* view) - : view_(view), - frame_retry_count_(0), - next_frame_time_(base::TimeTicks::Now()), - frame_duration_( - base::TimeDelta::FromMicroseconds(frame_rate_threshold_us)), - weak_ptr_factory_(this) {} - - void GenerateCopyFrame(const gfx::Rect& damage_rect) { - if (!view_->render_widget_host()) - return; - // The below code is similar in functionality to - // DelegatedFrameHost::CopyFromCompositingSurface but we reuse the same - // SkBitmap in the GPU codepath and avoid scaling where possible. - // Let the compositor copy into a new SkBitmap - std::unique_ptr request = - std::make_unique( - viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP, - base::Bind( - &CefCopyFrameGenerator::CopyFromCompositingSurfaceHasResult, - weak_ptr_factory_.GetWeakPtr(), damage_rect)); - - request->set_area(gfx::Rect(view_->GetCompositorViewportPixelSize())); - view_->GetRootLayer()->RequestCopyOfOutput(std::move(request)); - } - - void set_frame_rate_threshold_us(int frame_rate_threshold_us) { - frame_duration_ = - base::TimeDelta::FromMicroseconds(frame_rate_threshold_us); - } - - private: - void CopyFromCompositingSurfaceHasResult( - const gfx::Rect& damage_rect, - std::unique_ptr result) { - if (result->IsEmpty() || result->size().IsEmpty() || - !view_->render_widget_host()) { - OnCopyFrameCaptureFailure(damage_rect); - return; - } - - std::unique_ptr source = - std::make_unique(result->AsSkBitmap()); - DCHECK(source); - - if (source) { - std::shared_ptr bitmap(std::move(source)); - - base::TimeTicks now = base::TimeTicks::Now(); - base::TimeDelta next_frame_in = next_frame_time_ - now; - if (next_frame_in > frame_duration_ / 4) { - next_frame_time_ += frame_duration_; - base::PostDelayedTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::Bind(&CefCopyFrameGenerator::OnCopyFrameCaptureSuccess, - weak_ptr_factory_.GetWeakPtr(), damage_rect, bitmap), - next_frame_in); - } else { - next_frame_time_ = now + frame_duration_; - OnCopyFrameCaptureSuccess(damage_rect, bitmap); - } - - // Reset the frame retry count on successful frame generation. - frame_retry_count_ = 0; - } else { - OnCopyFrameCaptureFailure(damage_rect); - } - } - - void OnCopyFrameCaptureFailure(const gfx::Rect& damage_rect) { - const bool force_frame = (++frame_retry_count_ <= kFrameRetryLimit); - if (force_frame) { - // Retry with the same |damage_rect|. - CEF_POST_TASK(CEF_UIT, - base::Bind(&CefCopyFrameGenerator::GenerateCopyFrame, - weak_ptr_factory_.GetWeakPtr(), damage_rect)); - } - } - - void OnCopyFrameCaptureSuccess(const gfx::Rect& damage_rect, - std::shared_ptr bitmap) { - view_->OnPaint(damage_rect, bitmap->width(), bitmap->height(), - bitmap->getPixels()); - } - - CefRenderWidgetHostViewOSR* const view_; - int frame_retry_count_; - base::TimeTicks next_frame_time_; - base::TimeDelta frame_duration_; - - base::WeakPtrFactory weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(CefCopyFrameGenerator); -}; - -// Used to control the VSync rate in subprocesses when BeginFrame scheduling is -// enabled. -class CefBeginFrameTimer : public viz::DelayBasedTimeSourceClient { - public: - CefBeginFrameTimer(int frame_rate_threshold_us, const base::Closure& callback) - : callback_(callback) { - time_source_.reset(new viz::DelayBasedTimeSource( - base::CreateSingleThreadTaskRunnerWithTraits( - {content::BrowserThread::UI}) - .get())); - time_source_->SetTimebaseAndInterval( - base::TimeTicks(), - base::TimeDelta::FromMicroseconds(frame_rate_threshold_us)); - time_source_->SetClient(this); - } - - void SetActive(bool active) { time_source_->SetActive(active); } - - bool IsActive() const { return time_source_->Active(); } - - void SetFrameRateThresholdUs(int frame_rate_threshold_us) { - time_source_->SetTimebaseAndInterval( - base::TimeTicks::Now(), - base::TimeDelta::FromMicroseconds(frame_rate_threshold_us)); - } - - private: - // cc::TimerSourceClient implementation. - void OnTimerTick() override { callback_.Run(); } - - const base::Closure callback_; - std::unique_ptr time_source_; - - DISALLOW_COPY_AND_ASSIGN(CefBeginFrameTimer); -}; - CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( SkColor background_color, bool use_shared_texture, @@ -337,10 +159,6 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( : content::RenderWidgetHostViewBase(widget), background_color_(background_color), frame_rate_threshold_us_(0), -#if !defined(OS_MACOSX) - compositor_widget_(gfx::kNullAcceleratedWidget), -#endif - software_output_device_(NULL), hold_resize_(false), pending_resize_(false), pending_resize_force_(false), @@ -349,7 +167,7 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( parent_host_view_(parent_host_view), popup_host_view_(NULL), child_host_view_(NULL), - is_showing_(!render_widget_host_->is_hidden()), + is_showing_(false), is_destroyed_(false), pinch_zoom_enabled_(content::IsPinchToZoomEnabled()), is_scroll_offset_changed_pending_(false), @@ -371,7 +189,6 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( content::RenderViewHost::From(render_widget_host_)); } -#if !defined(OS_MACOSX) local_surface_id_allocator_.GenerateId(); local_surface_id_allocation_ = local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation(); @@ -384,9 +201,6 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( false /* should_register_frame_sink_id */); root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); -#endif - - PlatformCreateCompositorWidget(is_guest_view_hack); bool opaque = SkColorGetA(background_color_) == SK_AlphaOPAQUE; GetRootLayer()->SetFillsBoundsOpaquely(opaque); @@ -394,28 +208,22 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( external_begin_frame_enabled_ = use_external_begin_frame; -#if !defined(OS_MACOSX) - // On macOS the ui::Compositor is created/owned by the platform view. content::ImageTransportFactory* factory = content::ImageTransportFactory::GetInstance(); ui::ContextFactoryPrivate* context_factory_private = factory->GetContextFactoryPrivate(); + // Matching the attributes from RecyclableCompositorMac. compositor_.reset(new ui::Compositor( context_factory_private->AllocateFrameSinkId(), content::GetContextFactory(), context_factory_private, base::ThreadTaskRunnerHandle::Get(), false /* enable_pixel_canvas */, use_external_begin_frame ? this : nullptr)); - compositor_->SetAcceleratedWidget(compositor_widget_); - - // Tell the compositor to use shared textures if the client can handle - // OnAcceleratedPaint. - compositor_->EnableSharedTexture(use_shared_texture); + compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); compositor_->SetDelegate(this); compositor_->SetRootLayer(root_layer_.get()); compositor_->AddChildFrameSink(GetFrameSinkId()); -#endif if (browser_impl_.get()) ResizeRootLayer(false); @@ -433,34 +241,33 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( render_widget_host_->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner( GetFrameSinkId(), this); } + + if (!render_widget_host_->is_hidden()) { + Show(); + } + + if (!factory->IsGpuCompositingDisabled()) { + video_consumer_.reset(new CefVideoConsumerOSR(this)); + video_consumer_->SetActive(true); + video_consumer_->SetFrameRate( + base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_)); + } } CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() { -#if defined(OS_MACOSX) - if (is_showing_) - browser_compositor_->SetRenderWidgetHostIsHidden(true); -#else // Marking the DelegatedFrameHost as removed from the window hierarchy is // necessary to remove all connections to its old ui::Compositor. if (is_showing_) delegated_frame_host_->WasHidden(); delegated_frame_host_->DetachFromCompositor(); -#endif - PlatformDestroyCompositorWidget(); + delegated_frame_host_.reset(nullptr); + compositor_.reset(nullptr); + root_layer_.reset(nullptr); - if (copy_frame_generator_.get()) - copy_frame_generator_.reset(NULL); - -#if !defined(OS_MACOSX) - delegated_frame_host_.reset(NULL); - compositor_.reset(NULL); - root_layer_.reset(NULL); -#endif - - DCHECK(parent_host_view_ == NULL); - DCHECK(popup_host_view_ == NULL); - DCHECK(child_host_view_ == NULL); + DCHECK(!parent_host_view_); + DCHECK(!popup_host_view_); + DCHECK(!child_host_view_); DCHECK(guest_host_views_.empty()); if (text_input_manager_) @@ -515,14 +322,10 @@ void CefRenderWidgetHostViewOSR::Show() { is_showing_ = true; -#if defined(OS_MACOSX) - browser_compositor_->SetRenderWidgetHostIsHidden(false); -#else delegated_frame_host_->AttachToCompositor(compositor_.get()); delegated_frame_host_->WasShown( GetLocalSurfaceIdAllocation().local_surface_id(), GetRootLayer()->bounds().size(), base::nullopt); -#endif // Note that |render_widget_host_| will retrieve size parameters from the // DelegatedFrameHost, so it must have WasShown called after. @@ -543,12 +346,8 @@ void CefRenderWidgetHostViewOSR::Hide() { if (render_widget_host_) render_widget_host_->WasHidden(); -#if defined(OS_MACOSX) - browser_compositor_->SetRenderWidgetHostIsHidden(true); -#else GetDelegatedFrameHost()->WasHidden(); GetDelegatedFrameHost()->DetachFromCompositor(); -#endif } bool CefRenderWidgetHostViewOSR::IsShowing() { @@ -619,53 +418,10 @@ void CefRenderWidgetHostViewOSR::TakeFallbackContentFrom( void CefRenderWidgetHostViewOSR::DidCreateNewRendererCompositorFrameSink( viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { - renderer_compositor_frame_sink_.reset( - new CefCompositorFrameSinkClient(renderer_compositor_frame_sink, this)); - if (GetDelegatedFrameHost()) { - GetDelegatedFrameHost()->DidCreateNewRendererCompositorFrameSink( - renderer_compositor_frame_sink_.get()); - } + NOTREACHED(); } -void CefRenderWidgetHostViewOSR::OnPresentCompositorFrame() { - // Is Chromium rendering to a shared texture? - void* shared_texture = nullptr; - ui::Compositor* compositor = GetCompositor(); - if (compositor) { - shared_texture = compositor->GetSharedTexture(); - } - - if (shared_texture) { - CefRefPtr handler = - browser_impl_->GetClient()->GetRenderHandler(); - CHECK(handler); - - CefRenderHandler::RectList rcList; - - { - // Find the corresponding damage rect. If there isn't one pass the entire - // view size for a full redraw. - base::AutoLock lock_scope(damage_rect_lock_); - - // TODO: in the future we need to correlate the presentation - // notification with the sequence number from BeginFrame - gfx::Rect damage; - auto const i = damage_rects_.begin(); - if (i != damage_rects_.end()) { - damage = i->second; - damage_rects_.erase(i); - } else { - damage = GetViewBounds(); - } - rcList.push_back( - CefRect(damage.x(), damage.y(), damage.width(), damage.height())); - } - - handler->OnAcceleratedPaint(browser_impl_.get(), - IsPopupWidget() ? PET_POPUP : PET_VIEW, rcList, - shared_texture); - } -} +void CefRenderWidgetHostViewOSR::OnPresentCompositorFrame() {} void CefRenderWidgetHostViewOSR::AddDamageRect(uint32_t sequence, const gfx::Rect& rect) { @@ -687,93 +443,10 @@ void CefRenderWidgetHostViewOSR::SubmitCompositorFrame( const viz::LocalSurfaceId& local_surface_id, viz::CompositorFrame frame, base::Optional hit_test_region_list) { - TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::OnSwapCompositorFrame"); - - // Update the frame rate. At this point we should have a valid connection back - // to the Synthetic Frame Source, which is important so we can actually modify - // the frame rate to something other than the default of 60Hz. - if (sync_frame_rate_) { - if (frame_rate_threshold_us_ != 0) { - GetCompositor()->SetDisplayVSyncParameters( - base::TimeTicks::Now(), - base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_)); - } - sync_frame_rate_ = false; - } - - if (frame.metadata.root_scroll_offset != last_scroll_offset_) { - last_scroll_offset_ = frame.metadata.root_scroll_offset; - - if (!is_scroll_offset_changed_pending_) { - // Send the notification asnychronously. - CEF_POST_TASK( - CEF_UIT, - base::Bind(&CefRenderWidgetHostViewOSR::OnScrollOffsetChanged, - weak_ptr_factory_.GetWeakPtr())); - } - } - - if (!frame.render_pass_list.empty()) { - if (software_output_device_) { - if (!begin_frame_timer_.get()) { - // If BeginFrame scheduling is enabled SoftwareOutputDevice activity - // will be controlled via OnSetNeedsBeginFrames. Otherwise, activate - // the SoftwareOutputDevice now (when the first frame is generated). - software_output_device_->SetActive(true); - } - - // The compositor will draw directly to the SoftwareOutputDevice which - // then calls OnPaint. - // We would normally call BrowserCompositorMac::SubmitCompositorFrame on - // macOS, however it contains compositor resize logic that we don't want. - // Consequently we instead call the SwapDelegatedFrame method directly. - GetDelegatedFrameHost()->SubmitCompositorFrame( - local_surface_id, std::move(frame), std::move(hit_test_region_list)); - } else { - ui::Compositor* compositor = GetCompositor(); - if (!compositor) - return; - - // Will be nullptr if we're not using shared textures. - const void* shared_texture = compositor->GetSharedTexture(); - - // Determine the damage rectangle for the current frame. This is the - // same calculation that SwapDelegatedFrame uses. - viz::RenderPass* root_pass = frame.render_pass_list.back().get(); - gfx::Size frame_size = root_pass->output_rect.size(); - gfx::Rect damage_rect = - gfx::ToEnclosingRect(gfx::RectF(root_pass->damage_rect)); - damage_rect.Intersect(gfx::Rect(frame_size)); - - if (shared_texture) { - AddDamageRect(frame.metadata.begin_frame_ack.sequence_number, - damage_rect); - } - - // We would normally call BrowserCompositorMac::SubmitCompositorFrame on - // macOS, however it contains compositor resize logic that we don't - // want. Consequently we instead call the SwapDelegatedFrame method - // directly. - GetDelegatedFrameHost()->SubmitCompositorFrame( - local_surface_id, std::move(frame), std::move(hit_test_region_list)); - - if (!shared_texture) { - if (!copy_frame_generator_.get()) { - copy_frame_generator_.reset( - new CefCopyFrameGenerator(frame_rate_threshold_us_, this)); - } - - // Request a copy of the last compositor frame which will eventually - // call OnPaint asynchronously. - copy_frame_generator_->GenerateCopyFrame(damage_rect); - } - } - } + NOTREACHED(); } void CefRenderWidgetHostViewOSR::ClearCompositorFrame() { - // This method is only used for content rendering timeout when surface sync is - // off. NOTREACHED(); } @@ -806,7 +479,12 @@ void CefRenderWidgetHostViewOSR::InitAsPopup( if (handler.get()) handler->OnPopupSize(browser_impl_.get(), widget_pos); + if (video_consumer_) { + video_consumer_->SizeChanged(); + } + ResizeRootLayer(false); + Show(); } @@ -1113,23 +791,17 @@ void CefRenderWidgetHostViewOSR::SelectionChanged(const base::string16& text, cef_range); } -#if !defined(OS_MACOSX) const viz::LocalSurfaceIdAllocation& CefRenderWidgetHostViewOSR::GetLocalSurfaceIdAllocation() const { return local_surface_id_allocation_; } -#endif const viz::FrameSinkId& CefRenderWidgetHostViewOSR::GetFrameSinkId() const { return GetDelegatedFrameHost()->frame_sink_id(); } viz::FrameSinkId CefRenderWidgetHostViewOSR::GetRootFrameSinkId() { -#if defined(OS_MACOSX) - return browser_compositor_->GetRootFrameSinkId(); -#else return compositor_->frame_sink_id(); -#endif } std::unique_ptr @@ -1137,33 +809,10 @@ CefRenderWidgetHostViewOSR::CreateSyntheticGestureTarget() { return std::make_unique(host()); } -#if !defined(OS_MACOSX) -viz::ScopedSurfaceIdAllocator -CefRenderWidgetHostViewOSR::DidUpdateVisualProperties( - const cc::RenderFrameMetadata& metadata) { - bool force = - local_surface_id_allocation_ != metadata.local_surface_id_allocation; - base::OnceCallback allocation_task = - base::BindOnce(&CefRenderWidgetHostViewOSR::SynchronizeVisualProperties, - weak_ptr_factory_.GetWeakPtr(), force); - return viz::ScopedSurfaceIdAllocator(std::move(allocation_task)); -} -#endif - void CefRenderWidgetHostViewOSR::SetNeedsBeginFrames(bool enabled) { SetFrameRate(); - if (!external_begin_frame_enabled_) { - // Start/stop the timer that sends BeginFrame requests. - begin_frame_timer_->SetActive(enabled); - } - - if (software_output_device_) { - // When the SoftwareOutputDevice is active it will call OnPaint for each - // frame. If the SoftwareOutputDevice is deactivated while an invalidation - // region is pending it will call OnPaint immediately. - software_output_device_->SetActive(enabled); - } + host_display_client_->SetActive(enabled); } void CefRenderWidgetHostViewOSR::SetWantsAnimateOnlyBeginFrames() { @@ -1206,12 +855,8 @@ void CefRenderWidgetHostViewOSR::DidNavigate() { // With surface synchronization enabled we need to force synchronization on // first navigation. ResizeRootLayer(true); -#if defined(OS_MACOSX) - browser_compositor_->DidNavigate(); -#else if (delegated_frame_host_) delegated_frame_host_->DidNavigate(); -#endif } void CefRenderWidgetHostViewOSR::OnDisplayDidFinishFrame( @@ -1221,30 +866,24 @@ void CefRenderWidgetHostViewOSR::OnDisplayDidFinishFrame( void CefRenderWidgetHostViewOSR::OnNeedsExternalBeginFrames( bool needs_begin_frames) { + SetFrameRate(); needs_external_begin_frames_ = needs_begin_frames; } -std::unique_ptr -CefRenderWidgetHostViewOSR::CreateSoftwareOutputDevice( - ui::Compositor* compositor) { - DCHECK_EQ(GetCompositor(), compositor); - DCHECK(!copy_frame_generator_); - DCHECK(!software_output_device_); - software_output_device_ = new CefSoftwareOutputDeviceOSR( - compositor, background_color_ == SK_ColorTRANSPARENT, - base::Bind(&CefRenderWidgetHostViewOSR::OnPaint, - weak_ptr_factory_.GetWeakPtr())); - return base::WrapUnique(software_output_device_); +std::unique_ptr +CefRenderWidgetHostViewOSR::CreateHostDisplayClient() { + host_display_client_ = + new CefHostDisplayClientOSR(this, gfx::kNullAcceleratedWidget); + host_display_client_->SetActive(true); + return base::WrapUnique(host_display_client_); } bool CefRenderWidgetHostViewOSR::InstallTransparency() { if (background_color_ == SK_ColorTRANSPARENT) { SetBackgroundColor(background_color_); -#if defined(OS_MACOSX) - browser_compositor_->SetBackgroundColor(background_color_); -#else - compositor_->SetBackgroundColor(background_color_); -#endif + if (compositor_) { + compositor_->SetBackgroundColor(background_color_); + } return true; } return false; @@ -1274,16 +913,7 @@ void CefRenderWidgetHostViewOSR::OnScreenInfoChanged() { else render_widget_host_->SendScreenRects(); -#if defined(OS_MACOSX) - // RenderWidgetHostImpl will query BrowserCompositorMac for the dimensions - // to send to the renderer, so it is required that BrowserCompositorMac be - // updated first. Only notify RenderWidgetHostImpl of the update if any - // properties it will query have changed. - if (UpdateNSViewAndDisplay()) - render_widget_host_->NotifyScreenInfoChanged(); -#else render_widget_host_->NotifyScreenInfoChanged(); -#endif // We might want to change the cursor scale factor here as well - see the // cache for the current_cursor_, as passed by UpdateCursor from the @@ -1302,8 +932,7 @@ void CefRenderWidgetHostViewOSR::Invalidate( popup_host_view_->Invalidate(type); return; } - - InvalidateInternal(gfx::Rect(GetCompositorViewportPixelSize())); + InvalidateInternal(gfx::Rect(SizeInPixels())); } void CefRenderWidgetHostViewOSR::SendExternalBeginFrame() { @@ -1324,11 +953,8 @@ void CefRenderWidgetHostViewOSR::SendExternalBeginFrame() { if (render_widget_host_) render_widget_host_->ProgressFlingIfNeeded(frame_time); - if (renderer_compositor_frame_sink_) { - GetCompositor()->context_factory_private()->IssueExternalBeginFrame( - GetCompositor(), begin_frame_args); - renderer_compositor_frame_sink_->OnBeginFrame(begin_frame_args, {}); - } + GetCompositor()->context_factory_private()->IssueExternalBeginFrame( + GetCompositor(), begin_frame_args); if (!IsPopupWidget() && popup_host_view_) { popup_host_view_->SendExternalBeginFrame(); @@ -1653,12 +1279,28 @@ void CefRenderWidgetHostViewOSR::ReleaseResize() { } } +gfx::Size CefRenderWidgetHostViewOSR::SizeInPixels() { + return gfx::ConvertSizeToPixel(current_device_scale_factor_, + GetViewBounds().size()); +} + +#if defined(OS_MACOSX) +void CefRenderWidgetHostViewOSR::SetActive(bool active) {} + +void CefRenderWidgetHostViewOSR::ShowDefinitionForSelection() {} + +void CefRenderWidgetHostViewOSR::SpeakSelection() {} +#endif + void CefRenderWidgetHostViewOSR::OnPaint(const gfx::Rect& damage_rect, - int bitmap_width, - int bitmap_height, - void* bitmap_pixels) { + const gfx::Size& pixel_size, + const void* pixels) { TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::OnPaint"); + if (!pixels) { + return; + } + CefRefPtr handler = browser_impl_->client()->GetRenderHandler(); CHECK(handler); @@ -1667,21 +1309,19 @@ void CefRenderWidgetHostViewOSR::OnPaint(const gfx::Rect& damage_rect, // pending. HoldResize(); - gfx::Rect rect_in_bitmap(0, 0, bitmap_width, bitmap_height); - rect_in_bitmap.Intersect(damage_rect); + gfx::Rect rect_in_pixels(0, 0, pixel_size.width(), pixel_size.height()); + rect_in_pixels.Intersect(damage_rect); CefRenderHandler::RectList rcList; - rcList.push_back(CefRect(rect_in_bitmap.x(), rect_in_bitmap.y(), - rect_in_bitmap.width(), rect_in_bitmap.height())); + rcList.push_back(CefRect(rect_in_pixels.x(), rect_in_pixels.y(), + rect_in_pixels.width(), rect_in_pixels.height())); handler->OnPaint(browser_impl_.get(), IsPopupWidget() ? PET_POPUP : PET_VIEW, - rcList, bitmap_pixels, bitmap_width, bitmap_height); + rcList, pixels, pixel_size.width(), pixel_size.height()); ReleaseResize(); } -#if !defined(OS_MACOSX) - ui::Compositor* CefRenderWidgetHostViewOSR::GetCompositor() const { return compositor_.get(); } @@ -1695,8 +1335,6 @@ content::DelegatedFrameHost* CefRenderWidgetHostViewOSR::GetDelegatedFrameHost() return delegated_frame_host_.get(); } -#endif // !defined(OS_MACOSX) - void CefRenderWidgetHostViewOSR::SetFrameRate() { CefRefPtr browser; if (parent_host_view_) { @@ -1713,18 +1351,8 @@ void CefRenderWidgetHostViewOSR::SetFrameRate() { ui::Compositor* compositor = GetCompositor(); - int frame_rate; - if (compositor && compositor->shared_texture_enabled()) { - // No upper-bound when using OnAcceleratedPaint. - frame_rate = browser->settings().windowless_frame_rate; - if (frame_rate <= 0) { - frame_rate = 1; - } - sync_frame_rate_ = true; - } else { - frame_rate = - osr_util::ClampFrameRate(browser->settings().windowless_frame_rate); - } + int frame_rate = + osr_util::ClampFrameRate(browser->settings().windowless_frame_rate); frame_rate_threshold_us_ = 1000000 / frame_rate; @@ -1742,20 +1370,9 @@ void CefRenderWidgetHostViewOSR::SetFrameRate() { } #endif - if (copy_frame_generator_.get()) { - copy_frame_generator_->set_frame_rate_threshold_us( - frame_rate_threshold_us_); - } - - if (!external_begin_frame_enabled_) { - if (begin_frame_timer_.get()) { - begin_frame_timer_->SetFrameRateThresholdUs(frame_rate_threshold_us_); - } else { - begin_frame_timer_.reset(new CefBeginFrameTimer( - frame_rate_threshold_us_, - base::Bind(&CefRenderWidgetHostViewOSR::OnBeginFrameTimerTick, - weak_ptr_factory_.GetWeakPtr()))); - } + if (video_consumer_) { + video_consumer_->SetFrameRate( + base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_)); } } @@ -1806,9 +1423,6 @@ void CefRenderWidgetHostViewOSR::ResizeRootLayer(bool force) { GetRootLayer()->SetBounds(gfx::Rect(size)); -#if defined(OS_MACOSX) - bool resized = UpdateNSViewAndDisplay(); -#else const gfx::Size& size_in_pixels = gfx::ConvertSizeToPixel(current_device_scale_factor_, size); @@ -1817,59 +1431,22 @@ void CefRenderWidgetHostViewOSR::ResizeRootLayer(bool force) { local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation(); if (GetCompositor()) { + compositor_local_surface_id_allocator_.GenerateId(); GetCompositor()->SetScaleAndSize(current_device_scale_factor_, size_in_pixels, - local_surface_id_allocation_); + compositor_local_surface_id_allocator_ + .GetCurrentLocalSurfaceIdAllocation()); } - PlatformResizeCompositorWidget(size_in_pixels); - bool resized = true; GetDelegatedFrameHost()->EmbedSurface( local_surface_id_allocation_.local_surface_id(), size, cc::DeadlinePolicy::UseDefaultDeadline()); -#endif // !defined(OS_MACOSX) // Note that |render_widget_host_| will retrieve resize parameters from the // DelegatedFrameHost, so it must have SynchronizeVisualProperties called // after. - if (resized && render_widget_host_) - render_widget_host_->SynchronizeVisualProperties(); -} - -void CefRenderWidgetHostViewOSR::OnBeginFrameTimerTick() { - const base::TimeTicks frame_time = base::TimeTicks::Now(); - const base::TimeDelta vsync_period = - base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_); - SendBeginFrame(frame_time, vsync_period); -} - -void CefRenderWidgetHostViewOSR::SendBeginFrame(base::TimeTicks frame_time, - base::TimeDelta vsync_period) { - TRACE_EVENT1("cef", "CefRenderWidgetHostViewOSR::SendBeginFrame", - "frame_time_us", frame_time.ToInternalValue()); - - base::TimeTicks display_time = frame_time + vsync_period; - - // TODO(brianderson): Use adaptive draw-time estimation. - base::TimeDelta estimated_browser_composite_time = - base::TimeDelta::FromMicroseconds( - (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60)); - - base::TimeTicks deadline = display_time - estimated_browser_composite_time; - - const viz::BeginFrameArgs& begin_frame_args = viz::BeginFrameArgs::Create( - BEGINFRAME_FROM_HERE, begin_frame_source_.source_id(), - begin_frame_number_, frame_time, deadline, vsync_period, - viz::BeginFrameArgs::NORMAL); - DCHECK(begin_frame_args.IsValid()); - begin_frame_number_++; - if (render_widget_host_) - render_widget_host_->ProgressFlingIfNeeded(frame_time); - - if (renderer_compositor_frame_sink_) { - renderer_compositor_frame_sink_->OnBeginFrame(begin_frame_args, {}); - } + render_widget_host_->SynchronizeVisualProperties(); } void CefRenderWidgetHostViewOSR::CancelWidget() { @@ -1952,10 +1529,11 @@ void CefRenderWidgetHostViewOSR::OnGuestViewFrameSwapped( void CefRenderWidgetHostViewOSR::InvalidateInternal( const gfx::Rect& bounds_in_pixels) { - if (software_output_device_) { - software_output_device_->OnPaint(bounds_in_pixels); - } else if (copy_frame_generator_.get()) { - copy_frame_generator_->GenerateCopyFrame(bounds_in_pixels); + if (video_consumer_) { + video_consumer_->SizeChanged(); + } else { + OnPaint(bounds_in_pixels, host_display_client_->GetPixelSize(), + host_display_client_->GetPixelMemory()); } } @@ -1997,10 +1575,7 @@ viz::FrameSinkId CefRenderWidgetHostViewOSR::AllocateFrameSinkId( content::ImageTransportFactory::GetInstance(); return is_guest_view_hack ? factory->GetContextFactoryPrivate()->AllocateFrameSinkId() - : viz::FrameSinkId(base::checked_cast( - render_widget_host_->GetProcess()->GetID()), - base::checked_cast( - render_widget_host_->GetRoutingID())); + : render_widget_host_->GetFrameSinkId(); } void CefRenderWidgetHostViewOSR::UpdateBackgroundColorFromRenderer( diff --git a/libcef/browser/osr/render_widget_host_view_osr.h b/libcef/browser/osr/render_widget_host_view_osr.h index da1851d85..12cd6e854 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.h +++ b/libcef/browser/osr/render_widget_host_view_osr.h @@ -13,7 +13,8 @@ #include "include/cef_base.h" #include "include/cef_browser.h" -#include "libcef/browser/browser_host_impl.h" + +#include "libcef/browser/osr/host_display_client_osr.h" #include "libcef/browser/osr/motion_event_osr.h" #include "base/memory/weak_ptr.h" @@ -59,21 +60,12 @@ class BackingStore; class CursorManager; } // namespace content -class CefBeginFrameTimer; +class CefBrowserHostImpl; class CefCopyFrameGenerator; class CefSoftwareOutputDeviceOSR; +class CefVideoConsumerOSR; class CefWebContentsViewOSR; -#if defined(OS_MACOSX) -#ifdef __OBJC__ -@class CALayer; -@class NSWindow; -#else -class CALayer; -class NSWindow; -#endif -#endif - #if defined(USE_X11) class CefWindowX11; #endif @@ -172,8 +164,6 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, void GetScreenInfo(content::ScreenInfo* results) override; void TransformPointToRootSurface(gfx::PointF* point) override; gfx::Rect GetBoundsInRootWindow() override; - viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties( - const cc::RenderFrameMetadata& metadata) override; viz::SurfaceId GetCurrentSurfaceId() const override; content::BrowserAccessibilityManager* CreateBrowserAccessibilityManager( content::BrowserAccessibilityDelegate* delegate, @@ -202,13 +192,12 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, const viz::FrameSinkId& GetFrameSinkId() const override; viz::FrameSinkId GetRootFrameSinkId() override; - // ui::ExternalBeginFrameClient implementation: + // ui::ExternalBeginFrameClient implementation. void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) override; void OnNeedsExternalBeginFrames(bool needs_begin_frames) override; // ui::CompositorDelegate implementation. - std::unique_ptr CreateSoftwareOutputDevice( - ui::Compositor* compositor) override; + std::unique_ptr CreateHostDisplayClient() override; // TextInputManager::Observer implementation. void OnUpdateTextInputStateCalled( @@ -238,10 +227,12 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, void HoldResize(); void ReleaseResize(); + gfx::Size SizeInPixels(); void OnPaint(const gfx::Rect& damage_rect, - int bitmap_width, - int bitmap_height, - void* bitmap_pixels); + const gfx::Size& pixel_size, + const void* pixels); + + void OnBeginFame(base::TimeTicks frame_time); bool IsPopupWidget() const { return widget_type_ == content::WidgetType::kPopup; @@ -277,12 +268,6 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, } ui::Layer* GetRootLayer() const; -#if defined(OS_MACOSX) - content::BrowserCompositorMac* browser_compositor() const { - return browser_compositor_.get(); - } -#endif - void OnPresentCompositorFrame(); private: @@ -292,10 +277,6 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, void SetDeviceScaleFactor(); void ResizeRootLayer(bool force); - // Called by CefBeginFrameTimer to send a BeginFrame request. - void OnBeginFrameTimerTick(); - void SendBeginFrame(base::TimeTicks frame_time, base::TimeDelta vsync_period); - void CancelWidget(); void OnScrollOffsetChanged(); @@ -323,21 +304,6 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, // opaqueness changes. void UpdateBackgroundColorFromRenderer(SkColor color); -#if defined(OS_MACOSX) - display::Display GetDisplay(); - void OnDidUpdateVisualPropertiesComplete( - const cc::RenderFrameMetadata& metadata); - - friend class MacHelper; - bool UpdateNSViewAndDisplay(); -#endif // defined(OS_MACOSX) - - void PlatformCreateCompositorWidget(bool is_guest_view_hack); -#if !defined(OS_MACOSX) - void PlatformResizeCompositorWidget(const gfx::Size& size); -#endif - void PlatformDestroyCompositorWidget(); - #if defined(USE_AURA) ui::PlatformCursor GetPlatformCursor(blink::WebCursorInfo::Type type); #endif @@ -347,35 +313,21 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, int frame_rate_threshold_us_; -#if !defined(OS_MACOSX) std::unique_ptr compositor_; - gfx::AcceleratedWidget compositor_widget_; std::unique_ptr delegated_frame_host_; std::unique_ptr delegated_frame_host_client_; std::unique_ptr root_layer_; viz::LocalSurfaceIdAllocation local_surface_id_allocation_; viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_; -#endif + viz::ParentLocalSurfaceIdAllocator compositor_local_surface_id_allocator_; -#if defined(OS_WIN) - std::unique_ptr window_; -#elif defined(OS_MACOSX) - NSWindow* window_; - CALayer* background_layer_; - std::unique_ptr browser_compositor_; - MacHelper* mac_helper_; -#elif defined(USE_X11) - CefWindowX11* window_; +#if defined(USE_X11) std::unique_ptr invisible_cursor_; #endif std::unique_ptr cursor_manager_; - // Used to control the VSync rate in subprocesses when BeginFrame scheduling - // is enabled. - std::unique_ptr begin_frame_timer_; - // Provides |source_id| for BeginFrameArgs that we create. viz::StubBeginFrameSource begin_frame_source_; uint64_t begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber; @@ -384,12 +336,8 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, bool external_begin_frame_enabled_ = false; bool needs_external_begin_frames_ = false; - // Used for direct rendering from the compositor when GPU compositing is - // disabled. This object is owned by the compositor. - CefSoftwareOutputDeviceOSR* software_output_device_; - - // Used for managing copy requests when GPU compositing is enabled. - std::unique_ptr copy_frame_generator_; + CefHostDisplayClientOSR* host_display_client_; + std::unique_ptr video_consumer_; bool hold_resize_; bool pending_resize_; diff --git a/libcef/browser/osr/render_widget_host_view_osr_linux.cc b/libcef/browser/osr/render_widget_host_view_osr_linux.cc index b397364de..655be2200 100644 --- a/libcef/browser/osr/render_widget_host_view_osr_linux.cc +++ b/libcef/browser/osr/render_widget_host_view_osr_linux.cc @@ -169,26 +169,6 @@ XCursorCache* cursor_cache = nullptr; } // namespace #endif // defined(USE_X11) -void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget( - bool is_guest_view_hack) { -#if defined(USE_X11) - // Create a hidden 1x1 window. It will delete itself on close. - window_ = new CefWindowX11(NULL, None, gfx::Rect(0, 0, 1, 1), ""); - compositor_widget_ = window_->xwindow(); -#endif -} - -void CefRenderWidgetHostViewOSR::PlatformResizeCompositorWidget( - const gfx::Size&) {} - -void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() { -#if defined(USE_X11) - DCHECK(window_); - window_->Close(); -#endif - compositor_widget_ = gfx::kNullAcceleratedWidget; -} - ui::PlatformCursor CefRenderWidgetHostViewOSR::GetPlatformCursor( blink::WebCursorInfo::Type type) { #if defined(USE_X11) diff --git a/libcef/browser/osr/render_widget_host_view_osr_mac.mm b/libcef/browser/osr/render_widget_host_view_osr_mac.mm deleted file mode 100644 index 0c8fd4666..000000000 --- a/libcef/browser/osr/render_widget_host_view_osr_mac.mm +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. -// Portions copyright (c) 2012 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 "libcef/browser/osr/render_widget_host_view_osr.h" - -#include -#include -#include - -#import - -#include "libcef/browser/browser_host_impl.h" - -#include "base/compiler_specific.h" -#include "base/strings/utf_string_conversions.h" -#include "content/browser/renderer_host/render_widget_host_impl.h" -#include "content/common/view_messages.h" -#include "ui/accelerated_widget_mac/accelerated_widget_mac.h" -#include "ui/display/screen.h" - -class MacHelper : public content::BrowserCompositorMacClient, - public ui::AcceleratedWidgetMacNSView { - public: - explicit MacHelper(CefRenderWidgetHostViewOSR* view) : view_(view) {} - virtual ~MacHelper() {} - - // BrowserCompositorMacClient methods: - - SkColor BrowserCompositorMacGetGutterColor() const override { - // When making an element on the page fullscreen the element's background - // may not match the page's, so use black as the gutter color to avoid - // flashes of brighter colors during the transition. - if (view_->render_widget_host()->delegate() && - view_->render_widget_host()->delegate()->IsFullscreenForCurrentTab()) { - return SK_ColorBLACK; - } - return *view_->GetBackgroundColor(); - } - - void BrowserCompositorMacOnBeginFrame(base::TimeTicks frame_time) override {} - - void OnFrameTokenChanged(uint32_t frame_token) override { - view_->render_widget_host()->DidProcessFrame(frame_token); - } - - void DestroyCompositorForShutdown() override {} - - bool OnBrowserCompositorSurfaceIdChanged() override { - return view_->render_widget_host()->SynchronizeVisualProperties(); - } - - std::vector CollectSurfaceIdsForEviction() override { - return view_->render_widget_host()->CollectSurfaceIdsForEviction(); - } - - // AcceleratedWidgetMacNSView methods: - - void AcceleratedWidgetCALayerParamsUpdated() override {} - - private: - // Guaranteed to outlive this object. - CefRenderWidgetHostViewOSR* view_; - - DISALLOW_COPY_AND_ASSIGN(MacHelper); -}; - -void CefRenderWidgetHostViewOSR::SetActive(bool active) {} - -void CefRenderWidgetHostViewOSR::ShowDefinitionForSelection() {} - -void CefRenderWidgetHostViewOSR::SpeakSelection() {} - -viz::ScopedSurfaceIdAllocator -CefRenderWidgetHostViewOSR::DidUpdateVisualProperties( - const cc::RenderFrameMetadata& metadata) { - base::OnceCallback allocation_task = base::BindOnce( - base::IgnoreResult( - &CefRenderWidgetHostViewOSR::OnDidUpdateVisualPropertiesComplete), - weak_ptr_factory_.GetWeakPtr(), metadata); - return browser_compositor_->GetScopedRendererSurfaceIdAllocator( - std::move(allocation_task)); -} - -display::Display CefRenderWidgetHostViewOSR::GetDisplay() { - content::ScreenInfo screen_info; - GetScreenInfo(&screen_info); - - // Start with a reasonable display representation. - display::Display display = - display::Screen::GetScreen()->GetDisplayNearestView(nullptr); - - // Populate attributes based on |screen_info|. - display.set_bounds(screen_info.rect); - display.set_work_area(screen_info.available_rect); - display.set_device_scale_factor(screen_info.device_scale_factor); - display.set_color_space(screen_info.color_space); - display.set_color_depth(screen_info.depth); - display.set_depth_per_component(screen_info.depth_per_component); - display.set_is_monochrome(screen_info.is_monochrome); - display.SetRotationAsDegree(screen_info.orientation_angle); - - return display; -} - -void CefRenderWidgetHostViewOSR::OnDidUpdateVisualPropertiesComplete( - const cc::RenderFrameMetadata& metadata) { - DCHECK_EQ(current_device_scale_factor_, metadata.device_scale_factor); - browser_compositor_->UpdateSurfaceFromChild( - metadata.device_scale_factor, metadata.viewport_size_in_pixels, - metadata.local_surface_id_allocation.value_or( - viz::LocalSurfaceIdAllocation())); -} - -const viz::LocalSurfaceIdAllocation& -CefRenderWidgetHostViewOSR::GetLocalSurfaceIdAllocation() const { - return browser_compositor_->GetRendererLocalSurfaceIdAllocation(); -} - -ui::Compositor* CefRenderWidgetHostViewOSR::GetCompositor() const { - return browser_compositor_->GetCompositor(); -} - -ui::Layer* CefRenderWidgetHostViewOSR::GetRootLayer() const { - return browser_compositor_->GetRootLayer(); -} - -content::DelegatedFrameHost* CefRenderWidgetHostViewOSR::GetDelegatedFrameHost() - const { - return browser_compositor_->GetDelegatedFrameHost(); -} - -bool CefRenderWidgetHostViewOSR::UpdateNSViewAndDisplay() { - return browser_compositor_->UpdateSurfaceFromNSView( - GetRootLayer()->bounds().size(), GetDisplay()); -} - -void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget( - bool is_guest_view_hack) { - // Create a borderless non-visible 1x1 window. - window_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - - // Create a CALayer which is used by BrowserCompositorViewMac for rendering. - background_layer_ = [[[CALayer alloc] init] retain]; - [background_layer_ setBackgroundColor:CGColorGetConstantColor(kCGColorClear)]; - NSView* content_view = [window_ contentView]; - [content_view setLayer:background_layer_]; - [content_view setWantsLayer:YES]; - - mac_helper_ = new MacHelper(this); - browser_compositor_.reset(new content::BrowserCompositorMac( - mac_helper_, mac_helper_, render_widget_host_->is_hidden(), GetDisplay(), - AllocateFrameSinkId(is_guest_view_hack))); -} - -void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() { - DCHECK(window_); - - [window_ close]; - window_ = nil; - [background_layer_ release]; - background_layer_ = nil; - - browser_compositor_.reset(); - - delete mac_helper_; - mac_helper_ = nullptr; -} diff --git a/libcef/browser/osr/render_widget_host_view_osr_win.cc b/libcef/browser/osr/render_widget_host_view_osr_win.cc index 090f51527..48569030c 100644 --- a/libcef/browser/osr/render_widget_host_view_osr_win.cc +++ b/libcef/browser/osr/render_widget_host_view_osr_win.cc @@ -142,25 +142,6 @@ bool IsSystemCursorID(LPCWSTR cursor_id) { } // namespace -void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget( - bool is_guest_view_hack) { - DCHECK(!window_); - window_.reset(new CefCompositorHostWin()); - compositor_widget_ = window_->hwnd(); -} - -void CefRenderWidgetHostViewOSR::PlatformResizeCompositorWidget( - const gfx::Size& size) { - DCHECK(window_); - SetWindowPos(window_->hwnd(), NULL, 0, 0, size.width(), size.height(), - SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); -} - -void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() { - window_.reset(NULL); - compositor_widget_ = gfx::kNullAcceleratedWidget; -} - ui::PlatformCursor CefRenderWidgetHostViewOSR::GetPlatformCursor( blink::WebCursorInfo::Type type) { HMODULE module_handle = NULL; diff --git a/libcef/browser/osr/software_output_device_osr.cc b/libcef/browser/osr/software_output_device_osr.cc deleted file mode 100644 index 67d5eef30..000000000 --- a/libcef/browser/osr/software_output_device_osr.cc +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. -// Portions copyright (c) 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 "libcef/browser/osr/software_output_device_osr.h" - -#include "libcef/browser/browser_host_impl.h" -#include "libcef/browser/osr/render_widget_host_view_osr.h" -#include "libcef/browser/thread_util.h" - -#include "third_party/skia/src/core/SkDevice.h" -#include "ui/compositor/compositor.h" -#include "ui/gfx/skia_util.h" - -CefSoftwareOutputDeviceOSR::CefSoftwareOutputDeviceOSR( - ui::Compositor* compositor, - bool transparent, - const OnPaintCallback& callback) - : transparent_(transparent), callback_(callback), active_(false) { - CEF_REQUIRE_UIT(); - DCHECK(!callback_.is_null()); -} - -CefSoftwareOutputDeviceOSR::~CefSoftwareOutputDeviceOSR() { - CEF_REQUIRE_UIT(); -} - -void CefSoftwareOutputDeviceOSR::Resize(const gfx::Size& viewport_pixel_size, - float scale_factor) { - CEF_REQUIRE_UIT(); - - if (viewport_pixel_size_ == viewport_pixel_size) - return; - - viewport_pixel_size_ = viewport_pixel_size; - - canvas_.reset(NULL); - bitmap_.reset(new SkBitmap); - bitmap_->allocN32Pixels(viewport_pixel_size.width(), - viewport_pixel_size.height(), !transparent_); - if (bitmap_->drawsNothing()) { - NOTREACHED(); - bitmap_.reset(NULL); - return; - } - - if (transparent_) - bitmap_->eraseARGB(0, 0, 0, 0); - - canvas_.reset(new SkCanvas(*bitmap_.get())); -} - -SkCanvas* CefSoftwareOutputDeviceOSR::BeginPaint(const gfx::Rect& damage_rect) { - CEF_REQUIRE_UIT(); - DCHECK(canvas_.get()); - DCHECK(bitmap_.get()); - - damage_rect_ = damage_rect; - - return canvas_.get(); -} - -void CefSoftwareOutputDeviceOSR::EndPaint() { - CEF_REQUIRE_UIT(); - DCHECK(canvas_.get()); - DCHECK(bitmap_.get()); - - if (!bitmap_.get()) - return; - - viz::SoftwareOutputDevice::EndPaint(); - - if (active_) - OnPaint(damage_rect_); -} - -void CefSoftwareOutputDeviceOSR::SetActive(bool active) { - if (active == active_) - return; - active_ = active; - - // Call OnPaint immediately if deactivated while a damage rect is pending. - if (!active_ && !pending_damage_rect_.IsEmpty()) - OnPaint(pending_damage_rect_); -} - -void CefSoftwareOutputDeviceOSR::Invalidate(const gfx::Rect& damage_rect) { - if (pending_damage_rect_.IsEmpty()) - pending_damage_rect_ = damage_rect; - else - pending_damage_rect_.Union(damage_rect); -} - -void CefSoftwareOutputDeviceOSR::OnPaint(const gfx::Rect& damage_rect) { - gfx::Rect rect = damage_rect; - if (!pending_damage_rect_.IsEmpty()) { - rect.Union(pending_damage_rect_); - pending_damage_rect_.SetRect(0, 0, 0, 0); - } - - rect.Intersect(gfx::Rect(viewport_pixel_size_)); - if (rect.IsEmpty()) - return; - - callback_.Run(rect, bitmap_->width(), bitmap_->height(), - bitmap_->getPixels()); -} diff --git a/libcef/browser/osr/software_output_device_osr.h b/libcef/browser/osr/software_output_device_osr.h deleted file mode 100644 index cfcc6c58d..000000000 --- a/libcef/browser/osr/software_output_device_osr.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. -// Portions copyright (c) 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. - -#ifndef CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_OSR_H_ -#define CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_OSR_H_ - -#include "base/callback.h" -#include "components/viz/service/display/software_output_device.h" - -namespace ui { -class Compositor; -} - -// Device implementation for direct software rendering via DelegatedFrameHost. -// All Rect/Size values are in pixels. -class CefSoftwareOutputDeviceOSR : public viz::SoftwareOutputDevice { - public: - typedef base::Callback - OnPaintCallback; - - CefSoftwareOutputDeviceOSR(ui::Compositor* compositor, - bool transparent, - const OnPaintCallback& callback); - ~CefSoftwareOutputDeviceOSR() override; - - // viz::SoftwareOutputDevice implementation. - void Resize(const gfx::Size& viewport_pixel_size, - float scale_factor) override; - SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override; - void EndPaint() override; - - void SetActive(bool active); - - // Include |damage_rect| the next time OnPaint is called. - void Invalidate(const gfx::Rect& damage_rect); - - // Deliver the OnPaint notification immediately. - void OnPaint(const gfx::Rect& damage_rect); - - private: - const bool transparent_; - const OnPaintCallback callback_; - - bool active_; - std::unique_ptr canvas_; - std::unique_ptr bitmap_; - gfx::Rect pending_damage_rect_; - - DISALLOW_COPY_AND_ASSIGN(CefSoftwareOutputDeviceOSR); -}; - -#endif // CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_OSR_H_ diff --git a/libcef/browser/osr/software_output_device_proxy.cc b/libcef/browser/osr/software_output_device_proxy.cc new file mode 100644 index 000000000..60088a4ec --- /dev/null +++ b/libcef/browser/osr/software_output_device_proxy.cc @@ -0,0 +1,151 @@ +// 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.h" +#include "components/viz/common/resources/resource_sizes.h" +#include "mojo/public/cpp/base/shared_memory_utils.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 +#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; + } + +#if !defined(OS_WIN) + auto shm = mojo::CreateReadOnlySharedMemoryRegion(required_bytes); + if (!shm.IsValid()) { + DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes"; + return; + } + + shm_ = std::move(shm.mapping); + 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(shm_.memory()), skia::CRASH_ON_FAILURE); + + mojo::ScopedSharedBufferHandle scoped_handle = + mojo::WrapReadOnlySharedMemoryRegion(std::move(shm.region)); +#else + base::SharedMemory shm; + if (!shm.CreateAnonymous(required_bytes)) { + DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes"; + return; + } + canvas_ = skia::CreatePlatformCanvasWithSharedSection( + viewport_pixel_size_.width(), viewport_pixel_size_.height(), false, + shm.handle().GetHandle(), skia::CRASH_ON_FAILURE); + + // Transfer handle ownership to the browser process. + mojo::ScopedSharedBufferHandle scoped_handle = mojo::WrapSharedMemoryHandle( + shm.GetReadOnlyHandle(), required_bytes, + mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly); +#endif + + layered_window_updater_->OnAllocatedSharedMemory(viewport_pixel_size_, + std::move(scoped_handle)); +} + +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 diff --git a/libcef/browser/osr/software_output_device_proxy.h b/libcef/browser/osr/software_output_device_proxy.h new file mode 100644 index 000000000..0eede5bb6 --- /dev/null +++ b/libcef/browser/osr/software_output_device_proxy.h @@ -0,0 +1,52 @@ +#ifndef CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_PROXY_H_ +#define CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_PROXY_H_ + +#include "base/memory/shared_memory_mapping.h" +#include "base/threading/thread_checker.h" +#include "components/viz/service/display/software_output_device.h" +#include "components/viz/service/viz_service_export.h" +#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h" +#include "services/viz/privileged/interfaces/compositing/layered_window_updater.mojom.h" + +namespace viz { + +// SoftwareOutputDevice implementation that draws indirectly. An +// implementation of mojom::LayeredWindowUpdater in the browser process +// handles the actual drawing. Pixel backing is in SharedMemory so no copying +// between processes is required. +class VIZ_SERVICE_EXPORT SoftwareOutputDeviceProxy + : public SoftwareOutputDevice { + public: + explicit SoftwareOutputDeviceProxy( + mojom::LayeredWindowUpdaterPtr layered_window_updater); + ~SoftwareOutputDeviceProxy() override; + + // SoftwareOutputDevice implementation. + void OnSwapBuffers(SwapBuffersCallback swap_ack_callback) override; + + // SoftwareOutputDeviceBase implementation. + void Resize(const gfx::Size& viewport_pixel_size, + float scale_factor) override; + SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override; + void EndPaint() override; + + private: + // Runs |swap_ack_callback_| after draw has happened. + void DrawAck(); + + mojom::LayeredWindowUpdaterPtr layered_window_updater_; + + std::unique_ptr canvas_; + bool waiting_on_draw_ack_ = false; + bool in_paint_ = false; + base::OnceClosure swap_ack_callback_; + base::WritableSharedMemoryMapping shm_; + + THREAD_CHECKER(thread_checker_); + + DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceProxy); +}; + +} // namespace viz + +#endif // CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_PROXY_H_ \ No newline at end of file diff --git a/libcef/browser/osr/video_consumer_osr.cc b/libcef/browser/osr/video_consumer_osr.cc new file mode 100644 index 000000000..ea7961516 --- /dev/null +++ b/libcef/browser/osr/video_consumer_osr.cc @@ -0,0 +1,89 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "libcef/browser/osr/video_consumer_osr.h" + +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/osr/render_widget_host_view_osr.h" + +#include "media/base/video_frame_metadata.h" +#include "media/capture/mojom/video_capture_types.mojom.h" +#include "ui/gfx/skbitmap_operations.h" + +CefVideoConsumerOSR::CefVideoConsumerOSR(CefRenderWidgetHostViewOSR* view) + : view_(view), + video_capturer_(view->CreateVideoCapturer()), + weak_ptr_factory_(this) { + const gfx::Size view_size = view_->SizeInPixels(); + video_capturer_->SetResolutionConstraints(view_size, view_size, true); + video_capturer_->SetAutoThrottlingEnabled(false); + video_capturer_->SetMinSizeChangePeriod(base::TimeDelta()); + video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB, + gfx::ColorSpace::CreateREC709()); +} + +CefVideoConsumerOSR::~CefVideoConsumerOSR() = default; + +void CefVideoConsumerOSR::SetActive(bool active) { + if (active) { + video_capturer_->Start(this); + } else { + video_capturer_->Stop(); + } +} + +void CefVideoConsumerOSR::SetFrameRate(base::TimeDelta frame_rate) { + video_capturer_->SetMinCapturePeriod(frame_rate); +} + +void CefVideoConsumerOSR::SizeChanged() { + const gfx::Size view_size = view_->SizeInPixels(); + video_capturer_->SetResolutionConstraints(view_size, view_size, true); + video_capturer_->RequestRefreshFrame(); +} + +void CefVideoConsumerOSR::OnFrameCaptured( + base::ReadOnlySharedMemoryRegion data, + ::media::mojom::VideoFrameInfoPtr info, + const gfx::Rect& content_rect, + viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) { + const gfx::Size view_size = view_->SizeInPixels(); + if (view_size != content_rect.size()) { + video_capturer_->SetResolutionConstraints(view_size, view_size, true); + video_capturer_->RequestRefreshFrame(); + return; + } + + if (!data.IsValid()) { + callbacks->Done(); + return; + } + base::ReadOnlySharedMemoryMapping mapping = data.Map(); + if (!mapping.IsValid()) { + DLOG(ERROR) << "Shared memory mapping failed."; + return; + } + if (mapping.size() < + media::VideoFrame::AllocationSize(info->pixel_format, info->coded_size)) { + DLOG(ERROR) << "Shared memory size was less than expected."; + return; + } + + // The SkBitmap's pixels will be marked as immutable, but the installPixels() + // API requires a non-const pointer. So, cast away the const. + void* const pixels = const_cast(mapping.memory()); + + media::VideoFrameMetadata metadata; + metadata.MergeInternalValuesFrom(info->metadata); + gfx::Rect damage_rect; + + if (!metadata.GetRect(media::VideoFrameMetadata::CAPTURE_UPDATE_RECT, + &damage_rect)) { + damage_rect = content_rect; + } + + view_->OnPaint(damage_rect, content_rect.size(), pixels); +} + +void CefVideoConsumerOSR::OnStopped() {} diff --git a/libcef/browser/osr/video_consumer_osr.h b/libcef/browser/osr/video_consumer_osr.h new file mode 100644 index 000000000..643a27c99 --- /dev/null +++ b/libcef/browser/osr/video_consumer_osr.h @@ -0,0 +1,36 @@ +#ifndef LIBCEF_BROWSER_OSR_VIDEO_CONSUMER_OSR_H_ +#define LIBCEF_BROWSER_OSR_VIDEO_CONSUMER_OSR_H_ + +#include "base/callback.h" +#include "base/memory/weak_ptr.h" +#include "components/viz/host/client_frame_sink_video_capturer.h" + +class CefRenderWidgetHostViewOSR; + +class CefVideoConsumerOSR : public viz::mojom::FrameSinkVideoConsumer { + public: + explicit CefVideoConsumerOSR(CefRenderWidgetHostViewOSR* view); + ~CefVideoConsumerOSR() override; + + void SetActive(bool active); + void SetFrameRate(base::TimeDelta frame_rate); + void SizeChanged(); + + private: + // viz::mojom::FrameSinkVideoConsumer implementation. + void OnFrameCaptured( + base::ReadOnlySharedMemoryRegion data, + ::media::mojom::VideoFrameInfoPtr info, + const gfx::Rect& content_rect, + viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) override; + void OnStopped() override; + + CefRenderWidgetHostViewOSR* const view_; + std::unique_ptr video_capturer_; + + base::WeakPtrFactory weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(CefVideoConsumerOSR); +}; + +#endif // LIBCEF_BROWSER_OSR_VIDEO_CONSUMER_OSR_H_ \ No newline at end of file diff --git a/libcef/common/main_delegate.cc b/libcef/common/main_delegate.cc index 5504ef95f..66385800b 100644 --- a/libcef/common/main_delegate.cc +++ b/libcef/common/main_delegate.cc @@ -558,15 +558,6 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) { std::vector disable_features; - if (settings.windowless_rendering_enabled) { - // Disable VizDisplayCompositor when OSR is enabled until - // we have implemented Viz support - if (features::kVizDisplayCompositor.default_state == - base::FEATURE_ENABLED_BY_DEFAULT) { - disable_features.push_back(features::kVizDisplayCompositor.name); - } - } - if (network::features::kOutOfBlinkCors.default_state == base::FEATURE_ENABLED_BY_DEFAULT) { // TODO: Add support for out-of-Blink CORS (see issue #2716) diff --git a/patch/patch.cfg b/patch/patch.cfg index 1e45a4df9..6b465daf2 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -383,11 +383,6 @@ patches = [ # https://bitbucket.org/chromiumembedded/cef/issues/2540 'name': 'mac_fling_scheduler_2540', }, - { - # Support rendering to a hardware GL/D3D texture/surface provided by the client - # https://bitbucket.org/chromiumembedded/cef/issues/1006 - 'name': 'external_textures_1006', - }, { # Linux: Use poll instead of select to fix crash during startup. # https://bitbucket.org/chromiumembedded/cef/issues/2466 @@ -460,5 +455,10 @@ patches = [ # Shutdown for all Profiles before local_state deletion. # This crash was introduced by https://crrev.com/7d032b378c. 'name': 'chrome_pref_watcher', - } + }, + { + # Add support for OSR rendering with Viz. + # https://bitbucket.org/chromiumembedded/cef/issues/2575 + 'name': 'viz_osr_2575', + } ] diff --git a/patch/patches/external_textures_1006.patch b/patch/patches/external_textures_1006.patch deleted file mode 100644 index be50f4196..000000000 --- a/patch/patches/external_textures_1006.patch +++ /dev/null @@ -1,1337 +0,0 @@ -diff --git content/browser/compositor/browser_compositor_output_surface.cc content/browser/compositor/browser_compositor_output_surface.cc -index 79b2ae7b6fef..7c0e65975c14 100644 ---- content/browser/compositor/browser_compositor_output_surface.cc -+++ content/browser/compositor/browser_compositor_output_surface.cc -@@ -41,6 +41,10 @@ void BrowserCompositorOutputSurface::SetReflector(ReflectorImpl* reflector) { - OnReflectorChanged(); - } - -+void* BrowserCompositorOutputSurface::GetSharedTexture() const { -+ return nullptr; -+} -+ - void BrowserCompositorOutputSurface::OnReflectorChanged() { - } - -diff --git content/browser/compositor/browser_compositor_output_surface.h content/browser/compositor/browser_compositor_output_surface.h -index c91aedd16481..1a92c5effd11 100644 ---- content/browser/compositor/browser_compositor_output_surface.h -+++ content/browser/compositor/browser_compositor_output_surface.h -@@ -43,6 +43,8 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface - - void SetReflector(ReflectorImpl* reflector); - -+ virtual void* GetSharedTexture() const; -+ - // Called when |reflector_| was updated. - virtual void OnReflectorChanged(); - -diff --git content/browser/compositor/gpu_process_transport_factory.cc content/browser/compositor/gpu_process_transport_factory.cc -index 7e3574cb69fa..df9a00d1ae53 100644 ---- content/browser/compositor/gpu_process_transport_factory.cc -+++ content/browser/compositor/gpu_process_transport_factory.cc -@@ -216,6 +216,18 @@ GpuProcessTransportFactory::~GpuProcessTransportFactory() { - task_graph_runner_->Shutdown(); - } - -+void* GpuProcessTransportFactory::GetSharedTexture(ui::Compositor* compositor) { -+ PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor); -+ if (it == per_compositor_data_.end()) -+ return nullptr; -+ PerCompositorData* data = it->second.get(); -+ DCHECK(data); -+ -+ if (data->display_output_surface) -+ return data->display_output_surface->GetSharedTexture(); -+ return nullptr; -+} -+ - std::unique_ptr - GpuProcessTransportFactory::CreateSoftwareOutputDevice( - gfx::AcceleratedWidget widget, -@@ -243,7 +255,7 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice( - #endif - } - --std::unique_ptr CreateOverlayCandidateValidator( -+std::unique_ptr OverlayCandidateValidator( - gfx::AcceleratedWidget widget) { - std::unique_ptr validator; - #if defined(USE_OZONE) -@@ -419,10 +431,20 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( - // surfaces as they are not following the correct mode. - DisableGpuCompositing(compositor.get()); - } -+ -+ std::unique_ptr output_device; -+ if (compositor->delegate()) { -+ output_device = compositor->delegate()->CreateSoftwareOutputDevice( -+ compositor.get()); -+ } -+ if (!output_device) { -+ output_device = CreateSoftwareOutputDevice(compositor->widget(), -+ compositor->task_runner()); -+ } -+ - display_output_surface = - std::make_unique( -- CreateSoftwareOutputDevice(compositor->widget(), -- compositor->task_runner())); -+ CreateSoftwareOutputDevice(compositor->widget(), compositor->task_runner())); - } else { - DCHECK(context_provider); - const auto& capabilities = context_provider->ContextCapabilities(); -@@ -430,10 +452,11 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( - display_output_surface = - std::make_unique( - context_provider, -- std::unique_ptr()); -+ std::unique_ptr(), -+ compositor->shared_texture_enabled()); - } else if (capabilities.surfaceless) { - DCHECK(capabilities.texture_format_bgra8888); -- auto validator = CreateOverlayCandidateValidator(compositor->widget()); -+ auto validator = OverlayCandidateValidator(compositor->widget()); - overlay_validator = validator.get(); - auto gpu_output_surface = - std::make_unique( -@@ -443,7 +466,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( - display_output_surface = std::move(gpu_output_surface); - } else { - std::unique_ptr validator = -- CreateOverlayCandidateValidator(compositor->widget()); -+ OverlayCandidateValidator(compositor->widget()); - overlay_validator = validator.get(); - auto gpu_output_surface = - std::make_unique( -@@ -881,7 +904,8 @@ GpuProcessTransportFactory::CreatePerCompositorData( - gfx::AcceleratedWidget widget = compositor->widget(); - - auto data = std::make_unique(); -- if (widget == gfx::kNullAcceleratedWidget) { -+ if (widget == gfx::kNullAcceleratedWidget || -+ compositor->shared_texture_enabled()) { - data->surface_handle = gpu::kNullSurfaceHandle; - } else { - #if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) -diff --git content/browser/compositor/gpu_process_transport_factory.h content/browser/compositor/gpu_process_transport_factory.h -index 4a78bdea7ded..6cfe36fc7e5c 100644 ---- content/browser/compositor/gpu_process_transport_factory.h -+++ content/browser/compositor/gpu_process_transport_factory.h -@@ -100,6 +100,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory, - void IssueExternalBeginFrame(ui::Compositor* compositor, - const viz::BeginFrameArgs& args) override; - void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override; -+ void* GetSharedTexture(ui::Compositor* compositor) override; - void AddVSyncParameterObserver( - ui::Compositor* compositor, - viz::mojom::VSyncParameterObserverPtr observer) override; -diff --git content/browser/compositor/offscreen_browser_compositor_output_surface.cc content/browser/compositor/offscreen_browser_compositor_output_surface.cc -index c38198dfe820..d6edf48c14b1 100644 ---- content/browser/compositor/offscreen_browser_compositor_output_surface.cc -+++ content/browser/compositor/offscreen_browser_compositor_output_surface.cc -@@ -33,9 +33,11 @@ OffscreenBrowserCompositorOutputSurface:: - OffscreenBrowserCompositorOutputSurface( - scoped_refptr context, - std::unique_ptr -- overlay_candidate_validator) -+ overlay_candidate_validator, -+ bool shared_texture_enabled) - : BrowserCompositorOutputSurface(std::move(context), - std::move(overlay_candidate_validator)), -+ shared_texture_enabled_(shared_texture_enabled), - weak_ptr_factory_(this) { - capabilities_.uses_default_gl_framebuffer = false; - } -@@ -45,6 +47,10 @@ OffscreenBrowserCompositorOutputSurface:: - DiscardBackbuffer(); - } - -+void* OffscreenBrowserCompositorOutputSurface::GetSharedTexture() const { -+ return (void*)shared_handle_; -+} -+ - void OffscreenBrowserCompositorOutputSurface::BindToClient( - viz::OutputSurfaceClient* client) { - DCHECK(client); -@@ -53,42 +59,72 @@ void OffscreenBrowserCompositorOutputSurface::BindToClient( - } - - void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() { -- bool update_source_texture = !reflector_texture_ || reflector_changed_; -- reflector_changed_ = false; -- if (!reflector_texture_) { -- reflector_texture_.reset(new ReflectorTexture(context_provider())); -- -- GLES2Interface* gl = context_provider_->ContextGL(); -- -- const int max_texture_size = -- context_provider_->ContextCapabilities().max_texture_size; -- int texture_width = std::min(max_texture_size, reshape_size_.width()); -- int texture_height = std::min(max_texture_size, reshape_size_.height()); -- -- gl->BindTexture(GL_TEXTURE_2D, reflector_texture_->texture_id()); -- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -- gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(kFboTextureFormat), -- texture_width, texture_height, 0, -- GLDataFormat(kFboTextureFormat), -- GLDataType(kFboTextureFormat), nullptr); -+ GLES2Interface* gl = context_provider_->ContextGL(); -+ -+ const int max_texture_size = -+ context_provider_->ContextCapabilities().max_texture_size; -+ int texture_width = std::min(max_texture_size, reshape_size_.width()); -+ int texture_height = std::min(max_texture_size, reshape_size_.height()); -+ -+ GLuint color_attachment = 0; -+ -+ if (shared_texture_enabled_) { -+ if (!shared_handle_ && (texture_width > 0) && (texture_height > 0)) { -+ gl->GenTextures(1, &shared_texture_); -+ gl->BindTexture(GL_TEXTURE_2D, shared_texture_); -+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -+ shared_handle_ = gl->CreateSharedTexture(shared_texture_, texture_width, -+ texture_height); -+ -+ if (shared_handle_) { -+ color_attachment = shared_texture_; -+ } else { -+ gl->DeleteTextures(1, &shared_texture_); -+ shared_texture_ = 0; -+ } -+ } -+ } else { -+ // The shared texture code above in theory could work with the reflector -+ // texture However, there were issues making associating it a shared surface -+ // and then attaching it to the FBO (incomplete?) -+ bool update_source_texture = !reflector_texture_ || reflector_changed_; -+ reflector_changed_ = false; -+ if (!reflector_texture_) { -+ reflector_texture_.reset(new ReflectorTexture(context_provider())); -+ -+ gl->BindTexture(GL_TEXTURE_2D, reflector_texture_->texture_id()); -+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -+ gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(kFboTextureFormat), -+ texture_width, texture_height, 0, -+ GLDataFormat(kFboTextureFormat), -+ GLDataType(kFboTextureFormat), nullptr); -+ -+ color_attachment = reflector_texture_->texture_id(); -+ -+ // The reflector may be created later or detached and re-attached, -+ // so don't assume it always exists. For example, ChromeOS always -+ // creates a reflector asynchronosly when creating this for software -+ // mirroring. See |DisplayManager::CreateMirrorWindowAsyncIfAny|. -+ if (reflector_ && update_source_texture) -+ reflector_->OnSourceTextureMailboxUpdated( -+ reflector_texture_->mailbox()); -+ } -+ } -+ -+ if (color_attachment) { - if (!fbo_) - gl->GenFramebuffers(1, &fbo_); - - gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); - gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, -- GL_TEXTURE_2D, reflector_texture_->texture_id(), -- 0); -+ GL_TEXTURE_2D, color_attachment, 0); - } -- -- // The reflector may be created later or detached and re-attached, -- // so don't assume it always exists. For example, ChromeOS always -- // creates a reflector asynchronosly when creating this for software -- // mirroring. See |DisplayManager::CreateMirrorWindowAsyncIfAny|. -- if (reflector_ && update_source_texture) -- reflector_->OnSourceTextureMailboxUpdated(reflector_texture_->mailbox()); - } - - void OffscreenBrowserCompositorOutputSurface::DiscardBackbuffer() { -@@ -100,6 +136,16 @@ void OffscreenBrowserCompositorOutputSurface::DiscardBackbuffer() { - reflector_->OnSourceTextureMailboxUpdated(nullptr); - } - -+ if (shared_handle_) { -+ gl->DeleteSharedTexture(shared_handle_); -+ shared_handle_ = 0ull; -+ } -+ -+ if (shared_texture_) { -+ gl->DeleteTextures(1, &shared_texture_); -+ shared_texture_ = 0; -+ } -+ - if (fbo_) { - gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); - gl->DeleteFramebuffers(1, &fbo_); -@@ -122,15 +168,20 @@ void OffscreenBrowserCompositorOutputSurface::Reshape( - } - - void OffscreenBrowserCompositorOutputSurface::BindFramebuffer() { -- bool need_to_bind = !!reflector_texture_.get(); -+ GLES2Interface* gl = context_provider_->ContextGL(); - -+ bool need_to_bind = !!reflector_texture_.get(); - EnsureBackbuffer(); -- DCHECK(reflector_texture_.get()); - DCHECK(fbo_); - -- if (need_to_bind) { -- GLES2Interface* gl = context_provider_->ContextGL(); -+ if (shared_handle_) { - gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); -+ gl->LockSharedTexture(shared_handle_); -+ } else { -+ DCHECK(reflector_texture_.get()); -+ if (need_to_bind) { -+ gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); -+ } - } - } - -@@ -151,6 +202,12 @@ void OffscreenBrowserCompositorOutputSurface::SwapBuffers( - // The original implementation had a flickering issue (crbug.com/515332). - gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); - -+ // If using a shared texture we need to Flush. -+ if (shared_handle_) { -+ gl->UnlockSharedTexture(shared_handle_); -+ gl->Flush(); -+ } -+ - gpu::SyncToken sync_token; - gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); - context_provider_->ContextSupport()->SignalSyncToken( -@@ -190,7 +247,9 @@ void OffscreenBrowserCompositorOutputSurface::OnSwapBuffersComplete( - const std::vector& latency_info) { - latency_tracker_.OnGpuSwapBuffersCompleted(latency_info); - client_->DidReceiveSwapBuffersAck(); -- client_->DidReceivePresentationFeedback(gfx::PresentationFeedback()); -+ gfx::PresentationFeedback feedback; -+ feedback.timestamp = base::TimeTicks::Now(); -+ client_->DidReceivePresentationFeedback(feedback); - } - - unsigned OffscreenBrowserCompositorOutputSurface::UpdateGpuFence() { -diff --git content/browser/compositor/offscreen_browser_compositor_output_surface.h content/browser/compositor/offscreen_browser_compositor_output_surface.h -index 9756ca6f5bc3..c470746b5b93 100644 ---- content/browser/compositor/offscreen_browser_compositor_output_surface.h -+++ content/browser/compositor/offscreen_browser_compositor_output_surface.h -@@ -30,7 +30,8 @@ class OffscreenBrowserCompositorOutputSurface - OffscreenBrowserCompositorOutputSurface( - scoped_refptr context, - std::unique_ptr -- overlay_candidate_validator); -+ overlay_candidate_validator, -+ bool shared_texture_enabled); - - ~OffscreenBrowserCompositorOutputSurface() override; - -@@ -52,11 +53,15 @@ class OffscreenBrowserCompositorOutputSurface - gfx::BufferFormat GetOverlayBufferFormat() const override; - uint32_t GetFramebufferCopyTextureFormat() override; - -+ void* GetSharedTexture() const override; -+ - // BrowserCompositorOutputSurface implementation. - void OnReflectorChanged() override; - - unsigned UpdateGpuFence() override; - -+ void NotifyRenderHost(const std::vector& latency_info); -+ - void OnSwapBuffersComplete(const std::vector& latency_info); - - viz::OutputSurfaceClient* client_ = nullptr; -@@ -64,6 +69,11 @@ class OffscreenBrowserCompositorOutputSurface - uint32_t fbo_ = 0; - bool reflector_changed_ = false; - std::unique_ptr reflector_texture_; -+ -+ bool shared_texture_enabled_ = false; -+ uint64_t shared_handle_ = 0ull; -+ uint32_t shared_texture_ = 0; -+ - ui::LatencyTracker latency_tracker_; - base::WeakPtrFactory - weak_ptr_factory_; -diff --git gpu/GLES2/gl2chromium_autogen.h gpu/GLES2/gl2chromium_autogen.h -index 052b441e020d..9c3044185400 100644 ---- gpu/GLES2/gl2chromium_autogen.h -+++ gpu/GLES2/gl2chromium_autogen.h -@@ -411,6 +411,10 @@ - GLES2_GET_FUN(CreateClientGpuFenceCHROMIUM) - #define glWaitGpuFenceCHROMIUM GLES2_GET_FUN(WaitGpuFenceCHROMIUM) - #define glDestroyGpuFenceCHROMIUM GLES2_GET_FUN(DestroyGpuFenceCHROMIUM) -+#define glCreateSharedTexture GLES2_GET_FUN(CreateSharedTexture) -+#define glLockSharedTexture GLES2_GET_FUN(LockSharedTexture) -+#define glUnlockSharedTexture GLES2_GET_FUN(UnlockSharedTexture) -+#define glDeleteSharedTexture GLES2_GET_FUN(DeleteSharedTexture) - #define glInvalidateReadbackBufferShadowDataCHROMIUM \ - GLES2_GET_FUN(InvalidateReadbackBufferShadowDataCHROMIUM) - #define glFramebufferTextureMultiviewOVR \ -diff --git gpu/command_buffer/build_gles2_cmd_buffer.py gpu/command_buffer/build_gles2_cmd_buffer.py -index e830f36dcb81..9e647f3bbd54 100755 ---- gpu/command_buffer/build_gles2_cmd_buffer.py -+++ gpu/command_buffer/build_gles2_cmd_buffer.py -@@ -4228,6 +4228,35 @@ _FUNCTION_INFO = { - 'extension': 'CHROMIUM_gpu_fence', - 'extension_flag': 'chromium_gpu_fence', - }, -+ 'CreateSharedTexture': { -+ 'type': 'Custom', -+ 'data_transfer_methods': ['shm'], -+ 'cmd_args': 'GLint texture_id, GLint width, ' -+ 'GLint height, GLuint64* result', -+ 'result': ['GLuint64'], -+ 'unit_test': False, -+ 'impl_func': False, -+ 'client_test': False, -+ 'extension': True, -+ }, -+ 'LockSharedTexture': { -+ 'type': 'Custom', -+ 'unit_test': False, -+ 'client_test': False, -+ 'extension': True, -+ }, -+ 'UnlockSharedTexture': { -+ 'type': 'Custom', -+ 'unit_test': False, -+ 'client_test': False, -+ 'extension': True, -+ }, -+ 'DeleteSharedTexture': { -+ 'type': 'Custom', -+ 'unit_test': False, -+ 'client_test': False, -+ 'extension': True, -+ }, - 'UnpremultiplyAndDitherCopyCHROMIUM': { - 'decoder_func': 'DoUnpremultiplyAndDitherCopyCHROMIUM', - 'cmd_args': 'GLuint source_id, GLuint dest_id, GLint x, GLint y, ' -diff --git gpu/command_buffer/client/gles2_c_lib_autogen.h gpu/command_buffer/client/gles2_c_lib_autogen.h -index 1772133baf4d..601301cad308 100644 ---- gpu/command_buffer/client/gles2_c_lib_autogen.h -+++ gpu/command_buffer/client/gles2_c_lib_autogen.h -@@ -1896,6 +1896,20 @@ void GL_APIENTRY GLES2WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) { - void GL_APIENTRY GLES2DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) { - gles2::GetGLContext()->DestroyGpuFenceCHROMIUM(gpu_fence_id); - } -+GLuint64 GL_APIENTRY GLES2CreateSharedTexture(GLuint texture_id, -+ GLsizei width, -+ GLsizei height) { -+ return gles2::GetGLContext()->CreateSharedTexture(texture_id, width, height); -+} -+void GL_APIENTRY GLES2LockSharedTexture(GLuint64 shared_handle) { -+ gles2::GetGLContext()->LockSharedTexture(shared_handle); -+} -+void GL_APIENTRY GLES2UnlockSharedTexture(GLuint64 shared_handle) { -+ gles2::GetGLContext()->UnlockSharedTexture(shared_handle); -+} -+void GL_APIENTRY GLES2DeleteSharedTexture(GLuint64 shared_handle) { -+ gles2::GetGLContext()->DeleteSharedTexture(shared_handle); -+} - void GL_APIENTRY - GLES2InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) { - gles2::GetGLContext()->InvalidateReadbackBufferShadowDataCHROMIUM(buffer_id); -@@ -3403,6 +3417,22 @@ extern const NameToFunc g_gles2_function_table[] = { - "glDestroyGpuFenceCHROMIUM", - reinterpret_cast(glDestroyGpuFenceCHROMIUM), - }, -+ { -+ "glCreateSharedTexture", -+ reinterpret_cast(glCreateSharedTexture), -+ }, -+ { -+ "glLockSharedTexture", -+ reinterpret_cast(glLockSharedTexture), -+ }, -+ { -+ "glUnlockSharedTexture", -+ reinterpret_cast(glUnlockSharedTexture), -+ }, -+ { -+ "glDeleteSharedTexture", -+ reinterpret_cast(glDeleteSharedTexture), -+ }, - { - "glInvalidateReadbackBufferShadowDataCHROMIUM", - reinterpret_cast( -diff --git gpu/command_buffer/client/gles2_cmd_helper_autogen.h gpu/command_buffer/client/gles2_cmd_helper_autogen.h -index dbe1d6080d28..6902055b7c70 100644 ---- gpu/command_buffer/client/gles2_cmd_helper_autogen.h -+++ gpu/command_buffer/client/gles2_cmd_helper_autogen.h -@@ -3513,6 +3513,42 @@ void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) { - } - } - -+void CreateSharedTexture(GLint texture_id, -+ GLint width, -+ GLint height, -+ uint32_t result_shm_id, -+ uint32_t result_shm_offset) { -+ gles2::cmds::CreateSharedTexture* c = -+ GetCmdSpace(); -+ if (c) { -+ c->Init(texture_id, width, height, result_shm_id, result_shm_offset); -+ } -+} -+ -+void LockSharedTexture(GLuint64 shared_handle) { -+ gles2::cmds::LockSharedTexture* c = -+ GetCmdSpace(); -+ if (c) { -+ c->Init(shared_handle); -+ } -+} -+ -+void UnlockSharedTexture(GLuint64 shared_handle) { -+ gles2::cmds::UnlockSharedTexture* c = -+ GetCmdSpace(); -+ if (c) { -+ c->Init(shared_handle); -+ } -+} -+ -+void DeleteSharedTexture(GLuint64 shared_handle) { -+ gles2::cmds::DeleteSharedTexture* c = -+ GetCmdSpace(); -+ if (c) { -+ c->Init(shared_handle); -+ } -+} -+ - void SetReadbackBufferShadowAllocationINTERNAL(GLuint buffer_id, - GLint shm_id, - GLuint shm_offset, -diff --git gpu/command_buffer/client/gles2_implementation.cc gpu/command_buffer/client/gles2_implementation.cc -index 211bfd81a53c..26f65497638e 100644 ---- gpu/command_buffer/client/gles2_implementation.cc -+++ gpu/command_buffer/client/gles2_implementation.cc -@@ -7619,6 +7619,22 @@ void GLES2Implementation::Viewport(GLint x, - CheckGLError(); - } - -+GLuint64 GLES2Implementation::CreateSharedTexture(GLuint texture_id, -+ GLsizei width, -+ GLsizei height) { -+ typedef cmds::CreateSharedTexture::Result Result; -+ auto result = GetResultAs(); -+ if (!result) { -+ return 0; -+ } -+ *result = 0; -+ helper_->CreateSharedTexture(texture_id, width, height, GetResultShmId(), -+ result.offset()); -+ -+ WaitForCmd(); -+ return *result; -+} -+ - void GLES2Implementation::IssueBeginQuery(GLenum target, - GLuint id, - uint32_t sync_data_shm_id, -diff --git gpu/command_buffer/client/gles2_implementation_autogen.h gpu/command_buffer/client/gles2_implementation_autogen.h -index dd25fd00046a..cd02e794f801 100644 ---- gpu/command_buffer/client/gles2_implementation_autogen.h -+++ gpu/command_buffer/client/gles2_implementation_autogen.h -@@ -1337,6 +1337,16 @@ void WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) override; - - void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) override; - -+GLuint64 CreateSharedTexture(GLuint texture_id, -+ GLsizei width, -+ GLsizei height) override; -+ -+void LockSharedTexture(GLuint64 shared_handle) override; -+ -+void UnlockSharedTexture(GLuint64 shared_handle) override; -+ -+void DeleteSharedTexture(GLuint64 shared_handle) override; -+ - void InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) override; - - void FramebufferTextureMultiviewOVR(GLenum target, -diff --git gpu/command_buffer/client/gles2_implementation_impl_autogen.h gpu/command_buffer/client/gles2_implementation_impl_autogen.h -index 123fcfe07b93..7c019fc91dd6 100644 ---- gpu/command_buffer/client/gles2_implementation_impl_autogen.h -+++ gpu/command_buffer/client/gles2_implementation_impl_autogen.h -@@ -3790,6 +3790,30 @@ void GLES2Implementation::DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) { - CheckGLError(); - } - -+void GLES2Implementation::LockSharedTexture(GLuint64 shared_handle) { -+ GPU_CLIENT_SINGLE_THREAD_CHECK(); -+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLockSharedTexture(" -+ << shared_handle << ")"); -+ helper_->LockSharedTexture(shared_handle); -+ CheckGLError(); -+} -+ -+void GLES2Implementation::UnlockSharedTexture(GLuint64 shared_handle) { -+ GPU_CLIENT_SINGLE_THREAD_CHECK(); -+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnlockSharedTexture(" -+ << shared_handle << ")"); -+ helper_->UnlockSharedTexture(shared_handle); -+ CheckGLError(); -+} -+ -+void GLES2Implementation::DeleteSharedTexture(GLuint64 shared_handle) { -+ GPU_CLIENT_SINGLE_THREAD_CHECK(); -+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteSharedTexture(" -+ << shared_handle << ")"); -+ helper_->DeleteSharedTexture(shared_handle); -+ CheckGLError(); -+} -+ - void GLES2Implementation::FramebufferTextureMultiviewOVR(GLenum target, - GLenum attachment, - GLuint texture, -diff --git gpu/command_buffer/client/gles2_interface_autogen.h gpu/command_buffer/client/gles2_interface_autogen.h -index dcf283b6555c..43d17fcc02bd 100644 ---- gpu/command_buffer/client/gles2_interface_autogen.h -+++ gpu/command_buffer/client/gles2_interface_autogen.h -@@ -1006,6 +1006,12 @@ virtual GLuint CreateGpuFenceCHROMIUM() = 0; - virtual GLuint CreateClientGpuFenceCHROMIUM(ClientGpuFence source) = 0; - virtual void WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) = 0; - virtual void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) = 0; -+virtual GLuint64 CreateSharedTexture(GLuint texture_id, -+ GLsizei width, -+ GLsizei height) = 0; -+virtual void LockSharedTexture(GLuint64 shared_handle) = 0; -+virtual void UnlockSharedTexture(GLuint64 shared_handle) = 0; -+virtual void DeleteSharedTexture(GLuint64 shared_handle) = 0; - virtual void InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) = 0; - virtual void FramebufferTextureMultiviewOVR(GLenum target, - GLenum attachment, -diff --git gpu/command_buffer/client/gles2_interface_stub_autogen.h gpu/command_buffer/client/gles2_interface_stub_autogen.h -index bd728edb5702..da59935fc7b8 100644 ---- gpu/command_buffer/client/gles2_interface_stub_autogen.h -+++ gpu/command_buffer/client/gles2_interface_stub_autogen.h -@@ -976,6 +976,12 @@ GLuint CreateGpuFenceCHROMIUM() override; - GLuint CreateClientGpuFenceCHROMIUM(ClientGpuFence source) override; - void WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) override; - void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) override; -+GLuint64 CreateSharedTexture(GLuint texture_id, -+ GLsizei width, -+ GLsizei height) override; -+void LockSharedTexture(GLuint64 shared_handle) override; -+void UnlockSharedTexture(GLuint64 shared_handle) override; -+void DeleteSharedTexture(GLuint64 shared_handle) override; - void InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) override; - void FramebufferTextureMultiviewOVR(GLenum target, - GLenum attachment, -diff --git gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h -index 305731012054..9fdd3db6aa60 100644 ---- gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h -+++ gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h -@@ -1296,6 +1296,14 @@ GLuint GLES2InterfaceStub::CreateClientGpuFenceCHROMIUM( - } - void GLES2InterfaceStub::WaitGpuFenceCHROMIUM(GLuint /* gpu_fence_id */) {} - void GLES2InterfaceStub::DestroyGpuFenceCHROMIUM(GLuint /* gpu_fence_id */) {} -+GLuint64 GLES2InterfaceStub::CreateSharedTexture(GLuint /* texture_id */, -+ GLsizei /* width */, -+ GLsizei /* height */) { -+ return 0; -+} -+void GLES2InterfaceStub::LockSharedTexture(GLuint64 /* shared_handle */) {} -+void GLES2InterfaceStub::UnlockSharedTexture(GLuint64 /* shared_handle */) {} -+void GLES2InterfaceStub::DeleteSharedTexture(GLuint64 /* shared_handle */) {} - void GLES2InterfaceStub::InvalidateReadbackBufferShadowDataCHROMIUM( - GLuint /* buffer_id */) {} - void GLES2InterfaceStub::FramebufferTextureMultiviewOVR( -diff --git gpu/command_buffer/client/gles2_trace_implementation_autogen.h gpu/command_buffer/client/gles2_trace_implementation_autogen.h -index 6f6b8dde72cf..078386560a72 100644 ---- gpu/command_buffer/client/gles2_trace_implementation_autogen.h -+++ gpu/command_buffer/client/gles2_trace_implementation_autogen.h -@@ -976,6 +976,12 @@ GLuint CreateGpuFenceCHROMIUM() override; - GLuint CreateClientGpuFenceCHROMIUM(ClientGpuFence source) override; - void WaitGpuFenceCHROMIUM(GLuint gpu_fence_id) override; - void DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) override; -+GLuint64 CreateSharedTexture(GLuint texture_id, -+ GLsizei width, -+ GLsizei height) override; -+void LockSharedTexture(GLuint64 shared_handle) override; -+void UnlockSharedTexture(GLuint64 shared_handle) override; -+void DeleteSharedTexture(GLuint64 shared_handle) override; - void InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id) override; - void FramebufferTextureMultiviewOVR(GLenum target, - GLenum attachment, -diff --git gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h -index 4a0a5288fa73..f56be5dad6cb 100644 ---- gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h -+++ gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h -@@ -2724,6 +2724,28 @@ void GLES2TraceImplementation::DestroyGpuFenceCHROMIUM(GLuint gpu_fence_id) { - gl_->DestroyGpuFenceCHROMIUM(gpu_fence_id); - } - -+GLuint64 GLES2TraceImplementation::CreateSharedTexture(GLuint texture_id, -+ GLsizei width, -+ GLsizei height) { -+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CreateSharedTexture"); -+ return gl_->CreateSharedTexture(texture_id, width, height); -+} -+ -+void GLES2TraceImplementation::LockSharedTexture(GLuint64 shared_handle) { -+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::LockSharedTexture"); -+ gl_->LockSharedTexture(shared_handle); -+} -+ -+void GLES2TraceImplementation::UnlockSharedTexture(GLuint64 shared_handle) { -+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::UnlockSharedTexture"); -+ gl_->UnlockSharedTexture(shared_handle); -+} -+ -+void GLES2TraceImplementation::DeleteSharedTexture(GLuint64 shared_handle) { -+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DeleteSharedTexture"); -+ gl_->DeleteSharedTexture(shared_handle); -+} -+ - void GLES2TraceImplementation::InvalidateReadbackBufferShadowDataCHROMIUM( - GLuint buffer_id) { - TRACE_EVENT_BINARY_EFFICIENT0( -diff --git gpu/command_buffer/common/gles2_cmd_format_autogen.h gpu/command_buffer/common/gles2_cmd_format_autogen.h -index cf009da41277..c5f46fba64b4 100644 ---- gpu/command_buffer/common/gles2_cmd_format_autogen.h -+++ gpu/command_buffer/common/gles2_cmd_format_autogen.h -@@ -17294,6 +17294,193 @@ static_assert(offsetof(DestroyGpuFenceCHROMIUM, header) == 0, - static_assert(offsetof(DestroyGpuFenceCHROMIUM, gpu_fence_id) == 4, - "offset of DestroyGpuFenceCHROMIUM gpu_fence_id should be 4"); - -+struct CreateSharedTexture { -+ typedef CreateSharedTexture ValueType; -+ static const CommandId kCmdId = kCreateSharedTexture; -+ static const cmd::ArgFlags kArgFlags = cmd::kFixed; -+ static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); -+ -+ typedef GLuint64 Result; -+ -+ static uint32_t ComputeSize() { -+ return static_cast(sizeof(ValueType)); // NOLINT -+ } -+ -+ void SetHeader() { header.SetCmd(); } -+ -+ void Init(GLint _texture_id, -+ GLint _width, -+ GLint _height, -+ uint32_t _result_shm_id, -+ uint32_t _result_shm_offset) { -+ SetHeader(); -+ texture_id = _texture_id; -+ width = _width; -+ height = _height; -+ result_shm_id = _result_shm_id; -+ result_shm_offset = _result_shm_offset; -+ } -+ -+ void* Set(void* cmd, -+ GLint _texture_id, -+ GLint _width, -+ GLint _height, -+ uint32_t _result_shm_id, -+ uint32_t _result_shm_offset) { -+ static_cast(cmd)->Init(_texture_id, _width, _height, -+ _result_shm_id, _result_shm_offset); -+ return NextCmdAddress(cmd); -+ } -+ -+ gpu::CommandHeader header; -+ int32_t texture_id; -+ int32_t width; -+ int32_t height; -+ uint32_t result_shm_id; -+ uint32_t result_shm_offset; -+}; -+ -+static_assert(sizeof(CreateSharedTexture) == 24, -+ "size of CreateSharedTexture should be 24"); -+static_assert(offsetof(CreateSharedTexture, header) == 0, -+ "offset of CreateSharedTexture header should be 0"); -+static_assert(offsetof(CreateSharedTexture, texture_id) == 4, -+ "offset of CreateSharedTexture texture_id should be 4"); -+static_assert(offsetof(CreateSharedTexture, width) == 8, -+ "offset of CreateSharedTexture width should be 8"); -+static_assert(offsetof(CreateSharedTexture, height) == 12, -+ "offset of CreateSharedTexture height should be 12"); -+static_assert(offsetof(CreateSharedTexture, result_shm_id) == 16, -+ "offset of CreateSharedTexture result_shm_id should be 16"); -+static_assert(offsetof(CreateSharedTexture, result_shm_offset) == 20, -+ "offset of CreateSharedTexture result_shm_offset should be 20"); -+ -+struct LockSharedTexture { -+ typedef LockSharedTexture ValueType; -+ static const CommandId kCmdId = kLockSharedTexture; -+ static const cmd::ArgFlags kArgFlags = cmd::kFixed; -+ static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); -+ -+ static uint32_t ComputeSize() { -+ return static_cast(sizeof(ValueType)); // NOLINT -+ } -+ -+ void SetHeader() { header.SetCmd(); } -+ -+ void Init(GLuint64 _shared_handle) { -+ SetHeader(); -+ GLES2Util::MapUint64ToTwoUint32(static_cast(_shared_handle), -+ &shared_handle_0, &shared_handle_1); -+ } -+ -+ void* Set(void* cmd, GLuint64 _shared_handle) { -+ static_cast(cmd)->Init(_shared_handle); -+ return NextCmdAddress(cmd); -+ } -+ -+ GLuint64 shared_handle() const volatile { -+ return static_cast( -+ GLES2Util::MapTwoUint32ToUint64(shared_handle_0, shared_handle_1)); -+ } -+ -+ gpu::CommandHeader header; -+ uint32_t shared_handle_0; -+ uint32_t shared_handle_1; -+}; -+ -+static_assert(sizeof(LockSharedTexture) == 12, -+ "size of LockSharedTexture should be 12"); -+static_assert(offsetof(LockSharedTexture, header) == 0, -+ "offset of LockSharedTexture header should be 0"); -+static_assert(offsetof(LockSharedTexture, shared_handle_0) == 4, -+ "offset of LockSharedTexture shared_handle_0 should be 4"); -+static_assert(offsetof(LockSharedTexture, shared_handle_1) == 8, -+ "offset of LockSharedTexture shared_handle_1 should be 8"); -+ -+struct UnlockSharedTexture { -+ typedef UnlockSharedTexture ValueType; -+ static const CommandId kCmdId = kUnlockSharedTexture; -+ static const cmd::ArgFlags kArgFlags = cmd::kFixed; -+ static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); -+ -+ static uint32_t ComputeSize() { -+ return static_cast(sizeof(ValueType)); // NOLINT -+ } -+ -+ void SetHeader() { header.SetCmd(); } -+ -+ void Init(GLuint64 _shared_handle) { -+ SetHeader(); -+ GLES2Util::MapUint64ToTwoUint32(static_cast(_shared_handle), -+ &shared_handle_0, &shared_handle_1); -+ } -+ -+ void* Set(void* cmd, GLuint64 _shared_handle) { -+ static_cast(cmd)->Init(_shared_handle); -+ return NextCmdAddress(cmd); -+ } -+ -+ GLuint64 shared_handle() const volatile { -+ return static_cast( -+ GLES2Util::MapTwoUint32ToUint64(shared_handle_0, shared_handle_1)); -+ } -+ -+ gpu::CommandHeader header; -+ uint32_t shared_handle_0; -+ uint32_t shared_handle_1; -+}; -+ -+static_assert(sizeof(UnlockSharedTexture) == 12, -+ "size of UnlockSharedTexture should be 12"); -+static_assert(offsetof(UnlockSharedTexture, header) == 0, -+ "offset of UnlockSharedTexture header should be 0"); -+static_assert(offsetof(UnlockSharedTexture, shared_handle_0) == 4, -+ "offset of UnlockSharedTexture shared_handle_0 should be 4"); -+static_assert(offsetof(UnlockSharedTexture, shared_handle_1) == 8, -+ "offset of UnlockSharedTexture shared_handle_1 should be 8"); -+ -+struct DeleteSharedTexture { -+ typedef DeleteSharedTexture ValueType; -+ static const CommandId kCmdId = kDeleteSharedTexture; -+ static const cmd::ArgFlags kArgFlags = cmd::kFixed; -+ static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); -+ -+ static uint32_t ComputeSize() { -+ return static_cast(sizeof(ValueType)); // NOLINT -+ } -+ -+ void SetHeader() { header.SetCmd(); } -+ -+ void Init(GLuint64 _shared_handle) { -+ SetHeader(); -+ GLES2Util::MapUint64ToTwoUint32(static_cast(_shared_handle), -+ &shared_handle_0, &shared_handle_1); -+ } -+ -+ void* Set(void* cmd, GLuint64 _shared_handle) { -+ static_cast(cmd)->Init(_shared_handle); -+ return NextCmdAddress(cmd); -+ } -+ -+ GLuint64 shared_handle() const volatile { -+ return static_cast( -+ GLES2Util::MapTwoUint32ToUint64(shared_handle_0, shared_handle_1)); -+ } -+ -+ gpu::CommandHeader header; -+ uint32_t shared_handle_0; -+ uint32_t shared_handle_1; -+}; -+ -+static_assert(sizeof(DeleteSharedTexture) == 12, -+ "size of DeleteSharedTexture should be 12"); -+static_assert(offsetof(DeleteSharedTexture, header) == 0, -+ "offset of DeleteSharedTexture header should be 0"); -+static_assert(offsetof(DeleteSharedTexture, shared_handle_0) == 4, -+ "offset of DeleteSharedTexture shared_handle_0 should be 4"); -+static_assert(offsetof(DeleteSharedTexture, shared_handle_1) == 8, -+ "offset of DeleteSharedTexture shared_handle_1 should be 8"); -+ - struct SetReadbackBufferShadowAllocationINTERNAL { - typedef SetReadbackBufferShadowAllocationINTERNAL ValueType; - static const CommandId kCmdId = kSetReadbackBufferShadowAllocationINTERNAL; -diff --git gpu/command_buffer/common/gles2_cmd_format_test_autogen.h gpu/command_buffer/common/gles2_cmd_format_test_autogen.h -index ee423c7663fc..3d736022f54b 100644 ---- gpu/command_buffer/common/gles2_cmd_format_test_autogen.h -+++ gpu/command_buffer/common/gles2_cmd_format_test_autogen.h -@@ -5710,6 +5710,52 @@ TEST_F(GLES2FormatTest, DestroyGpuFenceCHROMIUM) { - CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); - } - -+TEST_F(GLES2FormatTest, CreateSharedTexture) { -+ cmds::CreateSharedTexture& cmd = *GetBufferAs(); -+ void* next_cmd = cmd.Set(&cmd, static_cast(11), static_cast(12), -+ static_cast(13), static_cast(14), -+ static_cast(15)); -+ EXPECT_EQ(static_cast(cmds::CreateSharedTexture::kCmdId), -+ cmd.header.command); -+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); -+ EXPECT_EQ(static_cast(11), cmd.texture_id); -+ EXPECT_EQ(static_cast(12), cmd.width); -+ EXPECT_EQ(static_cast(13), cmd.height); -+ EXPECT_EQ(static_cast(14), cmd.result_shm_id); -+ EXPECT_EQ(static_cast(15), cmd.result_shm_offset); -+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -+} -+ -+TEST_F(GLES2FormatTest, LockSharedTexture) { -+ cmds::LockSharedTexture& cmd = *GetBufferAs(); -+ void* next_cmd = cmd.Set(&cmd, static_cast(11)); -+ EXPECT_EQ(static_cast(cmds::LockSharedTexture::kCmdId), -+ cmd.header.command); -+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); -+ EXPECT_EQ(static_cast(11), cmd.shared_handle()); -+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -+} -+ -+TEST_F(GLES2FormatTest, UnlockSharedTexture) { -+ cmds::UnlockSharedTexture& cmd = *GetBufferAs(); -+ void* next_cmd = cmd.Set(&cmd, static_cast(11)); -+ EXPECT_EQ(static_cast(cmds::UnlockSharedTexture::kCmdId), -+ cmd.header.command); -+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); -+ EXPECT_EQ(static_cast(11), cmd.shared_handle()); -+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -+} -+ -+TEST_F(GLES2FormatTest, DeleteSharedTexture) { -+ cmds::DeleteSharedTexture& cmd = *GetBufferAs(); -+ void* next_cmd = cmd.Set(&cmd, static_cast(11)); -+ EXPECT_EQ(static_cast(cmds::DeleteSharedTexture::kCmdId), -+ cmd.header.command); -+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); -+ EXPECT_EQ(static_cast(11), cmd.shared_handle()); -+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -+} -+ - TEST_F(GLES2FormatTest, SetReadbackBufferShadowAllocationINTERNAL) { - cmds::SetReadbackBufferShadowAllocationINTERNAL& cmd = - *GetBufferAs(); -diff --git gpu/command_buffer/common/gles2_cmd_ids_autogen.h gpu/command_buffer/common/gles2_cmd_ids_autogen.h -index 3f3f159828ab..8f447617205b 100644 ---- gpu/command_buffer/common/gles2_cmd_ids_autogen.h -+++ gpu/command_buffer/common/gles2_cmd_ids_autogen.h -@@ -360,7 +360,11 @@ - OP(MaxShaderCompilerThreadsKHR) /* 601 */ \ - OP(CreateAndTexStorage2DSharedImageINTERNALImmediate) /* 602 */ \ - OP(BeginSharedImageAccessDirectCHROMIUM) /* 603 */ \ -- OP(EndSharedImageAccessDirectCHROMIUM) /* 604 */ -+ OP(EndSharedImageAccessDirectCHROMIUM) /* 604 */ \ -+ OP(CreateSharedTexture) /* 605 */ \ -+ OP(LockSharedTexture) /* 606 */ \ -+ OP(UnlockSharedTexture) /* 607 */ \ -+ OP(DeleteSharedTexture) /* 608 */ - - enum CommandId { - kOneBeforeStartPoint = -diff --git gpu/command_buffer/gles2_cmd_buffer_functions.txt gpu/command_buffer/gles2_cmd_buffer_functions.txt -index 7c3d121e54dc..b9b7ffa2a585 100644 ---- gpu/command_buffer/gles2_cmd_buffer_functions.txt -+++ gpu/command_buffer/gles2_cmd_buffer_functions.txt -@@ -412,6 +412,12 @@ GL_APICALL GLuint GL_APIENTRY glCreateClientGpuFenceCHROMIUM (ClientGpuFen - GL_APICALL void GL_APIENTRY glWaitGpuFenceCHROMIUM (GLuint gpu_fence_id); - GL_APICALL void GL_APIENTRY glDestroyGpuFenceCHROMIUM (GLuint gpu_fence_id); - -+// shared handle extensions -+GL_APICALL GLuint64 GL_APIENTRY glCreateSharedTexture (GLuint texture_id, GLsizei width, GLsizei height); -+GL_APICALL void GL_APIENTRY glLockSharedTexture (GLuint64 shared_handle); -+GL_APICALL void GL_APIENTRY glUnlockSharedTexture (GLuint64 shared_handle); -+GL_APICALL void GL_APIENTRY glDeleteSharedTexture (GLuint64 shared_handle); -+ - // Extension CHROMIUM_nonblocking_readback - GL_APICALL void GL_APIENTRY glInvalidateReadbackBufferShadowDataCHROMIUM (GLidBuffer buffer_id); - // (used for CHROMIUM_nonblocking_readback implementation) -diff --git gpu/command_buffer/service/BUILD.gn gpu/command_buffer/service/BUILD.gn -index 5a84425376f2..6af28715789b 100644 ---- gpu/command_buffer/service/BUILD.gn -+++ gpu/command_buffer/service/BUILD.gn -@@ -108,6 +108,8 @@ target(link_target_type, "gles2_sources") { - visibility = [ "//gpu/*" ] - - sources = [ -+ "//cef/libcef/browser/gpu/external_texture_manager.cc", -+ "//cef/libcef/browser/gpu/external_texture_manager.h", - "abstract_texture.h", - "abstract_texture_impl_shared_context_state.cc", - "abstract_texture_impl_shared_context_state.h", -diff --git gpu/command_buffer/service/gles2_cmd_decoder.cc gpu/command_buffer/service/gles2_cmd_decoder.cc -index bc72d2624aad..18a477c53445 100644 ---- gpu/command_buffer/service/gles2_cmd_decoder.cc -+++ gpu/command_buffer/service/gles2_cmd_decoder.cc -@@ -38,6 +38,7 @@ - #include "base/strings/stringprintf.h" - #include "base/trace_event/trace_event.h" - #include "build/build_config.h" -+#include "cef/libcef/browser/gpu/external_texture_manager.h" - #include "gpu/command_buffer/common/debug_marker_manager.h" - #include "gpu/command_buffer/common/gles2_cmd_format.h" - #include "gpu/command_buffer/common/gles2_cmd_utils.h" -@@ -917,6 +918,13 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { - return group_->mailbox_manager(); - } - -+ ExternalTextureManager* external_texture_manager() { -+ if (!external_texture_manager_.get()) { -+ external_texture_manager_.reset(new gles2::ExternalTextureManager()); -+ } -+ return external_texture_manager_.get(); -+ } -+ - ImageManager* image_manager() { return group_->image_manager(); } - - VertexArrayManager* vertex_array_manager() { -@@ -2645,6 +2653,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { - - std::unique_ptr vertex_array_manager_; - -+ std::unique_ptr external_texture_manager_; -+ - base::flat_set> writes_submitted_but_not_completed_; - - // The format of the back buffer_ -@@ -5620,6 +5630,59 @@ error::Error GLES2DecoderImpl::HandleDestroyGpuFenceCHROMIUM( - return error::kNoError; - } - -+error::Error GLES2DecoderImpl::HandleCreateSharedTexture( -+ uint32_t immediate_data_size, -+ const volatile void* cmd_data) { -+ const volatile gles2::cmds::CreateSharedTexture& c = -+ *static_cast(cmd_data); -+ GLuint texture_id = c.texture_id; -+ uint32_t width = c.width; -+ uint32_t height = c.height; -+ -+ typedef cmds::CreateSharedTexture::Result Result; -+ Result* result_dst = GetSharedMemoryAs( -+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst)); -+ if (!result_dst) { -+ return error::kOutOfBounds; -+ } -+ -+ void* shared_handle = external_texture_manager()->CreateTexture( -+ texture_id, width, height, texture_manager()); -+ -+ *result_dst = (GLuint64)(shared_handle); -+ return error::kNoError; -+} -+ -+error::Error GLES2DecoderImpl::HandleLockSharedTexture( -+ uint32_t immediate_data_size, -+ const volatile void* cmd_data) { -+ const volatile gles2::cmds::LockSharedTexture& c = -+ *static_cast(cmd_data); -+ void* handle = (void*)(c.shared_handle()); -+ external_texture_manager()->LockTexture(handle); -+ return error::kNoError; -+} -+ -+error::Error GLES2DecoderImpl::HandleUnlockSharedTexture( -+ uint32_t immediate_data_size, -+ const volatile void* cmd_data) { -+ const volatile gles2::cmds::UnlockSharedTexture& c = -+ *static_cast(cmd_data); -+ void* handle = (void*)(c.shared_handle()); -+ external_texture_manager()->UnlockTexture(handle); -+ return error::kNoError; -+} -+ -+error::Error GLES2DecoderImpl::HandleDeleteSharedTexture( -+ uint32_t immediate_data_size, -+ const volatile void* cmd_data) { -+ const volatile gles2::cmds::DeleteSharedTexture& c = -+ *static_cast(cmd_data); -+ void* handle = (void*)(c.shared_handle()); -+ external_texture_manager()->DeleteTexture(handle, texture_manager()); -+ return error::kNoError; -+} -+ - void GLES2DecoderImpl::CreateBackTexture() { - for (auto it = saved_back_textures_.begin(); it != saved_back_textures_.end(); - ++it) { -diff --git gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc -index 15fd3f99101d..3c1234940c41 100644 ---- gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc -+++ gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc -@@ -11,6 +11,7 @@ - #include "base/callback.h" - #include "base/stl_util.h" - #include "base/strings/string_split.h" -+#include "cef/libcef/browser/gpu/external_texture_manager.h" - #include "gpu/command_buffer/service/command_buffer_service.h" - #include "gpu/command_buffer/service/decoder_client.h" - #include "gpu/command_buffer/service/feature_info.h" -@@ -2589,6 +2590,67 @@ error::Error GLES2DecoderPassthroughImpl::CheckSwapBuffersResult( - return error::kNoError; - } - -+ExternalTextureManager* -+GLES2DecoderPassthroughImpl::external_texture_manager() { -+ if (!external_texture_manager_.get()) { -+ external_texture_manager_.reset(new gles2::ExternalTextureManager()); -+ } -+ return external_texture_manager_.get(); -+} -+ -+error::Error GLES2DecoderPassthroughImpl::HandleCreateSharedTexture( -+ uint32_t immediate_data_size, -+ const volatile void* cmd_data) { -+ const volatile gles2::cmds::CreateSharedTexture& c = -+ *static_cast(cmd_data); -+ GLuint texture_id = c.texture_id; -+ uint32_t width = c.width; -+ uint32_t height = c.height; -+ -+ typedef cmds::CreateSharedTexture::Result Result; -+ Result* result_dst = GetSharedMemoryAs( -+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst)); -+ if (!result_dst) { -+ return error::kOutOfBounds; -+ } -+ -+ void* shared_handle = external_texture_manager()->CreateTexture( -+ texture_id, width, height, nullptr); -+ -+ *result_dst = (GLuint64)(shared_handle); -+ return error::kNoError; -+} -+ -+error::Error GLES2DecoderPassthroughImpl::HandleLockSharedTexture( -+ uint32_t immediate_data_size, -+ const volatile void* cmd_data) { -+ const volatile gles2::cmds::LockSharedTexture& c = -+ *static_cast(cmd_data); -+ void* handle = (void*)(c.shared_handle()); -+ external_texture_manager()->LockTexture(handle); -+ return error::kNoError; -+} -+ -+error::Error GLES2DecoderPassthroughImpl::HandleUnlockSharedTexture( -+ uint32_t immediate_data_size, -+ const volatile void* cmd_data) { -+ const volatile gles2::cmds::UnlockSharedTexture& c = -+ *static_cast(cmd_data); -+ void* handle = (void*)(c.shared_handle()); -+ external_texture_manager()->UnlockTexture(handle); -+ return error::kNoError; -+} -+ -+error::Error GLES2DecoderPassthroughImpl::HandleDeleteSharedTexture( -+ uint32_t immediate_data_size, -+ const volatile void* cmd_data) { -+ const volatile gles2::cmds::DeleteSharedTexture& c = -+ *static_cast(cmd_data); -+ void* handle = (void*)(c.shared_handle()); -+ external_texture_manager()->DeleteTexture(handle, nullptr); -+ return error::kNoError; -+} -+ - // static - GLES2DecoderPassthroughImpl::TextureTarget - GLES2DecoderPassthroughImpl::GLenumToTextureTarget(GLenum target) { -diff --git gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h -index 1fa45e8311c3..f67179f3bdc4 100644 ---- gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h -+++ gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h -@@ -45,6 +45,7 @@ class SharedImageRepresentationGLTexturePassthrough; - namespace gles2 { - - class ContextGroup; -+class ExternalTextureManager; - class GPUTracer; - class MultiDrawManager; - class PassthroughAbstractTextureImpl; -@@ -377,6 +378,8 @@ class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { - - void SetOptionalExtensionsRequestedForTesting(bool request_extensions); - -+ ExternalTextureManager* external_texture_manager(); -+ - void* GetScratchMemory(size_t size); - - template -@@ -581,6 +584,8 @@ class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl : public GLES2Decoder { - - std::unique_ptr multi_draw_manager_; - -+ std::unique_ptr external_texture_manager_; -+ - // State tracking of currently bound 2D textures (client IDs) - size_t active_texture_unit_; - -diff --git ui/compositor/compositor.cc ui/compositor/compositor.cc -index 15c98e2b7d42..d607234f8ad7 100644 ---- ui/compositor/compositor.cc -+++ ui/compositor/compositor.cc -@@ -548,6 +548,16 @@ gfx::AcceleratedWidget Compositor::widget() const { - return widget_; - } - -+void* Compositor::GetSharedTexture() { -+ if (context_factory_private_) -+ return context_factory_private_->GetSharedTexture(this); -+ return nullptr; -+} -+ -+void Compositor::EnableSharedTexture(bool enable) { -+ shared_texture_enabled_ = enable; -+} -+ - void Compositor::AddObserver(CompositorObserver* observer) { - observer_list_.AddObserver(observer); - } -diff --git ui/compositor/compositor.h ui/compositor/compositor.h -index 494241c374b7..f07133a4b147 100644 ---- ui/compositor/compositor.h -+++ ui/compositor/compositor.h -@@ -24,6 +24,7 @@ - #include "components/viz/common/frame_sinks/begin_frame_args.h" - #include "components/viz/common/surfaces/frame_sink_id.h" - #include "components/viz/host/host_frame_sink_client.h" -+#include "components/viz/service/display/software_output_device.h" - #include "services/viz/privileged/interfaces/compositing/vsync_parameter_observer.mojom-forward.h" - #include "third_party/skia/include/core/SkColor.h" - #include "third_party/skia/include/core/SkMatrix44.h" -@@ -155,6 +156,8 @@ class COMPOSITOR_EXPORT ContextFactoryPrivate { - - virtual void SetOutputIsSecure(Compositor* compositor, bool secure) = 0; - -+ virtual void* GetSharedTexture(ui::Compositor* compositor) = 0; -+ - // Adds an observer for vsync parameter changes. - virtual void AddVSyncParameterObserver( - Compositor* compositor, -@@ -199,6 +202,17 @@ class COMPOSITOR_EXPORT ContextFactory { - virtual bool SyncTokensRequiredForDisplayCompositor() = 0; - }; - -+class COMPOSITOR_EXPORT CompositorDelegate { -+ public: -+ virtual std::unique_ptr CreateSoftwareOutputDevice( -+ ui::Compositor* compositor) { -+ return nullptr; -+ } -+ -+ protected: -+ virtual ~CompositorDelegate() {} -+}; -+ - // Compositor object to take care of GPU painting. - // A Browser compositor object is responsible for generating the final - // displayable form of pixels comprising a single widget's contents. It draws an -@@ -238,6 +252,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, - // Schedules a redraw of the layer tree associated with this compositor. - void ScheduleDraw(); - -+ CompositorDelegate* delegate() const { return delegate_; } -+ void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; } -+ - // Sets the root of the layer tree drawn by this Compositor. The root layer - // must have no parent. The compositor's root layer is reset if the root layer - // is destroyed. NULL can be passed to reset the root layer, in which case the -@@ -341,6 +358,10 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, - return task_runner_; - } - -+ void* GetSharedTexture(); -+ void EnableSharedTexture(bool enable); -+ bool shared_texture_enabled() const { return shared_texture_enabled_; } -+ - // Compositor does not own observers. It is the responsibility of the - // observer to remove itself when it is done observing. - void AddObserver(CompositorObserver* observer); -@@ -454,6 +475,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, - ui::ContextFactory* context_factory_; - ui::ContextFactoryPrivate* context_factory_private_; - -+ CompositorDelegate* delegate_ = nullptr; -+ - // The root of the Layer tree drawn by this compositor. - Layer* root_layer_ = nullptr; - -@@ -485,6 +508,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, - - ExternalBeginFrameClient* const external_begin_frame_client_; - -+ bool shared_texture_enabled_ = false; -+ - const bool force_software_compositor_; - - // The device scale factor of the monitor that this compositor is compositing -diff --git ui/compositor/host/host_context_factory_private.cc ui/compositor/host/host_context_factory_private.cc -index 0ff1e05244e0..93d69530edc2 100644 ---- ui/compositor/host/host_context_factory_private.cc -+++ ui/compositor/host/host_context_factory_private.cc -@@ -297,6 +297,10 @@ void HostContextFactoryPrivate::AddVSyncParameterObserver( - } - } - -+void* HostContextFactoryPrivate::GetSharedTexture(Compositor* /*compositor*/) { -+ return nullptr; -+} -+ - viz::FrameSinkManagerImpl* HostContextFactoryPrivate::GetFrameSinkManager() { - // When running with viz there is no FrameSinkManagerImpl in the browser - // process. FrameSinkManagerImpl runs in the GPU process instead. Anything in -diff --git ui/compositor/host/host_context_factory_private.h ui/compositor/host/host_context_factory_private.h -index dc31ab80f17e..c7c08d6137eb 100644 ---- ui/compositor/host/host_context_factory_private.h -+++ ui/compositor/host/host_context_factory_private.h -@@ -50,6 +50,8 @@ class HostContextFactoryPrivate : public ContextFactoryPrivate { - - void UnconfigureCompositor(Compositor* compositor); - -+ void* GetSharedTexture(ui::Compositor* compositor) override; -+ - void set_is_gpu_compositing_disabled(bool value) { - is_gpu_compositing_disabled_ = value; - } diff --git a/patch/patches/viz_osr_2575.patch b/patch/patches/viz_osr_2575.patch new file mode 100644 index 000000000..3de49a4dd --- /dev/null +++ b/patch/patches/viz_osr_2575.patch @@ -0,0 +1,263 @@ +diff --git components/viz/host/host_display_client.cc components/viz/host/host_display_client.cc +index f5e18df4e06e..58a8e8ef125b 100644 +--- components/viz/host/host_display_client.cc ++++ components/viz/host/host_display_client.cc +@@ -46,9 +46,14 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams( + } + #endif + +-#if defined(OS_WIN) ++void HostDisplayClient::UseProxyOutputDevice( ++ UseProxyOutputDeviceCallback callback) { ++ std::move(callback).Run(false); ++} ++ + void HostDisplayClient::CreateLayeredWindowUpdater( + mojom::LayeredWindowUpdaterRequest request) { ++#if OS_WIN + if (!NeedsToUseLayerWindow(widget_)) { + DLOG(ERROR) << "HWND shouldn't be using a layered window"; + return; +@@ -56,8 +61,8 @@ void HostDisplayClient::CreateLayeredWindowUpdater( + + layered_window_updater_ = + std::make_unique(widget_, std::move(request)); +-} + #endif ++} + + #if defined(USE_X11) + void HostDisplayClient::DidCompleteSwapWithNewSize(const gfx::Size& size) { +diff --git components/viz/host/host_display_client.h components/viz/host/host_display_client.h +index 5e5c5da4a3cf..30eca49765bd 100644 +--- components/viz/host/host_display_client.h ++++ components/viz/host/host_display_client.h +@@ -30,17 +30,17 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient { + mojom::DisplayClientPtr GetBoundPtr( + scoped_refptr task_runner); + +- private: ++ protected: + // mojom::DisplayClient implementation: ++ void UseProxyOutputDevice(UseProxyOutputDeviceCallback callback) override; ++ + #if defined(OS_MACOSX) + void OnDisplayReceivedCALayerParams( + const gfx::CALayerParams& ca_layer_params) override; + #endif + +-#if defined(OS_WIN) + void CreateLayeredWindowUpdater( + mojom::LayeredWindowUpdaterRequest request) override; +-#endif + + #if defined(USE_X11) + void DidCompleteSwapWithNewSize(const gfx::Size& size) override; +diff --git components/viz/host/layered_window_updater_impl.cc components/viz/host/layered_window_updater_impl.cc +index d3a49ed8be8d..38a927b8f734 100644 +--- components/viz/host/layered_window_updater_impl.cc ++++ components/viz/host/layered_window_updater_impl.cc +@@ -47,7 +47,7 @@ void LayeredWindowUpdaterImpl::OnAllocatedSharedMemory( + shm_handle.Close(); + } + +-void LayeredWindowUpdaterImpl::Draw(DrawCallback draw_callback) { ++void LayeredWindowUpdaterImpl::Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) { + TRACE_EVENT0("viz", "LayeredWindowUpdaterImpl::Draw"); + + if (!canvas_) { +diff --git components/viz/host/layered_window_updater_impl.h components/viz/host/layered_window_updater_impl.h +index 93c52d2b928c..4dc645e770a2 100644 +--- components/viz/host/layered_window_updater_impl.h ++++ components/viz/host/layered_window_updater_impl.h +@@ -33,7 +33,7 @@ class VIZ_HOST_EXPORT LayeredWindowUpdaterImpl + void OnAllocatedSharedMemory( + const gfx::Size& pixel_size, + mojo::ScopedSharedBufferHandle scoped_buffer_handle) override; +- void Draw(DrawCallback draw_callback) override; ++ void Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) override; + + private: + const HWND hwnd_; +diff --git components/viz/service/BUILD.gn components/viz/service/BUILD.gn +index f17983a5cc70..4a8f2fd8d415 100644 +--- components/viz/service/BUILD.gn ++++ components/viz/service/BUILD.gn +@@ -13,6 +13,8 @@ config("viz_service_implementation") { + + viz_component("service") { + sources = [ ++ "//cef/libcef/browser/osr/software_output_device_proxy.cc", ++ "//cef/libcef/browser/osr/software_output_device_proxy.h", + "display/bsp_tree.cc", + "display/bsp_tree.h", + "display/bsp_walk_action.cc", +diff --git components/viz/service/display_embedder/output_surface_provider_impl.cc components/viz/service/display_embedder/output_surface_provider_impl.cc +index 8fe397588eb4..1218985f7310 100644 +--- components/viz/service/display_embedder/output_surface_provider_impl.cc ++++ components/viz/service/display_embedder/output_surface_provider_impl.cc +@@ -11,6 +11,7 @@ + #include "base/compiler_specific.h" + #include "base/threading/thread_task_runner_handle.h" + #include "cc/base/switches.h" ++#include "cef/libcef/browser/osr/software_output_device_proxy.h" + #include "components/viz/common/display/renderer_settings.h" + #include "components/viz/common/frame_sinks/begin_frame_source.h" + #include "components/viz/service/display_embedder/gl_output_surface.h" +@@ -243,6 +244,20 @@ OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform( + if (headless_) + return std::make_unique(); + ++ { ++ mojo::ScopedAllowSyncCallForTesting allow_sync; ++ DCHECK(display_client); ++ bool use_proxy_output_device = false; ++ if (display_client->UseProxyOutputDevice(&use_proxy_output_device) && ++ use_proxy_output_device) { ++ mojom::LayeredWindowUpdaterPtr layered_window_updater; ++ display_client->CreateLayeredWindowUpdater( ++ mojo::MakeRequest(&layered_window_updater)); ++ return std::make_unique( ++ std::move(layered_window_updater)); ++ } ++ } ++ + #if defined(OS_WIN) + return CreateSoftwareOutputDeviceWin(surface_handle, &output_device_backing_, + display_client); +diff --git components/viz/service/display_embedder/software_output_device_win.cc components/viz/service/display_embedder/software_output_device_win.cc +index 4e3f0255d5fe..0de947b54b7c 100644 +--- components/viz/service/display_embedder/software_output_device_win.cc ++++ components/viz/service/display_embedder/software_output_device_win.cc +@@ -268,8 +268,9 @@ void SoftwareOutputDeviceWinProxy::EndPaintDelegated( + if (!canvas_) + return; + +- layered_window_updater_->Draw(base::BindOnce( +- &SoftwareOutputDeviceWinProxy::DrawAck, base::Unretained(this))); ++ layered_window_updater_->Draw( ++ damage_rect, base::BindOnce(&SoftwareOutputDeviceWinProxy::DrawAck, ++ base::Unretained(this))); + waiting_on_draw_ack_ = true; + + TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceWinProxy::Draw", this); +diff --git mojo/public/cpp/bindings/sync_call_restrictions.h mojo/public/cpp/bindings/sync_call_restrictions.h +index 906be544c90f..a110f254d7ec 100644 +--- mojo/public/cpp/bindings/sync_call_restrictions.h ++++ mojo/public/cpp/bindings/sync_call_restrictions.h +@@ -34,6 +34,7 @@ class HostContextFactoryPrivate; + + namespace viz { + class HostFrameSinkManager; ++class GpuDisplayProvider; + } + + namespace mojo { +@@ -91,6 +92,8 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) SyncCallRestrictions { + // For preventing frame swaps of wrong size during resize on Windows. + // (https://crbug.com/811945) + friend class ui::HostContextFactoryPrivate; ++ // For query of whether to use SoftwareOutputDevice or not ++ friend class viz::GpuDisplayProvider; + // END ALLOWED USAGE. + + #if ENABLE_SYNC_CALL_RESTRICTIONS +diff --git services/viz/privileged/interfaces/compositing/display_private.mojom services/viz/privileged/interfaces/compositing/display_private.mojom +index deb327b77054..d9926ec35165 100644 +--- services/viz/privileged/interfaces/compositing/display_private.mojom ++++ services/viz/privileged/interfaces/compositing/display_private.mojom +@@ -77,12 +77,14 @@ interface DisplayPrivate { + }; + + interface DisplayClient { ++ [Sync] ++ UseProxyOutputDevice() => (bool success); ++ + [EnableIf=is_mac] + OnDisplayReceivedCALayerParams(gfx.mojom.CALayerParams ca_layer_params); + + // Creates a LayeredWindowUpdater implementation to draw into a layered + // window. +- [EnableIf=is_win] + CreateLayeredWindowUpdater(LayeredWindowUpdater& layered_window_updater); + + // Notifies that a swap has occurred and provides information about the pixel +diff --git services/viz/privileged/interfaces/compositing/layered_window_updater.mojom services/viz/privileged/interfaces/compositing/layered_window_updater.mojom +index 360cab3eee4c..6834242f23d2 100644 +--- services/viz/privileged/interfaces/compositing/layered_window_updater.mojom ++++ services/viz/privileged/interfaces/compositing/layered_window_updater.mojom +@@ -22,5 +22,5 @@ interface LayeredWindowUpdater { + // Draws to the HWND by copying pixels from shared memory. Callback must be + // called after draw operation is complete to signal shared memory can be + // modified. +- Draw() => (); ++ Draw(gfx.mojom.Rect damage_rect) => (); + }; +diff --git ui/compositor/compositor.h ui/compositor/compositor.h +index 494241c374b7..1cbfb9cdb683 100644 +--- ui/compositor/compositor.h ++++ ui/compositor/compositor.h +@@ -23,7 +23,9 @@ + #include "cc/trees/layer_tree_host_single_thread_client.h" + #include "components/viz/common/frame_sinks/begin_frame_args.h" + #include "components/viz/common/surfaces/frame_sink_id.h" ++#include "components/viz/host/host_display_client.h" + #include "components/viz/host/host_frame_sink_client.h" ++#include "components/viz/service/display/software_output_device.h" + #include "services/viz/privileged/interfaces/compositing/vsync_parameter_observer.mojom-forward.h" + #include "third_party/skia/include/core/SkColor.h" + #include "third_party/skia/include/core/SkMatrix44.h" +@@ -199,6 +201,14 @@ class COMPOSITOR_EXPORT ContextFactory { + virtual bool SyncTokensRequiredForDisplayCompositor() = 0; + }; + ++class COMPOSITOR_EXPORT CompositorDelegate { ++ public: ++ virtual std::unique_ptr CreateHostDisplayClient() = 0; ++ ++ protected: ++ virtual ~CompositorDelegate() {} ++}; ++ + // Compositor object to take care of GPU painting. + // A Browser compositor object is responsible for generating the final + // displayable form of pixels comprising a single widget's contents. It draws an +@@ -238,6 +248,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, + // Schedules a redraw of the layer tree associated with this compositor. + void ScheduleDraw(); + ++ CompositorDelegate* delegate() const { return delegate_; } ++ void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; } ++ + // Sets the root of the layer tree drawn by this Compositor. The root layer + // must have no parent. The compositor's root layer is reset if the root layer + // is destroyed. NULL can be passed to reset the root layer, in which case the +@@ -454,6 +467,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, + ui::ContextFactory* context_factory_; + ui::ContextFactoryPrivate* context_factory_private_; + ++ CompositorDelegate* delegate_ = nullptr; ++ + // The root of the Layer tree drawn by this compositor. + Layer* root_layer_ = nullptr; + +diff --git ui/compositor/host/host_context_factory_private.cc ui/compositor/host/host_context_factory_private.cc +index 0ff1e05244e0..5b8721034296 100644 +--- ui/compositor/host/host_context_factory_private.cc ++++ ui/compositor/host/host_context_factory_private.cc +@@ -99,8 +99,13 @@ void HostContextFactoryPrivate::ConfigureCompositor( + mojo::MakeRequest(&root_params->compositor_frame_sink_client); + root_params->display_private = + mojo::MakeRequest(&compositor_data.display_private); +- compositor_data.display_client = +- std::make_unique(compositor); ++ if (compositor->delegate()) { ++ compositor_data.display_client = ++ compositor->delegate()->CreateHostDisplayClient(); ++ } else { ++ compositor_data.display_client = ++ std::make_unique(compositor); ++ } + root_params->display_client = + compositor_data.display_client->GetBoundPtr(resize_task_runner_) + .PassInterface(); diff --git a/tests/ceftests/os_rendering_unittest.cc b/tests/ceftests/os_rendering_unittest.cc index b9c8398ff..75d4e06aa 100644 --- a/tests/ceftests/os_rendering_unittest.cc +++ b/tests/ceftests/os_rendering_unittest.cc @@ -36,11 +36,11 @@ const int kOsrHeight = 400; // bounding client rects for edit box and navigate button #if defined(OS_WIN) -const CefRect kExpandedSelectRect(463, 42, 81, 334); +const CefRect kExpandedSelectRect(462, 42, 81, 334); #elif defined(OS_MACOSX) -const CefRect kExpandedSelectRect(463, 42, 75, 286); +const CefRect kExpandedSelectRect(462, 42, 75, 286); #elif defined(OS_LINUX) -const CefRect kExpandedSelectRect(463, 42, 79, 334); +const CefRect kExpandedSelectRect(462, 42, 79, 334); #else #error "Unsupported platform" #endif // defined(OS_WIN)