diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 08e035ecde2eb..3f0ea61eb5361 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -561,6 +561,7 @@ TEST_P(AiksTest, ColorWheel) { ImGui::End(); Canvas canvas; + canvas.Scale(GetContentScale()); Paint paint; // Default blend is kSourceOver. paint.color = Color::White(); @@ -653,6 +654,7 @@ TEST_P(AiksTest, SolidStrokesRenderCorrectly) { ImGui::End(); Canvas canvas; + canvas.Scale(GetContentScale()); Paint paint; paint.color = Color::White(); diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index 67003b8df0908..35c8de65f80fb 100644 --- a/impeller/display_list/display_list_unittests.cc +++ b/impeller/display_list/display_list_unittests.cc @@ -115,6 +115,9 @@ TEST_P(DisplayListTest, CanDrawArc) { Point(200, 200), Point(400, 400), 20, Color::White(), Color::White()); flutter::DisplayListBuilder builder; + + Vector2 scale = GetContentScale(); + builder.scale(scale.x, scale.y); builder.setStyle(flutter::DlDrawStyle::kStroke); builder.setStrokeCap(flutter::DlStrokeCap::kRound); builder.setStrokeJoin(flutter::DlStrokeJoin::kMiter); diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index 359fde09fd618..1517bbd486fa2 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -105,6 +105,7 @@ TEST_P(EntityTest, EntityPassSubpassCoverageIsCorrect) { TEST_P(EntityTest, CanDrawRect) { Entity entity; + entity.SetTransformation(Matrix::MakeScale(GetContentScale())); entity.SetContents(SolidColorContents::Make( PathBuilder{}.AddRect({100, 100, 100, 100}).TakePath(), Color::Red())); ASSERT_TRUE(OpenPlaygroundHere(entity)); @@ -121,6 +122,7 @@ TEST_P(EntityTest, ThreeStrokesInOnePath) { .TakePath(); Entity entity; + entity.SetTransformation(Matrix::MakeScale(GetContentScale())); auto contents = std::make_unique(); contents->SetPath(std::move(path)); contents->SetColor(Color::Red()); @@ -151,6 +153,7 @@ TEST_P(EntityTest, TriangleInsideASquare) { .TakePath(); Entity entity; + entity.SetTransformation(Matrix::MakeScale(GetContentScale())); auto contents = std::make_unique(); contents->SetPath(std::move(path)); contents->SetColor(Color::Red()); @@ -192,7 +195,8 @@ TEST_P(EntityTest, StrokeCapAndJoinTest) { } ImGui::End(); - auto render_path = [width = width, &context, &pass]( + auto world_matrix = Matrix::MakeScale(GetContentScale()); + auto render_path = [width = width, &context, &pass, &world_matrix]( Path path, SolidStrokeContents::Cap cap, SolidStrokeContents::Join join) { auto contents = std::make_unique(); @@ -204,6 +208,7 @@ TEST_P(EntityTest, StrokeCapAndJoinTest) { contents->SetStrokeMiter(miter_limit); Entity entity; + entity.SetTransformation(world_matrix); entity.SetContents(std::move(contents)); auto coverage = entity.GetCoverage(); @@ -314,6 +319,7 @@ TEST_P(EntityTest, CubicCurveTest) { .Close() .TakePath(); Entity entity; + entity.SetTransformation(Matrix::MakeScale(GetContentScale())); entity.SetContents(SolidColorContents::Make(path, Color::Red())); ASSERT_TRUE(OpenPlaygroundHere(entity)); } @@ -541,6 +547,7 @@ TEST_P(EntityTest, CubicCurveAndOverlapTest) { .Close() .TakePath(); Entity entity; + entity.SetTransformation(Matrix::MakeScale(GetContentScale())); entity.SetContents(SolidColorContents::Make(path, Color::Red())); ASSERT_TRUE(OpenPlaygroundHere(entity)); } @@ -643,8 +650,10 @@ TEST_P(EntityTest, BlendingModeOptions) { ImGui::SetNextWindowPos({200, 450}); } - auto draw_rect = [&context, &pass](Rect rect, Color color, - Entity::BlendMode blend_mode) -> bool { + auto world_matrix = Matrix::MakeScale(GetContentScale()); + auto draw_rect = [&context, &pass, &world_matrix]( + Rect rect, Color color, + Entity::BlendMode blend_mode) -> bool { using VS = SolidFillPipeline::VertexShader; VertexBufferBuilder vtx_builder; { @@ -668,7 +677,8 @@ TEST_P(EntityTest, BlendingModeOptions) { vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer())); VS::FrameInfo frame_info; - frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()); + frame_info.mvp = + Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix; frame_info.color = color.Premultiply(); VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); @@ -710,6 +720,7 @@ TEST_P(EntityTest, BlendingModeOptions) { TEST_P(EntityTest, BezierCircleScaled) { Entity entity; + entity.SetTransformation(Matrix::MakeScale(GetContentScale())); auto path = PathBuilder{} .MoveTo({97.325, 34.818}) .CubicCurveTo({98.50862885295136, 34.81812293973836}, @@ -751,7 +762,8 @@ TEST_P(EntityTest, Filters) { {fi_bridge, FilterInput::Make(blend0), fi_bridge, fi_bridge}); Entity entity; - entity.SetTransformation(Matrix::MakeTranslation({500, 300}) * + entity.SetTransformation(Matrix::MakeScale(GetContentScale()) * + Matrix::MakeTranslation({500, 300}) * Matrix::MakeScale(Vector2{0.5, 0.5})); entity.SetContents(blend1); return entity.Render(context, pass); @@ -823,7 +835,8 @@ TEST_P(EntityTest, GaussianBlurFilter) { blur_styles[selected_blur_style]); auto input_size = bridge->GetSize(); - auto ctm = Matrix::MakeTranslation(Vector3(offset[0], offset[1])) * + auto ctm = Matrix::MakeScale(GetContentScale()) * + Matrix::MakeTranslation(Vector3(offset[0], offset[1])) * Matrix::MakeRotationZ(Radians(rotation)) * Matrix::MakeScale(Vector2(scale[0], scale[1])) * Matrix::MakeSkew(skew[0], skew[1]) * @@ -964,6 +977,7 @@ TEST_P(EntityTest, DrawVerticesSolidColorTrianglesWithoutIndex) { std::make_shared(vertices); contents->SetColor(Color::White()); Entity e; + e.SetTransformation(Matrix::MakeScale(GetContentScale())); e.SetContents(contents); ASSERT_TRUE(OpenPlaygroundHere(e)); diff --git a/impeller/playground/backend/gles/playground_impl_gles.cc b/impeller/playground/backend/gles/playground_impl_gles.cc index 9229604f19980..8c507f57ce302 100644 --- a/impeller/playground/backend/gles/playground_impl_gles.cc +++ b/impeller/playground/backend/gles/playground_impl_gles.cc @@ -124,7 +124,7 @@ std::shared_ptr PlaygroundImplGLES::GetContext() const { } // |PlaygroundImpl| -PlaygroundImpl::WindowHandle PlaygroundImplGLES::GetWindowHandle() { +PlaygroundImpl::WindowHandle PlaygroundImplGLES::GetWindowHandle() const { return handle_.get(); } diff --git a/impeller/playground/backend/gles/playground_impl_gles.h b/impeller/playground/backend/gles/playground_impl_gles.h index 99f0c300b02a2..9540d1460e6a9 100644 --- a/impeller/playground/backend/gles/playground_impl_gles.h +++ b/impeller/playground/backend/gles/playground_impl_gles.h @@ -27,7 +27,7 @@ class PlaygroundImplGLES final : public PlaygroundImpl { std::shared_ptr GetContext() const override; // |PlaygroundImpl| - WindowHandle GetWindowHandle() override; + WindowHandle GetWindowHandle() const override; // |PlaygroundImpl| std::unique_ptr AcquireSurfaceFrame( diff --git a/impeller/playground/backend/metal/playground_impl_mtl.h b/impeller/playground/backend/metal/playground_impl_mtl.h index 9aa9da659e097..345574ebe16ac 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.h +++ b/impeller/playground/backend/metal/playground_impl_mtl.h @@ -32,7 +32,7 @@ class PlaygroundImplMTL final : public PlaygroundImpl { std::shared_ptr GetContext() const override; // |PlaygroundImpl| - WindowHandle GetWindowHandle() override; + WindowHandle GetWindowHandle() const override; // |PlaygroundImpl| std::unique_ptr AcquireSurfaceFrame( diff --git a/impeller/playground/backend/metal/playground_impl_mtl.mm b/impeller/playground/backend/metal/playground_impl_mtl.mm index 3bcd631c34cbc..3ba5f7c167a78 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.mm +++ b/impeller/playground/backend/metal/playground_impl_mtl.mm @@ -84,7 +84,7 @@ } // |PlaygroundImpl| -PlaygroundImpl::WindowHandle PlaygroundImplMTL::GetWindowHandle() { +PlaygroundImpl::WindowHandle PlaygroundImplMTL::GetWindowHandle() const { return handle_.get(); } @@ -96,9 +96,10 @@ } const auto layer_size = data_->metal_layer.bounds.size; - const auto layer_scale = data_->metal_layer.contentsScale; - data_->metal_layer.drawableSize = CGSizeMake(layer_size.width * layer_scale, - layer_size.height * layer_scale); + const auto scale = GetContentScale(); + data_->metal_layer.drawableSize = + CGSizeMake(layer_size.width * scale.x, layer_size.height * scale.y); + return SurfaceMTL::WrapCurrentMetalLayerDrawable(context, data_->metal_layer); } diff --git a/impeller/playground/imgui/imgui_impl_impeller.cc b/impeller/playground/imgui/imgui_impl_impeller.cc index 9328bd8ca6675..539432a437f20 100644 --- a/impeller/playground/imgui/imgui_impl_impeller.cc +++ b/impeller/playground/imgui/imgui_impl_impeller.cc @@ -140,11 +140,23 @@ void ImGui_ImplImpeller_RenderDrawData(ImDrawData* draw_data, impeller::StorageMode::kHostVisible, total_vtx_bytes + total_idx_bytes); buffer->SetLabel(impeller::SPrintF("ImGui vertex+index buffer")); + auto display_rect = + impeller::Rect(draw_data->DisplayPos.x, draw_data->DisplayPos.y, + draw_data->DisplaySize.x, draw_data->DisplaySize.y); + + auto viewport = impeller::Viewport{ + .rect = impeller::Rect( + display_rect.origin.x * draw_data->FramebufferScale.x, + display_rect.origin.y * draw_data->FramebufferScale.y, + display_rect.size.width * draw_data->FramebufferScale.x, + display_rect.size.height * draw_data->FramebufferScale.y)}; + + // Allocate vertex shader uniform buffer. VS::UniformBuffer uniforms; - uniforms.mvp = impeller::Matrix::MakeOrthographic( - impeller::Size(draw_data->DisplaySize.x, draw_data->DisplaySize.y)); - uniforms.mvp = uniforms.mvp.Translate( - -impeller::Vector3(draw_data->DisplayPos.x, draw_data->DisplayPos.y)); + uniforms.mvp = impeller::Matrix::MakeOrthographic(display_rect.size) + .Translate(-display_rect.origin); + auto vtx_uniforms = + render_pass.GetTransientsBuffer().EmplaceUniform(uniforms); size_t vertex_buffer_offset = 0; size_t index_buffer_offset = total_vtx_bytes; @@ -185,29 +197,39 @@ void ImGui_ImplImpeller_RenderDrawData(ImDrawData* draw_data, IM_ASSERT(false && "Could not copy indices to buffer."); } - auto viewport = impeller::Viewport{ - .rect = - impeller::Rect(draw_data->DisplayPos.x, draw_data->DisplayPos.y, - draw_data->DisplaySize.x, draw_data->DisplaySize.y)}; - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { - // Project scissor/clipping rectangles into framebuffer space. - impeller::IPoint clip_min(pcmd->ClipRect.x - draw_data->DisplayPos.x, - pcmd->ClipRect.y - draw_data->DisplayPos.y); - impeller::IPoint clip_max(pcmd->ClipRect.z - draw_data->DisplayPos.x, - pcmd->ClipRect.w - draw_data->DisplayPos.y); - // Ensure the scissor never goes out of bounds. - clip_min.x = std::clamp( - clip_min.x, 0ll, draw_data->DisplaySize.x); - clip_min.y = std::clamp( - clip_min.y, 0ll, draw_data->DisplaySize.y); - if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) { - continue; // Nothing to render. + // Make the clip rect relative to the viewport. + auto clip_rect = impeller::Rect::MakeLTRB( + (pcmd->ClipRect.x - draw_data->DisplayPos.x) * + draw_data->FramebufferScale.x, + (pcmd->ClipRect.y - draw_data->DisplayPos.y) * + draw_data->FramebufferScale.y, + (pcmd->ClipRect.z - draw_data->DisplayPos.x) * + draw_data->FramebufferScale.x, + (pcmd->ClipRect.w - draw_data->DisplayPos.y) * + draw_data->FramebufferScale.y); + { + // Clamp the clip to the viewport bounds. + auto visible_clip = clip_rect.Intersection(viewport.rect); + if (!visible_clip.has_value()) { + continue; // Nothing to render. + } + clip_rect = visible_clip.value(); + } + { + // Clamp the clip to ensure it never goes outside of the render + // target. + auto visible_clip = clip_rect.Intersection(impeller::Rect::MakeSize( + impeller::Size(render_pass.GetRenderTargetSize()))); + if (!visible_clip.has_value()) { + continue; // Nothing to render. + } + clip_rect = visible_clip.value(); } impeller::Command cmd; @@ -215,19 +237,11 @@ void ImGui_ImplImpeller_RenderDrawData(ImDrawData* draw_data, draw_list_i, cmd_i); cmd.viewport = viewport; - cmd.scissor = impeller::IRect::MakeLTRB( - std::max(0ll, clip_min.x), // - std::max(0ll, clip_min.y), // - std::min( - render_pass.GetRenderTargetSize().width, clip_max.x), // - std::min( - render_pass.GetRenderTargetSize().height, clip_max.y) // - ); + cmd.scissor = impeller::IRect(clip_rect); cmd.winding = impeller::WindingOrder::kClockwise; cmd.pipeline = bd->pipeline; - VS::BindUniformBuffer( - cmd, render_pass.GetTransientsBuffer().EmplaceUniform(uniforms)); + VS::BindUniformBuffer(cmd, vtx_uniforms); FS::BindTex(cmd, bd->font_texture, bd->sampler); size_t vb_start = diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc index fb22a604e564b..9a569881e5b75 100644 --- a/impeller/playground/playground.cc +++ b/impeller/playground/playground.cc @@ -150,6 +150,10 @@ ISize Playground::GetWindowSize() const { return window_size_; } +Point Playground::GetContentScale() const { + return impl_->GetContentScale(); +} + void Playground::SetCursorPosition(Point pos) { cursor_position_ = pos; } diff --git a/impeller/playground/playground.h b/impeller/playground/playground.h index 02cb83a5af6fe..4ecacf7eb3a02 100644 --- a/impeller/playground/playground.h +++ b/impeller/playground/playground.h @@ -44,6 +44,8 @@ class Playground : public ::testing::TestWithParam { ISize GetWindowSize() const; + Point GetContentScale() const; + std::shared_ptr GetContext() const; bool OpenPlaygroundHere(Renderer::RenderCallback render_callback); diff --git a/impeller/playground/playground_impl.cc b/impeller/playground/playground_impl.cc index ba2f19788f05e..2e79e255b6595 100644 --- a/impeller/playground/playground_impl.cc +++ b/impeller/playground/playground_impl.cc @@ -4,6 +4,9 @@ #include "impeller/playground/playground_impl.h" +#define GLFW_INCLUDE_NONE +#include "third_party/glfw/include/GLFW/glfw3.h" + #if IMPELLER_ENABLE_METAL #include "impeller/playground/backend/metal/playground_impl_mtl.h" #endif // IMPELLER_ENABLE_METAL @@ -37,4 +40,13 @@ PlaygroundImpl::PlaygroundImpl() = default; PlaygroundImpl::~PlaygroundImpl() = default; +Vector2 PlaygroundImpl::GetContentScale() const { + auto window = reinterpret_cast(GetWindowHandle()); + + Vector2 scale(1, 1); + ::glfwGetWindowContentScale(window, &scale.x, &scale.y); + + return scale; +} + } // namespace impeller diff --git a/impeller/playground/playground_impl.h b/impeller/playground/playground_impl.h index d15923b129190..cd47439778d7e 100644 --- a/impeller/playground/playground_impl.h +++ b/impeller/playground/playground_impl.h @@ -21,13 +21,15 @@ class PlaygroundImpl { using WindowHandle = void*; - virtual WindowHandle GetWindowHandle() = 0; + virtual WindowHandle GetWindowHandle() const = 0; virtual std::shared_ptr GetContext() const = 0; virtual std::unique_ptr AcquireSurfaceFrame( std::shared_ptr context) = 0; + Vector2 GetContentScale() const; + protected: PlaygroundImpl(); diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc index c9c2a08de3f43..1fffabcb53adf 100644 --- a/impeller/renderer/renderer_unittests.cc +++ b/impeller/renderer/renderer_unittests.cc @@ -76,7 +76,8 @@ TEST_P(RendererTest, CanCreateBoxPrimitive) { cmd.BindVertices(vertex_buffer); VS::UniformBuffer uniforms; - uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()); + uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + Matrix::MakeScale(GetContentScale()); VS::BindUniformBuffer(cmd, pass.GetTransientsBuffer().EmplaceUniform(uniforms)); @@ -158,6 +159,7 @@ TEST_P(RendererTest, CanRenderMultiplePrimitives) { for (size_t j = 0; j < 1; j++) { VS::UniformBuffer uniforms; uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + Matrix::MakeScale(GetContentScale()) * Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f}); VS::BindUniformBuffer( cmd, pass.GetTransientsBuffer().EmplaceUniform(uniforms)); @@ -324,7 +326,8 @@ TEST_P(RendererTest, CanRenderInstanced) { ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool { VS::FrameInfo frame_info; - frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()); + frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + Matrix::MakeScale(GetContentScale()); VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); VS::BindInstanceInfo(