GLES1: gl(Enable|Disable)ClientState
+ Introduce the GL_OES_point_size_array extension for point size array
support.
BUG=angleproject:2306
Change-Id: Ib1a60b7dcd0497eb807f0d3c80bc95b4748d9a96
Reviewed-on: https://chromium-review.googlesource.com/1014282
Commit-Queue: Lingfeng Yang <lfy@google.com>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index 1bf0b35..6c2e5bf 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -226,7 +226,8 @@
robustResourceInitialization(false),
programCacheControl(false),
textureRectangle(false),
- geometryShader(false)
+ geometryShader(false),
+ pointSizeArray(false)
{
}
@@ -698,6 +699,8 @@
map["GL_ANGLE_program_cache_control"] = esOnlyExtension(&Extensions::programCacheControl);
map["GL_ANGLE_texture_rectangle"] = enableableExtension(&Extensions::textureRectangle);
map["GL_EXT_geometry_shader"] = enableableExtension(&Extensions::geometryShader);
+ // GLES1 extensinos
+ map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArray);
// clang-format on
return map;
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index 9e34092..c2b83d8 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -374,6 +374,9 @@
// GL_EXT_geometry_shader
bool geometryShader;
+
+ // GLES1 emulation: GLES1 extensions
+ bool pointSizeArray;
};
struct ExtensionInfo
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 4b4f347..fada66e 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -2978,6 +2978,10 @@
{
mCaps = mImplementation->getNativeCaps();
+ mExtensions = mImplementation->getNativeExtensions();
+
+ mLimitations = mImplementation->getNativeLimitations();
+
// GLES1 emulation: Initialize caps (Table 6.20 / 6.22 in the ES 1.1 spec)
if (getClientVersion() < Version(2, 0))
{
@@ -2987,12 +2991,11 @@
mCaps.maxModelviewMatrixStackDepth = Caps::GlobalMatrixStackDepth;
mCaps.maxProjectionMatrixStackDepth = Caps::GlobalMatrixStackDepth;
mCaps.maxTextureMatrixStackDepth = Caps::GlobalMatrixStackDepth;
+
+ // Default extensions for GLES1
+ mExtensions.pointSizeArray = true;
}
- mExtensions = mImplementation->getNativeExtensions();
-
- mLimitations = mImplementation->getNativeLimitations();
-
if (getClientVersion() < Version(3, 0))
{
// Disable ES3+ extensions
diff --git a/src/libANGLE/Context_gles_1_0.cpp b/src/libANGLE/Context_gles_1_0.cpp
index 3f1b823..6aa7f71 100644
--- a/src/libANGLE/Context_gles_1_0.cpp
+++ b/src/libANGLE/Context_gles_1_0.cpp
@@ -95,14 +95,14 @@
UNIMPLEMENTED();
}
-void Context::disableClientState(GLenum clientState)
+void Context::disableClientState(ClientVertexArrayType clientState)
{
- UNIMPLEMENTED();
+ mGLState.gles1().setClientStateEnabled(clientState, false);
}
-void Context::enableClientState(GLenum clientState)
+void Context::enableClientState(ClientVertexArrayType clientState)
{
- UNIMPLEMENTED();
+ mGLState.gles1().setClientStateEnabled(clientState, true);
}
void Context::fogf(GLenum pname, GLfloat param)
diff --git a/src/libANGLE/Context_gles_1_0_autogen.h b/src/libANGLE/Context_gles_1_0_autogen.h
index 8dd4ab4..0584898 100644
--- a/src/libANGLE/Context_gles_1_0_autogen.h
+++ b/src/libANGLE/Context_gles_1_0_autogen.h
@@ -23,8 +23,8 @@
void color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); \
void colorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); \
void depthRangex(GLfixed n, GLfixed f); \
- void disableClientState(GLenum array); \
- void enableClientState(GLenum array); \
+ void disableClientState(ClientVertexArrayType arrayPacked); \
+ void enableClientState(ClientVertexArrayType arrayPacked); \
void fogf(GLenum pname, GLfloat param); \
void fogfv(GLenum pname, const GLfloat *params); \
void fogx(GLenum pname, GLfixed param); \
diff --git a/src/libANGLE/ErrorStrings.h b/src/libANGLE/ErrorStrings.h
index 9234b80..0b1f807 100644
--- a/src/libANGLE/ErrorStrings.h
+++ b/src/libANGLE/ErrorStrings.h
@@ -64,6 +64,7 @@
ERRMSG(InvalidBufferTypes, "Invalid buffer target enum.");
ERRMSG(InvalidBufferUsage, "Invalid buffer usage enum.");
ERRMSG(InvalidClearMask, "Invalid mask bits.");
+ERRMSG(InvalidClientState, "Invalid client vertex array type.");
ERRMSG(InvalidCombinedImageUnit,
"Specified unit must be in [GL_TEXTURE0, GL_TEXTURE0 + GL_MAX_COMBINED_IMAGE_UNITS)");
ERRMSG(InvalidConstantColor,
@@ -172,6 +173,7 @@
ERRMSG(
PixelUnpackBufferBoundForTransformFeedback,
"It is undefined behavior to use a pixel unpack buffer that is bound for transform feedback.");
+ERRMSG(PointSizeArrayExtensionNotEnabled, "GL_OES_point_size_array not enabled.");
ERRMSG(ProgramDoesNotExist, "Program doesn't exist.");
ERRMSG(ProgramNotBound, "A program must be bound.");
ERRMSG(ProgramNotLinked, "Program not linked.");
diff --git a/src/libANGLE/GLES1State.cpp b/src/libANGLE/GLES1State.cpp
index de9cf67..7a3c932 100644
--- a/src/libANGLE/GLES1State.cpp
+++ b/src/libANGLE/GLES1State.cpp
@@ -264,8 +264,53 @@
void GLES1State::multMatrix(const angle::Mat4 &m)
{
- angle::Mat4 currentMatrix = currentMatrixStack().back();
+ angle::Mat4 currentMatrix = currentMatrixStack().back();
currentMatrixStack().back() = currentMatrix.product(m);
}
+void GLES1State::setClientStateEnabled(ClientVertexArrayType clientState, bool enable)
+{
+ switch (clientState)
+ {
+ case ClientVertexArrayType::Vertex:
+ mVertexArrayEnabled = enable;
+ break;
+ case ClientVertexArrayType::Normal:
+ mNormalArrayEnabled = enable;
+ break;
+ case ClientVertexArrayType::Color:
+ mColorArrayEnabled = enable;
+ break;
+ case ClientVertexArrayType::PointSize:
+ mPointSizeArrayEnabled = enable;
+ break;
+ case ClientVertexArrayType::TextureCoord:
+ mTexCoordArrayEnabled[mClientActiveTexture] = enable;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+bool GLES1State::isClientStateEnabled(ClientVertexArrayType clientState) const
+{
+ switch (clientState)
+ {
+ case ClientVertexArrayType::Vertex:
+ return mVertexArrayEnabled;
+ case ClientVertexArrayType::Normal:
+ return mNormalArrayEnabled;
+ case ClientVertexArrayType::Color:
+ return mColorArrayEnabled;
+ case ClientVertexArrayType::PointSize:
+ return mPointSizeArrayEnabled;
+ case ClientVertexArrayType::TextureCoord:
+ return mTexCoordArrayEnabled[mClientActiveTexture];
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
} // namespace gl
diff --git a/src/libANGLE/GLES1State.h b/src/libANGLE/GLES1State.h
index b9582b1..c6d7a44 100644
--- a/src/libANGLE/GLES1State.h
+++ b/src/libANGLE/GLES1State.h
@@ -150,6 +150,9 @@
void loadMatrix(const angle::Mat4 &m);
void multMatrix(const angle::Mat4 &m);
+ void setClientStateEnabled(ClientVertexArrayType clientState, bool enable);
+ bool isClientStateEnabled(ClientVertexArrayType clientState) const;
+
private:
friend class State;
diff --git a/src/libANGLE/PackedGLEnums_autogen.cpp b/src/libANGLE/PackedGLEnums_autogen.cpp
index 81f2c8d..1731f6e 100644
--- a/src/libANGLE/PackedGLEnums_autogen.cpp
+++ b/src/libANGLE/PackedGLEnums_autogen.cpp
@@ -192,6 +192,46 @@
}
template <>
+ClientVertexArrayType FromGLenum<ClientVertexArrayType>(GLenum from)
+{
+ switch (from)
+ {
+ case GL_COLOR_ARRAY:
+ return ClientVertexArrayType::Color;
+ case GL_NORMAL_ARRAY:
+ return ClientVertexArrayType::Normal;
+ case GL_POINT_SIZE_ARRAY_OES:
+ return ClientVertexArrayType::PointSize;
+ case GL_TEXTURE_COORD_ARRAY:
+ return ClientVertexArrayType::TextureCoord;
+ case GL_VERTEX_ARRAY:
+ return ClientVertexArrayType::Vertex;
+ default:
+ return ClientVertexArrayType::InvalidEnum;
+ }
+}
+
+GLenum ToGLenum(ClientVertexArrayType from)
+{
+ switch (from)
+ {
+ case ClientVertexArrayType::Color:
+ return GL_COLOR_ARRAY;
+ case ClientVertexArrayType::Normal:
+ return GL_NORMAL_ARRAY;
+ case ClientVertexArrayType::PointSize:
+ return GL_POINT_SIZE_ARRAY_OES;
+ case ClientVertexArrayType::TextureCoord:
+ return GL_TEXTURE_COORD_ARRAY;
+ case ClientVertexArrayType::Vertex:
+ return GL_VERTEX_ARRAY;
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+template <>
CullFaceMode FromGLenum<CullFaceMode>(GLenum from)
{
switch (from)
diff --git a/src/libANGLE/PackedGLEnums_autogen.h b/src/libANGLE/PackedGLEnums_autogen.h
index 79d263a..3f68081 100644
--- a/src/libANGLE/PackedGLEnums_autogen.h
+++ b/src/libANGLE/PackedGLEnums_autogen.h
@@ -84,6 +84,22 @@
BufferUsage FromGLenum<BufferUsage>(GLenum from);
GLenum ToGLenum(BufferUsage from);
+enum class ClientVertexArrayType : uint8_t
+{
+ Color = 0,
+ Normal = 1,
+ PointSize = 2,
+ TextureCoord = 3,
+ Vertex = 4,
+
+ InvalidEnum = 5,
+ EnumCount = 5,
+};
+
+template <>
+ClientVertexArrayType FromGLenum<ClientVertexArrayType>(GLenum from);
+GLenum ToGLenum(ClientVertexArrayType from);
+
enum class CullFaceMode : uint8_t
{
Back = 0,
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index a81fe6f..eea13f9 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -827,6 +827,16 @@
// GLES1 emulation
case GL_ALPHA_TEST:
return mGLES1State.mAlphaTestEnabled;
+ case GL_VERTEX_ARRAY:
+ return mGLES1State.mVertexArrayEnabled;
+ case GL_NORMAL_ARRAY:
+ return mGLES1State.mNormalArrayEnabled;
+ case GL_COLOR_ARRAY:
+ return mGLES1State.mColorArrayEnabled;
+ case GL_POINT_SIZE_ARRAY_OES:
+ return mGLES1State.mPointSizeArrayEnabled;
+ case GL_TEXTURE_COORD_ARRAY:
+ return mGLES1State.mTexCoordArrayEnabled[mGLES1State.mClientActiveTexture];
default:
UNREACHABLE();
diff --git a/src/libANGLE/packed_gl_enums.json b/src/libANGLE/packed_gl_enums.json
index 936e5f3..53b840e 100644
--- a/src/libANGLE/packed_gl_enums.json
+++ b/src/libANGLE/packed_gl_enums.json
@@ -37,6 +37,14 @@
"StreamDraw": "GL_STREAM_DRAW",
"StreamRead": "GL_STREAM_READ"
},
+ "ClientVertexArrayType":
+ {
+ "Vertex": "GL_VERTEX_ARRAY",
+ "Normal": "GL_NORMAL_ARRAY",
+ "Color": "GL_COLOR_ARRAY",
+ "PointSize": "GL_POINT_SIZE_ARRAY_OES",
+ "TextureCoord": "GL_TEXTURE_COORD_ARRAY"
+ },
"CullFaceMode":
{
"Back": "GL_BACK",
diff --git a/src/libANGLE/validationES1.cpp b/src/libANGLE/validationES1.cpp
index dfa817b..6a7730f 100644
--- a/src/libANGLE/validationES1.cpp
+++ b/src/libANGLE/validationES1.cpp
@@ -20,7 +20,7 @@
return false; \
}
-namespace
+namespace gl
{
bool ValidateAlphaFuncCommon(gl::Context *context, gl::AlphaTestFunc func)
@@ -37,12 +37,35 @@
case gl::AlphaTestFunc::NotEqual:
return true;
default:
- context->handleError(gl::InvalidEnum() << gl::kErrorEnumNotSupported);
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
return false;
}
}
-} // anonymous namespace
+bool ValidateClientStateCommon(gl::Context *context, gl::ClientVertexArrayType arrayType)
+{
+ ANGLE_VALIDATE_IS_GLES1(context);
+ switch (arrayType)
+ {
+ case gl::ClientVertexArrayType::Vertex:
+ case gl::ClientVertexArrayType::Normal:
+ case gl::ClientVertexArrayType::Color:
+ case gl::ClientVertexArrayType::TextureCoord:
+ return true;
+ case gl::ClientVertexArrayType::PointSize:
+ if (!context->getExtensions().pointSizeArray)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), PointSizeArrayExtensionNotEnabled);
+ return false;
+ }
+ return true;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidClientState);
+ return false;
+ }
+}
+
+} // namespace gl
namespace gl
{
@@ -129,16 +152,14 @@
return true;
}
-bool ValidateDisableClientState(Context *context, GLenum array)
+bool ValidateDisableClientState(Context *context, ClientVertexArrayType arrayType)
{
- UNIMPLEMENTED();
- return true;
+ return ValidateClientStateCommon(context, arrayType);
}
-bool ValidateEnableClientState(Context *context, GLenum array)
+bool ValidateEnableClientState(Context *context, ClientVertexArrayType arrayType)
{
- UNIMPLEMENTED();
- return true;
+ return ValidateClientStateCommon(context, arrayType);
}
bool ValidateFogf(Context *context, GLenum pname, GLfloat param)
@@ -933,4 +954,5 @@
UNIMPLEMENTED();
return true;
}
-}
+
+} // namespace gl
diff --git a/src/libANGLE/validationES1.h b/src/libANGLE/validationES1.h
index be871e7..a549d8b 100644
--- a/src/libANGLE/validationES1.h
+++ b/src/libANGLE/validationES1.h
@@ -35,8 +35,8 @@
const void *pointer);
bool ValidateCullFace(Context *context, GLenum mode);
bool ValidateDepthRangex(Context *context, GLfixed n, GLfixed f);
-bool ValidateDisableClientState(Context *context, GLenum array);
-bool ValidateEnableClientState(Context *context, GLenum array);
+bool ValidateDisableClientState(Context *context, ClientVertexArrayType array);
+bool ValidateEnableClientState(Context *context, ClientVertexArrayType array);
bool ValidateFogf(Context *context, GLenum pname, GLfloat param);
bool ValidateFogfv(Context *context, GLenum pname, const GLfloat *params);
bool ValidateFogx(Context *context, GLenum pname, GLfixed param);
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index 29f11f5..27d0d3b 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -794,7 +794,14 @@
// GLES1 emulation: GLES1-specific caps
case GL_ALPHA_TEST:
+ case GL_VERTEX_ARRAY:
+ case GL_NORMAL_ARRAY:
+ case GL_COLOR_ARRAY:
+ case GL_TEXTURE_COORD_ARRAY:
return context->getClientVersion() < Version(2, 0);
+ case GL_POINT_SIZE_ARRAY_OES:
+ return context->getClientVersion() < Version(2, 0) &&
+ context->getExtensions().pointSizeArray;
default:
return false;
diff --git a/src/libGLESv2/entry_points_gles_1_0_autogen.cpp b/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
index beada99..e606904 100644
--- a/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
+++ b/src/libGLESv2/entry_points_gles_1_0_autogen.cpp
@@ -223,11 +223,12 @@
Context *context = GetValidGlobalContext();
if (context)
{
- context->gatherParams<EntryPoint::DisableClientState>(array);
+ ClientVertexArrayType arrayPacked = FromGLenum<ClientVertexArrayType>(array);
+ context->gatherParams<EntryPoint::DisableClientState>(arrayPacked);
- if (context->skipValidation() || ValidateDisableClientState(context, array))
+ if (context->skipValidation() || ValidateDisableClientState(context, arrayPacked))
{
- context->disableClientState(array);
+ context->disableClientState(arrayPacked);
}
}
}
@@ -239,11 +240,12 @@
Context *context = GetValidGlobalContext();
if (context)
{
- context->gatherParams<EntryPoint::EnableClientState>(array);
+ ClientVertexArrayType arrayPacked = FromGLenum<ClientVertexArrayType>(array);
+ context->gatherParams<EntryPoint::EnableClientState>(arrayPacked);
- if (context->skipValidation() || ValidateEnableClientState(context, array))
+ if (context->skipValidation() || ValidateEnableClientState(context, arrayPacked))
{
- context->enableClientState(array);
+ context->enableClientState(arrayPacked);
}
}
}
diff --git a/src/tests/angle_end2end_tests.gypi b/src/tests/angle_end2end_tests.gypi
index a02248e..4e63d56 100644
--- a/src/tests/angle_end2end_tests.gypi
+++ b/src/tests/angle_end2end_tests.gypi
@@ -49,6 +49,7 @@
'<(angle_path)/src/tests/gl_tests/GeometryShaderTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/AlphaFuncTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/ClientActiveTextureTest.cpp',
+ '<(angle_path)/src/tests/gl_tests/gles1/ClientStateEnable.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/CurrentColorTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/CurrentNormalTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/CurrentTextureCoordsTest.cpp',
diff --git a/src/tests/gl_tests/gles1/ClientStateEnable.cpp b/src/tests/gl_tests/gles1/ClientStateEnable.cpp
new file mode 100644
index 0000000..6ef1203
--- /dev/null
+++ b/src/tests/gl_tests/gles1/ClientStateEnable.cpp
@@ -0,0 +1,92 @@
+//
+// 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.
+//
+
+// ClientStateEnable.cpp: Tests basic usage of gl(Enable|Disable)ClientState.
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include <vector>
+
+using namespace angle;
+
+class ClientStateEnable : public ANGLETest
+{
+ protected:
+ ClientStateEnable()
+ {
+ setWindowWidth(32);
+ setWindowHeight(32);
+ setConfigRedBits(8);
+ setConfigGreenBits(8);
+ setConfigBlueBits(8);
+ setConfigAlphaBits(8);
+ setConfigDepthBits(24);
+ }
+
+ std::vector<GLenum> mClientStates = {
+ GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, GL_COLOR_ARRAY,
+ GL_POINT_SIZE_ARRAY_OES, GL_TEXTURE_COORD_ARRAY,
+ };
+};
+
+// Checks that all client vertex array states are disabled to start with.
+TEST_P(ClientStateEnable, InitialState)
+{
+ for (auto clientState : mClientStates)
+ {
+ EXPECT_GL_FALSE(glIsEnabled(clientState));
+ EXPECT_GL_NO_ERROR();
+ }
+}
+
+// Checks that glEnableClientState sets the state to be enabled,
+// and glDisableClientState sets the state to be disabled.
+TEST_P(ClientStateEnable, EnableState)
+{
+ for (auto clientState : mClientStates)
+ {
+ EXPECT_GL_FALSE(glIsEnabled(clientState));
+ glEnableClientState(clientState);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_GL_TRUE(glIsEnabled(clientState));
+ glDisableClientState(clientState);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_GL_FALSE(glIsEnabled(clientState));
+ }
+}
+
+// Negative test: Checks that invalid enums for client state generate the proper GL error.
+TEST_P(ClientStateEnable, Negative)
+{
+ glEnableClientState(0);
+ EXPECT_GL_ERROR(GL_INVALID_ENUM);
+}
+
+// Checks that enable/disable states are different if we are in different client texture unit
+// states.
+TEST_P(ClientStateEnable, TextureUnit)
+{
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ // Spec minimum lets us assume 2 multitexturing units.
+ glClientActiveTexture(GL_TEXTURE1);
+ EXPECT_GL_FALSE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ EXPECT_GL_TRUE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ EXPECT_GL_FALSE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+
+ glClientActiveTexture(GL_TEXTURE0);
+ EXPECT_GL_TRUE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ EXPECT_GL_FALSE(glIsEnabled(GL_TEXTURE_COORD_ARRAY));
+}
+
+ANGLE_INSTANTIATE_TEST(ClientStateEnable, ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES());