1 //
2 // Copyright 2015 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 
7 // IndexBufferOffsetTest.cpp: Test glDrawElements with an offset and an index buffer
8 
9 #include "test_utils/ANGLETest.h"
10 #include "system_utils.h"
11 
12 using namespace angle;
13 
14 class IndexBufferOffsetTest : public ANGLETest
15 {
16   protected:
IndexBufferOffsetTest()17     IndexBufferOffsetTest()
18     {
19         setWindowWidth(128);
20         setWindowHeight(128);
21         setConfigRedBits(8);
22         setConfigGreenBits(8);
23         setConfigBlueBits(8);
24         setConfigAlphaBits(8);
25     }
26 
SetUp()27     void SetUp() override
28     {
29         ANGLETest::SetUp();
30 
31         const std::string vertexShaderSource =
32             SHADER_SOURCE(precision highp float; attribute vec2 position;
33 
34                           void main()
35                           {
36                               gl_Position = vec4(position, 0.0, 1.0);
37                           });
38 
39         const std::string fragmentShaderSource =
40             SHADER_SOURCE(precision highp float; uniform vec4 color;
41 
42                           void main()
43                           {
44                               gl_FragColor = color;
45                           });
46 
47         mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
48         ASSERT_NE(0u, mProgram);
49 
50         mColorUniformLocation      = glGetUniformLocation(mProgram, "color");
51         mPositionAttributeLocation = glGetAttribLocation(mProgram, "position");
52 
53         const GLfloat vertices[] =
54         {
55             -1.0f, -1.0f,
56             -1.0f,  1.0f,
57              1.0f, -1.0f,
58              1.0f,  1.0f
59         };
60         glGenBuffers(1, &mVertexBuffer);
61         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
62         glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
63 
64         glGenBuffers(1, &mIndexBuffer);
65         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
66     }
67 
TearDown()68     void TearDown() override
69     {
70         glDeleteBuffers(1, &mVertexBuffer);
71         glDeleteBuffers(1, &mIndexBuffer);
72         glDeleteProgram(mProgram);
73         ANGLETest::TearDown();
74     }
75 
runTest(GLenum type,int typeWidth,void * indexData)76     void runTest(GLenum type, int typeWidth, void *indexData)
77     {
78         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
79         glClear(GL_COLOR_BUFFER_BIT);
80 
81         GLuint nullIndexData[] = {0, 0, 0, 0, 0, 0};
82 
83         size_t indexDataWidth = 6 * typeWidth;
84 
85         glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * indexDataWidth, nullptr, GL_DYNAMIC_DRAW);
86         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexDataWidth, nullIndexData);
87         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth, indexData);
88         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth, nullIndexData);
89 
90         glUseProgram(mProgram);
91 
92         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
93         glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
94         glEnableVertexAttribArray(mPositionAttributeLocation);
95 
96         glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
97 
98         for (int i = 0; i < 16; i++)
99         {
100             glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast<GLvoid *>(indexDataWidth));
101             EXPECT_PIXEL_EQ(64, 64, 255, 0, 0, 255);
102         }
103 
104         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth, nullIndexData);
105         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth, indexData);
106 
107         glUniform4f(mColorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
108         glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast<GLvoid *>(indexDataWidth * 2));
109         EXPECT_PIXEL_EQ(64, 64, 0, 255, 0, 255);
110 
111         EXPECT_GL_NO_ERROR();
112         swapBuffers();
113     }
114 
115     GLuint mProgram;
116     GLint mColorUniformLocation;
117     GLint mPositionAttributeLocation;
118     GLuint mVertexBuffer;
119     GLuint mIndexBuffer;
120 };
121 
122 // Test using an offset for an UInt8 index buffer
TEST_P(IndexBufferOffsetTest,UInt8Index)123 TEST_P(IndexBufferOffsetTest, UInt8Index)
124 {
125     GLubyte indexData[] = {0, 1, 2, 1, 2, 3};
126     runTest(GL_UNSIGNED_BYTE, 1, indexData);
127 }
128 
129 // Test using an offset for an UInt16 index buffer
TEST_P(IndexBufferOffsetTest,UInt16Index)130 TEST_P(IndexBufferOffsetTest, UInt16Index)
131 {
132     GLushort indexData[] = {0, 1, 2, 1, 2, 3};
133     runTest(GL_UNSIGNED_SHORT, 2, indexData);
134 }
135 
136 // Test using an offset for an UInt32 index buffer
TEST_P(IndexBufferOffsetTest,UInt32Index)137 TEST_P(IndexBufferOffsetTest, UInt32Index)
138 {
139     if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint"))
140     {
141         std::cout << "Test skipped because ES3 or GL_OES_element_index_uint is not available." << std::endl;
142         return;
143     }
144 
145     GLuint indexData[] = {0, 1, 2, 1, 2, 3};
146     runTest(GL_UNSIGNED_INT, 4, indexData);
147 }
148 
149 ANGLE_INSTANTIATE_TEST(IndexBufferOffsetTest,
150                        ES2_D3D9(),
151                        ES2_D3D11(),
152                        ES3_D3D11(),
153                        ES2_OPENGL(),
154                        ES3_OPENGL(),
155                        ES2_OPENGLES(),
156                        ES3_OPENGLES());
157