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 #include "test_utils/ANGLETest.h"
8
9 #include <vector>
10 #include "test_utils/gl_raii.h"
11
12 using namespace angle;
13
14 class IncompleteTextureTest : public ANGLETest
15 {
16 protected:
IncompleteTextureTest()17 IncompleteTextureTest()
18 {
19 setWindowWidth(128);
20 setWindowHeight(128);
21 setConfigRedBits(8);
22 setConfigGreenBits(8);
23 setConfigBlueBits(8);
24 setConfigAlphaBits(8);
25 }
26
testSetUp()27 void testSetUp() override
28 {
29 constexpr char kVS[] = R"(precision highp float;
30 attribute vec4 position;
31 varying vec2 texcoord;
32
33 void main()
34 {
35 gl_Position = position;
36 texcoord = (position.xy * 0.5) + 0.5;
37 })";
38
39 constexpr char kFS[] = R"(precision highp float;
40 uniform sampler2D tex;
41 varying vec2 texcoord;
42
43 void main()
44 {
45 gl_FragColor = texture2D(tex, texcoord);
46 })";
47
48 mProgram = CompileProgram(kVS, kFS);
49 if (mProgram == 0)
50 {
51 FAIL() << "shader compilation failed.";
52 }
53
54 mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
55 }
56
testTearDown()57 void testTearDown() override { glDeleteProgram(mProgram); }
58
59 GLuint mProgram;
60 GLint mTextureUniformLocation;
61 };
62
63 class IncompleteTextureTestES3 : public ANGLETest
64 {
65 protected:
IncompleteTextureTestES3()66 IncompleteTextureTestES3()
67 {
68 setWindowWidth(128);
69 setWindowHeight(128);
70 setConfigRedBits(8);
71 setConfigGreenBits(8);
72 setConfigBlueBits(8);
73 setConfigAlphaBits(8);
74 }
75 };
76
77 class IncompleteTextureTestES31 : public ANGLETest
78 {
79 protected:
IncompleteTextureTestES31()80 IncompleteTextureTestES31()
81 {
82 setWindowWidth(128);
83 setWindowHeight(128);
84 setConfigRedBits(8);
85 setConfigGreenBits(8);
86 setConfigBlueBits(8);
87 setConfigAlphaBits(8);
88 }
89 };
90
91 // Test rendering with an incomplete texture.
TEST_P(IncompleteTextureTest,IncompleteTexture2D)92 TEST_P(IncompleteTextureTest, IncompleteTexture2D)
93 {
94 GLTexture tex;
95 glActiveTexture(GL_TEXTURE0);
96 glBindTexture(GL_TEXTURE_2D, tex);
97
98 glUseProgram(mProgram);
99 glUniform1i(mTextureUniformLocation, 0);
100
101 constexpr GLsizei kTextureSize = 2;
102 std::vector<GLColor> textureData(kTextureSize * kTextureSize, GLColor::red);
103
104 // Make a complete texture.
105 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA,
106 GL_UNSIGNED_BYTE, textureData.data());
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
108
109 // Should be complete - expect red.
110 drawQuad(mProgram, "position", 0.5f);
111 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "complete texture should be red";
112
113 // Make texture incomplete.
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
115
116 // Should be incomplete - expect black.
117 drawQuad(mProgram, "position", 0.5f);
118 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black) << "incomplete texture should be black";
119
120 // Make texture complete by defining the second mip.
121 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTextureSize >> 1, kTextureSize >> 1, 0, GL_RGBA,
122 GL_UNSIGNED_BYTE, textureData.data());
123
124 // Should be complete - expect red.
125 drawQuad(mProgram, "position", 0.5f);
126 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "mip-complete texture should be red";
127 }
128
129 // Tests redefining a texture with half the size works as expected.
TEST_P(IncompleteTextureTest,UpdateTexture)130 TEST_P(IncompleteTextureTest, UpdateTexture)
131 {
132 GLTexture tex;
133 glActiveTexture(GL_TEXTURE0);
134 glBindTexture(GL_TEXTURE_2D, tex);
135
136 glUseProgram(mProgram);
137 glUniform1i(mTextureUniformLocation, 0);
138
139 constexpr GLsizei redTextureSize = 64;
140 std::vector<GLColor> redTextureData(redTextureSize * redTextureSize, GLColor::red);
141 for (GLint mip = 0; mip < 7; ++mip)
142 {
143 const GLsizei mipSize = redTextureSize >> mip;
144
145 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, mipSize, mipSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
146 redTextureData.data());
147 }
148
149 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
151
152 drawQuad(mProgram, "position", 0.5f);
153 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
154
155 constexpr GLsizei greenTextureSize = 32;
156 std::vector<GLColor> greenTextureData(greenTextureSize * greenTextureSize, GLColor::green);
157
158 for (GLint mip = 0; mip < 6; ++mip)
159 {
160 const GLsizei mipSize = greenTextureSize >> mip;
161
162 glTexSubImage2D(GL_TEXTURE_2D, mip, mipSize, mipSize, mipSize, mipSize, GL_RGBA,
163 GL_UNSIGNED_BYTE, greenTextureData.data());
164 }
165
166 drawQuad(mProgram, "position", 0.5f);
167 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - greenTextureSize, getWindowHeight() - greenTextureSize,
168 GLColor::green);
169 }
170
171 // Tests that incomplete textures don't get initialized with the unpack buffer contents.
TEST_P(IncompleteTextureTestES3,UnpackBufferBound)172 TEST_P(IncompleteTextureTestES3, UnpackBufferBound)
173 {
174 // http://anglebug.com/4092
175 ANGLE_SKIP_TEST_IF(IsVulkan());
176 std::vector<GLColor> red(16, GLColor::red);
177
178 GLBuffer unpackBuffer;
179 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
180 glBufferData(GL_PIXEL_UNPACK_BUFFER, red.size() * sizeof(GLColor), red.data(), GL_STATIC_DRAW);
181
182 draw2DTexturedQuad(0.5f, 1.0f, true);
183 ASSERT_GL_NO_ERROR();
184
185 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
186 }
187
188 // Tests that the incomplete multisample texture has the correct alpha value.
TEST_P(IncompleteTextureTestES31,MultisampleTexture)189 TEST_P(IncompleteTextureTestES31, MultisampleTexture)
190 {
191 // http://anglebug.com/4092
192 ANGLE_SKIP_TEST_IF(IsVulkan());
193 constexpr char kVS[] = R"(#version 310 es
194 in vec2 position;
195 out vec2 texCoord;
196 void main()
197 {
198 gl_Position = vec4(position, 0, 1);
199 texCoord = (position * 0.5) + 0.5;
200 })";
201
202 constexpr char kFS[] = R"(#version 310 es
203 precision mediump float;
204 in vec2 texCoord;
205 out vec4 color;
206 uniform mediump sampler2DMS tex;
207 void main()
208 {
209 ivec2 texSize = textureSize(tex);
210 ivec2 texel = ivec2(vec2(texSize) * texCoord);
211 color = texelFetch(tex, texel, 0);
212 })";
213
214 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
215 glClear(GL_COLOR_BUFFER_BIT);
216 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
217
218 // The zero texture will be incomplete by default.
219 ANGLE_GL_PROGRAM(program, kVS, kFS);
220 drawQuad(program, "position", 0.5f);
221 ASSERT_GL_NO_ERROR();
222
223 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
224 }
225
226 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
227 // tests should be run against.
228 ANGLE_INSTANTIATE_TEST_ES2(IncompleteTextureTest);
229 ANGLE_INSTANTIATE_TEST_ES3(IncompleteTextureTestES3);
230 ANGLE_INSTANTIATE_TEST_ES31(IncompleteTextureTestES31);
231