[Flutter GPU] Add WindingOrder. (#55413)
Resolves https://github.com/flutter/flutter/issues/155636.
(Extends test in https://github.com/flutter/engine/pull/55409)
diff --git a/lib/gpu/formats.h b/lib/gpu/formats.h
index a70d608..cd9ac85 100644
--- a/lib/gpu/formats.h
+++ b/lib/gpu/formats.h
@@ -522,6 +522,25 @@
return ToImpellerCullMode(static_cast<FlutterGPUCullMode>(value));
}
+enum class FlutterGPUWindingOrder {
+ kClockwise,
+ kCounterClockwise,
+};
+
+constexpr impeller::WindingOrder ToImpellerWindingOrder(
+ FlutterGPUWindingOrder value) {
+ switch (value) {
+ case FlutterGPUWindingOrder::kClockwise:
+ return impeller::WindingOrder::kClockwise;
+ case FlutterGPUWindingOrder::kCounterClockwise:
+ return impeller::WindingOrder::kCounterClockwise;
+ }
+}
+
+constexpr impeller::WindingOrder ToImpellerWindingOrder(int value) {
+ return ToImpellerWindingOrder(static_cast<FlutterGPUWindingOrder>(value));
+}
+
} // namespace gpu
} // namespace flutter
diff --git a/lib/gpu/lib/src/formats.dart b/lib/gpu/lib/src/formats.dart
index 2bd1b5d..ec6e703 100644
--- a/lib/gpu/lib/src/formats.dart
+++ b/lib/gpu/lib/src/formats.dart
@@ -141,6 +141,11 @@
backFace,
}
+enum WindingOrder {
+ clockwise,
+ counterClockwise,
+}
+
enum CompareFunction {
/// Comparison test never passes.
never,
diff --git a/lib/gpu/lib/src/render_pass.dart b/lib/gpu/lib/src/render_pass.dart
index 18718bb..f690210 100644
--- a/lib/gpu/lib/src/render_pass.dart
+++ b/lib/gpu/lib/src/render_pass.dart
@@ -262,6 +262,10 @@
_setCullMode(cullMode.index);
}
+ void setWindingOrder(WindingOrder windingOrder) {
+ _setWindingOrder(windingOrder.index);
+ }
+
void draw() {
if (!_draw()) {
throw Exception("Failed to append draw");
@@ -416,6 +420,10 @@
symbol: 'InternalFlutterGpu_RenderPass_SetCullMode')
external void _setCullMode(int cullMode);
+ @Native<Void Function(Pointer<Void>, Int)>(
+ symbol: 'InternalFlutterGpu_RenderPass_SetWindingOrder')
+ external void _setWindingOrder(int windingOrder);
+
@Native<Bool Function(Pointer<Void>)>(
symbol: 'InternalFlutterGpu_RenderPass_Draw')
external bool _draw();
diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc
index 69eec79..26fcf54 100644
--- a/lib/gpu/render_pass.cc
+++ b/lib/gpu/render_pass.cc
@@ -567,6 +567,15 @@
pipeline_descriptor.SetCullMode(flutter::gpu::ToImpellerCullMode(cull_mode));
}
+void InternalFlutterGpu_RenderPass_SetWindingOrder(
+ flutter::gpu::RenderPass* wrapper,
+ int winding_order) {
+ impeller::PipelineDescriptor& pipeline_descriptor =
+ wrapper->GetPipelineDescriptor();
+ pipeline_descriptor.SetWindingOrder(
+ flutter::gpu::ToImpellerWindingOrder(winding_order));
+}
+
bool InternalFlutterGpu_RenderPass_Draw(flutter::gpu::RenderPass* wrapper) {
return wrapper->Draw();
}
diff --git a/lib/gpu/render_pass.h b/lib/gpu/render_pass.h
index 94f6627..4069d37 100644
--- a/lib/gpu/render_pass.h
+++ b/lib/gpu/render_pass.h
@@ -252,6 +252,11 @@
int cull_mode);
FLUTTER_GPU_EXPORT
+extern void InternalFlutterGpu_RenderPass_SetWindingOrder(
+ flutter::gpu::RenderPass* wrapper,
+ int winding_order);
+
+FLUTTER_GPU_EXPORT
extern bool InternalFlutterGpu_RenderPass_Draw(
flutter::gpu::RenderPass* wrapper);
diff --git a/testing/dart/gpu_test.dart b/testing/dart/gpu_test.dart
index 05ba001..e8ead29 100644
--- a/testing/dart/gpu_test.dart
+++ b/testing/dart/gpu_test.dart
@@ -479,11 +479,21 @@
state.renderPass.draw();
}
+ // Draw the green rectangle.
+ // Defaults to clockwise winding order. So frontface culling should not
+ // impact the green triangle.
state.renderPass.setCullMode(gpu.CullMode.frontFace);
drawTriangle(Colors.lime);
+
+ // Backface cull a red triangle.
state.renderPass.setCullMode(gpu.CullMode.backFace);
drawTriangle(Colors.red);
+ // Invert the winding mode and frontface cull a red rectangle.
+ state.renderPass.setWindingOrder(gpu.WindingOrder.counterClockwise);
+ state.renderPass.setCullMode(gpu.CullMode.frontFace);
+ drawTriangle(Colors.red);
+
state.commandBuffer.submit();
final ui.Image image = state.renderTexture.asImage();