blob: 8ae600ac18ee98c9a201feeb0116a8e459d8c8d4 [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 Etuaho4a8329f2016-01-11 17:12:57 +0200280class Texture2DTestWithDrawScale : public Texture2DTest
Jamie Madill2453dbc2015-07-14 11:35:42 -0400281{
282 protected:
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200283 Texture2DTestWithDrawScale() : Texture2DTest(), mDrawScaleUniformLocation(-1) {}
284
285 std::string getVertexShaderSource() override
Jamie Madill2453dbc2015-07-14 11:35:42 -0400286 {
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200287 return std::string(SHADER_SOURCE
288 (
289 precision highp float;
290 attribute vec4 position;
291 varying vec2 texcoord;
292
293 uniform vec2 drawScale;
294
295 void main()
296 {
297 gl_Position = vec4(position.xy * drawScale, 0.0, 1.0);
298 texcoord = (position.xy * 0.5) + 0.5;
299 }
300 )
301 );
Jamie Madill2453dbc2015-07-14 11:35:42 -0400302 }
303
304 void SetUp() override
305 {
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200306 Texture2DTest::SetUp();
307 mDrawScaleUniformLocation = glGetUniformLocation(mProgram, "drawScale");
308 ASSERT_NE(-1, mDrawScaleUniformLocation);
Jamie Madill2453dbc2015-07-14 11:35:42 -0400309
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200310 glUseProgram(mProgram);
311 glUniform2f(mDrawScaleUniformLocation, 1.0f, 1.0f);
312 glUseProgram(0);
313 ASSERT_GL_NO_ERROR();
314 }
315
316 GLint mDrawScaleUniformLocation;
317};
318
Olli Etuaho4644a202016-01-12 15:12:53 +0200319class Sampler2DAsFunctionParameterTest : public Texture2DTest
320{
321 protected:
322 Sampler2DAsFunctionParameterTest() : Texture2DTest() {}
323
324 std::string getFragmentShaderSource() override
325 {
326 return std::string(SHADER_SOURCE
327 (
328 precision highp float;
329 uniform sampler2D tex;
330 varying vec2 texcoord;
331
332 vec4 computeFragColor(sampler2D aTex)
333 {
334 return texture2D(aTex, texcoord);
335 }
336
337 void main()
338 {
339 gl_FragColor = computeFragColor(tex);
340 }
341 )
342 );
343 }
344};
345
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200346class TextureCubeTest : public TexCoordDrawTest
347{
348 protected:
349 TextureCubeTest()
350 : TexCoordDrawTest(),
351 mTexture2D(0),
352 mTextureCube(0),
353 mTexture2DUniformLocation(-1),
354 mTextureCubeUniformLocation(-1)
355 {
356 }
357
358 std::string getFragmentShaderSource() override
359 {
360 return std::string(SHADER_SOURCE
361 (
362 precision highp float;
363 uniform sampler2D tex2D;
364 uniform samplerCube texCube;
365 varying vec2 texcoord;
366
367 void main()
368 {
369 gl_FragColor = texture2D(tex2D, texcoord);
370 gl_FragColor += textureCube(texCube, vec3(texcoord, 0));
371 }
372 )
373 );
374 }
375
376 void SetUp() override
377 {
378 TexCoordDrawTest::SetUp();
379
380 glGenTextures(1, &mTextureCube);
381 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
382 glTexStorage2DEXT(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
383 EXPECT_GL_NO_ERROR();
384
385 mTexture2D = create2DTexture();
386
387 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
388 ASSERT_NE(-1, mTexture2DUniformLocation);
389 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
390 ASSERT_NE(-1, mTextureCubeUniformLocation);
391 }
392
393 void TearDown() override
394 {
395 glDeleteTextures(1, &mTextureCube);
396 TexCoordDrawTest::TearDown();
397 }
398
399 GLuint mTexture2D;
400 GLuint mTextureCube;
401 GLint mTexture2DUniformLocation;
402 GLint mTextureCubeUniformLocation;
403};
404
Olli Etuaho2173db3d2016-01-12 13:55:14 +0200405class SamplerArrayTest : public TexCoordDrawTest
406{
407 protected:
408 SamplerArrayTest()
409 : TexCoordDrawTest(),
410 mTexture2DA(0),
411 mTexture2DB(0),
412 mTexture0UniformLocation(-1),
413 mTexture1UniformLocation(-1)
414 {
415 }
416
417 std::string getFragmentShaderSource() override
418 {
419 return std::string(SHADER_SOURCE
420 (
421 precision mediump float;
422 uniform highp sampler2D tex2DArray[2];
423 varying vec2 texcoord;
424 void main()
425 {
426 gl_FragColor = texture2D(tex2DArray[0], texcoord);
427 gl_FragColor += texture2D(tex2DArray[1], texcoord);
428 }
429 )
430 );
431 }
432
433 void SetUp() override
434 {
435 TexCoordDrawTest::SetUp();
436
437 mTexture0UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[0]");
438 ASSERT_NE(-1, mTexture0UniformLocation);
439 mTexture1UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[1]");
440 ASSERT_NE(-1, mTexture1UniformLocation);
441
442 mTexture2DA = create2DTexture();
443 mTexture2DB = create2DTexture();
444 ASSERT_GL_NO_ERROR();
445 }
446
447 void TearDown() override
448 {
449 glDeleteTextures(1, &mTexture2DA);
450 glDeleteTextures(1, &mTexture2DB);
451 TexCoordDrawTest::TearDown();
452 }
453
454 void testSamplerArrayDraw()
455 {
456 GLubyte texData[4];
457 texData[0] = 0;
458 texData[1] = 60;
459 texData[2] = 0;
460 texData[3] = 255;
461
462 glActiveTexture(GL_TEXTURE0);
463 glBindTexture(GL_TEXTURE_2D, mTexture2DA);
464 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
465
466 texData[1] = 120;
467 glActiveTexture(GL_TEXTURE1);
468 glBindTexture(GL_TEXTURE_2D, mTexture2DB);
469 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
470 EXPECT_GL_ERROR(GL_NO_ERROR);
471
472 glUseProgram(mProgram);
473 glUniform1i(mTexture0UniformLocation, 0);
474 glUniform1i(mTexture1UniformLocation, 1);
475 drawQuad(mProgram, "position", 0.5f);
476 EXPECT_GL_NO_ERROR();
477
478 EXPECT_PIXEL_NEAR(0, 0, 0, 180, 0, 255, 2);
479 }
480
481 GLuint mTexture2DA;
482 GLuint mTexture2DB;
483 GLint mTexture0UniformLocation;
484 GLint mTexture1UniformLocation;
485};
486
487
488class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
489{
490 protected:
491 SamplerArrayAsFunctionParameterTest() : SamplerArrayTest() {}
492
493 std::string getFragmentShaderSource() override
494 {
495 return std::string(SHADER_SOURCE
496 (
497 precision mediump float;
498 uniform highp sampler2D tex2DArray[2];
499 varying vec2 texcoord;
500
501 vec4 computeFragColor(highp sampler2D aTex2DArray[2])
502 {
503 return texture2D(aTex2DArray[0], texcoord) + texture2D(aTex2DArray[1], texcoord);
504 }
505
506 void main()
507 {
508 gl_FragColor = computeFragColor(tex2DArray);
509 }
510 )
511 );
512 }
513};
514
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200515class Texture2DArrayTestES3 : public TexCoordDrawTest
516{
517 protected:
518 Texture2DArrayTestES3() : TexCoordDrawTest(), m2DArrayTexture(0), mTextureArrayLocation(-1) {}
519
520 std::string getVertexShaderSource() override
521 {
522 return std::string(
Jamie Madill2453dbc2015-07-14 11:35:42 -0400523 "#version 300 es\n"
524 "out vec2 texcoord;\n"
525 "in vec4 position;\n"
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200526 "void main()\n"
527 "{\n"
528 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
529 " texcoord = (position.xy * 0.5) + 0.5;\n"
530 "}\n");
531 }
Jamie Madill2453dbc2015-07-14 11:35:42 -0400532
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200533 std::string getFragmentShaderSource() override
534 {
535 return std::string(
Jamie Madill2453dbc2015-07-14 11:35:42 -0400536 "#version 300 es\n"
537 "precision highp float;\n"
Olli Etuaho183d7e22015-11-20 15:59:09 +0200538 "uniform highp sampler2DArray tex2DArray;\n"
Jamie Madill2453dbc2015-07-14 11:35:42 -0400539 "in vec2 texcoord;\n"
540 "out vec4 fragColor;\n"
541 "void main()\n"
542 "{\n"
543 " fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, 0.0));\n"
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200544 "}\n");
545 }
Jamie Madill2453dbc2015-07-14 11:35:42 -0400546
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200547 void SetUp() override
548 {
549 TexCoordDrawTest::SetUp();
Jamie Madill2453dbc2015-07-14 11:35:42 -0400550
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200551 mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
Jamie Madill2453dbc2015-07-14 11:35:42 -0400552 ASSERT_NE(-1, mTextureArrayLocation);
553
554 glGenTextures(1, &m2DArrayTexture);
555 ASSERT_GL_NO_ERROR();
556 }
557
558 void TearDown() override
559 {
560 glDeleteTextures(1, &m2DArrayTexture);
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200561 TexCoordDrawTest::TearDown();
Jamie Madill2453dbc2015-07-14 11:35:42 -0400562 }
563
564 GLuint m2DArrayTexture;
Jamie Madill2453dbc2015-07-14 11:35:42 -0400565 GLint mTextureArrayLocation;
566};
567
Olli Etuaho1a679902016-01-14 12:21:47 +0200568class ShadowSamplerPlusSampler3DTestES3 : public TexCoordDrawTest
569{
570 protected:
571 ShadowSamplerPlusSampler3DTestES3()
572 : TexCoordDrawTest(),
573 mTextureShadow(0),
574 mTexture3D(0),
575 mTextureShadowUniformLocation(-1),
576 mTexture3DUniformLocation(-1),
577 mDepthRefUniformLocation(-1)
578 {
579 }
580
581 std::string getVertexShaderSource() override
582 {
583 return std::string(
584 "#version 300 es\n"
585 "out vec2 texcoord;\n"
586 "in vec4 position;\n"
587 "void main()\n"
588 "{\n"
589 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
590 " texcoord = (position.xy * 0.5) + 0.5;\n"
591 "}\n");
592 }
593
594 std::string getFragmentShaderSource() override
595 {
596 return std::string(
597 "#version 300 es\n"
598 "precision highp float;\n"
599 "uniform highp sampler2DShadow tex2DShadow;\n"
600 "uniform highp sampler3D tex3D;\n"
601 "in vec2 texcoord;\n"
602 "uniform float depthRef;\n"
603 "out vec4 fragColor;\n"
604 "void main()\n"
605 "{\n"
606 " fragColor = vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.5);\n"
607 " fragColor += texture(tex3D, vec3(texcoord, 0.0));\n"
608 "}\n");
609 }
610
611 void SetUp() override
612 {
613 TexCoordDrawTest::SetUp();
614
615 glGenTextures(1, &mTexture3D);
616
617 glGenTextures(1, &mTextureShadow);
618 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
619 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
620
621 mTextureShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
622 ASSERT_NE(-1, mTextureShadowUniformLocation);
623 mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
624 ASSERT_NE(-1, mTexture3DUniformLocation);
625 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
626 ASSERT_NE(-1, mDepthRefUniformLocation);
627 }
628
629 void TearDown() override
630 {
631 glDeleteTextures(1, &mTextureShadow);
632 glDeleteTextures(1, &mTexture3D);
633 TexCoordDrawTest::TearDown();
634 }
635
636 GLuint mTextureShadow;
637 GLuint mTexture3D;
638 GLint mTextureShadowUniformLocation;
639 GLint mTexture3DUniformLocation;
640 GLint mDepthRefUniformLocation;
641};
642
Olli Etuahoc8c99a02016-01-14 16:47:22 +0200643class SamplerTypeMixTestES3 : public TexCoordDrawTest
644{
645 protected:
646 SamplerTypeMixTestES3()
647 : TexCoordDrawTest(),
648 mTexture2D(0),
649 mTextureCube(0),
650 mTexture2DShadow(0),
651 mTextureCubeShadow(0),
652 mTexture2DUniformLocation(-1),
653 mTextureCubeUniformLocation(-1),
654 mTexture2DShadowUniformLocation(-1),
655 mTextureCubeShadowUniformLocation(-1),
656 mDepthRefUniformLocation(-1)
657 {
658 }
659
660 std::string getVertexShaderSource() override
661 {
662 return std::string(
663 "#version 300 es\n"
664 "out vec2 texcoord;\n"
665 "in vec4 position;\n"
666 "void main()\n"
667 "{\n"
668 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
669 " texcoord = (position.xy * 0.5) + 0.5;\n"
670 "}\n");
671 }
672
673 std::string getFragmentShaderSource() override
674 {
675 return std::string(
676 "#version 300 es\n"
677 "precision highp float;\n"
678 "uniform highp sampler2D tex2D;\n"
679 "uniform highp samplerCube texCube;\n"
680 "uniform highp sampler2DShadow tex2DShadow;\n"
681 "uniform highp samplerCubeShadow texCubeShadow;\n"
682 "in vec2 texcoord;\n"
683 "uniform float depthRef;\n"
684 "out vec4 fragColor;\n"
685 "void main()\n"
686 "{\n"
687 " fragColor = texture(tex2D, texcoord);\n"
688 " fragColor += texture(texCube, vec3(1.0, 0.0, 0.0));\n"
689 " fragColor += vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.25);\n"
690 " fragColor += vec4(texture(texCubeShadow, vec4(1.0, 0.0, 0.0, depthRef)) * "
691 "0.125);\n"
692 "}\n");
693 }
694
695 void SetUp() override
696 {
697 TexCoordDrawTest::SetUp();
698
699 glGenTextures(1, &mTexture2D);
700 glGenTextures(1, &mTextureCube);
701
702 glGenTextures(1, &mTexture2DShadow);
703 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
704 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
705
706 glGenTextures(1, &mTextureCubeShadow);
707 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
708 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
709
710 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
711 ASSERT_NE(-1, mTexture2DUniformLocation);
712 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
713 ASSERT_NE(-1, mTextureCubeUniformLocation);
714 mTexture2DShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
715 ASSERT_NE(-1, mTexture2DShadowUniformLocation);
716 mTextureCubeShadowUniformLocation = glGetUniformLocation(mProgram, "texCubeShadow");
717 ASSERT_NE(-1, mTextureCubeShadowUniformLocation);
718 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
719 ASSERT_NE(-1, mDepthRefUniformLocation);
720
721 ASSERT_GL_NO_ERROR();
722 }
723
724 void TearDown() override
725 {
726 glDeleteTextures(1, &mTexture2D);
727 glDeleteTextures(1, &mTextureCube);
728 glDeleteTextures(1, &mTexture2DShadow);
729 glDeleteTextures(1, &mTextureCubeShadow);
730 TexCoordDrawTest::TearDown();
731 }
732
733 GLuint mTexture2D;
734 GLuint mTextureCube;
735 GLuint mTexture2DShadow;
736 GLuint mTextureCubeShadow;
737 GLint mTexture2DUniformLocation;
738 GLint mTextureCubeUniformLocation;
739 GLint mTexture2DShadowUniformLocation;
740 GLint mTextureCubeShadowUniformLocation;
741 GLint mDepthRefUniformLocation;
742};
743
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200744TEST_P(Texture2DTest, NegativeAPISubImage)
Jamie Madillf67115c2014-04-22 13:14:05 -0400745{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400746 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Jamie Madillf67115c2014-04-22 13:14:05 -0400747 EXPECT_GL_ERROR(GL_NO_ERROR);
748
749 const GLubyte *pixels[20] = { 0 };
750 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
751 EXPECT_GL_ERROR(GL_INVALID_VALUE);
752}
Geoff Langc41e42d2014-04-28 10:58:16 -0400753
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200754TEST_P(Texture2DTest, ZeroSizedUploads)
Geoff Langc41e42d2014-04-28 10:58:16 -0400755{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400756 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Geoff Langc41e42d2014-04-28 10:58:16 -0400757 EXPECT_GL_ERROR(GL_NO_ERROR);
758
759 // Use the texture first to make sure it's in video memory
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200760 glUseProgram(mProgram);
Jamie Madilld4cfa572014-07-08 10:00:32 -0400761 glUniform1i(mTexture2DUniformLocation, 0);
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200762 drawQuad(mProgram, "position", 0.5f);
Geoff Langc41e42d2014-04-28 10:58:16 -0400763
764 const GLubyte *pixel[4] = { 0 };
765
766 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
767 EXPECT_GL_NO_ERROR();
768
769 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
770 EXPECT_GL_NO_ERROR();
771
772 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
773 EXPECT_GL_NO_ERROR();
774}
Jamie Madilld4cfa572014-07-08 10:00:32 -0400775
776// Test drawing with two texture types, to trigger an ANGLE bug in validation
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200777TEST_P(TextureCubeTest, CubeMapBug)
Jamie Madilld4cfa572014-07-08 10:00:32 -0400778{
779 glActiveTexture(GL_TEXTURE0);
780 glBindTexture(GL_TEXTURE_2D, mTexture2D);
781 glActiveTexture(GL_TEXTURE1);
782 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
783 EXPECT_GL_ERROR(GL_NO_ERROR);
784
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200785 glUseProgram(mProgram);
786 glUniform1i(mTexture2DUniformLocation, 0);
787 glUniform1i(mTextureCubeUniformLocation, 1);
788 drawQuad(mProgram, "position", 0.5f);
Jamie Madilld4cfa572014-07-08 10:00:32 -0400789 EXPECT_GL_NO_ERROR();
790}
Jamie Madill9aca0592014-10-06 16:26:59 -0400791
Olli Etuaho53a2da12016-01-11 15:43:32 +0200792// Test drawing with two texture types accessed from the same shader and check that the result of
793// drawing is correct.
794TEST_P(TextureCubeTest, CubeMapDraw)
795{
796 GLubyte texData[4];
797 texData[0] = 0;
798 texData[1] = 60;
799 texData[2] = 0;
800 texData[3] = 255;
801
802 glActiveTexture(GL_TEXTURE0);
803 glBindTexture(GL_TEXTURE_2D, mTexture2D);
804 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
805
806 glActiveTexture(GL_TEXTURE1);
807 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
808 texData[1] = 120;
809 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
810 texData);
811 EXPECT_GL_ERROR(GL_NO_ERROR);
812
813 glUseProgram(mProgram);
814 glUniform1i(mTexture2DUniformLocation, 0);
815 glUniform1i(mTextureCubeUniformLocation, 1);
816 drawQuad(mProgram, "position", 0.5f);
817 EXPECT_GL_NO_ERROR();
818
819 int px = getWindowWidth() - 1;
820 int py = 0;
821 EXPECT_PIXEL_NEAR(px, py, 0, 180, 0, 255, 2);
822}
823
Olli Etuaho4644a202016-01-12 15:12:53 +0200824TEST_P(Sampler2DAsFunctionParameterTest, Sampler2DAsFunctionParameter)
825{
826 glActiveTexture(GL_TEXTURE0);
827 glBindTexture(GL_TEXTURE_2D, mTexture2D);
828 GLubyte texData[4];
829 texData[0] = 0;
830 texData[1] = 128;
831 texData[2] = 0;
832 texData[3] = 255;
833 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
834 glUseProgram(mProgram);
835 glUniform1i(mTexture2DUniformLocation, 0);
836 drawQuad(mProgram, "position", 0.5f);
837 EXPECT_GL_NO_ERROR();
838
839 EXPECT_PIXEL_NEAR(0, 0, 0, 128, 0, 255, 2);
840}
841
Olli Etuaho2173db3d2016-01-12 13:55:14 +0200842// Test drawing with two textures passed to the shader in a sampler array.
843TEST_P(SamplerArrayTest, SamplerArrayDraw)
844{
845 testSamplerArrayDraw();
846}
847
848// Test drawing with two textures passed to the shader in a sampler array which is passed to a
849// user-defined function in the shader.
850TEST_P(SamplerArrayAsFunctionParameterTest, SamplerArrayAsFunctionParameter)
851{
852 testSamplerArrayDraw();
853}
854
Jamie Madill9aca0592014-10-06 16:26:59 -0400855// Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200856TEST_P(Texture2DTestWithDrawScale, MipmapsTwice)
Jamie Madill9aca0592014-10-06 16:26:59 -0400857{
858 int px = getWindowWidth() / 2;
859 int py = getWindowHeight() / 2;
860
861 glActiveTexture(GL_TEXTURE0);
862 glBindTexture(GL_TEXTURE_2D, mTexture2D);
863
864 // Fill with red
865 std::vector<GLubyte> pixels(4 * 16 * 16);
866 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
867 {
868 pixels[pixelId * 4 + 0] = 255;
869 pixels[pixelId * 4 + 1] = 0;
870 pixels[pixelId * 4 + 2] = 0;
871 pixels[pixelId * 4 + 3] = 255;
872 }
873
874 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
875 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
876 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
877 glGenerateMipmap(GL_TEXTURE_2D);
878
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200879 glUseProgram(mProgram);
Jamie Madill9aca0592014-10-06 16:26:59 -0400880 glUniform1i(mTexture2DUniformLocation, 0);
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200881 glUniform2f(mDrawScaleUniformLocation, 0.0625f, 0.0625f);
882 drawQuad(mProgram, "position", 0.5f);
Jamie Madill9aca0592014-10-06 16:26:59 -0400883 EXPECT_GL_NO_ERROR();
884 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
885
886 // Fill with blue
887 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
888 {
889 pixels[pixelId * 4 + 0] = 0;
890 pixels[pixelId * 4 + 1] = 0;
891 pixels[pixelId * 4 + 2] = 255;
892 pixels[pixelId * 4 + 3] = 255;
893 }
894
895 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
896 glGenerateMipmap(GL_TEXTURE_2D);
897
898 // Fill with green
899 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
900 {
901 pixels[pixelId * 4 + 0] = 0;
902 pixels[pixelId * 4 + 1] = 255;
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 glGenerateMipmap(GL_TEXTURE_2D);
909
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200910 drawQuad(mProgram, "position", 0.5f);
Jamie Madill9aca0592014-10-06 16:26:59 -0400911
912 EXPECT_GL_NO_ERROR();
913 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
914}
Jamie Madillf8fccb32014-11-12 15:05:26 -0500915
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500916// Test creating a FBO with a cube map render target, to test an ANGLE bug
917// https://code.google.com/p/angleproject/issues/detail?id=849
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200918TEST_P(TextureCubeTest, CubeMapFBO)
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500919{
920 GLuint fbo;
921 glGenFramebuffers(1, &fbo);
922 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
923
924 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
925 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mTextureCube, 0);
926
Corentin Wallez322653b2015-06-17 18:33:56 +0200927 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500928
929 glDeleteFramebuffers(1, &fbo);
930
931 EXPECT_GL_NO_ERROR();
932}
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000933
934// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a default color.
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200935TEST_P(Texture2DTest, TexStorage)
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000936{
937 int width = getWindowWidth();
938 int height = getWindowHeight();
939
940 GLuint tex2D;
941 glGenTextures(1, &tex2D);
942 glActiveTexture(GL_TEXTURE0);
943 glBindTexture(GL_TEXTURE_2D, tex2D);
944
945 // Fill with red
946 std::vector<GLubyte> pixels(3 * 16 * 16);
947 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
948 {
949 pixels[pixelId * 3 + 0] = 255;
950 pixels[pixelId * 3 + 1] = 0;
951 pixels[pixelId * 3 + 2] = 0;
952 }
953
954 // ANGLE internally uses RGBA as the DirectX format for RGB images
955 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
956 // The data is kept in a CPU-side image and the image is marked as dirty.
957 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
958
959 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
960 // glTexSubImage2D should take into account that the image is dirty.
961 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
962 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
963 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
964
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200965 glUseProgram(mProgram);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000966 glUniform1i(mTexture2DUniformLocation, 0);
Olli Etuaho4a8329f2016-01-11 17:12:57 +0200967 drawQuad(mProgram, "position", 0.5f);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000968 glDeleteTextures(1, &tex2D);
969 EXPECT_GL_NO_ERROR();
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000970 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
Geoff Langfbfa47c2015-03-31 11:26:00 -0400971
972 // Validate that the region of the texture without data has an alpha of 1.0
973 GLubyte pixel[4];
974 glReadPixels(3 * width / 4, 3 * height / 4, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
975 EXPECT_EQ(pixel[3], 255);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000976}
977
978// 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 +0200979TEST_P(Texture2DTest, TexStorageWithPBO)
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000980{
981 if (extensionEnabled("NV_pixel_buffer_object"))
982 {
983 int width = getWindowWidth();
984 int height = getWindowHeight();
985
986 GLuint tex2D;
987 glGenTextures(1, &tex2D);
988 glActiveTexture(GL_TEXTURE0);
989 glBindTexture(GL_TEXTURE_2D, tex2D);
990
991 // Fill with red
992 std::vector<GLubyte> pixels(3 * 16 * 16);
993 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
994 {
995 pixels[pixelId * 3 + 0] = 255;
996 pixels[pixelId * 3 + 1] = 0;
997 pixels[pixelId * 3 + 2] = 0;
998 }
999
1000 // Read 16x16 region from red backbuffer to PBO
1001 GLuint pbo;
1002 glGenBuffers(1, &pbo);
1003 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
1004 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
1005
1006 // ANGLE internally uses RGBA as the DirectX format for RGB images
1007 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
1008 // The data is kept in a CPU-side image and the image is marked as dirty.
1009 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
1010
1011 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
1012 // glTexSubImage2D should take into account that the image is dirty.
1013 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, NULL);
1014 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1015 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1016
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001017 glUseProgram(mProgram);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001018 glUniform1i(mTexture2DUniformLocation, 0);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001019 drawQuad(mProgram, "position", 0.5f);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001020 glDeleteTextures(1, &tex2D);
Olli Etuaho19d48db2016-01-13 14:43:21 +02001021 glDeleteBuffers(1, &pbo);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +00001022 EXPECT_GL_NO_ERROR();
1023 EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
1024 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
1025 }
1026}
Jamie Madillbc393df2015-01-29 13:46:07 -05001027
1028// See description on testFloatCopySubImage
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001029TEST_P(Texture2DTest, CopySubImageFloat_R_R)
Jamie Madillbc393df2015-01-29 13:46:07 -05001030{
1031 testFloatCopySubImage(1, 1);
1032}
1033
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001034TEST_P(Texture2DTest, CopySubImageFloat_RG_R)
Jamie Madillbc393df2015-01-29 13:46:07 -05001035{
1036 testFloatCopySubImage(2, 1);
1037}
1038
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001039TEST_P(Texture2DTest, CopySubImageFloat_RG_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -05001040{
1041 testFloatCopySubImage(2, 2);
1042}
1043
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001044TEST_P(Texture2DTest, CopySubImageFloat_RGB_R)
Jamie Madillbc393df2015-01-29 13:46:07 -05001045{
1046 testFloatCopySubImage(3, 1);
1047}
1048
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001049TEST_P(Texture2DTest, CopySubImageFloat_RGB_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -05001050{
1051 testFloatCopySubImage(3, 2);
1052}
1053
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001054TEST_P(Texture2DTest, CopySubImageFloat_RGB_RGB)
Jamie Madillbc393df2015-01-29 13:46:07 -05001055{
1056 testFloatCopySubImage(3, 3);
1057}
1058
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001059TEST_P(Texture2DTest, CopySubImageFloat_RGBA_R)
Jamie Madillbc393df2015-01-29 13:46:07 -05001060{
1061 testFloatCopySubImage(4, 1);
1062}
1063
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001064TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -05001065{
1066 testFloatCopySubImage(4, 2);
1067}
1068
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001069TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGB)
Jamie Madillbc393df2015-01-29 13:46:07 -05001070{
1071 testFloatCopySubImage(4, 3);
1072}
1073
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001074TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGBA)
Jamie Madillbc393df2015-01-29 13:46:07 -05001075{
1076 testFloatCopySubImage(4, 4);
1077}
Austin Kinross07285142015-03-26 11:36:16 -07001078
1079// Port of https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html
1080// 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 +02001081TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE)
Austin Kinross07285142015-03-26 11:36:16 -07001082{
1083 const int npotTexSize = 5;
1084 const int potTexSize = 4; // Should be less than npotTexSize
1085 GLuint tex2D;
1086
1087 if (extensionEnabled("GL_OES_texture_npot"))
1088 {
1089 // This test isn't applicable if texture_npot is enabled
1090 return;
1091 }
1092
1093 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1094
Austin Kinross5faa15b2016-01-11 13:32:48 -08001095 // Default unpack alignment is 4. The values of 'pixels' below needs it to be 1.
1096 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1097
Austin Kinross07285142015-03-26 11:36:16 -07001098 glActiveTexture(GL_TEXTURE0);
1099 glGenTextures(1, &tex2D);
1100 glBindTexture(GL_TEXTURE_2D, tex2D);
1101
1102 std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize);
1103 for (size_t pixelId = 0; pixelId < npotTexSize * npotTexSize; ++pixelId)
1104 {
1105 pixels[pixelId] = 64;
1106 }
1107
1108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1110
1111 // Check that an NPOT texture not on level 0 generates INVALID_VALUE
1112 glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
1113 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1114
1115 // Check that an NPOT texture on level 0 succeeds
1116 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
1117 EXPECT_GL_NO_ERROR();
1118
1119 // Check that generateMipmap fails on NPOT
1120 glGenerateMipmap(GL_TEXTURE_2D);
1121 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1122
1123 // Check that nothing is drawn if filtering is not correct for NPOT
1124 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1125 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1126 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1128 glClear(GL_COLOR_BUFFER_BIT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001129 drawQuad(mProgram, "position", 1.0f);
Austin Kinross07285142015-03-26 11:36:16 -07001130 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
1131
1132 // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
1133 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
1136 glClear(GL_COLOR_BUFFER_BIT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001137 drawQuad(mProgram, "position", 1.0f);
Austin Kinross07285142015-03-26 11:36:16 -07001138 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
1139
1140 // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw
1141 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1142 glClear(GL_COLOR_BUFFER_BIT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001143 drawQuad(mProgram, "position", 1.0f);
Austin Kinross07285142015-03-26 11:36:16 -07001144 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
1145
1146 // Check that glTexImage2D for POT texture succeeds
1147 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
1148 EXPECT_GL_NO_ERROR();
1149
1150 // Check that generateMipmap for an POT texture succeeds
1151 glGenerateMipmap(GL_TEXTURE_2D);
1152 EXPECT_GL_NO_ERROR();
1153
1154 // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw
1155 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1156 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1157 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1158 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1159 glClear(GL_COLOR_BUFFER_BIT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001160 drawQuad(mProgram, "position", 1.0f);
Austin Kinross07285142015-03-26 11:36:16 -07001161 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
1162 EXPECT_GL_NO_ERROR();
1163}
Jamie Madillfa05f602015-05-07 13:47:11 -04001164
Austin Kinross08528e12015-10-07 16:24:40 -07001165// Test to ensure that glTexSubImage2D always accepts data for non-power-of-two subregions.
1166// ANGLE previously rejected this if GL_OES_texture_npot wasn't active, which is incorrect.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001167TEST_P(Texture2DTest, NPOTSubImageParameters)
Austin Kinross08528e12015-10-07 16:24:40 -07001168{
1169 glActiveTexture(GL_TEXTURE0);
1170 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1171
1172 // Create an 8x8 (i.e. power-of-two) texture.
1173 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
1175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1176 glGenerateMipmap(GL_TEXTURE_2D);
1177
1178 // Supply a 3x3 (i.e. non-power-of-two) subimage to the texture.
1179 // This should always work, even if GL_OES_texture_npot isn't active.
1180 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1181
1182 EXPECT_GL_NO_ERROR();
1183}
1184
Jamie Madill2453dbc2015-07-14 11:35:42 -04001185// In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG RBA->RGBA8, with 1.0
1186// in the alpha channel. This test covers a bug where redefining array textures with these formats does not work as
1187// expected.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001188TEST_P(Texture2DArrayTestES3, RedefineInittableArray)
Jamie Madill2453dbc2015-07-14 11:35:42 -04001189{
1190 std::vector<GLubyte> pixelData;
1191 for (size_t count = 0; count < 5000; count++)
1192 {
1193 pixelData.push_back(0u);
1194 pixelData.push_back(255u);
1195 pixelData.push_back(0u);
1196 }
1197
1198 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001199 glUseProgram(mProgram);
Jamie Madill2453dbc2015-07-14 11:35:42 -04001200 glUniform1i(mTextureArrayLocation, 0);
1201
1202 // The first draw worked correctly.
1203 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixelData[0]);
1204
1205 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1206 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1207 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
1208 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001209 drawQuad(mProgram, "position", 1.0f);
Jamie Madill2453dbc2015-07-14 11:35:42 -04001210 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
1211
1212 // The dimension of the respecification must match the original exactly to trigger the bug.
1213 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 +02001214 drawQuad(mProgram, "position", 1.0f);
Jamie Madill2453dbc2015-07-14 11:35:42 -04001215 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
1216
1217 ASSERT_GL_NO_ERROR();
1218}
1219
Olli Etuaho1a679902016-01-14 12:21:47 +02001220// Test shadow sampler and regular non-shadow sampler coexisting in the same shader.
1221// This test is needed especially to confirm that sampler registers get assigned correctly on
1222// the HLSL backend even when there's a mix of different HLSL sampler and texture types.
1223TEST_P(ShadowSamplerPlusSampler3DTestES3, ShadowSamplerPlusSampler3DDraw)
1224{
1225 glActiveTexture(GL_TEXTURE0);
1226 glBindTexture(GL_TEXTURE_3D, mTexture3D);
1227 GLubyte texData[4];
1228 texData[0] = 0;
1229 texData[1] = 60;
1230 texData[2] = 0;
1231 texData[3] = 255;
1232 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1233
1234 glActiveTexture(GL_TEXTURE1);
1235 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
1236 GLfloat depthTexData[1];
1237 depthTexData[0] = 0.5f;
1238 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
1239 depthTexData);
1240
1241 glUseProgram(mProgram);
1242 glUniform1f(mDepthRefUniformLocation, 0.3f);
1243 glUniform1i(mTexture3DUniformLocation, 0);
1244 glUniform1i(mTextureShadowUniformLocation, 1);
1245
1246 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
1247 drawQuad(mProgram, "position", 0.5f);
1248 EXPECT_GL_NO_ERROR();
1249 // The shader writes 0.5 * <comparison result (1.0)> + <texture color>
1250 EXPECT_PIXEL_NEAR(0, 0, 128, 188, 128, 255, 2);
1251
1252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);
1253 drawQuad(mProgram, "position", 0.5f);
1254 EXPECT_GL_NO_ERROR();
1255 // The shader writes 0.5 * <comparison result (0.0)> + <texture color>
1256 EXPECT_PIXEL_NEAR(0, 0, 0, 60, 0, 255, 2);
1257}
1258
Olli Etuahoc8c99a02016-01-14 16:47:22 +02001259// Test multiple different sampler types in the same shader.
1260// This test makes sure that even if sampler / texture registers get grouped together based on type
1261// or otherwise get shuffled around in the HLSL backend of the shader translator, the D3D renderer
1262// still has the right register index information for each ESSL sampler.
1263// The tested ESSL samplers have the following types in D3D11 HLSL:
1264// sampler2D: Texture2D + SamplerState
1265// samplerCube: TextureCube + SamplerState
1266// sampler2DShadow: Texture2D + SamplerComparisonState
1267// samplerCubeShadow: TextureCube + SamplerComparisonState
1268TEST_P(SamplerTypeMixTestES3, SamplerTypeMixDraw)
1269{
1270 glActiveTexture(GL_TEXTURE0);
1271 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1272 GLubyte texData[4];
1273 texData[0] = 0;
1274 texData[1] = 0;
1275 texData[2] = 120;
1276 texData[3] = 255;
1277 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1278
1279 glActiveTexture(GL_TEXTURE1);
1280 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
1281 texData[0] = 0;
1282 texData[1] = 90;
1283 texData[2] = 0;
1284 texData[3] = 255;
1285 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
1286 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
1287 texData);
1288
1289 glActiveTexture(GL_TEXTURE2);
1290 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
1291 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
1292 GLfloat depthTexData[1];
1293 depthTexData[0] = 0.5f;
1294 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
1295 depthTexData);
1296
1297 glActiveTexture(GL_TEXTURE3);
1298 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
1299 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
1300 depthTexData[0] = 0.2f;
1301 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT32F, 1, 1);
1302 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT,
1303 depthTexData);
1304
1305 EXPECT_GL_NO_ERROR();
1306
1307 glUseProgram(mProgram);
1308 glUniform1f(mDepthRefUniformLocation, 0.3f);
1309 glUniform1i(mTexture2DUniformLocation, 0);
1310 glUniform1i(mTextureCubeUniformLocation, 1);
1311 glUniform1i(mTexture2DShadowUniformLocation, 2);
1312 glUniform1i(mTextureCubeShadowUniformLocation, 3);
1313
1314 drawQuad(mProgram, "position", 0.5f);
1315 EXPECT_GL_NO_ERROR();
1316 // The shader writes:
1317 // <texture 2d color> +
1318 // <cube map color> +
1319 // 0.25 * <comparison result (1.0)> +
1320 // 0.125 * <comparison result (0.0)>
1321 EXPECT_PIXEL_NEAR(0, 0, 64, 154, 184, 255, 2);
1322}
1323
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001324class TextureLimitsTest : public ANGLETest
1325{
1326 protected:
1327 struct RGBA8
1328 {
1329 uint8_t R, G, B, A;
1330 };
1331
1332 TextureLimitsTest()
1333 : mProgram(0), mMaxVertexTextures(0), mMaxFragmentTextures(0), mMaxCombinedTextures(0)
1334 {
1335 setWindowWidth(128);
1336 setWindowHeight(128);
1337 setConfigRedBits(8);
1338 setConfigGreenBits(8);
1339 setConfigBlueBits(8);
1340 setConfigAlphaBits(8);
1341 }
1342
1343 ~TextureLimitsTest()
1344 {
1345 if (mProgram != 0)
1346 {
1347 glDeleteProgram(mProgram);
1348 mProgram = 0;
1349
1350 if (!mTextures.empty())
1351 {
1352 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), &mTextures[0]);
1353 }
1354 }
1355 }
1356
1357 void SetUp() override
1358 {
1359 ANGLETest::SetUp();
1360
1361 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mMaxVertexTextures);
1362 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mMaxFragmentTextures);
1363 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxCombinedTextures);
1364
1365 ASSERT_GL_NO_ERROR();
1366 }
1367
1368 void compileProgramWithTextureCounts(const std::string &vertexPrefix,
1369 GLint vertexTextureCount,
1370 GLint vertexActiveTextureCount,
1371 const std::string &fragPrefix,
1372 GLint fragmentTextureCount,
1373 GLint fragmentActiveTextureCount)
1374 {
1375 std::stringstream vertexShaderStr;
1376 vertexShaderStr << "attribute vec2 position;\n"
1377 << "varying vec4 color;\n"
1378 << "varying vec2 texCoord;\n";
1379
1380 for (GLint textureIndex = 0; textureIndex < vertexTextureCount; ++textureIndex)
1381 {
1382 vertexShaderStr << "uniform sampler2D " << vertexPrefix << textureIndex << ";\n";
1383 }
1384
1385 vertexShaderStr << "void main() {\n"
1386 << " gl_Position = vec4(position, 0, 1);\n"
1387 << " texCoord = (position * 0.5) + 0.5;\n"
1388 << " color = vec4(0);\n";
1389
1390 for (GLint textureIndex = 0; textureIndex < vertexActiveTextureCount; ++textureIndex)
1391 {
1392 vertexShaderStr << " color += texture2D(" << vertexPrefix << textureIndex
1393 << ", texCoord);\n";
1394 }
1395
1396 vertexShaderStr << "}";
1397
1398 std::stringstream fragmentShaderStr;
1399 fragmentShaderStr << "varying mediump vec4 color;\n"
1400 << "varying mediump vec2 texCoord;\n";
1401
1402 for (GLint textureIndex = 0; textureIndex < fragmentTextureCount; ++textureIndex)
1403 {
1404 fragmentShaderStr << "uniform sampler2D " << fragPrefix << textureIndex << ";\n";
1405 }
1406
1407 fragmentShaderStr << "void main() {\n"
1408 << " gl_FragColor = color;\n";
1409
1410 for (GLint textureIndex = 0; textureIndex < fragmentActiveTextureCount; ++textureIndex)
1411 {
1412 fragmentShaderStr << " gl_FragColor += texture2D(" << fragPrefix << textureIndex
1413 << ", texCoord);\n";
1414 }
1415
1416 fragmentShaderStr << "}";
1417
1418 const std::string &vertexShaderSource = vertexShaderStr.str();
1419 const std::string &fragmentShaderSource = fragmentShaderStr.str();
1420
1421 mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
1422 }
1423
1424 RGBA8 getPixel(GLint texIndex)
1425 {
1426 RGBA8 pixel = {static_cast<uint8_t>(texIndex & 0x7u), static_cast<uint8_t>(texIndex >> 3),
1427 0, 255u};
1428 return pixel;
1429 }
1430
1431 void initTextures(GLint tex2DCount, GLint texCubeCount)
1432 {
1433 GLint totalCount = tex2DCount + texCubeCount;
1434 mTextures.assign(totalCount, 0);
1435 glGenTextures(totalCount, &mTextures[0]);
1436 ASSERT_GL_NO_ERROR();
1437
1438 std::vector<RGBA8> texData(16 * 16);
1439
1440 GLint texIndex = 0;
1441 for (; texIndex < tex2DCount; ++texIndex)
1442 {
1443 texData.assign(texData.size(), getPixel(texIndex));
1444 glActiveTexture(GL_TEXTURE0 + texIndex);
1445 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
1446 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1447 &texData[0]);
1448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1450 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1451 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1452 }
1453
1454 ASSERT_GL_NO_ERROR();
1455
1456 for (; texIndex < texCubeCount; ++texIndex)
1457 {
1458 texData.assign(texData.size(), getPixel(texIndex));
1459 glActiveTexture(GL_TEXTURE0 + texIndex);
1460 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[texIndex]);
1461 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1462 GL_UNSIGNED_BYTE, &texData[0]);
1463 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1464 GL_UNSIGNED_BYTE, &texData[0]);
1465 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1466 GL_UNSIGNED_BYTE, &texData[0]);
1467 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1468 GL_UNSIGNED_BYTE, &texData[0]);
1469 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1470 GL_UNSIGNED_BYTE, &texData[0]);
1471 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
1472 GL_UNSIGNED_BYTE, &texData[0]);
1473 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1474 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1475 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1476 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1477 }
1478
1479 ASSERT_GL_NO_ERROR();
1480 }
1481
1482 void testWithTextures(GLint vertexTextureCount,
1483 const std::string &vertexTexturePrefix,
1484 GLint fragmentTextureCount,
1485 const std::string &fragmentTexturePrefix)
1486 {
1487 // Generate textures
1488 initTextures(vertexTextureCount + fragmentTextureCount, 0);
1489
1490 glUseProgram(mProgram);
1491 RGBA8 expectedSum = {0};
1492 for (GLint texIndex = 0; texIndex < vertexTextureCount; ++texIndex)
1493 {
1494 std::stringstream uniformNameStr;
1495 uniformNameStr << vertexTexturePrefix << texIndex;
1496 const std::string &uniformName = uniformNameStr.str();
1497 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
1498 ASSERT_NE(-1, location);
1499
1500 glUniform1i(location, texIndex);
1501 RGBA8 contribution = getPixel(texIndex);
1502 expectedSum.R += contribution.R;
1503 expectedSum.G += contribution.G;
1504 }
1505
1506 for (GLint texIndex = 0; texIndex < fragmentTextureCount; ++texIndex)
1507 {
1508 std::stringstream uniformNameStr;
1509 uniformNameStr << fragmentTexturePrefix << texIndex;
1510 const std::string &uniformName = uniformNameStr.str();
1511 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
1512 ASSERT_NE(-1, location);
1513
1514 glUniform1i(location, texIndex + vertexTextureCount);
1515 RGBA8 contribution = getPixel(texIndex + vertexTextureCount);
1516 expectedSum.R += contribution.R;
1517 expectedSum.G += contribution.G;
1518 }
1519
1520 ASSERT_GE(256u, expectedSum.G);
1521
1522 drawQuad(mProgram, "position", 0.5f);
1523 ASSERT_GL_NO_ERROR();
1524 EXPECT_PIXEL_EQ(0, 0, expectedSum.R, expectedSum.G, 0, 255);
1525 }
1526
1527 GLuint mProgram;
1528 std::vector<GLuint> mTextures;
1529 GLint mMaxVertexTextures;
1530 GLint mMaxFragmentTextures;
1531 GLint mMaxCombinedTextures;
1532};
1533
1534// Test rendering with the maximum vertex texture units.
1535TEST_P(TextureLimitsTest, MaxVertexTextures)
1536{
Jamie Madill1ea9aaa2015-10-07 11:13:55 -04001537 // TODO(jmadill): Figure out why this fails on Intel.
1538 if (isIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
1539 {
1540 std::cout << "Test skipped on Intel." << std::endl;
1541 return;
1542 }
1543
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001544 compileProgramWithTextureCounts("tex", mMaxVertexTextures, mMaxVertexTextures, "tex", 0, 0);
1545 ASSERT_NE(0u, mProgram);
1546 ASSERT_GL_NO_ERROR();
1547
1548 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
1549}
1550
1551// Test rendering with the maximum fragment texture units.
1552TEST_P(TextureLimitsTest, MaxFragmentTextures)
1553{
Jamie Madill1ea9aaa2015-10-07 11:13:55 -04001554 // TODO(jmadill): Figure out why this fails on Intel.
1555 if (isIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
1556 {
1557 std::cout << "Test skipped on Intel." << std::endl;
1558 return;
1559 }
1560
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001561 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures, mMaxFragmentTextures);
1562 ASSERT_NE(0u, mProgram);
1563 ASSERT_GL_NO_ERROR();
1564
1565 testWithTextures(mMaxFragmentTextures, "tex", 0, "tex");
1566}
1567
1568// Test rendering with maximum combined texture units.
1569TEST_P(TextureLimitsTest, MaxCombinedTextures)
1570{
Jamie Madill412f17d2015-09-25 08:43:54 -04001571 // TODO(jmadill): Investigate workaround.
1572 if (isIntel() && GetParam() == ES2_OPENGL())
1573 {
1574 std::cout << "Test skipped on Intel." << std::endl;
1575 return;
1576 }
1577
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001578 GLint vertexTextures = mMaxVertexTextures;
1579
1580 if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
1581 {
1582 vertexTextures = mMaxCombinedTextures - mMaxFragmentTextures;
1583 }
1584
1585 compileProgramWithTextureCounts("vtex", vertexTextures, vertexTextures, "ftex",
1586 mMaxFragmentTextures, mMaxFragmentTextures);
1587 ASSERT_NE(0u, mProgram);
1588 ASSERT_GL_NO_ERROR();
1589
1590 testWithTextures(vertexTextures, "vtex", mMaxFragmentTextures, "ftex");
1591}
1592
1593// Negative test for exceeding the number of vertex textures
1594TEST_P(TextureLimitsTest, ExcessiveVertexTextures)
1595{
1596 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 1, mMaxVertexTextures + 1, "tex", 0,
1597 0);
1598 ASSERT_EQ(0u, mProgram);
1599}
1600
1601// Negative test for exceeding the number of fragment textures
1602TEST_P(TextureLimitsTest, ExcessiveFragmentTextures)
1603{
1604 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 1,
1605 mMaxFragmentTextures + 1);
1606 ASSERT_EQ(0u, mProgram);
1607}
1608
1609// Test active vertex textures under the limit, but excessive textures specified.
1610TEST_P(TextureLimitsTest, MaxActiveVertexTextures)
1611{
Jamie Madill1ea9aaa2015-10-07 11:13:55 -04001612 // TODO(jmadill): Figure out why this fails on Intel.
1613 if (isIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
1614 {
1615 std::cout << "Test skipped on Intel." << std::endl;
1616 return;
1617 }
1618
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001619 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 4, mMaxVertexTextures, "tex", 0, 0);
1620 ASSERT_NE(0u, mProgram);
1621 ASSERT_GL_NO_ERROR();
1622
1623 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
1624}
1625
1626// Test active fragment textures under the limit, but excessive textures specified.
1627TEST_P(TextureLimitsTest, MaxActiveFragmentTextures)
1628{
Jamie Madill1ea9aaa2015-10-07 11:13:55 -04001629 // TODO(jmadill): Figure out why this fails on Intel.
1630 if (isIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
1631 {
1632 std::cout << "Test skipped on Intel." << std::endl;
1633 return;
1634 }
1635
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001636 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 4,
1637 mMaxFragmentTextures);
1638 ASSERT_NE(0u, mProgram);
1639 ASSERT_GL_NO_ERROR();
1640
1641 testWithTextures(0, "tex", mMaxFragmentTextures, "tex");
1642}
1643
1644// Negative test for pointing two sampler uniforms of different types to the same texture.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001645// GLES 2.0.25 section 2.10.4 page 39.
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001646TEST_P(TextureLimitsTest, TextureTypeConflict)
1647{
1648 const std::string &vertexShader =
1649 "attribute vec2 position;\n"
1650 "varying float color;\n"
1651 "uniform sampler2D tex2D;\n"
1652 "uniform samplerCube texCube;\n"
1653 "void main() {\n"
1654 " gl_Position = vec4(position, 0, 1);\n"
1655 " vec2 texCoord = (position * 0.5) + 0.5;\n"
1656 " color = texture2D(tex2D, texCoord).x;\n"
1657 " color += textureCube(texCube, vec3(texCoord, 0)).x;\n"
1658 "}";
1659 const std::string &fragmentShader =
1660 "varying mediump float color;\n"
1661 "void main() {\n"
1662 " gl_FragColor = vec4(color, 0, 0, 1);\n"
1663 "}";
1664
1665 mProgram = CompileProgram(vertexShader, fragmentShader);
1666 ASSERT_NE(0u, mProgram);
1667
1668 initTextures(1, 0);
1669
1670 glUseProgram(mProgram);
1671 GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
1672 ASSERT_NE(-1, tex2DLocation);
1673 GLint texCubeLocation = glGetUniformLocation(mProgram, "texCube");
1674 ASSERT_NE(-1, texCubeLocation);
1675
1676 glUniform1i(tex2DLocation, 0);
1677 glUniform1i(texCubeLocation, 0);
1678 ASSERT_GL_NO_ERROR();
1679
1680 drawQuad(mProgram, "position", 0.5f);
1681 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1682}
1683
1684// Negative test for rendering with texture outside the valid range.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001685// TODO(jmadill): Possibly adjust the test according to the spec:
1686// GLES 3.0.4 section 2.12.7 mentions that specifying an out-of-range sampler uniform value
1687// generates an INVALID_VALUE error - GLES 2.0 doesn't yet have this mention.
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001688TEST_P(TextureLimitsTest, DrawWithTexturePastMaximum)
1689{
1690 const std::string &vertexShader =
1691 "attribute vec2 position;\n"
1692 "varying float color;\n"
1693 "uniform sampler2D tex2D;\n"
1694 "void main() {\n"
1695 " gl_Position = vec4(position, 0, 1);\n"
1696 " vec2 texCoord = (position * 0.5) + 0.5;\n"
1697 " color = texture2D(tex2D, texCoord).x;\n"
1698 "}";
1699 const std::string &fragmentShader =
1700 "varying mediump float color;\n"
1701 "void main() {\n"
1702 " gl_FragColor = vec4(color, 0, 0, 1);\n"
1703 "}";
1704
1705 mProgram = CompileProgram(vertexShader, fragmentShader);
1706 ASSERT_NE(0u, mProgram);
1707
1708 glUseProgram(mProgram);
1709 GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
1710 ASSERT_NE(-1, tex2DLocation);
1711
1712 glUniform1i(tex2DLocation, mMaxCombinedTextures);
1713 ASSERT_GL_NO_ERROR();
1714
1715 drawQuad(mProgram, "position", 0.5f);
1716 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1717}
1718
Jamie Madillfa05f602015-05-07 13:47:11 -04001719// 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 +02001720// TODO(oetuaho): Enable all below tests on OpenGL. Requires a fix for ANGLE bug 1278.
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001721ANGLE_INSTANTIATE_TEST(Texture2DTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3());
Olli Etuaho51f1c0f2016-01-13 16:16:24 +02001722ANGLE_INSTANTIATE_TEST(TextureCubeTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3(), ES2_OPENGL());
1723ANGLE_INSTANTIATE_TEST(Texture2DTestWithDrawScale,
1724 ES2_D3D9(),
1725 ES2_D3D11(),
1726 ES2_D3D11_FL9_3(),
1727 ES2_OPENGL());
1728ANGLE_INSTANTIATE_TEST(Sampler2DAsFunctionParameterTest,
1729 ES2_D3D9(),
1730 ES2_D3D11(),
1731 ES2_D3D11_FL9_3(),
1732 ES2_OPENGL());
1733ANGLE_INSTANTIATE_TEST(SamplerArrayTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3(), ES2_OPENGL());
Olli Etuaho2173db3d2016-01-12 13:55:14 +02001734ANGLE_INSTANTIATE_TEST(SamplerArrayAsFunctionParameterTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3());
Olli Etuaho1a679902016-01-14 12:21:47 +02001735ANGLE_INSTANTIATE_TEST(ShadowSamplerPlusSampler3DTestES3, ES3_D3D11(), ES3_OPENGL());
Olli Etuahoc8c99a02016-01-14 16:47:22 +02001736ANGLE_INSTANTIATE_TEST(SamplerTypeMixTestES3, ES3_D3D11(), ES3_OPENGL());
Olli Etuaho4a8329f2016-01-11 17:12:57 +02001737ANGLE_INSTANTIATE_TEST(Texture2DArrayTestES3, ES3_D3D11(), ES3_OPENGL());
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001738ANGLE_INSTANTIATE_TEST(TextureLimitsTest, ES2_D3D11(), ES2_OPENGL());
Jamie Madillfa05f602015-05-07 13:47:11 -04001739
1740} // namespace