GLES1: Shade model API

+ add sample

BUG=angleproject:2306

Change-Id: Ie0c391618ec2b771cc99b96db02b9008a86272b9
Reviewed-on: https://chromium-review.googlesource.com/1079992
Commit-Queue: Lingfeng Yang <lfy@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 8eb6d9d..e75dcaa 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -7091,6 +7091,7 @@
             case GL_POINT_SIZE_ARRAY_STRIDE_OES:
             case GL_POINT_SIZE_ARRAY_TYPE_OES:
             case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
+            case GL_SHADE_MODEL:
                 *type      = GL_INT;
                 *numParams = 1;
                 return true;
diff --git a/src/libANGLE/Context_gles_1_0.cpp b/src/libANGLE/Context_gles_1_0.cpp
index e4f9f5d..6f0033a 100644
--- a/src/libANGLE/Context_gles_1_0.cpp
+++ b/src/libANGLE/Context_gles_1_0.cpp
@@ -451,9 +451,9 @@
         angle::Mat4::Scale(angle::Vector3(FixedToFloat(x), FixedToFloat(y), FixedToFloat(z))));
 }
 
-void Context::shadeModel(GLenum mode)
+void Context::shadeModel(ShadingModel model)
 {
-    UNIMPLEMENTED();
+    mGLState.gles1().setShadeModel(model);
 }
 
 void Context::texCoordPointer(GLint size, GLenum type, GLsizei stride, const void *ptr)
diff --git a/src/libANGLE/Context_gles_1_0_autogen.h b/src/libANGLE/Context_gles_1_0_autogen.h
index 3f3dc5c..fbde893 100644
--- a/src/libANGLE/Context_gles_1_0_autogen.h
+++ b/src/libANGLE/Context_gles_1_0_autogen.h
@@ -83,7 +83,7 @@
     void sampleCoveragex(GLclampx value, GLboolean invert);                                \
     void scalef(GLfloat x, GLfloat y, GLfloat z);                                          \
     void scalex(GLfixed x, GLfixed y, GLfixed z);                                          \
-    void shadeModel(GLenum mode);                                                          \
+    void shadeModel(ShadingModel modePacked);                                              \
     void texCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);    \
     void texEnvf(GLenum target, GLenum pname, GLfloat param);                              \
     void texEnvfv(GLenum target, GLenum pname, const GLfloat *params);                     \
diff --git a/src/libANGLE/ErrorStrings.h b/src/libANGLE/ErrorStrings.h
index 341897e..995111e 100644
--- a/src/libANGLE/ErrorStrings.h
+++ b/src/libANGLE/ErrorStrings.h
@@ -127,6 +127,7 @@
 ERRMSG(InvalidSampler, "Sampler is not valid");
 ERRMSG(InvalidShaderName, "Shader object expected.");
 ERRMSG(InvalidShaderType, "Invalid shader type.");
+ERRMSG(InvalidShadingModel, "Invalid shading model.");
 ERRMSG(InvalidStencil, "Invalid stencil.");
 ERRMSG(InvalidStencilBitMask, "Invalid stencil bit mask.");
 ERRMSG(InvalidTarget, "Invalid target.");
diff --git a/src/libANGLE/GLES1State.cpp b/src/libANGLE/GLES1State.cpp
index b98b46f..19e0d7e 100644
--- a/src/libANGLE/GLES1State.cpp
+++ b/src/libANGLE/GLES1State.cpp
@@ -363,4 +363,9 @@
     return mColorMaterialEnabled;
 }
 
+void GLES1State::setShadeModel(ShadingModel model)
+{
+    mShadeModel = model;
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/GLES1State.h b/src/libANGLE/GLES1State.h
index 65515d1..c32e725 100644
--- a/src/libANGLE/GLES1State.h
+++ b/src/libANGLE/GLES1State.h
@@ -169,6 +169,8 @@
     const MaterialParameters &materialParameters() const;
     bool isColorMaterialEnabled() const;
 
+    void setShadeModel(ShadingModel model);
+
   private:
     friend class State;
     friend class GLES1Renderer;
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index a0aacf5..a708f83 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -2413,6 +2413,9 @@
         case GL_MATRIX_MODE:
             *params = ToGLenum(mGLES1State.mMatrixMode);
             break;
+        case GL_SHADE_MODEL:
+            *params = ToGLenum(mGLES1State.mShadeModel);
+            break;
         default:
             UNREACHABLE();
             break;
diff --git a/src/libANGLE/validationES1.cpp b/src/libANGLE/validationES1.cpp
index 10d1cbe..a299065 100644
--- a/src/libANGLE/validationES1.cpp
+++ b/src/libANGLE/validationES1.cpp
@@ -862,10 +862,18 @@
     return true;
 }
 
