mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Fix OSR surface sizing on browser resize (fixes issue #2733).
This includes the following changes: - Update usage of surface IDs to match the Aura implementation from the RWHVAura/Window classes. - Batch CefBrowserHost::WasResized calls to avoid excessive/unnecessary calls to SynchronizeVisualProperties. - Cache the results of CefRenderHandler::GetViewRect after resize and make RWHVOSR::GetViewBounds the source of truth for all size calculations. - Fix bounds calculations in CefVideoConsumerOSR with GPU enabled. Known issues: - The size passed to OnPaint may be off by 1 pixel in cases where the device scale factor is not 1 and does not divide evenly into the pixel size. This is due to the inexact conversion from integer pixel size to integer logical size for GetViewRect.
This commit is contained in:
@@ -1079,7 +1079,7 @@ void CefBrowserHostImpl::WasResized() {
|
||||
if (!web_contents() || !platform_delegate_)
|
||||
return;
|
||||
|
||||
platform_delegate_->SynchronizeVisualProperties();
|
||||
platform_delegate_->WasResized();
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::WasHidden(bool hidden) {
|
||||
|
@@ -145,7 +145,7 @@ class CefBrowserPlatformDelegate {
|
||||
virtual bool CanUseExternalBeginFrame() const = 0;
|
||||
|
||||
// Notify the window that it was resized.
|
||||
virtual void SynchronizeVisualProperties() = 0;
|
||||
virtual void WasResized() = 0;
|
||||
|
||||
// Send input events.
|
||||
virtual void SendKeyEvent(const CefKeyEvent& event) = 0;
|
||||
|
@@ -47,7 +47,7 @@ SkColor CefBrowserPlatformDelegateBackground::GetBackgroundColor() const {
|
||||
return native_delegate_->GetBackgroundColor();
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateBackground::SynchronizeVisualProperties() {
|
||||
void CefBrowserPlatformDelegateBackground::WasResized() {
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,7 @@ class CefBrowserPlatformDelegateBackground
|
||||
SkColor GetBackgroundColor() const override;
|
||||
bool CanUseSharedTexture() const override;
|
||||
bool CanUseExternalBeginFrame() const override;
|
||||
void SynchronizeVisualProperties() override;
|
||||
void WasResized() override;
|
||||
void SendKeyEvent(const CefKeyEvent& event) override;
|
||||
void SendMouseClickEvent(const CefMouseEvent& event,
|
||||
CefBrowserHost::MouseButtonType type,
|
||||
|
@@ -33,7 +33,7 @@ bool CefBrowserPlatformDelegateNative::CanUseExternalBeginFrame() const {
|
||||
return use_external_begin_frame_;
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateNative::SynchronizeVisualProperties() {
|
||||
void CefBrowserPlatformDelegateNative::WasResized() {
|
||||
content::RenderViewHost* host = browser_->web_contents()->GetRenderViewHost();
|
||||
if (host)
|
||||
host->GetWidget()->SynchronizeVisualProperties();
|
||||
|
@@ -28,7 +28,7 @@ class CefBrowserPlatformDelegateNative : public CefBrowserPlatformDelegate {
|
||||
bool CanUseSharedTexture() const override;
|
||||
bool CanUseExternalBeginFrame() const override;
|
||||
SkColor GetBackgroundColor() const override;
|
||||
void SynchronizeVisualProperties() override;
|
||||
void WasResized() override;
|
||||
bool IsWindowless() const override;
|
||||
bool IsViewsHosted() const override;
|
||||
|
||||
|
@@ -85,10 +85,10 @@ SkColor CefBrowserPlatformDelegateOsr::GetBackgroundColor() const {
|
||||
return native_delegate_->GetBackgroundColor();
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateOsr::SynchronizeVisualProperties() {
|
||||
void CefBrowserPlatformDelegateOsr::WasResized() {
|
||||
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||
if (view)
|
||||
view->SynchronizeVisualProperties();
|
||||
view->WasResized();
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateOsr::SendKeyEvent(const CefKeyEvent& event) {
|
||||
|
@@ -30,7 +30,7 @@ class CefBrowserPlatformDelegateOsr
|
||||
SkColor GetBackgroundColor() const override;
|
||||
bool CanUseSharedTexture() const override;
|
||||
bool CanUseExternalBeginFrame() const override;
|
||||
void SynchronizeVisualProperties() override;
|
||||
void WasResized() override;
|
||||
void SendKeyEvent(const CefKeyEvent& event) override;
|
||||
void SendMouseClickEvent(const CefMouseEvent& event,
|
||||
CefBrowserHost::MouseButtonType type,
|
||||
|
@@ -149,6 +149,36 @@ ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) {
|
||||
return latency_info;
|
||||
}
|
||||
|
||||
gfx::Rect GetViewBounds(CefBrowserHostImpl* browser) {
|
||||
if (!browser)
|
||||
return gfx::Rect();
|
||||
|
||||
CefRect rc;
|
||||
CefRefPtr<CefRenderHandler> handler =
|
||||
browser->GetClient()->GetRenderHandler();
|
||||
CHECK(handler);
|
||||
|
||||
handler->GetViewRect(browser, rc);
|
||||
CHECK_GT(rc.width, 0);
|
||||
CHECK_GT(rc.height, 0);
|
||||
|
||||
return gfx::Rect(rc.x, rc.y, rc.width, rc.height);
|
||||
}
|
||||
|
||||
float GetDeviceScaleFactor(CefBrowserHostImpl* browser) {
|
||||
if (!browser)
|
||||
return kDefaultScaleFactor;
|
||||
|
||||
CefScreenInfo screen_info(kDefaultScaleFactor, 0, 0, false, CefRect(),
|
||||
CefRect());
|
||||
CefRefPtr<CefRenderHandler> handler = browser->client()->GetRenderHandler();
|
||||
CHECK(handler);
|
||||
if (!handler->GetScreenInfo(browser, screen_info))
|
||||
return kDefaultScaleFactor;
|
||||
|
||||
return screen_info.device_scale_factor;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||
@@ -159,23 +189,12 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||
CefRenderWidgetHostViewOSR* parent_host_view)
|
||||
: content::RenderWidgetHostViewBase(widget),
|
||||
background_color_(background_color),
|
||||
frame_rate_threshold_us_(0),
|
||||
host_display_client_(nullptr),
|
||||
hold_resize_(false),
|
||||
pending_resize_(false),
|
||||
pending_resize_force_(false),
|
||||
render_widget_host_(content::RenderWidgetHostImpl::From(widget)),
|
||||
has_parent_(parent_host_view != nullptr),
|
||||
parent_host_view_(parent_host_view),
|
||||
popup_host_view_(nullptr),
|
||||
child_host_view_(nullptr),
|
||||
is_showing_(false),
|
||||
is_destroyed_(false),
|
||||
pinch_zoom_enabled_(content::IsPinchToZoomEnabled()),
|
||||
is_scroll_offset_changed_pending_(false),
|
||||
mouse_wheel_phase_handler_(this),
|
||||
gesture_provider_(CreateGestureProviderConfig(), this),
|
||||
forward_touch_to_popup_(false),
|
||||
weak_ptr_factory_(this) {
|
||||
DCHECK(render_widget_host_);
|
||||
DCHECK(!render_widget_host_->GetView());
|
||||
@@ -191,9 +210,6 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||
content::RenderViewHost::From(render_widget_host_));
|
||||
}
|
||||
|
||||
local_surface_id_allocator_.GenerateId();
|
||||
local_surface_id_allocation_ =
|
||||
local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
delegated_frame_host_client_.reset(new CefDelegatedFrameHostClient(this));
|
||||
|
||||
// Matching the attributes from BrowserCompositorMac.
|
||||
@@ -231,12 +247,9 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||
if (render_widget_host_impl)
|
||||
render_widget_host_impl->SetCompositorForFlingScheduler(compositor_.get());
|
||||
|
||||
if (browser_impl_.get())
|
||||
ResizeRootLayer(false);
|
||||
|
||||
cursor_manager_.reset(new content::CursorManager(this));
|
||||
|
||||
// Do this last because it may result in a call to SetNeedsBeginFrames.
|
||||
// This may result in a call to GetFrameSinkId().
|
||||
render_widget_host_->SetView(this);
|
||||
|
||||
if (GetTextInputManager())
|
||||
@@ -248,16 +261,13 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||
GetFrameSinkId(), this);
|
||||
}
|
||||
|
||||
if (!render_widget_host_->is_hidden()) {
|
||||
if (browser_impl_ && !parent_host_view_) {
|
||||
// For child/popup views this will be called from the associated InitAs*()
|
||||
// method.
|
||||
SetRootLayerSize(false /* force */);
|
||||
if (!render_widget_host_->is_hidden())
|
||||
Show();
|
||||
}
|
||||
|
||||
if (!content::GpuDataManagerImpl::GetInstance()->IsGpuCompositingDisabled()) {
|
||||
video_consumer_.reset(new CefVideoConsumerOSR(this));
|
||||
video_consumer_->SetActive(true);
|
||||
video_consumer_->SetFrameRate(
|
||||
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_));
|
||||
}
|
||||
}
|
||||
|
||||
CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() {
|
||||
@@ -297,7 +307,7 @@ void CefRenderWidgetHostViewOSR::InitAsChild(gfx::NativeView parent_view) {
|
||||
// The parent view should not render while the full-screen view exists.
|
||||
parent_host_view_->Hide();
|
||||
|
||||
ResizeRootLayer(false);
|
||||
SetRootLayerSize(false /* force */);
|
||||
Show();
|
||||
}
|
||||
|
||||
@@ -321,7 +331,7 @@ bool CefRenderWidgetHostViewOSR::HasFocus() {
|
||||
}
|
||||
|
||||
bool CefRenderWidgetHostViewOSR::IsSurfaceAvailableForCopy() {
|
||||
return GetDelegatedFrameHost()->CanCopyFromCompositingSurface();
|
||||
return delegated_frame_host_->CanCopyFromCompositingSurface();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::Show() {
|
||||
@@ -330,18 +340,42 @@ void CefRenderWidgetHostViewOSR::Show() {
|
||||
|
||||
is_showing_ = true;
|
||||
|
||||
delegated_frame_host_->AttachToCompositor(compositor_.get());
|
||||
delegated_frame_host_->WasShown(
|
||||
GetLocalSurfaceIdAllocation().local_surface_id(),
|
||||
GetRootLayer()->bounds().size(), base::nullopt);
|
||||
// If the viz::LocalSurfaceIdAllocation is invalid, we may have been evicted,
|
||||
// and no other visual properties have since been changed. Allocate a new id
|
||||
// and start synchronizing.
|
||||
if (!GetLocalSurfaceIdAllocation().IsValid()) {
|
||||
AllocateLocalSurfaceId();
|
||||
SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
|
||||
GetLocalSurfaceIdAllocation());
|
||||
}
|
||||
|
||||
// Note that |render_widget_host_| will retrieve size parameters from the
|
||||
// DelegatedFrameHost, so it must have WasShown called after.
|
||||
if (render_widget_host_)
|
||||
if (render_widget_host_) {
|
||||
render_widget_host_->WasShown(
|
||||
base::nullopt /* record_tab_switch_time_request */);
|
||||
}
|
||||
|
||||
delegated_frame_host_->AttachToCompositor(compositor_.get());
|
||||
delegated_frame_host_->WasShown(
|
||||
GetLocalSurfaceIdAllocation().local_surface_id(), GetViewBounds().size(),
|
||||
base::nullopt);
|
||||
|
||||
if (!content::GpuDataManagerImpl::GetInstance()->IsGpuCompositingDisabled()) {
|
||||
// Start generating frames when we're visible and at the correct size.
|
||||
if (!video_consumer_) {
|
||||
video_consumer_.reset(new CefVideoConsumerOSR(this));
|
||||
UpdateFrameRate();
|
||||
|
||||
// Call OnRenderFrameMetadataChangedAfterActivation for every frame.
|
||||
content::RenderFrameMetadataProviderImpl* provider =
|
||||
content::RenderWidgetHostImpl::From(render_widget_host_)
|
||||
->render_frame_metadata_provider();
|
||||
provider->ReportAllFrameSubmissionsForTesting(true);
|
||||
} else {
|
||||
video_consumer_->SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::Hide() {
|
||||
if (!is_showing_)
|
||||
return;
|
||||
@@ -351,12 +385,16 @@ void CefRenderWidgetHostViewOSR::Hide() {
|
||||
if (browser_impl_.get())
|
||||
browser_impl_->CancelContextMenu();
|
||||
|
||||
if (video_consumer_) {
|
||||
video_consumer_->SetActive(false);
|
||||
}
|
||||
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->WasHidden();
|
||||
|
||||
GetDelegatedFrameHost()->WasHidden(
|
||||
delegated_frame_host_->WasHidden(
|
||||
content::DelegatedFrameHost::HiddenCause::kOther);
|
||||
GetDelegatedFrameHost()->DetachFromCompositor();
|
||||
delegated_frame_host_->DetachFromCompositor();
|
||||
}
|
||||
|
||||
bool CefRenderWidgetHostViewOSR::IsShowing() {
|
||||
@@ -365,26 +403,15 @@ bool CefRenderWidgetHostViewOSR::IsShowing() {
|
||||
|
||||
void CefRenderWidgetHostViewOSR::EnsureSurfaceSynchronizedForWebTest() {
|
||||
++latest_capture_sequence_number_;
|
||||
SynchronizeVisualProperties();
|
||||
SynchronizeVisualProperties(cc::DeadlinePolicy::UseInfiniteDeadline(),
|
||||
base::nullopt);
|
||||
}
|
||||
|
||||
gfx::Rect CefRenderWidgetHostViewOSR::GetViewBounds() {
|
||||
if (IsPopupWidget())
|
||||
return popup_position_;
|
||||
|
||||
if (!browser_impl_.get())
|
||||
return gfx::Rect();
|
||||
|
||||
CefRect rc;
|
||||
CefRefPtr<CefRenderHandler> handler =
|
||||
browser_impl_->GetClient()->GetRenderHandler();
|
||||
CHECK(handler);
|
||||
|
||||
handler->GetViewRect(browser_impl_.get(), rc);
|
||||
CHECK_GT(rc.width, 0);
|
||||
CHECK_GT(rc.height, 0);
|
||||
|
||||
return gfx::Rect(rc.x, rc.y, rc.width, rc.height);
|
||||
return current_view_bounds_;
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::SetBackgroundColor(SkColor color) {
|
||||
@@ -416,9 +443,9 @@ void CefRenderWidgetHostViewOSR::TakeFallbackContentFrom(
|
||||
CefRenderWidgetHostViewOSR* view_cef =
|
||||
static_cast<CefRenderWidgetHostViewOSR*>(view);
|
||||
SetBackgroundColor(view_cef->background_color_);
|
||||
if (GetDelegatedFrameHost() && view_cef->GetDelegatedFrameHost()) {
|
||||
GetDelegatedFrameHost()->TakeFallbackContentFrom(
|
||||
view_cef->GetDelegatedFrameHost());
|
||||
if (delegated_frame_host_ && view_cef->delegated_frame_host_) {
|
||||
delegated_frame_host_->TakeFallbackContentFrom(
|
||||
view_cef->delegated_frame_host_.get());
|
||||
}
|
||||
host()->GetContentRenderingTimeoutFrom(view_cef->host());
|
||||
}
|
||||
@@ -432,13 +459,55 @@ void CefRenderWidgetHostViewOSR::OnPresentCompositorFrame() {}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::OnDidUpdateVisualPropertiesComplete(
|
||||
const cc::RenderFrameMetadata& metadata) {
|
||||
bool force = false;
|
||||
if (metadata.local_surface_id_allocation) {
|
||||
force = local_surface_id_allocator_.UpdateFromChild(
|
||||
*metadata.local_surface_id_allocation);
|
||||
if (host()->is_hidden()) {
|
||||
// When an embedded child responds, we want to accept its changes to the
|
||||
// viz::LocalSurfaceId. However we do not want to embed surfaces while
|
||||
// hidden. Nor do we want to embed invalid ids when we are evicted. Becoming
|
||||
// visible will generate a new id, if necessary, and begin embedding.
|
||||
UpdateLocalSurfaceIdFromEmbeddedClient(
|
||||
metadata.local_surface_id_allocation);
|
||||
} else {
|
||||
SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
|
||||
metadata.local_surface_id_allocation);
|
||||
}
|
||||
}
|
||||
|
||||
SynchronizeVisualProperties(force);
|
||||
void CefRenderWidgetHostViewOSR::AllocateLocalSurfaceId() {
|
||||
if (!parent_local_surface_id_allocator_) {
|
||||
parent_local_surface_id_allocator_ =
|
||||
std::make_unique<viz::ParentLocalSurfaceIdAllocator>();
|
||||
}
|
||||
parent_local_surface_id_allocator_->GenerateId();
|
||||
}
|
||||
|
||||
const viz::LocalSurfaceIdAllocation&
|
||||
CefRenderWidgetHostViewOSR::GetCurrentLocalSurfaceIdAllocation() const {
|
||||
return parent_local_surface_id_allocator_
|
||||
->GetCurrentLocalSurfaceIdAllocation();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::UpdateLocalSurfaceIdFromEmbeddedClient(
|
||||
const base::Optional<viz::LocalSurfaceIdAllocation>&
|
||||
embedded_client_local_surface_id_allocation) {
|
||||
if (embedded_client_local_surface_id_allocation) {
|
||||
parent_local_surface_id_allocator_->UpdateFromChild(
|
||||
*embedded_client_local_surface_id_allocation);
|
||||
} else {
|
||||
AllocateLocalSurfaceId();
|
||||
}
|
||||
}
|
||||
|
||||
const viz::LocalSurfaceIdAllocation&
|
||||
CefRenderWidgetHostViewOSR::GetOrCreateLocalSurfaceIdAllocation() {
|
||||
if (!parent_local_surface_id_allocator_)
|
||||
AllocateLocalSurfaceId();
|
||||
return GetCurrentLocalSurfaceIdAllocation();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::InvalidateLocalSurfaceId() {
|
||||
if (!parent_local_surface_id_allocator_)
|
||||
return;
|
||||
parent_local_surface_id_allocator_->Invalidate();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::AddDamageRect(uint32_t sequence,
|
||||
@@ -465,7 +534,7 @@ void CefRenderWidgetHostViewOSR::SubmitCompositorFrame(
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::ResetFallbackToFirstNavigationSurface() {
|
||||
GetDelegatedFrameHost()->ResetFallbackToFirstNavigationSurface();
|
||||
delegated_frame_host_->ResetFallbackToFirstNavigationSurface();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::InitAsPopup(
|
||||
@@ -493,12 +562,9 @@ void CefRenderWidgetHostViewOSR::InitAsPopup(
|
||||
if (handler.get())
|
||||
handler->OnPopupSize(browser_impl_.get(), widget_pos);
|
||||
|
||||
if (video_consumer_) {
|
||||
video_consumer_->SizeChanged();
|
||||
}
|
||||
|
||||
ResizeRootLayer(false);
|
||||
|
||||
// The size doesn't change for popups so we need to force the
|
||||
// initialization.
|
||||
SetRootLayerSize(true /* force */);
|
||||
Show();
|
||||
}
|
||||
|
||||
@@ -635,7 +701,7 @@ void CefRenderWidgetHostViewOSR::CopyFromSurface(
|
||||
const gfx::Rect& src_rect,
|
||||
const gfx::Size& output_size,
|
||||
base::OnceCallback<void(const SkBitmap&)> callback) {
|
||||
GetDelegatedFrameHost()->CopyFromCompositingSurface(src_rect, output_size,
|
||||
delegated_frame_host_->CopyFromCompositingSurface(src_rect, output_size,
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
@@ -702,8 +768,7 @@ CefRenderWidgetHostViewOSR::DidUpdateVisualProperties(
|
||||
#endif
|
||||
|
||||
viz::SurfaceId CefRenderWidgetHostViewOSR::GetCurrentSurfaceId() const {
|
||||
return GetDelegatedFrameHost()
|
||||
? GetDelegatedFrameHost()->GetCurrentSurfaceId()
|
||||
return delegated_frame_host_ ? delegated_frame_host_->GetCurrentSurfaceId()
|
||||
: viz::SurfaceId();
|
||||
}
|
||||
|
||||
@@ -806,17 +871,28 @@ void CefRenderWidgetHostViewOSR::SelectionChanged(const base::string16& text,
|
||||
|
||||
const viz::LocalSurfaceIdAllocation&
|
||||
CefRenderWidgetHostViewOSR::GetLocalSurfaceIdAllocation() const {
|
||||
return local_surface_id_allocation_;
|
||||
return const_cast<CefRenderWidgetHostViewOSR*>(this)
|
||||
->GetOrCreateLocalSurfaceIdAllocation();
|
||||
}
|
||||
|
||||
const viz::FrameSinkId& CefRenderWidgetHostViewOSR::GetFrameSinkId() const {
|
||||
return GetDelegatedFrameHost()->frame_sink_id();
|
||||
return delegated_frame_host_->frame_sink_id();
|
||||
}
|
||||
|
||||
viz::FrameSinkId CefRenderWidgetHostViewOSR::GetRootFrameSinkId() {
|
||||
return compositor_->frame_sink_id();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::OnRenderFrameMetadataChangedAfterActivation() {
|
||||
if (video_consumer_) {
|
||||
// Need to wait for the first frame of the new size before calling
|
||||
// SizeChanged. Otherwise, the video frame will be letterboxed.
|
||||
auto metadata =
|
||||
host_->render_frame_metadata_provider()->LastRenderFrameMetadata();
|
||||
video_consumer_->SizeChanged(metadata.viewport_size_in_pixels);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<content::SyntheticGestureTarget>
|
||||
CefRenderWidgetHostViewOSR::CreateSyntheticGestureTarget() {
|
||||
return std::make_unique<CefSyntheticGestureTargetOSR>(host());
|
||||
@@ -831,8 +907,8 @@ void CefRenderWidgetHostViewOSR::SetNeedsBeginFrames(bool enabled) {
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::SetWantsAnimateOnlyBeginFrames() {
|
||||
if (GetDelegatedFrameHost()) {
|
||||
GetDelegatedFrameHost()->SetWantsAnimateOnlyBeginFrames();
|
||||
if (delegated_frame_host_) {
|
||||
delegated_frame_host_->SetWantsAnimateOnlyBeginFrames();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -850,11 +926,25 @@ bool CefRenderWidgetHostViewOSR::TransformPointToCoordSpaceForView(
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::DidNavigate() {
|
||||
// With surface synchronization enabled we need to force synchronization on
|
||||
// first navigation.
|
||||
ResizeRootLayer(true);
|
||||
if (!IsShowing()) {
|
||||
// Navigating while hidden should not allocate a new LocalSurfaceID. Once
|
||||
// sizes are ready, or we begin to Show, we can then allocate the new
|
||||
// LocalSurfaceId.
|
||||
InvalidateLocalSurfaceId();
|
||||
} else {
|
||||
if (is_first_navigation_) {
|
||||
// The first navigation does not need a new LocalSurfaceID. The renderer
|
||||
// can use the ID that was already provided.
|
||||
SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
|
||||
GetLocalSurfaceIdAllocation());
|
||||
} else {
|
||||
SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
|
||||
base::nullopt);
|
||||
}
|
||||
}
|
||||
if (delegated_frame_host_)
|
||||
delegated_frame_host_->DidNavigate();
|
||||
is_first_navigation_ = false;
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::OnFrameComplete(
|
||||
@@ -881,16 +971,53 @@ bool CefRenderWidgetHostViewOSR::InstallTransparency() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::SynchronizeVisualProperties(bool force) {
|
||||
void CefRenderWidgetHostViewOSR::WasResized() {
|
||||
// Only one resize will be in-flight at a time.
|
||||
if (hold_resize_) {
|
||||
if (!pending_resize_)
|
||||
pending_resize_ = true;
|
||||
if (force)
|
||||
pending_resize_force_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ResizeRootLayer(force);
|
||||
SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
|
||||
base::nullopt);
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::SynchronizeVisualProperties(
|
||||
const cc::DeadlinePolicy& deadline_policy,
|
||||
const base::Optional<viz::LocalSurfaceIdAllocation>&
|
||||
child_local_surface_id_allocation) {
|
||||
SetFrameRate();
|
||||
|
||||
const bool resized = ResizeRootLayer();
|
||||
bool surface_id_updated = false;
|
||||
|
||||
if (!resized && child_local_surface_id_allocation) {
|
||||
// Update the current surface ID.
|
||||
parent_local_surface_id_allocator_->UpdateFromChild(
|
||||
*child_local_surface_id_allocation);
|
||||
surface_id_updated = true;
|
||||
}
|
||||
|
||||
// Allocate a new surface ID if the surface has been resized or if the current
|
||||
// ID is invalid (meaning we may have been evicted).
|
||||
if (resized || !GetCurrentLocalSurfaceIdAllocation().IsValid()) {
|
||||
AllocateLocalSurfaceId();
|
||||
surface_id_updated = true;
|
||||
}
|
||||
|
||||
if (surface_id_updated) {
|
||||
delegated_frame_host_->EmbedSurface(
|
||||
GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
|
||||
GetViewBounds().size(), deadline_policy);
|
||||
|
||||
// |render_widget_host_| will retrieve resize parameters from the
|
||||
// DelegatedFrameHost and this view, so SynchronizeVisualProperties must be
|
||||
// called last.
|
||||
if (render_widget_host_) {
|
||||
render_widget_host_->SynchronizeVisualProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::OnScreenInfoChanged() {
|
||||
@@ -898,7 +1025,8 @@ void CefRenderWidgetHostViewOSR::OnScreenInfoChanged() {
|
||||
if (!render_widget_host_)
|
||||
return;
|
||||
|
||||
SynchronizeVisualProperties();
|
||||
SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
|
||||
base::nullopt);
|
||||
|
||||
if (render_widget_host_->delegate())
|
||||
render_widget_host_->delegate()->SendScreenRects();
|
||||
@@ -1259,32 +1387,16 @@ void CefRenderWidgetHostViewOSR::UpdateFrameRate() {
|
||||
frame_rate_threshold_us_ = 0;
|
||||
SetFrameRate();
|
||||
|
||||
if (video_consumer_) {
|
||||
video_consumer_->SetFrameRate(
|
||||
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_));
|
||||
}
|
||||
|
||||
// Notify the guest hosts if any.
|
||||
for (auto guest_host_view : guest_host_views_)
|
||||
guest_host_view->UpdateFrameRate();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::HoldResize() {
|
||||
if (!hold_resize_)
|
||||
hold_resize_ = true;
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::ReleaseResize() {
|
||||
if (!hold_resize_)
|
||||
return;
|
||||
|
||||
hold_resize_ = false;
|
||||
if (pending_resize_) {
|
||||
bool force = pending_resize_force_;
|
||||
pending_resize_ = false;
|
||||
pending_resize_force_ = false;
|
||||
CEF_POST_TASK(
|
||||
CEF_UIT,
|
||||
base::Bind(&CefRenderWidgetHostViewOSR::SynchronizeVisualProperties,
|
||||
weak_ptr_factory_.GetWeakPtr(), force));
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Size CefRenderWidgetHostViewOSR::SizeInPixels() {
|
||||
return gfx::ConvertSizeToPixel(current_device_scale_factor_,
|
||||
GetViewBounds().size());
|
||||
@@ -1316,10 +1428,6 @@ void CefRenderWidgetHostViewOSR::OnPaint(const gfx::Rect& damage_rect,
|
||||
browser_impl_->client()->GetRenderHandler();
|
||||
CHECK(handler);
|
||||
|
||||
// Don't execute SynchronizeVisualProperties while the OnPaint callback is
|
||||
// pending.
|
||||
HoldResize();
|
||||
|
||||
gfx::Rect rect_in_pixels(0, 0, pixel_size.width(), pixel_size.height());
|
||||
rect_in_pixels.Intersect(damage_rect);
|
||||
|
||||
@@ -1330,18 +1438,15 @@ void CefRenderWidgetHostViewOSR::OnPaint(const gfx::Rect& damage_rect,
|
||||
handler->OnPaint(browser_impl_.get(), IsPopupWidget() ? PET_POPUP : PET_VIEW,
|
||||
rcList, pixels, pixel_size.width(), pixel_size.height());
|
||||
|
||||
ReleaseResize();
|
||||
// Release the resize hold when we reach the desired size.
|
||||
if (hold_resize_ && pixel_size == SizeInPixels())
|
||||
ReleaseResizeHold();
|
||||
}
|
||||
|
||||
ui::Layer* CefRenderWidgetHostViewOSR::GetRootLayer() const {
|
||||
return root_layer_.get();
|
||||
}
|
||||
|
||||
content::DelegatedFrameHost* CefRenderWidgetHostViewOSR::GetDelegatedFrameHost()
|
||||
const {
|
||||
return delegated_frame_host_.get();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::SetFrameRate() {
|
||||
CefRefPtr<CefBrowserHostImpl> browser;
|
||||
if (parent_host_view_) {
|
||||
@@ -1373,19 +1478,13 @@ void CefRenderWidgetHostViewOSR::SetFrameRate() {
|
||||
}
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::SetDeviceScaleFactor() {
|
||||
float new_scale_factor = kDefaultScaleFactor;
|
||||
bool CefRenderWidgetHostViewOSR::SetDeviceScaleFactor() {
|
||||
// This method should not be called while the resize hold is active.
|
||||
DCHECK(!hold_resize_);
|
||||
|
||||
if (browser_impl_.get()) {
|
||||
CefScreenInfo screen_info(kDefaultScaleFactor, 0, 0, false, CefRect(),
|
||||
CefRect());
|
||||
CefRefPtr<CefRenderHandler> handler =
|
||||
browser_impl_->client()->GetRenderHandler();
|
||||
CHECK(handler);
|
||||
if (handler->GetScreenInfo(browser_impl_.get(), screen_info)) {
|
||||
new_scale_factor = screen_info.device_scale_factor;
|
||||
}
|
||||
}
|
||||
const float new_scale_factor = ::GetDeviceScaleFactor(browser_impl_.get());
|
||||
if (new_scale_factor == current_device_scale_factor_)
|
||||
return false;
|
||||
|
||||
current_device_scale_factor_ = new_scale_factor;
|
||||
|
||||
@@ -1397,52 +1496,69 @@ void CefRenderWidgetHostViewOSR::SetDeviceScaleFactor() {
|
||||
if (rwhi->GetView())
|
||||
rwhi->GetView()->set_current_device_scale_factor(new_scale_factor);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::ResizeRootLayer(bool force) {
|
||||
SetFrameRate();
|
||||
bool CefRenderWidgetHostViewOSR::SetViewBounds() {
|
||||
// This method should not be called while the resize hold is active.
|
||||
DCHECK(!hold_resize_);
|
||||
|
||||
const float orgScaleFactor = current_device_scale_factor_;
|
||||
SetDeviceScaleFactor();
|
||||
const bool scaleFactorDidChange =
|
||||
(orgScaleFactor != current_device_scale_factor_);
|
||||
// Popup bounds are set in InitAsPopup.
|
||||
if (IsPopupWidget())
|
||||
return false;
|
||||
|
||||
gfx::Size size;
|
||||
if (!IsPopupWidget())
|
||||
size = GetViewBounds().size();
|
||||
else
|
||||
size = popup_position_.size();
|
||||
const gfx::Rect& new_bounds = ::GetViewBounds(browser_impl_.get());
|
||||
if (new_bounds == current_view_bounds_)
|
||||
return false;
|
||||
|
||||
if (!force && !scaleFactorDidChange &&
|
||||
size == GetRootLayer()->bounds().size()) {
|
||||
return;
|
||||
current_view_bounds_ = new_bounds;
|
||||
return true;
|
||||
}
|
||||
|
||||
GetRootLayer()->SetBounds(gfx::Rect(size));
|
||||
bool CefRenderWidgetHostViewOSR::SetRootLayerSize(bool force) {
|
||||
const bool scale_factor_changed = SetDeviceScaleFactor();
|
||||
const bool view_bounds_changed = SetViewBounds();
|
||||
if (!force && !scale_factor_changed && !view_bounds_changed)
|
||||
return false;
|
||||
|
||||
const gfx::Size& size_in_pixels =
|
||||
gfx::ConvertSizeToPixel(current_device_scale_factor_, size);
|
||||
|
||||
local_surface_id_allocator_.GenerateId();
|
||||
local_surface_id_allocation_ =
|
||||
local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
GetRootLayer()->SetBounds(gfx::Rect(GetViewBounds().size()));
|
||||
|
||||
if (compositor_) {
|
||||
compositor_local_surface_id_allocator_.GenerateId();
|
||||
compositor_->SetScaleAndSize(current_device_scale_factor_, size_in_pixels,
|
||||
compositor_->SetScaleAndSize(current_device_scale_factor_, SizeInPixels(),
|
||||
compositor_local_surface_id_allocator_
|
||||
.GetCurrentLocalSurfaceIdAllocation());
|
||||
}
|
||||
|
||||
GetDelegatedFrameHost()->EmbedSurface(
|
||||
local_surface_id_allocation_.local_surface_id(), size,
|
||||
cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
return (scale_factor_changed || view_bounds_changed);
|
||||
}
|
||||
|
||||
// Note that |render_widget_host_| will retrieve resize parameters from the
|
||||
// DelegatedFrameHost, so it must have SynchronizeVisualProperties called
|
||||
// after.
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->SynchronizeVisualProperties();
|
||||
bool CefRenderWidgetHostViewOSR::ResizeRootLayer() {
|
||||
if (!hold_resize_) {
|
||||
// The resize hold is not currently active.
|
||||
if (SetRootLayerSize(false /* force */)) {
|
||||
// The size has changed. Avoid resizing again until ReleaseResizeHold() is
|
||||
// called.
|
||||
hold_resize_ = true;
|
||||
return true;
|
||||
}
|
||||
} else if (!pending_resize_) {
|
||||
// The resize hold is currently active. Another resize will be triggered
|
||||
// from ReleaseResizeHold().
|
||||
pending_resize_ = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::ReleaseResizeHold() {
|
||||
DCHECK(hold_resize_);
|
||||
hold_resize_ = false;
|
||||
if (pending_resize_) {
|
||||
pending_resize_ = false;
|
||||
CEF_POST_TASK(CEF_UIT, base::Bind(&CefRenderWidgetHostViewOSR::WasResized,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
}
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::CancelWidget() {
|
||||
@@ -1509,7 +1625,7 @@ void CefRenderWidgetHostViewOSR::RemoveGuestHostView(
|
||||
void CefRenderWidgetHostViewOSR::InvalidateInternal(
|
||||
const gfx::Rect& bounds_in_pixels) {
|
||||
if (video_consumer_) {
|
||||
video_consumer_->SizeChanged();
|
||||
video_consumer_->RequestRefreshFrame(bounds_in_pixels);
|
||||
} else if (host_display_client_) {
|
||||
OnPaint(bounds_in_pixels, host_display_client_->GetPixelSize(),
|
||||
host_display_client_->GetPixelMemory());
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/optional.h"
|
||||
#include "build/build_config.h"
|
||||
#include "cc/layers/deadline_policy.h"
|
||||
#include "components/viz/common/frame_sinks/begin_frame_source.h"
|
||||
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
|
||||
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
|
||||
@@ -189,6 +190,7 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
const override;
|
||||
const viz::FrameSinkId& GetFrameSinkId() const override;
|
||||
viz::FrameSinkId GetRootFrameSinkId() override;
|
||||
void OnRenderFrameMetadataChangedAfterActivation() override;
|
||||
|
||||
void OnFrameComplete(const viz::BeginFrameAck& ack);
|
||||
|
||||
@@ -208,7 +210,11 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
|
||||
bool InstallTransparency();
|
||||
|
||||
void SynchronizeVisualProperties(bool force = false);
|
||||
void WasResized();
|
||||
void SynchronizeVisualProperties(
|
||||
const cc::DeadlinePolicy& deadline_policy,
|
||||
const base::Optional<viz::LocalSurfaceIdAllocation>&
|
||||
child_local_surface_id_allocation);
|
||||
void OnScreenInfoChanged();
|
||||
void Invalidate(CefBrowserHost::PaintElementType type);
|
||||
void SendExternalBeginFrame();
|
||||
@@ -220,9 +226,6 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
void SendFocusEvent(bool focus);
|
||||
void UpdateFrameRate();
|
||||
|
||||
void HoldResize();
|
||||
void ReleaseResize();
|
||||
|
||||
gfx::Size SizeInPixels();
|
||||
void OnPaint(const gfx::Rect& damage_rect,
|
||||
const gfx::Size& pixel_size,
|
||||
@@ -269,11 +272,14 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
const cc::RenderFrameMetadata& metadata);
|
||||
|
||||
private:
|
||||
content::DelegatedFrameHost* GetDelegatedFrameHost() const;
|
||||
|
||||
void SetFrameRate();
|
||||
void SetDeviceScaleFactor();
|
||||
void ResizeRootLayer(bool force);
|
||||
bool SetDeviceScaleFactor();
|
||||
bool SetViewBounds();
|
||||
bool SetRootLayerSize(bool force);
|
||||
|
||||
// Manages resizing so that only one resize request is in-flight at a time.
|
||||
bool ResizeRootLayer();
|
||||
void ReleaseResizeHold();
|
||||
|
||||
void CancelWidget();
|
||||
|
||||
@@ -296,6 +302,27 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
|
||||
viz::FrameSinkId AllocateFrameSinkId();
|
||||
|
||||
// Forces the view to allocate a new viz::LocalSurfaceId for the next
|
||||
// CompositorFrame submission in anticipation of a synchronization operation
|
||||
// that does not involve a resize or a device scale factor change.
|
||||
void AllocateLocalSurfaceId();
|
||||
const viz::LocalSurfaceIdAllocation& GetCurrentLocalSurfaceIdAllocation()
|
||||
const;
|
||||
|
||||
// Sets the current viz::LocalSurfaceId, in cases where the embedded client
|
||||
// has allocated one. Also sets child sequence number component of the
|
||||
// viz::LocalSurfaceId allocator.
|
||||
void UpdateLocalSurfaceIdFromEmbeddedClient(
|
||||
const base::Optional<viz::LocalSurfaceIdAllocation>&
|
||||
local_surface_id_allocation);
|
||||
|
||||
// Returns the current viz::LocalSurfaceIdAllocation.
|
||||
const viz::LocalSurfaceIdAllocation& GetOrCreateLocalSurfaceIdAllocation();
|
||||
|
||||
// Marks the current viz::LocalSurfaceId as invalid. AllocateLocalSurfaceId
|
||||
// must be called before submitting new CompositorFrames.
|
||||
void InvalidateLocalSurfaceId();
|
||||
|
||||
void AddDamageRect(uint32_t sequence, const gfx::Rect& rect);
|
||||
|
||||
// Applies background color without notifying the RenderWidget about
|
||||
@@ -309,15 +336,17 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
// The background color of the web content.
|
||||
SkColor background_color_;
|
||||
|
||||
int frame_rate_threshold_us_;
|
||||
int frame_rate_threshold_us_ = 0;
|
||||
|
||||
std::unique_ptr<ui::Compositor> compositor_;
|
||||
std::unique_ptr<content::DelegatedFrameHost> delegated_frame_host_;
|
||||
std::unique_ptr<content::DelegatedFrameHostClient>
|
||||
delegated_frame_host_client_;
|
||||
std::unique_ptr<ui::Layer> root_layer_;
|
||||
viz::LocalSurfaceIdAllocation local_surface_id_allocation_;
|
||||
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
|
||||
|
||||
// Used to allocate LocalSurfaceIds when this is embedding external content.
|
||||
std::unique_ptr<viz::ParentLocalSurfaceIdAllocator>
|
||||
parent_local_surface_id_allocator_;
|
||||
viz::ParentLocalSurfaceIdAllocator compositor_local_surface_id_allocator_;
|
||||
|
||||
#if defined(USE_X11)
|
||||
@@ -334,12 +363,11 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
bool external_begin_frame_enabled_ = false;
|
||||
bool needs_external_begin_frames_ = false;
|
||||
|
||||
CefHostDisplayClientOSR* host_display_client_;
|
||||
CefHostDisplayClientOSR* host_display_client_ = nullptr;
|
||||
std::unique_ptr<CefVideoConsumerOSR> video_consumer_;
|
||||
|
||||
bool hold_resize_;
|
||||
bool pending_resize_;
|
||||
bool pending_resize_force_;
|
||||
bool hold_resize_ = false;
|
||||
bool pending_resize_ = false;
|
||||
|
||||
// The associated Model. While |this| is being Destroyed,
|
||||
// |render_widget_host_| is NULL and the message loop is run one last time
|
||||
@@ -348,14 +376,16 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
|
||||
bool has_parent_;
|
||||
CefRenderWidgetHostViewOSR* parent_host_view_;
|
||||
CefRenderWidgetHostViewOSR* popup_host_view_;
|
||||
CefRenderWidgetHostViewOSR* child_host_view_;
|
||||
CefRenderWidgetHostViewOSR* popup_host_view_ = nullptr;
|
||||
CefRenderWidgetHostViewOSR* child_host_view_ = nullptr;
|
||||
std::set<CefRenderWidgetHostViewOSR*> guest_host_views_;
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> browser_impl_;
|
||||
|
||||
bool is_showing_;
|
||||
bool is_destroyed_;
|
||||
bool is_showing_ = false;
|
||||
bool is_destroyed_ = false;
|
||||
bool is_first_navigation_ = true;
|
||||
gfx::Rect current_view_bounds_;
|
||||
gfx::Rect popup_position_;
|
||||
base::Lock damage_rect_lock_;
|
||||
std::map<uint32_t, gfx::Rect> damage_rects_;
|
||||
@@ -366,7 +396,7 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
|
||||
// The last scroll offset of the view.
|
||||
gfx::Vector2dF last_scroll_offset_;
|
||||
bool is_scroll_offset_changed_pending_;
|
||||
bool is_scroll_offset_changed_pending_ = false;
|
||||
|
||||
content::MouseWheelPhaseHandler mouse_wheel_phase_handler_;
|
||||
|
||||
@@ -382,7 +412,7 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
ui::FilteredGestureProvider gesture_provider_;
|
||||
|
||||
CefMotionEventOSR pointer_state_;
|
||||
bool forward_touch_to_popup_;
|
||||
bool forward_touch_to_popup_ = false;
|
||||
|
||||
base::WeakPtrFactory<CefRenderWidgetHostViewOSR> weak_ptr_factory_;
|
||||
|
||||
|
@@ -11,16 +11,35 @@
|
||||
#include "media/capture/mojom/video_capture_types.mojom.h"
|
||||
#include "ui/gfx/skbitmap_operations.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper to always call Done() at the end of OnFrameCaptured().
|
||||
class ScopedVideoFrameDone {
|
||||
public:
|
||||
explicit ScopedVideoFrameDone(
|
||||
mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
|
||||
callbacks)
|
||||
: callbacks_(std::move(callbacks)) {}
|
||||
~ScopedVideoFrameDone() { callbacks_->Done(); }
|
||||
|
||||
private:
|
||||
mojo::Remote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks> callbacks_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
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());
|
||||
: view_(view), video_capturer_(view->CreateVideoCapturer()) {
|
||||
video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB,
|
||||
gfx::ColorSpace::CreateREC709());
|
||||
|
||||
// Always use the highest resolution within constraints that doesn't exceed
|
||||
// the source size.
|
||||
video_capturer_->SetAutoThrottlingEnabled(false);
|
||||
video_capturer_->SetMinSizeChangePeriod(base::TimeDelta());
|
||||
|
||||
SizeChanged(view_->SizeInPixels());
|
||||
SetActive(true);
|
||||
}
|
||||
|
||||
CefVideoConsumerOSR::~CefVideoConsumerOSR() = default;
|
||||
@@ -37,42 +56,49 @@ 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);
|
||||
void CefVideoConsumerOSR::SizeChanged(const gfx::Size& size_in_pixels) {
|
||||
if (size_in_pixels_ == size_in_pixels)
|
||||
return;
|
||||
size_in_pixels_ = size_in_pixels;
|
||||
|
||||
// Capture resolution will be held constant.
|
||||
video_capturer_->SetResolutionConstraints(size_in_pixels, size_in_pixels,
|
||||
true /* use_fixed_aspect_ratio */);
|
||||
}
|
||||
|
||||
void CefVideoConsumerOSR::RequestRefreshFrame(
|
||||
const base::Optional<gfx::Rect>& bounds_in_pixels) {
|
||||
bounds_in_pixels_ = bounds_in_pixels;
|
||||
video_capturer_->RequestRefreshFrame();
|
||||
}
|
||||
|
||||
// Frame size values are as follows:
|
||||
// info->coded_size = Width and height of the video frame. Not all pixels in
|
||||
// this region are valid.
|
||||
// info->visible_rect = Region of coded_size that contains image data, also
|
||||
// known as the clean aperture.
|
||||
// content_rect = Region of the frame that contains the captured content, with
|
||||
// the rest of the frame having been letterboxed to adhere to resolution
|
||||
// constraints.
|
||||
void CefVideoConsumerOSR::OnFrameCaptured(
|
||||
base::ReadOnlySharedMemoryRegion data,
|
||||
::media::mojom::VideoFrameInfoPtr info,
|
||||
const gfx::Rect& content_rect,
|
||||
mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
|
||||
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;
|
||||
}
|
||||
ScopedVideoFrameDone scoped_done(std::move(callbacks));
|
||||
|
||||
mojo::Remote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
|
||||
callbacks_remote(std::move(callbacks));
|
||||
|
||||
if (!data.IsValid()) {
|
||||
callbacks_remote->Done();
|
||||
if (!data.IsValid())
|
||||
return;
|
||||
}
|
||||
|
||||
base::ReadOnlySharedMemoryMapping mapping = data.Map();
|
||||
if (!mapping.IsValid()) {
|
||||
DLOG(ERROR) << "Shared memory mapping failed.";
|
||||
callbacks_remote->Done();
|
||||
return;
|
||||
}
|
||||
if (mapping.size() <
|
||||
media::VideoFrame::AllocationSize(info->pixel_format, info->coded_size)) {
|
||||
DLOG(ERROR) << "Shared memory size was less than expected.";
|
||||
callbacks_remote->Done();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -84,15 +110,27 @@ void CefVideoConsumerOSR::OnFrameCaptured(
|
||||
metadata.MergeInternalValuesFrom(info->metadata);
|
||||
gfx::Rect damage_rect;
|
||||
|
||||
if (bounds_in_pixels_) {
|
||||
// Use the bounds passed to RequestRefreshFrame().
|
||||
damage_rect = gfx::Rect(info->coded_size);
|
||||
damage_rect.Intersect(*bounds_in_pixels_);
|
||||
bounds_in_pixels_ = base::nullopt;
|
||||
} else {
|
||||
// Retrieve the rectangular region of the frame that has changed since the
|
||||
// frame with the directly preceding CAPTURE_COUNTER. If that frame was not
|
||||
// received, typically because it was dropped during transport from the
|
||||
// producer, clients must assume that the entire frame has changed.
|
||||
// This rectangle is relative to the full frame data, i.e. [0, 0,
|
||||
// coded_size.width(), coded_size.height()]. It does not have to be
|
||||
// fully contained within visible_rect.
|
||||
if (!metadata.GetRect(media::VideoFrameMetadata::CAPTURE_UPDATE_RECT,
|
||||
&damage_rect) ||
|
||||
damage_rect.IsEmpty()) {
|
||||
damage_rect = content_rect;
|
||||
damage_rect = gfx::Rect(info->coded_size);
|
||||
}
|
||||
}
|
||||
|
||||
view_->OnPaint(damage_rect, info->coded_size, pixels);
|
||||
|
||||
callbacks_remote->Done();
|
||||
}
|
||||
|
||||
void CefVideoConsumerOSR::OnStopped() {}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#define LIBCEF_BROWSER_OSR_VIDEO_CONSUMER_OSR_H_
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/optional.h"
|
||||
#include "components/viz/host/client_frame_sink_video_capturer.h"
|
||||
#include "media/capture/mojom/video_capture_types.mojom.h"
|
||||
|
||||
@@ -15,7 +15,8 @@ class CefVideoConsumerOSR : public viz::mojom::FrameSinkVideoConsumer {
|
||||
|
||||
void SetActive(bool active);
|
||||
void SetFrameRate(base::TimeDelta frame_rate);
|
||||
void SizeChanged();
|
||||
void SizeChanged(const gfx::Size& size_in_pixels);
|
||||
void RequestRefreshFrame(const base::Optional<gfx::Rect>& bounds_in_pixels);
|
||||
|
||||
private:
|
||||
// viz::mojom::FrameSinkVideoConsumer implementation.
|
||||
@@ -30,7 +31,8 @@ class CefVideoConsumerOSR : public viz::mojom::FrameSinkVideoConsumer {
|
||||
CefRenderWidgetHostViewOSR* const view_;
|
||||
std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer_;
|
||||
|
||||
base::WeakPtrFactory<CefVideoConsumerOSR> weak_ptr_factory_;
|
||||
gfx::Size size_in_pixels_;
|
||||
base::Optional<gfx::Rect> bounds_in_pixels_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefVideoConsumerOSR);
|
||||
};
|
||||
|
@@ -184,8 +184,8 @@ SkColor CefBrowserPlatformDelegateViews::GetBackgroundColor() const {
|
||||
return native_delegate_->GetBackgroundColor();
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateViews::SynchronizeVisualProperties() {
|
||||
native_delegate_->SynchronizeVisualProperties();
|
||||
void CefBrowserPlatformDelegateViews::WasResized() {
|
||||
native_delegate_->WasResized();
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateViews::SendKeyEvent(const CefKeyEvent& event) {
|
||||
|
@@ -42,7 +42,7 @@ class CefBrowserPlatformDelegateViews
|
||||
bool CanUseSharedTexture() const override;
|
||||
bool CanUseExternalBeginFrame() const override;
|
||||
SkColor GetBackgroundColor() const override;
|
||||
void SynchronizeVisualProperties() override;
|
||||
void WasResized() override;
|
||||
void SendKeyEvent(const CefKeyEvent& event) override;
|
||||
void SendMouseClickEvent(const CefMouseEvent& event,
|
||||
CefBrowserHost::MouseButtonType type,
|
||||
|
@@ -626,13 +626,18 @@ class OSRTestHandler : public RoutingTestHandler,
|
||||
case OSR_TEST_RESIZE:
|
||||
if (StartTest()) {
|
||||
browser->GetHost()->WasResized();
|
||||
// There may be some partial repaints before the full repaint.
|
||||
} else if (IsFullRepaint(dirtyRects[0], width, height)) {
|
||||
EXPECT_EQ(GetScaledInt(kOsrWidth) * 2, width);
|
||||
EXPECT_EQ(GetScaledInt(kOsrHeight) * 2, height);
|
||||
} else {
|
||||
// There may be some partial repaints before the full repaint at the
|
||||
// desired size.
|
||||
const int desired_width = GetScaledInt(kOsrWidth) * 2;
|
||||
const int desired_height = GetScaledInt(kOsrHeight) * 2;
|
||||
|
||||
EXPECT_EQ(dirtyRects.size(), 1U);
|
||||
if (width == desired_width && height == desired_height &&
|
||||
IsFullRepaint(dirtyRects[0], width, height)) {
|
||||
DestroySucceededTestSoon();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OSR_TEST_INVALIDATE: {
|
||||
if (StartTest()) {
|
||||
|
Reference in New Issue
Block a user