| // |
| // 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 "util/test_utils.h" |
| |
| using namespace angle; |
| |
| class IndexBufferOffsetTest : public ANGLETest |
| { |
| protected: |
| IndexBufferOffsetTest() |
| { |
| setWindowWidth(128); |
| setWindowHeight(128); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| |
| void testSetUp() override |
| { |
| constexpr char kVS[] = |
| R"(precision highp float; |
| attribute vec2 position; |
| |
| void main() |
| { |
| gl_Position = vec4(position, 0.0, 1.0); |
| })"; |
| |
| constexpr char kFS[] = |
| R"(precision highp float; |
| uniform vec4 color; |
| |
| void main() |
| { |
| gl_FragColor = color; |
| })"; |
| |
| mProgram = CompileProgram(kVS, kFS); |
| 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 testTearDown() override |
| { |
| glDeleteBuffers(1, &mVertexBuffer); |
| glDeleteBuffers(1, &mIndexBuffer); |
| glDeleteProgram(mProgram); |
| } |
| |
| 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<void *>(indexDataWidth)); |
| EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::red); |
| } |
| |
| 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<void *>(indexDataWidth * 2)); |
| EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::green); |
| |
| 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) |
| { |
| // TODO(jie.a.chen@intel.com): Re-enable the test once the driver fix is |
| // available in public release. |
| // http://anglebug.com/2663 |
| ANGLE_SKIP_TEST_IF(IsIntel() && IsVulkan()); |
| |
| 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) |
| { |
| ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && |
| !IsGLExtensionEnabled("GL_OES_element_index_uint")); |
| |
| GLuint indexData[] = {0, 1, 2, 1, 2, 3}; |
| runTest(GL_UNSIGNED_INT, 4, indexData); |
| } |
| |
| // Uses index buffer offset and 2 drawElement calls one of the other, makes sure the second |
| // drawElement call will use the correct offset. |
| TEST_P(IndexBufferOffsetTest, DrawAtDifferentOffsets) |
| { |
| GLushort indexData[] = {0, 1, 2, 1, 2, 3}; |
| glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| size_t indexDataWidth = 6 * sizeof(GLushort); |
| |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexData, GL_DYNAMIC_DRAW); |
| 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); |
| |
| glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0); |
| glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, |
| reinterpret_cast<void *>(indexDataWidth / 2)); |
| |
| // Check the upper left triangle |
| EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4, GLColor::red); |
| |
| // Check the down right triangle |
| EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red); |
| |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| // Uses index buffer offset and 2 drawElement calls one of the other with different counts, |
| // makes sure the second drawElement call will have its data available. |
| TEST_P(IndexBufferOffsetTest, DrawWithDifferentCountsSameOffset) |
| { |
| GLubyte indexData[] = {99, 0, 1, 2, 1, 2, 3}; |
| glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| size_t indexDataWidth = 7 * sizeof(GLubyte); |
| |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexData, GL_DYNAMIC_DRAW); |
| 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); |
| |
| // The first draw draws the first triangle, and the second draws a quad. |
| glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(1)); |
| glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(1)); |
| |
| // Check the upper left triangle |
| EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4, GLColor::red); |
| |
| // Check the down right triangle |
| EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red); |
| |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| ANGLE_INSTANTIATE_TEST(IndexBufferOffsetTest, |
| ES2_D3D9(), |
| ES2_D3D11(), |
| ES3_D3D11(), |
| ES2_METAL(), |
| ES2_OPENGL(), |
| ES3_OPENGL(), |
| ES2_OPENGLES(), |
| ES3_OPENGLES(), |
| ES2_VULKAN()); |