Skip to content

Commit 3c95a89

Browse files
authored
Add viewport and scissor support (flutter#9)
1 parent a476b92 commit 3c95a89

File tree

5 files changed

+90
-0
lines changed

5 files changed

+90
-0
lines changed

impeller/geometry/geometry_unittests.cc

+32
Original file line numberDiff line numberDiff line change
@@ -335,5 +335,37 @@ TEST(GeometryTest, RectContainsPoint) {
335335
}
336336
}
337337

338+
TEST(GeometryTest, RectContainsRect) {
339+
{
340+
Rect a(100, 100, 100, 100);
341+
ASSERT_TRUE(a.Contains(a));
342+
}
343+
{
344+
Rect a(100, 100, 100, 100);
345+
Rect b(0, 0, 0, 0);
346+
ASSERT_FALSE(a.Contains(b));
347+
}
348+
{
349+
Rect a(100, 100, 100, 100);
350+
Rect b(150, 150, 20, 20);
351+
ASSERT_TRUE(a.Contains(b));
352+
}
353+
{
354+
Rect a(100, 100, 100, 100);
355+
Rect b(150, 150, 100, 100);
356+
ASSERT_FALSE(a.Contains(b));
357+
}
358+
{
359+
Rect a(100, 100, 100, 100);
360+
Rect b(50, 50, 100, 100);
361+
ASSERT_FALSE(a.Contains(b));
362+
}
363+
{
364+
Rect a(100, 100, 100, 100);
365+
Rect b(0, 0, 300, 300);
366+
ASSERT_FALSE(a.Contains(b));
367+
}
368+
}
369+
338370
} // namespace testing
339371
} // namespace impeller

impeller/geometry/rect.h

+4
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ struct TRect {
8484
p.y < origin.y + size.height;
8585
}
8686

87+
constexpr bool Contains(const TRect& o) const {
88+
return Union(o).size == size;
89+
}
90+
8791
constexpr bool IsZero() const { return size.IsZero(); }
8892

8993
constexpr bool IsEmpty() const { return size.IsEmpty(); }

impeller/renderer/backend/metal/render_pass_mtl.mm

+31
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,28 @@ static bool Bind(PassBindingsCache& pass,
428428
: MTLWindingCounterClockwise];
429429
[encoder setCullMode:MTLCullModeNone];
430430
[encoder setStencilReferenceValue:command.stencil_reference];
431+
if (command.viewport.has_value()) {
432+
auto v = command.viewport.value();
433+
MTLViewport viewport = {
434+
.originX = v.rect.origin.x,
435+
.originY = v.rect.origin.y,
436+
.width = v.rect.size.width,
437+
.height = v.rect.size.height,
438+
.znear = v.znear,
439+
.zfar = v.zfar,
440+
};
441+
[encoder setViewport:viewport];
442+
}
443+
if (command.scissor.has_value()) {
444+
auto s = command.scissor.value();
445+
MTLScissorRect scissor = {
446+
.x = static_cast<NSUInteger>(s.origin.x),
447+
.y = static_cast<NSUInteger>(s.origin.y),
448+
.width = static_cast<NSUInteger>(s.size.width),
449+
.height = static_cast<NSUInteger>(s.size.height),
450+
};
451+
[encoder setScissorRect:scissor];
452+
}
431453
if (!bind_stage_resources(command.vertex_bindings, ShaderStage::kVertex)) {
432454
return false;
433455
}
@@ -472,6 +494,15 @@ static bool Bind(PassBindingsCache& pass,
472494
return false;
473495
}
474496

497+
if (command.scissor.has_value()) {
498+
auto target_rect = IRect({}, render_target_.GetRenderTargetSize());
499+
if (!target_rect.Contains(command.scissor.value())) {
500+
VALIDATION_LOG << "Cannot apply a scissor that lies outside the bounds "
501+
"of the render target.";
502+
return false;
503+
}
504+
}
505+
475506
commands_.emplace_back(std::move(command));
476507
return true;
477508
}

impeller/renderer/command.h

+15
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
#include <map>
88
#include <memory>
9+
#include <optional>
910
#include <string>
1011

1112
#include "flutter/fml/logging.h"
1213
#include "flutter/fml/macros.h"
14+
#include "impeller/geometry/rect.h"
1315
#include "impeller/renderer/buffer_view.h"
1416
#include "impeller/renderer/formats.h"
1517
#include "impeller/renderer/pipeline.h"
@@ -69,6 +71,19 @@ struct Command {
6971
PrimitiveType primitive_type = PrimitiveType::kTriangle;
7072
WindingOrder winding = WindingOrder::kClockwise;
7173
uint32_t stencil_reference = 0u;
74+
//----------------------------------------------------------------------------
75+
/// The viewport coordinates that the rasterizer linearly maps normalized
76+
/// device coordinates to.
77+
/// If unset, the viewport is the size of the render target with a zero
78+
/// origin, znear=0, and zfar=1.
79+
///
80+
std::optional<Viewport> viewport;
81+
//----------------------------------------------------------------------------
82+
/// The scissor rect to use for clipping writes to the render target. The
83+
/// scissor rect must lie entirely within the render target.
84+
/// If unset, no scissor is applied.
85+
///
86+
std::optional<IRect> scissor;
7287

7388
bool BindVertices(const VertexBuffer& buffer);
7489

impeller/renderer/formats.h

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#include "flutter/fml/hash_combine.h"
1313
#include "flutter/fml/macros.h"
14+
#include "impeller/geometry/rect.h"
15+
#include "impeller/geometry/scalar.h"
1416
#include "impeller/geometry/color.h"
1517

1618
namespace impeller {
@@ -149,6 +151,12 @@ enum class PrimitiveType {
149151
// checks. Hence, they are not supported here.
150152
};
151153

154+
struct Viewport {
155+
Rect rect;
156+
Scalar znear = 0.0f;
157+
Scalar zfar = 1.0f;
158+
};
159+
152160
enum class MinMagFilter {
153161
/// Select nearest to the sample point. Most widely supported.
154162
kNearest,

0 commit comments

Comments
 (0)