22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44
5+ #include " impeller/geometry/path_builder.h"
6+ #include " impeller/renderer/formats.h"
7+ #include " impeller/renderer/vertex_buffer_builder.h"
58#include " linear_gradient_contents.h"
69
710#include " impeller/entity/contents/clip_contents.h"
@@ -20,25 +23,64 @@ ClipContents::ClipContents() = default;
2023
2124ClipContents::~ClipContents () = default ;
2225
26+ void ClipContents::SetClipOperation (Entity::ClipOperation clip_op) {
27+ clip_op_ = clip_op;
28+ }
29+
2330bool ClipContents::Render (const ContentContext& renderer,
2431 const Entity& entity,
2532 RenderPass& pass) const {
2633 using VS = ClipPipeline::VertexShader;
2734
35+ VS::FrameInfo info;
36+ // The color really doesn't matter.
37+ info.color = Color::SkyBlue ();
38+
2839 Command cmd;
29- cmd.label = " Clip" ;
30- cmd.pipeline =
31- renderer.GetClipPipeline (OptionsFromPassAndEntity (pass, entity));
40+ auto options = OptionsFromPassAndEntity (pass, entity);
3241 cmd.stencil_reference = entity.GetStencilDepth ();
42+ options.stencil_compare = CompareFunction::kEqual ;
43+ options.stencil_operation = StencilOperation::kIncrementClamp ;
44+
45+ if (clip_op_ == Entity::ClipOperation::kDifference ) {
46+ {
47+ cmd.label = " Difference Clip (Increment)" ;
48+
49+ cmd.primitive_type = PrimitiveType::kTriangleStrip ;
50+ auto points = Rect (Size (pass.GetRenderTargetSize ())).GetPoints ();
51+ auto vertices =
52+ VertexBufferBuilder<VS::PerVertexData>{}
53+ .AddVertices ({{points[0 ]}, {points[1 ]}, {points[2 ]}, {points[3 ]}})
54+ .CreateVertexBuffer (pass.GetTransientsBuffer ());
55+ cmd.BindVertices (std::move (vertices));
56+
57+ info.mvp = Matrix::MakeOrthographic (pass.GetRenderTargetSize ());
58+ VS::BindFrameInfo (cmd, pass.GetTransientsBuffer ().EmplaceUniform (info));
59+
60+ cmd.pipeline = renderer.GetClipPipeline (options);
61+ pass.AddCommand (cmd);
62+ }
63+
64+ {
65+ cmd.label = " Difference Clip (Punch)" ;
66+
67+ cmd.primitive_type = PrimitiveType::kTriangle ;
68+ cmd.stencil_reference = entity.GetStencilDepth () + 1 ;
69+ options.stencil_compare = CompareFunction::kEqual ;
70+ options.stencil_operation = StencilOperation::kDecrementClamp ;
71+ }
72+ } else {
73+ cmd.label = " Intersect Clip" ;
74+ options.stencil_compare = CompareFunction::kEqual ;
75+ options.stencil_operation = StencilOperation::kIncrementClamp ;
76+ }
77+
78+ cmd.pipeline = renderer.GetClipPipeline (options);
3379 cmd.BindVertices (SolidColorContents::CreateSolidFillVertices (
3480 entity.GetPath (), pass.GetTransientsBuffer ()));
3581
36- VS::FrameInfo info;
37- // The color really doesn't matter.
38- info.color = Color::SkyBlue ();
3982 info.mvp = Matrix::MakeOrthographic (pass.GetRenderTargetSize ()) *
4083 entity.GetTransformation ();
41-
4284 VS::BindFrameInfo (cmd, pass.GetTransientsBuffer ().EmplaceUniform (info));
4385
4486 pass.AddCommand (std::move (cmd));
@@ -59,9 +101,11 @@ bool ClipRestoreContents::Render(const ContentContext& renderer,
59101 using VS = ClipPipeline::VertexShader;
60102
61103 Command cmd;
62- cmd.label = " Clip Restore" ;
63- cmd.pipeline =
64- renderer.GetClipRestorePipeline (OptionsFromPassAndEntity (pass, entity));
104+ cmd.label = " Restore Clip" ;
105+ auto options = OptionsFromPassAndEntity (pass, entity);
106+ options.stencil_compare = CompareFunction::kLess ;
107+ options.stencil_operation = StencilOperation::kSetToReferenceValue ;
108+ cmd.pipeline = renderer.GetClipPipeline (options);
65109 cmd.stencil_reference = entity.GetStencilDepth ();
66110
67111 // Create a rect that covers the whole render target.
0 commit comments