-bool ValidateShadeModel(Context *context, GLenum mode)
+bool ValidateShadeModel(Context *context, ShadingModel mode)
 {
-    UNIMPLEMENTED();
-    return true;
+    ANGLE_VALIDATE_IS_GLES1(context);
+    switch (mode)
+    {
+        case ShadingModel::Flat:
+        case ShadingModel::Smooth:
+            return true;
+        default:
+            ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShadingModel);
+            return false;
+    }
 }
 
 bool ValidateTexCoordPointer(Context *context,
diff --git a/src/libANGLE/validationES1.h b/src/libANGLE/validationES1.h
index 5f65831..6c3b593 100644
--- a/src/libANGLE/validationES1.h
+++ b/src/libANGLE/validationES1.h
@@ -137,7 +137,7 @@
 bool ValidateSampleCoveragex(Context *context, GLclampx value, GLboolean invert);
 bool ValidateScalef(Context *context, GLfloat x, GLfloat y, GLfloat z);
 bool ValidateScalex(Context *context, GLfixed x, GLfixed y, GLfixed z);
-bool ValidateShadeModel(Context *context, GLenum mode);
+bool ValidateShadeModel(Context *context, ShadingModel mode);
 bool ValidateTexCoordPointer(Context *context,
                              GLint size,
                              GLenum type,
diff --git a/src/libGLESv2/entry_points_gles_1_0_autogen.cpp b/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
index dd1af79..a677c10 100644
--- a/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
+++ b/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
@@ -1246,11 +1246,12 @@
     Context *context = GetValidGlobalContext();
     if (context)
     {
-        context->gatherParams<EntryPoint::ShadeModel>(mode);
+        ShadingModel modePacked = FromGLenum<ShadingModel>(mode);
+        context->gatherParams<EntryPoint::ShadeModel>(modePacked);
 
-        if (context->skipValidation() || ValidateShadeModel(context, mode))
+        if (context->skipValidation() || ValidateShadeModel(context, modePacked))
         {
-            context->shadeModel(mode);
+            context->shadeModel(modePacked);
         }
     }
 }
diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.cpp b/src/libGLESv2/entry_points_gles_ext_autogen.cpp
index ec47ad4..b16d2a0 100644
--- a/src/libGLESv2/entry_points_gles_ext_autogen.cpp
+++ b/src/libGLESv2/entry_points_gles_ext_autogen.cpp
@@ -12778,11 +12778,12 @@
     if (context)
     {
         ASSERT(context == GetValidGlobalContext());
-        context->gatherParams<EntryPoint::ShadeModel>(mode);
+        ShadingModel modePacked = FromGLenum<ShadingModel>(mode);
+        context->gatherParams<EntryPoint::ShadeModel>(modePacked);
 
-        if (context->skipValidation() || ValidateShadeModel(context, mode))
+        if (context->skipValidation() || ValidateShadeModel(context, modePacked))
         {
-            context->shadeModel(mode);
+            context->shadeModel(modePacked);
         }
     }
 }
diff --git a/src/tests/angle_end2end_tests.gypi b/src/tests/angle_end2end_tests.gypi
index 0b11f2e..97933f2 100644
--- a/src/tests/angle_end2end_tests.gypi
+++ b/src/tests/angle_end2end_tests.gypi
@@ -62,6 +62,7 @@
             '<(angle_path)/src/tests/gl_tests/gles1/MatrixMultTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/MatrixStackTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/LightsTest.cpp',
+            '<(angle_path)/src/tests/gl_tests/gles1/ShadeModelTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/TextureTargetEnableTest.cpp',
             '<(angle_path)/src/tests/gl_tests/gles1/VertexPointerTest.cpp',
             '<(angle_path)/src/tests/gl_tests/GLSLTest.cpp',
diff --git a/src/tests/gl_tests/gles1/ShadeModelTest.cpp b/src/tests/gl_tests/gles1/ShadeModelTest.cpp
new file mode 100644
index 0000000..46acfee
--- /dev/null
+++ b/src/tests/gl_tests/gles1/ShadeModelTest.cpp
@@ -0,0 +1,71 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShadeModelTest.cpp: Tests the shade model API.
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include "random_utils.h"
+
+#include <stdint.h>
+
+using namespace angle;
+
+class ShadeModelTest : public ANGLETest
+{
+  protected:
+    ShadeModelTest()
+    {
+        setWindowWidth(32);
+        setWindowHeight(32);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+    }
+};
+
+// Checks that the initial state is correct.
+TEST_P(ShadeModelTest, InitialState)
+{
+    GLint shadeModel = 0;
+    glGetIntegerv(GL_SHADE_MODEL, &shadeModel);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_GLENUM_EQ(GL_SMOOTH, shadeModel);
+}
+
+// Negative test for shade model.
+TEST_P(ShadeModelTest, Negative)
+{
+    glShadeModel(GL_TEXTURE_2D);
+    EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+// Checks that the state can be set.
+TEST_P(ShadeModelTest, Set)
+{
+    glShadeModel(GL_FLAT);
+    EXPECT_GL_NO_ERROR();
+
+    GLint shadeModel;
+    glGetIntegerv(GL_SHADE_MODEL, &shadeModel);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_GLENUM_EQ(GL_FLAT, shadeModel);
+
+    glShadeModel(GL_SMOOTH);
+    EXPECT_GL_NO_ERROR();
+
+    glGetIntegerv(GL_SHADE_MODEL, &shadeModel);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_GLENUM_EQ(GL_SMOOTH, shadeModel);
+}
+
+ANGLE_INSTANTIATE_TEST(ShadeModelTest, ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES());