• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   public:
setupFramebuffer(const GLenum sizedInternalFormat)77     void setupFramebuffer(const GLenum sizedInternalFormat)
78     {
79         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
80         glRenderbufferStorage(GL_RENDERBUFFER, sizedInternalFormat, getWindowWidth(),
81                               getWindowHeight());
82         ASSERT_GL_NO_ERROR();
83 
84         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
85         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
86                                   mRenderbuffer);
87         glViewport(0, 0, getWindowWidth(), getWindowHeight());
88         ASSERT_GL_NO_ERROR();
89     }
90 
91   private:
92     GLRenderbuffer mRenderbuffer;
93     GLFramebuffer mFramebuffer;
94 };
95 
96 class IncompleteTextureTestES31 : public ANGLETest
97 {
98   protected:
IncompleteTextureTestES31()99     IncompleteTextureTestES31()
100     {
101         setWindowWidth(128);
102         setWindowHeight(128);
103         setConfigRedBits(8);
104         setConfigGreenBits(8);
105         setConfigBlueBits(8);
106         setConfigAlphaBits(8);
107     }
108 };
109 
110 // Test rendering with an incomplete texture.
TEST_P(IncompleteTextureTest,IncompleteTexture2D)111 TEST_P(IncompleteTextureTest, IncompleteTexture2D)
112 {
113     GLTexture tex;
114     glActiveTexture(GL_TEXTURE0);
115     glBindTexture(GL_TEXTURE_2D, tex);
116 
117     glUseProgram(mProgram);
118     glUniform1i(mTextureUniformLocation, 0);
119 
120     constexpr GLsizei kTextureSize = 2;
121     std::vector<GLColor> textureData(kTextureSize * kTextureSize, GLColor::red);
122 
123     // Make a complete texture.
124     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA,
125                  GL_UNSIGNED_BYTE, textureData.data());
126     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
127 
128     // Should be complete - expect red.
129     drawQuad(mProgram, "position", 0.5f);
130     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "complete texture should be red";
131 
132     // Make texture incomplete.
133     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
134 
135     // Should be incomplete - expect black.
136     drawQuad(mProgram, "position", 0.5f);
137     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black) << "incomplete texture should be black";
138 
139     // Make texture complete by defining the second mip.
140     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTextureSize >> 1, kTextureSize >> 1, 0, GL_RGBA,
141                  GL_UNSIGNED_BYTE, textureData.data());
142 
143     // Should be complete - expect red.
144     drawQuad(mProgram, "position", 0.5f);
145     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "mip-complete texture should be red";
146 }
147 
148 // Tests redefining a texture with half the size works as expected.
TEST_P(IncompleteTextureTest,UpdateTexture)149 TEST_P(IncompleteTextureTest, UpdateTexture)
150 {
151     GLTexture tex;
152     glActiveTexture(GL_TEXTURE0);
153     glBindTexture(GL_TEXTURE_2D, tex);
154 
155     glUseProgram(mProgram);
156     glUniform1i(mTextureUniformLocation, 0);
157 
158     constexpr GLsizei redTextureSize = 64;
159     std::vector<GLColor> redTextureData(redTextureSize * redTextureSize, GLColor::red);
160     for (GLint mip = 0; mip < 7; ++mip)
161     {
162         const GLsizei mipSize = redTextureSize >> mip;
163 
164         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, mipSize, mipSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
165                      redTextureData.data());
166     }
167 
168     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
169     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
170 
171     drawQuad(mProgram, "position", 0.5f);
172     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
173 
174     constexpr GLsizei greenTextureSize = 32;
175     std::vector<GLColor> greenTextureData(greenTextureSize * greenTextureSize, GLColor::green);
176 
177     for (GLint mip = 0; mip < 6; ++mip)
178     {
179         const GLsizei mipSize = greenTextureSize >> mip;
180 
181         glTexSubImage2D(GL_TEXTURE_2D, mip, mipSize, mipSize, mipSize, mipSize, GL_RGBA,
182                         GL_UNSIGNED_BYTE, greenTextureData.data());
183     }
184 
185     drawQuad(mProgram, "position", 0.5f);
186     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - greenTextureSize, getWindowHeight() - greenTextureSize,
187                           GLColor::green);
188 }
189 
190 // Tests that incomplete textures don't get initialized with the unpack buffer contents.
TEST_P(IncompleteTextureTestES3,UnpackBufferBound)191 TEST_P(IncompleteTextureTestES3, UnpackBufferBound)
192 {
193     // http://anglebug.com/4092
194     ANGLE_SKIP_TEST_IF(IsVulkan());
195     std::vector<GLColor> red(16, GLColor::red);
196 
197     GLBuffer unpackBuffer;
198     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
199     glBufferData(GL_PIXEL_UNPACK_BUFFER, red.size() * sizeof(GLColor), red.data(), GL_STATIC_DRAW);
200 
201     draw2DTexturedQuad(0.5f, 1.0f, true);
202     ASSERT_GL_NO_ERROR();
203 
204     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
205 }
206 
207 // Tests that the incomplete multisample texture has the correct alpha value.
TEST_P(IncompleteTextureTestES31,MultisampleTexture)208 TEST_P(IncompleteTextureTestES31, MultisampleTexture)
209 {
210     // http://anglebug.com/4092
211     ANGLE_SKIP_TEST_IF(IsVulkan());
212     constexpr char kVS[] = R"(#version 310 es
213 in vec2 position;
214 out vec2 texCoord;
215 void main()
216 {
217     gl_Position = vec4(position, 0, 1);
218     texCoord = (position * 0.5) + 0.5;
219 })";
220 
221     constexpr char kFS[] = R"(#version 310 es
222 precision mediump float;
223 in vec2 texCoord;
224 out vec4 color;
225 uniform mediump sampler2DMS tex;
226 void main()
227 {
228     ivec2 texSize = textureSize(tex);
229     ivec2 texel = ivec2(vec2(texSize) * texCoord);
230     color = texelFetch(tex, texel, 0);
231 })";
232 
233     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
234     glClear(GL_COLOR_BUFFER_BIT);
235     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
236 
237     // The zero texture will be incomplete by default.
238     ANGLE_GL_PROGRAM(program, kVS, kFS);
239     drawQuad(program, "position", 0.5f);
240     ASSERT_GL_NO_ERROR();
241 
242     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
243 }
244 
245 // Verifies that an incomplete integer texture has a signed integer type default value.
TEST_P(IncompleteTextureTestES3,IntegerType)246 TEST_P(IncompleteTextureTestES3, IntegerType)
247 {
248     // GLES backend on Adreno has a problem to create a incomplete texture, although it doesn't go
249     // through the routine which creates a incomplete texture in the ANGLE driver.
250     ANGLE_SKIP_TEST_IF(IsAdreno() && IsAndroid() && IsOpenGLES());
251 
252     // http://crbug.com/1168370
253     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsOpenGL());
254 
255     constexpr char kVS[] = R"(#version 300 es
256 in highp vec2 position;
257 out highp vec2 texCoord;
258 void main()
259 {
260     gl_Position = vec4(position, 0, 1);
261     texCoord = (position * 0.5) + 0.5;
262 })";
263 
264     constexpr char kFS[] = R"(#version 300 es
265 in highp vec2 texCoord;
266 out highp ivec4 color;
267 uniform highp isampler2D tex;
268 void main()
269 {
270     ivec2 texSize = textureSize(tex, 0);
271     ivec2 texel = ivec2(vec2(texSize) * texCoord);
272     color = texelFetch(tex, texel, 0);
273 })";
274 
275     constexpr GLint clearColori[4] = {-10, 20, -30, 40};
276     constexpr GLint blackColori[4] = {0, 0, 0, 127};
277 
278     setupFramebuffer(GL_RGBA8I);
279     glClearBufferiv(GL_COLOR, 0, clearColori);
280     ASSERT_GL_NO_ERROR();
281     EXPECT_PIXEL_8I(0, 0, clearColori[0], clearColori[1], clearColori[2], clearColori[3]);
282 
283     // Since no texture attachment has been specified, it is incomplete by definition
284     ANGLE_GL_PROGRAM(program, kVS, kFS);
285 
286     glUseProgram(program);
287 
288     drawQuad(program, "position", 0.5f);
289     ASSERT_GL_NO_ERROR();
290 
291     const int width  = getWindowWidth() - 1;
292     const int height = getWindowHeight() - 1;
293     EXPECT_PIXEL_8I(0, 0, blackColori[0], blackColori[1], blackColori[2], blackColori[3]);
294     EXPECT_PIXEL_8I(width, 0, blackColori[0], blackColori[1], blackColori[2], blackColori[3]);
295     EXPECT_PIXEL_8I(0, height, blackColori[0], blackColori[1], blackColori[2], blackColori[3]);
296     EXPECT_PIXEL_8I(width, height, blackColori[0], blackColori[1], blackColori[2], blackColori[3]);
297 }
298 
299 // Verifies that an incomplete unsigned integer texture has an unsigned integer type default value.
TEST_P(IncompleteTextureTestES3,UnsignedIntegerType)300 TEST_P(IncompleteTextureTestES3, UnsignedIntegerType)
301 {
302     // GLES backend on Adreno has a problem to create a incomplete texture, although it doesn't go
303     // through the routine which creates a incomplete texture in the ANGLE driver.
304     ANGLE_SKIP_TEST_IF(IsAdreno() && IsAndroid() && IsOpenGLES());
305 
306     // http://crbug.com/1168370
307     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsOpenGL());
308 
309     constexpr char kVS[] = R"(#version 300 es
310 in highp vec2 position;
311 out highp vec2 texCoord;
312 void main()
313 {
314     gl_Position = vec4(position, 0, 1);
315     texCoord = (position * 0.5) + 0.5;
316 })";
317 
318     constexpr char kFS[] = R"(#version 300 es
319 in highp vec2 texCoord;
320 out highp uvec4 color;
321 uniform highp usampler2D tex;
322 void main()
323 {
324     ivec2 texSize = textureSize(tex, 0);
325     ivec2 texel = ivec2(vec2(texSize) * texCoord);
326     color = texelFetch(tex, texel, 0);
327 })";
328 
329     constexpr GLuint clearColorui[4] = {40, 30, 20, 10};
330     constexpr GLuint blackColorui[4] = {0, 0, 0, 255};
331 
332     setupFramebuffer(GL_RGBA8UI);
333     glClearBufferuiv(GL_COLOR, 0, clearColorui);
334     ASSERT_GL_NO_ERROR();
335     EXPECT_PIXEL_8UI(0, 0, clearColorui[0], clearColorui[1], clearColorui[2], clearColorui[3]);
336 
337     // Since no texture attachment has been specified, it is incomplete by definition
338     ANGLE_GL_PROGRAM(program, kVS, kFS);
339 
340     glUseProgram(program);
341 
342     drawQuad(program, "position", 0.5f);
343     ASSERT_GL_NO_ERROR();
344 
345     const int width  = getWindowWidth() - 1;
346     const int height = getWindowHeight() - 1;
347     EXPECT_PIXEL_8UI(0, 0, blackColorui[0], blackColorui[1], blackColorui[2], blackColorui[3]);
348     EXPECT_PIXEL_8UI(width, 0, blackColorui[0], blackColorui[1], blackColorui[2], blackColorui[3]);
349     EXPECT_PIXEL_8UI(0, height, blackColorui[0], blackColorui[1], blackColorui[2], blackColorui[3]);
350     EXPECT_PIXEL_8UI(width, height, blackColorui[0], blackColorui[1], blackColorui[2],
351                      blackColorui[3]);
352 }
353 
354 // Verifies that we are able to create an incomplete shadow texture.
TEST_P(IncompleteTextureTestES3,ShadowType)355 TEST_P(IncompleteTextureTestES3, ShadowType)
356 {
357     // GLES backend on Adreno has a problem to create a incomplete texture, although it doesn't go
358     // through the routine which creates a incomplete texture in the ANGLE driver.
359     ANGLE_SKIP_TEST_IF(IsAdreno() && IsAndroid() && IsOpenGLES());
360 
361     // http://crbug.com/1168370
362     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsOpenGL());
363 
364     // http://anglebug.com/5594
365     ANGLE_SKIP_TEST_IF(IsD3D11() || IsOSX());
366 
367     constexpr char kVS[] = R"(#version 300 es
368 in highp vec2 position;
369 out highp vec3 texCoord;
370 void main()
371 {
372     gl_Position = vec4(position, 0, 1);
373     texCoord = vec3(((position * 0.5) + 0.5), 0.5);
374 })";
375 
376     constexpr char kFS[] = R"(#version 300 es
377 in highp vec3 texCoord;
378 out highp vec4 color;
379 uniform highp sampler2DShadow tex;
380 void main()
381 {
382     color = vec4(vec3(texture(tex, texCoord)), 1.0f);
383 })";
384 
385     constexpr GLColor clearColor = {10, 40, 20, 30};
386     constexpr GLColor blackColor = {0, 0, 0, 255};
387 
388     setupFramebuffer(GL_RGBA8);
389     glClearBufferfv(GL_COLOR, 0, clearColor.toNormalizedVector().data());
390     ASSERT_GL_NO_ERROR();
391     EXPECT_PIXEL_EQ(0, 0, clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
392 
393     // Since no texture attachment has been specified, it is incomplete by definition
394     ANGLE_GL_PROGRAM(program, kVS, kFS);
395 
396     glUseProgram(program);
397     glUniform1i(glGetUniformLocation(program, "tex"), 1);
398     ASSERT_GL_NO_ERROR();
399 
400     drawQuad(program, "position", 0.5f);
401     ASSERT_GL_NO_ERROR();
402 
403     const int width  = getWindowWidth() - 1;
404     const int height = getWindowHeight() - 1;
405     EXPECT_PIXEL_EQ(0, 0, blackColor[0], blackColor[1], blackColor[2], blackColor[3]);
406     EXPECT_PIXEL_EQ(width, 0, blackColor[0], blackColor[1], blackColor[2], blackColor[3]);
407     EXPECT_PIXEL_EQ(0, height, blackColor[0], blackColor[1], blackColor[2], blackColor[3]);
408     EXPECT_PIXEL_EQ(width, height, blackColor[0], blackColor[1], blackColor[2], blackColor[3]);
409 }
410 
411 ANGLE_INSTANTIATE_TEST_ES2(IncompleteTextureTest);
412 
413 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IncompleteTextureTestES3);
414 ANGLE_INSTANTIATE_TEST_ES3(IncompleteTextureTestES3);
415 
416 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IncompleteTextureTestES31);
417 ANGLE_INSTANTIATE_TEST_ES31(IncompleteTextureTestES31);
418