1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // BuiltinVariableTest:
7 //   Tests the correctness of the builtin GLSL variables.
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 
12 using namespace angle;
13 
14 class BuiltinVariableVertexIdTest : public ANGLETest
15 {
16   protected:
BuiltinVariableVertexIdTest()17     BuiltinVariableVertexIdTest()
18     {
19         setWindowWidth(64);
20         setWindowHeight(64);
21         setConfigRedBits(8);
22         setConfigGreenBits(8);
23         setConfigBlueBits(8);
24         setConfigAlphaBits(8);
25         setConfigDepthBits(24);
26     }
27 
SetUp()28     void SetUp() override
29     {
30         ANGLETest::SetUp();
31 
32         const std::string vsSource =
33             "#version 300 es\n"
34             "precision highp float;\n"
35             "in vec4 position;\n"
36             "in int expectedID;"
37             "out vec4 color;\n"
38             "\n"
39             "void main()\n"
40             "{\n"
41             "    gl_Position = position;\n"
42             "    color = vec4(gl_VertexID != expectedID, gl_VertexID == expectedID, 0.0, 1.0);"
43             "}\n";
44 
45         const std::string fsSource =
46             "#version 300 es\n"
47             "precision highp float;\n"
48             "in vec4 color;\n"
49             "out vec4 fragColor;\n"
50             "void main()\n"
51             "{\n"
52             "    fragColor = color;\n"
53             "}\n";
54 
55         mProgram = CompileProgram(vsSource, fsSource);
56         ASSERT_NE(0u, mProgram);
57 
58         mPositionLocation = glGetAttribLocation(mProgram, "position");
59         ASSERT_NE(-1, mPositionLocation);
60         mExpectedIdLocation = glGetAttribLocation(mProgram, "expectedID");
61         ASSERT_NE(-1, mExpectedIdLocation);
62 
63         static const float positions[] =
64         {
65              0.5,  0.5,
66             -0.5,  0.5,
67              0.5, -0.5,
68             -0.5, -0.5
69         };
70         glGenBuffers(1, &mPositionBuffer);
71         glBindBuffer(GL_ARRAY_BUFFER, mPositionBuffer);
72         glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
73 
74         ASSERT_GL_NO_ERROR();
75     }
76 
TearDown()77     void TearDown() override
78     {
79         glDeleteBuffers(1, &mPositionBuffer);
80         glDeleteBuffers(1, &mExpectedIdBuffer);
81         glDeleteBuffers(1, &mIndexBuffer);
82         glDeleteProgram(mProgram);
83 
84         ANGLETest::TearDown();
85     }
86 
87     // Renders a primitive using the specified mode, each vertex color will
88     // be green if gl_VertexID is correct, red otherwise.
runTest(GLuint drawMode,const std::vector<GLint> & indices,int count)89     void runTest(GLuint drawMode, const std::vector<GLint> &indices, int count)
90     {
91         glClearColor(0.0, 0.0, 0.0, 1.0);
92         glClear(GL_COLOR_BUFFER_BIT);
93 
94         glGenBuffers(1, &mIndexBuffer);
95         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
96         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * indices.size(), indices.data(),
97                      GL_STATIC_DRAW);
98 
99         std::vector<GLint> expectedIds = makeRange(count);
100 
101         glGenBuffers(1, &mExpectedIdBuffer);
102         glBindBuffer(GL_ARRAY_BUFFER, mExpectedIdBuffer);
103         glBufferData(GL_ARRAY_BUFFER, sizeof(GLint) * expectedIds.size(), expectedIds.data(),
104                      GL_STATIC_DRAW);
105 
106         glBindBuffer(GL_ARRAY_BUFFER, mPositionBuffer);
107         glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
108         glEnableVertexAttribArray(mPositionLocation);
109 
110         glBindBuffer(GL_ARRAY_BUFFER, mExpectedIdBuffer);
111         glVertexAttribIPointer(mExpectedIdLocation, 1, GL_INT, 0, 0);
112         glEnableVertexAttribArray(mExpectedIdLocation);
113 
114         glUseProgram(mProgram);
115         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
116         glDrawElements(drawMode, count, GL_UNSIGNED_INT, 0);
117 
118         std::vector<GLColor> pixels(getWindowWidth() * getWindowHeight());
119         glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
120                      pixels.data());
121 
122         ASSERT_GL_NO_ERROR();
123 
124         const GLColor green(0, 255, 0, 255);
125         const GLColor black(0, 0, 0, 255);
126 
127         for (const auto &pixel : pixels)
128         {
129             EXPECT_TRUE(pixel == green || pixel == black);
130         }
131     }
132 
makeRange(int n) const133     std::vector<GLint> makeRange(int n) const
134     {
135         std::vector<GLint> result;
136         for (int i = 0; i < n; i++)
137         {
138             result.push_back(i);
139         }
140 
141         return result;
142     }
143 
144     GLuint mPositionBuffer   = 0;
145     GLuint mExpectedIdBuffer = 0;
146     GLuint mIndexBuffer      = 0;
147 
148     GLuint mProgram           = 0;
149     GLint mPositionLocation   = -1;
150     GLint mExpectedIdLocation = -1;
151 };
152 
153 // Test gl_VertexID when rendering points
TEST_P(BuiltinVariableVertexIdTest,Points)154 TEST_P(BuiltinVariableVertexIdTest, Points)
155 {
156     runTest(GL_POINTS, makeRange(4), 4);
157 }
158 
159 // Test gl_VertexID when rendering line strips
TEST_P(BuiltinVariableVertexIdTest,LineStrip)160 TEST_P(BuiltinVariableVertexIdTest, LineStrip)
161 {
162     runTest(GL_LINE_STRIP, makeRange(4), 4);
163 }
164 
165 // Test gl_VertexID when rendering line loops
TEST_P(BuiltinVariableVertexIdTest,LineLoop)166 TEST_P(BuiltinVariableVertexIdTest, LineLoop)
167 {
168     runTest(GL_LINE_LOOP, makeRange(4), 4);
169 }
170 
171 // Test gl_VertexID when rendering lines
TEST_P(BuiltinVariableVertexIdTest,Lines)172 TEST_P(BuiltinVariableVertexIdTest, Lines)
173 {
174     runTest(GL_LINES, makeRange(4), 4);
175 }
176 
177 // Test gl_VertexID when rendering triangle strips
TEST_P(BuiltinVariableVertexIdTest,TriangleStrip)178 TEST_P(BuiltinVariableVertexIdTest, TriangleStrip)
179 {
180     runTest(GL_TRIANGLE_STRIP, makeRange(4), 4);
181 }
182 
183 // Test gl_VertexID when rendering triangle fans
TEST_P(BuiltinVariableVertexIdTest,TriangleFan)184 TEST_P(BuiltinVariableVertexIdTest, TriangleFan)
185 {
186     std::vector<GLint> indices;
187     indices.push_back(0);
188     indices.push_back(1);
189     indices.push_back(3);
190     indices.push_back(2);
191     runTest(GL_TRIANGLE_FAN, indices, 4);
192 }
193 
194 // Test gl_VertexID when rendering triangles
TEST_P(BuiltinVariableVertexIdTest,Triangles)195 TEST_P(BuiltinVariableVertexIdTest, Triangles)
196 {
197     std::vector<GLint> indices;
198     indices.push_back(0);
199     indices.push_back(1);
200     indices.push_back(2);
201     indices.push_back(1);
202     indices.push_back(2);
203     indices.push_back(3);
204     runTest(GL_TRIANGLES, indices, 6);
205 }
206 
207 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
208 // tests should be run against.
209 ANGLE_INSTANTIATE_TEST(BuiltinVariableVertexIdTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
210