// // 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. // #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" using namespace angle; class LineLoopTest : public ANGLETest { protected: LineLoopTest() { setWindowWidth(256); setWindowHeight(256); setConfigRedBits(8); setConfigGreenBits(8); setConfigBlueBits(8); setConfigAlphaBits(8); } void testSetUp() override { mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); if (mProgram == 0) { FAIL() << "shader compilation failed."; } mPositionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib()); mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform()); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); ASSERT_GL_NO_ERROR(); } void testTearDown() override { glDeleteProgram(mProgram); } void checkPixels() { std::vector pixels(getWindowWidth() * getWindowHeight() * 4); glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); ASSERT_GL_NO_ERROR(); for (int y = 0; y < getWindowHeight(); y++) { for (int x = 0; x < getWindowWidth(); x++) { const GLubyte *pixel = &pixels[0] + ((y * getWindowWidth() + x) * 4); EXPECT_EQ(pixel[0], 0); EXPECT_EQ(pixel[1], pixel[2]); ASSERT_EQ(pixel[3], 255); } } } void runTest(GLenum indexType, GLuint indexBuffer, const void *indexPtr) { glClear(GL_COLOR_BUFFER_BIT); static const GLfloat loopPositions[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f}; static const GLfloat stripPositions[] = {-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f}; static const GLubyte stripIndices[] = {1, 0, 3, 2, 1}; glUseProgram(mProgram); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); glEnableVertexAttribArray(mPositionLocation); glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, loopPositions); glUniform4f(mColorLocation, 0.0f, 0.0f, 1.0f, 1.0f); glDrawElements(GL_LINE_LOOP, 4, indexType, indexPtr); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, stripPositions); glUniform4f(mColorLocation, 0, 1, 0, 1); glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_BYTE, stripIndices); checkPixels(); } GLuint mProgram; GLint mPositionLocation; GLint mColorLocation; }; TEST_P(LineLoopTest, LineLoopUByteIndices) { // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details // On Win7, the D3D SDK Layers emits a false warning for these tests. // This doesn't occur on Windows 10 (Version 1511) though. ignoreD3D11SDKLayersWarnings(); static const GLubyte indices[] = {0, 7, 6, 9, 8, 0}; runTest(GL_UNSIGNED_BYTE, 0, indices + 1); } TEST_P(LineLoopTest, LineLoopUShortIndices) { // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details ignoreD3D11SDKLayersWarnings(); static const GLushort indices[] = {0, 7, 6, 9, 8, 0}; runTest(GL_UNSIGNED_SHORT, 0, indices + 1); } TEST_P(LineLoopTest, LineLoopUIntIndices) { if (!IsGLExtensionEnabled("GL_OES_element_index_uint")) { return; } // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details ignoreD3D11SDKLayersWarnings(); static const GLuint indices[] = {0, 7, 6, 9, 8, 0}; runTest(GL_UNSIGNED_INT, 0, indices + 1); } TEST_P(LineLoopTest, LineLoopUByteIndexBuffer) { // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details ignoreD3D11SDKLayersWarnings(); static const GLubyte indices[] = {0, 7, 6, 9, 8, 0}; GLuint buf; glGenBuffers(1, &buf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); runTest(GL_UNSIGNED_BYTE, buf, reinterpret_cast(sizeof(GLubyte))); glDeleteBuffers(1, &buf); } TEST_P(LineLoopTest, LineLoopUShortIndexBuffer) { // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details ignoreD3D11SDKLayersWarnings(); static const GLushort indices[] = {0, 7, 6, 9, 8, 0}; GLuint buf; glGenBuffers(1, &buf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); runTest(GL_UNSIGNED_SHORT, buf, reinterpret_cast(sizeof(GLushort))); glDeleteBuffers(1, &buf); } TEST_P(LineLoopTest, LineLoopUIntIndexBuffer) { if (!IsGLExtensionEnabled("GL_OES_element_index_uint")) { return; } // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details ignoreD3D11SDKLayersWarnings(); static const GLuint indices[] = {0, 7, 6, 9, 8, 0}; GLuint buf; glGenBuffers(1, &buf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); runTest(GL_UNSIGNED_INT, buf, reinterpret_cast(sizeof(GLuint))); glDeleteBuffers(1, &buf); } // Tests an edge case with a very large line loop element count. // Disabled because it is slow and triggers an internal error. TEST_P(LineLoopTest, DISABLED_DrawArraysWithLargeCount) { constexpr char kVS[] = "void main() { gl_Position = vec4(0); }"; constexpr char kFS[] = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }"; ANGLE_GL_PROGRAM(program, kVS, kFS); glUseProgram(program); glDrawArrays(GL_LINE_LOOP, 0, 0x3FFFFFFE); EXPECT_GL_ERROR(GL_OUT_OF_MEMORY); glDrawArrays(GL_LINE_LOOP, 0, 0x1FFFFFFE); EXPECT_GL_NO_ERROR(); } class LineLoopIndirectTest : public LineLoopTest { protected: void runTest(GLenum indexType, const void *indices, GLuint indicesSize, GLuint firstIndex) { struct DrawCommand { GLuint count; GLuint primCount; GLuint firstIndex; GLint baseVertex; GLuint reservedMustBeZero; }; glClear(GL_COLOR_BUFFER_BIT); static const GLfloat loopPositions[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f}; static const GLfloat stripPositions[] = {-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f}; static const GLubyte stripIndices[] = {1, 0, 3, 2, 1}; glUseProgram(mProgram); GLuint vertexArray = 0; glGenVertexArrays(1, &vertexArray); glBindVertexArray(vertexArray); ASSERT_GL_NO_ERROR(); GLuint vertBuffer = 0; glGenBuffers(1, &vertBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(loopPositions), loopPositions, GL_STATIC_DRAW); glEnableVertexAttribArray(mPositionLocation); glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr); glUniform4f(mColorLocation, 0.0f, 0.0f, 1.0f, 1.0f); ASSERT_GL_NO_ERROR(); GLuint buf; glGenBuffers(1, &buf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSize, indices, GL_STATIC_DRAW); DrawCommand cmdBuffer = {}; cmdBuffer.count = 4; cmdBuffer.firstIndex = firstIndex; cmdBuffer.primCount = 1; GLuint indirectBuf = 0; glGenBuffers(1, &indirectBuf); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuf); glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawCommand), &cmdBuffer, GL_STATIC_DRAW); ASSERT_GL_NO_ERROR(); glDrawElementsIndirect(GL_LINE_LOOP, indexType, nullptr); ASSERT_GL_NO_ERROR(); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); glDeleteBuffers(1, &indirectBuf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDeleteBuffers(1, &buf); glBindVertexArray(0); glDeleteVertexArrays(1, &vertexArray); glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteBuffers(1, &vertBuffer); glEnableVertexAttribArray(mPositionLocation); glVertexAttribPointer(mPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, stripPositions); glUniform4f(mColorLocation, 0, 1, 0, 1); glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_BYTE, stripIndices); checkPixels(); } }; TEST_P(LineLoopIndirectTest, UByteIndexIndirectBuffer) { // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details ignoreD3D11SDKLayersWarnings(); static const GLubyte indices[] = {0, 7, 6, 9, 8, 0}; // Start at index 1. runTest(GL_UNSIGNED_BYTE, reinterpret_cast(indices), sizeof(indices), 1); } TEST_P(LineLoopIndirectTest, UShortIndexIndirectBuffer) { // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details ignoreD3D11SDKLayersWarnings(); static const GLushort indices[] = {0, 7, 6, 9, 8, 0}; // Start at index 1. runTest(GL_UNSIGNED_SHORT, reinterpret_cast(indices), sizeof(indices), 1); } // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. ANGLE_INSTANTIATE_TEST_ES2(LineLoopTest); ANGLE_INSTANTIATE_TEST_ES31(LineLoopIndirectTest);