// // Copyright 2015 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. // // IndexBufferOffsetTest.cpp: Test glDrawElements with an offset and an index buffer #include "test_utils/ANGLETest.h" #include "system_utils.h" using namespace angle; class IndexBufferOffsetTest : public ANGLETest { protected: IndexBufferOffsetTest() { setWindowWidth(128); setWindowHeight(128); setConfigRedBits(8); setConfigGreenBits(8); setConfigBlueBits(8); setConfigAlphaBits(8); } void SetUp() override { ANGLETest::SetUp(); const std::string vertexShaderSource = SHADER_SOURCE(precision highp float; attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }); const std::string fragmentShaderSource = SHADER_SOURCE(precision highp float; uniform vec4 color; void main() { gl_FragColor = color; }); mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource); ASSERT_NE(0u, mProgram); mColorUniformLocation = glGetUniformLocation(mProgram, "color"); mPositionAttributeLocation = glGetAttribLocation(mProgram, "position"); const GLfloat vertices[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f }; glGenBuffers(1, &mVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW); glGenBuffers(1, &mIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); } void TearDown() override { glDeleteBuffers(1, &mVertexBuffer); glDeleteBuffers(1, &mIndexBuffer); glDeleteProgram(mProgram); ANGLETest::TearDown(); } void runTest(GLenum type, int typeWidth, void *indexData) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); GLuint nullIndexData[] = {0, 0, 0, 0, 0, 0}; size_t indexDataWidth = 6 * typeWidth; glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * indexDataWidth, nullptr, GL_DYNAMIC_DRAW); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexDataWidth, nullIndexData); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth, indexData); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth, nullIndexData); glUseProgram(mProgram); glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(mPositionAttributeLocation); glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f); for (int i = 0; i < 16; i++) { glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast(indexDataWidth)); EXPECT_PIXEL_EQ(64, 64, 255, 0, 0, 255); } glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth, nullIndexData); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth, indexData); glUniform4f(mColorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f); glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast(indexDataWidth * 2)); EXPECT_PIXEL_EQ(64, 64, 0, 255, 0, 255); EXPECT_GL_NO_ERROR(); swapBuffers(); } GLuint mProgram; GLint mColorUniformLocation; GLint mPositionAttributeLocation; GLuint mVertexBuffer; GLuint mIndexBuffer; }; // Test using an offset for an UInt8 index buffer TEST_P(IndexBufferOffsetTest, UInt8Index) { GLubyte indexData[] = {0, 1, 2, 1, 2, 3}; runTest(GL_UNSIGNED_BYTE, 1, indexData); } // Test using an offset for an UInt16 index buffer TEST_P(IndexBufferOffsetTest, UInt16Index) { GLushort indexData[] = {0, 1, 2, 1, 2, 3}; runTest(GL_UNSIGNED_SHORT, 2, indexData); } // Test using an offset for an UInt32 index buffer TEST_P(IndexBufferOffsetTest, UInt32Index) { if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_element_index_uint")) { std::cout << "Test skipped because ES3 or GL_OES_element_index_uint is not available." << std::endl; return; } GLuint indexData[] = {0, 1, 2, 1, 2, 3}; runTest(GL_UNSIGNED_INT, 4, indexData); } ANGLE_INSTANTIATE_TEST(IndexBufferOffsetTest, ES2_D3D9(), ES2_D3D11(), ES3_D3D11(), ES2_OPENGL(), ES3_OPENGL(), ES2_OPENGLES(), ES3_OPENGLES());