blob: f3d5c5a2364c523762d792d76ce97066367b0872 [file] [log] [blame]
Jamie Madillfa05f602015-05-07 13:47:11 -04001//
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
Corentin Wallezd3970de2015-05-14 11:07:48 -04007#include "test_utils/ANGLETest.h"
Jamie Madillf67115c2014-04-22 13:14:05 -04008
Jamie Madillfa05f602015-05-07 13:47:11 -04009using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070010
Jamie Madillfa05f602015-05-07 13:47:11 -040011namespace
12{
13
Olli Etuaho4a8329f2016-01-11 17:12:57 +020014class TexCoordDrawTest : public ANGLETest
Jamie Madillf67115c2014-04-22 13:14:05 -040015{
Jamie Madillbc393df2015-01-29 13:46:07 -050016 protected:
Olli Etuaho51f1c0f2016-01-13 16:16:24 +020017 TexCoordDrawTest() : ANGLETest(), mProgram(0), mFramebuffer(0), mFramebufferColorTexture(0)
Jamie Madillf67115c2014-04-22 13:14:05 -040018 {
19 setWindowWidth(128);
20 setWindowHeight(128);
21 setConfigRedBits(8);
22 setConfigGreenBits(8);
23 setConfigBlueBits(8);
24 setConfigAlphaBits(8);
25 }
26
Olli Etuaho4a8329f2016-01-11 17:12:57 +020027 virtual std::string getVertexShaderSource()
Jamie Madillf67115c2014-04-22 13:14:05 -040028 {
Olli Etuaho4a8329f2016-01-11 17:12:57 +020029 return std::string(SHADER_SOURCE
Geoff Langc41e42d2014-04-28 10:58:16 -040030 (
31 precision highp float;
32 attribute vec4 position;
33 varying vec2 texcoord;
34
35 void main()
36 {
Olli Etuaho4a8329f2016-01-11 17:12:57 +020037 gl_Position = vec4(position.xy, 0.0, 1.0);
Geoff Langc41e42d2014-04-28 10:58:16 -040038 texcoord = (position.xy * 0.5) + 0.5;
39 }
Olli Etuaho4a8329f2016-01-11 17:12:57 +020040 )
Geoff Langc41e42d2014-04-28 10:58:16 -040041 );
Olli Etuaho4a8329f2016-01-11 17:12:57 +020042 }
Geoff Langc41e42d2014-04-28 10:58:16 -040043
Olli Etuaho4a8329f2016-01-11 17:12:57 +020044 virtual std::string getFragmentShaderSource() = 0;
45
46 void SetUp() override
47 {
48 ANGLETest::SetUp();
49 const std::string vertexShaderSource = getVertexShaderSource();
50 const std::string fragmentShaderSource = getFragmentShaderSource();
51
52 mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
53 ASSERT_NE(0u, mProgram);
54 ASSERT_GL_NO_ERROR();
Olli Etuaho51f1c0f2016-01-13 16:16:24 +020055
56 setUpFramebuffer();
Olli Etuaho4a8329f2016-01-11 17:12:57 +020057 }
58
59 void TearDown() override
60 {
Olli Etuaho51f1c0f2016-01-13 16:16:24 +020061 glBindFramebuffer(GL_FRAMEBUFFER, 0);
62 glDeleteFramebuffers(1, &mFramebuffer);
63 glDeleteTextures(1, &mFramebufferColorTexture);
Olli Etuaho4a8329f2016-01-11 17:12:57 +020064 glDeleteProgram(mProgram);
65 ANGLETest::TearDown();
66 }
67
Olli Etuaho51f1c0f2016-01-13 16:16:24 +020068 void setUpFramebuffer()
69 {
70 // We use an FBO to work around an issue where the default framebuffer applies SRGB
71 // conversion (particularly known to happen incorrectly on Intel GL drivers). It's not
72 // clear whether this issue can even be fixed on all backends. For example GLES 3.0.4 spec
73 // section 4.4 says that the format of the default framebuffer is entirely up to the window
74 // system, so it might be SRGB, and GLES 3.0 doesn't have a "FRAMEBUFFER_SRGB" to turn off
75 // SRGB conversion like desktop GL does.
76 // TODO(oetuaho): Get rid of this if the underlying issue is fixed.
77 glGenFramebuffers(1, &mFramebuffer);
78 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
79
80 glGenTextures(1, &mFramebufferColorTexture);
81 glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
82 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
83 GL_UNSIGNED_BYTE, nullptr);
84 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
85 mFramebufferColorTexture, 0);
86 ASSERT_GL_NO_ERROR();
87 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
88 glBindTexture(GL_TEXTURE_2D, 0);
89 }
90
Olli Etuaho4a8329f2016-01-11 17:12:57 +020091 // Returns the created texture ID.
92 GLuint create2DTexture()
93 {
94 GLuint texture2D;
95 glGenTextures(1, &texture2D);
96 glBindTexture(GL_TEXTURE_2D, texture2D);
97 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
98 EXPECT_GL_NO_ERROR();
99 return texture2D;
100 }
101
102 GLuint mProgram;
Olli Etuaho51f1c0f2016-01-13 16:16:24 +0200103 GLuint mFramebuffer;
104
105 private:
106 GLuint mFramebufferColorTexture;
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200107};
108
109class Texture2DTest : public TexCoordDrawTest
110{
111 protected:
112 Texture2DTest() : TexCoordDrawTest(), mTexture2D(0), mTexture2DUniformLocation(-1) {}
113
114 std::string getFragmentShaderSource() override
115 {
116 return std::string(SHADER_SOURCE
Geoff Langc41e42d2014-04-28 10:58:16 -0400117 (
118 precision highp float;
119 uniform sampler2D tex;
120 varying vec2 texcoord;
121
122 void main()
123 {
124 gl_FragColor = texture2D(tex, texcoord);
125 }
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200126 )
Geoff Langc41e42d2014-04-28 10:58:16 -0400127 );
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200128 }
Geoff Langc41e42d2014-04-28 10:58:16 -0400129
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200130 void SetUp() override
131 {
132 TexCoordDrawTest::SetUp();
133 mTexture2D = create2DTexture();
Jamie Madilld4cfa572014-07-08 10:00:32 -0400134
Jamie Madill9aca0592014-10-06 16:26:59 -0400135 ASSERT_GL_NO_ERROR();
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200136
137 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex");
138 ASSERT_NE(-1, mTexture2DUniformLocation);
Jamie Madillf67115c2014-04-22 13:14:05 -0400139 }
140
Jamie Madillfa05f602015-05-07 13:47:11 -0400141 void TearDown() override
Jamie Madillf67115c2014-04-22 13:14:05 -0400142 {
Jamie Madilld4cfa572014-07-08 10:00:32 -0400143 glDeleteTextures(1, &mTexture2D);
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200144 TexCoordDrawTest::TearDown();
Jamie Madillf67115c2014-04-22 13:14:05 -0400145 }
146
Jamie Madillbc393df2015-01-29 13:46:07 -0500147 // Tests CopyTexSubImage with floating point textures of various formats.
148 void testFloatCopySubImage(int sourceImageChannels, int destImageChannels)
149 {
Geoff Langbde666a2015-04-07 17:17:08 -0400150 // TODO(jmadill): Figure out why this is broken on Intel D3D11
151 if (isIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
152 {
153 std::cout << "Test skipped on Intel D3D11." << std::endl;
154 return;
155 }
156
Geoff Langfbfa47c2015-03-31 11:26:00 -0400157 if (getClientVersion() < 3)
158 {
159 if (!extensionEnabled("GL_OES_texture_float"))
160 {
161 std::cout << "Test skipped due to missing GL_OES_texture_float." << std::endl;
162 return;
163 }
164
165 if ((sourceImageChannels < 3 || destImageChannels < 3) && !extensionEnabled("GL_EXT_texture_rg"))
166 {
167 std::cout << "Test skipped due to missing GL_EXT_texture_rg." << std::endl;
168 return;
169 }
170 }
171
Jamie Madillbc393df2015-01-29 13:46:07 -0500172 GLfloat sourceImageData[4][16] =
173 {
174 { // R
175 1.0f,
176 0.0f,
177 0.0f,
178 1.0f
179 },
180 { // RG
181 1.0f, 0.0f,
182 0.0f, 1.0f,
183 0.0f, 0.0f,
184 1.0f, 1.0f
185 },
186 { // RGB
187 1.0f, 0.0f, 0.0f,
188 0.0f, 1.0f, 0.0f,
189 0.0f, 0.0f, 1.0f,
190 1.0f, 1.0f, 0.0f
191 },
192 { // RGBA
193 1.0f, 0.0f, 0.0f, 1.0f,
194 0.0f, 1.0f, 0.0f, 1.0f,
195 0.0f, 0.0f, 1.0f, 1.0f,
196 1.0f, 1.0f, 0.0f, 1.0f
197 },
198 };
199
200 GLenum imageFormats[] =
201 {
202 GL_R32F,
203 GL_RG32F,
204 GL_RGB32F,
205 GL_RGBA32F,
206 };
207
208 GLenum sourceUnsizedFormats[] =
209 {
210 GL_RED,
211 GL_RG,
212 GL_RGB,
213 GL_RGBA,
214 };
215
216 GLuint textures[2];
217
218 glGenTextures(2, textures);
219
220 GLfloat *imageData = sourceImageData[sourceImageChannels - 1];
221 GLenum sourceImageFormat = imageFormats[sourceImageChannels - 1];
222 GLenum sourceUnsizedFormat = sourceUnsizedFormats[sourceImageChannels - 1];
223 GLenum destImageFormat = imageFormats[destImageChannels - 1];
224
225 glBindTexture(GL_TEXTURE_2D, textures[0]);
226 glTexStorage2DEXT(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
229 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, sourceUnsizedFormat, GL_FLOAT, imageData);
230
hendrikwb27f79a2015-03-04 11:26:46 -0800231 if (sourceImageChannels < 3 && !extensionEnabled("GL_EXT_texture_rg"))
Jamie Madillbc393df2015-01-29 13:46:07 -0500232 {
233 // This is not supported
234 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
235 }
236 else
237 {
238 ASSERT_GL_NO_ERROR();
239 }
240
241 GLuint fbo;
242 glGenFramebuffers(1, &fbo);
243 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
244 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
245
246 glBindTexture(GL_TEXTURE_2D, textures[1]);
247 glTexStorage2DEXT(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
249 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
250
251 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2);
252 ASSERT_GL_NO_ERROR();
253
254 glBindFramebuffer(GL_FRAMEBUFFER, 0);
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200255 drawQuad(mProgram, "position", 0.5f);
Jamie Madillbc393df2015-01-29 13:46:07 -0500256
257 int testImageChannels = std::min(sourceImageChannels, destImageChannels);
258
259 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
260 if (testImageChannels > 1)
261 {
262 EXPECT_PIXEL_EQ(getWindowHeight() - 1, 0, 0, 255, 0, 255);
263 EXPECT_PIXEL_EQ(getWindowHeight() - 1, getWindowWidth() - 1, 255, 255, 0, 255);
264 if (testImageChannels > 2)
265 {
266 EXPECT_PIXEL_EQ(0, getWindowWidth() - 1, 0, 0, 255, 255);
267 }
268 }
269
270 glDeleteFramebuffers(1, &fbo);
271 glDeleteTextures(2, textures);
272
273 ASSERT_GL_NO_ERROR();
274 }
275
Jamie Madilld4cfa572014-07-08 10:00:32 -0400276 GLuint mTexture2D;
Jamie Madilld4cfa572014-07-08 10:00:32 -0400277 GLint mTexture2DUniformLocation;
Jamie Madillf67115c2014-04-22 13:14:05 -0400278};
279
Olli Etuahoa7416ff2016-01-18 12:22:55 +0200280class Texture2DTestES3 : public Texture2DTest
281{
282 protected:
283 Texture2DTestES3() : Texture2DTest() {}
284
285 std::string getVertexShaderSource() override
286 {
287 return std::string(
288 "#version 300 es\n"
289 "out vec2 texcoord;\n"
290 "in vec4 position;\n"
291 "void main()\n"
292 "{\n"
293 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
294 " texcoord = (position.xy * 0.5) + 0.5;\n"
295 "}\n");
296 }
297
298 std::string getFragmentShaderSource() override
299 {
300 return std::string(
301 "#version 300 es\n"
302 "precision highp float;\n"
303 "uniform highp sampler2D tex;\n"
304 "in vec2 texcoord;\n"
305 "out vec4 fragColor;\n"
306 "void main()\n"
307 "{\n"
308 " fragColor = texture(tex, texcoord);\n"
309 "}\n");
310 }
311};
312
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200313class Texture2DTestWithDrawScale : public Texture2DTest
Jamie Madill2453dbc2015-07-14 11:35:42 -0400314{
315 protected:
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200316 Texture2DTestWithDrawScale() : Texture2DTest(), mDrawScaleUniformLocation(-1) {}
317
318 std::string getVertexShaderSource() override
Jamie Madill2453dbc2015-07-14 11:35:42 -0400319 {
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200320 return std::string(SHADER_SOURCE
321 (
322 precision highp float;
323 attribute vec4 position;
324 varying vec2 texcoord;
325
326 uniform vec2 drawScale;
327
328 void main()
329 {
330 gl_Position = vec4(position.xy * drawScale, 0.0, 1.0);
331 texcoord = (position.xy * 0.5) + 0.5;
332 }
333 )
334 );
Jamie Madill2453dbc2015-07-14 11:35:42 -0400335 }
336
337 void SetUp() override
338 {
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200339 Texture2DTest::SetUp();
340 mDrawScaleUniformLocation = glGetUniformLocation(mProgram, "drawScale");
341 ASSERT_NE(-1, mDrawScaleUniformLocation);
Jamie Madill2453dbc2015-07-14 11:35:42 -0400342
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200343 glUseProgram(mProgram);
344 glUniform2f(mDrawScaleUniformLocation, 1.0f, 1.0f);
345 glUseProgram(0);
346 ASSERT_GL_NO_ERROR();
347 }
348
349 GLint mDrawScaleUniformLocation;
350};
351
Olli Etuaho4644a202016-01-12 15:12:53 +0200352class Sampler2DAsFunctionParameterTest : public Texture2DTest
353{
354 protected:
355 Sampler2DAsFunctionParameterTest() : Texture2DTest() {}
356
357 std::string getFragmentShaderSource() override
358 {
359 return std::string(SHADER_SOURCE
360 (
361 precision highp float;
362 uniform sampler2D tex;
363 varying vec2 texcoord;
364
365 vec4 computeFragColor(sampler2D aTex)
366 {
367 return texture2D(aTex, texcoord);
368 }
369
370 void main()
371 {
372 gl_FragColor = computeFragColor(tex);
373 }
374 )
375 );
376 }
377};
378
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200379class TextureCubeTest : public TexCoordDrawTest
380{
381 protected:
382 TextureCubeTest()
383 : TexCoordDrawTest(),
384 mTexture2D(0),
385 mTextureCube(0),
386 mTexture2DUniformLocation(-1),
387 mTextureCubeUniformLocation(-1)
388 {
389 }
390
391 std::string getFragmentShaderSource() override
392 {
393 return std::string(SHADER_SOURCE
394 (
395 precision highp float;
396 uniform sampler2D tex2D;
397 uniform samplerCube texCube;
398 varying vec2 texcoord;
399
400 void main()
401 {
402 gl_FragColor = texture2D(tex2D, texcoord);
403 gl_FragColor += textureCube(texCube, vec3(texcoord, 0));
404 }
405 )
406 );
407 }
408
409 void SetUp() override
410 {
411 TexCoordDrawTest::SetUp();
412
413 glGenTextures(1, &mTextureCube);
414 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
415 glTexStorage2DEXT(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
416 EXPECT_GL_NO_ERROR();
417
418 mTexture2D = create2DTexture();
419
420 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
421 ASSERT_NE(-1, mTexture2DUniformLocation);
422 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
423 ASSERT_NE(-1, mTextureCubeUniformLocation);
424 }
425
426 void TearDown() override
427 {
428 glDeleteTextures(1, &mTextureCube);
429 TexCoordDrawTest::TearDown();
430 }
431
432 GLuint mTexture2D;
433 GLuint mTextureCube;
434 GLint mTexture2DUniformLocation;
435 GLint mTextureCubeUniformLocation;
436};
437
Olli Etuaho2173db3d2016-01-12 13:55:14 +0200438class SamplerArrayTest : public TexCoordDrawTest
439{
440 protected:
441 SamplerArrayTest()
442 : TexCoordDrawTest(),
443 mTexture2DA(0),
444 mTexture2DB(0),
445 mTexture0UniformLocation(-1),
446 mTexture1UniformLocation(-1)
447 {
448 }
449
450 std::string getFragmentShaderSource() override
451 {
452 return std::string(SHADER_SOURCE
453 (
454 precision mediump float;
455 uniform highp sampler2D tex2DArray[2];
456 varying vec2 texcoord;
457 void main()
458 {
459 gl_FragColor = texture2D(tex2DArray[0], texcoord);
460 gl_FragColor += texture2D(tex2DArray[1], texcoord);
461 }
462 )
463 );
464 }
465
466 void SetUp() override
467 {
468 TexCoordDrawTest::SetUp();
469
470 mTexture0UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[0]");
471 ASSERT_NE(-1, mTexture0UniformLocation);
472 mTexture1UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[1]");
473 ASSERT_NE(-1, mTexture1UniformLocation);
474
475 mTexture2DA = create2DTexture();
476 mTexture2DB = create2DTexture();
477 ASSERT_GL_NO_ERROR();
478 }
479
480 void TearDown() override
481 {
482 glDeleteTextures(1, &mTexture2DA);
483 glDeleteTextures(1, &mTexture2DB);
484 TexCoordDrawTest::TearDown();
485 }
486
487 void testSamplerArrayDraw()
488 {
489 GLubyte texData[4];
490 texData[0] = 0;
491 texData[1] = 60;
492 texData[2] = 0;
493 texData[3] = 255;
494
495 glActiveTexture(GL_TEXTURE0);
496 glBindTexture(GL_TEXTURE_2D, mTexture2DA);
497 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
498
499 texData[1] = 120;
500 glActiveTexture(GL_TEXTURE1);
501 glBindTexture(GL_TEXTURE_2D, mTexture2DB);
502 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
503 EXPECT_GL_ERROR(GL_NO_ERROR);
504
505 glUseProgram(mProgram);
506 glUniform1i(mTexture0UniformLocation, 0);
507 glUniform1i(mTexture1UniformLocation, 1);
508 drawQuad(mProgram, "position", 0.5f);
509 EXPECT_GL_NO_ERROR();
510
511 EXPECT_PIXEL_NEAR(0, 0, 0, 180, 0, 255, 2);
512 }
513
514 GLuint mTexture2DA;
515 GLuint mTexture2DB;
516 GLint mTexture0UniformLocation;
517 GLint mTexture1UniformLocation;
518};
519
520
521class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
522{
523 protected:
524 SamplerArrayAsFunctionParameterTest() : SamplerArrayTest() {}
525
526 std::string getFragmentShaderSource() override
527 {
528 return std::string(SHADER_SOURCE
529 (
530 precision mediump float;
531 uniform highp sampler2D tex2DArray[2];
532 varying vec2 texcoord;
533
534 vec4 computeFragColor(highp sampler2D aTex2DArray[2])
535 {
536 return texture2D(aTex2DArray[0], texcoord) + texture2D(aTex2DArray[1], texcoord);
537 }
538
539 void main()
540 {
541 gl_FragColor = computeFragColor(tex2DArray);
542 }
543 )
544 );
545 }
546};
547
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200548class Texture2DArrayTestES3 : public TexCoordDrawTest
549{
550 protected:
551 Texture2DArrayTestES3() : TexCoordDrawTest(), m2DArrayTexture(0), mTextureArrayLocation(-1) {}
552
553 std::string getVertexShaderSource() override
554 {
555 return std::string(
Jamie Madill2453dbc2015-07-14 11:35:42 -0400556 "#version 300 es\n"
557 "out vec2 texcoord;\n"
558 "in vec4 position;\n"
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200559 "void main()\n"
560 "{\n"
561 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
562 " texcoord = (position.xy * 0.5) + 0.5;\n"
563 "}\n");
564 }
Jamie Madill2453dbc2015-07-14 11:35:42 -0400565
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200566 std::string getFragmentShaderSource() override
567 {
568 return std::string(
Jamie Madill2453dbc2015-07-14 11:35:42 -0400569 "#version 300 es\n"
570 "precision highp float;\n"
Olli Etuaho183d7e22015-11-20 15:59:09 +0200571 "uniform highp sampler2DArray tex2DArray;\n"
Jamie Madill2453dbc2015-07-14 11:35:42 -0400572 "in vec2 texcoord;\n"
573 "out vec4 fragColor;\n"
574 "void main()\n"
575 "{\n"
576 " fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, 0.0));\n"
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200577 "}\n");
578 }
Jamie Madill2453dbc2015-07-14 11:35:42 -0400579
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200580 void SetUp() override
581 {
582 TexCoordDrawTest::SetUp();
Jamie Madill2453dbc2015-07-14 11:35:42 -0400583
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200584 mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
Jamie Madill2453dbc2015-07-14 11:35:42 -0400585 ASSERT_NE(-1, mTextureArrayLocation);
586
587 glGenTextures(1, &m2DArrayTexture);
588 ASSERT_GL_NO_ERROR();
589 }
590
591 void TearDown() override
592 {
593 glDeleteTextures(1, &m2DArrayTexture);
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200594 TexCoordDrawTest::TearDown();
Jamie Madill2453dbc2015-07-14 11:35:42 -0400595 }
596
597 GLuint m2DArrayTexture;
Jamie Madill2453dbc2015-07-14 11:35:42 -0400598 GLint mTextureArrayLocation;
599};
600
Olli Etuaho1a679902016-01-14 12:21:47 +0200601class ShadowSamplerPlusSampler3DTestES3 : public TexCoordDrawTest
602{
603 protected:
604 ShadowSamplerPlusSampler3DTestES3()
605 : TexCoordDrawTest(),
606 mTextureShadow(0),
607 mTexture3D(0),
608 mTextureShadowUniformLocation(-1),
609 mTexture3DUniformLocation(-1),
610 mDepthRefUniformLocation(-1)
611 {
612 }
613
614 std::string getVertexShaderSource() override
615 {
616 return std::string(
617 "#version 300 es\n"
618 "out vec2 texcoord;\n"
619 "in vec4 position;\n"
620 "void main()\n"
621 "{\n"
622 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
623 " texcoord = (position.xy * 0.5) + 0.5;\n"
624 "}\n");
625 }
626
627 std::string getFragmentShaderSource() override
628 {
629 return std::string(
630 "#version 300 es\n"
631 "precision highp float;\n"
632 "uniform highp sampler2DShadow tex2DShadow;\n"
633 "uniform highp sampler3D tex3D;\n"
634 "in vec2 texcoord;\n"
635 "uniform float depthRef;\n"
636 "out vec4 fragColor;\n"
637 "void main()\n"
638 "{\n"
639 " fragColor = vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.5);\n"
640 " fragColor += texture(tex3D, vec3(texcoord, 0.0));\n"
641 "}\n");
642 }
643
644 void SetUp() override
645 {
646 TexCoordDrawTest::SetUp();
647
648 glGenTextures(1, &mTexture3D);
649
650 glGenTextures(1, &mTextureShadow);
651 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
652 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
653
654 mTextureShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
655 ASSERT_NE(-1, mTextureShadowUniformLocation);
656 mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
657 ASSERT_NE(-1, mTexture3DUniformLocation);
658 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
659 ASSERT_NE(-1, mDepthRefUniformLocation);
660 }
661
662 void TearDown() override
663 {
664 glDeleteTextures(1, &mTextureShadow);
665 glDeleteTextures(1, &mTexture3D);
666 TexCoordDrawTest::TearDown();
667 }
668
669 GLuint mTextureShadow;
670 GLuint mTexture3D;
671 GLint mTextureShadowUniformLocation;
672 GLint mTexture3DUniformLocation;
673 GLint mDepthRefUniformLocation;
674};
675
Olli Etuahoc8c99a02016-01-14 16:47:22 +0200676class SamplerTypeMixTestES3 : public TexCoordDrawTest
677{
678 protected:
679 SamplerTypeMixTestES3()
680 : TexCoordDrawTest(),
681 mTexture2D(0),
682 mTextureCube(0),
683 mTexture2DShadow(0),
684 mTextureCubeShadow(0),
685 mTexture2DUniformLocation(-1),
686 mTextureCubeUniformLocation(-1),
687 mTexture2DShadowUniformLocation(-1),
688 mTextureCubeShadowUniformLocation(-1),
689 mDepthRefUniformLocation(-1)
690 {
691 }
692
693 std::string getVertexShaderSource() override
694 {
695 return std::string(
696 "#version 300 es\n"
697 "out vec2 texcoord;\n"
698 "in vec4 position;\n"
699 "void main()\n"
700 "{\n"
701 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
702 " texcoord = (position.xy * 0.5) + 0.5;\n"
703 "}\n");
704 }
705
706 std::string getFragmentShaderSource() override
707 {
708 return std::string(
709 "#version 300 es\n"
710 "precision highp float;\n"
711 "uniform highp sampler2D tex2D;\n"
712 "uniform highp samplerCube texCube;\n"
713 "uniform highp sampler2DShadow tex2DShadow;\n"
714 "uniform highp samplerCubeShadow texCubeShadow;\n"
715 "in vec2 texcoord;\n"
716 "uniform float depthRef;\n"
717 "out vec4 fragColor;\n"
718 "void main()\n"
719 "{\n"
720 " fragColor = texture(tex2D, texcoord);\n"
721 " fragColor += texture(texCube, vec3(1.0, 0.0, 0.0));\n"
722 " fragColor += vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.25);\n"
723 " fragColor += vec4(texture(texCubeShadow, vec4(1.0, 0.0, 0.0, depthRef)) * "
724 "0.125);\n"
725 "}\n");
726 }
727
728 void SetUp() override
729 {
730 TexCoordDrawTest::SetUp();
731
732 glGenTextures(1, &mTexture2D);
733 glGenTextures(1, &mTextureCube);
734
735 glGenTextures(1, &mTexture2DShadow);
736 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
737 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
738
739 glGenTextures(1, &mTextureCubeShadow);
740 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
741 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
742
743 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
744 ASSERT_NE(-1, mTexture2DUniformLocation);
745 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
746 ASSERT_NE(-1, mTextureCubeUniformLocation);
747 mTexture2DShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
748 ASSERT_NE(-1, mTexture2DShadowUniformLocation);
749 mTextureCubeShadowUniformLocation = glGetUniformLocation(mProgram, "texCubeShadow");
750 ASSERT_NE(-1, mTextureCubeShadowUniformLocation);
751 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
752 ASSERT_NE(-1, mDepthRefUniformLocation);
753
754 ASSERT_GL_NO_ERROR();
755 }
756
757 void TearDown() override
758 {
759 glDeleteTextures(1, &mTexture2D);
760 glDeleteTextures(1, &mTextureCube);
761 glDeleteTextures(1, &mTexture2DShadow);
762 glDeleteTextures(1, &mTextureCubeShadow);
763 TexCoordDrawTest::TearDown();
764 }
765
766 GLuint mTexture2D;
767 GLuint mTextureCube;
768 GLuint mTexture2DShadow;
769 GLuint mTextureCubeShadow;
770 GLint mTexture2DUniformLocation;
771 GLint mTextureCubeUniformLocation;
772 GLint mTexture2DShadowUniformLocation;
773 GLint mTextureCubeShadowUniformLocation;
774 GLint mDepthRefUniformLocation;
775};
776
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200777TEST_P(Texture2DTest, NegativeAPISubImage)
Jamie Madillf67115c2014-04-22 13:14:05 -0400778{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400779 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Jamie Madillf67115c2014-04-22 13:14:05 -0400780 EXPECT_GL_ERROR(GL_NO_ERROR);
781
782 const GLubyte *pixels[20] = { 0 };
783 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
784 EXPECT_GL_ERROR(GL_INVALID_VALUE);
785}
Geoff Langc41e42d2014-04-28 10:58:16 -0400786
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200787TEST_P(Texture2DTest, ZeroSizedUploads)
Geoff Langc41e42d2014-04-28 10:58:16 -0400788{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400789 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Geoff Langc41e42d2014-04-28 10:58:16 -0400790 EXPECT_GL_ERROR(GL_NO_ERROR);
791
792 // Use the texture first to make sure it's in video memory
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200793 glUseProgram(mProgram);
Jamie Madilld4cfa572014-07-08 10:00:32 -0400794 glUniform1i(mTexture2DUniformLocation, 0);
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200795 drawQuad(mProgram, "position", 0.5f);
Geoff Langc41e42d2014-04-28 10:58:16 -0400796
797 const GLubyte *pixel[4] = { 0 };
798
799 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
800 EXPECT_GL_NO_ERROR();
801
802 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
803 EXPECT_GL_NO_ERROR();
804
805 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
806 EXPECT_GL_NO_ERROR();
807}
Jamie Madilld4cfa572014-07-08 10:00:32 -0400808
809// Test drawing with two texture types, to trigger an ANGLE bug in validation
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200810TEST_P(TextureCubeTest, CubeMapBug)
Jamie Madilld4cfa572014-07-08 10:00:32 -0400811{
812 glActiveTexture(GL_TEXTURE0);
813 glBindTexture(GL_TEXTURE_2D, mTexture2D);
814 glActiveTexture(GL_TEXTURE1);
815 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
816 EXPECT_GL_ERROR(GL_NO_ERROR);
817
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200818 glUseProgram(mProgram);
819 glUniform1i(mTexture2DUniformLocation, 0);
820 glUniform1i(mTextureCubeUniformLocation, 1);
821 drawQuad(mProgram, "position", 0.5f);
Jamie Madilld4cfa572014-07-08 10:00:32 -0400822 EXPECT_GL_NO_ERROR();
823}
Jamie Madill9aca0592014-10-06 16:26:59 -0400824
Olli Etuaho53a2da12016-01-11 15:43:32 +0200825// Test drawing with two texture types accessed from the same shader and check that the result of
826// drawing is correct.
827TEST_P(TextureCubeTest, CubeMapDraw)
828{
829 GLubyte texData[4];
830 texData[0] = 0;
831 texData[1] = 60;
832 texData[2] = 0;
833 texData[3] = 255;
834
835 glActiveTexture(GL_TEXTURE0);
836 glBindTexture(GL_TEXTURE_2D, mTexture2D);
837 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
838
839 glActiveTexture(GL_TEXTURE1);
840 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
841 texData[1] = 120;
842 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
843 texData);
844 EXPECT_GL_ERROR(GL_NO_ERROR);
845
846 glUseProgram(mProgram);
847 glUniform1i(mTexture2DUniformLocation, 0);
848 glUniform1i(mTextureCubeUniformLocation, 1);
849 drawQuad(mProgram, "position", 0.5f);
850 EXPECT_GL_NO_ERROR();
851
852 int px = getWindowWidth() - 1;
853 int py = 0;
854 EXPECT_PIXEL_NEAR(px, py, 0, 180, 0, 255, 2);
855}
856
Olli Etuaho4644a202016-01-12 15:12:53 +0200857TEST_P(Sampler2DAsFunctionParameterTest, Sampler2DAsFunctionParameter)
858{
859 glActiveTexture(GL_TEXTURE0);
860 glBindTexture(GL_TEXTURE_2D, mTexture2D);
861 GLubyte texData[4];
862 texData[0] = 0;
863 texData[1] = 128;
864 texData[2] = 0;
865 texData[3] = 255;
866 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
867 glUseProgram(mProgram);
868 glUniform1i(mTexture2DUniformLocation, 0);
869 drawQuad(mProgram, "position", 0.5f);
870 EXPECT_GL_NO_ERROR();
871
872 EXPECT_PIXEL_NEAR(0, 0, 0, 128, 0, 255, 2);
873}
874
Olli Etuaho2173db3d2016-01-12 13:55:14 +0200875// Test drawing with two textures passed to the shader in a sampler array.
876TEST_P(SamplerArrayTest, SamplerArrayDraw)
877{
878 testSamplerArrayDraw();
879}
880
881// Test drawing with two textures passed to the shader in a sampler array which is passed to a
882// user-defined function in the shader.
883TEST_P(SamplerArrayAsFunctionParameterTest, SamplerArrayAsFunctionParameter)
884{
885 testSamplerArrayDraw();
886}
887
Jamie Madill9aca0592014-10-06 16:26:59 -0400888// Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200889TEST_P(Texture2DTestWithDrawScale, MipmapsTwice)
Jamie Madill9aca0592014-10-06 16:26:59 -0400890{
891 int px = getWindowWidth() / 2;
892 int py = getWindowHeight() / 2;
893
894 glActiveTexture(GL_TEXTURE0);
895 glBindTexture(GL_TEXTURE_2D, mTexture2D);
896
897 // Fill with red
898 std::vector<GLubyte> pixels(4 * 16 * 16);
899 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
900 {
901 pixels[pixelId * 4 + 0] = 255;
902 pixels[pixelId * 4 + 1] = 0;
903 pixels[pixelId * 4 + 2] = 0;
904 pixels[pixelId * 4 + 3] = 255;
905 }
906
907 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
908 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
909 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
910 glGenerateMipmap(GL_TEXTURE_2D);
911
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200912 glUseProgram(mProgram);
Jamie Madill9aca0592014-10-06 16:26:59 -0400913 glUniform1i(mTexture2DUniformLocation, 0);
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200914 glUniform2f(mDrawScaleUniformLocation, 0.0625f, 0.0625f);
915 drawQuad(mProgram, "position", 0.5f);
Jamie Madill9aca0592014-10-06 16:26:59 -0400916 EXPECT_GL_NO_ERROR();
917 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
918
919 // Fill with blue
920 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
921 {
922 pixels[pixelId * 4 + 0] = 0;
923 pixels[pixelId * 4 + 1] = 0;
924 pixels[pixelId * 4 + 2] = 255;
925 pixels[pixelId * 4 + 3] = 255;
926 }
927
928 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
929 glGenerateMipmap(GL_TEXTURE_2D);
930
931 // Fill with green
932 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
933 {
934 pixels[pixelId * 4 + 0] = 0;
935 pixels[pixelId * 4 + 1] = 255;
936 pixels[pixelId * 4 + 2] = 0;
937 pixels[pixelId * 4 + 3] = 255;
938 }
939
940 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
941 glGenerateMipmap(GL_TEXTURE_2D);
942
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200943 drawQuad(mProgram, "position", 0.5f);
Jamie Madill9aca0592014-10-06 16:26:59 -0400944
945 EXPECT_GL_NO_ERROR();
946 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
947}
Jamie Madillf8fccb32014-11-12 15:05:26 -0500948
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500949// Test creating a FBO with a cube map render target, to test an ANGLE bug
950// https://code.google.com/p/angleproject/issues/detail?id=849
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200951TEST_P(TextureCubeTest, CubeMapFBO)
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500952{
953 GLuint fbo;
954 glGenFramebuffers(1, &fbo);
955 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
956
957 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
958 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mTextureCube, 0);
959
Corentin Wallez322653b2015-06-17 18:33:56 +0200960 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500961
962 glDeleteFramebuffers(1, &fbo);
963
964 EXPECT_GL_NO_ERROR();
965}
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000966
967// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a default color.
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200968TEST_P(Texture2DTest, TexStorage)
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000969{
970 int width = getWindowWidth();
971 int height = getWindowHeight();
972
973 GLuint tex2D;
974 glGenTextures(1, &tex2D);
975 glActiveTexture(GL_TEXTURE0);
976 glBindTexture(GL_TEXTURE_2D, tex2D);
977
978 // Fill with red
979 std::vector<GLubyte> pixels(3 * 16 * 16);
980 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
981 {
982 pixels[pixelId * 3 + 0] = 255;
983 pixels[pixelId * 3 + 1] = 0;
984 pixels[pixelId * 3 + 2] = 0;
985 }
986
987 // ANGLE internally uses RGBA as the DirectX format for RGB images
988 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
989 // The data is kept in a CPU-side image and the image is marked as dirty.
990 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
991
992 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
993 // glTexSubImage2D should take into account that the image is dirty.
994 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
995 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
996 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
997
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200998 glUseProgram(mProgram);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000999 glUniform1i(mTexture2DUniformLocation, 0);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001000 drawQuad(mProgram, "position", 0.5f);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001001 glDeleteTextures(1, &tex2D);
1002 EXPECT_GL_NO_ERROR();
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001003 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
Geoff Langfbfa47c2015-03-31 11:26:00 -04001004
1005 // Validate that the region of the texture without data has an alpha of 1.0
1006 GLubyte pixel[4];
1007 glReadPixels(3 * width / 4, 3 * height / 4, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
1008 EXPECT_EQ(pixel[3], 255);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001009}
1010
1011// Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has initialized the image with a default color.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001012TEST_P(Texture2DTest, TexStorageWithPBO)
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001013{
1014 if (extensionEnabled("NV_pixel_buffer_object"))
1015 {
1016 int width = getWindowWidth();
1017 int height = getWindowHeight();
1018
1019 GLuint tex2D;
1020 glGenTextures(1, &tex2D);
1021 glActiveTexture(GL_TEXTURE0);
1022 glBindTexture(GL_TEXTURE_2D, tex2D);
1023
1024 // Fill with red
1025 std::vector<GLubyte> pixels(3 * 16 * 16);
1026 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
1027 {
1028 pixels[pixelId * 3 + 0] = 255;
1029 pixels[pixelId * 3 + 1] = 0;
1030 pixels[pixelId * 3 + 2] = 0;
1031 }
1032
1033 // Read 16x16 region from red backbuffer to PBO
1034 GLuint pbo;
1035 glGenBuffers(1, &pbo);
1036 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
1037 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
1038
1039 // ANGLE internally uses RGBA as the DirectX format for RGB images
1040 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
1041 // The data is kept in a CPU-side image and the image is marked as dirty.
1042 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
1043
1044 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
1045 // glTexSubImage2D should take into account that the image is dirty.
1046 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, NULL);
1047 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1048 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1049
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001050 glUseProgram(mProgram);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001051 glUniform1i(mTexture2DUniformLocation, 0);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001052 drawQuad(mProgram, "position", 0.5f);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001053 glDeleteTextures(1, &tex2D);
Olli Etuaho19d48db2016-01-13 14:43:21 +02001054 glDeleteBuffers(1, &pbo);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001055 EXPECT_GL_NO_ERROR();
1056 EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
1057 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
1058 }
1059}
Jamie Madillbc393df2015-01-29 13:46:07 -05001060
1061// See description on testFloatCopySubImage
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001062TEST_P(Texture2DTest, CopySubImageFloat_R_R)
Jamie Madillbc393df2015-01-29 13:46:07 -05001063{
1064 testFloatCopySubImage(1, 1);
1065}
1066
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001067TEST_P(Texture2DTest, CopySubImageFloat_RG_R)
Jamie Madillbc393df2015-01-29 13:46:07 -05001068{
1069 testFloatCopySubImage(2, 1);
1070}
1071
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001072TEST_P(Texture2DTest, CopySubImageFloat_RG_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -05001073{
1074 testFloatCopySubImage(2, 2);
1075}
1076
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001077TEST_P(Texture2DTest, CopySubImageFloat_RGB_R)
Jamie Madillbc393df2015-01-29 13:46:07 -05001078{
1079 testFloatCopySubImage(3, 1);
1080}
1081
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001082TEST_P(Texture2DTest, CopySubImageFloat_RGB_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -05001083{
1084 testFloatCopySubImage(3, 2);
1085}
1086
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001087TEST_P(Texture2DTest, CopySubImageFloat_RGB_RGB)
Jamie Madillbc393df2015-01-29 13:46:07 -05001088{
1089 testFloatCopySubImage(3, 3);
1090}
1091
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001092TEST_P(Texture2DTest, CopySubImageFloat_RGBA_R)
Jamie Madillbc393df2015-01-29 13:46:07 -05001093{
1094 testFloatCopySubImage(4, 1);
1095}
1096
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001097TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -05001098{
1099 testFloatCopySubImage(4, 2);
1100}
1101
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001102TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGB)
Jamie Madillbc393df2015-01-29 13:46:07 -05001103{
1104 testFloatCopySubImage(4, 3);
1105}
1106
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001107TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGBA)
Jamie Madillbc393df2015-01-29 13:46:07 -05001108{
1109 testFloatCopySubImage(4, 4);
1110}
Austin Kinross07285142015-03-26 11:36:16 -07001111
1112// Port of https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html
1113// Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly handles GL_ALPHA
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001114TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE)
Austin Kinross07285142015-03-26 11:36:16 -07001115{
1116 const int npotTexSize = 5;
1117 const int potTexSize = 4; // Should be less than npotTexSize
1118 GLuint tex2D;
1119
1120 if (extensionEnabled("GL_OES_texture_npot"))
1121 {
1122 // This test isn't applicable if texture_npot is enabled
1123 return;
1124 }
1125
1126 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1127
Austin Kinross5faa15b2016-01-11 13:32:48 -08001128 // Default unpack alignment is 4. The values of 'pixels' below needs it to be 1.
1129 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1130
Austin Kinross07285142015-03-26 11:36:16 -07001131 glActiveTexture(GL_TEXTURE0);
1132 glGenTextures(1, &tex2D);
1133 glBindTexture(GL_TEXTURE_2D, tex2D);
1134
1135 std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize);
1136 for (size_t pixelId = 0; pixelId < npotTexSize * npotTexSize; ++pixelId)
1137 {
1138 pixels[pixelId] = 64;
1139 }
1140
1141 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1142 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1143
1144 // Check that an NPOT texture not on level 0 generates INVALID_VALUE
1145 glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
1146 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1147
1148 // Check that an NPOT texture on level 0 succeeds
1149 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
1150 EXPECT_GL_NO_ERROR();
1151
1152 // Check that generateMipmap fails on NPOT
1153 glGenerateMipmap(GL_TEXTURE_2D);
1154 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1155
1156 // Check that nothing is drawn if filtering is not correct for NPOT
1157 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1158 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1159 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1161 glClear(GL_COLOR_BUFFER_BIT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001162 drawQuad(mProgram, "position", 1.0f);
Austin Kinross07285142015-03-26 11:36:16 -07001163 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
1164
1165 // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
1166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
1169 glClear(GL_COLOR_BUFFER_BIT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001170 drawQuad(mProgram, "position", 1.0f);
Austin Kinross07285142015-03-26 11:36:16 -07001171 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
1172
1173 // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw
1174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1175 glClear(GL_COLOR_BUFFER_BIT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001176 drawQuad(mProgram, "position", 1.0f);
Austin Kinross07285142015-03-26 11:36:16 -07001177 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
1178
1179 // Check that glTexImage2D for POT texture succeeds
1180 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
1181 EXPECT_GL_NO_ERROR();
1182
1183 // Check that generateMipmap for an POT texture succeeds
1184 glGenerateMipmap(GL_TEXTURE_2D);
1185 EXPECT_GL_NO_ERROR();
1186
1187 // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw
1188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1190 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1192 glClear(GL_COLOR_BUFFER_BIT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001193 drawQuad(mProgram, "position", 1.0f);
Austin Kinross07285142015-03-26 11:36:16 -07001194 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
1195 EXPECT_GL_NO_ERROR();
1196}
Jamie Madillfa05f602015-05-07 13:47:11 -04001197
Austin Kinross08528e12015-10-07 16:24:40 -07001198// Test to ensure that glTexSubImage2D always accepts data for non-power-of-two subregions.
1199// ANGLE previously rejected this if GL_OES_texture_npot wasn't active, which is incorrect.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001200TEST_P(Texture2DTest, NPOTSubImageParameters)
Austin Kinross08528e12015-10-07 16:24:40 -07001201{
1202 glActiveTexture(GL_TEXTURE0);
1203 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1204
1205 // Create an 8x8 (i.e. power-of-two) texture.
1206 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
1208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1209 glGenerateMipmap(GL_TEXTURE_2D);
1210
1211 // Supply a 3x3 (i.e. non-power-of-two) subimage to the texture.
1212 // This should always work, even if GL_OES_texture_npot isn't active.
1213 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1214
1215 EXPECT_GL_NO_ERROR();
1216}
1217
Olli Etuahoa7416ff2016-01-18 12:22:55 +02001218// Test to check that texture completeness is determined correctly when the texture base level is
1219// greater than 0, and also that level 0 is not sampled when base level is greater than 0.
1220TEST_P(Texture2DTestES3, DrawWithBaseLevel1)
1221{
1222 glActiveTexture(GL_TEXTURE0);
1223 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1224 GLubyte texDataRed[4u * 4u * 4u];
1225 for (size_t i = 0u; i < 4u * 4u; ++i)
1226 {
1227 texDataRed[i * 4u] = 255u;
1228 texDataRed[i * 4u + 1u] = 0u;
1229 texDataRed[i * 4u + 2u] = 0u;
1230 texDataRed[i * 4u + 3u] = 255u;
1231 }
1232 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed);
1233 GLubyte texDataGreen[2u * 2u * 4u];
1234 for (size_t i = 0u; i < 2u * 2u; ++i)
1235 {
1236 texDataGreen[i * 4u] = 0u;
1237 texDataGreen[i * 4u + 1u] = 255u;
1238 texDataGreen[i * 4u + 2u] = 0u;
1239 texDataGreen[i * 4u + 3u] = 255u;
1240 }
1241 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataGreen);
1242 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataGreen);
1243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1246
1247 EXPECT_GL_NO_ERROR();
1248
1249 drawQuad(mProgram, "position", 0.5f);
1250
1251 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
1252}
1253
Jamie Madill2453dbc2015-07-14 11:35:42 -04001254// In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG RBA->RGBA8, with 1.0
1255// in the alpha channel. This test covers a bug where redefining array textures with these formats does not work as
1256// expected.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001257TEST_P(Texture2DArrayTestES3, RedefineInittableArray)
Jamie Madill2453dbc2015-07-14 11:35:42 -04001258{
1259 std::vector<GLubyte> pixelData;
1260 for (size_t count = 0; count < 5000; count++)
1261 {
1262 pixelData.push_back(0u);
1263 pixelData.push_back(255u);
1264 pixelData.push_back(0u);
1265 }
1266
1267 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001268 glUseProgram(mProgram);
Jamie Madill2453dbc2015-07-14 11:35:42 -04001269 glUniform1i(mTextureArrayLocation, 0);
1270
1271 // The first draw worked correctly.
1272 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixelData[0]);
1273
1274 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1275 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1276 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
1277 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001278 drawQuad(mProgram, "position", 1.0f);
Jamie Madill2453dbc2015-07-14 11:35:42 -04001279 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
1280
1281 // The dimension of the respecification must match the original exactly to trigger the bug.
1282 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixelData[0]);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001283 drawQuad(mProgram, "position", 1.0f);
Jamie Madill2453dbc2015-07-14 11:35:42 -04001284 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
1285
1286 ASSERT_GL_NO_ERROR();
1287}
1288
Olli Etuaho1a679902016-01-14 12:21:47 +02001289// Test shadow sampler and regular non-shadow sampler coexisting in the same shader.
1290// This test is needed especially to confirm that sampler registers get assigned correctly on
1291// the HLSL backend even when there's a mix of different HLSL sampler and texture types.
1292TEST_P(ShadowSamplerPlusSampler3DTestES3, ShadowSamplerPlusSampler3DDraw)
1293{
1294 glActiveTexture(GL_TEXTURE0);
1295 glBindTexture(GL_TEXTURE_3D, mTexture3D);
1296 GLubyte texData[4];
1297 texData[0] = 0;
1298 texData[1] = 60;
1299 texData[2] = 0;
1300 texData[3] = 255;
1301 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1302
1303 glActiveTexture(GL_TEXTURE1);
1304 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
1305 GLfloat depthTexData[1];
1306 depthTexData[0] = 0.5f;
1307 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
1308 depthTexData);
1309
1310 glUseProgram(mProgram);
1311 glUniform1f(mDepthRefUniformLocation, 0.3f);
1312 glUniform1i(mTexture3DUniformLocation, 0);
1313 glUniform1i(mTextureShadowUniformLocation, 1);
1314
1315 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
1316 drawQuad(mProgram, "position", 0.5f);
1317 EXPECT_GL_NO_ERROR();
1318 // The shader writes 0.5 * <comparison result (1.0)> + <texture color>
1319 EXPECT_PIXEL_NEAR(0, 0, 128, 188, 128, 255, 2);
1320
1321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);
1322 drawQuad(mProgram, "position", 0.5f);
1323 EXPECT_GL_NO_ERROR();
1324 // The shader writes 0.5 * <comparison result (0.0)> + <texture color>
1325 EXPECT_PIXEL_NEAR(0, 0, 0, 60, 0, 255, 2);
1326}
1327
Olli Etuahoc8c99a02016-01-14 16:47:22 +02001328// Test multiple different sampler types in the same shader.
1329// This test makes sure that even if sampler / texture registers get grouped together based on type
1330// or otherwise get shuffled around in the HLSL backend of the shader translator, the D3D renderer
1331// still has the right register index information for each ESSL sampler.
1332// The tested ESSL samplers have the following types in D3D11 HLSL:
1333// sampler2D: Texture2D + SamplerState
1334// samplerCube: TextureCube + SamplerState
1335// sampler2DShadow: Texture2D + SamplerComparisonState
1336// samplerCubeShadow: TextureCube + SamplerComparisonState
1337TEST_P(SamplerTypeMixTestES3, SamplerTypeMixDraw)
1338{
1339 glActiveTexture(GL_TEXTURE0);
1340 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1341 GLubyte texData[4];
1342 texData[0] = 0;
1343 texData[1] = 0;
1344 texData[2] = 120;
1345 texData[3] = 255;
1346 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1347
1348 glActiveTexture(GL_TEXTURE1);
1349 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
1350 texData[0] = 0;
1351 texData[1] = 90;
1352 texData[2] = 0;
1353 texData[3] = 255;
1354 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
1355 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
1356 texData);
1357
1358 glActiveTexture(GL_TEXTURE2);
1359 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
1360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
1361 GLfloat depthTexData[1];
1362 depthTexData[0] = 0.5f;
1363 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
1364 depthTexData);
1365
1366 glActiveTexture(GL_TEXTURE3);
1367 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
1368 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
1369 depthTexData[0] = 0.2f;
1370 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT32F, 1, 1);
1371 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT,
1372 depthTexData);
1373
1374 EXPECT_GL_NO_ERROR();
1375
1376 glUseProgram(mProgram);
1377 glUniform1f(mDepthRefUniformLocation, 0.3f);
1378 glUniform1i(mTexture2DUniformLocation, 0);
1379 glUniform1i(mTextureCubeUniformLocation, 1);
1380 glUniform1i(mTexture2DShadowUniformLocation, 2);
1381 glUniform1i(mTextureCubeShadowUniformLocation, 3);
1382
1383 drawQuad(mProgram, "position", 0.5f);
1384 EXPECT_GL_NO_ERROR();
1385 // The shader writes:
1386 // <texture 2d color> +
1387 // <cube map color> +
1388 // 0.25 * <comparison result (1.0)> +
1389 // 0.125 * <comparison result (0.0)>
1390 EXPECT_PIXEL_NEAR(0, 0, 64, 154, 184, 255, 2);
1391}
1392
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001393class TextureLimitsTest : public ANGLETest
1394{
1395 protected:
1396 struct RGBA8
1397 {
1398 uint8_t R, G, B, A;
1399 };
1400
1401 TextureLimitsTest()
1402 : mProgram(0), mMaxVertexTextures(0), mMaxFragmentTextures(0), mMaxCombinedTextures(0)
1403 {
1404 setWindowWidth(128);
1405 setWindowHeight(128);
1406 setConfigRedBits(8);
1407 setConfigGreenBits(8);
1408 setConfigBlueBits(8);
1409 setConfigAlphaBits(8);
1410 }
1411
1412 ~TextureLimitsTest()
1413 {
1414 if (mProgram != 0)
1415 {
1416 glDeleteProgram(mProgram);
1417 mProgram = 0;
1418
1419 if (!mTextures.empty())
1420 {
1421 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), &mTextures[0]);
1422 }
1423 }
1424 }
1425
1426 void SetUp() override
1427 {
1428 ANGLETest::SetUp();
1429
1430 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mMaxVertexTextures);
1431 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mMaxFragmentTextures);
1432 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxCombinedTextures);
1433
1434 ASSERT_GL_NO_ERROR();
1435 }
1436
1437 void compileProgramWithTextureCounts(const std::string &vertexPrefix,
1438 GLint vertexTextureCount,
1439 GLint vertexActiveTextureCount,
1440 const std::string &fragPrefix,
1441 GLint fragmentTextureCount,
1442 GLint fragmentActiveTextureCount)
1443 {
1444 std::stringstream vertexShaderStr;
1445 vertexShaderStr << "attribute vec2 position;\n"
1446 << "varying vec4 color;\n"
1447 << "varying vec2 texCoord;\n";
1448
1449 for (GLint textureIndex = 0; textureIndex < vertexTextureCount; ++textureIndex)
1450 {
1451 vertexShaderStr << "uniform sampler2D " << vertexPrefix << textureIndex << ";\n";
1452 }
1453
1454 vertexShaderStr << "void main() {\n"
1455 << " gl_Position = vec4(position, 0, 1);\n"
1456 << " texCoord = (position * 0.5) + 0.5;\n"
1457 << " color = vec4(0);\n";
1458
1459 for (GLint textureIndex = 0; textureIndex < vertexActiveTextureCount; ++textureIndex)
1460 {
1461 vertexShaderStr << " color += texture2D(" << vertexPrefix << textureIndex
1462 << ", texCoord);\n";
1463 }
1464
1465 vertexShaderStr << "}";
1466
1467 std::stringstream fragmentShaderStr;
1468 fragmentShaderStr << "varying mediump vec4 color;\n"
1469 << "varying mediump vec2 texCoord;\n";
1470
1471 for (GLint textureIndex = 0; textureIndex < fragmentTextureCount; ++textureIndex)
1472 {
1473 fragmentShaderStr << "uniform sampler2D " << fragPrefix << textureIndex << ";\n";
1474 }
1475
1476 fragmentShaderStr << "void main() {\n"
1477 << " gl_FragColor = color;\n";
1478
1479 for (GLint textureIndex = 0; textureIndex < fragmentActiveTextureCount; ++textureIndex)
1480 {
1481 fragmentShaderStr << " gl_FragColor += texture2D(" << fragPrefix << textureIndex
1482 << ", texCoord);\n";
1483 }
1484
1485 fragmentShaderStr << "}";
1486
1487 const std::string &vertexShaderSource = vertexShaderStr.str();
1488 const std::string &fragmentShaderSource = fragmentShaderStr.str();
1489
1490 mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
1491 }
1492
1493 RGBA8 getPixel(GLint texIndex)
1494 {
1495 RGBA8 pixel = {static_cast<uint8_t>(texIndex & 0x7u), static_cast<uint8_t>(texIndex >> 3),
1496 0, 255u};
1497 return pixel;
1498 }
1499
1500 void initTextures(GLint tex2DCount, GLint texCubeCount)
1501 {
1502 GLint totalCount = tex2DCount + texCubeCount;
1503 mTextures.assign(totalCount, 0);
1504 glGenTextures(totalCount, &mTextures[0]);
1505 ASSERT_GL_NO_ERROR();
1506
1507 std::vector<RGBA8> texData(16 * 16);
1508
1509 GLint texIndex = 0;
1510 for (; texIndex < tex2DCount; ++texIndex)
1511 {
1512 texData.assign(texData.size(), getPixel(texIndex));
1513 glActiveTexture(GL_TEXTURE0 + texIndex);
1514 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
1515 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1516 &texData[0]);
1517 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1518 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1519 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1520 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1521 }
1522
1523 ASSERT_GL_NO_ERROR();
1524
1525 for (; texIndex < texCubeCount; ++texIndex)
1526 {
1527 texData.assign(texData.size(), getPixel(texIndex));
1528 glActiveTexture(GL_TEXTURE0 + texIndex);
1529 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[texIndex]);
1530 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1531 GL_UNSIGNED_BYTE, &texData[0]);
1532 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1533 GL_UNSIGNED_BYTE, &texData[0]);
1534 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1535 GL_UNSIGNED_BYTE, &texData[0]);
1536 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1537 GL_UNSIGNED_BYTE, &texData[0]);
1538 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1539 GL_UNSIGNED_BYTE, &texData[0]);
1540 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1541 GL_UNSIGNED_BYTE, &texData[0]);
1542 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1543 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1544 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1545 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1546 }
1547
1548 ASSERT_GL_NO_ERROR();
1549 }
1550
1551 void testWithTextures(GLint vertexTextureCount,
1552 const std::string &vertexTexturePrefix,
1553 GLint fragmentTextureCount,
1554 const std::string &fragmentTexturePrefix)
1555 {
1556 // Generate textures
1557 initTextures(vertexTextureCount + fragmentTextureCount, 0);
1558
1559 glUseProgram(mProgram);
1560 RGBA8 expectedSum = {0};
1561 for (GLint texIndex = 0; texIndex < vertexTextureCount; ++texIndex)
1562 {
1563 std::stringstream uniformNameStr;
1564 uniformNameStr << vertexTexturePrefix << texIndex;
1565 const std::string &uniformName = uniformNameStr.str();
1566 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
1567 ASSERT_NE(-1, location);
1568
1569 glUniform1i(location, texIndex);
1570 RGBA8 contribution = getPixel(texIndex);
1571 expectedSum.R += contribution.R;
1572 expectedSum.G += contribution.G;
1573 }
1574
1575 for (GLint texIndex = 0; texIndex < fragmentTextureCount; ++texIndex)
1576 {
1577 std::stringstream uniformNameStr;
1578 uniformNameStr << fragmentTexturePrefix << texIndex;
1579 const std::string &uniformName = uniformNameStr.str();
1580 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
1581 ASSERT_NE(-1, location);
1582
1583 glUniform1i(location, texIndex + vertexTextureCount);
1584 RGBA8 contribution = getPixel(texIndex + vertexTextureCount);
1585 expectedSum.R += contribution.R;
1586 expectedSum.G += contribution.G;
1587 }
1588
1589 ASSERT_GE(256u, expectedSum.G);
1590
1591 drawQuad(mProgram, "position", 0.5f);
1592 ASSERT_GL_NO_ERROR();
1593 EXPECT_PIXEL_EQ(0, 0, expectedSum.R, expectedSum.G, 0, 255);
1594 }
1595
1596 GLuint mProgram;
1597 std::vector<GLuint> mTextures;
1598 GLint mMaxVertexTextures;
1599 GLint mMaxFragmentTextures;
1600 GLint mMaxCombinedTextures;
1601};
1602
1603// Test rendering with the maximum vertex texture units.
1604TEST_P(TextureLimitsTest, MaxVertexTextures)
1605{
Jamie Madill1ea9aaa2015-10-07 11:13:55 -04001606 // TODO(jmadill): Figure out why this fails on Intel.
1607 if (isIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
1608 {
1609 std::cout << "Test skipped on Intel." << std::endl;
1610 return;
1611 }
1612
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001613 compileProgramWithTextureCounts("tex", mMaxVertexTextures, mMaxVertexTextures, "tex", 0, 0);
1614 ASSERT_NE(0u, mProgram);
1615 ASSERT_GL_NO_ERROR();
1616
1617 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
1618}
1619
1620// Test rendering with the maximum fragment texture units.
1621TEST_P(TextureLimitsTest, MaxFragmentTextures)
1622{
Jamie Madill1ea9aaa2015-10-07 11:13:55 -04001623 // TODO(jmadill): Figure out why this fails on Intel.
1624 if (isIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
1625 {
1626 std::cout << "Test skipped on Intel." << std::endl;
1627 return;
1628 }
1629
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001630 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures, mMaxFragmentTextures);
1631 ASSERT_NE(0u, mProgram);
1632 ASSERT_GL_NO_ERROR();
1633
1634 testWithTextures(mMaxFragmentTextures, "tex", 0, "tex");
1635}
1636
1637// Test rendering with maximum combined texture units.
1638TEST_P(TextureLimitsTest, MaxCombinedTextures)
1639{
Jamie Madill412f17d2015-09-25 08:43:54 -04001640 // TODO(jmadill): Investigate workaround.
1641 if (isIntel() && GetParam() == ES2_OPENGL())
1642 {
1643 std::cout << "Test skipped on Intel." << std::endl;
1644 return;
1645 }
1646
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001647 GLint vertexTextures = mMaxVertexTextures;
1648
1649 if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
1650 {
1651 vertexTextures = mMaxCombinedTextures - mMaxFragmentTextures;
1652 }
1653
1654 compileProgramWithTextureCounts("vtex", vertexTextures, vertexTextures, "ftex",
1655 mMaxFragmentTextures, mMaxFragmentTextures);
1656 ASSERT_NE(0u, mProgram);
1657 ASSERT_GL_NO_ERROR();
1658
1659 testWithTextures(vertexTextures, "vtex", mMaxFragmentTextures, "ftex");
1660}
1661
1662// Negative test for exceeding the number of vertex textures
1663TEST_P(TextureLimitsTest, ExcessiveVertexTextures)
1664{
1665 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 1, mMaxVertexTextures + 1, "tex", 0,
1666 0);
1667 ASSERT_EQ(0u, mProgram);
1668}
1669
1670// Negative test for exceeding the number of fragment textures
1671TEST_P(TextureLimitsTest, ExcessiveFragmentTextures)
1672{
1673 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 1,
1674 mMaxFragmentTextures + 1);
1675 ASSERT_EQ(0u, mProgram);
1676}
1677
1678// Test active vertex textures under the limit, but excessive textures specified.
1679TEST_P(TextureLimitsTest, MaxActiveVertexTextures)
1680{
Jamie Madill1ea9aaa2015-10-07 11:13:55 -04001681 // TODO(jmadill): Figure out why this fails on Intel.
1682 if (isIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
1683 {
1684 std::cout << "Test skipped on Intel." << std::endl;
1685 return;
1686 }
1687
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001688 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 4, mMaxVertexTextures, "tex", 0, 0);
1689 ASSERT_NE(0u, mProgram);
1690 ASSERT_GL_NO_ERROR();
1691
1692 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
1693}
1694
1695// Test active fragment textures under the limit, but excessive textures specified.
1696TEST_P(TextureLimitsTest, MaxActiveFragmentTextures)
1697{
Jamie Madill1ea9aaa2015-10-07 11:13:55 -04001698 // TODO(jmadill): Figure out why this fails on Intel.
1699 if (isIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
1700 {
1701 std::cout << "Test skipped on Intel." << std::endl;
1702 return;
1703 }
1704
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001705 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 4,
1706 mMaxFragmentTextures);
1707 ASSERT_NE(0u, mProgram);
1708 ASSERT_GL_NO_ERROR();
1709
1710 testWithTextures(0, "tex", mMaxFragmentTextures, "tex");
1711}
1712
1713// Negative test for pointing two sampler uniforms of different types to the same texture.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001714// GLES 2.0.25 section 2.10.4 page 39.
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001715TEST_P(TextureLimitsTest, TextureTypeConflict)
1716{
1717 const std::string &vertexShader =
1718 "attribute vec2 position;\n"
1719 "varying float color;\n"
1720 "uniform sampler2D tex2D;\n"
1721 "uniform samplerCube texCube;\n"
1722 "void main() {\n"
1723 " gl_Position = vec4(position, 0, 1);\n"
1724 " vec2 texCoord = (position * 0.5) + 0.5;\n"
1725 " color = texture2D(tex2D, texCoord).x;\n"
1726 " color += textureCube(texCube, vec3(texCoord, 0)).x;\n"
1727 "}";
1728 const std::string &fragmentShader =
1729 "varying mediump float color;\n"
1730 "void main() {\n"
1731 " gl_FragColor = vec4(color, 0, 0, 1);\n"
1732 "}";
1733
1734 mProgram = CompileProgram(vertexShader, fragmentShader);
1735 ASSERT_NE(0u, mProgram);
1736
1737 initTextures(1, 0);
1738
1739 glUseProgram(mProgram);
1740 GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
1741 ASSERT_NE(-1, tex2DLocation);
1742 GLint texCubeLocation = glGetUniformLocation(mProgram, "texCube");
1743 ASSERT_NE(-1, texCubeLocation);
1744
1745 glUniform1i(tex2DLocation, 0);
1746 glUniform1i(texCubeLocation, 0);
1747 ASSERT_GL_NO_ERROR();
1748
1749 drawQuad(mProgram, "position", 0.5f);
1750 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1751}
1752
1753// Negative test for rendering with texture outside the valid range.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001754// TODO(jmadill): Possibly adjust the test according to the spec:
1755// GLES 3.0.4 section 2.12.7 mentions that specifying an out-of-range sampler uniform value
1756// generates an INVALID_VALUE error - GLES 2.0 doesn't yet have this mention.
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001757TEST_P(TextureLimitsTest, DrawWithTexturePastMaximum)
1758{
1759 const std::string &vertexShader =
1760 "attribute vec2 position;\n"
1761 "varying float color;\n"
1762 "uniform sampler2D tex2D;\n"
1763 "void main() {\n"
1764 " gl_Position = vec4(position, 0, 1);\n"
1765 " vec2 texCoord = (position * 0.5) + 0.5;\n"
1766 " color = texture2D(tex2D, texCoord).x;\n"
1767 "}";
1768 const std::string &fragmentShader =
1769 "varying mediump float color;\n"
1770 "void main() {\n"
1771 " gl_FragColor = vec4(color, 0, 0, 1);\n"
1772 "}";
1773
1774 mProgram = CompileProgram(vertexShader, fragmentShader);
1775 ASSERT_NE(0u, mProgram);
1776
1777 glUseProgram(mProgram);
1778 GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
1779 ASSERT_NE(-1, tex2DLocation);
1780
1781 glUniform1i(tex2DLocation, mMaxCombinedTextures);
1782 ASSERT_GL_NO_ERROR();
1783
1784 drawQuad(mProgram, "position", 0.5f);
1785 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1786}
1787
Jamie Madillfa05f602015-05-07 13:47:11 -04001788// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Olli Etuaho51f1c0f2016-01-13 16:16:24 +02001789// TODO(oetuaho): Enable all below tests on OpenGL. Requires a fix for ANGLE bug 1278.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001790ANGLE_INSTANTIATE_TEST(Texture2DTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3());
Olli Etuaho51f1c0f2016-01-13 16:16:24 +02001791ANGLE_INSTANTIATE_TEST(TextureCubeTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3(), ES2_OPENGL());
1792ANGLE_INSTANTIATE_TEST(Texture2DTestWithDrawScale,
1793 ES2_D3D9(),
1794 ES2_D3D11(),
1795 ES2_D3D11_FL9_3(),
1796 ES2_OPENGL());
1797ANGLE_INSTANTIATE_TEST(Sampler2DAsFunctionParameterTest,
1798 ES2_D3D9(),
1799 ES2_D3D11(),
1800 ES2_D3D11_FL9_3(),
1801 ES2_OPENGL());
1802ANGLE_INSTANTIATE_TEST(SamplerArrayTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3(), ES2_OPENGL());
Olli Etuaho2173db3d2016-01-12 13:55:14 +02001803ANGLE_INSTANTIATE_TEST(SamplerArrayAsFunctionParameterTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3());
Olli Etuahoa7416ff2016-01-18 12:22:55 +02001804ANGLE_INSTANTIATE_TEST(Texture2DTestES3, ES3_D3D11(), ES3_OPENGL());
Olli Etuaho1a679902016-01-14 12:21:47 +02001805ANGLE_INSTANTIATE_TEST(ShadowSamplerPlusSampler3DTestES3, ES3_D3D11(), ES3_OPENGL());
Olli Etuahoc8c99a02016-01-14 16:47:22 +02001806ANGLE_INSTANTIATE_TEST(SamplerTypeMixTestES3, ES3_D3D11(), ES3_OPENGL());
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001807ANGLE_INSTANTIATE_TEST(Texture2DArrayTestES3, ES3_D3D11(), ES3_OPENGL());
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001808ANGLE_INSTANTIATE_TEST(TextureLimitsTest, ES2_D3D11(), ES2_OPENGL());
Jamie Madillfa05f602015-05-07 13:47:11 -04001809
1810} // namespace