Commit 060088a5 by Lingfeng Yang Committed by Commit Bot

GLES1: Clip plane API and rendering

- Add unit tests for the API - Update test expectations + Pass through point size from the vertex array to the shader, required for new tests to pass. BUG=angleproject:2306 Change-Id: Ib19436c1f4cb12873adea94f734c821363f9e27d Reviewed-on: https://chromium-review.googlesource.com/1079993 Commit-Queue: Lingfeng Yang <lfy@google.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent fba1f61d
......@@ -1683,6 +1683,9 @@ void Context::getIntegervImpl(GLenum pname, GLint *params)
case GL_MAX_LIGHTS:
*params = mCaps.maxLights;
break;
case GL_MAX_CLIP_PLANES:
*params = mCaps.maxClipPlanes;
break;
// GLES1 emulation: Vertex attribute queries
case GL_VERTEX_ARRAY_BUFFER_BINDING:
case GL_NORMAL_ARRAY_BUFFER_BINDING:
......@@ -7064,6 +7067,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_MAX_PROJECTION_STACK_DEPTH:
case GL_MAX_TEXTURE_STACK_DEPTH:
case GL_MAX_LIGHTS:
case GL_MAX_CLIP_PLANES:
case GL_VERTEX_ARRAY_STRIDE:
case GL_NORMAL_ARRAY_STRIDE:
case GL_COLOR_ARRAY_STRIDE:
......
......@@ -62,12 +62,17 @@ void Context::clientActiveTexture(GLenum texture)
void Context::clipPlanef(GLenum p, const GLfloat *eqn)
{
UNIMPLEMENTED();
mGLState.gles1().setClipPlane(p - GL_CLIP_PLANE0, eqn);
}
void Context::clipPlanex(GLenum plane, const GLfixed *equation)
{
UNIMPLEMENTED();
const GLfloat equationf[4] = {
FixedToFloat(equation[0]), FixedToFloat(equation[1]), FixedToFloat(equation[2]),
FixedToFloat(equation[3]),
};
mGLState.gles1().setClipPlane(plane - GL_CLIP_PLANE0, equationf);
}
void Context::color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
......@@ -145,12 +150,19 @@ void Context::frustumx(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GL
void Context::getClipPlanef(GLenum plane, GLfloat *equation)
{
UNIMPLEMENTED();
mGLState.gles1().getClipPlane(plane - GL_CLIP_PLANE0, equation);
}
void Context::getClipPlanex(GLenum plane, GLfixed *equation)
{
UNIMPLEMENTED();
GLfloat equationf[4] = {};
mGLState.gles1().getClipPlane(plane - GL_CLIP_PLANE0, equationf);
for (int i = 0; i < 4; i++)
{
equation[i] = FloatToFixed(equationf[i]);
}
}
void Context::getFixedv(GLenum pname, GLfixed *params)
......
......@@ -66,6 +66,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(InvalidClipPlane, "Invalid clip plane.");
ERRMSG(InvalidCombinedImageUnit,
"Specified unit must be in [GL_TEXTURE0, GL_TEXTURE0 + GL_MAX_COMBINED_IMAGE_UNITS)");
ERRMSG(InvalidConstantColor,
......
......@@ -107,7 +107,7 @@ Error GLES1Renderer::prepareForDraw(Context *context, State *glState)
}
setUniformMatrix4fv(programObject, mProgramState.textureMatrixLoc, kTexUnitCount, GL_FALSE,
(float *)uniformBuffers.textureMatrices.data());
reinterpret_cast<float *>(uniformBuffers.textureMatrices.data()));
}
// Texturing
......@@ -211,25 +211,43 @@ Error GLES1Renderer::prepareForDraw(Context *context, State *glState)
setUniform1iv(programObject, mProgramState.lightEnablesLoc, kLightCount,
uniformBuffers.lightEnables.data());
setUniform4fv(programObject, mProgramState.lightAmbientsLoc, kLightCount,
(GLfloat *)uniformBuffers.lightAmbients.data());
reinterpret_cast<float *>(uniformBuffers.lightAmbients.data()));
setUniform4fv(programObject, mProgramState.lightDiffusesLoc, kLightCount,
(GLfloat *)uniformBuffers.lightDiffuses.data());
reinterpret_cast<float *>(uniformBuffers.lightDiffuses.data()));
setUniform4fv(programObject, mProgramState.lightSpecularsLoc, kLightCount,
(GLfloat *)uniformBuffers.lightSpeculars.data());
reinterpret_cast<float *>(uniformBuffers.lightSpeculars.data()));
setUniform4fv(programObject, mProgramState.lightPositionsLoc, kLightCount,
(GLfloat *)uniformBuffers.lightPositions.data());
reinterpret_cast<float *>(uniformBuffers.lightPositions.data()));
setUniform3fv(programObject, mProgramState.lightDirectionsLoc, kLightCount,
(GLfloat *)uniformBuffers.lightDirections.data());
reinterpret_cast<float *>(uniformBuffers.lightDirections.data()));
setUniform1fv(programObject, mProgramState.lightSpotlightExponentsLoc, kLightCount,
(GLfloat *)uniformBuffers.spotlightExponents.data());
reinterpret_cast<float *>(uniformBuffers.spotlightExponents.data()));
setUniform1fv(programObject, mProgramState.lightSpotlightCutoffAnglesLoc, kLightCount,
(GLfloat *)uniformBuffers.spotlightCutoffAngles.data());
reinterpret_cast<float *>(uniformBuffers.spotlightCutoffAngles.data()));
setUniform1fv(programObject, mProgramState.lightAttenuationConstsLoc, kLightCount,
(GLfloat *)uniformBuffers.attenuationConsts.data());
reinterpret_cast<float *>(uniformBuffers.attenuationConsts.data()));
setUniform1fv(programObject, mProgramState.lightAttenuationLinearsLoc, kLightCount,
(GLfloat *)uniformBuffers.attenuationLinears.data());
reinterpret_cast<float *>(uniformBuffers.attenuationLinears.data()));
setUniform1fv(programObject, mProgramState.lightAttenuationQuadraticsLoc, kLightCount,
(GLfloat *)uniformBuffers.attenuationQuadratics.data());
reinterpret_cast<float *>(uniformBuffers.attenuationQuadratics.data()));
}
// Clip planes
{
bool enableClipPlanes = false;
for (int i = 0; i < kClipPlaneCount; i++)
{
uniformBuffers.clipPlaneEnables[i] = glState->getEnableFeature(GL_CLIP_PLANE0 + i);
enableClipPlanes = enableClipPlanes || uniformBuffers.clipPlaneEnables[i];
gles1State.getClipPlane(
i, reinterpret_cast<float *>(uniformBuffers.clipPlanes.data() + i));
}
setUniform1i(programObject, mProgramState.enableClipPlanesLoc, enableClipPlanes);
setUniform1iv(programObject, mProgramState.clipPlaneEnablesLoc, kClipPlaneCount,
uniformBuffers.clipPlaneEnables.data());
setUniform4fv(programObject, mProgramState.clipPlanesLoc, kClipPlaneCount,
reinterpret_cast<float *>(uniformBuffers.clipPlanes.data()));
}
// None of those are changes in sampler, so there is no need to set the GL_PROGRAM dirty.
......@@ -484,6 +502,10 @@ Error GLES1Renderer::initializeRendererProgram(Context *context, State *glState)
mProgramState.lightAttenuationQuadraticsLoc =
programObject->getUniformLocation("light_attenuation_quadratics");
mProgramState.enableClipPlanesLoc = programObject->getUniformLocation("enable_clip_planes");
mProgramState.clipPlaneEnablesLoc = programObject->getUniformLocation("clip_plane_enables");
mProgramState.clipPlanesLoc = programObject->getUniformLocation("clip_planes");
glState->setProgram(context, programObject);
for (int i = 0; i < kTexUnitCount; i++)
......
......@@ -73,8 +73,9 @@ class GLES1Renderer final : angle::NonCopyable
void setUniform1f(Program *programObject, GLint loc, GLfloat value);
void setUniform1fv(Program *programObject, GLint loc, GLint count, const GLfloat *value);
static constexpr int kTexUnitCount = 4;
static constexpr int kLightCount = 8;
static constexpr int kTexUnitCount = 4;
static constexpr int kLightCount = 8;
static constexpr int kClipPlaneCount = 6;
static constexpr int kVertexAttribIndex = 0;
static constexpr int kNormalAttribIndex = 1;
......@@ -132,6 +133,11 @@ class GLES1Renderer final : angle::NonCopyable
GLint enableTextureCubeMapLoc;
std::array<GLint, kTexUnitCount> tex2DSamplerLocs;
std::array<GLint, kTexUnitCount> texCubeSamplerLocs;
// Clip planes
GLint enableClipPlanesLoc;
GLint clipPlaneEnablesLoc;
GLint clipPlanesLoc;
};
struct GLES1UniformBuffers
......@@ -152,6 +158,10 @@ class GLES1Renderer final : angle::NonCopyable
std::array<GLfloat, kLightCount> attenuationConsts;
std::array<GLfloat, kLightCount> attenuationLinears;
std::array<GLfloat, kLightCount> attenuationQuadratics;
// Clip planes
std::array<GLint, kClipPlaneCount> clipPlaneEnables;
std::array<Vec4Uniform, kClipPlaneCount> clipPlanes;
};
GLES1UniformBuffers mUniformBuffers;
......
......@@ -68,6 +68,8 @@ void main()
vec4 vertexPos = projection * modelview * pos;
gl_Position = vertexPos;
gl_PointSize = pointsize;
}
)";
......@@ -78,6 +80,7 @@ precision highp float;
// Defines for GL constants
#define kMaxLights 8
#define kMaxTexUnits 4
#define kMaxClipPlanes 6
#define kModulate 0x2100
#define kDecal 0x2101
......@@ -207,6 +210,12 @@ uniform float light_attenuation_consts[kMaxLights];
uniform float light_attenuation_linears[kMaxLights];
uniform float light_attenuation_quadratics[kMaxLights];
// User clip plane /////////////////////////////////////////////////////////////
uniform bool enable_clip_planes;
uniform bool clip_plane_enables[kMaxClipPlanes];
uniform vec4 clip_planes[kMaxClipPlanes];
// Outgoing fragment////////////////////////////////////////////////////////////
out vec4 frag_color;
......@@ -414,11 +423,30 @@ bool doAlphaTest(vec4 currentFragment)
return shouldPassAlpha;
}
bool doClipPlaneTest() {
bool res = true;
for (int i = 0; i < kMaxClipPlanes; i++) {
if (clip_plane_enables[i]) {
float dist = dot(clip_planes[i].xyz, pos_varying.xyz) + clip_planes[i].w;
res = res && (dist >= 0.0);
}
}
return res;
}
)";
constexpr char kGLES1DrawFShaderMain[] = R"(
void main()
{
if (enable_clip_planes) {
if (!doClipPlaneTest()) {
discard;
}
}
vec4 currentFragment;
vec4 vertex_color;
......
......@@ -137,9 +137,7 @@ void GLES1State::initialize(const Context *context, const State *state)
mLogicOp = LogicalOperation::Copy;
mClipPlaneEnabled.resize(caps.maxClipPlanes, false);
mClipPlanes.resize(caps.maxClipPlanes, angle::Vector4(0.0f, 0.0f, 0.0f, 0.0f));
mClipPlanes.resize(caps.maxClipPlanes, {false, angle::Vector4(0.0f, 0.0f, 0.0f, 0.0f)});
mPointParameters.pointSizeMin = 0.1f;
mPointParameters.pointSizeMax = 100.0f;
......@@ -368,4 +366,22 @@ void GLES1State::setShadeModel(ShadingModel model)
mShadeModel = model;
}
void GLES1State::setClipPlane(unsigned int plane, const GLfloat *equation)
{
assert(plane < mClipPlanes.size());
mClipPlanes[plane].equation[0] = equation[0];
mClipPlanes[plane].equation[1] = equation[1];
mClipPlanes[plane].equation[2] = equation[2];
mClipPlanes[plane].equation[3] = equation[3];
}
void GLES1State::getClipPlane(unsigned int plane, GLfloat *equation) const
{
assert(plane < mClipPlanes.size());
equation[0] = mClipPlanes[plane].equation[0];
equation[1] = mClipPlanes[plane].equation[1];
equation[2] = mClipPlanes[plane].equation[2];
equation[3] = mClipPlanes[plane].equation[3];
}
} // namespace gl
......@@ -114,6 +114,12 @@ struct PointParameters
GLfloat pointSize;
};
struct ClipPlaneParameters
{
bool enabled;
angle::Vector4 equation;
};
class Context;
class GLES1Renderer;
class State;
......@@ -171,6 +177,9 @@ class GLES1State final : angle::NonCopyable
void setShadeModel(ShadingModel model);
void setClipPlane(unsigned int plane, const GLfloat *equation);
void getClipPlane(unsigned int plane, GLfloat *equation) const;
private:
friend class State;
friend class GLES1Renderer;
......@@ -190,7 +199,6 @@ class GLES1State final : angle::NonCopyable
std::vector<bool> mTexCoordArrayEnabled;
// Table 6.7-6.16 (IsEnabled)
std::vector<bool> mClipPlaneEnabled;
bool mLineSmoothEnabled;
bool mPointSmoothEnabled;
bool mPointSpriteEnabled;
......@@ -242,7 +250,7 @@ class GLES1State final : angle::NonCopyable
LogicalOperation mLogicOp;
// Table 6.7
std::vector<angle::Vector4> mClipPlanes;
std::vector<ClipPlaneParameters> mClipPlanes;
// Table 6.19
HintSetting mLineSmoothHint;
......
......@@ -801,6 +801,14 @@ void State::setEnableFeature(GLenum feature, bool enabled)
case GL_COLOR_MATERIAL:
mGLES1State.mColorMaterialEnabled = enabled;
break;
case GL_CLIP_PLANE0:
case GL_CLIP_PLANE1:
case GL_CLIP_PLANE2:
case GL_CLIP_PLANE3:
case GL_CLIP_PLANE4:
case GL_CLIP_PLANE5:
mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled = enabled;
break;
default:
UNREACHABLE();
}
......@@ -887,6 +895,13 @@ bool State::getEnableFeature(GLenum feature) const
return mGLES1State.mRescaleNormalEnabled;
case GL_COLOR_MATERIAL:
return mGLES1State.mColorMaterialEnabled;
case GL_CLIP_PLANE0:
case GL_CLIP_PLANE1:
case GL_CLIP_PLANE2:
case GL_CLIP_PLANE3:
case GL_CLIP_PLANE4:
case GL_CLIP_PLANE5:
return mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled;
default:
UNREACHABLE();
return false;
......
......@@ -316,6 +316,19 @@ bool ValidateLightModelSingleComponent(Context *context, GLenum pname)
}
}
bool ValidateClipPlaneCommon(Context *context, GLenum plane)
{
ANGLE_VALIDATE_IS_GLES1(context);
if (plane < GL_CLIP_PLANE0 || plane >= GL_CLIP_PLANE0 + context->getCaps().maxClipPlanes)
{
ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidClipPlane);
return false;
}
return true;
}
} // namespace gl
namespace gl
......@@ -351,16 +364,14 @@ bool ValidateClientActiveTexture(Context *context, GLenum texture)
return ValidateMultitextureUnit(context, texture);
}
bool ValidateClipPlanef(Context *context, GLenum p, const GLfloat *eqn)
bool ValidateClipPlanef(Context *context, GLenum plane, const GLfloat *eqn)
{
UNIMPLEMENTED();
return true;
return ValidateClipPlaneCommon(context, plane);
}
bool ValidateClipPlanex(Context *context, GLenum plane, const GLfixed *equation)
{
UNIMPLEMENTED();
return true;
return ValidateClipPlaneCommon(context, plane);
}
bool ValidateColor4f(Context *context, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
......@@ -477,14 +488,12 @@ bool ValidateGetBufferParameteriv(Context *context, GLenum target, GLenum pname,
bool ValidateGetClipPlanef(Context *context, GLenum plane, GLfloat *equation)
{
UNIMPLEMENTED();
return true;
return ValidateClipPlaneCommon(context, plane);
}
bool ValidateGetClipPlanex(Context *context, GLenum plane, GLfixed *equation)
{
UNIMPLEMENTED();
return true;
return ValidateClipPlaneCommon(context, plane);
}
bool ValidateGetFixedv(Context *context, GLenum pname, GLfixed *params)
......
......@@ -811,6 +811,12 @@ bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
case GL_NORMALIZE:
case GL_RESCALE_NORMAL:
case GL_COLOR_MATERIAL:
case GL_CLIP_PLANE0:
case GL_CLIP_PLANE1:
case GL_CLIP_PLANE2:
case GL_CLIP_PLANE3:
case GL_CLIP_PLANE4:
case GL_CLIP_PLANE5:
return context->getClientVersion() < Version(2, 0);
case GL_POINT_SIZE_ARRAY_OES:
return context->getClientVersion() < Version(2, 0) &&
......
......@@ -52,6 +52,7 @@
'<(angle_path)/src/tests/gl_tests/gles1/BasicDrawTest.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/ClipPlaneTest.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',
......
//
// 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.
//
// ClipPlaneTest.cpp: Tests basic usage of user clip planes.
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include "random_utils.h"
#include <stdint.h>
using namespace angle;
class ClipPlaneTest : public ANGLETest
{
protected:
ClipPlaneTest()
{
setWindowWidth(32);
setWindowHeight(32);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
}
};
// Checks that disable / enable works as expected.
TEST_P(ClipPlaneTest, InitialState)
{
GLint planeCount = 0;
glGetIntegerv(GL_MAX_CLIP_PLANES, &planeCount);
EXPECT_GL_NO_ERROR();
EXPECT_GE(planeCount, 1); // spec minimum
GLfloat clipPlane[4] = {};
for (int i = 0; i < planeCount; i++)
{
GLenum plane = GL_CLIP_PLANE0 + i;
EXPECT_GL_FALSE(glIsEnabled(plane));
EXPECT_GL_NO_ERROR();
glGetClipPlanef(plane, clipPlane);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(0.0f, clipPlane[0]);
EXPECT_EQ(0.0f, clipPlane[1]);
EXPECT_EQ(0.0f, clipPlane[2]);
EXPECT_EQ(0.0f, clipPlane[3]);
}
}
// Negative test for invalid clip planes.
TEST_P(ClipPlaneTest, Negative)
{
GLint planeCount = 0;
glGetIntegerv(GL_MAX_CLIP_PLANES, &planeCount);
EXPECT_GL_NO_ERROR();
glClipPlanef(GL_CLIP_PLANE0 + planeCount, nullptr);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glClipPlanef(GL_CLIP_PLANE0 - 1, nullptr);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glGetClipPlanef(GL_CLIP_PLANE0 + planeCount, nullptr);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glGetClipPlanef(GL_CLIP_PLANE0 - 1, nullptr);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
// Test for setting clip plane values.
TEST_P(ClipPlaneTest, Set)
{
GLint planeCount = 0;
glGetIntegerv(GL_MAX_CLIP_PLANES, &planeCount);
EXPECT_GL_NO_ERROR();
for (int i = 0; i < planeCount; i++)
{
GLenum plane = GL_CLIP_PLANE0 + i;
EXPECT_GL_FALSE(glIsEnabled(plane));
EXPECT_GL_NO_ERROR();
GLfloat clipPlane[4] = {
i + 0.0f, i + 1.0f, i + 2.0f, i + 3.0f,
};
glClipPlanef(plane, clipPlane);
EXPECT_GL_NO_ERROR();
GLfloat actualClipPlane[4] = {};
glGetClipPlanef(plane, actualClipPlane);
EXPECT_EQ(clipPlane[0], actualClipPlane[0]);
EXPECT_EQ(clipPlane[1], actualClipPlane[1]);
EXPECT_EQ(clipPlane[2], actualClipPlane[2]);
EXPECT_EQ(clipPlane[3], actualClipPlane[3]);
glEnable(plane);
EXPECT_GL_NO_ERROR();
EXPECT_GL_TRUE(glIsEnabled(plane));
}
}
ANGLE_INSTANTIATE_TEST(ClipPlaneTest, ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES());
......@@ -455,7 +455,6 @@ TEST_P(GLES1ConformanceTest, ViewportClamp)
TEST_P(GLES1ConformanceTest, XForm)
{
ANGLE_SKIP_TEST_IF(true);
ASSERT_NE(CONFORMANCE_TEST_ERROR, XFormExec());
}
......@@ -471,13 +470,11 @@ TEST_P(GLES1ConformanceTest, XFormNormal)
TEST_P(GLES1ConformanceTest, XFormViewport)
{
ANGLE_SKIP_TEST_IF(true);
ASSERT_NE(CONFORMANCE_TEST_ERROR, XFormViewportExec());
}
TEST_P(GLES1ConformanceTest, XFormHomogenous)
{
ANGLE_SKIP_TEST_IF(true);
ASSERT_NE(CONFORMANCE_TEST_ERROR, XFormHomogenousExec());
}
......@@ -521,7 +518,6 @@ TEST_P(GLES1ConformanceTest, PointSprite)
TEST_P(GLES1ConformanceTest, UserClip)
{
ANGLE_SKIP_TEST_IF(true);
ASSERT_NE(CONFORMANCE_TEST_ERROR, UserClipExec());
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment