Skip to content

Commit

Permalink
Add viewport and scissor support (flutter#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdero authored and dnfield committed Apr 27, 2022
1 parent 88f4c24 commit dde655f
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 0 deletions.
32 changes: 32 additions & 0 deletions impeller/geometry/geometry_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -335,5 +335,37 @@ TEST(GeometryTest, RectContainsPoint) {
}
}

TEST(GeometryTest, RectContainsRect) {
{
Rect a(100, 100, 100, 100);
ASSERT_TRUE(a.Contains(a));
}
{
Rect a(100, 100, 100, 100);
Rect b(0, 0, 0, 0);
ASSERT_FALSE(a.Contains(b));
}
{
Rect a(100, 100, 100, 100);
Rect b(150, 150, 20, 20);
ASSERT_TRUE(a.Contains(b));
}
{
Rect a(100, 100, 100, 100);
Rect b(150, 150, 100, 100);
ASSERT_FALSE(a.Contains(b));
}
{
Rect a(100, 100, 100, 100);
Rect b(50, 50, 100, 100);
ASSERT_FALSE(a.Contains(b));
}
{
Rect a(100, 100, 100, 100);
Rect b(0, 0, 300, 300);
ASSERT_FALSE(a.Contains(b));
}
}

} // namespace testing
} // namespace impeller
4 changes: 4 additions & 0 deletions impeller/geometry/rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ struct TRect {
p.y < origin.y + size.height;
}

constexpr bool Contains(const TRect& o) const {
return Union(o).size == size;
}

constexpr bool IsZero() const { return size.IsZero(); }

constexpr bool IsEmpty() const { return size.IsEmpty(); }
Expand Down
31 changes: 31 additions & 0 deletions impeller/renderer/backend/metal/render_pass_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,28 @@ static bool Bind(PassBindingsCache& pass,
: MTLWindingCounterClockwise];
[encoder setCullMode:MTLCullModeNone];
[encoder setStencilReferenceValue:command.stencil_reference];
if (command.viewport.has_value()) {
auto v = command.viewport.value();
MTLViewport viewport = {
.originX = v.rect.origin.x,
.originY = v.rect.origin.y,
.width = v.rect.size.width,
.height = v.rect.size.height,
.znear = v.znear,
.zfar = v.zfar,
};
[encoder setViewport:viewport];
}
if (command.scissor.has_value()) {
auto s = command.scissor.value();
MTLScissorRect scissor = {
.x = static_cast<NSUInteger>(s.origin.x),
.y = static_cast<NSUInteger>(s.origin.y),
.width = static_cast<NSUInteger>(s.size.width),
.height = static_cast<NSUInteger>(s.size.height),
};
[encoder setScissorRect:scissor];
}
if (!bind_stage_resources(command.vertex_bindings, ShaderStage::kVertex)) {
return false;
}
Expand Down Expand Up @@ -472,6 +494,15 @@ static bool Bind(PassBindingsCache& pass,
return false;
}

if (command.scissor.has_value()) {
auto target_rect = IRect({}, render_target_.GetRenderTargetSize());
if (!target_rect.Contains(command.scissor.value())) {
VALIDATION_LOG << "Cannot apply a scissor that lies outside the bounds "
"of the render target.";
return false;
}
}

commands_.emplace_back(std::move(command));
return true;
}
Expand Down
15 changes: 15 additions & 0 deletions impeller/renderer/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

#include <map>
#include <memory>
#include <optional>
#include <string>

#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "impeller/geometry/rect.h"
#include "impeller/renderer/buffer_view.h"
#include "impeller/renderer/formats.h"
#include "impeller/renderer/pipeline.h"
Expand Down Expand Up @@ -69,6 +71,19 @@ struct Command {
PrimitiveType primitive_type = PrimitiveType::kTriangle;
WindingOrder winding = WindingOrder::kClockwise;
uint32_t stencil_reference = 0u;
//----------------------------------------------------------------------------
/// The viewport coordinates that the rasterizer linearly maps normalized
/// device coordinates to.
/// If unset, the viewport is the size of the render target with a zero
/// origin, znear=0, and zfar=1.
///
std::optional<Viewport> viewport;
//----------------------------------------------------------------------------
/// The scissor rect to use for clipping writes to the render target. The
/// scissor rect must lie entirely within the render target.
/// If unset, no scissor is applied.
///
std::optional<IRect> scissor;

bool BindVertices(const VertexBuffer& buffer);

Expand Down
8 changes: 8 additions & 0 deletions impeller/renderer/formats.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#include "flutter/fml/hash_combine.h"
#include "flutter/fml/macros.h"
#include "impeller/geometry/rect.h"
#include "impeller/geometry/scalar.h"
#include "impeller/geometry/color.h"

namespace impeller {
Expand Down Expand Up @@ -149,6 +151,12 @@ enum class PrimitiveType {
// checks. Hence, they are not supported here.
};

struct Viewport {
Rect rect;
Scalar znear = 0.0f;
Scalar zfar = 1.0f;
};

enum class MinMagFilter {
/// Select nearest to the sample point. Most widely supported.
kNearest,
Expand Down

0 comments on commit dde655f

Please sign in to comment.