| // | |
| // 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 <vector> | |
| #include "test_utils/gl_raii.h" | |
| using namespace angle; | |
| class IncompleteTextureTest : public ANGLETest | |
| { | |
| protected: | |
| IncompleteTextureTest() | |
| { | |
| setWindowWidth(128); | |
| setWindowHeight(128); | |
| setConfigRedBits(8); | |
| setConfigGreenBits(8); | |
| setConfigBlueBits(8); | |
| setConfigAlphaBits(8); | |
| } | |
| void testSetUp() override | |
| { | |
| constexpr char kVS[] = R"(precision highp float; | |
| attribute vec4 position; | |
| varying vec2 texcoord; | |
| void main() | |
| { | |
| gl_Position = position; | |
| texcoord = (position.xy * 0.5) + 0.5; | |
| })"; | |
| constexpr char kFS[] = R"(precision highp float; | |
| uniform sampler2D tex; | |
| varying vec2 texcoord; | |
| void main() | |
| { | |
| gl_FragColor = texture2D(tex, texcoord); | |
| })"; | |
| mProgram = CompileProgram(kVS, kFS); | |
| if (mProgram == 0) | |
| { | |
| FAIL() << "shader compilation failed."; | |
| } | |
| mTextureUniformLocation = glGetUniformLocation(mProgram, "tex"); | |
| } | |
| void testTearDown() override { glDeleteProgram(mProgram); } | |
| GLuint mProgram; | |
| GLint mTextureUniformLocation; | |
| }; | |
| class IncompleteTextureTestES3 : public ANGLETest | |
| { | |
| protected: | |
| IncompleteTextureTestES3() | |
| { | |
| setWindowWidth(128); | |
| setWindowHeight(128); | |
| setConfigRedBits(8); | |
| setConfigGreenBits(8); | |
| setConfigBlueBits(8); | |
| setConfigAlphaBits(8); | |
| } | |
| }; | |
| class IncompleteTextureTestES31 : public ANGLETest | |
| { | |
| protected: | |
| IncompleteTextureTestES31() | |
| { | |
| setWindowWidth(128); | |
| setWindowHeight(128); | |
| setConfigRedBits(8); | |
| setConfigGreenBits(8); | |
| setConfigBlueBits(8); | |
| setConfigAlphaBits(8); | |
| } | |
| }; | |
| // Test rendering with an incomplete texture. | |
| TEST_P(IncompleteTextureTest, IncompleteTexture2D) | |
| { | |
| GLTexture tex; | |
| glActiveTexture(GL_TEXTURE0); | |
| glBindTexture(GL_TEXTURE_2D, tex); | |
| glUseProgram(mProgram); | |
| glUniform1i(mTextureUniformLocation, 0); | |
| constexpr GLsizei kTextureSize = 2; | |
| std::vector<GLColor> textureData(kTextureSize * kTextureSize, GLColor::red); | |
| // Make a complete texture. | |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA, | |
| GL_UNSIGNED_BYTE, textureData.data()); | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| // Should be complete - expect red. | |
| drawQuad(mProgram, "position", 0.5f); | |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "complete texture should be red"; | |
| // Make texture incomplete. | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | |
| // Should be incomplete - expect black. | |
| drawQuad(mProgram, "position", 0.5f); | |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black) << "incomplete texture should be black"; | |
| // Make texture complete by defining the second mip. | |
| glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTextureSize >> 1, kTextureSize >> 1, 0, GL_RGBA, | |
| GL_UNSIGNED_BYTE, textureData.data()); | |
| // Should be complete - expect red. | |
| drawQuad(mProgram, "position", 0.5f); | |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "mip-complete texture should be red"; | |
| } | |
| // Tests redefining a texture with half the size works as expected. | |
| TEST_P(IncompleteTextureTest, UpdateTexture) | |
| { | |
| GLTexture tex; | |
| glActiveTexture(GL_TEXTURE0); | |
| glBindTexture(GL_TEXTURE_2D, tex); | |
| glUseProgram(mProgram); | |
| glUniform1i(mTextureUniformLocation, 0); | |
| constexpr GLsizei redTextureSize = 64; | |
| std::vector<GLColor> redTextureData(redTextureSize * redTextureSize, GLColor::red); | |
| for (GLint mip = 0; mip < 7; ++mip) | |
| { | |
| const GLsizei mipSize = redTextureSize >> mip; | |
| glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, mipSize, mipSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, | |
| redTextureData.data()); | |
| } | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| drawQuad(mProgram, "position", 0.5f); | |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); | |
| constexpr GLsizei greenTextureSize = 32; | |
| std::vector<GLColor> greenTextureData(greenTextureSize * greenTextureSize, GLColor::green); | |
| for (GLint mip = 0; mip < 6; ++mip) | |
| { | |
| const GLsizei mipSize = greenTextureSize >> mip; | |
| glTexSubImage2D(GL_TEXTURE_2D, mip, mipSize, mipSize, mipSize, mipSize, GL_RGBA, | |
| GL_UNSIGNED_BYTE, greenTextureData.data()); | |
| } | |
| drawQuad(mProgram, "position", 0.5f); | |
| EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - greenTextureSize, getWindowHeight() - greenTextureSize, | |
| GLColor::green); | |
| } | |
| // Tests that incomplete textures don't get initialized with the unpack buffer contents. | |
| TEST_P(IncompleteTextureTestES3, UnpackBufferBound) | |
| { | |
| // http://anglebug.com/4092 | |
| ANGLE_SKIP_TEST_IF(IsVulkan()); | |
| std::vector<GLColor> red(16, GLColor::red); | |
| GLBuffer unpackBuffer; | |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer); | |
| glBufferData(GL_PIXEL_UNPACK_BUFFER, red.size() * sizeof(GLColor), red.data(), GL_STATIC_DRAW); | |
| draw2DTexturedQuad(0.5f, 1.0f, true); | |
| ASSERT_GL_NO_ERROR(); | |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); | |
| } | |
| // Tests that the incomplete multisample texture has the correct alpha value. | |
| TEST_P(IncompleteTextureTestES31, MultisampleTexture) | |
| { | |
| // http://anglebug.com/4092 | |
| ANGLE_SKIP_TEST_IF(IsVulkan()); | |
| constexpr char kVS[] = R"(#version 310 es | |
| in vec2 position; | |
| out vec2 texCoord; | |
| void main() | |
| { | |
| gl_Position = vec4(position, 0, 1); | |
| texCoord = (position * 0.5) + 0.5; | |
| })"; | |
| constexpr char kFS[] = R"(#version 310 es | |
| precision mediump float; | |
| in vec2 texCoord; | |
| out vec4 color; | |
| uniform mediump sampler2DMS tex; | |
| void main() | |
| { | |
| ivec2 texSize = textureSize(tex); | |
| ivec2 texel = ivec2(vec2(texSize) * texCoord); | |
| color = texelFetch(tex, texel, 0); | |
| })"; | |
| glClearColor(1.0f, 0.0f, 0.0f, 1.0f); | |
| glClear(GL_COLOR_BUFFER_BIT); | |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); | |
| // The zero texture will be incomplete by default. | |
| ANGLE_GL_PROGRAM(program, kVS, kFS); | |
| drawQuad(program, "position", 0.5f); | |
| ASSERT_GL_NO_ERROR(); | |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); | |
| } | |
| // Use this to select which configurations (e.g. which renderer, which GLES major version) these | |
| // tests should be run against. | |
| ANGLE_INSTANTIATE_TEST_ES2(IncompleteTextureTest); | |
| ANGLE_INSTANTIATE_TEST_ES3(IncompleteTextureTestES3); | |
| ANGLE_INSTANTIATE_TEST_ES31(IncompleteTextureTestES31); |