Commit 77191cc4 authored by Albert Chaulk's avatar Albert Chaulk Committed by Commit Bot

Allow exo embedded surfaces to crop

Cropping with a SurfaceDrawQuad is done a little differently than with
a texture quad, it need to be scaled up and positioned in the target
space and then clipped using the clip_rect.

Bug: b/143612326
Test: manually
Change-Id: I38e78fd5ff4c60df2c44f9054136d8b27ac55ddc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1972259Reviewed-by: default avatarAlex Sakhartchouk <alexst@chromium.org>
Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Commit-Queue: Albert Chaulk <achaulk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726540}
parent 0efc4729
...@@ -157,6 +157,13 @@ void WebContentController::AttachTo(aura::Window* window, int window_id) { ...@@ -157,6 +157,13 @@ void WebContentController::AttachTo(aura::Window* window, int window_id) {
// Unretained is safe because we unset this in the destructor. // Unretained is safe because we unset this in the destructor.
surface_->SetEmbeddedSurfaceId( surface_->SetEmbeddedSurfaceId(
base::Bind(&WebContentController::GetSurfaceId, base::Unretained(this))); base::Bind(&WebContentController::GetSurfaceId, base::Unretained(this)));
current_rfh_ = GetWebContents()->GetMainFrame();
if (current_rfh_) {
auto size = current_rfh_->GetFrameSize();
if (size.has_value())
surface_->SetEmbeddedSurfaceSize(*size);
}
} }
void WebContentController::ProcessInputEvent(const webview::InputEvent& ev) { void WebContentController::ProcessInputEvent(const webview::InputEvent& ev) {
...@@ -399,6 +406,13 @@ void WebContentController::OnSurfaceDestroying(exo::Surface* surface) { ...@@ -399,6 +406,13 @@ void WebContentController::OnSurfaceDestroying(exo::Surface* surface) {
surface_ = nullptr; surface_ = nullptr;
} }
void WebContentController::FrameSizeChanged(
content::RenderFrameHost* render_frame_host,
const gfx::Size& frame_size) {
if (render_frame_host == current_rfh_ && surface_)
surface_->SetEmbeddedSurfaceSize(frame_size);
}
void WebContentController::RenderFrameCreated( void WebContentController::RenderFrameCreated(
content::RenderFrameHost* render_frame_host) { content::RenderFrameHost* render_frame_host) {
current_render_frame_set_.insert(render_frame_host); current_render_frame_set_.insert(render_frame_host);
...@@ -414,6 +428,8 @@ void WebContentController::RenderFrameCreated( ...@@ -414,6 +428,8 @@ void WebContentController::RenderFrameCreated(
void WebContentController::RenderFrameDeleted( void WebContentController::RenderFrameDeleted(
content::RenderFrameHost* render_frame_host) { content::RenderFrameHost* render_frame_host) {
current_render_frame_set_.erase(render_frame_host); current_render_frame_set_.erase(render_frame_host);
if (render_frame_host == current_rfh_)
current_rfh_ = nullptr;
} }
void WebContentController::RenderFrameHostChanged( void WebContentController::RenderFrameHostChanged(
...@@ -421,8 +437,15 @@ void WebContentController::RenderFrameHostChanged( ...@@ -421,8 +437,15 @@ void WebContentController::RenderFrameHostChanged(
content::RenderFrameHost* new_host) { content::RenderFrameHost* new_host) {
// The surface ID may have changed, so trigger a new commit to re-issue the // The surface ID may have changed, so trigger a new commit to re-issue the
// draw quad. // draw quad.
if (surface_) current_rfh_ = new_host;
if (surface_) {
if (new_host) {
auto size = new_host->GetFrameSize();
if (size.has_value())
surface_->SetEmbeddedSurfaceSize(*size);
}
surface_->Commit(); surface_->Commit();
}
} }
void WebContentController::OnJsClientInstanceRegistered( void WebContentController::OnJsClientInstanceRegistered(
......
...@@ -91,6 +91,8 @@ class WebContentController : public exo::SurfaceObserver, ...@@ -91,6 +91,8 @@ class WebContentController : public exo::SurfaceObserver,
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
void RenderFrameHostChanged(content::RenderFrameHost* old_host, void RenderFrameHostChanged(content::RenderFrameHost* old_host,
content::RenderFrameHost* new_host) override; content::RenderFrameHost* new_host) override;
void FrameSizeChanged(content::RenderFrameHost* render_frame_host,
const gfx::Size& frame_size) override;
// JsClientInstance::Observer // JsClientInstance::Observer
void OnJsClientInstanceRegistered(int process_id, void OnJsClientInstanceRegistered(int process_id,
...@@ -100,6 +102,7 @@ class WebContentController : public exo::SurfaceObserver, ...@@ -100,6 +102,7 @@ class WebContentController : public exo::SurfaceObserver,
ui::GestureRecognizerImpl gesture_recognizer_; ui::GestureRecognizerImpl gesture_recognizer_;
exo::Surface* surface_ = nullptr; exo::Surface* surface_ = nullptr;
content::RenderFrameHost* current_rfh_ = nullptr;
std::set<std::string> current_javascript_channel_set_; std::set<std::string> current_javascript_channel_set_;
std::set<content::RenderFrameHost*> current_render_frame_set_; std::set<content::RenderFrameHost*> current_render_frame_set_;
......
...@@ -561,6 +561,10 @@ void Surface::SetEmbeddedSurfaceId( ...@@ -561,6 +561,10 @@ void Surface::SetEmbeddedSurfaceId(
first_embedded_surface_id_ = viz::SurfaceId(); first_embedded_surface_id_ = viz::SurfaceId();
} }
void Surface::SetEmbeddedSurfaceSize(const gfx::Size& size) {
embedded_surface_size_ = gfx::SizeF(size);
}
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);
...@@ -996,14 +1000,41 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin, ...@@ -996,14 +1000,41 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin,
gfx::ConvertRectToPixel(device_scale_factor, damage_rect)); gfx::ConvertRectToPixel(device_scale_factor, damage_rect));
} }
gfx::PointF scale(content_size_.width(), content_size_.height());
gfx::Vector2dF translate(0.0f, 0.0f);
// Surface quads require the quad rect to be appropriately sized and need to
// use the shared quad clip rect.
if (get_current_surface_id_) {
quad_rect = gfx::Rect(content_size_);
// Scale the |embedded_surface_size_| to |content_size_|.
if (embedded_surface_size_.width() || embedded_surface_size_.height()) {
scale.Scale(1.0f / embedded_surface_size_.width(),
1.0f / embedded_surface_size_.height());
}
if (!state_.crop.IsEmpty()) {
// In order to crop an AxB rect to CxD we need to scale by A/C, B/D.
// We achieve clipping by scaling it up and then drawing only in the
// output rectangle.
scale.Scale(content_size_.width() / state_.crop.width(),
content_size_.height() / state_.crop.height());
translate = -state_.crop.origin().OffsetFromOrigin();
}
} else {
scale.Scale(state_.buffer_scale);
}
// Compute the total transformation from post-transform buffer coordinates to // Compute the total transformation from post-transform buffer coordinates to
// target coordinates. // target coordinates.
SkMatrix viewport_to_target_matrix; SkMatrix viewport_to_target_matrix;
// Scale and offset the normalized space to fit the content size rectangle. // Scale and offset the normalized space to fit the content size rectangle.
viewport_to_target_matrix.setScale( viewport_to_target_matrix.setScale(scale.x(), scale.y());
content_size_.width() * state_.buffer_scale,
content_size_.height() * state_.buffer_scale); gfx::PointF target = gfx::PointF(origin) + translate;
viewport_to_target_matrix.postTranslate(origin.x(), origin.y()); viewport_to_target_matrix.postTranslate(target.x(), target.y());
// Convert from DPs to pixels. // Convert from DPs to pixels.
viewport_to_target_matrix.postScale(device_scale_factor, device_scale_factor); viewport_to_target_matrix.postScale(device_scale_factor, device_scale_factor);
...@@ -1057,13 +1088,17 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin, ...@@ -1057,13 +1088,17 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin,
} }
} }
if (latest_embedded_surface_id_.is_valid()) { if (latest_embedded_surface_id_.is_valid()) {
if (!state_.crop.IsEmpty()) {
quad_state->is_clipped = true;
quad_state->clip_rect = output_rect;
}
viz::SurfaceDrawQuad* surface_quad = viz::SurfaceDrawQuad* surface_quad =
render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>(); render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
surface_quad->SetNew(quad_state, quad_rect, quad_rect, surface_quad->SetNew(quad_state, quad_rect, quad_rect,
viz::SurfaceRange(first_embedded_surface_id_, viz::SurfaceRange(first_embedded_surface_id_,
latest_embedded_surface_id_), latest_embedded_surface_id_),
background_color, background_color,
/*stretch_content_to_fill_bounds=*/true); /*stretch_content_to_fill_bounds=*/false);
} }
// A resource was still produced for this so we still need to release it // A resource was still produced for this so we still need to release it
// later. // later.
......
...@@ -180,6 +180,9 @@ class Surface final : public ui::PropertyHandler { ...@@ -180,6 +180,9 @@ class Surface final : public ui::PropertyHandler {
void SetEmbeddedSurfaceId( void SetEmbeddedSurfaceId(
base::RepeatingCallback<viz::SurfaceId()> surface_id_callback); base::RepeatingCallback<viz::SurfaceId()> surface_id_callback);
// Set the size of the embedded surface, to allow proper scaling.
void SetEmbeddedSurfaceSize(const gfx::Size& size);
// 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);
...@@ -458,6 +461,10 @@ class Surface final : public ui::PropertyHandler { ...@@ -458,6 +461,10 @@ class Surface final : public ui::PropertyHandler {
viz::SurfaceId latest_embedded_surface_id_; viz::SurfaceId latest_embedded_surface_id_;
base::RepeatingCallback<viz::SurfaceId()> get_current_surface_id_; base::RepeatingCallback<viz::SurfaceId()> get_current_surface_id_;
// The embedded surface is actually |embedded_surface_size_|. This is used
// for calculating clipping and scaling.
gfx::SizeF embedded_surface_size_;
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