Commit fd08f984 authored by Albert Chaulk's avatar Albert Chaulk Committed by Commit Bot

Fix layer ordering with exo subsurfaces & webviews

An exo surface is collapsed into a single CompositorFrame during
presentation; if there is an aura window displaying webcontents it
will be rendered on top of all exo content due to the actual viz
layer structure

This replaces the contents of an exo layer with the web contents
by emitting a SurfaceDrawQuad instead, drawing the web contents in
the correct position

As a consequence the aura window corresponding to the web contents
is hidden as we do not want it drawn in the usual aura manner

Bug: b/141980352
Test: desktop build w/ webview
Change-Id: If45aa68e80f115f36ef0edee34f03c09f06dfcf1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1850366Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Reviewed-by: default avatarAlex Sakhartchouk <alexst@chromium.org>
Commit-Queue: Albert Chaulk <achaulk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#705112}
parent 7be0e2ce
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/web_preferences.h" #include "content/public/common/web_preferences.h"
...@@ -69,6 +70,11 @@ WebviewController::WebviewController(content::BrowserContext* browser_context, ...@@ -69,6 +70,11 @@ WebviewController::WebviewController(content::BrowserContext* browser_context,
WebviewController::~WebviewController() { WebviewController::~WebviewController() {
cast_web_contents_->RemoveObserver(this); cast_web_contents_->RemoveObserver(this);
if (surface_) {
surface_->RemoveSurfaceObserver(this);
surface_->SetEmbeddedSurfaceId(base::RepeatingCallback<viz::SurfaceId()>());
}
} }
std::unique_ptr<content::NavigationThrottle> std::unique_ptr<content::NavigationThrottle>
...@@ -212,13 +218,42 @@ void WebviewController::ClosePage() { ...@@ -212,13 +218,42 @@ void WebviewController::ClosePage() {
cast_web_contents_->ClosePage(); cast_web_contents_->ClosePage();
} }
viz::SurfaceId WebviewController::GetSurfaceId() {
auto* rwhv = contents_->GetRenderWidgetHostView();
if (!rwhv)
return viz::SurfaceId();
auto frame_sink_id = rwhv->GetRenderWidgetHost()->GetFrameSinkId();
auto local_surface_id =
rwhv->GetNativeView()->GetLocalSurfaceIdAllocation().local_surface_id();
return viz::SurfaceId(frame_sink_id, local_surface_id);
}
void WebviewController::AttachTo(aura::Window* window, int window_id) { void WebviewController::AttachTo(aura::Window* window, int window_id) {
auto* contents_window = contents_->GetNativeView(); auto* contents_window = contents_->GetNativeView();
window->SetLayoutManager(new WebviewLayoutManager(contents_window)); window->SetLayoutManager(new WebviewLayoutManager(window, contents_window));
contents_window->set_id(window_id); contents_window->set_id(window_id);
contents_window->SetBounds(gfx::Rect(window->bounds().size())); contents_window->SetBounds(gfx::Rect(window->bounds().size()));
contents_window->Show(); // The aura window is hidden to avoid being shown via the usual layer method,
window->AddChild(contents_->GetNativeView()); // instead it is shows via a SurfaceDrawQuad by exo.
contents_window->Hide();
window->AddChild(contents_window);
exo::Surface* surface = exo::Surface::AsSurface(window);
CHECK(surface) << "Attaching Webview to non-EXO surface window";
CHECK(!surface_) << "Attaching already attached WebView";
surface_ = surface;
surface_->AddSurfaceObserver(this);
// Unretained is safe because we unset this in the destructor.
surface_->SetEmbeddedSurfaceId(
base::Bind(&WebviewController::GetSurfaceId, base::Unretained(this)));
}
void WebviewController::OnSurfaceDestroying(exo::Surface* surface) {
DCHECK_EQ(surface, surface_);
surface->RemoveSurfaceObserver(this);
surface_ = nullptr;
} }
void WebviewController::ProcessInputEvent(const webview::InputEvent& ev) { void WebviewController::ProcessInputEvent(const webview::InputEvent& ev) {
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "base/supports_user_data.h" #include "base/supports_user_data.h"
#include "chromecast/browser/cast_web_contents.h" #include "chromecast/browser/cast_web_contents.h"
#include "chromecast/browser/webview/proto/webview.pb.h" #include "chromecast/browser/webview/proto/webview.pb.h"
#include "components/exo/surface.h"
#include "components/exo/surface_observer.h"
#include "ui/events/gestures/gesture_recognizer_impl.h" #include "ui/events/gestures/gesture_recognizer_impl.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -36,7 +38,8 @@ class WebviewNavigationThrottle; ...@@ -36,7 +38,8 @@ class WebviewNavigationThrottle;
// This owns a WebContents and CastWebContents and processes proto commands // This owns a WebContents and CastWebContents and processes proto commands
// to allow the web contents to be controlled and embedded. // to allow the web contents to be controlled and embedded.
class WebviewController : public CastWebContents::Delegate, class WebviewController : public CastWebContents::Delegate,
public CastWebContents::Observer { public CastWebContents::Observer,
public exo::SurfaceObserver {
public: public:
class Client { class Client {
public: public:
...@@ -90,6 +93,7 @@ class WebviewController : public CastWebContents::Delegate, ...@@ -90,6 +93,7 @@ class WebviewController : public CastWebContents::Delegate,
void HandleUpdateSettings(const webview::UpdateSettingsRequest& request); void HandleUpdateSettings(const webview::UpdateSettingsRequest& request);
void HandleSetAutoMediaPlaybackPolicy( void HandleSetAutoMediaPlaybackPolicy(
const webview::SetAutoMediaPlaybackPolicyRequest& request); const webview::SetAutoMediaPlaybackPolicyRequest& request);
viz::SurfaceId GetSurfaceId();
bool Check(bool condition, const char* error); bool Check(bool condition, const char* error);
...@@ -101,6 +105,9 @@ class WebviewController : public CastWebContents::Delegate, ...@@ -101,6 +105,9 @@ class WebviewController : public CastWebContents::Delegate,
// CastWebContents::Observer // CastWebContents::Observer
void ResourceLoadFailed(CastWebContents* cast_web_contents) override; void ResourceLoadFailed(CastWebContents* cast_web_contents) override;
// exo::SurfaceObserver
void OnSurfaceDestroying(exo::Surface* surface) override;
Client* client_; // Not owned. Client* client_; // Not owned.
std::unique_ptr<content::WebContents> contents_; std::unique_ptr<content::WebContents> contents_;
std::unique_ptr<CastWebContents> cast_web_contents_; std::unique_ptr<CastWebContents> cast_web_contents_;
...@@ -110,6 +117,8 @@ class WebviewController : public CastWebContents::Delegate, ...@@ -110,6 +117,8 @@ class WebviewController : public CastWebContents::Delegate,
ui::GestureRecognizerImpl gesture_recognizer_; ui::GestureRecognizerImpl gesture_recognizer_;
exo::Surface* surface_ = nullptr;
// The navigation throttle for the current navigation event, if any. // The navigation throttle for the current navigation event, if any.
// Is set only: // Is set only:
// When has_navigation_delegate is true, and // When has_navigation_delegate is true, and
......
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
namespace chromecast { namespace chromecast {
WebviewLayoutManager::WebviewLayoutManager(aura::Window* web_contents_window) WebviewLayoutManager::WebviewLayoutManager(aura::Window* parent,
: web_contents_window_(web_contents_window) {} aura::Window* web_contents_window)
: parent_(parent), web_contents_window_(web_contents_window) {}
WebviewLayoutManager::~WebviewLayoutManager() {} WebviewLayoutManager::~WebviewLayoutManager() {}
void WebviewLayoutManager::OnWindowResized() { void WebviewLayoutManager::OnWindowResized() {
web_contents_window_->SetBounds( web_contents_window_->SetBounds(gfx::Rect(parent_->bounds().size()));
gfx::Rect(web_contents_window_->parent()->bounds().size()));
} }
void WebviewLayoutManager::OnWindowAddedToLayout(aura::Window* child) {} void WebviewLayoutManager::OnWindowAddedToLayout(aura::Window* child) {}
......
...@@ -13,7 +13,7 @@ namespace chromecast { ...@@ -13,7 +13,7 @@ namespace chromecast {
// Resizes the provided window to be the parent window's size. // Resizes the provided window to be the parent window's size.
class WebviewLayoutManager : public aura::LayoutManager { class WebviewLayoutManager : public aura::LayoutManager {
public: public:
explicit WebviewLayoutManager(aura::Window* web_contents_window); WebviewLayoutManager(aura::Window* parent, aura::Window* web_contents_window);
~WebviewLayoutManager() override; ~WebviewLayoutManager() override;
void OnWindowResized() override; void OnWindowResized() override;
...@@ -26,6 +26,7 @@ class WebviewLayoutManager : public aura::LayoutManager { ...@@ -26,6 +26,7 @@ class WebviewLayoutManager : public aura::LayoutManager {
const gfx::Rect& requested_bounds) override; const gfx::Rect& requested_bounds) override;
private: private:
aura::Window* parent_;
aura::Window* web_contents_window_; aura::Window* web_contents_window_;
DISALLOW_COPY_AND_ASSIGN(WebviewLayoutManager); DISALLOW_COPY_AND_ASSIGN(WebviewLayoutManager);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "components/viz/common/quads/render_pass.h" #include "components/viz/common/quads/render_pass.h"
#include "components/viz/common/quads/shared_quad_state.h" #include "components/viz/common/quads/shared_quad_state.h"
#include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/resources/single_release_callback.h" #include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/service/surfaces/surface.h" #include "components/viz/service/surfaces/surface.h"
...@@ -540,6 +541,12 @@ int32_t Surface::GetClientSurfaceId() const { ...@@ -540,6 +541,12 @@ int32_t Surface::GetClientSurfaceId() const {
return window_->GetProperty(kClientSurfaceIdKey); return window_->GetProperty(kClientSurfaceIdKey);
} }
void Surface::SetEmbeddedSurfaceId(
base::RepeatingCallback<viz::SurfaceId()> surface_id_callback) {
get_current_surface_id_ = std::move(surface_id_callback);
first_embedded_surface_id_ = viz::SurfaceId();
}
void Surface::SetAcquireFence(std::unique_ptr<gfx::GpuFence> gpu_fence) { void Surface::SetAcquireFence(std::unique_ptr<gfx::GpuFence> gpu_fence) {
TRACE_EVENT1("exo", "Surface::SetAcquireFence", "fence_fd", TRACE_EVENT1("exo", "Surface::SetAcquireFence", "fence_fd",
gpu_fence ? gpu_fence->GetGpuFenceHandle().native_fd.fd : -1); gpu_fence ? gpu_fence->GetGpuFenceHandle().native_fd.fd : -1);
...@@ -1013,14 +1020,33 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin, ...@@ -1013,14 +1020,33 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin,
buffer_transform_.TransformRectReverse(&uv_crop); buffer_transform_.TransformRectReverse(&uv_crop);
} }
// Texture quad is only needed if buffer is not fully transparent. SkColor background_color = SK_ColorTRANSPARENT;
if (state_.alpha) { if (current_resource_has_alpha_ && are_contents_opaque)
background_color = SK_ColorBLACK; // Avoid writing alpha < 1
// If this surface is being replaced by a SurfaceId emit a SurfaceDrawQuad.
if (get_current_surface_id_) {
auto current_surface_id = get_current_surface_id_.Run();
if (current_surface_id.is_valid()) {
if (!first_embedded_surface_id_.is_valid())
first_embedded_surface_id_ = current_surface_id;
viz::SurfaceDrawQuad* surface_quad =
render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
surface_quad->SetNew(
quad_state, quad_rect, quad_rect,
viz::SurfaceRange(first_embedded_surface_id_, current_surface_id),
background_color,
/*stretch_content_to_fill_bounds=*/true,
/*ignores_input_event=*/false);
} else {
// If there is no valid surface, reset the start of the range.
first_embedded_surface_id_ = viz::SurfaceId();
}
} else if (state_.alpha) {
// Texture quad is only needed if buffer is not fully transparent.
viz::TextureDrawQuad* texture_quad = viz::TextureDrawQuad* texture_quad =
render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0}; float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
SkColor background_color = SK_ColorTRANSPARENT;
if (current_resource_has_alpha_ && are_contents_opaque)
background_color = SK_ColorBLACK; // Avoid writing alpha < 1
texture_quad->SetNew( texture_quad->SetNew(
quad_state, quad_rect, quad_rect, quad_state, quad_rect, quad_rect,
/* needs_blending=*/!are_contents_opaque, current_resource_.id, /* needs_blending=*/!are_contents_opaque, current_resource_.id,
......
...@@ -170,6 +170,12 @@ class Surface final : public ui::PropertyHandler { ...@@ -170,6 +170,12 @@ class Surface final : public ui::PropertyHandler {
void SetClientSurfaceId(int32_t client_surface_id); void SetClientSurfaceId(int32_t client_surface_id);
int32_t GetClientSurfaceId() const; int32_t GetClientSurfaceId() const;
// Enable embedding of an arbitrary viz surface in this exo surface.
// If the callback is valid, a SurfaceDrawQuad will be emitted targeting
// the returned SurfaceId each frame.
void SetEmbeddedSurfaceId(
base::RepeatingCallback<viz::SurfaceId()> surface_id_callback);
// Request that the attached surface buffer at the next commit is associated // Request that the attached surface buffer at the next commit is associated
// with a gpu fence to be signaled when the buffer is ready for use. // with a gpu fence to be signaled when the buffer is ready for use.
void SetAcquireFence(std::unique_ptr<gfx::GpuFence> gpu_fence); void SetAcquireFence(std::unique_ptr<gfx::GpuFence> gpu_fence);
...@@ -440,6 +446,9 @@ class Surface final : public ui::PropertyHandler { ...@@ -440,6 +446,9 @@ class Surface final : public ui::PropertyHandler {
std::unique_ptr<ash::OutputProtectionDelegate> output_protection_; std::unique_ptr<ash::OutputProtectionDelegate> output_protection_;
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
viz::SurfaceId first_embedded_surface_id_;
base::RepeatingCallback<viz::SurfaceId()> get_current_surface_id_;
DISALLOW_COPY_AND_ASSIGN(Surface); DISALLOW_COPY_AND_ASSIGN(Surface);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment