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

Update surface quad's quad_rect & scaling

The math to scale and size the rect was incorrect. The quad rect
should actually be an unscaled embedded_surface_size_ instead
of a scaled content_size_. This fixes distortion of the contents as
currently the quad will still be scaled incorrectly

Similarly, the implementation of the matrix means that translate needs
to be scaled up/down as well

  with continually variable crop offsets and scaling

Bug: b/143612326
Test: manually, a 256x256 crop of a 1024x600 surface into a 512x512 quad
Change-Id: If545170f9ae4cd53075b2f3128b7dc38383077d3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1994263
Commit-Queue: Albert Chaulk <achaulk@chromium.org>
Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Cr-Commit-Position: refs/heads/master@{#730973}
parent c039719b
......@@ -562,7 +562,7 @@ void Surface::SetEmbeddedSurfaceId(
}
void Surface::SetEmbeddedSurfaceSize(const gfx::Size& size) {
embedded_surface_size_ = gfx::SizeF(size);
embedded_surface_size_ = size;
}
void Surface::SetAcquireFence(std::unique_ptr<gfx::GpuFence> gpu_fence) {
......@@ -1007,12 +1007,8 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin,
// 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());
}
quad_rect = gfx::Rect(embedded_surface_size_);
scale = gfx::PointF(1.0f, 1.0f);
if (!state_.crop.IsEmpty()) {
// In order to crop an AxB rect to CxD we need to scale by A/C, B/D.
......@@ -1021,7 +1017,9 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin,
scale.Scale(content_size_.width() / state_.crop.width(),
content_size_.height() / state_.crop.height());
translate = -state_.crop.origin().OffsetFromOrigin();
auto offset = state_.crop.origin().OffsetFromOrigin();
translate =
gfx::Vector2dF(-offset.x() * scale.x(), -offset.y() * scale.y());
}
} else {
scale.Scale(state_.buffer_scale);
......
......@@ -464,7 +464,7 @@ class Surface final : public ui::PropertyHandler {
// The embedded surface is actually |embedded_surface_size_|. This is used
// for calculating clipping and scaling.
gfx::SizeF embedded_surface_size_;
gfx::Size embedded_surface_size_;
DISALLOW_COPY_AND_ASSIGN(Surface);
};
......
......@@ -894,6 +894,64 @@ TEST_P(SurfaceTest, SurfaceQuad) {
}
}
TEST_P(SurfaceTest, ScaledSurfaceQuad) {
gfx::Size buffer_size(1, 1);
auto buffer = std::make_unique<Buffer>(
exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
true, true, false);
auto surface = std::make_unique<Surface>();
auto shell_surface = std::make_unique<ShellSurface>(surface.get());
surface->Attach(buffer.get());
surface->SetAlpha(1.0f);
surface->SetEmbeddedSurfaceId(base::BindRepeating([]() -> viz::SurfaceId {
return viz::SurfaceId(
viz::FrameSinkId(1, 1),
viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
}));
// A 256x256 surface, of which as 128x128 chunk is selected, drawn into a
// 128x64 rect.
surface->SetEmbeddedSurfaceSize(gfx::Size(256, 256));
surface->SetViewport(gfx::Size(128, 64));
surface->SetCrop(
gfx::RectF(gfx::PointF(32.0f, 32.0f), gfx::SizeF(128.0f, 128.0f)));
{
surface->Commit();
base::RunLoop().RunUntilIdle();
const viz::CompositorFrame& frame =
GetFrameFromSurface(shell_surface.get());
EXPECT_EQ(1u, frame.render_pass_list.size());
EXPECT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
EXPECT_EQ(1u, frame.resource_list.size());
// Ensure that the quad is correct and the resource is included.
EXPECT_EQ(1u, frame.resource_list.back().id);
EXPECT_EQ(viz::DrawQuad::Material::kSurfaceContent,
frame.render_pass_list.back()->quad_list.back()->material);
// We are outputting to 0,0 -> 128,64.
EXPECT_EQ(gfx::Rect(gfx::Point(), gfx::Size(128, 64)),
frame.render_pass_list.back()
->quad_list.back()
->shared_quad_state->clip_rect);
// Rect should be the unmodified surface size.
EXPECT_EQ(gfx::Rect(gfx::Point(0, 0), gfx::Size(256, 256)),
frame.render_pass_list.back()->quad_list.back()->rect);
// To get 32,32 -> 160,160 into the correct position it must be translated
// backwards and scaled 0.5x in Y, then everything is scaled by the scale
// factor.
EXPECT_EQ(gfx::Transform(1.0f * device_scale_factor(), 0.0f, 0.0f,
0.5f * device_scale_factor(),
-32.0f * device_scale_factor(),
-16.0f * device_scale_factor()),
frame.render_pass_list.back()
->quad_list.back()
->shared_quad_state->quad_to_target_transform);
}
}
TEST_P(SurfaceTest, Commit) {
std::unique_ptr<Surface> surface(new 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