Implement Culling and FrontFace

This patch implements Culling and FrontFace on backends, and add tests too.

This test also verified that we couldn't invert FrontFace on Metal backend.
Otherwise, the tests would fail on all HWs.

But we do need to invert CCW/CW on OpenGL backend. Because Y axis is up in
OpenGL while Y axis is down in WebGPU.

Bug=dawn:43

Change-Id: I7dd0922477397a13c5f7208e104ff352a673a556
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8420
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Yunchao He <yunchao.he@intel.com>
diff --git a/src/dawn_native/opengl/RenderPipelineGL.cpp b/src/dawn_native/opengl/RenderPipelineGL.cpp
index 037f185..59b1e26 100644
--- a/src/dawn_native/opengl/RenderPipelineGL.cpp
+++ b/src/dawn_native/opengl/RenderPipelineGL.cpp
@@ -40,6 +40,23 @@
             }
         }
 
+        void ApplyFrontFaceAndCulling(const OpenGLFunctions& gl,
+                                      dawn::FrontFace face,
+                                      dawn::CullMode mode) {
+            if (mode == dawn::CullMode::None) {
+                gl.Disable(GL_CULL_FACE);
+            } else {
+                gl.Enable(GL_CULL_FACE);
+                // Note that we invert winding direction in OpenGL. Because Y axis is up in OpenGL,
+                // which is different from WebGPU and other backends (Y axis is down).
+                GLenum direction = (face == dawn::FrontFace::CCW) ? GL_CW : GL_CCW;
+                gl.FrontFace(direction);
+
+                GLenum cullMode = (mode == dawn::CullMode::Front) ? GL_FRONT : GL_BACK;
+                gl.CullFace(cullMode);
+            }
+        }
+
         GLenum GLBlendFactor(dawn::BlendFactor factor, bool alpha) {
             switch (factor) {
                 case dawn::BlendFactor::Zero:
@@ -236,6 +253,8 @@
         ASSERT(mVertexArrayObject);
         gl.BindVertexArray(mVertexArrayObject);
 
+        ApplyFrontFaceAndCulling(gl, GetFrontFace(), GetCullMode());
+
         ApplyDepthStencilState(gl, GetDepthStencilStateDescriptor(), &persistentPipelineState);
 
         for (uint32_t attachmentSlot : IterateBitSet(GetColorAttachmentsMask())) {