1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "common/mathutil.h"
8 #include "test_utils/ANGLETest.h"
9 #include "test_utils/gl_raii.h"
10
11 using namespace angle;
12
13 namespace
14 {
15
16 constexpr GLuint kPixelTolerance = 1u;
17 constexpr GLfloat kPixelTolerance32F = 0.01f;
18
19 // Single compressed ETC2 block of source pixels all set red
20 constexpr uint8_t kCompressedImageETC2[] = {0x7E, 0x80, 0x04, 0x7F, 0x00, 0x07, 0xE0, 0x00};
21
22 // Take a pixel, and reset the components not covered by the format to default
23 // values. In particular, the default value for the alpha component is 255
24 // (1.0 as unsigned normalized fixed point value).
25 // For legacy formats, the components may be reordered to match the color that
26 // would be created if a pixel of that format was initialized from the given color
SliceFormatColor(GLenum format,GLColor full)27 GLColor SliceFormatColor(GLenum format, GLColor full)
28 {
29 switch (format)
30 {
31 case GL_RED:
32 return GLColor(full.R, 0, 0, 255u);
33 case GL_RG:
34 return GLColor(full.R, full.G, 0, 255u);
35 case GL_RGB:
36 return GLColor(full.R, full.G, full.B, 255u);
37 case GL_RGBA:
38 return full;
39 case GL_LUMINANCE:
40 return GLColor(full.R, full.R, full.R, 255u);
41 case GL_ALPHA:
42 return GLColor(0, 0, 0, full.R);
43 case GL_LUMINANCE_ALPHA:
44 return GLColor(full.R, full.R, full.R, full.G);
45 default:
46 EXPECT_TRUE(false);
47 return GLColor::white;
48 }
49 }
50
SliceFormatColor16UI(GLenum format,GLColor16UI full)51 GLColor16UI SliceFormatColor16UI(GLenum format, GLColor16UI full)
52 {
53 switch (format)
54 {
55 case GL_RED:
56 return GLColor16UI(full.R, 0, 0, 0xFFFF);
57 case GL_RG:
58 return GLColor16UI(full.R, full.G, 0, 0xFFFF);
59 case GL_RGB:
60 return GLColor16UI(full.R, full.G, full.B, 0xFFFF);
61 case GL_RGBA:
62 return full;
63 case GL_LUMINANCE:
64 return GLColor16UI(full.R, full.R, full.R, 0xFFFF);
65 case GL_ALPHA:
66 return GLColor16UI(0, 0, 0, full.R);
67 case GL_LUMINANCE_ALPHA:
68 return GLColor16UI(full.R, full.R, full.R, full.G);
69 default:
70 EXPECT_TRUE(false);
71 return GLColor16UI(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
72 }
73 }
74
75 // As above, for 32F colors
SliceFormatColor32F(GLenum format,GLColor32F full)76 GLColor32F SliceFormatColor32F(GLenum format, GLColor32F full)
77 {
78 switch (format)
79 {
80 case GL_RED:
81 return GLColor32F(full.R, 0.0f, 0.0f, 1.0f);
82 case GL_RG:
83 return GLColor32F(full.R, full.G, 0.0f, 1.0f);
84 case GL_RGB:
85 return GLColor32F(full.R, full.G, full.B, 1.0f);
86 case GL_RGBA:
87 return full;
88 case GL_LUMINANCE:
89 return GLColor32F(full.R, full.R, full.R, 1.0f);
90 case GL_ALPHA:
91 return GLColor32F(0.0f, 0.0f, 0.0f, full.R);
92 case GL_LUMINANCE_ALPHA:
93 return GLColor32F(full.R, full.R, full.R, full.G);
94 default:
95 EXPECT_TRUE(false);
96 return GLColor32F(1.0f, 1.0f, 1.0f, 1.0f);
97 }
98 }
99
100 class TexCoordDrawTest : public ANGLETest<>
101 {
102 protected:
TexCoordDrawTest()103 TexCoordDrawTest() : ANGLETest(), mProgram(0), mFramebuffer(0), mFramebufferColorTexture(0)
104 {
105 setWindowWidth(128);
106 setWindowHeight(128);
107 setConfigRedBits(8);
108 setConfigGreenBits(8);
109 setConfigBlueBits(8);
110 setConfigAlphaBits(8);
111 }
112
getVertexShaderSource()113 virtual const char *getVertexShaderSource()
114 {
115 return R"(precision highp float;
116 attribute vec4 position;
117 varying vec2 texcoord;
118
119 void main()
120 {
121 gl_Position = vec4(position.xy, 0.0, 1.0);
122 texcoord = (position.xy * 0.5) + 0.5;
123 })";
124 }
125
126 virtual const char *getFragmentShaderSource() = 0;
127
setUpProgram()128 virtual void setUpProgram()
129 {
130 const char *vertexShaderSource = getVertexShaderSource();
131 const char *fragmentShaderSource = getFragmentShaderSource();
132
133 mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
134 ASSERT_NE(0u, mProgram);
135 ASSERT_GL_NO_ERROR();
136 }
137
testSetUp()138 void testSetUp() override { setUpFramebuffer(); }
139
testTearDown()140 void testTearDown() override
141 {
142 glBindFramebuffer(GL_FRAMEBUFFER, 0);
143 glDeleteFramebuffers(1, &mFramebuffer);
144 glDeleteTextures(1, &mFramebufferColorTexture);
145 glDeleteProgram(mProgram);
146 }
147
setUpFramebuffer()148 void setUpFramebuffer()
149 {
150 // We use an FBO to work around an issue where the default framebuffer applies SRGB
151 // conversion (particularly known to happen incorrectly on Intel GL drivers). It's not
152 // clear whether this issue can even be fixed on all backends. For example GLES 3.0.4 spec
153 // section 4.4 says that the format of the default framebuffer is entirely up to the window
154 // system, so it might be SRGB, and GLES 3.0 doesn't have a "FRAMEBUFFER_SRGB" to turn off
155 // SRGB conversion like desktop GL does.
156 // TODO(oetuaho): Get rid of this if the underlying issue is fixed.
157 glGenFramebuffers(1, &mFramebuffer);
158 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
159
160 glGenTextures(1, &mFramebufferColorTexture);
161 glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
162 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
163 GL_UNSIGNED_BYTE, nullptr);
164 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
165 mFramebufferColorTexture, 0);
166 ASSERT_GL_NO_ERROR();
167 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
168 glBindTexture(GL_TEXTURE_2D, 0);
169 }
170
171 // Returns the created texture ID.
create2DTexture()172 GLuint create2DTexture()
173 {
174 GLuint texture2D;
175 glGenTextures(1, &texture2D);
176 glBindTexture(GL_TEXTURE_2D, texture2D);
177 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
178 EXPECT_GL_NO_ERROR();
179 return texture2D;
180 }
181
182 GLuint mProgram;
183 GLuint mFramebuffer;
184
185 private:
186 GLuint mFramebufferColorTexture;
187 };
188
189 class Texture2DTest : public TexCoordDrawTest
190 {
191 protected:
Texture2DTest()192 Texture2DTest() : TexCoordDrawTest(), mTexture2D(0), mTexture2DUniformLocation(-1) {}
193
getFragmentShaderSource()194 const char *getFragmentShaderSource() override
195 {
196 return R"(precision highp float;
197 uniform sampler2D tex;
198 varying vec2 texcoord;
199
200 void main()
201 {
202 gl_FragColor = texture2D(tex, texcoord);
203 })";
204 }
205
getTextureUniformName()206 virtual const char *getTextureUniformName() { return "tex"; }
207
setUpProgram()208 void setUpProgram() override
209 {
210 TexCoordDrawTest::setUpProgram();
211 mTexture2DUniformLocation = glGetUniformLocation(mProgram, getTextureUniformName());
212 ASSERT_NE(-1, mTexture2DUniformLocation);
213 }
214
testSetUp()215 void testSetUp() override
216 {
217 TexCoordDrawTest::testSetUp();
218 mTexture2D = create2DTexture();
219
220 ASSERT_GL_NO_ERROR();
221 }
222
testTearDown()223 void testTearDown() override
224 {
225 glDeleteTextures(1, &mTexture2D);
226 TexCoordDrawTest::testTearDown();
227 }
228
229 // Tests CopyTexSubImage with floating point textures of various formats.
testFloatCopySubImage(int sourceImageChannels,int destImageChannels)230 void testFloatCopySubImage(int sourceImageChannels, int destImageChannels)
231 {
232 setUpProgram();
233
234 if (getClientMajorVersion() < 3)
235 {
236 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage") ||
237 !IsGLExtensionEnabled("GL_OES_texture_float"));
238
239 ANGLE_SKIP_TEST_IF((sourceImageChannels < 3 || destImageChannels < 3) &&
240 !IsGLExtensionEnabled("GL_EXT_texture_rg"));
241
242 ANGLE_SKIP_TEST_IF(destImageChannels == 3 &&
243 !IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"));
244
245 ANGLE_SKIP_TEST_IF(destImageChannels == 4 &&
246 !IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"));
247
248 ANGLE_SKIP_TEST_IF(destImageChannels <= 2);
249 }
250 else
251 {
252 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_color_buffer_float"));
253
254 ANGLE_SKIP_TEST_IF(destImageChannels == 3 &&
255 !IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"));
256 }
257
258 // clang-format off
259 GLfloat sourceImageData[4][16] =
260 {
261 { // R
262 1.0f,
263 0.0f,
264 0.0f,
265 1.0f
266 },
267 { // RG
268 1.0f, 0.0f,
269 0.0f, 1.0f,
270 0.0f, 0.0f,
271 1.0f, 1.0f
272 },
273 { // RGB
274 1.0f, 0.0f, 0.0f,
275 0.0f, 1.0f, 0.0f,
276 0.0f, 0.0f, 1.0f,
277 1.0f, 1.0f, 0.0f
278 },
279 { // RGBA
280 1.0f, 0.0f, 0.0f, 1.0f,
281 0.0f, 1.0f, 0.0f, 1.0f,
282 0.0f, 0.0f, 1.0f, 1.0f,
283 1.0f, 1.0f, 0.0f, 1.0f
284 },
285 };
286 // clang-format on
287
288 GLenum imageFormats[] = {
289 GL_R32F,
290 GL_RG32F,
291 GL_RGB32F,
292 GL_RGBA32F,
293 };
294
295 GLenum sourceUnsizedFormats[] = {
296 GL_RED,
297 GL_RG,
298 GL_RGB,
299 GL_RGBA,
300 };
301
302 GLTexture textures[2];
303
304 GLfloat *imageData = sourceImageData[sourceImageChannels - 1];
305 GLenum sourceImageFormat = imageFormats[sourceImageChannels - 1];
306 GLenum sourceUnsizedFormat = sourceUnsizedFormats[sourceImageChannels - 1];
307 GLenum destImageFormat = imageFormats[destImageChannels - 1];
308
309 glBindTexture(GL_TEXTURE_2D, textures[0]);
310 if (getClientMajorVersion() >= 3)
311 {
312 glTexStorage2D(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
313 }
314 else
315 {
316 glTexStorage2DEXT(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
317 }
318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
320 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, sourceUnsizedFormat, GL_FLOAT, imageData);
321
322 if (sourceImageChannels < 3 && !IsGLExtensionEnabled("GL_EXT_texture_rg"))
323 {
324 // This is not supported
325 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
326 }
327 else
328 {
329 ASSERT_GL_NO_ERROR();
330 }
331
332 GLuint fbo;
333 glGenFramebuffers(1, &fbo);
334 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
335 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
336
337 glBindTexture(GL_TEXTURE_2D, textures[1]);
338 if (getClientMajorVersion() >= 3)
339 {
340 glTexStorage2D(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
341 }
342 else
343 {
344 glTexStorage2DEXT(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
345 }
346 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
347 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
348
349 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2);
350 ASSERT_GL_NO_ERROR();
351
352 glBindFramebuffer(GL_FRAMEBUFFER, 0);
353 drawQuad(mProgram, "position", 0.5f);
354
355 int testImageChannels = std::min(sourceImageChannels, destImageChannels);
356
357 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
358 if (testImageChannels > 1)
359 {
360 EXPECT_PIXEL_EQ(getWindowHeight() - 1, 0, 0, 255, 0, 255);
361 EXPECT_PIXEL_EQ(getWindowHeight() - 1, getWindowWidth() - 1, 255, 255, 0, 255);
362 if (testImageChannels > 2)
363 {
364 EXPECT_PIXEL_EQ(0, getWindowWidth() - 1, 0, 0, 255, 255);
365 }
366 }
367
368 glDeleteFramebuffers(1, &fbo);
369
370 ASSERT_GL_NO_ERROR();
371 }
372
373 void testTextureSize(int testCaseIndex);
374 void testTextureSizeError();
375
376 struct UploadThenUseStageParam
377 {
378 GLenum useStage;
379 bool closeRenderPassAfterUse;
380 };
381
382 void testUploadThenUseInDifferentStages(const std::vector<UploadThenUseStageParam> &uses);
383
384 GLuint mTexture2D;
385 GLint mTexture2DUniformLocation;
386 };
387
388 class Texture2DTestES3 : public Texture2DTest
389 {
390 protected:
Texture2DTestES3()391 Texture2DTestES3() : Texture2DTest() {}
392
getVertexShaderSource()393 const char *getVertexShaderSource() override
394 {
395 return "#version 300 es\n"
396 "out vec2 texcoord;\n"
397 "in vec4 position;\n"
398 "void main()\n"
399 "{\n"
400 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
401 " texcoord = (position.xy * 0.5) + 0.5;\n"
402 "}\n";
403 }
404
getFragmentShaderSource()405 const char *getFragmentShaderSource() override
406 {
407 return "#version 300 es\n"
408 "precision highp float;\n"
409 "uniform highp sampler2D tex;\n"
410 "in vec2 texcoord;\n"
411 "out vec4 fragColor;\n"
412 "void main()\n"
413 "{\n"
414 " fragColor = texture(tex, texcoord);\n"
415 "}\n";
416 }
417
testSetUp()418 void testSetUp() override
419 {
420 Texture2DTest::testSetUp();
421 setUpProgram();
422 }
423
createImmutableTexture2D(GLuint texture,size_t width,size_t height,GLenum format,GLenum internalFormat,GLenum type,GLsizei levels,GLubyte data[4])424 void createImmutableTexture2D(GLuint texture,
425 size_t width,
426 size_t height,
427 GLenum format,
428 GLenum internalFormat,
429 GLenum type,
430 GLsizei levels,
431 GLubyte data[4])
432 {
433 // Support only 1 level for now
434 ASSERT(levels == 1);
435
436 glBindTexture(GL_TEXTURE_2D, texture);
437
438 glTexStorage2D(GL_TEXTURE_2D, levels, internalFormat, width, height);
439 ASSERT_GL_NO_ERROR();
440
441 if (data != nullptr)
442 {
443 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
444 ASSERT_GL_NO_ERROR();
445 }
446
447 // Disable mipmapping
448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
450 ASSERT_GL_NO_ERROR();
451 }
452
verifyResults2D(GLuint texture,GLubyte referenceColor[4])453 void verifyResults2D(GLuint texture, GLubyte referenceColor[4])
454 {
455 // Draw a quad with the target texture
456 glUseProgram(mProgram);
457 glBindTexture(GL_TEXTURE_2D, texture);
458 glUniform1i(mTexture2DUniformLocation, 0);
459
460 drawQuad(mProgram, "position", 0.5f);
461
462 // Expect that the rendered quad's color is the same as the reference color with a tolerance
463 // of 1
464 EXPECT_PIXEL_NEAR(0, 0, referenceColor[0], referenceColor[1], referenceColor[2],
465 referenceColor[3], 1);
466 }
467 };
468
469 class Texture2DTestES3YUV : public Texture2DTestES3
470 {};
471
472 class Texture2DTestES3RobustInit : public Texture2DTestES3
473 {
474 protected:
Texture2DTestES3RobustInit()475 Texture2DTestES3RobustInit() : Texture2DTestES3() { setRobustResourceInit(true); }
476 };
477
478 class Texture2DBaseMaxTestES3 : public ANGLETest<>
479 {
480 protected:
481 static constexpr size_t kMip0Size = 13;
482 static constexpr uint32_t kMipCount = 4;
483
Texture2DBaseMaxTestES3()484 Texture2DBaseMaxTestES3() : ANGLETest(), mTextureLocation(0), mLodLocation(0)
485 {
486 setWindowWidth(128);
487 setWindowHeight(128);
488 setConfigRedBits(8);
489 setConfigGreenBits(8);
490 setConfigBlueBits(8);
491 setConfigAlphaBits(8);
492 }
493
getMipDataSize(size_t mip0Size,size_t mip)494 static constexpr size_t getMipDataSize(size_t mip0Size, size_t mip)
495 {
496 size_t mipSize = std::max<size_t>(1u, mip0Size >> mip);
497 return mipSize * mipSize;
498 }
499
getTotalMipDataSize(size_t mip0Size)500 static constexpr size_t getTotalMipDataSize(size_t mip0Size)
501 {
502 size_t totalCount = 0;
503 for (size_t mip = 0; mip < kMipCount; ++mip)
504 {
505 totalCount += getMipDataSize(mip0Size, mip);
506 }
507 return totalCount;
508 }
509
getMipDataOffset(size_t mip0Size,size_t mip)510 static constexpr size_t getMipDataOffset(size_t mip0Size, size_t mip)
511 {
512 // This calculates:
513 //
514 // mip == 0: 0
515 // o.w.: sum(0, mip-1) getMipDataSize(i)
516 //
517 // The above can be calculated simply as:
518 //
519 // (mip0 >> (kMipCount-1))^2 * (0x55555555 & ((1 << (2*mip)) - 1))
520 // \__________ ___________/ \_______________ ________________/
521 // \/ \/
522 // last mip size sum(0, mip-1) (4^i)
523 //
524 // But let's loop explicitly for clarity.
525 size_t offset = 0;
526 for (size_t m = 0; m < mip; ++m)
527 {
528 offset += getMipDataSize(mip0Size, m);
529 }
530 return offset;
531 }
532
533 template <typename colorType = GLColor>
fillMipData(colorType * data,size_t mip0Size,const colorType mipColors[kMipCount])534 void fillMipData(colorType *data, size_t mip0Size, const colorType mipColors[kMipCount])
535 {
536 for (size_t mip = 0; mip < kMipCount; ++mip)
537 {
538 size_t offset = getMipDataOffset(mip0Size, mip);
539 size_t size = getMipDataSize(mip0Size, mip);
540 std::fill(data + offset, data + offset + size, mipColors[mip]);
541 }
542 }
543
initTest(bool immutable)544 void initTest(bool immutable)
545 {
546 // Set up program to sample from specific lod level.
547 mProgram.makeRaster(essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
548 ASSERT(mProgram.valid());
549
550 glUseProgram(mProgram);
551
552 mTextureLocation = glGetUniformLocation(mProgram, essl3_shaders::Texture2DUniform());
553 ASSERT_NE(-1, mTextureLocation);
554
555 mLodLocation = glGetUniformLocation(mProgram, essl3_shaders::LodUniform());
556 ASSERT_NE(-1, mLodLocation);
557
558 // Set up texture with a handful of lods.
559 glActiveTexture(GL_TEXTURE0);
560 glBindTexture(GL_TEXTURE_2D, mTexture);
561
562 std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
563 fillMipData(mipData.data(), kMip0Size, kMipColors);
564
565 if (immutable)
566 {
567 glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size);
568 for (size_t mip = 0; mip < kMipCount; ++mip)
569 {
570 glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip,
571 GL_RGBA, GL_UNSIGNED_BYTE,
572 mipData.data() + getMipDataOffset(kMip0Size, mip));
573 }
574 }
575 else
576 {
577 for (size_t mip = 0; mip < kMipCount; ++mip)
578 {
579 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, kMip0Size >> mip, kMip0Size >> mip, 0,
580 GL_RGBA, GL_UNSIGNED_BYTE,
581 mipData.data() + getMipDataOffset(kMip0Size, mip));
582 }
583 }
584
585 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
586 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
587
588 EXPECT_GL_NO_ERROR();
589 }
590
setLodUniform(uint32_t lod)591 void setLodUniform(uint32_t lod) { glUniform1f(mLodLocation, lod); }
592
593 void testPingPongBaseLevel(bool immutable);
594 void testGenerateMipmapAfterRebase(bool immutable);
595
596 GLProgram mProgram;
597 GLTexture mTexture;
598 GLint mTextureLocation;
599 GLint mLodLocation;
600
601 const GLColor kMipColors[kMipCount] = {
602 GLColor::red,
603 GLColor::green,
604 GLColor::blue,
605 GLColor::magenta,
606 };
607 };
608
609 class TextureES31PPO
610 {
611 protected:
TextureES31PPO()612 TextureES31PPO() : mVertProg(0), mFragProg(0), mPipeline(0) {}
613
get2DTexturedVertexShaderSource()614 const char *get2DTexturedVertexShaderSource()
615 {
616 return "#version 310 es\n"
617 "precision mediump float;\n"
618 "in vec2 position;\n"
619 "out vec2 texCoord;\n"
620 "void main()\n"
621 "{\n"
622 " gl_Position = vec4(position, 0, 1);\n"
623 " texCoord = position * 0.5 + vec2(0.5);\n"
624 "}";
625 }
626
get2DTexturedFragmentShaderSource()627 const char *get2DTexturedFragmentShaderSource()
628 {
629 return "#version 310 es\n"
630 "precision mediump float;\n"
631 "in vec2 texCoord;\n"
632 "uniform sampler2D tex1;\n"
633 "uniform sampler2D tex2;\n"
634 "uniform sampler2D tex3;\n"
635 "uniform sampler2D tex4;\n"
636 "out vec4 color;\n"
637 "void main()\n"
638 "{\n"
639 " color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
640 " + texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
641 "}";
642 }
643
bindProgramPipeline(const GLchar * vertString,const GLchar * fragString)644 void bindProgramPipeline(const GLchar *vertString, const GLchar *fragString)
645 {
646 mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertString);
647 ASSERT_NE(mVertProg, 0u);
648 mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
649 ASSERT_NE(mFragProg, 0u);
650
651 // Generate a program pipeline and attach the programs to their respective stages
652 glGenProgramPipelines(1, &mPipeline);
653 EXPECT_GL_NO_ERROR();
654 glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
655 EXPECT_GL_NO_ERROR();
656 glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
657 EXPECT_GL_NO_ERROR();
658 glBindProgramPipeline(mPipeline);
659 EXPECT_GL_NO_ERROR();
660 }
661
bind2DTexturedQuadProgramPipeline()662 void bind2DTexturedQuadProgramPipeline()
663 {
664 const char *vertexShaderSource = get2DTexturedVertexShaderSource();
665 const char *fragmentShaderSource = get2DTexturedFragmentShaderSource();
666
667 m2DTexturedQuadVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertexShaderSource);
668 ASSERT_NE(m2DTexturedQuadVertProg, 0u);
669 m2DTexturedQuadFragProg =
670 glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragmentShaderSource);
671 ASSERT_NE(m2DTexturedQuadFragProg, 0u);
672
673 // Generate a program pipeline and attach the programs to their respective stages
674 glGenProgramPipelines(1, &m2DTexturedQuadPipeline);
675 EXPECT_GL_NO_ERROR();
676 glUseProgramStages(m2DTexturedQuadPipeline, GL_VERTEX_SHADER_BIT, m2DTexturedQuadVertProg);
677 EXPECT_GL_NO_ERROR();
678 glUseProgramStages(m2DTexturedQuadPipeline, GL_FRAGMENT_SHADER_BIT,
679 m2DTexturedQuadFragProg);
680 EXPECT_GL_NO_ERROR();
681 glBindProgramPipeline(m2DTexturedQuadPipeline);
682 EXPECT_GL_NO_ERROR();
683 }
684
ppoDrawQuad(std::array<Vector3,6> & quadVertices,const std::string & positionAttribName,const GLfloat positionAttribZ,const GLfloat positionAttribXYScale)685 void ppoDrawQuad(std::array<Vector3, 6> &quadVertices,
686 const std::string &positionAttribName,
687 const GLfloat positionAttribZ,
688 const GLfloat positionAttribXYScale)
689 {
690 glUseProgram(0);
691
692 for (Vector3 &vertex : quadVertices)
693 {
694 vertex.x() *= positionAttribXYScale;
695 vertex.y() *= positionAttribXYScale;
696 vertex.z() = positionAttribZ;
697 }
698
699 GLint positionLocation = glGetAttribLocation(mVertProg, positionAttribName.c_str());
700
701 glBindBuffer(GL_ARRAY_BUFFER, 0);
702 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
703 glEnableVertexAttribArray(positionLocation);
704
705 glDrawArrays(GL_TRIANGLES, 0, 6);
706
707 glDisableVertexAttribArray(positionLocation);
708 glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
709 }
710
711 GLuint mVertProg;
712 GLuint mFragProg;
713 GLuint mPipeline;
714 GLuint m2DTexturedQuadVertProg;
715 GLuint m2DTexturedQuadFragProg;
716 GLuint m2DTexturedQuadPipeline;
717 };
718
719 class Texture2DTestES31PPO : public TextureES31PPO, public Texture2DTest
720 {
721 protected:
Texture2DTestES31PPO()722 Texture2DTestES31PPO() : TextureES31PPO(), Texture2DTest() {}
723
testSetUp()724 void testSetUp() override { Texture2DTest::testSetUp(); }
725 };
726
727 class Texture2DIntegerAlpha1TestES3 : public Texture2DTest
728 {
729 protected:
Texture2DIntegerAlpha1TestES3()730 Texture2DIntegerAlpha1TestES3() : Texture2DTest() {}
731
getVertexShaderSource()732 const char *getVertexShaderSource() override
733 {
734 return "#version 300 es\n"
735 "out vec2 texcoord;\n"
736 "in vec4 position;\n"
737 "void main()\n"
738 "{\n"
739 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
740 " texcoord = (position.xy * 0.5) + 0.5;\n"
741 "}\n";
742 }
743
getFragmentShaderSource()744 const char *getFragmentShaderSource() override
745 {
746 return "#version 300 es\n"
747 "precision highp float;\n"
748 "uniform highp isampler2D tex;\n"
749 "in vec2 texcoord;\n"
750 "out vec4 fragColor;\n"
751 "void main()\n"
752 "{\n"
753 " vec4 green = vec4(0, 1, 0, 1);\n"
754 " vec4 black = vec4(0, 0, 0, 0);\n"
755 " fragColor = (texture(tex, texcoord).a == 1) ? green : black;\n"
756 "}\n";
757 }
758
testSetUp()759 void testSetUp() override
760 {
761 Texture2DTest::testSetUp();
762 setUpProgram();
763 }
764 };
765
766 class Texture2DUnsignedIntegerAlpha1TestES3 : public Texture2DTest
767 {
768 protected:
Texture2DUnsignedIntegerAlpha1TestES3()769 Texture2DUnsignedIntegerAlpha1TestES3() : Texture2DTest() {}
770
getVertexShaderSource()771 const char *getVertexShaderSource() override
772 {
773 return "#version 300 es\n"
774 "out vec2 texcoord;\n"
775 "in vec4 position;\n"
776 "void main()\n"
777 "{\n"
778 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
779 " texcoord = (position.xy * 0.5) + 0.5;\n"
780 "}\n";
781 }
782
getFragmentShaderSource()783 const char *getFragmentShaderSource() override
784 {
785 return "#version 300 es\n"
786 "precision highp float;\n"
787 "uniform highp usampler2D tex;\n"
788 "in vec2 texcoord;\n"
789 "out vec4 fragColor;\n"
790 "void main()\n"
791 "{\n"
792 " vec4 green = vec4(0, 1, 0, 1);\n"
793 " vec4 black = vec4(0, 0, 0, 0);\n"
794 " fragColor = (texture(tex, texcoord).a == 1u) ? green : black;\n"
795 "}\n";
796 }
797
testSetUp()798 void testSetUp() override
799 {
800 Texture2DTest::testSetUp();
801 setUpProgram();
802 }
803 };
804
805 class Texture2DTestWithDrawScale : public Texture2DTest
806 {
807 protected:
Texture2DTestWithDrawScale()808 Texture2DTestWithDrawScale() : Texture2DTest(), mDrawScaleUniformLocation(-1) {}
809
getVertexShaderSource()810 const char *getVertexShaderSource() override
811 {
812 return
813 R"(precision highp float;
814 attribute vec4 position;
815 varying vec2 texcoord;
816
817 uniform vec2 drawScale;
818
819 void main()
820 {
821 gl_Position = vec4(position.xy * drawScale, 0.0, 1.0);
822 texcoord = (position.xy * 0.5) + 0.5;
823 })";
824 }
825
testSetUp()826 void testSetUp() override
827 {
828 Texture2DTest::testSetUp();
829
830 setUpProgram();
831
832 mDrawScaleUniformLocation = glGetUniformLocation(mProgram, "drawScale");
833 ASSERT_NE(-1, mDrawScaleUniformLocation);
834
835 glUseProgram(mProgram);
836 glUniform2f(mDrawScaleUniformLocation, 1.0f, 1.0f);
837 glUseProgram(0);
838 ASSERT_GL_NO_ERROR();
839 }
840
841 GLint mDrawScaleUniformLocation;
842 };
843
844 class Sampler2DAsFunctionParameterTest : public Texture2DTest
845 {
846 protected:
Sampler2DAsFunctionParameterTest()847 Sampler2DAsFunctionParameterTest() : Texture2DTest() {}
848
getFragmentShaderSource()849 const char *getFragmentShaderSource() override
850 {
851 return
852 R"(precision highp float;
853 uniform sampler2D tex;
854 varying vec2 texcoord;
855
856 vec4 computeFragColor(sampler2D aTex)
857 {
858 return texture2D(aTex, texcoord);
859 }
860
861 void main()
862 {
863 gl_FragColor = computeFragColor(tex);
864 })";
865 }
866
testSetUp()867 void testSetUp() override
868 {
869 Texture2DTest::testSetUp();
870 setUpProgram();
871 }
872 };
873
874 class TextureCubeTest : public TexCoordDrawTest
875 {
876 protected:
TextureCubeTest()877 TextureCubeTest()
878 : TexCoordDrawTest(),
879 mTexture2D(0),
880 mTextureCube(0),
881 mTexture2DUniformLocation(-1),
882 mTextureCubeUniformLocation(-1)
883 {}
884
getFragmentShaderSource()885 const char *getFragmentShaderSource() override
886 {
887 return
888 R"(precision highp float;
889 uniform sampler2D tex2D;
890 uniform samplerCube texCube;
891 varying vec2 texcoord;
892
893 void main()
894 {
895 gl_FragColor = texture2D(tex2D, texcoord);
896 gl_FragColor += textureCube(texCube, vec3(texcoord, 0));
897 })";
898 }
899
testSetUp()900 void testSetUp() override
901 {
902 TexCoordDrawTest::testSetUp();
903
904 glGenTextures(1, &mTextureCube);
905 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
906 for (GLenum face = 0; face < 6; face++)
907 {
908 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
909 GL_UNSIGNED_BYTE, nullptr);
910 }
911 EXPECT_GL_NO_ERROR();
912
913 mTexture2D = create2DTexture();
914
915 setUpProgram();
916
917 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
918 ASSERT_NE(-1, mTexture2DUniformLocation);
919 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
920 ASSERT_NE(-1, mTextureCubeUniformLocation);
921 }
922
testTearDown()923 void testTearDown() override
924 {
925 glDeleteTextures(1, &mTextureCube);
926 TexCoordDrawTest::testTearDown();
927 }
928
929 GLuint mTexture2D;
930 GLuint mTextureCube;
931 GLint mTexture2DUniformLocation;
932 GLint mTextureCubeUniformLocation;
933 };
934
935 class TextureCubeTestES3 : public ANGLETest<>
936 {
937 protected:
TextureCubeTestES3()938 TextureCubeTestES3() {}
939 };
940
941 class SamplerArrayTest : public TexCoordDrawTest
942 {
943 protected:
SamplerArrayTest()944 SamplerArrayTest()
945 : TexCoordDrawTest(),
946 mTexture2DA(0),
947 mTexture2DB(0),
948 mTexture0UniformLocation(-1),
949 mTexture1UniformLocation(-1)
950 {}
951
getFragmentShaderSource()952 const char *getFragmentShaderSource() override
953 {
954 return
955 R"(precision mediump float;
956 uniform highp sampler2D tex2DArray[2];
957 varying vec2 texcoord;
958 void main()
959 {
960 gl_FragColor = texture2D(tex2DArray[0], texcoord);
961 gl_FragColor += texture2D(tex2DArray[1], texcoord);
962 })";
963 }
964
testSetUp()965 void testSetUp() override
966 {
967 TexCoordDrawTest::testSetUp();
968
969 setUpProgram();
970
971 mTexture0UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[0]");
972 ASSERT_NE(-1, mTexture0UniformLocation);
973 mTexture1UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[1]");
974 ASSERT_NE(-1, mTexture1UniformLocation);
975
976 mTexture2DA = create2DTexture();
977 mTexture2DB = create2DTexture();
978 ASSERT_GL_NO_ERROR();
979 }
980
testTearDown()981 void testTearDown() override
982 {
983 glDeleteTextures(1, &mTexture2DA);
984 glDeleteTextures(1, &mTexture2DB);
985 TexCoordDrawTest::testTearDown();
986 }
987
testSamplerArrayDraw()988 void testSamplerArrayDraw()
989 {
990 GLubyte texData[4];
991 texData[0] = 0;
992 texData[1] = 60;
993 texData[2] = 0;
994 texData[3] = 255;
995
996 glActiveTexture(GL_TEXTURE0);
997 glBindTexture(GL_TEXTURE_2D, mTexture2DA);
998 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
999
1000 texData[1] = 120;
1001 glActiveTexture(GL_TEXTURE1);
1002 glBindTexture(GL_TEXTURE_2D, mTexture2DB);
1003 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1004 EXPECT_GL_ERROR(GL_NO_ERROR);
1005
1006 glUseProgram(mProgram);
1007 glUniform1i(mTexture0UniformLocation, 0);
1008 glUniform1i(mTexture1UniformLocation, 1);
1009 drawQuad(mProgram, "position", 0.5f);
1010 EXPECT_GL_NO_ERROR();
1011
1012 EXPECT_PIXEL_NEAR(0, 0, 0, 180, 0, 255, 2);
1013 }
1014
1015 GLuint mTexture2DA;
1016 GLuint mTexture2DB;
1017 GLint mTexture0UniformLocation;
1018 GLint mTexture1UniformLocation;
1019 };
1020
1021 class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
1022 {
1023 protected:
SamplerArrayAsFunctionParameterTest()1024 SamplerArrayAsFunctionParameterTest() : SamplerArrayTest() {}
1025
getFragmentShaderSource()1026 const char *getFragmentShaderSource() override
1027 {
1028 return
1029 R"(precision mediump float;
1030 uniform highp sampler2D tex2DArray[2];
1031 varying vec2 texcoord;
1032
1033 vec4 computeFragColor(highp sampler2D aTex2DArray[2])
1034 {
1035 return texture2D(aTex2DArray[0], texcoord) + texture2D(aTex2DArray[1], texcoord);
1036 }
1037
1038 void main()
1039 {
1040 gl_FragColor = computeFragColor(tex2DArray);
1041 })";
1042 }
1043 };
1044
1045 class Texture2DArrayTestES3 : public TexCoordDrawTest
1046 {
1047 protected:
Texture2DArrayTestES3()1048 Texture2DArrayTestES3()
1049 : TexCoordDrawTest(),
1050 m2DArrayTexture(0),
1051 mTextureArrayLocation(-1),
1052 mTextureArraySliceUniformLocation(-1)
1053 {}
1054
getVertexShaderSource()1055 const char *getVertexShaderSource() override
1056 {
1057 return R"(#version 300 es
1058 out vec2 texcoord;
1059 in vec4 position;
1060 void main()
1061 {
1062 gl_Position = vec4(position.xy, 0.0, 1.0);
1063 texcoord = (position.xy * 0.5) + 0.5;
1064 })";
1065 }
1066
getFragmentShaderSource()1067 const char *getFragmentShaderSource() override
1068 {
1069 return R"(#version 300 es
1070 precision highp float;
1071 uniform highp sampler2DArray tex2DArray;
1072 uniform int slice;
1073 in vec2 texcoord;
1074 out vec4 fragColor;
1075 void main()
1076 {
1077 fragColor = texture(tex2DArray, vec3(texcoord, float(slice)));
1078 })";
1079 }
1080
testSetUp()1081 void testSetUp() override
1082 {
1083 TexCoordDrawTest::testSetUp();
1084
1085 setUpProgram();
1086
1087 mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
1088 ASSERT_NE(-1, mTextureArrayLocation);
1089
1090 mTextureArraySliceUniformLocation = glGetUniformLocation(mProgram, "slice");
1091 ASSERT_NE(-1, mTextureArraySliceUniformLocation);
1092
1093 glGenTextures(1, &m2DArrayTexture);
1094 ASSERT_GL_NO_ERROR();
1095 }
1096
testTearDown()1097 void testTearDown() override
1098 {
1099 glDeleteTextures(1, &m2DArrayTexture);
1100 TexCoordDrawTest::testTearDown();
1101 }
1102
1103 GLuint m2DArrayTexture;
1104 GLint mTextureArrayLocation;
1105 GLint mTextureArraySliceUniformLocation;
1106 };
1107
1108 class TextureSizeTextureArrayTest : public TexCoordDrawTest
1109 {
1110 protected:
TextureSizeTextureArrayTest()1111 TextureSizeTextureArrayTest()
1112 : TexCoordDrawTest(),
1113 mTexture2DA(0),
1114 mTexture2DB(0),
1115 mTexture0Location(-1),
1116 mTexture1Location(-1)
1117 {}
1118
getVertexShaderSource()1119 const char *getVertexShaderSource() override { return essl3_shaders::vs::Simple(); }
1120
getFragmentShaderSource()1121 const char *getFragmentShaderSource() override
1122 {
1123 return "#version 300 es\n"
1124 "precision highp float;\n"
1125 "uniform highp sampler2D tex2DArray[2];\n"
1126 "out vec4 fragColor;\n"
1127 "void main()\n"
1128 "{\n"
1129 " float red = float(textureSize(tex2DArray[0], 0).x) / 255.0;\n"
1130 " float green = float(textureSize(tex2DArray[1], 0).x) / 255.0;\n"
1131 " fragColor = vec4(red, green, 0.0, 1.0);\n"
1132 "}\n";
1133 }
1134
testSetUp()1135 void testSetUp() override
1136 {
1137 TexCoordDrawTest::testSetUp();
1138
1139 setUpProgram();
1140
1141 mTexture0Location = glGetUniformLocation(mProgram, "tex2DArray[0]");
1142 ASSERT_NE(-1, mTexture0Location);
1143 mTexture1Location = glGetUniformLocation(mProgram, "tex2DArray[1]");
1144 ASSERT_NE(-1, mTexture1Location);
1145
1146 mTexture2DA = create2DTexture();
1147 mTexture2DB = create2DTexture();
1148 ASSERT_GL_NO_ERROR();
1149 }
1150
testTearDown()1151 void testTearDown() override
1152 {
1153 glDeleteTextures(1, &mTexture2DA);
1154 glDeleteTextures(1, &mTexture2DB);
1155 TexCoordDrawTest::testTearDown();
1156 }
1157
1158 GLuint mTexture2DA;
1159 GLuint mTexture2DB;
1160 GLint mTexture0Location;
1161 GLint mTexture1Location;
1162 };
1163
1164 // Test for GL_OES_texture_3D extension
1165 class Texture3DTestES2 : public TexCoordDrawTest
1166 {
1167 protected:
Texture3DTestES2()1168 Texture3DTestES2() : TexCoordDrawTest(), mTexture3D(0), mTexture3DUniformLocation(-1) {}
1169
getVertexShaderSource()1170 const char *getVertexShaderSource() override
1171 {
1172 return "#version 100\n"
1173 "varying vec2 texcoord;\n"
1174 "attribute vec4 position;\n"
1175 "void main()\n"
1176 "{\n"
1177 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1178 " texcoord = (position.xy * 0.5) + 0.5;\n"
1179 "}\n";
1180 }
1181
getFragmentShaderSource()1182 const char *getFragmentShaderSource() override
1183 {
1184 if (!hasTexture3DExt())
1185 {
1186 return "#version 100\n"
1187 "precision highp float;\n"
1188 "varying vec2 texcoord;\n"
1189 "void main()\n"
1190 "{\n"
1191 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
1192 "}\n";
1193 }
1194 return "#version 100\n"
1195 "#extension GL_OES_texture_3D : enable\n"
1196 "precision highp float;\n"
1197 "uniform highp sampler3D tex3D;\n"
1198 "uniform highp float level;\n"
1199 "varying vec2 texcoord;\n"
1200 "void main()\n"
1201 "{\n"
1202 " gl_FragColor = texture3DLod(tex3D, vec3(texcoord, 0.0), level);\n"
1203 "}\n";
1204 }
1205
testSetUp()1206 void testSetUp() override
1207 {
1208 // http://anglebug.com/5728
1209 ANGLE_SKIP_TEST_IF(IsOzone());
1210
1211 TexCoordDrawTest::testSetUp();
1212
1213 glGenTextures(1, &mTexture3D);
1214
1215 setUpProgram();
1216
1217 mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
1218 if (hasTexture3DExt())
1219 {
1220 ASSERT_NE(-1, mTexture3DUniformLocation);
1221 }
1222 }
1223
testTearDown()1224 void testTearDown() override
1225 {
1226 glDeleteTextures(1, &mTexture3D);
1227 TexCoordDrawTest::testTearDown();
1228 }
1229
hasTexture3DExt() const1230 bool hasTexture3DExt() const
1231 {
1232 // http://anglebug.com/4927
1233 if ((IsPixel2() || IsNexus5X()) && IsOpenGLES())
1234 {
1235 return false;
1236 }
1237 return IsGLExtensionEnabled("GL_OES_texture_3D");
1238 }
1239
1240 GLuint mTexture3D;
1241 GLint mTexture3DUniformLocation;
1242 };
1243
1244 class Texture3DTestES3 : public Texture3DTestES2
1245 {
1246 protected:
Texture3DTestES3()1247 Texture3DTestES3() : Texture3DTestES2() {}
1248
getVertexShaderSource()1249 const char *getVertexShaderSource() override
1250 {
1251 return "#version 300 es\n"
1252 "out vec2 texcoord;\n"
1253 "in vec4 position;\n"
1254 "void main()\n"
1255 "{\n"
1256 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1257 " texcoord = (position.xy * 0.5) + 0.5;\n"
1258 "}\n";
1259 }
1260
getFragmentShaderSource()1261 const char *getFragmentShaderSource() override
1262 {
1263 return "#version 300 es\n"
1264 "precision highp float;\n"
1265 "uniform highp sampler3D tex3D;\n"
1266 "in vec2 texcoord;\n"
1267 "out vec4 fragColor;\n"
1268 "void main()\n"
1269 "{\n"
1270 " fragColor = texture(tex3D, vec3(texcoord, 0.0));\n"
1271 "}\n";
1272 }
1273 };
1274
1275 class ShadowSamplerPlusSampler3DTestES3 : public TexCoordDrawTest
1276 {
1277 protected:
ShadowSamplerPlusSampler3DTestES3()1278 ShadowSamplerPlusSampler3DTestES3()
1279 : TexCoordDrawTest(),
1280 mTextureShadow(0),
1281 mTexture3D(0),
1282 mTextureShadowUniformLocation(-1),
1283 mTexture3DUniformLocation(-1),
1284 mDepthRefUniformLocation(-1)
1285 {}
1286
getVertexShaderSource()1287 const char *getVertexShaderSource() override
1288 {
1289 return "#version 300 es\n"
1290 "out vec2 texcoord;\n"
1291 "in vec4 position;\n"
1292 "void main()\n"
1293 "{\n"
1294 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1295 " texcoord = (position.xy * 0.5) + 0.5;\n"
1296 "}\n";
1297 }
1298
getFragmentShaderSource()1299 const char *getFragmentShaderSource() override
1300 {
1301 return "#version 300 es\n"
1302 "precision highp float;\n"
1303 "uniform highp sampler2DShadow tex2DShadow;\n"
1304 "uniform highp sampler3D tex3D;\n"
1305 "in vec2 texcoord;\n"
1306 "uniform float depthRef;\n"
1307 "out vec4 fragColor;\n"
1308 "void main()\n"
1309 "{\n"
1310 " fragColor = vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.5);\n"
1311 " fragColor += texture(tex3D, vec3(texcoord, 0.0));\n"
1312 "}\n";
1313 }
1314
testSetUp()1315 void testSetUp() override
1316 {
1317 TexCoordDrawTest::testSetUp();
1318
1319 glGenTextures(1, &mTexture3D);
1320
1321 glGenTextures(1, &mTextureShadow);
1322 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
1323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1324
1325 setUpProgram();
1326
1327 mTextureShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
1328 ASSERT_NE(-1, mTextureShadowUniformLocation);
1329 mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
1330 ASSERT_NE(-1, mTexture3DUniformLocation);
1331 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
1332 ASSERT_NE(-1, mDepthRefUniformLocation);
1333 }
1334
testTearDown()1335 void testTearDown() override
1336 {
1337 glDeleteTextures(1, &mTextureShadow);
1338 glDeleteTextures(1, &mTexture3D);
1339 TexCoordDrawTest::testTearDown();
1340 }
1341
1342 GLuint mTextureShadow;
1343 GLuint mTexture3D;
1344 GLint mTextureShadowUniformLocation;
1345 GLint mTexture3DUniformLocation;
1346 GLint mDepthRefUniformLocation;
1347 };
1348
1349 class SamplerTypeMixTestES3 : public TexCoordDrawTest
1350 {
1351 protected:
SamplerTypeMixTestES3()1352 SamplerTypeMixTestES3()
1353 : TexCoordDrawTest(),
1354 mTexture2D(0),
1355 mTextureCube(0),
1356 mTexture2DShadow(0),
1357 mTextureCubeShadow(0),
1358 mTexture2DUniformLocation(-1),
1359 mTextureCubeUniformLocation(-1),
1360 mTexture2DShadowUniformLocation(-1),
1361 mTextureCubeShadowUniformLocation(-1),
1362 mDepthRefUniformLocation(-1)
1363 {}
1364
getVertexShaderSource()1365 const char *getVertexShaderSource() override
1366 {
1367 return "#version 300 es\n"
1368 "out vec2 texcoord;\n"
1369 "in vec4 position;\n"
1370 "void main()\n"
1371 "{\n"
1372 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1373 " texcoord = (position.xy * 0.5) + 0.5;\n"
1374 "}\n";
1375 }
1376
getFragmentShaderSource()1377 const char *getFragmentShaderSource() override
1378 {
1379 return "#version 300 es\n"
1380 "precision highp float;\n"
1381 "uniform highp sampler2D tex2D;\n"
1382 "uniform highp samplerCube texCube;\n"
1383 "uniform highp sampler2DShadow tex2DShadow;\n"
1384 "uniform highp samplerCubeShadow texCubeShadow;\n"
1385 "in vec2 texcoord;\n"
1386 "uniform float depthRef;\n"
1387 "out vec4 fragColor;\n"
1388 "void main()\n"
1389 "{\n"
1390 " fragColor = texture(tex2D, texcoord);\n"
1391 " fragColor += texture(texCube, vec3(1.0, 0.0, 0.0));\n"
1392 " fragColor += vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.25);\n"
1393 " fragColor += vec4(texture(texCubeShadow, vec4(1.0, 0.0, 0.0, depthRef)) * "
1394 "0.125);\n"
1395 "}\n";
1396 }
1397
testSetUp()1398 void testSetUp() override
1399 {
1400 TexCoordDrawTest::testSetUp();
1401
1402 glGenTextures(1, &mTexture2D);
1403 glGenTextures(1, &mTextureCube);
1404
1405 glGenTextures(1, &mTexture2DShadow);
1406 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
1407 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1408
1409 glGenTextures(1, &mTextureCubeShadow);
1410 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
1411 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1412
1413 setUpProgram();
1414
1415 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
1416 ASSERT_NE(-1, mTexture2DUniformLocation);
1417 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
1418 ASSERT_NE(-1, mTextureCubeUniformLocation);
1419 mTexture2DShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
1420 ASSERT_NE(-1, mTexture2DShadowUniformLocation);
1421 mTextureCubeShadowUniformLocation = glGetUniformLocation(mProgram, "texCubeShadow");
1422 ASSERT_NE(-1, mTextureCubeShadowUniformLocation);
1423 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
1424 ASSERT_NE(-1, mDepthRefUniformLocation);
1425
1426 ASSERT_GL_NO_ERROR();
1427 }
1428
testTearDown()1429 void testTearDown() override
1430 {
1431 glDeleteTextures(1, &mTexture2D);
1432 glDeleteTextures(1, &mTextureCube);
1433 glDeleteTextures(1, &mTexture2DShadow);
1434 glDeleteTextures(1, &mTextureCubeShadow);
1435 TexCoordDrawTest::testTearDown();
1436 }
1437
1438 GLuint mTexture2D;
1439 GLuint mTextureCube;
1440 GLuint mTexture2DShadow;
1441 GLuint mTextureCubeShadow;
1442 GLint mTexture2DUniformLocation;
1443 GLint mTextureCubeUniformLocation;
1444 GLint mTexture2DShadowUniformLocation;
1445 GLint mTextureCubeShadowUniformLocation;
1446 GLint mDepthRefUniformLocation;
1447 };
1448
1449 class SamplerInStructTest : public Texture2DTest
1450 {
1451 protected:
SamplerInStructTest()1452 SamplerInStructTest() : Texture2DTest() {}
1453
getTextureUniformName()1454 const char *getTextureUniformName() override { return "us.tex"; }
1455
getFragmentShaderSource()1456 const char *getFragmentShaderSource() override
1457 {
1458 return "precision highp float;\n"
1459 "struct S\n"
1460 "{\n"
1461 " vec4 a;\n"
1462 " highp sampler2D tex;\n"
1463 "};\n"
1464 "uniform S us;\n"
1465 "varying vec2 texcoord;\n"
1466 "void main()\n"
1467 "{\n"
1468 " gl_FragColor = texture2D(us.tex, texcoord + us.a.x);\n"
1469 "}\n";
1470 }
1471
runSamplerInStructTest()1472 void runSamplerInStructTest()
1473 {
1474 setUpProgram();
1475
1476 glActiveTexture(GL_TEXTURE0);
1477 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1478 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1479 &GLColor::green);
1480 drawQuad(mProgram, "position", 0.5f);
1481 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1482 }
1483 };
1484
1485 class SamplerInStructAsFunctionParameterTest : public SamplerInStructTest
1486 {
1487 protected:
SamplerInStructAsFunctionParameterTest()1488 SamplerInStructAsFunctionParameterTest() : SamplerInStructTest() {}
1489
getFragmentShaderSource()1490 const char *getFragmentShaderSource() override
1491 {
1492 return "precision highp float;\n"
1493 "struct S\n"
1494 "{\n"
1495 " vec4 a;\n"
1496 " highp sampler2D tex;\n"
1497 "};\n"
1498 "uniform S us;\n"
1499 "varying vec2 texcoord;\n"
1500 "vec4 sampleFrom(S s) {\n"
1501 " return texture2D(s.tex, texcoord + s.a.x);\n"
1502 "}\n"
1503 "void main()\n"
1504 "{\n"
1505 " gl_FragColor = sampleFrom(us);\n"
1506 "}\n";
1507 }
1508 };
1509
1510 class SamplerInStructArrayAsFunctionParameterTest : public SamplerInStructTest
1511 {
1512 protected:
SamplerInStructArrayAsFunctionParameterTest()1513 SamplerInStructArrayAsFunctionParameterTest() : SamplerInStructTest() {}
1514
getTextureUniformName()1515 const char *getTextureUniformName() override { return "us[0].tex"; }
1516
getFragmentShaderSource()1517 const char *getFragmentShaderSource() override
1518 {
1519 return "precision highp float;\n"
1520 "struct S\n"
1521 "{\n"
1522 " vec4 a;\n"
1523 " highp sampler2D tex;\n"
1524 "};\n"
1525 "uniform S us[1];\n"
1526 "varying vec2 texcoord;\n"
1527 "vec4 sampleFrom(S s) {\n"
1528 " return texture2D(s.tex, texcoord + s.a.x);\n"
1529 "}\n"
1530 "void main()\n"
1531 "{\n"
1532 " gl_FragColor = sampleFrom(us[0]);\n"
1533 "}\n";
1534 }
1535 };
1536
1537 class SamplerInNestedStructAsFunctionParameterTest : public SamplerInStructTest
1538 {
1539 protected:
SamplerInNestedStructAsFunctionParameterTest()1540 SamplerInNestedStructAsFunctionParameterTest() : SamplerInStructTest() {}
1541
getTextureUniformName()1542 const char *getTextureUniformName() override { return "us[0].sub.tex"; }
1543
getFragmentShaderSource()1544 const char *getFragmentShaderSource() override
1545 {
1546 return "precision highp float;\n"
1547 "struct SUB\n"
1548 "{\n"
1549 " vec4 a;\n"
1550 " highp sampler2D tex;\n"
1551 "};\n"
1552 "struct S\n"
1553 "{\n"
1554 " SUB sub;\n"
1555 "};\n"
1556 "uniform S us[1];\n"
1557 "varying vec2 texcoord;\n"
1558 "vec4 sampleFrom(SUB s) {\n"
1559 " return texture2D(s.tex, texcoord + s.a.x);\n"
1560 "}\n"
1561 "void main()\n"
1562 "{\n"
1563 " gl_FragColor = sampleFrom(us[0].sub);\n"
1564 "}\n";
1565 }
1566 };
1567
1568 class SamplerInStructAndOtherVariableTest : public SamplerInStructTest
1569 {
1570 protected:
SamplerInStructAndOtherVariableTest()1571 SamplerInStructAndOtherVariableTest() : SamplerInStructTest() {}
1572
getFragmentShaderSource()1573 const char *getFragmentShaderSource() override
1574 {
1575 return "precision highp float;\n"
1576 "struct S\n"
1577 "{\n"
1578 " vec4 a;\n"
1579 " highp sampler2D tex;\n"
1580 "};\n"
1581 "uniform S us;\n"
1582 "uniform float us_tex;\n"
1583 "varying vec2 texcoord;\n"
1584 "void main()\n"
1585 "{\n"
1586 " gl_FragColor = texture2D(us.tex, texcoord + us.a.x + us_tex);\n"
1587 "}\n";
1588 }
1589 };
1590
1591 class Texture2DIntegerTestES3 : public Texture2DTest
1592 {
1593 protected:
Texture2DIntegerTestES3()1594 Texture2DIntegerTestES3() : Texture2DTest() {}
1595
getVertexShaderSource()1596 const char *getVertexShaderSource() override
1597 {
1598 return "#version 300 es\n"
1599 "out vec2 texcoord;\n"
1600 "in vec4 position;\n"
1601 "void main()\n"
1602 "{\n"
1603 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1604 " texcoord = (position.xy * 0.5) + 0.5;\n"
1605 "}\n";
1606 }
1607
getFragmentShaderSource()1608 const char *getFragmentShaderSource() override
1609 {
1610 return "#version 300 es\n"
1611 "precision highp float;\n"
1612 "precision highp usampler2D;\n"
1613 "uniform usampler2D tex;\n"
1614 "in vec2 texcoord;\n"
1615 "out vec4 fragColor;\n"
1616 "void main()\n"
1617 "{\n"
1618 " fragColor = vec4(texture(tex, texcoord))/255.0;\n"
1619 "}\n";
1620 }
1621 };
1622
1623 class TextureCubeIntegerTestES3 : public TexCoordDrawTest
1624 {
1625 protected:
TextureCubeIntegerTestES3()1626 TextureCubeIntegerTestES3()
1627 : TexCoordDrawTest(), mTextureCube(0), mTextureCubeUniformLocation(-1)
1628 {}
1629
getVertexShaderSource()1630 const char *getVertexShaderSource() override
1631 {
1632 return "#version 300 es\n"
1633 "out vec2 texcoord;\n"
1634 "in vec4 position;\n"
1635 "void main()\n"
1636 "{\n"
1637 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1638 " texcoord = 0.5*position.xy;\n"
1639 "}\n";
1640 }
1641
getFragmentShaderSource()1642 const char *getFragmentShaderSource() override
1643 {
1644 return "#version 300 es\n"
1645 "precision highp float;\n"
1646 "precision highp usamplerCube;\n"
1647 "uniform usamplerCube texCube;\n"
1648 "in vec2 texcoord;\n"
1649 "out vec4 fragColor;\n"
1650 "void main()\n"
1651 "{\n"
1652 " fragColor = vec4(texture(texCube, vec3(texcoord, 1)))/255.0;\n"
1653 "}\n";
1654 }
1655
testSetUp()1656 void testSetUp() override
1657 {
1658 TexCoordDrawTest::testSetUp();
1659 glGenTextures(1, &mTextureCube);
1660 setUpProgram();
1661
1662 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
1663 ASSERT_NE(-1, mTextureCubeUniformLocation);
1664 }
1665
testTearDown()1666 void testTearDown() override
1667 {
1668 glDeleteTextures(1, &mTextureCube);
1669 TexCoordDrawTest::testTearDown();
1670 }
1671
1672 GLuint mTextureCube;
1673 GLint mTextureCubeUniformLocation;
1674 };
1675
1676 class TextureCubeIntegerEdgeTestES3 : public TextureCubeIntegerTestES3
1677 {
1678 protected:
TextureCubeIntegerEdgeTestES3()1679 TextureCubeIntegerEdgeTestES3() : TextureCubeIntegerTestES3() {}
1680
getVertexShaderSource()1681 const char *getVertexShaderSource() override
1682 {
1683 return "#version 300 es\n"
1684 "out vec2 texcoord;\n"
1685 "in vec4 position;\n"
1686 "void main()\n"
1687 "{\n"
1688 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1689 " texcoord = position.xy;\n"
1690 "}\n";
1691 }
1692
getFragmentShaderSource()1693 const char *getFragmentShaderSource() override
1694 {
1695 return "#version 300 es\n"
1696 "precision highp float;\n"
1697 "precision highp usamplerCube;\n"
1698 "uniform usamplerCube texCube;\n"
1699 "in vec2 texcoord;\n"
1700 "out vec4 fragColor;\n"
1701 "void main()\n"
1702 "{\n"
1703 " fragColor = vec4(texture(texCube, vec3(texcoord, 0)))/255.0;\n"
1704 "}\n";
1705 }
1706 };
1707
1708 class Texture2DIntegerProjectiveOffsetTestES3 : public Texture2DTest
1709 {
1710 protected:
Texture2DIntegerProjectiveOffsetTestES3()1711 Texture2DIntegerProjectiveOffsetTestES3() : Texture2DTest() {}
1712
getVertexShaderSource()1713 const char *getVertexShaderSource() override
1714 {
1715 return "#version 300 es\n"
1716 "out vec2 texcoord;\n"
1717 "in vec4 position;\n"
1718 "void main()\n"
1719 "{\n"
1720 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1721 " texcoord = 0.5*position.xy + vec2(0.5, 0.5);\n"
1722 "}\n";
1723 }
1724
getFragmentShaderSource()1725 const char *getFragmentShaderSource() override
1726 {
1727 return "#version 300 es\n"
1728 "precision highp float;\n"
1729 "precision highp usampler2D;\n"
1730 "uniform usampler2D tex;\n"
1731 "in vec2 texcoord;\n"
1732 "out vec4 fragColor;\n"
1733 "void main()\n"
1734 "{\n"
1735 " fragColor = vec4(textureProjOffset(tex, vec3(texcoord, 1), ivec2(0,0), "
1736 "0.0))/255.0;\n"
1737 "}\n";
1738 }
1739 };
1740
1741 class Texture2DArrayIntegerTestES3 : public Texture2DArrayTestES3
1742 {
1743 protected:
Texture2DArrayIntegerTestES3()1744 Texture2DArrayIntegerTestES3() : Texture2DArrayTestES3() {}
1745
getVertexShaderSource()1746 const char *getVertexShaderSource() override
1747 {
1748 return R"(#version 300 es
1749 out vec2 texcoord;
1750 in vec4 position;
1751 void main()
1752 {
1753 gl_Position = vec4(position.xy, 0.0, 1.0);
1754 texcoord = (position.xy * 0.5) + 0.5;
1755 })";
1756 }
1757
getFragmentShaderSource()1758 const char *getFragmentShaderSource() override
1759 {
1760 return R"(#version 300 es
1761 precision highp float;
1762 uniform highp usampler2DArray tex2DArray;
1763 uniform int slice;
1764 in vec2 texcoord;
1765 out vec4 fragColor;
1766 void main()
1767 {
1768 fragColor = vec4(texture(tex2DArray, vec3(texcoord, slice)))/255.0;
1769 })";
1770 }
1771 };
1772
1773 class Texture3DIntegerTestES3 : public Texture3DTestES3
1774 {
1775 protected:
Texture3DIntegerTestES3()1776 Texture3DIntegerTestES3() : Texture3DTestES3() {}
1777
getVertexShaderSource()1778 const char *getVertexShaderSource() override
1779 {
1780 return "#version 300 es\n"
1781 "out vec2 texcoord;\n"
1782 "in vec4 position;\n"
1783 "void main()\n"
1784 "{\n"
1785 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1786 " texcoord = (position.xy * 0.5) + 0.5;\n"
1787 "}\n";
1788 }
1789
getFragmentShaderSource()1790 const char *getFragmentShaderSource() override
1791 {
1792 return "#version 300 es\n"
1793 "precision highp float;\n"
1794 "uniform highp usampler3D tex3D;\n"
1795 "in vec2 texcoord;\n"
1796 "out vec4 fragColor;\n"
1797 "void main()\n"
1798 "{\n"
1799 " fragColor = vec4(texture(tex3D, vec3(texcoord, 0.0)))/255.0;\n"
1800 "}\n";
1801 }
1802 };
1803
1804 class PBOCompressedTextureTest : public Texture2DTest
1805 {
1806 protected:
PBOCompressedTextureTest()1807 PBOCompressedTextureTest() : Texture2DTest() {}
1808
testSetUp()1809 void testSetUp() override
1810 {
1811 TexCoordDrawTest::testSetUp();
1812 glGenTextures(1, &mTexture2D);
1813 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1814 EXPECT_GL_NO_ERROR();
1815
1816 setUpProgram();
1817
1818 glGenBuffers(1, &mPBO);
1819 }
1820
testTearDown()1821 void testTearDown() override
1822 {
1823 glDeleteBuffers(1, &mPBO);
1824 Texture2DTest::testTearDown();
1825 }
1826
1827 void runCompressedSubImage();
1828
1829 GLuint mPBO;
1830 };
1831
1832 class ETC1CompressedTextureTest : public Texture2DTest
1833 {
1834 protected:
ETC1CompressedTextureTest()1835 ETC1CompressedTextureTest() : Texture2DTest() {}
1836
testSetUp()1837 void testSetUp() override
1838 {
1839 TexCoordDrawTest::testSetUp();
1840 glGenTextures(1, &mTexture2D);
1841 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1842 EXPECT_GL_NO_ERROR();
1843
1844 setUpProgram();
1845 }
1846
testTearDown()1847 void testTearDown() override { Texture2DTest::testTearDown(); }
1848 };
1849
1850 class Texture2DDepthStencilTestES3 : public Texture2DTest
1851 {
1852 protected:
Texture2DDepthStencilTestES3()1853 Texture2DDepthStencilTestES3() : Texture2DTest() {}
1854
1855 void TestSampleWithDepthStencilMode(GLenum format, GLenum mode, bool swizzle);
1856 };
1857
TestSampleWithDepthStencilMode(GLenum format,GLenum mode,bool swizzle)1858 void Texture2DDepthStencilTestES3::TestSampleWithDepthStencilMode(GLenum format,
1859 GLenum mode,
1860 bool swizzle)
1861 {
1862 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_stencil_texturing"));
1863
1864 constexpr GLsizei kSize = 4;
1865
1866 ASSERT(mode == GL_STENCIL_INDEX || mode == GL_DEPTH_COMPONENT);
1867
1868 bool isStencilMode;
1869 GLenum attachment;
1870 switch (format)
1871 {
1872 case GL_DEPTH_COMPONENT16:
1873 case GL_DEPTH_COMPONENT24:
1874 case GL_DEPTH_COMPONENT32F:
1875 attachment = GL_DEPTH_ATTACHMENT;
1876 isStencilMode = false;
1877 break;
1878 case GL_DEPTH24_STENCIL8:
1879 case GL_DEPTH32F_STENCIL8:
1880 attachment = GL_DEPTH_STENCIL_ATTACHMENT;
1881 isStencilMode = mode == GL_STENCIL_INDEX;
1882 break;
1883 case GL_STENCIL_INDEX8:
1884 attachment = GL_STENCIL_ATTACHMENT;
1885 isStencilMode = true;
1886 break;
1887 default:
1888 UNREACHABLE();
1889 }
1890
1891 // Set up a color texture.
1892 GLTexture colorTexture;
1893 glBindTexture(GL_TEXTURE_2D, colorTexture);
1894 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
1895 ASSERT_GL_NO_ERROR();
1896
1897 // Set up a depth/stencil texture to be sampled as mode.
1898 GLTexture depthStencilTexture;
1899 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
1900 glTexStorage2D(GL_TEXTURE_2D, 1, format, kSize, kSize);
1901 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1902 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1903 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, mode);
1904 if (swizzle)
1905 {
1906 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ALPHA);
1907 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
1908 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_GREEN);
1909 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
1910 }
1911 ASSERT_GL_NO_ERROR();
1912
1913 constexpr char kStencilFS[] =
1914 R"(#version 300 es
1915 precision mediump float;
1916 uniform highp usampler2D tex;
1917 out vec4 color;
1918 void main()
1919 {
1920 color = vec4(texelFetch(tex, ivec2(0, 0), 0)) / 255.0f;
1921 })";
1922
1923 constexpr char kDepthFS[] =
1924 R"(#version 300 es
1925 precision mediump float;
1926 uniform highp sampler2D tex;
1927 out vec4 color;
1928 void main()
1929 {
1930 color = texture(tex, vec2(0, 0));
1931 })";
1932
1933 // Clear stencil to 42.
1934 GLFramebuffer clearFBO;
1935 glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
1936 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, depthStencilTexture, 0);
1937 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1938 glClearDepthf(0.5);
1939 glClearStencil(42);
1940 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1941 ASSERT_GL_NO_ERROR();
1942
1943 glActiveTexture(GL_TEXTURE0);
1944 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
1945 EXPECT_GL_ERROR(GL_NO_ERROR);
1946
1947 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), isStencilMode ? kStencilFS : kDepthFS);
1948 GLint texLocation = glGetUniformLocation(program, "tex");
1949 ASSERT_NE(-1, texLocation);
1950 ASSERT_GL_NO_ERROR();
1951
1952 glUseProgram(program);
1953 glUniform1i(texLocation, 0);
1954
1955 GLFramebuffer drawFBO;
1956 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
1957 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1958 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1959 ASSERT_GL_NO_ERROR();
1960
1961 drawQuad(program, essl3_shaders::PositionAttrib(), 0.95f);
1962 ASSERT_GL_NO_ERROR();
1963
1964 if (isStencilMode)
1965 {
1966 GLColor expected = swizzle ? GLColor(1, 0, 0, 42) : GLColor(42, 0, 0, 1);
1967 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, expected);
1968 }
1969 else
1970 {
1971 GLColor expected = swizzle ? GLColor(255, 0, 0, 127) : GLColor(127, 0, 0, 255);
1972 EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
1973 }
1974 }
1975
TEST_P(Texture2DTest,NegativeAPISubImage)1976 TEST_P(Texture2DTest, NegativeAPISubImage)
1977 {
1978 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1979 EXPECT_GL_ERROR(GL_NO_ERROR);
1980
1981 setUpProgram();
1982
1983 const GLubyte *pixels[20] = {0};
1984 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1985 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1986
1987 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
1988 {
1989 // Create a 1-level immutable texture.
1990 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
1991
1992 // Try calling sub image on the second level.
1993 glTexSubImage2D(GL_TEXTURE_2D, 1, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1994 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1995 }
1996 }
1997
1998 // Test that querying GL_TEXTURE_BINDING* doesn't cause an unexpected error.
TEST_P(Texture2DTest,QueryBinding)1999 TEST_P(Texture2DTest, QueryBinding)
2000 {
2001 glBindTexture(GL_TEXTURE_2D, 0);
2002 EXPECT_GL_ERROR(GL_NO_ERROR);
2003
2004 GLint textureBinding;
2005 glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
2006 EXPECT_GL_NO_ERROR();
2007 EXPECT_EQ(0, textureBinding);
2008
2009 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &textureBinding);
2010 if (IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
2011 IsGLExtensionEnabled("GL_NV_EGL_stream_consumer_external"))
2012 {
2013 EXPECT_GL_NO_ERROR();
2014 EXPECT_EQ(0, textureBinding);
2015 }
2016 else
2017 {
2018 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2019 }
2020 }
2021
TEST_P(Texture2DTest,ZeroSizedUploads)2022 TEST_P(Texture2DTest, ZeroSizedUploads)
2023 {
2024 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2025 EXPECT_GL_ERROR(GL_NO_ERROR);
2026
2027 setUpProgram();
2028
2029 // Use the texture first to make sure it's in video memory
2030 glUseProgram(mProgram);
2031 glUniform1i(mTexture2DUniformLocation, 0);
2032 drawQuad(mProgram, "position", 0.5f);
2033
2034 const GLubyte *pixel[4] = {0};
2035
2036 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2037 EXPECT_GL_NO_ERROR();
2038
2039 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2040 EXPECT_GL_NO_ERROR();
2041
2042 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2043 EXPECT_GL_NO_ERROR();
2044 }
2045
2046 // Test that interleaved superseded updates work as expected
TEST_P(Texture2DTest,InterleavedSupersedingTextureUpdates)2047 TEST_P(Texture2DTest, InterleavedSupersedingTextureUpdates)
2048 {
2049 constexpr uint32_t kTexWidth = 3840;
2050 constexpr uint32_t kTexHeight = 2160;
2051 constexpr uint32_t kBpp = 4;
2052
2053 // Create the texture
2054 glActiveTexture(GL_TEXTURE0);
2055 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2056 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2057 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2058 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2059 nullptr);
2060 EXPECT_GL_ERROR(GL_NO_ERROR);
2061
2062 // 1. One big upload followed by many small identical uploads
2063 // Update the entire texture
2064 std::vector<GLubyte> fullTextureData(kTexWidth * kTexHeight * kBpp, 128);
2065 constexpr GLColor kFullTextureColor = GLColor(128u, 128u, 128u, 128u);
2066 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2067 fullTextureData.data());
2068
2069 // Make a number of identical updates to the right half of the texture
2070 std::vector<GLubyte> rightHalfData(kTexWidth * kTexHeight * kBpp, 201);
2071 constexpr GLColor kRightHalfColor = GLColor(201u, 201u, 201u, 201u);
2072 for (uint32_t iteration = 0; iteration < 10; iteration++)
2073 {
2074 glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, 0, kTexWidth / 2, kTexHeight, GL_RGBA,
2075 GL_UNSIGNED_BYTE, rightHalfData.data());
2076 }
2077
2078 setUpProgram();
2079 glUseProgram(mProgram);
2080 glUniform1i(mTexture2DUniformLocation, 0);
2081 drawQuad(mProgram, "position", 0.5f);
2082 EXPECT_GL_NO_ERROR();
2083 EXPECT_PIXEL_COLOR_EQ(1 * getWindowWidth() / 4, getWindowHeight() / 2, kFullTextureColor);
2084 EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 2, kRightHalfColor);
2085
2086 // 2. Some small uploads followed by one big upload followed by many identical uploads
2087 // Clear the entire texture
2088 std::vector<GLubyte> zeroTextureData(kTexWidth * kTexHeight * kBpp, 255);
2089 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2090 zeroTextureData.data());
2091
2092 // Update the top left quadrant of the texture
2093 std::vector<GLubyte> topLeftQuadrantData(kTexWidth * kTexHeight * kBpp, 128);
2094 constexpr GLColor kTopLeftQuandrantTextureColor = GLColor(128u, 128u, 128u, 128u);
2095 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2, GL_RGBA,
2096 GL_UNSIGNED_BYTE, topLeftQuadrantData.data());
2097
2098 // Update the top right quadrant of the texture
2099 std::vector<GLubyte> topRightQuadrantData(kTexWidth * kTexHeight * kBpp, 156);
2100 constexpr GLColor kTopRightQuadrantTextureColor = GLColor(156u, 156u, 156u, 156u);
2101 glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2,
2102 GL_RGBA, GL_UNSIGNED_BYTE, topRightQuadrantData.data());
2103
2104 // Update the bottom half of the texture
2105 std::vector<GLubyte> bottomHalfTextureData(kTexWidth * kTexHeight * kBpp, 187);
2106 constexpr GLColor kBottomHalfTextureColor = GLColor(187u, 187u, 187u, 187u);
2107 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight / 2, GL_RGBA, GL_UNSIGNED_BYTE,
2108 bottomHalfTextureData.data());
2109
2110 // Make a number of identical updates to the bottom right quadrant of the texture
2111 std::vector<GLubyte> bottomRightQuadrantData(kTexWidth * kTexHeight * kBpp, 201);
2112 constexpr GLColor kBottomRightQuadrantColor = GLColor(201u, 201u, 201u, 201u);
2113 for (uint32_t iteration = 0; iteration < 10; iteration++)
2114 {
2115 glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, 0, kTexWidth / 2, kTexHeight / 2, GL_RGBA,
2116 GL_UNSIGNED_BYTE, bottomRightQuadrantData.data());
2117 }
2118
2119 setUpProgram();
2120 glUseProgram(mProgram);
2121 glUniform1i(mTexture2DUniformLocation, 0);
2122 drawQuad(mProgram, "position", 0.5f);
2123 EXPECT_GL_NO_ERROR();
2124 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, kTopLeftQuandrantTextureColor);
2125 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1,
2126 kTopRightQuadrantTextureColor);
2127 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, kBottomHalfTextureColor);
2128 EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4,
2129 kBottomRightQuadrantColor);
2130
2131 // 3. Many small uploads folloed by one big upload
2132 // Clear the entire texture
2133 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2134 zeroTextureData.data());
2135
2136 // Make a number of small updates to different parts of the texture
2137 std::vector<std::pair<GLint, GLint>> xyOffsets = {
2138 {1, 4}, {128, 34}, {1208, 1090}, {2560, 2022}};
2139 constexpr GLColor kRandomColor = GLColor(55u, 128u, 201u, 255u);
2140 for (const std::pair<GLint, GLint> &xyOffset : xyOffsets)
2141 {
2142 glTexSubImage2D(GL_TEXTURE_2D, 0, xyOffset.first, xyOffset.second, 1, 1, GL_RGBA,
2143 GL_UNSIGNED_BYTE, kRandomColor.data());
2144 }
2145
2146 // Update the entire texture
2147 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2148 fullTextureData.data());
2149
2150 setUpProgram();
2151 glUseProgram(mProgram);
2152 glUniform1i(mTexture2DUniformLocation, 0);
2153 drawQuad(mProgram, "position", 0.5f);
2154 EXPECT_GL_NO_ERROR();
2155 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth() - 1, getWindowHeight() - 1, kFullTextureColor);
2156 }
2157
2158 // Test that repeated calls to glTexSubImage2D with superseding updates works
TEST_P(Texture2DTest,ManySupersedingTextureUpdates)2159 TEST_P(Texture2DTest, ManySupersedingTextureUpdates)
2160 {
2161 constexpr uint32_t kTexWidth = 3840;
2162 constexpr uint32_t kTexHeight = 2160;
2163 constexpr uint32_t kBpp = 4;
2164 std::vector<GLubyte> data(kTexWidth * kTexHeight * kBpp, 0);
2165
2166 // Create the texture
2167 glActiveTexture(GL_TEXTURE0);
2168 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2171 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2172 nullptr);
2173 EXPECT_GL_ERROR(GL_NO_ERROR);
2174
2175 // Make a large number of superseding updates
2176 for (uint32_t width = kTexWidth / 2, height = kTexHeight / 2;
2177 width < kTexWidth && height < kTexHeight; width++, height++)
2178 {
2179 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
2180 data.data());
2181 }
2182
2183 // Upload different color to the whole texture thus superseding all prior updates.
2184 std::vector<GLubyte> supersedingData(kTexWidth * kTexHeight * kBpp, 128);
2185 constexpr GLColor kGray = GLColor(128u, 128u, 128u, 128u);
2186 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2187 supersedingData.data());
2188
2189 setUpProgram();
2190 glUseProgram(mProgram);
2191 glUniform1i(mTexture2DUniformLocation, 0);
2192 drawQuad(mProgram, "position", 0.5f);
2193 EXPECT_GL_NO_ERROR();
2194 EXPECT_PIXEL_COLOR_EQ(0, 0, kGray);
2195 }
2196
TEST_P(Texture2DTest,DefineMultipleLevelsWithoutMipmapping)2197 TEST_P(Texture2DTest, DefineMultipleLevelsWithoutMipmapping)
2198 {
2199 setUpProgram();
2200
2201 constexpr size_t kImageSize = 256;
2202 std::array<GLColor, kImageSize * kImageSize> kMipColors[2];
2203
2204 std::fill(kMipColors[0].begin(), kMipColors[0].end(), GLColor::red);
2205 std::fill(kMipColors[1].begin(), kMipColors[1].end(), GLColor::green);
2206
2207 glActiveTexture(GL_TEXTURE0);
2208 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2211
2212 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2213 kMipColors[0].data());
2214 EXPECT_GL_NO_ERROR();
2215
2216 // Draw so the image is created.
2217 glUseProgram(mProgram);
2218 glUniform1i(mTexture2DUniformLocation, 0);
2219 drawQuad(mProgram, "position", 0.5f);
2220
2221 // Define level 1 of the texture.
2222 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2223 kMipColors[1].data());
2224 EXPECT_GL_NO_ERROR();
2225
2226 // Draw again.
2227 drawQuad(mProgram, "position", 0.5f);
2228 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0][0]);
2229 }
2230
2231 // Test drawing with two texture types, to trigger an ANGLE bug in validation
TEST_P(TextureCubeTest,CubeMapBug)2232 TEST_P(TextureCubeTest, CubeMapBug)
2233 {
2234 glActiveTexture(GL_TEXTURE0);
2235 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2236 glActiveTexture(GL_TEXTURE1);
2237 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2238 EXPECT_GL_ERROR(GL_NO_ERROR);
2239
2240 glUseProgram(mProgram);
2241 glUniform1i(mTexture2DUniformLocation, 0);
2242 glUniform1i(mTextureCubeUniformLocation, 1);
2243 drawQuad(mProgram, "position", 0.5f);
2244 EXPECT_GL_NO_ERROR();
2245 }
2246
2247 // Test drawing with two texture types accessed from the same shader and check that the result of
2248 // drawing is correct.
TEST_P(TextureCubeTest,CubeMapDraw)2249 TEST_P(TextureCubeTest, CubeMapDraw)
2250 {
2251 GLubyte texData[4];
2252 texData[0] = 0;
2253 texData[1] = 60;
2254 texData[2] = 0;
2255 texData[3] = 255;
2256
2257 glActiveTexture(GL_TEXTURE0);
2258 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2259 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
2260
2261 glActiveTexture(GL_TEXTURE1);
2262 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2263 texData[1] = 120;
2264 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2265 texData);
2266 EXPECT_GL_ERROR(GL_NO_ERROR);
2267
2268 glUseProgram(mProgram);
2269 glUniform1i(mTexture2DUniformLocation, 0);
2270 glUniform1i(mTextureCubeUniformLocation, 1);
2271 drawQuad(mProgram, "position", 0.5f);
2272 EXPECT_GL_NO_ERROR();
2273
2274 int px = getWindowWidth() - 1;
2275 int py = 0;
2276 EXPECT_PIXEL_NEAR(px, py, 0, 180, 0, 255, 2);
2277 }
2278
TEST_P(Sampler2DAsFunctionParameterTest,Sampler2DAsFunctionParameter)2279 TEST_P(Sampler2DAsFunctionParameterTest, Sampler2DAsFunctionParameter)
2280 {
2281 glActiveTexture(GL_TEXTURE0);
2282 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2283 GLubyte texData[4];
2284 texData[0] = 0;
2285 texData[1] = 128;
2286 texData[2] = 0;
2287 texData[3] = 255;
2288 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
2289 glUseProgram(mProgram);
2290 glUniform1i(mTexture2DUniformLocation, 0);
2291 drawQuad(mProgram, "position", 0.5f);
2292 EXPECT_GL_NO_ERROR();
2293
2294 EXPECT_PIXEL_NEAR(0, 0, 0, 128, 0, 255, 2);
2295 }
2296
2297 // Test drawing with two textures passed to the shader in a sampler array.
TEST_P(SamplerArrayTest,SamplerArrayDraw)2298 TEST_P(SamplerArrayTest, SamplerArrayDraw)
2299 {
2300 testSamplerArrayDraw();
2301 }
2302
2303 // Test drawing with two textures passed to the shader in a sampler array which is passed to a
2304 // user-defined function in the shader.
TEST_P(SamplerArrayAsFunctionParameterTest,SamplerArrayAsFunctionParameter)2305 TEST_P(SamplerArrayAsFunctionParameterTest, SamplerArrayAsFunctionParameter)
2306 {
2307 // TODO: Diagnose and fix. http://anglebug.com/2955
2308 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
2309
2310 testSamplerArrayDraw();
2311 }
2312
2313 // Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
TEST_P(Texture2DTestWithDrawScale,MipmapsTwice)2314 TEST_P(Texture2DTestWithDrawScale, MipmapsTwice)
2315 {
2316 int px = getWindowWidth() / 2;
2317 int py = getWindowHeight() / 2;
2318
2319 glActiveTexture(GL_TEXTURE0);
2320 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2321
2322 std::vector<GLColor> pixelsRed(16u * 16u, GLColor::red);
2323
2324 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
2325 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
2326 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2327 glGenerateMipmap(GL_TEXTURE_2D);
2328
2329 glUseProgram(mProgram);
2330 glUniform1i(mTexture2DUniformLocation, 0);
2331 glUniform2f(mDrawScaleUniformLocation, 0.0625f, 0.0625f);
2332 drawQuad(mProgram, "position", 0.5f);
2333 EXPECT_GL_NO_ERROR();
2334 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
2335
2336 std::vector<GLColor> pixelsBlue(16u * 16u, GLColor::blue);
2337
2338 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2339 pixelsBlue.data());
2340 glGenerateMipmap(GL_TEXTURE_2D);
2341
2342 drawQuad(mProgram, "position", 0.5f);
2343
2344 EXPECT_GL_NO_ERROR();
2345 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::blue);
2346
2347 std::vector<GLColor> pixelsGreen(16u * 16u, GLColor::green);
2348
2349 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2350 pixelsGreen.data());
2351 glGenerateMipmap(GL_TEXTURE_2D);
2352
2353 drawQuad(mProgram, "position", 0.5f);
2354
2355 EXPECT_GL_NO_ERROR();
2356 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
2357 }
2358
2359 // Test creating a FBO with a cube map render target, to test an ANGLE bug
2360 // https://code.google.com/p/angleproject/issues/detail?id=849
TEST_P(TextureCubeTest,CubeMapFBO)2361 TEST_P(TextureCubeTest, CubeMapFBO)
2362 {
2363 // http://anglebug.com/3145
2364 ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
2365
2366 GLFramebuffer fbo;
2367 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2368
2369 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2370 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
2371 mTextureCube, 0);
2372
2373 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2374 EXPECT_GL_NO_ERROR();
2375
2376 // Test clearing the six mip faces individually.
2377 std::array<GLColor, 6> faceColors = {{GLColor::red, GLColor::green, GLColor::blue,
2378 GLColor::yellow, GLColor::cyan, GLColor::magenta}};
2379
2380 for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
2381 {
2382 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2383 GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
2384
2385 Vector4 clearColorF = faceColors[faceIndex].toNormalizedVector();
2386 glClearColor(clearColorF.x(), clearColorF.y(), clearColorF.z(), clearColorF.w());
2387 glClear(GL_COLOR_BUFFER_BIT);
2388
2389 EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex]);
2390 }
2391
2392 // Iterate the faces again to make sure the colors haven't changed.
2393 for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
2394 {
2395 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2396 GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
2397 EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex])
2398 << "face color " << faceIndex << " shouldn't change";
2399 }
2400 }
2401
2402 // Tests clearing a cube map with a scissor enabled.
TEST_P(TextureCubeTest,CubeMapFBOScissoredClear)2403 TEST_P(TextureCubeTest, CubeMapFBOScissoredClear)
2404 {
2405 // http://anglebug.com/3145
2406 ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
2407
2408 constexpr size_t kSize = 16;
2409
2410 GLFramebuffer fbo;
2411 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2412 glViewport(0, 0, kSize, kSize);
2413
2414 GLTexture texcube;
2415 glBindTexture(GL_TEXTURE_CUBE_MAP, texcube);
2416 for (GLenum face = 0; face < 6; face++)
2417 {
2418 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
2419 GL_UNSIGNED_BYTE, nullptr);
2420 }
2421 ASSERT_GL_NO_ERROR();
2422
2423 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
2424 texcube, 0);
2425
2426 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2427 ASSERT_GL_NO_ERROR();
2428
2429 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2430 glClear(GL_COLOR_BUFFER_BIT);
2431 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2432
2433 glEnable(GL_SCISSOR_TEST);
2434 glScissor(kSize / 2, 0, kSize / 2, kSize);
2435 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2436 glClear(GL_COLOR_BUFFER_BIT);
2437
2438 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2439 EXPECT_PIXEL_COLOR_EQ(kSize / 2 + 1, 0, GLColor::green);
2440
2441 ASSERT_GL_NO_ERROR();
2442 }
2443
2444 // Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
2445 // default color.
TEST_P(Texture2DTest,TexStorage)2446 TEST_P(Texture2DTest, TexStorage)
2447 {
2448 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
2449 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
2450
2451 int width = getWindowWidth();
2452 int height = getWindowHeight();
2453
2454 GLTexture tex2D;
2455 glActiveTexture(GL_TEXTURE0);
2456 glBindTexture(GL_TEXTURE_2D, tex2D);
2457
2458 // Fill with red
2459 std::vector<GLubyte> pixels(3 * 16 * 16);
2460 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2461 {
2462 pixels[pixelId * 3 + 0] = 255;
2463 pixels[pixelId * 3 + 1] = 0;
2464 pixels[pixelId * 3 + 2] = 0;
2465 }
2466
2467 // ANGLE internally uses RGBA as the DirectX format for RGB images
2468 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent
2469 // alpha color. The data is kept in a CPU-side image and the image is marked as dirty.
2470 if (getClientMajorVersion() >= 3)
2471 {
2472 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2473 }
2474 else
2475 {
2476 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2477 }
2478
2479 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2480 // glTexSubImage2D should take into account that the image is dirty.
2481 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
2482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2483 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2484
2485 setUpProgram();
2486
2487 glUseProgram(mProgram);
2488 glUniform1i(mTexture2DUniformLocation, 0);
2489 drawQuad(mProgram, "position", 0.5f);
2490 EXPECT_GL_NO_ERROR();
2491 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2492
2493 // Validate that the region of the texture without data has an alpha of 1.0
2494 angle::GLColor pixel = ReadColor(3 * width / 4, 3 * height / 4);
2495 EXPECT_EQ(255, pixel.A);
2496 }
2497
2498 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2499 // initialized the image with a default color.
TEST_P(Texture2DTest,TexStorageWithPBO)2500 TEST_P(Texture2DTest, TexStorageWithPBO)
2501 {
2502 if (getClientMajorVersion() < 3)
2503 {
2504 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2505 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2506 }
2507
2508 const int width = getWindowWidth();
2509 const int height = getWindowHeight();
2510 const size_t pixelCount = width * height;
2511 const int componentCount = 3;
2512
2513 GLTexture tex2D;
2514 glActiveTexture(GL_TEXTURE0);
2515 glBindTexture(GL_TEXTURE_2D, tex2D);
2516
2517 // Fill with red
2518 std::vector<GLubyte> pixels(componentCount * pixelCount);
2519 for (size_t pixelId = 0; pixelId < pixelCount; ++pixelId)
2520 {
2521 pixels[pixelId * componentCount + 0] = 255;
2522 pixels[pixelId * componentCount + 1] = 0;
2523 pixels[pixelId * componentCount + 2] = 0;
2524 }
2525
2526 // Read 16x16 region from red backbuffer to PBO
2527 GLuint pbo;
2528 glGenBuffers(1, &pbo);
2529 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2530 glBufferData(GL_PIXEL_UNPACK_BUFFER, componentCount * pixelCount, pixels.data(),
2531 GL_STATIC_DRAW);
2532
2533 // ANGLE internally uses RGBA as the DirectX format for RGB images
2534 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent
2535 // alpha color. The data is kept in a CPU-side image and the image is marked as dirty.
2536 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, width, height);
2537
2538 // Initializes the color of the upper-left quadrant of pixels, leaves the other pixels
2539 // untouched. glTexSubImage2D should take into account that the image is dirty.
2540 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RGB, GL_UNSIGNED_BYTE,
2541 nullptr);
2542 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2543 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2544
2545 setUpProgram();
2546
2547 glUseProgram(mProgram);
2548 glUniform1i(mTexture2DUniformLocation, 0);
2549 drawQuad(mProgram, "position", 0.5f);
2550 glDeleteBuffers(1, &pbo);
2551 EXPECT_GL_NO_ERROR();
2552 EXPECT_PIXEL_RECT_EQ(0, 0, width / 2, height / 2, GLColor(255, 0, 0, 255));
2553 }
2554
2555 // Test that glTexSubImage2D combined with a PBO works properly after deleting the PBO
2556 // and drawing with the texture
2557 // Pseudo code for the follow test:
2558 // 1. Upload PBO to mTexture2D
2559 // 2. Delete PBO
2560 // 3. Draw with otherTexture (x5)
2561 // 4. Draw with mTexture2D
2562 // 5. Validate color output
TEST_P(Texture2DTest,PBOWithMultipleDraws)2563 TEST_P(Texture2DTest, PBOWithMultipleDraws)
2564 {
2565 if (getClientMajorVersion() < 3)
2566 {
2567 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2568 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2569 }
2570
2571 const GLuint width = getWindowWidth();
2572 const GLuint height = getWindowHeight();
2573 const GLuint windowPixelCount = width * height;
2574 std::vector<GLColor> pixelsRed(windowPixelCount, GLColor::red);
2575 std::vector<GLColor> pixelsGreen(windowPixelCount, GLColor::green);
2576
2577 // Create secondary draw that does not use mTexture
2578 const char *vertexShaderSource = getVertexShaderSource();
2579 const char *fragmentShaderSource = getFragmentShaderSource();
2580 ANGLE_GL_PROGRAM(otherProgram, vertexShaderSource, fragmentShaderSource);
2581
2582 GLint uniformLoc = glGetUniformLocation(otherProgram, getTextureUniformName());
2583 ASSERT_NE(-1, uniformLoc);
2584 glUseProgram(0);
2585
2586 // Create secondary Texture to draw with
2587 GLTexture otherTexture;
2588 glActiveTexture(GL_TEXTURE0);
2589 glBindTexture(GL_TEXTURE_2D, otherTexture);
2590 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2591 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
2592 pixelsRed.data());
2593 ASSERT_GL_NO_ERROR();
2594
2595 // Setup primary Texture
2596 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2598 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2599 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2600 ASSERT_GL_NO_ERROR();
2601
2602 // Setup PBO
2603 GLuint pbo = 0;
2604 glGenBuffers(1, &pbo);
2605 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2606 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
2607 GL_STATIC_DRAW);
2608 ASSERT_GL_NO_ERROR();
2609
2610 // Write PBO to mTexture
2611 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2612 ASSERT_GL_NO_ERROR();
2613 // Delete PBO as ANGLE should be properly handling refcount of this buffer
2614 glDeleteBuffers(1, &pbo);
2615 pixelsGreen.clear();
2616
2617 // Do 5 draws not involving primary texture that the PBO updated
2618 glUseProgram(otherProgram);
2619 glUniform1i(uniformLoc, 0);
2620 glBindTexture(GL_TEXTURE_2D, otherTexture);
2621 drawQuad(otherProgram, "position", 0.5f);
2622 glBindTexture(GL_TEXTURE_2D, 0);
2623 glUseProgram(0);
2624
2625 glUseProgram(otherProgram);
2626 glUniform1i(uniformLoc, 0);
2627 glBindTexture(GL_TEXTURE_2D, otherTexture);
2628 drawQuad(otherProgram, "position", 0.5f);
2629 glBindTexture(GL_TEXTURE_2D, 0);
2630 glUseProgram(0);
2631
2632 glUseProgram(otherProgram);
2633 glUniform1i(uniformLoc, 0);
2634 glBindTexture(GL_TEXTURE_2D, otherTexture);
2635 drawQuad(otherProgram, "position", 0.5f);
2636 glBindTexture(GL_TEXTURE_2D, 0);
2637 glUseProgram(0);
2638
2639 glUseProgram(otherProgram);
2640 glUniform1i(uniformLoc, 0);
2641 glBindTexture(GL_TEXTURE_2D, otherTexture);
2642 drawQuad(otherProgram, "position", 0.5f);
2643 glBindTexture(GL_TEXTURE_2D, 0);
2644 glUseProgram(0);
2645 ASSERT_GL_NO_ERROR();
2646
2647 std::vector<GLColor> output(windowPixelCount, GLColor::black);
2648 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2649 output.data());
2650 EXPECT_EQ(pixelsRed, output);
2651
2652 setUpProgram();
2653 // Draw using PBO updated texture
2654 glUseProgram(mProgram);
2655 glUniform1i(mTexture2DUniformLocation, 0);
2656 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2657 drawQuad(mProgram, "position", 0.5f);
2658 ASSERT_GL_NO_ERROR();
2659
2660 std::vector<GLColor> actual(windowPixelCount, GLColor::black);
2661 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2662 actual.data());
2663 // Value should be green as it was updated during PBO transfer to mTexture
2664 std::vector<GLColor> expected(windowPixelCount, GLColor::green);
2665 EXPECT_EQ(expected, actual);
2666 }
2667
2668 // Test that stencil texture uploads work.
TEST_P(Texture2DTestES3,TexImageWithStencilData)2669 TEST_P(Texture2DTestES3, TexImageWithStencilData)
2670 {
2671 constexpr GLsizei kSize = 4;
2672
2673 const std::array<std::tuple<GLenum, GLenum, int, int>, 3> testConfigs = {
2674 std::make_tuple(GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, 4),
2675 std::make_tuple(GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, 4, 0),
2676 std::make_tuple(GL_STENCIL_INDEX8, GL_UNSIGNED_BYTE, 1, 0)};
2677
2678 for (auto testConfig : testConfigs)
2679 {
2680 const GLenum format = std::get<0>(testConfig);
2681 const GLenum type = std::get<1>(testConfig);
2682 const GLenum typeLength = std::get<2>(testConfig);
2683 const GLenum typeOffset = std::get<3>(testConfig);
2684
2685 ANGLE_SKIP_TEST_IF(format == GL_STENCIL_INDEX8 &&
2686 !IsGLExtensionEnabled("GL_OES_texture_stencil8"));
2687
2688 // Set up the framebuffer
2689 GLTexture colorTexture;
2690 glBindTexture(GL_TEXTURE_2D, colorTexture);
2691 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2692 nullptr);
2693 ASSERT_GL_NO_ERROR();
2694
2695 GLTexture depthStencilTexture;
2696 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
2697
2698 GLubyte pixels[kSize * kSize * 8] = {};
2699 for (size_t pixelId = 0; pixelId < kSize * kSize; ++pixelId)
2700 {
2701 pixels[pixelId * typeLength + typeOffset] = 0xD5;
2702 }
2703 glTexImage2D(GL_TEXTURE_2D, 0, format, kSize, kSize, 0,
2704 format == GL_STENCIL_INDEX8 ? GL_STENCIL_INDEX : GL_DEPTH_STENCIL, type,
2705 pixels);
2706 ASSERT_GL_NO_ERROR();
2707
2708 GLFramebuffer fbo;
2709 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2710 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
2711 0);
2712 glFramebufferTexture2D(
2713 GL_FRAMEBUFFER,
2714 format == GL_STENCIL_INDEX8 ? GL_STENCIL_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT,
2715 GL_TEXTURE_2D, depthStencilTexture, 0);
2716 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2717 ASSERT_GL_NO_ERROR();
2718
2719 // Clear only color.
2720 glClearColor(0, 0, 0, 1);
2721 glClear(GL_COLOR_BUFFER_BIT);
2722 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
2723
2724 // If stencil is not set to 0xD5, rendering would fail.
2725 glEnable(GL_STENCIL_TEST);
2726 glStencilFunc(GL_EQUAL, 0xD5, 0xFF);
2727 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2728 glStencilMask(0xFF);
2729
2730 // Draw red
2731 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2732 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f);
2733 ASSERT_GL_NO_ERROR();
2734
2735 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
2736 }
2737 }
2738
2739 // Test that glTexSubImage2D combined with a PBO works properly. PBO has all pixels as red
2740 // except the middle one being green.
TEST_P(Texture2DTest,TexStorageWithPBOMiddlePixelDifferent)2741 TEST_P(Texture2DTest, TexStorageWithPBOMiddlePixelDifferent)
2742 {
2743 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2744 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2745
2746 int width = getWindowWidth();
2747 int height = getWindowHeight();
2748
2749 GLTexture tex2D;
2750 glActiveTexture(GL_TEXTURE0);
2751 glBindTexture(GL_TEXTURE_2D, tex2D);
2752
2753 std::vector<GLubyte> pixels(3 * 16 * 16);
2754
2755 // Initialize texture with default black color.
2756 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2757 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
2758
2759 // Fill PBO's data with red, with middle one as green
2760 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2761 {
2762 if (pixelId == 8 * 7 + 7)
2763 {
2764 pixels[pixelId * 3 + 0] = 0;
2765 pixels[pixelId * 3 + 1] = 255;
2766 pixels[pixelId * 3 + 2] = 0;
2767 }
2768 else
2769 {
2770 pixels[pixelId * 3 + 0] = 255;
2771 pixels[pixelId * 3 + 1] = 0;
2772 pixels[pixelId * 3 + 2] = 0;
2773 }
2774 }
2775
2776 GLuint pbo;
2777 glGenBuffers(1, &pbo);
2778 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2779 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
2780
2781 // Update the color of the texture's upper-left 8x8 pixels, leaves the other pixels untouched.
2782 // glTexSubImage2D should take into account that the image is dirty.
2783 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
2784 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2785 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2786
2787 setUpProgram();
2788
2789 glUseProgram(mProgram);
2790 glUniform1i(mTexture2DUniformLocation, 0);
2791 drawQuad(mProgram, "position", 0.5f);
2792 glDeleteBuffers(1, &pbo);
2793 EXPECT_GL_NO_ERROR();
2794 EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
2795 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2796 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
2797 }
2798
2799 // Test that glTexSubImage2D combined with a PBO works properly when glTexImage2D has
2800 // initialized the image with a luminance color
TEST_P(Texture2DTest,TexImageWithLuminancePBO)2801 TEST_P(Texture2DTest, TexImageWithLuminancePBO)
2802 {
2803 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2804
2805 int width = getWindowWidth();
2806 int height = getWindowHeight();
2807
2808 GLTexture tex2D;
2809 glActiveTexture(GL_TEXTURE0);
2810 glBindTexture(GL_TEXTURE_2D, tex2D);
2811
2812 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 16, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
2813 nullptr);
2814
2815 // Fill PBO with white, with middle one as grey
2816 std::vector<GLubyte> pixels(16 * 16);
2817 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2818 {
2819 if (pixelId == 8 * 7 + 7)
2820 {
2821 pixels[pixelId] = 128;
2822 }
2823 else
2824 {
2825 pixels[pixelId] = 255;
2826 }
2827 }
2828
2829 GLuint pbo;
2830 glGenBuffers(1, &pbo);
2831 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2832 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16, pixels.data(), GL_STATIC_DRAW);
2833
2834 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2835 // glTexSubImage2D should take into account that the image is dirty.
2836 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
2837 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2838 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2839
2840 setUpProgram();
2841
2842 glUseProgram(mProgram);
2843 glUniform1i(mTexture2DUniformLocation, 0);
2844 drawQuad(mProgram, "position", 0.5f);
2845 glDeleteBuffers(1, &pbo);
2846 EXPECT_GL_NO_ERROR();
2847 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 255, 255, 255);
2848 EXPECT_PIXEL_NEAR(width / 2 - 1, height / 2 - 1, 128, 128, 128, 255, 1);
2849 }
2850
2851 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2852 // initialized the image with a RGB656 color
TEST_P(Texture2DTest,TexImageWithRGB565PBO)2853 TEST_P(Texture2DTest, TexImageWithRGB565PBO)
2854 {
2855 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2856 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2857
2858 int width = getWindowWidth();
2859 int height = getWindowHeight();
2860
2861 GLTexture tex2D;
2862 glActiveTexture(GL_TEXTURE0);
2863 glBindTexture(GL_TEXTURE_2D, tex2D);
2864
2865 // Fill PBO with red, with middle one as green
2866 std::vector<GLushort> pixels(16 * 16);
2867 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2868 {
2869 if (pixelId == 8 * 7 + 8)
2870 {
2871 pixels[pixelId] = 0x7E0;
2872 }
2873 else
2874 {
2875 pixels[pixelId] = 0xF800;
2876 }
2877 }
2878
2879 GLuint pbo;
2880 glGenBuffers(1, &pbo);
2881 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2882 glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
2883
2884 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB565, 16, 16);
2885
2886 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2887 // glTexSubImage2D should take into account that the image is dirty.
2888 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
2889 reinterpret_cast<void *>(2));
2890 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2891 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2892
2893 setUpProgram();
2894
2895 glUseProgram(mProgram);
2896 glUniform1i(mTexture2DUniformLocation, 0);
2897 drawQuad(mProgram, "position", 0.5f);
2898 glDeleteBuffers(1, &pbo);
2899 EXPECT_GL_NO_ERROR();
2900 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2901 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
2902 }
2903
2904 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2905 // initialized the image with a RGBA4444 color
TEST_P(Texture2DTest,TexImageWithRGBA4444PBO)2906 TEST_P(Texture2DTest, TexImageWithRGBA4444PBO)
2907 {
2908 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2909 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2910
2911 int width = getWindowWidth();
2912 int height = getWindowHeight();
2913
2914 GLTexture tex2D;
2915 glActiveTexture(GL_TEXTURE0);
2916 glBindTexture(GL_TEXTURE_2D, tex2D);
2917
2918 // Fill PBO with red, with middle one as green
2919 std::vector<GLushort> pixels(16 * 16);
2920 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2921 {
2922 if (pixelId == 8 * 7 + 8)
2923 {
2924 pixels[pixelId] = 0xF0F;
2925 }
2926 else
2927 {
2928 pixels[pixelId] = 0xF00F;
2929 }
2930 }
2931
2932 GLuint pbo;
2933 glGenBuffers(1, &pbo);
2934 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2935 glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
2936
2937 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA4, 16, 16);
2938
2939 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2940 // glTexSubImage2D should take into account that the image is dirty.
2941 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
2942 reinterpret_cast<void *>(2));
2943 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2944 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2945
2946 setUpProgram();
2947
2948 glUseProgram(mProgram);
2949 glUniform1i(mTexture2DUniformLocation, 0);
2950 drawQuad(mProgram, "position", 0.5f);
2951 glDeleteBuffers(1, &pbo);
2952 EXPECT_GL_NO_ERROR();
2953 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2954 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
2955 }
2956
2957 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2958 // initialized the image with a RGBA5551 color
TEST_P(Texture2DTest,TexImageWithRGBA5551PBO)2959 TEST_P(Texture2DTest, TexImageWithRGBA5551PBO)
2960 {
2961 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2962 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2963
2964 int width = getWindowWidth();
2965 int height = getWindowHeight();
2966
2967 GLTexture tex2D;
2968 glActiveTexture(GL_TEXTURE0);
2969 glBindTexture(GL_TEXTURE_2D, tex2D);
2970
2971 // Fill PBO with red, with middle one as green
2972 std::vector<GLushort> pixels(16 * 16);
2973 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2974 {
2975 if (pixelId == 8 * 7 + 7)
2976 {
2977 pixels[pixelId] = 0x7C1;
2978 }
2979 else
2980 {
2981 pixels[pixelId] = 0xF801;
2982 }
2983 }
2984
2985 GLuint pbo;
2986 glGenBuffers(1, &pbo);
2987 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2988 glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
2989
2990 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB5_A1, 16, 16);
2991
2992 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2993 // glTexSubImage2D should take into account that the image is dirty.
2994 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, nullptr);
2995 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2996 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2997
2998 setUpProgram();
2999
3000 glUseProgram(mProgram);
3001 glUniform1i(mTexture2DUniformLocation, 0);
3002 drawQuad(mProgram, "position", 0.5f);
3003 glDeleteBuffers(1, &pbo);
3004 EXPECT_GL_NO_ERROR();
3005 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
3006 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
3007 }
3008
3009 // Test that glTexSubImage2D from a PBO respects GL_UNPACK_ROW_LENGTH.
TEST_P(Texture2DTest,TexImageUnpackRowLengthPBO)3010 TEST_P(Texture2DTest, TexImageUnpackRowLengthPBO)
3011 {
3012 if (getClientMajorVersion() < 3)
3013 {
3014 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3015 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3016 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_unpack_subimage"));
3017 }
3018
3019 const int width = getWindowWidth() / 2;
3020 const int height = getWindowHeight();
3021 const int rowLength = getWindowWidth();
3022 const int bufferSize = rowLength * height;
3023
3024 GLTexture tex2D;
3025 glActiveTexture(GL_TEXTURE0);
3026 glBindTexture(GL_TEXTURE_2D, tex2D);
3027
3028 std::vector<GLColor> pixels(bufferSize);
3029 for (int y = 0; y < rowLength; ++y)
3030 {
3031 for (int x = 0; x < width; ++x)
3032 {
3033 pixels[y * rowLength + x] =
3034 x < width ? (y < height / 2 ? GLColor::green : GLColor::blue) : GLColor::red;
3035 }
3036 }
3037
3038 GLuint pbo;
3039 glGenBuffers(1, &pbo);
3040 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3041 glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize * sizeof(GLColor), pixels.data(),
3042 GL_STATIC_DRAW);
3043
3044 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
3045
3046 // Initializes the texture from width x height of the PBO.
3047 glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength);
3048 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3049 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3050 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3051
3052 setUpProgram();
3053
3054 glUseProgram(mProgram);
3055 glUniform1i(mTexture2DUniformLocation, 0);
3056 drawQuad(mProgram, "position", 0.5f);
3057 glDeleteBuffers(1, &pbo);
3058 EXPECT_GL_NO_ERROR();
3059 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3060 EXPECT_PIXEL_COLOR_EQ(0, height - 1, GLColor::blue);
3061 }
3062
3063 // Test if the KHR debug label is set and passed to D3D correctly using glCopyTexImage2D.
TEST_P(Texture2DTest,TextureKHRDebugLabelWithCopyTexImage2D)3064 TEST_P(Texture2DTest, TextureKHRDebugLabelWithCopyTexImage2D)
3065 {
3066 GLTexture texture2D;
3067 glBindTexture(GL_TEXTURE_2D, texture2D);
3068
3069 // Create a texture and copy into, to initialize storage object.
3070 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 32, 32, 0);
3071
3072 // Set KHR Debug Label.
3073 std::string label = "TestKHR.DebugLabel";
3074 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3075
3076 std::vector<char> labelBuf(label.length() + 1);
3077 GLsizei labelLengthBuf = 0;
3078
3079 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3080 &labelLengthBuf, labelBuf.data());
3081
3082 EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
3083 EXPECT_STREQ(label.c_str(), labelBuf.data());
3084
3085 // Delete the texture.
3086 texture2D.reset();
3087 EXPECT_GL_NO_ERROR();
3088
3089 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3090 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3091
3092 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3093 &labelLengthBuf, labelBuf.data());
3094 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3095 }
3096
3097 // Test to call labeling API before the storage texture is created.
TEST_P(Texture2DTest,CallKHRDebugLabelBeforeTexStorageCreation)3098 TEST_P(Texture2DTest, CallKHRDebugLabelBeforeTexStorageCreation)
3099 {
3100 GLTexture texture2D;
3101 glBindTexture(GL_TEXTURE_2D, texture2D);
3102
3103 // Set label before texture storage creation.
3104 std::string label = "TestKHR.DebugLabel";
3105 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3106
3107 // Create a texture and copy into, to initialize storage object.
3108 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 32, 32, 0);
3109
3110 std::vector<char> labelBuf(label.length() + 1);
3111 GLsizei labelLengthBuf = 0;
3112
3113 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3114 &labelLengthBuf, labelBuf.data());
3115
3116 EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
3117 EXPECT_STREQ(label.c_str(), labelBuf.data());
3118
3119 // Delete the texture.
3120 texture2D.reset();
3121 EXPECT_GL_NO_ERROR();
3122
3123 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3124 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3125
3126 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3127 &labelLengthBuf, labelBuf.data());
3128 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3129 }
3130
3131 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3132 // initialized the image with a depth-only format.
TEST_P(Texture2DTestES3,TexImageWithDepthPBO)3133 TEST_P(Texture2DTestES3, TexImageWithDepthPBO)
3134 {
3135 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3136 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3137
3138 // http://anglebug.com/5315
3139 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3140
3141 constexpr GLsizei kSize = 4;
3142
3143 // Set up the framebuffer.
3144 GLTexture colorTexture;
3145 glBindTexture(GL_TEXTURE_2D, colorTexture);
3146 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3147 ASSERT_GL_NO_ERROR();
3148
3149 GLTexture depthTexture;
3150 glBindTexture(GL_TEXTURE_2D, depthTexture);
3151 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, kSize, kSize);
3152 ASSERT_GL_NO_ERROR();
3153
3154 GLFramebuffer fbo;
3155 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3156 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3157 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
3158 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3159 ASSERT_GL_NO_ERROR();
3160
3161 // Clear depth to 0, ensuring the texture's image is allocated.
3162 glClearDepthf(0);
3163 glClearColor(0, 0, 0, 1);
3164 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3165 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3166
3167 // Fill depth with 1.0f.
3168 std::vector<GLushort> pixels(kSize * kSize);
3169 for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3170 {
3171 pixels[pixelId] = 0xFFFF;
3172 }
3173
3174 GLuint pbo;
3175 glGenBuffers(1, &pbo);
3176 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3177 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3178 GL_STATIC_DRAW);
3179 ASSERT_GL_NO_ERROR();
3180
3181 // Upload PBO data.
3182 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
3183 nullptr);
3184
3185 // If depth is not set to 1, rendering would fail.
3186 glEnable(GL_DEPTH_TEST);
3187 glDepthFunc(GL_LESS);
3188
3189 // Draw red
3190 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3191 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3192 ASSERT_GL_NO_ERROR();
3193
3194 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3195 }
3196
3197 // Test sampling modes with a DEPTH_COMPONENT16 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth16)3198 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth16)
3199 {
3200 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, false);
3201 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX, false);
3202 }
3203
3204 // Test sampling modes with a swizzled DEPTH_COMPONENT16 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth16Swizzled)3205 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth16Swizzled)
3206 {
3207 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, true);
3208 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX, true);
3209 }
3210
3211 // Test sampling modes with a DEPTH_COMPONENT24 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24)3212 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24)
3213 {
3214 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, false);
3215 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_STENCIL_INDEX, false);
3216 }
3217
3218 // Test sampling modes with a swizzled DEPTH_COMPONENT24 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Swizzled)3219 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Swizzled)
3220 {
3221 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, true);
3222 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_STENCIL_INDEX, true);
3223 }
3224
3225 // Test depth sampling with a DEPTH_COMPONENT32F texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32f)3226 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32f)
3227 {
3228 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, false);
3229 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_STENCIL_INDEX, false);
3230 }
3231
3232 // Test depth sampling with a swizzled DEPTH_COMPONENT32F texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fSwizzled)3233 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fSwizzled)
3234 {
3235 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, true);
3236 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_STENCIL_INDEX, true);
3237 }
3238
3239 // Test sampling modes with a DEPTH24_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Stencil8)3240 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Stencil8)
3241 {
3242 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT, false);
3243 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX, false);
3244 }
3245
3246 // Test sampling modes with a swizzled DEPTH24_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Stencil8Swizzled)3247 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Stencil8Swizzled)
3248 {
3249 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT, true);
3250 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX, true);
3251 }
3252
3253 // Test sampling modes with a DEPTH32F_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fStencil8)3254 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fStencil8)
3255 {
3256 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT, false);
3257 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_STENCIL_INDEX, false);
3258 }
3259
3260 // Test sampling modes with a swizzled DEPTH32F_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fStencil8Swizzled)3261 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fStencil8Swizzled)
3262 {
3263 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT, true);
3264 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_STENCIL_INDEX, true);
3265 }
3266
3267 // Test sampling modes with a STENCIL_INDEX8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithStencil8)3268 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithStencil8)
3269 {
3270 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_stencil8"));
3271 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_DEPTH_COMPONENT, false);
3272 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, false);
3273 }
3274
3275 // Test sampling modes with a swizzled STENCIL_INDEX8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithStencil8Swizzled)3276 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithStencil8Swizzled)
3277 {
3278 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_stencil8"));
3279 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_DEPTH_COMPONENT, true);
3280 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, true);
3281 }
3282
3283 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3284 // initialized the image with a stencil-only format.
TEST_P(Texture2DTestES3,TexImageWithStencilPBO)3285 TEST_P(Texture2DTestES3, TexImageWithStencilPBO)
3286 {
3287 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3288 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3289
3290 // http://anglebug.com/5315
3291 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3292
3293 constexpr GLsizei kSize = 4;
3294
3295 // Set up the framebuffer.
3296 GLTexture colorTexture;
3297 glBindTexture(GL_TEXTURE_2D, colorTexture);
3298 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3299 ASSERT_GL_NO_ERROR();
3300
3301 GLTexture stencilTexture;
3302 glBindTexture(GL_TEXTURE_2D, stencilTexture);
3303 glTexStorage2D(GL_TEXTURE_2D, 1, GL_STENCIL_INDEX8, kSize, kSize);
3304 ASSERT_GL_NO_ERROR();
3305
3306 GLFramebuffer fbo;
3307 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3308 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3309 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, stencilTexture, 0);
3310 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3311 ASSERT_GL_NO_ERROR();
3312
3313 // Clear stencil to 0, ensuring the texture's image is allocated.
3314 glClearStencil(0);
3315 glClearColor(0, 0, 0, 1);
3316 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3317 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3318
3319 // Fill stencil with 0x4E
3320 std::vector<GLubyte> pixels(kSize * kSize);
3321 for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3322 {
3323 pixels[pixelId] = 0x4E;
3324 }
3325
3326 GLuint pbo;
3327 glGenBuffers(1, &pbo);
3328 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3329 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3330 GL_STATIC_DRAW);
3331 ASSERT_GL_NO_ERROR();
3332
3333 // Upload PBO data.
3334 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
3335 nullptr);
3336 ASSERT_GL_NO_ERROR();
3337
3338 // If stencil is not set to 0x4E, rendering would fail.
3339 glEnable(GL_STENCIL_TEST);
3340 glStencilFunc(GL_EQUAL, 0x4E, 0xFF);
3341 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3342 glStencilMask(0xFF);
3343
3344 // Draw red
3345 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3346 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3347 ASSERT_GL_NO_ERROR();
3348
3349 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3350 }
3351
3352 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3353 // initialized the image with a depth/stencil format.
TEST_P(Texture2DTestES3,TexImageWithDepthStencilPBO)3354 TEST_P(Texture2DTestES3, TexImageWithDepthStencilPBO)
3355 {
3356 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3357 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3358
3359 // http://anglebug.com/5313
3360 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
3361
3362 // http://anglebug.com/5315
3363 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3364
3365 constexpr GLsizei kSize = 4;
3366
3367 // Set up the framebuffer.
3368 GLTexture colorTexture;
3369 glBindTexture(GL_TEXTURE_2D, colorTexture);
3370 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3371 ASSERT_GL_NO_ERROR();
3372
3373 GLTexture depthStencilTexture;
3374 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
3375 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
3376 ASSERT_GL_NO_ERROR();
3377
3378 GLFramebuffer fbo;
3379 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3380 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3381 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
3382 depthStencilTexture, 0);
3383 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3384 ASSERT_GL_NO_ERROR();
3385
3386 // Clear depth and stencil to 0, ensuring the texture's image is allocated.
3387 glClearDepthf(0);
3388 glClearStencil(0);
3389 glClearColor(0, 0, 0, 1);
3390 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3391 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3392
3393 // Fill depth with 1.0f and stencil with 0xD5
3394 std::vector<GLuint> pixels(kSize * kSize);
3395 for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3396 {
3397 pixels[pixelId] = 0xFFFFFFD5;
3398 }
3399
3400 GLuint pbo;
3401 glGenBuffers(1, &pbo);
3402 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3403 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3404 GL_STATIC_DRAW);
3405 ASSERT_GL_NO_ERROR();
3406
3407 // Upload PBO data.
3408 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8,
3409 nullptr);
3410
3411 // If depth is not set to 1, rendering would fail.
3412 glEnable(GL_DEPTH_TEST);
3413 glDepthFunc(GL_LESS);
3414
3415 // If stencil is not set to 0xD5, rendering would fail.
3416 glEnable(GL_STENCIL_TEST);
3417 glStencilFunc(GL_EQUAL, 0xD5, 0xFF);
3418 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3419 glStencilMask(0xFF);
3420
3421 // Draw red
3422 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3423 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3424 ASSERT_GL_NO_ERROR();
3425
3426 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3427 }
3428
3429 // Test functionality of GL_ANGLE_yuv_internal_format with min/mag filters
3430 // set to nearest and linear modes.
TEST_P(Texture2DTestES3YUV,TexStorage2DYuvFilterModes)3431 TEST_P(Texture2DTestES3YUV, TexStorage2DYuvFilterModes)
3432 {
3433 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3434
3435 // Create YUV texture
3436 GLTexture yuvTexture;
3437 GLubyte yuvColor[] = {40, 40, 40, 40, 40, 40, 40, 40, 240, 109, 240, 109};
3438 GLubyte expectedRgbColor[] = {0, 0, 255, 255};
3439 createImmutableTexture2D(yuvTexture, 2, 4, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3440 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3441
3442 // Default is nearest filter mode
3443 verifyResults2D(yuvTexture, expectedRgbColor);
3444 ASSERT_GL_NO_ERROR();
3445
3446 // Enable linear filter mode
3447 glBindTexture(GL_TEXTURE_2D, yuvTexture);
3448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3450 verifyResults2D(yuvTexture, expectedRgbColor);
3451 ASSERT_GL_NO_ERROR();
3452
3453 const int windowHeight = getWindowHeight();
3454 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::blue, 1);
3455 EXPECT_PIXEL_COLOR_NEAR(0, windowHeight - 1, GLColor::blue, 1);
3456 EXPECT_PIXEL_COLOR_NEAR(0, windowHeight / 2, GLColor::blue, 1);
3457 }
3458
3459 // Test functionality of GL_ANGLE_yuv_internal_format while cycling through RGB and YUV sources
TEST_P(Texture2DTestES3,TexStorage2DCycleThroughYuvAndRgbSources)3460 TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvAndRgbSources)
3461 {
3462 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3463
3464 // Create YUV texture
3465 GLTexture yuvTexture;
3466 GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109};
3467 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
3468 createImmutableTexture2D(yuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3469 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3470
3471 // Create RGBA texture
3472 GLTexture rgbaTexture;
3473 GLubyte rgbaColor[4] = {0, 0, 255, 255};
3474 createImmutableTexture2D(rgbaTexture, 1, 1, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, 1, rgbaColor);
3475
3476 // Cycle through source textures
3477 // RGBA source
3478 verifyResults2D(rgbaTexture, rgbaColor);
3479 ASSERT_GL_NO_ERROR();
3480
3481 // YUV source
3482 verifyResults2D(yuvTexture, expectedRgbColor);
3483 ASSERT_GL_NO_ERROR();
3484
3485 // RGBA source
3486 verifyResults2D(rgbaTexture, rgbaColor);
3487 ASSERT_GL_NO_ERROR();
3488 }
3489
3490 // Test functionality of GL_ANGLE_yuv_internal_format with large number of YUV sources
TEST_P(Texture2DTestES3,TexStorage2DLargeYuvTextureCount)3491 TEST_P(Texture2DTestES3, TexStorage2DLargeYuvTextureCount)
3492 {
3493 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3494
3495 constexpr uint32_t kTextureCount = 16;
3496
3497 // Create YUV texture
3498 GLTexture yuvTexture[kTextureCount];
3499 for (uint32_t i = 0; i < kTextureCount; i++)
3500 {
3501 // Create 2 plane YCbCr 420 texture
3502 createImmutableTexture2D(yuvTexture[i], 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3503 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3504 }
3505
3506 // Cycle through YUV source textures
3507 glUseProgram(mProgram);
3508 glUniform1i(mTexture2DUniformLocation, 0);
3509
3510 for (uint32_t i = 0; i < kTextureCount; i++)
3511 {
3512 glBindTexture(GL_TEXTURE_2D, yuvTexture[i]);
3513 drawQuad(mProgram, "position", 0.5f);
3514 ASSERT_GL_NO_ERROR();
3515 }
3516 }
3517
3518 // Test functionality of GL_ANGLE_yuv_internal_format with simultaneous use of multiple YUV sources
TEST_P(Texture2DTestES3,TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData)3519 TEST_P(Texture2DTestES3, TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData)
3520 {
3521 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3522
3523 // Create YUV texture
3524 // Create 2 plane YCbCr 420 texture
3525 GLTexture twoPlaneYuvTexture;
3526 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3527 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3528
3529 // Create 3 plane YCbCr 420 texture
3530 GLTexture threePlaneYuvTexture;
3531 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
3532 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3533
3534 // Cycle through YUV source textures
3535 // Create program with 2 samplers
3536 const char *vertexShaderSource = getVertexShaderSource();
3537 const char *fragmentShaderSource = R"(#version 300 es
3538 precision highp float;
3539 uniform sampler2D tex0;
3540 uniform sampler2D tex1;
3541 in vec2 texcoord;
3542 out vec4 fragColor;
3543
3544 void main()
3545 {
3546 vec4 color0 = texture(tex0, texcoord);
3547 vec4 color1 = texture(tex1, texcoord);
3548 fragColor = color0 + color1;
3549 })";
3550
3551 ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
3552 glUseProgram(twoSamplersProgram);
3553 GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
3554 ASSERT_NE(-1, tex0Location);
3555 GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
3556 ASSERT_NE(-1, tex1Location);
3557
3558 glUniform1i(tex0Location, 0);
3559 glUniform1i(tex1Location, 1);
3560
3561 // Bind 2 plane YUV source
3562 glActiveTexture(GL_TEXTURE0);
3563 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3564 ASSERT_GL_NO_ERROR();
3565
3566 // Bind 3 plane YUV source
3567 glActiveTexture(GL_TEXTURE1);
3568 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3569 ASSERT_GL_NO_ERROR();
3570
3571 drawQuad(twoSamplersProgram, "position", 0.5f);
3572 ASSERT_GL_NO_ERROR();
3573
3574 // Switch active texture index and draw again
3575 // Bind 2 plane YUV source
3576 glActiveTexture(GL_TEXTURE1);
3577 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3578 ASSERT_GL_NO_ERROR();
3579
3580 // Bind 3 plane YUV source
3581 glActiveTexture(GL_TEXTURE0);
3582 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3583 ASSERT_GL_NO_ERROR();
3584
3585 drawQuad(twoSamplersProgram, "position", 0.5f);
3586 ASSERT_GL_NO_ERROR();
3587 }
3588
3589 // Test functional of GL_ANGLE_yuv_internal_format while cycling through YUV sources
TEST_P(Texture2DTestES3,TexStorage2DCycleThroughYuvSourcesNoData)3590 TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvSourcesNoData)
3591 {
3592 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3593
3594 // Create YUV texture
3595 // Create 2 plane YCbCr 420 texture
3596 GLTexture twoPlaneYuvTexture;
3597 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3598 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3599
3600 // Create 3 plane YCbCr 420 texture
3601 GLTexture threePlaneYuvTexture;
3602 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
3603 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3604
3605 // Cycle through YUV source textures
3606 glUseProgram(mProgram);
3607 glUniform1i(mTexture2DUniformLocation, 0);
3608
3609 // 2 plane YUV source
3610 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3611 drawQuad(mProgram, "position", 0.5f);
3612 ASSERT_GL_NO_ERROR();
3613
3614 // 3 plane YUV source
3615 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3616 drawQuad(mProgram, "position", 0.5f);
3617 ASSERT_GL_NO_ERROR();
3618
3619 // 2 plane YUV source
3620 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3621 drawQuad(mProgram, "position", 0.5f);
3622 ASSERT_GL_NO_ERROR();
3623 }
3624
3625 // Tests CopySubImage for float formats
TEST_P(Texture2DTest,CopySubImageFloat_R_R)3626 TEST_P(Texture2DTest, CopySubImageFloat_R_R)
3627 {
3628 testFloatCopySubImage(1, 1);
3629 }
3630
TEST_P(Texture2DTest,CopySubImageFloat_RG_R)3631 TEST_P(Texture2DTest, CopySubImageFloat_RG_R)
3632 {
3633 testFloatCopySubImage(2, 1);
3634 }
3635
TEST_P(Texture2DTest,CopySubImageFloat_RG_RG)3636 TEST_P(Texture2DTest, CopySubImageFloat_RG_RG)
3637 {
3638 testFloatCopySubImage(2, 2);
3639 }
3640
TEST_P(Texture2DTest,CopySubImageFloat_RGB_R)3641 TEST_P(Texture2DTest, CopySubImageFloat_RGB_R)
3642 {
3643 testFloatCopySubImage(3, 1);
3644 }
3645
TEST_P(Texture2DTest,CopySubImageFloat_RGB_RG)3646 TEST_P(Texture2DTest, CopySubImageFloat_RGB_RG)
3647 {
3648 testFloatCopySubImage(3, 2);
3649 }
3650
TEST_P(Texture2DTest,CopySubImageFloat_RGB_RGB)3651 TEST_P(Texture2DTest, CopySubImageFloat_RGB_RGB)
3652 {
3653 // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/1346)
3654 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3655
3656 testFloatCopySubImage(3, 3);
3657 }
3658
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_R)3659 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_R)
3660 {
3661 testFloatCopySubImage(4, 1);
3662 }
3663
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RG)3664 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RG)
3665 {
3666 testFloatCopySubImage(4, 2);
3667 }
3668
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RGB)3669 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGB)
3670 {
3671 testFloatCopySubImage(4, 3);
3672 }
3673
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RGBA)3674 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGBA)
3675 {
3676 testFloatCopySubImage(4, 4);
3677 }
3678
3679 // Port of
3680 // https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html
3681 // Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly
3682 // handles GL_ALPHA
TEST_P(Texture2DTest,TextureNPOT_GL_ALPHA_UBYTE)3683 TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE)
3684 {
3685 const int npotTexSize = 5;
3686 const int potTexSize = 4; // Should be less than npotTexSize
3687 GLTexture tex2D;
3688
3689 if (IsGLExtensionEnabled("GL_OES_texture_npot"))
3690 {
3691 // This test isn't applicable if texture_npot is enabled
3692 return;
3693 }
3694
3695 setUpProgram();
3696
3697 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3698
3699 // Default unpack alignment is 4. The values of 'pixels' below needs it to be 1.
3700 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3701
3702 glActiveTexture(GL_TEXTURE0);
3703 glBindTexture(GL_TEXTURE_2D, tex2D);
3704
3705 const std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize, 64);
3706
3707 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3708 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3709
3710 // Check that an NPOT texture not on level 0 generates INVALID_VALUE
3711 glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA,
3712 GL_UNSIGNED_BYTE, pixels.data());
3713 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3714
3715 // Check that an NPOT texture on level 0 succeeds
3716 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA,
3717 GL_UNSIGNED_BYTE, pixels.data());
3718 EXPECT_GL_NO_ERROR();
3719
3720 // Check that generateMipmap fails on NPOT
3721 glGenerateMipmap(GL_TEXTURE_2D);
3722 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3723
3724 // Check that nothing is drawn if filtering is not correct for NPOT
3725 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3726 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3727 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
3728 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
3729 glClear(GL_COLOR_BUFFER_BIT);
3730 drawQuad(mProgram, "position", 1.0f);
3731 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
3732
3733 // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
3734 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3735 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3736 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
3737 glClear(GL_COLOR_BUFFER_BIT);
3738 drawQuad(mProgram, "position", 1.0f);
3739 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
3740
3741 // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw
3742 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3743 glClear(GL_COLOR_BUFFER_BIT);
3744 drawQuad(mProgram, "position", 1.0f);
3745 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
3746
3747 // Check that glTexImage2D for POT texture succeeds
3748 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
3749 pixels.data());
3750 EXPECT_GL_NO_ERROR();
3751
3752 // Check that generateMipmap for an POT texture succeeds
3753 glGenerateMipmap(GL_TEXTURE_2D);
3754 EXPECT_GL_NO_ERROR();
3755
3756 // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw
3757 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
3758 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3759 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
3760 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
3761 glClear(GL_COLOR_BUFFER_BIT);
3762 drawQuad(mProgram, "position", 1.0f);
3763 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
3764 EXPECT_GL_NO_ERROR();
3765 }
3766
3767 // Test to ensure that glTexSubImage2D always accepts data for non-power-of-two subregions.
3768 // ANGLE previously rejected this if GL_OES_texture_npot wasn't active, which is incorrect.
TEST_P(Texture2DTest,NPOTSubImageParameters)3769 TEST_P(Texture2DTest, NPOTSubImageParameters)
3770 {
3771 glActiveTexture(GL_TEXTURE0);
3772 glBindTexture(GL_TEXTURE_2D, mTexture2D);
3773
3774 // Create an 8x8 (i.e. power-of-two) texture.
3775 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3776 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
3777 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3778 glGenerateMipmap(GL_TEXTURE_2D);
3779
3780 // Supply a 3x3 (i.e. non-power-of-two) subimage to the texture.
3781 // This should always work, even if GL_OES_texture_npot isn't active.
3782 std::array<GLColor, 3 * 3> data;
3783 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
3784
3785 EXPECT_GL_NO_ERROR();
3786 }
3787
3788 // Regression test for https://crbug.com/1222516 to prevent integer overflow during validation.
TEST_P(Texture2DTest,SubImageValidationOverflow)3789 TEST_P(Texture2DTest, SubImageValidationOverflow)
3790 {
3791 glActiveTexture(GL_TEXTURE0);
3792 glBindTexture(GL_TEXTURE_2D, mTexture2D);
3793
3794 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3795 EXPECT_GL_NO_ERROR();
3796
3797 glTexSubImage2D(GL_TEXTURE_2D, 0, -4, 0, 2147483647, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3798 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3799
3800 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, -4, 1, 2147483647, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3801 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3802 }
3803
3804 // Test that when a mutable texture is deleted, its corresponding pointer in the Vulkan backend,
3805 // which is used for mutable texture flushing, is also deleted, and is not accessed by the new
3806 // mutable texture after it.
TEST_P(Texture2DTest,MutableUploadThenDeleteThenMutableUpload)3807 TEST_P(Texture2DTest, MutableUploadThenDeleteThenMutableUpload)
3808 {
3809 GLTexture texture1;
3810 glBindTexture(GL_TEXTURE_2D, texture1);
3811 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3812 GLColor::red.data());
3813 texture1.reset();
3814 EXPECT_GL_NO_ERROR();
3815
3816 GLTexture texture2;
3817 glBindTexture(GL_TEXTURE_2D, texture2);
3818 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3819 GLColor::green.data());
3820 texture2.reset();
3821 EXPECT_GL_NO_ERROR();
3822 }
3823
3824 // Test to ensure that glTexStorage3D accepts ASTC sliced 3D. https://crbug.com/1060012
TEST_P(Texture3DTestES3,ImmutableASTCSliced3D)3825 TEST_P(Texture3DTestES3, ImmutableASTCSliced3D)
3826 {
3827 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_texture_compression_astc_sliced_3d"));
3828
3829 glBindTexture(GL_TEXTURE_3D, mTexture3D);
3830 glTexStorage3D(GL_TEXTURE_3D, 1, GL_COMPRESSED_RGBA_ASTC_4x4, 4, 4, 1);
3831 EXPECT_GL_NO_ERROR();
3832 }
3833
FillLevel(GLint level,GLuint width,GLuint height,const GLColor & color,bool cubemap,bool subTex)3834 void FillLevel(GLint level,
3835 GLuint width,
3836 GLuint height,
3837 const GLColor &color,
3838 bool cubemap,
3839 bool subTex)
3840 {
3841 std::vector<GLColor> pixels(width * height, color);
3842 std::vector<GLenum> targets;
3843 if (cubemap)
3844 {
3845 targets = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
3846 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
3847 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
3848 }
3849 else
3850 {
3851 targets = {GL_TEXTURE_2D};
3852 }
3853
3854 for (GLenum target : targets)
3855 {
3856 if (subTex)
3857 {
3858 glTexSubImage2D(target, level, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
3859 pixels.data());
3860 }
3861 else
3862 {
3863 glTexImage2D(target, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3864 pixels.data());
3865 }
3866 }
3867 }
3868
3869 // This is part of tests that webgl_conformance_vulkan_passthrough_tests
3870 // conformance/textures/misc/texture-size.html does
testTextureSize(int testCaseIndex)3871 void Texture2DTest::testTextureSize(int testCaseIndex)
3872 {
3873 std::array<GLColor, 6> kNewMipColors = {
3874 GLColor::green, GLColor::red, GLColor::blue,
3875 GLColor::yellow, GLColor::magenta, GLColor::cyan,
3876 };
3877 GLuint colorCount = 0;
3878
3879 setUpProgram();
3880
3881 constexpr char kVS[] =
3882 R"(precision highp float;
3883 attribute vec4 position;
3884 varying vec3 texcoord;
3885 void main()
3886 {
3887 gl_Position = position;
3888 texcoord = (position.xyz * 0.5) + 0.5;
3889 }
3890 )";
3891 constexpr char kFS[] =
3892 R"(precision mediump float;
3893 uniform samplerCube tex;
3894 varying vec3 texcoord;
3895 void main()
3896 {
3897 gl_FragColor = textureCube(tex, texcoord);
3898 })";
3899 ANGLE_GL_PROGRAM(programCubeMap, kVS, kFS);
3900 GLint textureCubeUniformLocation = glGetUniformLocation(programCubeMap, "tex");
3901 ASSERT_NE(-1, textureCubeUniformLocation);
3902 ASSERT_GL_NO_ERROR();
3903
3904 GLint max2DSize = 0;
3905 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize);
3906 GLint maxCubeMapSize = 0;
3907 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapSize);
3908 // Assuming 2048x2048xRGBA (22 mb with mips) will run on all WebGL platforms
3909 GLint max2DSquareSize = std::min(max2DSize, 2048);
3910 // I'd prefer this to be 2048 but that's 16 mb x 6 faces or 128 mb (with mips)
3911 // 1024 is 33.5 mb (with mips)
3912 maxCubeMapSize = std::min(maxCubeMapSize, 1024);
3913 ASSERT_GL_NO_ERROR();
3914
3915 for (GLint size = 1; size <= max2DSize; size *= 2)
3916 {
3917 bool cubeMap = testCaseIndex == 3;
3918 GLenum texTarget = cubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
3919 GLuint program = cubeMap ? programCubeMap : mProgram;
3920 GLint texWidth = 0, texHeight = 0;
3921
3922 switch (testCaseIndex)
3923 {
3924 case 0:
3925 texWidth = size;
3926 texHeight = 1;
3927 break;
3928 case 1:
3929 texWidth = 1;
3930 texHeight = size;
3931 break;
3932 case 2:
3933 case 3:
3934 texWidth = size;
3935 texHeight = size;
3936 break;
3937 }
3938
3939 if (texWidth == texHeight && size > max2DSquareSize)
3940 {
3941 return;
3942 }
3943
3944 if (cubeMap && size > maxCubeMapSize)
3945 {
3946 return;
3947 }
3948
3949 GLTexture texture;
3950 glActiveTexture(GL_TEXTURE0);
3951 glBindTexture(texTarget, texture);
3952 FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false);
3953 glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3954 glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3955 glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3956 glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3957 ASSERT_GL_NO_ERROR();
3958
3959 glClear(GL_COLOR_BUFFER_BIT);
3960 ASSERT_GL_NO_ERROR();
3961
3962 glUseProgram(program);
3963 if (cubeMap)
3964 {
3965 glUniform1i(textureCubeUniformLocation, 0);
3966 }
3967 else
3968 {
3969 glUniform1i(mTexture2DUniformLocation, 0);
3970 }
3971
3972 drawQuad(program, "position", 1.0f);
3973 ASSERT_GL_NO_ERROR();
3974 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
3975
3976 colorCount = (colorCount + 1) % kNewMipColors.size();
3977 FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false);
3978 glGenerateMipmap(texTarget);
3979 ASSERT_GL_NO_ERROR();
3980
3981 glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
3982 glClear(GL_COLOR_BUFFER_BIT);
3983 drawQuad(program, "position", 1.0f);
3984 ASSERT_GL_NO_ERROR();
3985 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
3986
3987 colorCount = (colorCount + 1) % kNewMipColors.size();
3988 FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, true);
3989 glGenerateMipmap(texTarget);
3990
3991 glClear(GL_COLOR_BUFFER_BIT);
3992 drawQuad(program, "position", 1.0f);
3993 ASSERT_GL_NO_ERROR();
3994 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
3995 }
3996 }
3997
testTextureSizeError()3998 void Texture2DTest::testTextureSizeError()
3999 {
4000 GLint max2DSize = 0;
4001 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize);
4002 glActiveTexture(GL_TEXTURE0);
4003 GLTexture texture;
4004 glBindTexture(GL_TEXTURE_2D, texture);
4005 FillLevel(0, max2DSize, max2DSize, GLColor::red, false, false);
4006 GLenum err = glGetError();
4007 bool passed = (err == GL_NO_ERROR || err == GL_OUT_OF_MEMORY);
4008 ASSERT_TRUE(passed);
4009 }
4010
4011 // Permutation 0 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase0)4012 TEST_P(Texture2DTest, TextureSizeCase0)
4013 {
4014 testTextureSize(0);
4015 }
4016
4017 // Permutation 1 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase1)4018 TEST_P(Texture2DTest, TextureSizeCase1)
4019 {
4020 testTextureSize(1);
4021 }
4022
4023 // Permutation 2 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase2)4024 TEST_P(Texture2DTest, TextureSizeCase2)
4025 {
4026 testTextureSize(2);
4027 }
4028
4029 // Permutation 3 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase3)4030 TEST_P(Texture2DTest, TextureSizeCase3)
4031 {
4032 testTextureSize(3);
4033 }
4034
4035 // Test allocating a very large texture
TEST_P(Texture2DTest,TextureMaxSize)4036 TEST_P(Texture2DTest, TextureMaxSize)
4037 {
4038 testTextureSizeError();
4039 }
4040
4041 // Test that drawing works correctly RGBA 3D texture
TEST_P(Texture3DTestES2,RGBA)4042 TEST_P(Texture3DTestES2, RGBA)
4043 {
4044 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4045
4046 // http://anglebug.com/5728
4047 ANGLE_SKIP_TEST_IF(IsOzone());
4048
4049 glActiveTexture(GL_TEXTURE0);
4050 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4051 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
4052 std::vector<GLColor> texDataRed(1u * 1u * 1u, GLColor::red);
4053 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4054 texDataGreen.data());
4055 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4056 texDataRed.data());
4057 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4058 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4059
4060 EXPECT_GL_NO_ERROR();
4061
4062 drawQuad(mProgram, "position", 0.5f);
4063
4064 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4065 }
4066
4067 // Test that drawing works correctly Luminance 3D texture
TEST_P(Texture3DTestES2,Luminance)4068 TEST_P(Texture3DTestES2, Luminance)
4069 {
4070 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4071
4072 // http://anglebug.com/5728
4073 ANGLE_SKIP_TEST_IF(IsOzone());
4074
4075 glActiveTexture(GL_TEXTURE0);
4076 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4077 std::vector<GLubyte> texData(2u * 2u * 2u, 125);
4078 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4079 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4080 texData.data());
4081 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4082 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4083
4084 EXPECT_GL_NO_ERROR();
4085
4086 drawQuad(mProgram, "position", 0.5f);
4087
4088 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(125, 125, 125, 255));
4089 }
4090
4091 // Test that drawing works correctly with glCopyTexSubImage3D
TEST_P(Texture3DTestES2,CopySubImageRGBA)4092 TEST_P(Texture3DTestES2, CopySubImageRGBA)
4093 {
4094 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4095
4096 // http://anglebug.com/5728
4097 ANGLE_SKIP_TEST_IF(IsOzone());
4098
4099 glClearColor(0, 0, 1, 1);
4100 glClear(GL_COLOR_BUFFER_BIT);
4101
4102 glActiveTexture(GL_TEXTURE0);
4103 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4104 std::vector<GLColor> texDataRed(4u * 4u * 4u, GLColor::red);
4105 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4106 texDataRed.data());
4107 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4108 texDataRed.data());
4109 glTexImage3DOES(GL_TEXTURE_3D, 2, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4110 texDataRed.data());
4111 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4112 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4113 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4114 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4115
4116 EXPECT_GL_NO_ERROR();
4117
4118 glClearColor(0, 1, 0, 1);
4119 glClear(GL_COLOR_BUFFER_BIT);
4120 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4121
4122 glUseProgram(mProgram);
4123 glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4124 drawQuad(mProgram, "position", 0.5f);
4125
4126 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4127 }
4128
TEST_P(Texture3DTestES2,CopySubImageLuminance)4129 TEST_P(Texture3DTestES2, CopySubImageLuminance)
4130 {
4131 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4132
4133 // http://anglebug.com/5728
4134 ANGLE_SKIP_TEST_IF(IsOzone());
4135
4136 glClearColor(1, 0, 0, 1);
4137 glClear(GL_COLOR_BUFFER_BIT);
4138
4139 glActiveTexture(GL_TEXTURE0);
4140 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4141 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 4, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4142 nullptr);
4143 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4144 nullptr);
4145 glTexImage3DOES(GL_TEXTURE_3D, 2, GL_LUMINANCE, 1, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4146 nullptr);
4147 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4148 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4149 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4150 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4151
4152 EXPECT_GL_NO_ERROR();
4153
4154 glClearColor(0, 1, 0, 1);
4155 glClear(GL_COLOR_BUFFER_BIT);
4156 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4157
4158 glUseProgram(mProgram);
4159 glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4160 drawQuad(mProgram, "position", 0.5f);
4161
4162 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
4163 }
4164
TEST_P(Texture3DTestES2,CopySubImageAlpha)4165 TEST_P(Texture3DTestES2, CopySubImageAlpha)
4166 {
4167 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4168
4169 // http://anglebug.com/5728
4170 ANGLE_SKIP_TEST_IF(IsOzone());
4171
4172 glClearColor(1, 0, 0, 0.5);
4173 glClear(GL_COLOR_BUFFER_BIT);
4174
4175 glActiveTexture(GL_TEXTURE0);
4176 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4177 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_ALPHA, 4, 4, 4, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4178 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_ALPHA, 2, 2, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4179 glTexImage3DOES(GL_TEXTURE_3D, 2, GL_ALPHA, 1, 1, 1, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4180 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4181 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4182 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4183 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4184
4185 EXPECT_GL_NO_ERROR();
4186
4187 glClearColor(0, 1, 0, 1);
4188 glClear(GL_COLOR_BUFFER_BIT);
4189 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4190
4191 glUseProgram(mProgram);
4192 glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4193 drawQuad(mProgram, "position", 0.5f);
4194
4195 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 128), 1.0);
4196 }
4197
4198 // Test that defining a 2D texture array fails with Texture3DOES on ES2.
TEST_P(Texture3DTestES2,DefineTexture2DArrayShouldFail)4199 TEST_P(Texture3DTestES2, DefineTexture2DArrayShouldFail)
4200 {
4201 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4202
4203 // http://anglebug.com/5728
4204 ANGLE_SKIP_TEST_IF(IsOzone());
4205
4206 glClearColor(1, 0, 0, 1);
4207 glClear(GL_COLOR_BUFFER_BIT);
4208
4209 glActiveTexture(GL_TEXTURE0);
4210 glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
4211 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4212
4213 glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4214 nullptr);
4215 glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4216 nullptr);
4217 glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4218 nullptr);
4219 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4220 }
4221
4222 // Verify shrinking a texture with glTexStorage2D works correctly
TEST_P(Texture2DTestES3,ChangeTexSizeWithTexStorage)4223 TEST_P(Texture2DTestES3, ChangeTexSizeWithTexStorage)
4224 {
4225 // TODO: http://anglebug.com/5256
4226 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL());
4227
4228 constexpr uint32_t kSizeLarge = 128;
4229 constexpr uint32_t kSizeSmall = 64;
4230
4231 glActiveTexture(GL_TEXTURE0);
4232 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4233 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4235
4236 // Create the texture with 'large' dimensions
4237 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4238 nullptr);
4239 ASSERT_GL_NO_ERROR();
4240
4241 GLFramebuffer destFbo;
4242 glBindFramebuffer(GL_FRAMEBUFFER, destFbo);
4243 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0);
4244 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4245
4246 // Draw with the new texture so it's created in the back end
4247 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
4248 glUseProgram(blueProgram);
4249 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
4250 ASSERT_GL_NO_ERROR();
4251 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::blue);
4252
4253 // Shrink the texture
4254 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall);
4255 ASSERT_GL_NO_ERROR();
4256
4257 // Create a source texture/FBO to blit from
4258 GLTexture sourceTex;
4259 glBindTexture(GL_TEXTURE_2D, sourceTex.get());
4260 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall);
4261 ASSERT_GL_NO_ERROR();
4262 GLFramebuffer sourceFbo;
4263 glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo);
4264 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTex, 0);
4265 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4266 // Fill the source texture with green
4267 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4268 glUseProgram(greenProgram);
4269 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
4270 ASSERT_GL_NO_ERROR();
4271 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::green);
4272
4273 // Blit the source (green) to the destination
4274 glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo);
4275 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFbo);
4276 glBlitFramebuffer(0, 0, kSizeSmall, kSizeSmall, 0, 0, kSizeSmall, kSizeSmall,
4277 GL_COLOR_BUFFER_BIT, GL_NEAREST);
4278 ASSERT_GL_NO_ERROR();
4279
4280 // Render to the default framebuffer sampling from the blited texture and verify it's green
4281 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4282 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4283 ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
4284 glUseProgram(texProgram);
4285 drawQuad(texProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
4286 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4287 }
4288
4289 // Regression test for http://crbug.com/949985 to make sure dirty bits are propagated up from
4290 // TextureImpl and the texture is synced before being used in a draw call.
TEST_P(Texture2DTestES3,TextureImplPropogatesDirtyBits)4291 TEST_P(Texture2DTestES3, TextureImplPropogatesDirtyBits)
4292 {
4293 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
4294 // Flaky hangs on Win10 AMD RX 550 GL. http://anglebug.com/3371
4295 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4296 // D3D Debug device reports an error. http://anglebug.com/3501
4297 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
4298 // Support copy from levels outside the image range. http://anglebug.com/4733
4299 ANGLE_SKIP_TEST_IF(IsVulkan());
4300
4301 // The workaround in the GL backend required to trigger this bug generates driver warning
4302 // messages.
4303 ScopedIgnorePlatformMessages ignoreMessages;
4304
4305 setUpProgram();
4306 glUseProgram(mProgram);
4307 glActiveTexture(GL_TEXTURE0 + mTexture2DUniformLocation);
4308
4309 GLTexture dest;
4310 glBindTexture(GL_TEXTURE_2D, dest);
4311
4312 GLTexture source;
4313 glBindTexture(GL_TEXTURE_2D, source);
4314
4315 // Put data in mip 0 and 1
4316 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4317 GLColor::red.data());
4318 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4319 GLColor::green.data());
4320
4321 // Disable mipmapping so source is complete
4322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4324
4325 // Force the dirty bits to be synchronized in source
4326 drawQuad(mProgram, "position", 1.0f);
4327
4328 // Copy from mip 1 of the source. In the GL backend this internally sets the base level to mip
4329 // 1 and sets a dirty bit.
4330 glCopyTextureCHROMIUM(source, 1, GL_TEXTURE_2D, dest, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_FALSE,
4331 GL_FALSE, GL_FALSE);
4332
4333 // Draw again, assertions are generated if the texture has internal dirty bits at draw time
4334 drawQuad(mProgram, "position", 1.0f);
4335 }
4336
4337 // This test case changes the base level of a texture that's attached to a framebuffer, clears every
4338 // level to green, and then samples the texture when rendering. Test is taken from
4339 // https://www.khronos.org/registry/webgl/sdk/tests/conformance2/rendering/framebuffer-texture-changing-base-level.html
TEST_P(Texture2DTestES3,FramebufferTextureChangingBaselevel)4340 TEST_P(Texture2DTestES3, FramebufferTextureChangingBaselevel)
4341 {
4342 // TODO(cnorthrop): Failing on Vulkan/Windows/AMD. http://anglebug.com/3996
4343 ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
4344
4345 setUpProgram();
4346
4347 constexpr GLint width = 8;
4348 constexpr GLint height = 4;
4349
4350 GLTexture texture;
4351 glBindTexture(GL_TEXTURE_2D, texture);
4352 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
4353 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4354 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4356
4357 // Create all mipmap levels for the texture from level 0 to the 1x1 pixel level.
4358 GLint level = 0;
4359 GLint levelW = width;
4360 GLint levelH = height;
4361 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4362 nullptr);
4363 while (levelW > 1 || levelH > 1)
4364 {
4365 ++level;
4366 levelW = static_cast<GLint>(std::max(1.0, std::floor(width / std::pow(2, level))));
4367 levelH = static_cast<GLint>(std::max(1.0, std::floor(height / std::pow(2, level))));
4368 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4369 nullptr);
4370 }
4371
4372 // Clear each level of the texture using an FBO. Change the base level to match the level used
4373 // for the FBO on each iteration.
4374 GLFramebuffer fbo;
4375 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4376 level = 0;
4377 levelW = width;
4378 levelH = height;
4379 while (levelW > 1 || levelH > 1)
4380 {
4381 levelW = static_cast<GLint>(std::floor(width / std::pow(2, level)));
4382 levelH = static_cast<GLint>(std::floor(height / std::pow(2, level)));
4383
4384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
4385 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, level);
4386
4387 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
4388 EXPECT_GL_NO_ERROR();
4389
4390 glClearColor(0, 1, 0, 1);
4391 glClear(GL_COLOR_BUFFER_BIT);
4392
4393 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4394
4395 ++level;
4396 }
4397
4398 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4399 glViewport(0, 0, 16, 16);
4400 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
4401
4402 drawQuad(mProgram, "position", 0.5f);
4403
4404 EXPECT_GL_NO_ERROR();
4405 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4406 }
4407
4408 // Test that changing the base level of a texture after redefining a level outside the mip-chain
4409 // preserves the other mips' data.
TEST_P(Texture2DBaseMaxTestES3,ExtendMipChainAfterRedefine)4410 TEST_P(Texture2DBaseMaxTestES3, ExtendMipChainAfterRedefine)
4411 {
4412 // http://anglebug.com/4699
4413 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
4414
4415 // http://anglebug.com/5153
4416 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA() && IsMac());
4417
4418 GLFramebuffer framebuffer;
4419 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4420
4421 GLTexture texture;
4422 glBindTexture(GL_TEXTURE_2D, texture);
4423
4424 std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
4425 fillMipData(mipData.data(), kMip0Size, kMipColors);
4426
4427 for (size_t mip = 1; mip < kMipCount; ++mip)
4428 {
4429 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA,
4430 GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip));
4431 }
4432
4433 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
4434 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
4435 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4436
4437 // Mip 1 is green. Verify this.
4438 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]);
4439
4440 // http://anglebug.com/4709
4441 ANGLE_SKIP_TEST_IF(IsOpenGL() && (IsIntel() || IsAMD()) && IsWindows());
4442
4443 // Add mip 0 and rebase the mip chain.
4444 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4445 mipData.data() + getMipDataOffset(kMip0Size, 0));
4446 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
4447
4448 // Mip 1 should still be green.
4449 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]);
4450
4451 // Verify the other mips too.
4452 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
4453 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4454 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[2]);
4455
4456 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
4457 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4458 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[3]);
4459
4460 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4461 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4462
4463 // http://anglebug.com/4704
4464 ANGLE_SKIP_TEST_IF(IsVulkan());
4465
4466 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]);
4467 }
4468
4469 // Test that changing the base level of a texture multiple times preserves the data.
TEST_P(Texture2DBaseMaxTestES3,PingPongBaseLevel)4470 TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevel)
4471 {
4472 testPingPongBaseLevel(false);
4473 }
TEST_P(Texture2DBaseMaxTestES3,PingPongBaseLevelImmutable)4474 TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevelImmutable)
4475 {
4476 testPingPongBaseLevel(true);
4477 }
testPingPongBaseLevel(bool immutable)4478 void Texture2DBaseMaxTestES3::testPingPongBaseLevel(bool immutable)
4479 {
4480 // http://anglebug.com/4710
4481 ANGLE_SKIP_TEST_IF(IsD3D());
4482
4483 // http://anglebug.com/4711
4484 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsWindows());
4485
4486 // http://anglebug.com/4701
4487 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
4488
4489 initTest(immutable);
4490
4491 // Ping pong a few times.
4492 for (uint32_t tries = 0; tries < 2; ++tries)
4493 {
4494 // Rebase to different mips and verify mips.
4495 for (uint32_t base = 0; base < kMipCount; ++base)
4496 {
4497 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base);
4498 for (uint32_t lod = 0; lod < kMipCount - base; ++lod)
4499 {
4500 setLodUniform(lod);
4501 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4502 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]);
4503 }
4504 }
4505
4506 // Rebase backwards and verify mips.
4507 for (uint32_t base = kMipCount - 2; base > 0; --base)
4508 {
4509 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base);
4510 for (uint32_t lod = 0; lod < kMipCount - base; ++lod)
4511 {
4512 setLodUniform(lod);
4513 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4514 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]);
4515 }
4516 }
4517 }
4518 }
4519
4520 // Test that glTexSubImage2D after incompatibly redefining a mip level correctly applies the update
4521 // after the redefine data.
TEST_P(Texture2DBaseMaxTestES3,SubImageAfterRedefine)4522 TEST_P(Texture2DBaseMaxTestES3, SubImageAfterRedefine)
4523 {
4524 initTest(false);
4525
4526 // Test that all mips have the expected data initially (this makes sure the texture image is
4527 // created already).
4528 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4529 {
4530 setLodUniform(lod);
4531 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4532 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
4533 }
4534
4535 // Redefine every level, followed by a glTexSubImage2D
4536 const GLColor kNewMipColors[kMipCount] = {
4537 GLColor::yellow,
4538 GLColor::cyan,
4539 GLColor(127, 0, 0, 255),
4540 GLColor(0, 127, 0, 255),
4541 };
4542 std::array<GLColor, getTotalMipDataSize(kMip0Size * 2)> newMipData;
4543 fillMipData(newMipData.data(), kMip0Size * 2, kNewMipColors);
4544
4545 const GLColor kSubImageMipColors[kMipCount] = {
4546 GLColor(0, 0, 127, 255),
4547 GLColor(127, 127, 0, 255),
4548 GLColor(0, 127, 127, 255),
4549 GLColor(127, 0, 127, 255),
4550 };
4551 std::array<GLColor, getTotalMipDataSize(kMip0Size)> subImageMipData;
4552 fillMipData(subImageMipData.data(), kMip0Size, kSubImageMipColors);
4553
4554 for (size_t mip = 0; mip < kMipCount; ++mip)
4555 {
4556 // Redefine the level.
4557 size_t newMipSize = (kMip0Size * 2) >> mip;
4558 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, newMipSize, newMipSize, 0, GL_RGBA,
4559 GL_UNSIGNED_BYTE, newMipData.data() + getMipDataOffset(kMip0Size * 2, mip));
4560
4561 // Immediately follow that with a subimage update.
4562 glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA,
4563 GL_UNSIGNED_BYTE,
4564 subImageMipData.data() + getMipDataOffset(kMip0Size, mip));
4565 }
4566 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1);
4567
4568 // Test that the texture looks as expected.
4569 const int w = getWindowWidth() - 1;
4570 const int h = getWindowHeight() - 1;
4571 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4572 {
4573 setLodUniform(lod);
4574 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4575 EXPECT_PIXEL_COLOR_EQ(0, 0, kSubImageMipColors[lod]);
4576 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColors[lod]);
4577 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColors[lod]);
4578 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColors[lod]);
4579 }
4580 }
4581
4582 // Test that incompatibly redefining a level then redefining it back to its original size works.
TEST_P(Texture2DBaseMaxTestES3,IncompatiblyRedefineLevelThenRevert)4583 TEST_P(Texture2DBaseMaxTestES3, IncompatiblyRedefineLevelThenRevert)
4584 {
4585 initTest(false);
4586
4587 // Test that all mips have the expected data initially (this makes sure the texture image is
4588 // created already).
4589 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4590 {
4591 setLodUniform(lod);
4592 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4593 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
4594 }
4595
4596 // Redefine Mip 1 to be larger.
4597 constexpr size_t kLargeMip1Size = getMipDataSize(kMip0Size * 2, 1);
4598 std::array<GLColor, kLargeMip1Size> interimMipData;
4599 std::fill(interimMipData.data(), interimMipData.data() + kLargeMip1Size, GLColor::yellow);
4600
4601 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4602 interimMipData.data());
4603
4604 // Redefine Mip 1 back to its original size.
4605 constexpr size_t kNormalMip1Size = getMipDataSize(kMip0Size, 1);
4606 std::array<GLColor, kLargeMip1Size> newMipData;
4607 std::fill(newMipData.data(), newMipData.data() + kNormalMip1Size, GLColor::cyan);
4608
4609 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size / 2, kMip0Size / 2, 0, GL_RGBA,
4610 GL_UNSIGNED_BYTE, newMipData.data());
4611
4612 // Verify texture colors.
4613 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4614 {
4615 setLodUniform(lod);
4616 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4617 EXPECT_PIXEL_COLOR_EQ(0, 0, lod == 1 ? GLColor::cyan : kMipColors[lod]);
4618 }
4619 }
4620
4621 // Test that redefining every level of a texture to another format works. The format uses more
4622 // bits per component, to ensure alignment requirements for the new format are taken into account.
TEST_P(Texture2DBaseMaxTestES3,RedefineEveryLevelToAnotherFormat)4623 TEST_P(Texture2DBaseMaxTestES3, RedefineEveryLevelToAnotherFormat)
4624 {
4625 initTest(false);
4626
4627 // Test that all mips have the expected data initially (this makes sure the texture image is
4628 // created already).
4629 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4630 {
4631 setLodUniform(lod);
4632 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4633 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
4634 }
4635
4636 const GLColor32F kNewMipColors[kMipCount] = {
4637 GLColor32F(1.0, 1.0, 0.0, 1.0f),
4638 GLColor32F(1.0, 0.0, 1.0, 1.0f),
4639 GLColor32F(0.0, 1.0, 1.0, 1.0f),
4640 GLColor32F(1.0, 1.0, 1.0, 1.0f),
4641 };
4642
4643 std::array<GLColor32F, getTotalMipDataSize(kMip0Size)> newMipData;
4644 fillMipData(newMipData.data(), kMip0Size, kNewMipColors);
4645
4646 // Redefine every level with the new format.
4647 for (size_t mip = 0; mip < kMipCount; ++mip)
4648 {
4649 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA32F, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA,
4650 GL_FLOAT, newMipData.data() + getMipDataOffset(kMip0Size, mip));
4651 }
4652
4653 // Verify texture colors.
4654 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4655 {
4656 setLodUniform(lod);
4657 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4658
4659 GLColor32F mipColor32F = kNewMipColors[lod];
4660 GLColor mipColor(static_cast<GLubyte>(std::roundf(mipColor32F.R * 255)),
4661 static_cast<GLubyte>(std::roundf(mipColor32F.G * 255)),
4662 static_cast<GLubyte>(std::roundf(mipColor32F.B * 255)),
4663 static_cast<GLubyte>(std::roundf(mipColor32F.A * 255)));
4664
4665 EXPECT_PIXEL_COLOR_EQ(0, 0, mipColor);
4666 }
4667 }
4668
4669 // Test that generating mipmaps after change base level.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRebase)4670 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebase)
4671 {
4672 // http://anglebug.com/5880
4673 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
4674
4675 testGenerateMipmapAfterRebase(false);
4676 }
4677
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRebaseImmutable)4678 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebaseImmutable)
4679 {
4680 // http://anglebug.com/4710
4681 ANGLE_SKIP_TEST_IF(IsD3D());
4682 // http://anglebug.com/5798
4683 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
4684 // http://anglebug.com/5880
4685 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
4686
4687 testGenerateMipmapAfterRebase(true);
4688 }
4689
testGenerateMipmapAfterRebase(bool immutable)4690 void Texture2DBaseMaxTestES3::testGenerateMipmapAfterRebase(bool immutable)
4691 {
4692 initTest(immutable);
4693
4694 // Test that all mips have the expected data initially (this makes sure the texture image is
4695 // created already).
4696 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4697 {
4698 setLodUniform(lod);
4699 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4700 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
4701 }
4702
4703 // Update level 1 (any level would do other than 0) with new data
4704 const GLColor kNewMipColor = GLColor::yellow;
4705 std::array<GLColor, getMipDataSize(kMip0Size >> 1, 0)> newMipData;
4706 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
4707
4708 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kMip0Size >> 1, kMip0Size >> 1, GL_RGBA,
4709 GL_UNSIGNED_BYTE, newMipData.data());
4710
4711 // Change base level and max level and then generate mipmaps. This should redefine level 1 and 2
4712 // with kNewMipColor and leave levels 0 and 3 unchanged.
4713 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
4714 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 2);
4715 glGenerateMipmap(GL_TEXTURE_2D);
4716 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
4717 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1);
4718
4719 // Test that the texture looks as expected.
4720 const int w = getWindowWidth() - 1;
4721 const int h = getWindowHeight() - 1;
4722 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4723 {
4724 setLodUniform(lod);
4725 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4726 if (lod == 0)
4727 {
4728 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
4729 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
4730 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
4731 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
4732 }
4733 else if (lod == kMipCount - 1)
4734 {
4735 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
4736 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
4737 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
4738 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
4739 }
4740 else
4741 {
4742 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor) << "lod " << lod;
4743 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor) << "lod " << lod;
4744 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor) << "lod " << lod;
4745 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor) << "lod " << lod;
4746 }
4747 }
4748 }
4749
4750 // Test that generating mipmaps after incompatibly redefining a level works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefine)4751 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefine)
4752 {
4753 initTest(false);
4754
4755 // Test that all mips have the expected data initially (this makes sure the texture image is
4756 // created already).
4757 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4758 {
4759 setLodUniform(lod);
4760 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4761 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
4762 }
4763
4764 // Redefine level 1 (any level would do other than 0) to an incompatible size, say the same size
4765 // as level 0.
4766 const GLColor kNewMipColor = GLColor::yellow;
4767 std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
4768 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
4769
4770 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4771 newMipData.data());
4772
4773 // Generate mipmaps. This should redefine level 1 back to being compatible with level 0.
4774 glGenerateMipmap(GL_TEXTURE_2D);
4775
4776 // Test that the texture looks as expected.
4777 const int w = getWindowWidth() - 1;
4778 const int h = getWindowHeight() - 1;
4779 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4780 {
4781 setLodUniform(lod);
4782 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4783 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]);
4784 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]);
4785 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]);
4786 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]);
4787 }
4788 }
4789
4790 // Test that generating mipmaps after incompatibly redefining a level while simultaneously changing
4791 // the base level works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefineAndRebase)4792 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefineAndRebase)
4793 {
4794 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4795
4796 // http://crbug.com/1100613
4797 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
4798
4799 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
4800 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
4801
4802 initTest(false);
4803
4804 // Test that all mips have the expected data initially (this makes sure the texture image is
4805 // created already).
4806 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4807 {
4808 setLodUniform(lod);
4809 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4810 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << lod;
4811 }
4812
4813 // Redefine level 2 to an incompatible size, say the same size as level 0.
4814 const GLColor kNewMipColor = GLColor::yellow;
4815 std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
4816 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
4817
4818 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4819 newMipData.data());
4820
4821 // Set base level of the texture to 1 then generate mipmaps. Level 2 that's redefined should
4822 // go back to being compatibly defined.
4823 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
4824 glGenerateMipmap(GL_TEXTURE_2D);
4825
4826 // Test that the texture looks as expected.
4827 const int w = getWindowWidth() - 1;
4828 const int h = getWindowHeight() - 1;
4829 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4830 {
4831 setLodUniform(lod);
4832 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4833 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]) << lod;
4834 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[1]) << lod;
4835 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[1]) << lod;
4836 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[1]) << lod;
4837 }
4838
4839 // Redefine level 1 (current base level) to an incompatible size.
4840 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4841 newMipData.data());
4842
4843 // Set base level of the texture back to 0 then generate mipmaps. Level 1 should go back to
4844 // being compatibly defined.
4845 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
4846 glGenerateMipmap(GL_TEXTURE_2D);
4847
4848 // Test that the texture looks as expected.
4849 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4850 {
4851 setLodUniform(lod);
4852 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4853 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]) << lod;
4854 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]) << lod;
4855 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]) << lod;
4856 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]) << lod;
4857 }
4858 }
4859
4860 // Test that generating mipmaps after incompatibly redefining the base level of the texture works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefiningBase)4861 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBase)
4862 {
4863 initTest(false);
4864
4865 // Test that all mips have the expected data initially (this makes sure the texture image is
4866 // created already).
4867 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4868 {
4869 setLodUniform(lod);
4870 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4871 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
4872 }
4873
4874 // Redefine level 0 to an incompatible size.
4875 const GLColor kNewMipColor = GLColor::yellow;
4876 std::array<GLColor, getMipDataSize(kMip0Size * 2, 0)> newMipData;
4877 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
4878
4879 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA,
4880 GL_UNSIGNED_BYTE, newMipData.data());
4881
4882 // Generate mipmaps.
4883 glGenerateMipmap(GL_TEXTURE_2D);
4884
4885 // Test that the texture looks as expected.
4886 const int w = getWindowWidth() - 1;
4887 const int h = getWindowHeight() - 1;
4888 for (uint32_t lod = 0; lod < kMipCount + 1; ++lod)
4889 {
4890 setLodUniform(lod);
4891 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4892 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor);
4893 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor);
4894 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor);
4895 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor);
4896 }
4897 }
4898
4899 // Test that generating mipmaps after incompatibly redefining the base level while simultaneously
4900 // changing MAX_LEVEL works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefiningBaseAndChangingMax)4901 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBaseAndChangingMax)
4902 {
4903 initTest(false);
4904
4905 // Test that all mips have the expected data initially (this makes sure the texture image is
4906 // created already).
4907 for (uint32_t lod = 0; lod < kMipCount; ++lod)
4908 {
4909 setLodUniform(lod);
4910 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4911 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
4912 }
4913
4914 // Redefine level 0 to an incompatible size.
4915 const GLColor kNewMipColor = GLColor::yellow;
4916 std::array<GLColor, getMipDataSize(kMip0Size * 2, 0)> newMipData;
4917 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
4918
4919 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA,
4920 GL_UNSIGNED_BYTE, newMipData.data());
4921
4922 // Set max level of the texture to 2 then generate mipmaps.
4923 constexpr uint32_t kMaxLevel = 2;
4924 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMaxLevel);
4925 glGenerateMipmap(GL_TEXTURE_2D);
4926
4927 // Test that the texture looks as expected.
4928 const int w = getWindowWidth() - 1;
4929 const int h = getWindowHeight() - 1;
4930 for (uint32_t lod = 0; lod <= kMaxLevel; ++lod)
4931 {
4932 setLodUniform(lod);
4933 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4934 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor);
4935 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor);
4936 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor);
4937 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor);
4938 }
4939 }
4940
4941 // Test that stage invalid texture levels work.
TEST_P(Texture2DBaseMaxTestES3,StageInvalidLevels)4942 TEST_P(Texture2DBaseMaxTestES3, StageInvalidLevels)
4943 {
4944 constexpr uint32_t kMaxLevel = 2;
4945 const GLColor kMipColor[kMaxLevel + 1] = {GLColor::red, GLColor::green, GLColor::blue};
4946
4947 initTest(false);
4948
4949 GLTexture texture;
4950 glBindTexture(GL_TEXTURE_2D, texture);
4951
4952 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4953 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4954 std::vector<GLColor> texDataCyan(2u * 2u, GLColor::cyan);
4955 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataCyan.data());
4956 setLodUniform(0);
4957 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4958 EXPECT_GL_NO_ERROR();
4959
4960 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
4961 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4962 texDataGreen.data());
4963 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::blue);
4964 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4965 EXPECT_GL_NO_ERROR();
4966
4967 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
4968 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
4969 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
4970 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4971
4972 // Test that the texture looks as expected.
4973 const int w = getWindowWidth() - 1;
4974 const int h = getWindowHeight() - 1;
4975 for (uint32_t lod = 0; lod <= kMaxLevel; ++lod)
4976 {
4977 setLodUniform(lod);
4978 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4979 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColor[lod]);
4980 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColor[lod]);
4981 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColor[lod]);
4982 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColor[lod]);
4983 }
4984 }
4985
4986 // Test redefine a mutable texture into an immutable texture.
TEST_P(Texture2DBaseMaxTestES3,RedefineMutableToImmutable)4987 TEST_P(Texture2DBaseMaxTestES3, RedefineMutableToImmutable)
4988 {
4989 // http://anglebug.com/4710
4990 ANGLE_SKIP_TEST_IF(IsD3D());
4991
4992 // http://anglebug.com/4701
4993 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
4994
4995 constexpr uint32_t kBaseLevel = 1;
4996 const GLColor kNewMipColors[kMipCount] = {
4997 GLColor::yellow,
4998 GLColor::cyan,
4999 GLColor::white,
5000 GLColor(127u, 127u, 127u, 255u),
5001 };
5002
5003 initTest(false);
5004
5005 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, kBaseLevel);
5006
5007 // Test that all mips have the expected data
5008 for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
5009 {
5010 setLodUniform(lod - kBaseLevel);
5011 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5012 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5013 }
5014
5015 glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size);
5016 std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
5017 fillMipData(mipData.data(), kMip0Size, kNewMipColors);
5018 for (size_t mip = 0; mip < kMipCount; ++mip)
5019 {
5020 glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA,
5021 GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip));
5022 }
5023
5024 // Test that all enabled mips have the expected data
5025 for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
5026 {
5027 setLodUniform(lod - kBaseLevel);
5028 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5029 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
5030 }
5031
5032 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5033 for (uint32_t lod = 0; lod < kBaseLevel; ++lod)
5034 {
5035 setLodUniform(lod);
5036 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5037 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
5038 }
5039 }
5040
5041 // Test that redefine a level with incompatible size beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,RedefineIncompatibleLevelBeyondMaxLevel)5042 TEST_P(Texture2DBaseMaxTestES3, RedefineIncompatibleLevelBeyondMaxLevel)
5043 {
5044 initTest(false);
5045
5046 // Test that all mips have the expected data initially (this makes sure the texture image is
5047 // created already).
5048 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5049 {
5050 setLodUniform(lod);
5051 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5052 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5053 }
5054
5055 uint32_t maxLevel = 1;
5056 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
5057
5058 // Update level 0
5059 const GLColor kNewMipLevle0Color = GLColor::yellow;
5060 std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5061 std::fill(newMipData.begin(), newMipData.end(), kNewMipLevle0Color);
5062 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kMip0Size, kMip0Size, GL_RGBA, GL_UNSIGNED_BYTE,
5063 newMipData.data());
5064
5065 // Update level 2 with incompatible data
5066 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5067 newMipData.data());
5068 EXPECT_GL_NO_ERROR();
5069
5070 // Test that the texture looks as expected.
5071 const int w = getWindowWidth() - 1;
5072 const int h = getWindowHeight() - 1;
5073 for (uint32_t lod = 0; lod < maxLevel; ++lod)
5074 {
5075 setLodUniform(lod);
5076 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5077 if (lod == 0)
5078 {
5079 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipLevle0Color);
5080 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipLevle0Color);
5081 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipLevle0Color);
5082 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipLevle0Color);
5083 }
5084 else
5085 {
5086 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5087 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]);
5088 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]);
5089 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]);
5090 }
5091 }
5092 }
5093
5094 // Port test from web_gl/conformance2/textures/misc/fuzz-545-immutable-tex-render-feedback.html.
5095 // What this tries to do is create a render feedback loop and ensure it is not crashing.
TEST_P(Texture2DBaseMaxTestES3,Fuzz545ImmutableTexRenderFeedback)5096 TEST_P(Texture2DBaseMaxTestES3, Fuzz545ImmutableTexRenderFeedback)
5097 {
5098 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5099
5100 constexpr uint32_t MIPS = 2;
5101 constexpr uint32_t SIZE = 10;
5102
5103 GLTexture immutTex;
5104 glBindTexture(GL_TEXTURE_2D, immutTex);
5105 glTexStorage2D(GL_TEXTURE_2D, MIPS, GL_RGBA8, SIZE, SIZE);
5106
5107 GLTexture mutTex;
5108 glBindTexture(GL_TEXTURE_2D, mutTex);
5109 for (uint32_t mip = 0; mip < MIPS; mip++)
5110 {
5111 const uint32_t size = SIZE >> mip;
5112 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5113 nullptr);
5114 }
5115
5116 constexpr GLenum MAG_FILTERS[] = {GL_LINEAR, GL_NEAREST};
5117 constexpr GLenum MIN_FILTERS[] = {
5118 GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST,
5119 GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST};
5120
5121 GLFramebuffer fbo;
5122 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5123
5124 const GLuint texs[] = {immutTex, mutTex};
5125 for (const GLuint tex : texs)
5126 {
5127 glBindTexture(GL_TEXTURE_2D, tex);
5128
5129 for (GLuint level_prime_base = 0; level_prime_base < (MIPS + 1); level_prime_base++)
5130 { // `level_base` in GLES
5131 // ES 3.0.6 p150
5132 GLuint _level_base = level_prime_base;
5133 if (tex == immutTex)
5134 {
5135 _level_base = std::min(_level_base, MIPS - 1);
5136 }
5137 const GLuint level_base = _level_base;
5138
5139 for (GLuint _level_prime_max = (level_prime_base - 1); _level_prime_max < (MIPS + 2);
5140 _level_prime_max++)
5141 { // `q` in GLES
5142 if (_level_prime_max < 0)
5143 continue;
5144 if (_level_prime_max == (MIPS + 1))
5145 {
5146 _level_prime_max = 10000; // This is the default, after all!
5147 }
5148 const GLuint level_prime_max = _level_prime_max;
5149
5150 // ES 3.0.6 p150
5151 GLuint _level_max = level_prime_max;
5152 if (tex == immutTex)
5153 {
5154 _level_max = std::min(std::max(level_base, level_prime_max), MIPS - 1);
5155 }
5156 const GLuint level_max = _level_max;
5157
5158 const GLuint p = std::floor((float)std::log2(SIZE)) + level_base;
5159 const GLuint q = std::min(p, level_max);
5160
5161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level_prime_base);
5162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level_prime_max);
5163
5164 const bool mipComplete = (q <= MIPS - 1);
5165
5166 for (const GLenum minFilter : MIN_FILTERS)
5167 {
5168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
5169
5170 for (const GLenum magFilter : MAG_FILTERS)
5171 {
5172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
5173
5174 for (GLuint dstMip = 0; dstMip < (MIPS + 1); dstMip++)
5175 {
5176 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5177 GL_TEXTURE_2D, tex, dstMip);
5178
5179 // ES3.0 p213-214
5180 bool fbComplete = true;
5181
5182 // * "The width and height of `image` are non-zero"
5183 fbComplete &= (0 <= dstMip && dstMip <= MIPS - 1);
5184
5185 if (tex != immutTex)
5186 { // "...does not name an immutable-format texture..."
5187 // * "...the value of [level] must be in the range `[level_base,
5188 // q]`"
5189 fbComplete &= (level_base <= dstMip && dstMip <= q);
5190
5191 // * "...the value of [level] is not `level_base`, then the texture
5192 // must be mipmap complete"
5193 if (dstMip != level_base)
5194 {
5195 fbComplete &= mipComplete;
5196 }
5197 }
5198
5199 // -
5200 GLenum expectError = 0;
5201 GLenum expectStatus = GL_FRAMEBUFFER_COMPLETE;
5202 if (!fbComplete)
5203 {
5204 expectStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
5205 expectError = GL_INVALID_FRAMEBUFFER_OPERATION;
5206 }
5207
5208 // -
5209 EXPECT_GLENUM_EQ(expectStatus,
5210 glCheckFramebufferStatus(GL_FRAMEBUFFER));
5211
5212 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
5213 EXPECT_EQ(expectError, glGetError());
5214 }
5215 }
5216 }
5217 }
5218 }
5219 }
5220 }
5221
5222 // Test to check that texture completeness is determined correctly when the texture base level is
5223 // greater than 0, and also that level 0 is not sampled when base level is greater than 0.
TEST_P(Texture2DTestES3,DrawWithBaseLevel1)5224 TEST_P(Texture2DTestES3, DrawWithBaseLevel1)
5225 {
5226 glActiveTexture(GL_TEXTURE0);
5227 glBindTexture(GL_TEXTURE_2D, mTexture2D);
5228
5229 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5230 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5231 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
5232 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5233 texDataGreen.data());
5234 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5235 texDataGreen.data());
5236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5239
5240 EXPECT_GL_NO_ERROR();
5241
5242 drawQuad(mProgram, "position", 0.5f);
5243
5244 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5245 }
5246
5247 // Test basic GL_EXT_copy_image copy without any bound textures
TEST_P(Texture2DTestES3,CopyImage)5248 TEST_P(Texture2DTestES3, CopyImage)
5249 {
5250 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5251
5252 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5253 GLTexture srcTexture;
5254 GLTexture destTexture;
5255
5256 glActiveTexture(GL_TEXTURE0);
5257 glBindTexture(GL_TEXTURE_2D, destTexture);
5258 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5259 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5262 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5263
5264 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
5265 glBindTexture(GL_TEXTURE_2D, srcTexture);
5266 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5267 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5268 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5269 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5270 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5271 texDataGreen.data());
5272
5273 glBindTexture(GL_TEXTURE_2D, 0);
5274
5275 // copy
5276 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0, 2,
5277 2, 0, 2, 2, 1);
5278
5279 glBindTexture(GL_TEXTURE_2D, destTexture);
5280
5281 EXPECT_GL_NO_ERROR();
5282
5283 glViewport(0, 0, 4, 4);
5284 drawQuad(mProgram, "position", 0.5f);
5285 EXPECT_GL_NO_ERROR();
5286
5287 EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green);
5288 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red);
5289 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red);
5290 }
5291
5292 // Test GL_EXT_copy_image compressed texture copy with mipmaps smaller than the block size
TEST_P(Texture2DTestES3,CopyCompressedImageMipMaps)5293 TEST_P(Texture2DTestES3, CopyCompressedImageMipMaps)
5294 {
5295 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5296 // TODO(http://anglebug.com/5634): Fix calls to vkCmdCopyBufferToImage() with images smaller
5297 // than the compressed format block size.
5298 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
5299
5300 constexpr uint32_t kSize = 4;
5301 constexpr size_t kNumLevels = 3;
5302 const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0};
5303
5304 GLTexture srcTexture;
5305 glBindTexture(GL_TEXTURE_2D, srcTexture);
5306 for (size_t level = 0; level < kNumLevels; ++level)
5307 {
5308 glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
5309 kSize >> level, 0, 8, CompressedImageETC1);
5310 EXPECT_GL_NO_ERROR();
5311 }
5312
5313 GLTexture destTexture;
5314 glBindTexture(GL_TEXTURE_2D, destTexture);
5315 for (size_t level = 0; level < kNumLevels; ++level)
5316 {
5317 glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
5318 kSize >> level, 0, 8, nullptr);
5319 EXPECT_GL_NO_ERROR();
5320 }
5321
5322 glBindTexture(GL_TEXTURE_2D, 0);
5323
5324 // copy
5325 for (size_t level = 0; level < kNumLevels; ++level)
5326 {
5327 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, level, 0, 0, 0, destTexture, GL_TEXTURE_2D,
5328 level, 0, 0, 0, kSize >> level, kSize >> level, 1);
5329 EXPECT_GL_NO_ERROR();
5330 }
5331 }
5332
5333 // Test GL_EXT_copy_image copy with a non-zero base level
TEST_P(Texture2DTestES3,CopyImageBaseLevel1)5334 TEST_P(Texture2DTestES3, CopyImageBaseLevel1)
5335 {
5336 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5337
5338 std::vector<GLColor> texDataBlack(8u * 8u, GLColor::black);
5339 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5340 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
5341 std::vector<GLColor> texDataBlue(4u * 4u, GLColor::blue);
5342
5343 GLTexture srcTexture;
5344 GLTexture destTexture;
5345
5346 glActiveTexture(GL_TEXTURE0);
5347 glBindTexture(GL_TEXTURE_2D, destTexture);
5348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5350 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5351 texDataBlack.data());
5352 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5353 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5354 texDataGreen.data());
5355 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data());
5356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5358
5359 glBindTexture(GL_TEXTURE_2D, srcTexture);
5360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5362 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5363 texDataBlack.data());
5364 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5365 texDataGreen.data());
5366 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data());
5367 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5370
5371 glBindTexture(GL_TEXTURE_2D, 0);
5372
5373 // copy
5374 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 1, 2, 2, 0, destTexture, GL_TEXTURE_2D, 1, 2,
5375 2, 0, 2, 2, 1);
5376
5377 glBindTexture(GL_TEXTURE_2D, destTexture);
5378
5379 EXPECT_GL_NO_ERROR();
5380
5381 glViewport(0, 0, 4, 4);
5382 drawQuad(mProgram, "position", 0.5f);
5383 EXPECT_GL_NO_ERROR();
5384
5385 EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green);
5386 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red);
5387 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red);
5388 }
5389
5390 // Test basic GL_EXT_copy_image copy without any draw calls by attaching the texture
5391 // to a framebuffer and reads from the framebuffer to validate the copy
TEST_P(Texture2DTestES3,CopyImageFB)5392 TEST_P(Texture2DTestES3, CopyImageFB)
5393 {
5394 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5395
5396 glViewport(0, 0, 4, 4);
5397 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5398 GLTexture srcTexture;
5399 GLTexture destTexture;
5400
5401 glActiveTexture(GL_TEXTURE0);
5402 glBindTexture(GL_TEXTURE_2D, destTexture);
5403 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5405 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5406 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5407 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5408
5409 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
5410 glBindTexture(GL_TEXTURE_2D, srcTexture);
5411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5412 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5413 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5414 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5415 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5416 texDataGreen.data());
5417 glBindTexture(GL_TEXTURE_2D, 0);
5418
5419 // copy
5420 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, destTexture, GL_TEXTURE_2D, 0, 0,
5421 1, 0, 3, 3, 1);
5422
5423 EXPECT_GL_NO_ERROR();
5424
5425 GLFramebuffer fb;
5426 glBindFramebuffer(GL_FRAMEBUFFER, fb);
5427 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0);
5428 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5429
5430 EXPECT_PIXEL_RECT_EQ(0, 1, 3, 3, GLColor::green);
5431 EXPECT_PIXEL_RECT_EQ(3, 0, 1, 4, GLColor::red);
5432 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 1, GLColor::red);
5433
5434 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5435 }
5436
5437 // Test GL_EXT_copy_image copy to a framebuffer attachment after
5438 // invalidation. Then draw with blending onto the framebuffer.
TEST_P(Texture2DTestES3,CopyImageFBInvalidateThenBlend)5439 TEST_P(Texture2DTestES3, CopyImageFBInvalidateThenBlend)
5440 {
5441 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5442
5443 ANGLE_GL_PROGRAM(drawBlueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
5444 ANGLE_GL_PROGRAM(drawRedProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
5445
5446 glViewport(0, 0, 4, 4);
5447 GLTexture srcTexture;
5448 GLTexture textureAttachment;
5449
5450 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
5451 glBindTexture(GL_TEXTURE_2D, srcTexture);
5452 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5453 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5454 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5455 texDataGreen.data());
5456 glBindTexture(GL_TEXTURE_2D, 0);
5457
5458 glBindTexture(GL_TEXTURE_2D, textureAttachment);
5459 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5460 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5461 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5462 glBindTexture(GL_TEXTURE_2D, 0);
5463
5464 GLFramebuffer fb;
5465 glBindFramebuffer(GL_FRAMEBUFFER, fb);
5466 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureAttachment,
5467 0);
5468 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5469
5470 // Draw something in the texture to make sure it's image is defined.
5471 drawQuad(drawRedProgram, essl1_shaders::PositionAttrib(), 0.0f);
5472
5473 // Invalidate the framebuffer.
5474 const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
5475 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
5476 ASSERT_GL_NO_ERROR();
5477
5478 // Copy into the framebuffer attachment.
5479 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, textureAttachment, GL_TEXTURE_2D,
5480 0, 0, 0, 0, 4, 4, 1);
5481 EXPECT_GL_NO_ERROR();
5482
5483 // Draw and blend, making sure both the copy and draw happen correctly.
5484 glEnable(GL_BLEND);
5485 glBlendFunc(GL_ONE, GL_ONE);
5486 drawQuad(drawBlueProgram, essl1_shaders::PositionAttrib(), 0.0f);
5487 ASSERT_GL_NO_ERROR();
5488
5489 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::cyan);
5490
5491 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5492 }
5493
5494 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
5495 // have images defined.
TEST_P(Texture2DTestES3,DrawWithLevelsOutsideRangeUndefined)5496 TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeUndefined)
5497 {
5498 // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
5499 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
5500
5501 glActiveTexture(GL_TEXTURE0);
5502 glBindTexture(GL_TEXTURE_2D, mTexture2D);
5503 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
5504 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5505 texDataGreen.data());
5506 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5508 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5509 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5510
5511 EXPECT_GL_NO_ERROR();
5512
5513 drawQuad(mProgram, "position", 0.5f);
5514
5515 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5516 }
5517
5518 // Test that drawing works correctly when level 0 is undefined and base level is 1.
TEST_P(Texture2DTestES3,DrawWithLevelZeroUndefined)5519 TEST_P(Texture2DTestES3, DrawWithLevelZeroUndefined)
5520 {
5521 // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
5522 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
5523
5524 glActiveTexture(GL_TEXTURE0);
5525 glBindTexture(GL_TEXTURE_2D, mTexture2D);
5526 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
5527 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5528 texDataGreen.data());
5529 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5531 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5532 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
5533
5534 EXPECT_GL_NO_ERROR();
5535
5536 // Texture is incomplete.
5537 drawQuad(mProgram, "position", 0.5f);
5538 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
5539
5540 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5541 texDataGreen.data());
5542
5543 // Texture is now complete.
5544 drawQuad(mProgram, "position", 0.5f);
5545 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5546 }
5547
5548 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
5549 // dimensions that don't fit the images inside the range.
5550 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)5551 TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
5552 {
5553 glActiveTexture(GL_TEXTURE0);
5554 glBindTexture(GL_TEXTURE_2D, mTexture2D);
5555 std::vector<GLColor> texDataRed(8u * 8u, GLColor::red);
5556 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
5557 std::vector<GLColor> texDataCyan(2u * 2u, GLColor::cyan);
5558
5559 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5560 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5561
5562 // Two levels that are initially unused.
5563 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5564 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5565 texDataCyan.data());
5566
5567 // One level that is used - only this level should affect completeness.
5568 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5569 texDataGreen.data());
5570
5571 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5572 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5573
5574 EXPECT_GL_NO_ERROR();
5575
5576 drawQuad(mProgram, "position", 0.5f);
5577
5578 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5579
5580 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
5581
5582 // Switch the level that is being used to the cyan level 2.
5583 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
5584 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
5585
5586 EXPECT_GL_NO_ERROR();
5587
5588 drawQuad(mProgram, "position", 0.5f);
5589
5590 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5591 }
5592
5593 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
5594 // have images defined.
TEST_P(Texture3DTestES3,DrawWithLevelsOutsideRangeUndefined)5595 TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeUndefined)
5596 {
5597 glActiveTexture(GL_TEXTURE0);
5598 glBindTexture(GL_TEXTURE_3D, mTexture3D);
5599 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
5600 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5601 texDataGreen.data());
5602 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5603 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5604 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
5605 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
5606
5607 EXPECT_GL_NO_ERROR();
5608
5609 drawQuad(mProgram, "position", 0.5f);
5610
5611 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5612 }
5613
5614 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
5615 // dimensions that don't fit the images inside the range.
5616 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture3DTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)5617 TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
5618 {
5619 glActiveTexture(GL_TEXTURE0);
5620 glBindTexture(GL_TEXTURE_3D, mTexture3D);
5621 std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
5622 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
5623 std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
5624
5625 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5626 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5627
5628 // Two levels that are initially unused.
5629 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5630 texDataRed.data());
5631 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5632 texDataCyan.data());
5633
5634 // One level that is used - only this level should affect completeness.
5635 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5636 texDataGreen.data());
5637
5638 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
5639 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
5640
5641 EXPECT_GL_NO_ERROR();
5642
5643 drawQuad(mProgram, "position", 0.5f);
5644
5645 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5646
5647 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
5648
5649 // Switch the level that is being used to the cyan level 2.
5650 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 2);
5651 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 2);
5652
5653 EXPECT_GL_NO_ERROR();
5654
5655 drawQuad(mProgram, "position", 0.5f);
5656
5657 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5658 }
5659
5660 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
5661 // have images defined.
TEST_P(Texture2DArrayTestES3,DrawWithLevelsOutsideRangeUndefined)5662 TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeUndefined)
5663 {
5664 glActiveTexture(GL_TEXTURE0);
5665 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
5666 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
5667 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5668 texDataGreen.data());
5669 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5670 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5671 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
5672 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
5673
5674 EXPECT_GL_NO_ERROR();
5675
5676 drawQuad(mProgram, "position", 0.5f);
5677
5678 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5679 }
5680
5681 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
5682 // dimensions that don't fit the images inside the range.
5683 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DArrayTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)5684 TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
5685 {
5686 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
5687 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
5688
5689 glActiveTexture(GL_TEXTURE0);
5690 glBindTexture(GL_TEXTURE_3D, m2DArrayTexture);
5691 std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
5692 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
5693 std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
5694
5695 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5696 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5697
5698 // Two levels that are initially unused.
5699 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5700 texDataRed.data());
5701 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5702 texDataCyan.data());
5703
5704 // One level that is used - only this level should affect completeness.
5705 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5706 texDataGreen.data());
5707
5708 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
5709 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
5710
5711 EXPECT_GL_NO_ERROR();
5712
5713 drawQuad(mProgram, "position", 0.5f);
5714
5715 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5716
5717 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
5718
5719 // Switch the level that is being used to the cyan level 2.
5720 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 2);
5721 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 2);
5722
5723 EXPECT_GL_NO_ERROR();
5724
5725 drawQuad(mProgram, "position", 0.5f);
5726
5727 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5728 }
5729
5730 // Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
5731 // in the Vulkan backend where the old higher-layer-count data upload was not removed.
TEST_P(Texture2DArrayTestES3,TextureArrayRedefineThenUse)5732 TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse)
5733 {
5734 int px = getWindowWidth() / 2;
5735 int py = getWindowHeight() / 2;
5736
5737 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
5738
5739 // Fill the whole texture with red, then redefine it and fill with green
5740 std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
5741 std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
5742 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5743 pixelsRed.data());
5744 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5745 pixelsGreen.data());
5746
5747 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5748 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5749 EXPECT_GL_NO_ERROR();
5750
5751 glUseProgram(mProgram);
5752 EXPECT_GL_NO_ERROR();
5753
5754 // Draw the first slice
5755 glUniform1i(mTextureArraySliceUniformLocation, 0);
5756 drawQuad(mProgram, "position", 0.5f);
5757 EXPECT_GL_NO_ERROR();
5758 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
5759
5760 // Draw the second slice
5761 glUniform1i(mTextureArraySliceUniformLocation, 1);
5762 drawQuad(mProgram, "position", 0.5f);
5763 EXPECT_GL_NO_ERROR();
5764 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
5765 }
5766
5767 // Create a 2D array texture and update layers with data and test that pruning
5768 // of superseded updates works as expected.
TEST_P(Texture2DArrayTestES3,TextureArrayPruneSupersededUpdates)5769 TEST_P(Texture2DArrayTestES3, TextureArrayPruneSupersededUpdates)
5770 {
5771 constexpr uint32_t kTexWidth = 256;
5772 constexpr uint32_t kTexHeight = 256;
5773 constexpr uint32_t kTexLayers = 3;
5774
5775 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
5776 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5777 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5778 EXPECT_GL_NO_ERROR();
5779
5780 // Initialize entire texture.
5781 constexpr GLColor kInitialExpectedColor = GLColor(201u, 201u, 201u, 201u);
5782 std::vector<GLColor> initialData(kTexWidth * kTexHeight * kTexLayers, kInitialExpectedColor);
5783 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kTexWidth, kTexHeight, kTexLayers, 0, GL_RGBA,
5784 GL_UNSIGNED_BYTE, initialData.data());
5785
5786 // Upate different layers with different colors, these together should supersed
5787 // the entire init update
5788 constexpr GLColor kExpectedColor[] = {GLColor(32u, 32u, 32u, 32u), GLColor(64u, 64u, 64u, 64u),
5789 GLColor(128u, 128u, 128u, 128u)};
5790 std::vector<GLColor> supersedingData[] = {
5791 std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[0]),
5792 std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[1]),
5793 std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[2])};
5794
5795 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kTexWidth, kTexHeight, 1, GL_RGBA,
5796 GL_UNSIGNED_BYTE, supersedingData[0].data());
5797 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, kTexWidth, kTexHeight, 1, GL_RGBA,
5798 GL_UNSIGNED_BYTE, supersedingData[1].data());
5799 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, kTexWidth, kTexHeight, 1, GL_RGBA,
5800 GL_UNSIGNED_BYTE, supersedingData[2].data());
5801
5802 glUseProgram(mProgram);
5803 EXPECT_GL_NO_ERROR();
5804
5805 // Draw layer 0
5806 glUniform1i(mTextureArraySliceUniformLocation, 0);
5807 drawQuad(mProgram, "position", 0.5f);
5808 EXPECT_GL_NO_ERROR();
5809 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[0]);
5810
5811 // Draw layer 1
5812 glUniform1i(mTextureArraySliceUniformLocation, 1);
5813 drawQuad(mProgram, "position", 0.5f);
5814 EXPECT_GL_NO_ERROR();
5815 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[1]);
5816
5817 // Draw layer 2
5818 glUniform1i(mTextureArraySliceUniformLocation, 2);
5819 drawQuad(mProgram, "position", 0.5f);
5820 EXPECT_GL_NO_ERROR();
5821 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[2]);
5822 }
5823
5824 // Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
5825 // the Vulkan backend where the old higher-layer-count data upload was not removed.
TEST_P(Texture2DArrayTestES3,TextureArrayUseThenRedefineThenUse)5826 TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse)
5827 {
5828 int px = getWindowWidth() / 2;
5829 int py = getWindowHeight() / 2;
5830
5831 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
5832
5833 // Fill the whole texture with red.
5834 std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
5835 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5836 pixelsRed.data());
5837
5838 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5839 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5840 EXPECT_GL_NO_ERROR();
5841
5842 glUseProgram(mProgram);
5843 EXPECT_GL_NO_ERROR();
5844
5845 // Draw the first slice
5846 glUniform1i(mTextureArraySliceUniformLocation, 0);
5847 drawQuad(mProgram, "position", 0.5f);
5848 EXPECT_GL_NO_ERROR();
5849 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
5850
5851 // Draw the fourth slice
5852 glUniform1i(mTextureArraySliceUniformLocation, 3);
5853 drawQuad(mProgram, "position", 0.5f);
5854 EXPECT_GL_NO_ERROR();
5855 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
5856
5857 // Redefine the image and fill with green
5858 std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
5859 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5860 pixelsGreen.data());
5861
5862 // Draw the first slice
5863 glUniform1i(mTextureArraySliceUniformLocation, 0);
5864 drawQuad(mProgram, "position", 0.5f);
5865 EXPECT_GL_NO_ERROR();
5866 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
5867
5868 // Draw the second slice
5869 glUniform1i(mTextureArraySliceUniformLocation, 1);
5870 drawQuad(mProgram, "position", 0.5f);
5871 EXPECT_GL_NO_ERROR();
5872 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
5873 }
5874
5875 // Test that texture completeness is updated if texture max level changes.
5876 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureCompletenessChangesWithMaxLevel)5877 TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
5878 {
5879 glActiveTexture(GL_TEXTURE0);
5880 glBindTexture(GL_TEXTURE_2D, mTexture2D);
5881 std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
5882
5883 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5884 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5885
5886 // A level that is initially unused.
5887 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5888 texDataGreen.data());
5889
5890 // One level that is initially used - only this level should affect completeness.
5891 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5892 texDataGreen.data());
5893
5894 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5895 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5896
5897 EXPECT_GL_NO_ERROR();
5898
5899 drawQuad(mProgram, "position", 0.5f);
5900
5901 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5902
5903 // Switch the max level to level 1. The levels within the used range now have inconsistent
5904 // dimensions and the texture should be incomplete.
5905 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5906
5907 EXPECT_GL_NO_ERROR();
5908
5909 drawQuad(mProgram, "position", 0.5f);
5910
5911 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
5912 }
5913
5914 // Test that compressed textures ignore the pixel unpack state.
5915 // (https://crbug.org/1267496)
TEST_P(Texture3DTestES3,PixelUnpackStateTexImage)5916 TEST_P(Texture3DTestES3, PixelUnpackStateTexImage)
5917 {
5918 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
5919 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
5920
5921 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
5922 glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
5923
5924 uint8_t data[64] = {0};
5925 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
5926 data);
5927 EXPECT_GL_NO_ERROR();
5928 }
5929
5930 // Test that compressed textures ignore the pixel unpack state.
5931 // (https://crbug.org/1267496)
TEST_P(Texture3DTestES3,PixelUnpackStateTexSubImage)5932 TEST_P(Texture3DTestES3, PixelUnpackStateTexSubImage)
5933 {
5934 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
5935 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
5936
5937 glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
5938
5939 uint8_t data[64] = {0};
5940 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
5941 data);
5942 EXPECT_GL_NO_ERROR();
5943
5944 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
5945
5946 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 4,
5947 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, data);
5948 EXPECT_GL_NO_ERROR();
5949 }
5950
5951 // Test that 3D texture completeness is updated if texture max level changes.
5952 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture3DTestES3,Texture3DCompletenessChangesWithMaxLevel)5953 TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel)
5954 {
5955 glActiveTexture(GL_TEXTURE0);
5956 glBindTexture(GL_TEXTURE_3D, mTexture3D);
5957 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
5958
5959 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5960 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5961
5962 // A level that is initially unused.
5963 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5964 texDataGreen.data());
5965
5966 // One level that is initially used - only this level should affect completeness.
5967 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5968 texDataGreen.data());
5969
5970 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
5971 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
5972
5973 EXPECT_GL_NO_ERROR();
5974
5975 drawQuad(mProgram, "position", 0.5f);
5976
5977 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5978
5979 // Switch the max level to level 1. The levels within the used range now have inconsistent
5980 // dimensions and the texture should be incomplete.
5981 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
5982
5983 EXPECT_GL_NO_ERROR();
5984
5985 drawQuad(mProgram, "position", 0.5f);
5986
5987 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
5988 }
5989
5990 // Test that texture completeness is updated if texture base level changes.
5991 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureCompletenessChangesWithBaseLevel)5992 TEST_P(Texture2DTestES3, TextureCompletenessChangesWithBaseLevel)
5993 {
5994 glActiveTexture(GL_TEXTURE0);
5995 glBindTexture(GL_TEXTURE_2D, mTexture2D);
5996 std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
5997
5998 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5999 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6000
6001 // Two levels that are initially unused.
6002 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6003 texDataGreen.data());
6004 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6005 texDataGreen.data());
6006
6007 // One level that is initially used - only this level should affect completeness.
6008 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6009 texDataGreen.data());
6010
6011 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
6012 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
6013
6014 EXPECT_GL_NO_ERROR();
6015
6016 drawQuad(mProgram, "position", 0.5f);
6017
6018 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6019
6020 // Switch the base level to level 1. The levels within the used range now have inconsistent
6021 // dimensions and the texture should be incomplete.
6022 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6023
6024 EXPECT_GL_NO_ERROR();
6025
6026 drawQuad(mProgram, "position", 0.5f);
6027
6028 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6029 }
6030
6031 // Test that texture is not complete if base level is greater than max level.
6032 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureBaseLevelGreaterThanMaxLevel)6033 TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMaxLevel)
6034 {
6035 glActiveTexture(GL_TEXTURE0);
6036 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6037
6038 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6039 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6040
6041 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
6042
6043 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
6044 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6045
6046 EXPECT_GL_NO_ERROR();
6047
6048 drawQuad(mProgram, "position", 0.5f);
6049
6050 // Texture should be incomplete.
6051 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6052 }
6053
6054 // Test that immutable texture base level and max level are clamped.
6055 // GLES 3.0.4 section 3.8.10 subsection Mipmapping
TEST_P(Texture2DTestES3,ImmutableTextureBaseLevelOutOfRange)6056 TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange)
6057 {
6058 glActiveTexture(GL_TEXTURE0);
6059 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6060
6061 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6062 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6063
6064 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
6065
6066 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
6067
6068 // For immutable-format textures, base level should be clamped to [0, levels - 1], and max level
6069 // should be clamped to [base_level, levels - 1].
6070 // GLES 3.0.4 section 3.8.10 subsection Mipmapping
6071 // In the case of this test, those rules make the effective base level and max level 0.
6072 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
6073 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
6074
6075 EXPECT_GL_NO_ERROR();
6076
6077 drawQuad(mProgram, "position", 0.5f);
6078
6079 // Texture should be complete.
6080 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6081 }
6082
6083 // Test that changing base level works when it affects the format of the texture.
TEST_P(Texture2DTestES3,TextureFormatChangesWithBaseLevel)6084 TEST_P(Texture2DTestES3, TextureFormatChangesWithBaseLevel)
6085 {
6086 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
6087 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
6088
6089 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL());
6090
6091 // Observed incorrect rendering on AMD OpenGL.
6092 ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
6093
6094 glActiveTexture(GL_TEXTURE0);
6095 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6096 std::vector<GLColor> texDataCyan(4u * 4u, GLColor::cyan);
6097 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6098
6099 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6100 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6101
6102 // RGBA8 level that's initially unused.
6103 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6104 texDataCyan.data());
6105
6106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6108
6109 // RG8 level that's initially used, with consistent dimensions with level 0 but a different
6110 // format. It reads green channel data from the green and alpha channels of texDataGreen
6111 // (this is a bit hacky but works).
6112 glTexImage2D(GL_TEXTURE_2D, 1, GL_RG8, 2, 2, 0, GL_RG, GL_UNSIGNED_BYTE, texDataGreen.data());
6113
6114 EXPECT_GL_NO_ERROR();
6115
6116 drawQuad(mProgram, "position", 0.5f);
6117
6118 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6119
6120 // Switch the texture to use the cyan level 0 with the RGBA format.
6121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6123
6124 EXPECT_GL_NO_ERROR();
6125
6126 drawQuad(mProgram, "position", 0.5f);
6127
6128 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6129 }
6130
6131 // Test that setting a texture image works when base level is out of range.
TEST_P(Texture2DTestES3,SetImageWhenBaseLevelOutOfRange)6132 TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange)
6133 {
6134 glActiveTexture(GL_TEXTURE0);
6135 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6136
6137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6138 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6139
6140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
6141 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
6142
6143 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
6144
6145 EXPECT_GL_NO_ERROR();
6146
6147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6148
6149 drawQuad(mProgram, "position", 0.5f);
6150
6151 // Texture should be complete.
6152 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6153 }
6154
6155 // In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG
6156 // RBA->RGBA8, with 1.0 in the alpha channel. This test covers a bug where redefining array textures
6157 // with these formats does not work as expected.
TEST_P(Texture2DArrayTestES3,RedefineInittableArray)6158 TEST_P(Texture2DArrayTestES3, RedefineInittableArray)
6159 {
6160 std::vector<GLubyte> pixelData;
6161 for (size_t count = 0; count < 5000; count++)
6162 {
6163 pixelData.push_back(0u);
6164 pixelData.push_back(255u);
6165 pixelData.push_back(0u);
6166 }
6167
6168 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6169 glUseProgram(mProgram);
6170 glUniform1i(mTextureArrayLocation, 0);
6171
6172 // The first draw worked correctly.
6173 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
6174 &pixelData[0]);
6175
6176 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6177 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6178 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
6179 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
6180 drawQuad(mProgram, "position", 1.0f);
6181 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6182
6183 // The dimension of the respecification must match the original exactly to trigger the bug.
6184 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
6185 &pixelData[0]);
6186 drawQuad(mProgram, "position", 1.0f);
6187 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6188
6189 ASSERT_GL_NO_ERROR();
6190 }
6191
6192 // Test shadow sampler and regular non-shadow sampler coexisting in the same shader.
6193 // This test is needed especially to confirm that sampler registers get assigned correctly on
6194 // the HLSL backend even when there's a mix of different HLSL sampler and texture types.
TEST_P(ShadowSamplerPlusSampler3DTestES3,ShadowSamplerPlusSampler3DDraw)6195 TEST_P(ShadowSamplerPlusSampler3DTestES3, ShadowSamplerPlusSampler3DDraw)
6196 {
6197 glActiveTexture(GL_TEXTURE0);
6198 glBindTexture(GL_TEXTURE_3D, mTexture3D);
6199 GLubyte texData[4];
6200 texData[0] = 0;
6201 texData[1] = 60;
6202 texData[2] = 0;
6203 texData[3] = 255;
6204 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6205
6206 glActiveTexture(GL_TEXTURE1);
6207 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
6208 GLfloat depthTexData[1];
6209 depthTexData[0] = 0.5f;
6210 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
6211 depthTexData);
6212
6213 glUseProgram(mProgram);
6214 glUniform1f(mDepthRefUniformLocation, 0.3f);
6215 glUniform1i(mTexture3DUniformLocation, 0);
6216 glUniform1i(mTextureShadowUniformLocation, 1);
6217
6218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
6219 drawQuad(mProgram, "position", 0.5f);
6220 EXPECT_GL_NO_ERROR();
6221 // The shader writes 0.5 * <comparison result (1.0)> + <texture color>
6222 EXPECT_PIXEL_NEAR(0, 0, 128, 188, 128, 255, 2);
6223
6224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);
6225 drawQuad(mProgram, "position", 0.5f);
6226 EXPECT_GL_NO_ERROR();
6227 // The shader writes 0.5 * <comparison result (0.0)> + <texture color>
6228 EXPECT_PIXEL_NEAR(0, 0, 0, 60, 0, 255, 2);
6229 }
6230
6231 // Test multiple different sampler types in the same shader.
6232 // This test makes sure that even if sampler / texture registers get grouped together based on type
6233 // or otherwise get shuffled around in the HLSL backend of the shader translator, the D3D renderer
6234 // still has the right register index information for each ESSL sampler.
6235 // The tested ESSL samplers have the following types in D3D11 HLSL:
6236 // sampler2D: Texture2D + SamplerState
6237 // samplerCube: TextureCube + SamplerState
6238 // sampler2DShadow: Texture2D + SamplerComparisonState
6239 // samplerCubeShadow: TextureCube + SamplerComparisonState
TEST_P(SamplerTypeMixTestES3,SamplerTypeMixDraw)6240 TEST_P(SamplerTypeMixTestES3, SamplerTypeMixDraw)
6241 {
6242 glActiveTexture(GL_TEXTURE0);
6243 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6244 GLubyte texData[4];
6245 texData[0] = 0;
6246 texData[1] = 0;
6247 texData[2] = 120;
6248 texData[3] = 255;
6249 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6250
6251 glActiveTexture(GL_TEXTURE1);
6252 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
6253 texData[0] = 0;
6254 texData[1] = 90;
6255 texData[2] = 0;
6256 texData[3] = 255;
6257 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
6258 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
6259 texData);
6260
6261 glActiveTexture(GL_TEXTURE2);
6262 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
6263 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
6264 GLfloat depthTexData[1];
6265 depthTexData[0] = 0.5f;
6266 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
6267 depthTexData);
6268
6269 glActiveTexture(GL_TEXTURE3);
6270 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
6271 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
6272 depthTexData[0] = 0.2f;
6273 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT32F, 1, 1);
6274 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT,
6275 depthTexData);
6276
6277 // http://anglebug.com/3949: TODO: Add a DS texture case
6278
6279 EXPECT_GL_NO_ERROR();
6280
6281 glUseProgram(mProgram);
6282 glUniform1f(mDepthRefUniformLocation, 0.3f);
6283 glUniform1i(mTexture2DUniformLocation, 0);
6284 glUniform1i(mTextureCubeUniformLocation, 1);
6285 glUniform1i(mTexture2DShadowUniformLocation, 2);
6286 glUniform1i(mTextureCubeShadowUniformLocation, 3);
6287
6288 drawQuad(mProgram, "position", 0.5f);
6289 EXPECT_GL_NO_ERROR();
6290 // The shader writes:
6291 // <texture 2d color> +
6292 // <cube map color> +
6293 // 0.25 * <comparison result (1.0)> +
6294 // 0.125 * <comparison result (0.0)>
6295 EXPECT_PIXEL_NEAR(0, 0, 64, 154, 184, 255, 2);
6296 }
6297
6298 // Test different base levels on textures accessed through the same sampler array.
6299 // Calling textureSize() on the samplers hits the D3D sampler metadata workaround.
TEST_P(TextureSizeTextureArrayTest,BaseLevelVariesInTextureArray)6300 TEST_P(TextureSizeTextureArrayTest, BaseLevelVariesInTextureArray)
6301 {
6302 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D11());
6303
6304 // http://anglebug.com/4391
6305 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsWindows() && IsD3D11());
6306
6307 glActiveTexture(GL_TEXTURE0);
6308 glBindTexture(GL_TEXTURE_2D, mTexture2DA);
6309 GLsizei size = 64;
6310 for (GLint level = 0; level < 7; ++level)
6311 {
6312 ASSERT_LT(0, size);
6313 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6314 nullptr);
6315 size = size / 2;
6316 }
6317 ASSERT_EQ(0, size);
6318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6319
6320 glActiveTexture(GL_TEXTURE1);
6321 glBindTexture(GL_TEXTURE_2D, mTexture2DB);
6322 size = 128;
6323 for (GLint level = 0; level < 8; ++level)
6324 {
6325 ASSERT_LT(0, size);
6326 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6327 nullptr);
6328 size = size / 2;
6329 }
6330 ASSERT_EQ(0, size);
6331 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 3);
6332 EXPECT_GL_NO_ERROR();
6333
6334 glUseProgram(mProgram);
6335 glUniform1i(mTexture0Location, 0);
6336 glUniform1i(mTexture1Location, 1);
6337
6338 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
6339 EXPECT_GL_NO_ERROR();
6340 // Red channel: width of level 1 of texture A: 32.
6341 // Green channel: width of level 3 of texture B: 16.
6342 EXPECT_PIXEL_NEAR(0, 0, 32, 16, 0, 255, 2);
6343 }
6344
6345 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6346 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBImplicitAlpha1)6347 TEST_P(Texture2DTestES3, TextureRGBImplicitAlpha1)
6348 {
6349 glActiveTexture(GL_TEXTURE0);
6350 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6351 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
6352 EXPECT_GL_NO_ERROR();
6353
6354 drawQuad(mProgram, "position", 0.5f);
6355
6356 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6357 }
6358
6359 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6360 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBXImplicitAlpha1)6361 TEST_P(Texture2DTestES3, TextureRGBXImplicitAlpha1)
6362 {
6363 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
6364
6365 GLTexture texture2D;
6366 glBindTexture(GL_TEXTURE_2D, texture2D);
6367 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBX8_ANGLE, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
6368 glActiveTexture(GL_TEXTURE0);
6369 EXPECT_GL_NO_ERROR();
6370
6371 drawQuad(mProgram, "position", 0.5f);
6372
6373 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6374 }
6375
6376 // Test that data upload to RGBX works.
TEST_P(Texture2DTestES3,TextureRGBXUpload)6377 TEST_P(Texture2DTestES3, TextureRGBXUpload)
6378 {
6379 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
6380
6381 const size_t kWidth = 32;
6382 const size_t kHeight = 32;
6383
6384 GLTexture color;
6385 glBindTexture(GL_TEXTURE_2D, color);
6386 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
6387
6388 GLFramebuffer fbo;
6389 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6390 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
6391 ASSERT_GL_NO_ERROR();
6392 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6393
6394 // Upload data to an RGBX texture
6395 const GLColorRGB kColor(100, 200, 55);
6396 std::vector<GLColorRGB> data(kWidth * kHeight, kColor);
6397
6398 GLTexture texture;
6399 glBindTexture(GL_TEXTURE_2D, texture);
6400 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight);
6401 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6402 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6403 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, data.data());
6404 ASSERT_GL_NO_ERROR();
6405
6406 // Sample from the texture
6407 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
6408 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
6409
6410 const GLColor kExpect(kColor.R, kColor.G, kColor.B, 255);
6411 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
6412 EXPECT_PIXEL_COLOR_NEAR(0, 1, kExpect, 1);
6413 EXPECT_PIXEL_COLOR_NEAR(1, 0, kExpect, 1);
6414 EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, kExpect, 1);
6415 EXPECT_PIXEL_COLOR_NEAR(0, kHeight - 1, kExpect, 1);
6416 EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, kExpect, 1);
6417 EXPECT_PIXEL_COLOR_NEAR(kWidth / 2, kHeight / 2, kExpect, 1);
6418 ASSERT_GL_NO_ERROR();
6419 }
6420
6421 // Test that data download from RGBX works.
TEST_P(Texture2DTestES3,TextureRGBXDownload)6422 TEST_P(Texture2DTestES3, TextureRGBXDownload)
6423 {
6424 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
6425
6426 const size_t kWidth = 32;
6427 const size_t kHeight = 32;
6428
6429 GLTexture color;
6430 glBindTexture(GL_TEXTURE_2D, color);
6431 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight);
6432
6433 GLFramebuffer fbo;
6434 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6435 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
6436 ASSERT_GL_NO_ERROR();
6437 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6438
6439 // Render to the RGBX texture
6440 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
6441 glUseProgram(program);
6442 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
6443 ASSERT_NE(colorLoc, -1);
6444
6445 glUniform4f(colorLoc, 0.3f, 0.6f, 0.8f, 0.2f);
6446 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
6447 ASSERT_GL_NO_ERROR();
6448
6449 // Readback as RGBX.
6450 std::vector<GLColor> readback(kWidth * kHeight);
6451 glReadPixels(0, 0, kWidth, kHeight, GL_RGBX8_ANGLE, GL_UNSIGNED_BYTE, readback.data());
6452 ASSERT_GL_NO_ERROR();
6453
6454 const GLColor kExpect(76, // 0.3f * 255
6455 153, // 0.6f * 255
6456 204, // 0.8f * 255
6457 255);
6458
6459 for (size_t y = 0; y < kHeight; y++)
6460 {
6461 for (size_t x = 0; x < kWidth; x++)
6462 {
6463 const GLColor actualColor = readback[y * kWidth + x];
6464
6465 EXPECT_NEAR(actualColor.R, kExpect.R, 1) << x << "x" << y;
6466 EXPECT_NEAR(actualColor.G, kExpect.G, 1) << x << "x" << y;
6467 EXPECT_NEAR(actualColor.B, kExpect.B, 1) << x << "x" << y;
6468 EXPECT_EQ(actualColor.A, kExpect.A) << x << "x" << y;
6469 }
6470 }
6471 ASSERT_GL_NO_ERROR();
6472 }
6473
6474 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6475 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminanceImplicitAlpha1)6476 TEST_P(Texture2DTest, TextureLuminanceImplicitAlpha1)
6477 {
6478 setUpProgram();
6479
6480 glActiveTexture(GL_TEXTURE0);
6481 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6482 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
6483 EXPECT_GL_NO_ERROR();
6484
6485 drawQuad(mProgram, "position", 0.5f);
6486
6487 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6488 }
6489
6490 // Validate that every component of the pixel will be equal to the luminance value we've set
6491 // and that the alpha channel will be 1 (or 255 to be exact).
TEST_P(Texture2DTest,TextureLuminanceRGBSame)6492 TEST_P(Texture2DTest, TextureLuminanceRGBSame)
6493 {
6494 setUpProgram();
6495
6496 glActiveTexture(GL_TEXTURE0);
6497 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6498 uint8_t pixel = 50;
6499 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pixel);
6500 EXPECT_GL_NO_ERROR();
6501
6502 drawQuad(mProgram, "position", 0.5f);
6503
6504 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel, pixel, pixel, 255));
6505 }
6506
6507 // Validate that every component of the pixel will be equal to the luminance value we've set
6508 // and that the alpha channel will be the second component.
TEST_P(Texture2DTest,TextureLuminanceAlphaRGBSame)6509 TEST_P(Texture2DTest, TextureLuminanceAlphaRGBSame)
6510 {
6511 setUpProgram();
6512
6513 glActiveTexture(GL_TEXTURE0);
6514 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6515 uint8_t pixel[] = {50, 25};
6516 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 1, 1, 0, GL_LUMINANCE_ALPHA,
6517 GL_UNSIGNED_BYTE, pixel);
6518 EXPECT_GL_NO_ERROR();
6519
6520 drawQuad(mProgram, "position", 0.5f);
6521
6522 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel[0], pixel[0], pixel[0], pixel[1]));
6523 }
6524
6525 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6526 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminance32ImplicitAlpha1)6527 TEST_P(Texture2DTest, TextureLuminance32ImplicitAlpha1)
6528 {
6529 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
6530 ANGLE_SKIP_TEST_IF(IsD3D9());
6531 ANGLE_SKIP_TEST_IF(IsVulkan());
6532
6533 setUpProgram();
6534
6535 glActiveTexture(GL_TEXTURE0);
6536 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6537 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_FLOAT, nullptr);
6538 EXPECT_GL_NO_ERROR();
6539
6540 drawQuad(mProgram, "position", 0.5f);
6541
6542 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6543 }
6544
6545 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6546 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminance16ImplicitAlpha1)6547 TEST_P(Texture2DTest, TextureLuminance16ImplicitAlpha1)
6548 {
6549 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
6550 ANGLE_SKIP_TEST_IF(IsD3D9());
6551 ANGLE_SKIP_TEST_IF(IsVulkan());
6552 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1420 is fixed
6553 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6554
6555 setUpProgram();
6556
6557 glActiveTexture(GL_TEXTURE0);
6558 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6559 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, nullptr);
6560 EXPECT_GL_NO_ERROR();
6561
6562 drawQuad(mProgram, "position", 0.5f);
6563
6564 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6565 }
6566
6567 // Test that CopyTexImage2D does not trigger assertion after CompressedTexImage2D.
6568 // https://crbug.com/1216276
TEST_P(Texture2DTest,CopyAfterCompressed)6569 TEST_P(Texture2DTest, CopyAfterCompressed)
6570 {
6571 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
6572
6573 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6574 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8, nullptr);
6575 EXPECT_GL_NO_ERROR();
6576
6577 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 0, 0, 4, 4, 0);
6578 EXPECT_GL_NO_ERROR();
6579 }
6580
6581 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6582 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB8UIImplicitAlpha1)6583 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB8UIImplicitAlpha1)
6584 {
6585 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac());
6586
6587 glActiveTexture(GL_TEXTURE0);
6588 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6589 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, nullptr);
6590 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6591 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6592 EXPECT_GL_NO_ERROR();
6593
6594 drawQuad(mProgram, "position", 0.5f);
6595
6596 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6597 }
6598
6599 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6600 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB8IImplicitAlpha1)6601 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB8IImplicitAlpha1)
6602 {
6603 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac());
6604
6605 glActiveTexture(GL_TEXTURE0);
6606 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6607
6608 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8I, 1, 1, 0, GL_RGB_INTEGER, GL_BYTE, nullptr);
6609 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6610 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6611 EXPECT_GL_NO_ERROR();
6612
6613 drawQuad(mProgram, "position", 0.5f);
6614
6615 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6616 }
6617
6618 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6619 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB16UIImplicitAlpha1)6620 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB16UIImplicitAlpha1)
6621 {
6622 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac());
6623
6624 glActiveTexture(GL_TEXTURE0);
6625 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6626 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, nullptr);
6627 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6628 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6629 EXPECT_GL_NO_ERROR();
6630
6631 drawQuad(mProgram, "position", 0.5f);
6632
6633 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6634 }
6635
6636 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6637 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB16IImplicitAlpha1)6638 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB16IImplicitAlpha1)
6639 {
6640 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac());
6641
6642 glActiveTexture(GL_TEXTURE0);
6643 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6644 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16I, 1, 1, 0, GL_RGB_INTEGER, GL_SHORT, nullptr);
6645 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6646 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6647 EXPECT_GL_NO_ERROR();
6648
6649 drawQuad(mProgram, "position", 0.5f);
6650
6651 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6652 }
6653
6654 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6655 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB32UIImplicitAlpha1)6656 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB32UIImplicitAlpha1)
6657 {
6658 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac());
6659
6660 glActiveTexture(GL_TEXTURE0);
6661 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6662 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, nullptr);
6663 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6664 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6665 EXPECT_GL_NO_ERROR();
6666
6667 drawQuad(mProgram, "position", 0.5f);
6668
6669 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6670 }
6671
6672 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6673 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB32IImplicitAlpha1)6674 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB32IImplicitAlpha1)
6675 {
6676 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac());
6677
6678 glActiveTexture(GL_TEXTURE0);
6679 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6680 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, nullptr);
6681 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6682 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6683 EXPECT_GL_NO_ERROR();
6684
6685 drawQuad(mProgram, "position", 0.5f);
6686
6687 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6688 }
6689
6690 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6691 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBSNORMImplicitAlpha1)6692 TEST_P(Texture2DTestES3, TextureRGBSNORMImplicitAlpha1)
6693 {
6694 glActiveTexture(GL_TEXTURE0);
6695 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6696 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8_SNORM, 1, 1, 0, GL_RGB, GL_BYTE, nullptr);
6697 EXPECT_GL_NO_ERROR();
6698
6699 drawQuad(mProgram, "position", 0.5f);
6700
6701 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6702 }
6703
6704 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6705 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGB9E5ImplicitAlpha1)6706 TEST_P(Texture2DTestES3, TextureRGB9E5ImplicitAlpha1)
6707 {
6708 glActiveTexture(GL_TEXTURE0);
6709 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6710 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV,
6711 nullptr);
6712 EXPECT_GL_NO_ERROR();
6713
6714 drawQuad(mProgram, "position", 0.5f);
6715
6716 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6717 }
6718
6719 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6720 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)6721 TEST_P(Texture2DTestES3, TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)
6722 {
6723 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
6724 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
6725
6726 glActiveTexture(GL_TEXTURE0);
6727 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6728 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 1, 1, 0, 8, nullptr);
6729 EXPECT_GL_NO_ERROR();
6730
6731 drawQuad(mProgram, "position", 0.5f);
6732
6733 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6734 }
6735
6736 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
6737 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)6738 TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)
6739 {
6740 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
6741 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
6742
6743 glActiveTexture(GL_TEXTURE0);
6744 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6745 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, 1, 1, 0, 8, nullptr);
6746 EXPECT_GL_NO_ERROR();
6747
6748 drawQuad(mProgram, "position", 0.5f);
6749
6750 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6751 }
6752
6753 // ETC2 punchthrough alpha formats must be initialized to opaque black when emulated
6754 // http://anglebug.com/6936
TEST_P(Texture2DTestES3RobustInit,TextureCOMPRESSEDRGB8A1ETC2)6755 TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDRGB8A1ETC2)
6756 {
6757 glActiveTexture(GL_TEXTURE0);
6758 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6759 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0,
6760 8, nullptr);
6761 EXPECT_GL_NO_ERROR();
6762
6763 drawQuad(mProgram, "position", 0.5f);
6764
6765 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6766 }
6767
6768 // ETC2 punchthrough alpha formats must be initialized to opaque black when emulated
6769 // http://anglebug.com/6936
TEST_P(Texture2DTestES3RobustInit,TextureCOMPRESSEDSRGB8A1ETC2)6770 TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDSRGB8A1ETC2)
6771 {
6772 glActiveTexture(GL_TEXTURE0);
6773 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6774 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0,
6775 8, nullptr);
6776 EXPECT_GL_NO_ERROR();
6777
6778 drawQuad(mProgram, "position", 0.5f);
6779
6780 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
6781 }
6782
6783 // Test that compressed textures ignore the pixel unpack state.
6784 // (https://crbug.org/1267496)
TEST_P(Texture2DTestES3,PixelUnpackStateTexImage)6785 TEST_P(Texture2DTestES3, PixelUnpackStateTexImage)
6786 {
6787 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
6788 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
6789
6790 glPixelStorei(GL_UNPACK_ROW_LENGTH, 9);
6791 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6792
6793 uint8_t data[64] = {0};
6794 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data);
6795 EXPECT_GL_NO_ERROR();
6796 }
6797
6798 // Test that compressed textures ignore the pixel unpack state.
6799 // (https://crbug.org/1267496)
TEST_P(Texture2DTestES3,PixelUnpackStateTexSubImage)6800 TEST_P(Texture2DTestES3, PixelUnpackStateTexSubImage)
6801 {
6802 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
6803 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
6804
6805 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6806
6807 uint8_t data[64] = {0};
6808 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data);
6809 EXPECT_GL_NO_ERROR();
6810
6811 glPixelStorei(GL_UNPACK_ROW_LENGTH, 9);
6812
6813 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64,
6814 data);
6815 EXPECT_GL_NO_ERROR();
6816 }
6817
6818 // Test for http://anglebug.com/6926.
TEST_P(Texture2DTestES3,TextureRGBUpdateWithPBO)6819 TEST_P(Texture2DTestES3, TextureRGBUpdateWithPBO)
6820 {
6821 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
6822
6823 glViewport(0, 0, 16, 16);
6824
6825 GLTexture tex1;
6826 std::vector<GLColor> texDataRed(16u * 16u, GLColor::red);
6827 std::vector<GLColor> texDataGreen(16u * 16u, GLColor::green);
6828
6829 glBindTexture(GL_TEXTURE_2D, tex1);
6830 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
6831 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, texDataRed.data());
6832 ASSERT_GL_NO_ERROR();
6833
6834 GLBuffer pbo;
6835 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
6836 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, texDataGreen.data(), GL_STATIC_DRAW);
6837 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
6838 ASSERT_GL_NO_ERROR();
6839
6840 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
6841 ASSERT_GL_NO_ERROR();
6842
6843 glBindTexture(GL_TEXTURE_2D, 0);
6844 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
6845 EXPECT_PIXEL_COLOR_EQ(4, 4, GLColor::green);
6846 }
6847
6848 // Copied from Texture2DTest::TexStorage
6849 // Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
6850 // default color.
TEST_P(Texture2DTestES31PPO,TexStorage)6851 TEST_P(Texture2DTestES31PPO, TexStorage)
6852 {
6853 ANGLE_SKIP_TEST_IF(!IsVulkan());
6854 ANGLE_SKIP_TEST_IF((getClientMajorVersion() < 3 && getClientMinorVersion() < 1) &&
6855 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
6856
6857 const char *vertexShaderSource = getVertexShaderSource();
6858 const char *fragmentShaderSource = getFragmentShaderSource();
6859
6860 bindProgramPipeline(vertexShaderSource, fragmentShaderSource);
6861 mTexture2DUniformLocation = glGetUniformLocation(mFragProg, getTextureUniformName());
6862
6863 int width = getWindowWidth();
6864 int height = getWindowHeight();
6865
6866 GLTexture tex2D;
6867 glActiveTexture(GL_TEXTURE0);
6868 glBindTexture(GL_TEXTURE_2D, tex2D);
6869
6870 // Fill with red
6871 std::vector<GLubyte> pixels(3 * 16 * 16);
6872 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
6873 {
6874 pixels[pixelId * 3 + 0] = 255;
6875 pixels[pixelId * 3 + 1] = 0;
6876 pixels[pixelId * 3 + 2] = 0;
6877 }
6878
6879 // ANGLE internally uses RGBA as the internal format for RGB images, therefore glTexStorage2DEXT
6880 // initializes the image to a default color to get a consistent alpha color. The data is kept in
6881 // a CPU-side image and the image is marked as dirty.
6882 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
6883
6884 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
6885 // glTexSubImage2D should take into account that the image is dirty.
6886 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
6887 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6888 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6889
6890 glActiveShaderProgram(mPipeline, mFragProg);
6891 glUniform1i(mTexture2DUniformLocation, 0);
6892
6893 std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
6894 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
6895
6896 EXPECT_GL_NO_ERROR();
6897 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
6898
6899 // Validate that the region of the texture without data has an alpha of 1.0
6900 angle::GLColor pixel = ReadColor(3 * width / 4, 3 * height / 4);
6901 EXPECT_EQ(255, pixel.A);
6902 }
6903
6904 // Copied from Texture2DTestES3::SingleTextureMultipleSamplers
6905 // Tests behaviour with a single texture and multiple sampler objects.
TEST_P(Texture2DTestES31PPO,SingleTextureMultipleSamplers)6906 TEST_P(Texture2DTestES31PPO, SingleTextureMultipleSamplers)
6907 {
6908 ANGLE_SKIP_TEST_IF(!IsVulkan());
6909
6910 const char *vertexShaderSource = getVertexShaderSource();
6911 const char *fragmentShaderSource = getFragmentShaderSource();
6912
6913 bindProgramPipeline(vertexShaderSource, fragmentShaderSource);
6914 mTexture2DUniformLocation = glGetUniformLocation(mFragProg, getTextureUniformName());
6915
6916 GLint maxTextureUnits = 0;
6917 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
6918 ANGLE_SKIP_TEST_IF(maxTextureUnits < 4);
6919
6920 constexpr int kSize = 16;
6921 std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
6922
6923 // Make a single-level texture, fill it with red.
6924 std::vector<GLColor> redColors(kSize * kSize, GLColor::red);
6925 GLTexture tex;
6926 glBindTexture(GL_TEXTURE_2D, tex);
6927 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6928 redColors.data());
6929 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6930 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6931
6932 // Simple confidence check.
6933 bind2DTexturedQuadProgramPipeline();
6934 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
6935 ASSERT_GL_NO_ERROR();
6936 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6937
6938 // Bind texture to unit 1 with a sampler object making it incomplete.
6939 GLSampler sampler;
6940 glBindSampler(0, sampler);
6941 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
6942 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6943
6944 // Make a mipmap texture, fill it with blue.
6945 std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
6946 GLTexture mipmapTex;
6947 glBindTexture(GL_TEXTURE_2D, mipmapTex);
6948 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6949 blueColors.data());
6950 glGenerateMipmap(GL_TEXTURE_2D);
6951
6952 // Draw with the sampler, expect blue.
6953 draw2DTexturedQuad(0.5f, 1.0f, true);
6954 ASSERT_GL_NO_ERROR();
6955 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
6956
6957 // Simple multitexturing program.
6958 constexpr char kVS[] =
6959 "#version 310 es\n"
6960 "precision mediump float;\n"
6961 "in vec2 position;\n"
6962 "out vec2 texCoord;\n"
6963 "void main()\n"
6964 "{\n"
6965 " gl_Position = vec4(position, 0, 1);\n"
6966 " texCoord = position * 0.5 + vec2(0.5);\n"
6967 "}";
6968
6969 constexpr char kFS[] =
6970 "#version 310 es\n"
6971 "precision mediump float;\n"
6972 "in vec2 texCoord;\n"
6973 "uniform sampler2D tex1;\n"
6974 "uniform sampler2D tex2;\n"
6975 "uniform sampler2D tex3;\n"
6976 "uniform sampler2D tex4;\n"
6977 "out vec4 color;\n"
6978 "void main()\n"
6979 "{\n"
6980 " color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
6981 " + texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
6982 "}";
6983
6984 bindProgramPipeline(kVS, kFS);
6985
6986 std::array<GLint, 4> texLocations = {
6987 {glGetUniformLocation(mFragProg, "tex1"), glGetUniformLocation(mFragProg, "tex2"),
6988 glGetUniformLocation(mFragProg, "tex3"), glGetUniformLocation(mFragProg, "tex4")}};
6989 for (GLint location : texLocations)
6990 {
6991 ASSERT_NE(-1, location);
6992 }
6993
6994 // Init the uniform data.
6995 glActiveShaderProgram(mPipeline, mFragProg);
6996 for (GLint location = 0; location < 4; ++location)
6997 {
6998 glUniform1i(texLocations[location], location);
6999 }
7000
7001 // Initialize four samplers
7002 GLSampler samplers[4];
7003
7004 // 0: non-mipped.
7005 glBindSampler(0, samplers[0]);
7006 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7007 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7008
7009 // 1: mipped.
7010 glBindSampler(1, samplers[1]);
7011 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
7012 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7013
7014 // 2: non-mipped.
7015 glBindSampler(2, samplers[2]);
7016 glSamplerParameteri(samplers[2], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7017 glSamplerParameteri(samplers[2], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7018
7019 // 3: mipped.
7020 glBindSampler(3, samplers[3]);
7021 glSamplerParameteri(samplers[3], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
7022 glSamplerParameteri(samplers[3], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7023
7024 // Bind two blue mipped textures and two single layer textures, should all draw.
7025 glActiveTexture(GL_TEXTURE0);
7026 glBindTexture(GL_TEXTURE_2D, tex);
7027
7028 glActiveTexture(GL_TEXTURE1);
7029 glBindTexture(GL_TEXTURE_2D, mipmapTex);
7030
7031 glActiveTexture(GL_TEXTURE2);
7032 glBindTexture(GL_TEXTURE_2D, tex);
7033
7034 glActiveTexture(GL_TEXTURE3);
7035 glBindTexture(GL_TEXTURE_2D, mipmapTex);
7036
7037 ASSERT_GL_NO_ERROR();
7038
7039 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7040 ASSERT_GL_NO_ERROR();
7041 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 255, 2);
7042
7043 // Bind four single layer textures, two should be incomplete.
7044 glActiveTexture(GL_TEXTURE1);
7045 glBindTexture(GL_TEXTURE_2D, tex);
7046
7047 glActiveTexture(GL_TEXTURE3);
7048 glBindTexture(GL_TEXTURE_2D, tex);
7049
7050 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7051 ASSERT_GL_NO_ERROR();
7052 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 2);
7053 }
7054
7055 // Use a sampler in a uniform struct.
TEST_P(SamplerInStructTest,SamplerInStruct)7056 TEST_P(SamplerInStructTest, SamplerInStruct)
7057 {
7058 runSamplerInStructTest();
7059 }
7060
7061 // Use a sampler in a uniform struct that's passed as a function parameter.
TEST_P(SamplerInStructAsFunctionParameterTest,SamplerInStructAsFunctionParameter)7062 TEST_P(SamplerInStructAsFunctionParameterTest, SamplerInStructAsFunctionParameter)
7063 {
7064 // Fails on Nexus 5X due to a driver bug. http://anglebug.com/1427
7065 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
7066
7067 runSamplerInStructTest();
7068 }
7069
7070 // Use a sampler in a uniform struct array with a struct from the array passed as a function
7071 // parameter.
TEST_P(SamplerInStructArrayAsFunctionParameterTest,SamplerInStructArrayAsFunctionParameter)7072 TEST_P(SamplerInStructArrayAsFunctionParameterTest, SamplerInStructArrayAsFunctionParameter)
7073 {
7074 // Fails on Nexus 5X due to a driver bug. http://anglebug.com/1427
7075 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
7076
7077 runSamplerInStructTest();
7078 }
7079
7080 // Use a sampler in a struct inside a uniform struct with the nested struct passed as a function
7081 // parameter.
TEST_P(SamplerInNestedStructAsFunctionParameterTest,SamplerInNestedStructAsFunctionParameter)7082 TEST_P(SamplerInNestedStructAsFunctionParameterTest, SamplerInNestedStructAsFunctionParameter)
7083 {
7084 // Fails on Nexus 5X due to a driver bug. http://anglebug.com/1427
7085 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
7086
7087 runSamplerInStructTest();
7088 }
7089
7090 // Make sure that there isn't a name conflict between sampler extracted from a struct and a
7091 // similarly named uniform.
TEST_P(SamplerInStructAndOtherVariableTest,SamplerInStructAndOtherVariable)7092 TEST_P(SamplerInStructAndOtherVariableTest, SamplerInStructAndOtherVariable)
7093 {
7094 runSamplerInStructTest();
7095 }
7096
7097 // GL_EXT_texture_filter_anisotropic
7098 class TextureAnisotropyTest : public Texture2DTest
7099 {
7100 protected:
uploadTexture()7101 void uploadTexture()
7102 {
7103 glActiveTexture(GL_TEXTURE0);
7104 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7105 GLColor texDataRed[1] = {GLColor::red};
7106 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed);
7107 EXPECT_GL_NO_ERROR();
7108 }
7109 };
7110
7111 // Tests that setting anisotropic filtering doesn't cause failures at draw time.
TEST_P(TextureAnisotropyTest,AnisotropyFunctional)7112 TEST_P(TextureAnisotropyTest, AnisotropyFunctional)
7113 {
7114 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_filter_anisotropic"));
7115
7116 setUpProgram();
7117
7118 uploadTexture();
7119
7120 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7122 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
7123 EXPECT_GL_NO_ERROR();
7124
7125 drawQuad(mProgram, "position", 0.5f);
7126
7127 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
7128 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7129 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
7130 }
7131
7132 // GL_OES_texture_border_clamp
7133 class TextureBorderClampTest : public Texture2DTest
7134 {
7135 protected:
TextureBorderClampTest()7136 TextureBorderClampTest() : Texture2DTest() {}
7137
getVertexShaderSource()7138 const char *getVertexShaderSource() override
7139 {
7140 return
7141 R"(precision highp float;
7142 attribute vec4 position;
7143 varying vec2 texcoord;
7144
7145 void main()
7146 {
7147 gl_Position = vec4(position.xy, 0.0, 1.0);
7148 // texcoords in [-0.5, 1.5]
7149 texcoord = (position.xy) + 0.5;
7150 })";
7151 }
7152
uploadTexture()7153 void uploadTexture()
7154 {
7155 glActiveTexture(GL_TEXTURE0);
7156 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7157 std::vector<GLColor> texDataRed(1, GLColor::red);
7158 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7159 texDataRed.data());
7160 EXPECT_GL_NO_ERROR();
7161 }
7162
testFormat(GLenum format,GLenum type,GLColor32F borderColor)7163 void testFormat(GLenum format, GLenum type, GLColor32F borderColor)
7164 {
7165 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7166 glActiveTexture(GL_TEXTURE0);
7167 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &borderColor.R);
7168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7172 glTexImage2D(GL_TEXTURE_2D, 0, format, 2, 2, 0, format, type, nullptr);
7173 drawQuad(mProgram, "position", 0.5f);
7174 }
7175
testCompressedFormat(GLenum format,GLsizei size,GLColor32F borderColor)7176 void testCompressedFormat(GLenum format, GLsizei size, GLColor32F borderColor)
7177 {
7178 setUpProgram();
7179 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7180 glActiveTexture(GL_TEXTURE0);
7181 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &borderColor.R);
7182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7186 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, 4, 4, 0, size, nullptr);
7187 drawQuad(mProgram, "position", 0.5f);
7188 }
7189 };
7190
7191 // Test if the color set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the texture in
7192 // GL_CLAMP_TO_BORDER wrap mode (set with glTexParameter).
TEST_P(TextureBorderClampTest,TextureBorderClampFunctional)7193 TEST_P(TextureBorderClampTest, TextureBorderClampFunctional)
7194 {
7195 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7196
7197 setUpProgram();
7198
7199 uploadTexture();
7200
7201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7202 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7203 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7204 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7205 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
7206 EXPECT_GL_NO_ERROR();
7207
7208 drawQuad(mProgram, "position", 0.5f);
7209
7210 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
7211 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7212 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
7213 }
7214
7215 // Test reading back GL_TEXTURE_BORDER_COLOR by glGetTexParameter.
TEST_P(TextureBorderClampTest,TextureBorderClampFunctional2)7216 TEST_P(TextureBorderClampTest, TextureBorderClampFunctional2)
7217 {
7218 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7219
7220 glActiveTexture(GL_TEXTURE0);
7221 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7222
7223 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
7224
7225 GLint colorFixedPoint[4] = {0};
7226 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorFixedPoint);
7227 constexpr GLint colorGreenFixedPoint[4] = {0, std::numeric_limits<GLint>::max(), 0,
7228 std::numeric_limits<GLint>::max()};
7229 EXPECT_EQ(colorFixedPoint[0], colorGreenFixedPoint[0]);
7230 EXPECT_EQ(colorFixedPoint[1], colorGreenFixedPoint[1]);
7231 EXPECT_EQ(colorFixedPoint[2], colorGreenFixedPoint[2]);
7232 EXPECT_EQ(colorFixedPoint[3], colorGreenFixedPoint[3]);
7233
7234 constexpr GLint colorBlueFixedPoint[4] = {0, 0, std::numeric_limits<GLint>::max(),
7235 std::numeric_limits<GLint>::max()};
7236 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorBlueFixedPoint);
7237
7238 GLfloat color[4] = {0.0f};
7239 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
7240 EXPECT_EQ(color[0], kFloatBlue.R);
7241 EXPECT_EQ(color[1], kFloatBlue.G);
7242 EXPECT_EQ(color[2], kFloatBlue.B);
7243 EXPECT_EQ(color[3], kFloatBlue.A);
7244 }
7245
7246 // Test GL_TEXTURE_BORDER_COLOR parameter validation at glTexParameter.
TEST_P(TextureBorderClampTest,TextureBorderClampValidation)7247 TEST_P(TextureBorderClampTest, TextureBorderClampValidation)
7248 {
7249 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7250
7251 glActiveTexture(GL_TEXTURE0);
7252 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7253
7254 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, 1.0f);
7255 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7256
7257 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::numeric_limits<GLint>::max());
7258 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7259
7260 glTexParameterfv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
7261 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7262
7263 GLint colorInt[4] = {0};
7264 glTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_BORDER_COLOR, colorInt);
7265 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7266
7267 if (getClientMajorVersion() < 3)
7268 {
7269 glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
7270 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7271 glGetTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
7272 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7273
7274 GLuint colorUInt[4] = {0};
7275 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
7276 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7277 glGetTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
7278 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7279
7280 GLSampler sampler;
7281 glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
7282 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7283 glGetSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
7284 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7285
7286 glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
7287 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7288 glGetSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
7289 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7290 }
7291 }
7292
7293 // Test GL_TEXTURE_BORDER_COLOR parameter with unorm formats.
TEST_P(TextureBorderClampTest,TextureBorderClampUnorm8)7294 TEST_P(TextureBorderClampTest, TextureBorderClampUnorm8)
7295 {
7296 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7297
7298 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
7299
7300 setUpProgram();
7301
7302 testFormat(GL_ALPHA, GL_UNSIGNED_BYTE, kBorder);
7303 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
7304
7305 testFormat(GL_RGB, GL_UNSIGNED_BYTE, kBorder);
7306 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
7307
7308 testFormat(GL_RGBA, GL_UNSIGNED_BYTE, kBorder);
7309 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
7310
7311 testFormat(GL_LUMINANCE, GL_UNSIGNED_BYTE, kBorder);
7312 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
7313
7314 testFormat(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, kBorder);
7315 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
7316 }
7317
7318 // Test GL_TEXTURE_BORDER_COLOR parameter with sRGB formats.
TEST_P(TextureBorderClampTest,TextureBorderClampSrgb)7319 TEST_P(TextureBorderClampTest, TextureBorderClampSrgb)
7320 {
7321 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7322 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB"));
7323
7324 // AMD D3D9 drivers always sample sRGB formats with (0, 0, 0, 0) border color, won't fix.
7325 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
7326
7327 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
7328
7329 setUpProgram();
7330
7331 testFormat(GL_SRGB_EXT, GL_UNSIGNED_BYTE, kBorder);
7332 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
7333
7334 testFormat(GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, kBorder);
7335 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
7336 }
7337
7338 // Test GL_TEXTURE_BORDER_COLOR parameter with half-float formats.
TEST_P(TextureBorderClampTest,TextureBorderClampFloat16)7339 TEST_P(TextureBorderClampTest, TextureBorderClampFloat16)
7340 {
7341 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7342 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
7343
7344 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
7345
7346 setUpProgram();
7347
7348 testFormat(GL_ALPHA, GL_HALF_FLOAT_OES, kBorder);
7349 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
7350
7351 testFormat(GL_RGB, GL_HALF_FLOAT_OES, kBorder);
7352 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
7353
7354 testFormat(GL_RGBA, GL_HALF_FLOAT_OES, kBorder);
7355 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
7356
7357 testFormat(GL_LUMINANCE, GL_HALF_FLOAT_OES, kBorder);
7358 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
7359
7360 testFormat(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, kBorder);
7361 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
7362 }
7363
7364 // Test GL_TEXTURE_BORDER_COLOR parameter with float formats.
TEST_P(TextureBorderClampTest,TextureBorderClampFloat32)7365 TEST_P(TextureBorderClampTest, TextureBorderClampFloat32)
7366 {
7367 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7368 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
7369
7370 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
7371
7372 setUpProgram();
7373
7374 testFormat(GL_ALPHA, GL_FLOAT, kBorder);
7375 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
7376
7377 testFormat(GL_RGB, GL_FLOAT, kBorder);
7378 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
7379
7380 testFormat(GL_RGBA, GL_FLOAT, kBorder);
7381 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
7382
7383 testFormat(GL_LUMINANCE, GL_FLOAT, kBorder);
7384 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
7385
7386 testFormat(GL_LUMINANCE_ALPHA, GL_FLOAT, kBorder);
7387 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
7388 }
7389
7390 // Test GL_TEXTURE_BORDER_COLOR parameter with red and red-green formats.
TEST_P(TextureBorderClampTest,TextureBorderClampRG)7391 TEST_P(TextureBorderClampTest, TextureBorderClampRG)
7392 {
7393 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7394 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
7395
7396 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
7397
7398 setUpProgram();
7399
7400 testFormat(GL_RED_EXT, GL_UNSIGNED_BYTE, kBorder);
7401 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
7402
7403 testFormat(GL_RG_EXT, GL_UNSIGNED_BYTE, kBorder);
7404 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
7405
7406 if (IsGLExtensionEnabled("GL_OES_texture_half_float"))
7407 {
7408 testFormat(GL_RED_EXT, GL_HALF_FLOAT_OES, kBorder);
7409 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
7410
7411 testFormat(GL_RG_EXT, GL_HALF_FLOAT_OES, kBorder);
7412 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
7413 }
7414
7415 if (IsGLExtensionEnabled("GL_OES_texture_float"))
7416 {
7417 testFormat(GL_RED_EXT, GL_FLOAT, kBorder);
7418 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
7419
7420 testFormat(GL_RG_EXT, GL_FLOAT, kBorder);
7421 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
7422 }
7423 }
7424
7425 // Test GL_TEXTURE_BORDER_COLOR parameter with DXT1 formats.
TEST_P(TextureBorderClampTest,TextureBorderClampDXT1)7426 TEST_P(TextureBorderClampTest, TextureBorderClampDXT1)
7427 {
7428 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7429 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
7430
7431 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
7432
7433 setUpProgram();
7434
7435 testCompressedFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 8, kBorder);
7436 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
7437
7438 testCompressedFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, kBorder);
7439 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
7440 }
7441
7442 // Test GL_TEXTURE_BORDER_COLOR parameter with DXT1 sRGB formats.
TEST_P(TextureBorderClampTest,TextureBorderClampDXT1Srgb)7443 TEST_P(TextureBorderClampTest, TextureBorderClampDXT1Srgb)
7444 {
7445 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7446 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc_srgb"));
7447
7448 // AMD D3D9 drivers always sample sRGB formats with (0, 0, 0, 0) border color, won't fix.
7449 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
7450
7451 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
7452
7453 setUpProgram();
7454
7455 testCompressedFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 8, kBorder);
7456 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
7457
7458 testCompressedFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 8, kBorder);
7459 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
7460 }
7461
7462 class TextureBorderClampTestES3 : public TextureBorderClampTest
7463 {
7464 protected:
TextureBorderClampTestES3()7465 TextureBorderClampTestES3() : TextureBorderClampTest() {}
7466 };
7467
7468 // Test if the color set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the texture in
7469 // GL_CLAMP_TO_BORDER wrap mode (set with glSamplerParameter).
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Functional)7470 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Functional)
7471 {
7472 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7473
7474 setUpProgram();
7475
7476 uploadTexture();
7477
7478 GLSampler sampler;
7479 glBindSampler(0, sampler);
7480 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7481 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7482 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7483 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7484 glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
7485 EXPECT_GL_NO_ERROR();
7486
7487 drawQuad(mProgram, "position", 0.5f);
7488
7489 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
7490 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7491 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
7492 }
7493
7494 // Test reading back GL_TEXTURE_BORDER_COLOR by glGetSamplerParameter.
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Functional2)7495 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Functional2)
7496 {
7497 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7498
7499 glActiveTexture(GL_TEXTURE0);
7500
7501 GLSampler sampler;
7502 glBindSampler(0, sampler);
7503
7504 glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
7505
7506 GLint colorFixedPoint[4] = {0};
7507 glGetSamplerParameteriv(sampler, GL_TEXTURE_BORDER_COLOR, colorFixedPoint);
7508 constexpr GLint colorGreenFixedPoint[4] = {0, std::numeric_limits<GLint>::max(), 0,
7509 std::numeric_limits<GLint>::max()};
7510 EXPECT_EQ(colorFixedPoint[0], colorGreenFixedPoint[0]);
7511 EXPECT_EQ(colorFixedPoint[1], colorGreenFixedPoint[1]);
7512 EXPECT_EQ(colorFixedPoint[2], colorGreenFixedPoint[2]);
7513 EXPECT_EQ(colorFixedPoint[3], colorGreenFixedPoint[3]);
7514
7515 constexpr GLint colorBlueFixedPoint[4] = {0, 0, std::numeric_limits<GLint>::max(),
7516 std::numeric_limits<GLint>::max()};
7517 glSamplerParameteriv(sampler, GL_TEXTURE_BORDER_COLOR, colorBlueFixedPoint);
7518
7519 GLfloat color[4] = {0.0f};
7520 glGetSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, color);
7521 EXPECT_EQ(color[0], kFloatBlue.R);
7522 EXPECT_EQ(color[1], kFloatBlue.G);
7523 EXPECT_EQ(color[2], kFloatBlue.B);
7524 EXPECT_EQ(color[3], kFloatBlue.A);
7525
7526 constexpr GLint colorSomewhatRedInt[4] = {500000, 0, 0, std::numeric_limits<GLint>::max()};
7527 glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorSomewhatRedInt);
7528 GLint colorInt[4] = {0};
7529 glGetSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
7530 EXPECT_EQ(colorInt[0], colorSomewhatRedInt[0]);
7531 EXPECT_EQ(colorInt[1], colorSomewhatRedInt[1]);
7532 EXPECT_EQ(colorInt[2], colorSomewhatRedInt[2]);
7533 EXPECT_EQ(colorInt[3], colorSomewhatRedInt[3]);
7534
7535 constexpr GLuint colorSomewhatRedUInt[4] = {500000, 0, 0, std::numeric_limits<GLuint>::max()};
7536 glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorSomewhatRedUInt);
7537 GLuint colorUInt[4] = {0};
7538 glGetSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
7539 EXPECT_EQ(colorUInt[0], colorSomewhatRedUInt[0]);
7540 EXPECT_EQ(colorUInt[1], colorSomewhatRedUInt[1]);
7541 EXPECT_EQ(colorUInt[2], colorSomewhatRedUInt[2]);
7542 EXPECT_EQ(colorUInt[3], colorSomewhatRedUInt[3]);
7543
7544 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7545
7546 constexpr GLint colorSomewhatGreenInt[4] = {0, 500000, 0, std::numeric_limits<GLint>::max()};
7547 glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorSomewhatGreenInt);
7548 glGetTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
7549 EXPECT_EQ(colorInt[0], colorSomewhatGreenInt[0]);
7550 EXPECT_EQ(colorInt[1], colorSomewhatGreenInt[1]);
7551 EXPECT_EQ(colorInt[2], colorSomewhatGreenInt[2]);
7552 EXPECT_EQ(colorInt[3], colorSomewhatGreenInt[3]);
7553
7554 constexpr GLuint colorSomewhatGreenUInt[4] = {0, 500000, 0, std::numeric_limits<GLuint>::max()};
7555 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorSomewhatGreenUInt);
7556 glGetTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
7557 EXPECT_EQ(colorUInt[0], colorSomewhatGreenUInt[0]);
7558 EXPECT_EQ(colorUInt[1], colorSomewhatGreenUInt[1]);
7559 EXPECT_EQ(colorUInt[2], colorSomewhatGreenUInt[2]);
7560 EXPECT_EQ(colorUInt[3], colorSomewhatGreenUInt[3]);
7561 }
7562
7563 // Test GL_TEXTURE_BORDER_COLOR parameter validation at glSamplerParameter.
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Validation)7564 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Validation)
7565 {
7566 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7567
7568 glActiveTexture(GL_TEXTURE0);
7569
7570 GLSampler sampler;
7571 glBindSampler(0, sampler);
7572
7573 glSamplerParameterf(sampler, GL_TEXTURE_BORDER_COLOR, 1.0f);
7574 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7575
7576 glSamplerParameteri(sampler, GL_TEXTURE_BORDER_COLOR, std::numeric_limits<GLint>::max());
7577 EXPECT_GL_ERROR(GL_INVALID_ENUM);
7578 }
7579
7580 // Test that format-specific adjustments are applied
7581 // when the border color type does not match the texture type.
TEST_P(TextureBorderClampTestES3,TextureBorderTypeMismatch)7582 TEST_P(TextureBorderClampTestES3, TextureBorderTypeMismatch)
7583 {
7584 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7585
7586 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7587 glActiveTexture(GL_TEXTURE0);
7588 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7589 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7590 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7591 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7592
7593 GLColor32UI kBorder = {1, 2, 3, 0};
7594 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kBorder.R);
7595 ASSERT_GL_NO_ERROR();
7596
7597 setUpProgram();
7598
7599 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
7600 drawQuad(mProgram, "position", 0.5f);
7601 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7602 }
7603
7604 class TextureBorderClampIntegerTestES3 : public Texture2DTest
7605 {
7606 protected:
TextureBorderClampIntegerTestES3()7607 TextureBorderClampIntegerTestES3() : Texture2DTest(), isUnsignedIntTest(false) {}
7608
getVertexShaderSource()7609 const char *getVertexShaderSource() override
7610 {
7611 return
7612 R"(#version 300 es
7613 out vec2 texcoord;
7614 in vec4 position;
7615
7616 void main()
7617 {
7618 gl_Position = vec4(position.xy, 0.0, 1.0);
7619 // texcoords in [-0.5, 1.5]
7620 texcoord = (position.xy) + 0.5;
7621 })";
7622 }
7623
getFragmentShaderSource()7624 const char *getFragmentShaderSource() override
7625 {
7626 if (isUnsignedIntTest)
7627 {
7628 return "#version 300 es\n"
7629 "precision highp float;\n"
7630 "uniform highp usampler2D tex;\n"
7631 "in vec2 texcoord;\n"
7632 "out vec4 fragColor;\n"
7633
7634 "void main()\n"
7635 "{\n"
7636 "vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
7637 "vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
7638 "fragColor = (texture(tex, texcoord).r == 150u)"
7639 " ? green : red;\n"
7640 "}\n";
7641 }
7642 else
7643 {
7644 return "#version 300 es\n"
7645 "precision highp float;\n"
7646 "uniform highp isampler2D tex;\n"
7647 "in vec2 texcoord;\n"
7648 "out vec4 fragColor;\n"
7649
7650 "void main()\n"
7651 "{\n"
7652 "vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
7653 "vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
7654 "fragColor = (texture(tex, texcoord).r == -50)"
7655 " ? green : red;\n"
7656 "}\n";
7657 }
7658 }
7659
uploadTexture()7660 void uploadTexture()
7661 {
7662 glActiveTexture(GL_TEXTURE0);
7663 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7664 if (isUnsignedIntTest)
7665 {
7666 std::vector<GLubyte> texData(4, 100);
7667 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
7668 texData.data());
7669 }
7670 else
7671 {
7672 std::vector<GLbyte> texData(4, 100);
7673 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, 1, 1, 0, GL_RGBA_INTEGER, GL_BYTE,
7674 texData.data());
7675 }
7676 EXPECT_GL_NO_ERROR();
7677 }
7678
7679 bool isUnsignedIntTest;
7680 };
7681
7682 // Test if the integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the
7683 // integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampInteger)7684 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampInteger)
7685 {
7686 // Fails on Win10 FYI x64 Release (AMD RX 550). http://anglebug.com/3760
7687 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
7688
7689 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7690
7691 setUpProgram();
7692
7693 uploadTexture();
7694
7695 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7696 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7697 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7698 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7699
7700 constexpr GLint borderColor[4] = {-50, -50, -50, -50};
7701 glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
7702
7703 EXPECT_GL_NO_ERROR();
7704
7705 drawQuad(mProgram, "position", 0.5f);
7706
7707 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
7708 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7709 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
7710 }
7711
7712 // Test if the integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the
7713 // integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampInteger2)7714 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampInteger2)
7715 {
7716 // Fails on Win10 FYI x64 Release (AMD RX 550). http://anglebug.com/3760
7717 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
7718
7719 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7720
7721 setUpProgram();
7722
7723 uploadTexture();
7724
7725 GLSampler sampler;
7726 glBindSampler(0, sampler);
7727 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7728 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7729 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7730 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7731
7732 constexpr GLint borderColor[4] = {-50, -50, -50, -50};
7733 glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, borderColor);
7734
7735 EXPECT_GL_NO_ERROR();
7736
7737 drawQuad(mProgram, "position", 0.5f);
7738
7739 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
7740 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7741 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
7742 }
7743
7744 // Test if the unsigned integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside
7745 // of the unsigned integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIuivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampIntegerUnsigned)7746 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampIntegerUnsigned)
7747 {
7748 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7749
7750 isUnsignedIntTest = true;
7751
7752 setUpProgram();
7753
7754 uploadTexture();
7755
7756 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7757 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7758 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7759 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7760
7761 constexpr GLuint borderColor[4] = {150, 150, 150, 150};
7762 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
7763
7764 EXPECT_GL_NO_ERROR();
7765
7766 drawQuad(mProgram, "position", 0.5f);
7767
7768 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
7769 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7770 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
7771 }
7772
7773 // Test if the unsigned integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside
7774 // of the unsigned integer texture in GL_CLAMP_TO_BORDER wrap mode (set with
7775 // glSamplerParameterIuivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampIntegerUnsigned2)7776 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampIntegerUnsigned2)
7777 {
7778 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
7779
7780 isUnsignedIntTest = true;
7781
7782 setUpProgram();
7783
7784 uploadTexture();
7785
7786 GLSampler sampler;
7787 glBindSampler(0, sampler);
7788 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7789 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7790 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7791 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7792
7793 constexpr GLuint borderColor[4] = {150, 150, 150, 150};
7794 glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, borderColor);
7795
7796 EXPECT_GL_NO_ERROR();
7797
7798 drawQuad(mProgram, "position", 0.5f);
7799
7800 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
7801 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7802 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
7803 }
7804
7805 // ~GL_OES_texture_border_clamp
7806
7807 // GL_EXT_texture_mirror_clamp_to_edge
7808 class TextureMirrorClampToEdgeTest : public Texture2DTest
7809 {
7810 protected:
TextureMirrorClampToEdgeTest()7811 TextureMirrorClampToEdgeTest() : Texture2DTest() {}
7812
getVertexShaderSource()7813 const char *getVertexShaderSource() override
7814 {
7815 return R"(precision highp float;
7816 attribute vec4 position;
7817 varying vec2 texcoord;
7818
7819 void main()
7820 {
7821 gl_Position = vec4(position.xy, 0.0, 1.0);
7822 texcoord = position.xy * 2.0;
7823 })";
7824 }
7825
uploadTexture(bool isInteger,bool isSigned,GLuint sampler)7826 void uploadTexture(bool isInteger, bool isSigned, GLuint sampler)
7827 {
7828 glActiveTexture(GL_TEXTURE0);
7829 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7830 if (isInteger && isSigned)
7831 {
7832 const int8_t data[] = {0, 0, 0, -1, -1, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, -1};
7833 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, 2, 2, 0, GL_RGBA_INTEGER, GL_BYTE, data);
7834 }
7835 else if (isInteger)
7836 {
7837 const uint8_t data[] = {0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1};
7838 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
7839 data);
7840 }
7841 else
7842 {
7843 const uint8_t data[] = {0, 0, 0, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255};
7844 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7845 }
7846
7847 if (sampler != 0)
7848 {
7849 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_MIRROR_CLAMP_TO_EDGE_EXT);
7850 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_MIRROR_CLAMP_TO_EDGE_EXT);
7851 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7852 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7853 }
7854 else
7855 {
7856 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRROR_CLAMP_TO_EDGE_EXT);
7857 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRROR_CLAMP_TO_EDGE_EXT);
7858 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7859 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7860 }
7861 ASSERT_GL_NO_ERROR();
7862 }
7863
checkTextureSampling()7864 void checkTextureSampling()
7865 {
7866 auto screenX = [&](float x) { return getWindowWidth() * (x * 0.25 + 0.5); };
7867 auto screenY = [&](float y) { return getWindowHeight() * (y * 0.25 + 0.5); };
7868
7869 // +S, +T
7870 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(0.25), GLColor::black);
7871 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(0.25), GLColor::red);
7872 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(0.25), GLColor::red);
7873 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(0.75), GLColor::green);
7874 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(1.50), GLColor::green);
7875 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(0.75), GLColor::blue);
7876 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(0.75), GLColor::blue);
7877 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(1.50), GLColor::blue);
7878 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(1.50), GLColor::blue);
7879
7880 // -S, +T
7881 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(0.25), GLColor::black);
7882 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(0.25), GLColor::red);
7883 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(0.25), GLColor::red);
7884 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(0.75), GLColor::green);
7885 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(1.50), GLColor::green);
7886 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(0.75), GLColor::blue);
7887 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(0.75), GLColor::blue);
7888 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(1.50), GLColor::blue);
7889 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(1.50), GLColor::blue);
7890
7891 // +S, -T
7892 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-0.25), GLColor::black);
7893 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-0.25), GLColor::red);
7894 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-0.25), GLColor::red);
7895 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-0.75), GLColor::green);
7896 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-1.50), GLColor::green);
7897 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-0.75), GLColor::blue);
7898 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-0.75), GLColor::blue);
7899 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-1.50), GLColor::blue);
7900 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-1.50), GLColor::blue);
7901
7902 // -S, -T
7903 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-0.25), GLColor::black);
7904 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-0.25), GLColor::red);
7905 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-0.25), GLColor::red);
7906 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-0.75), GLColor::green);
7907 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-1.50), GLColor::green);
7908 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-0.75), GLColor::blue);
7909 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-0.75), GLColor::blue);
7910 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-1.50), GLColor::blue);
7911 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-1.50), GLColor::blue);
7912 }
7913 };
7914
7915 // Test that the texture is correctly mirrored in negative directions
7916 // and clamped to edge pixels outside of the normalized range.
TEST_P(TextureMirrorClampToEdgeTest,TexParameter)7917 TEST_P(TextureMirrorClampToEdgeTest, TexParameter)
7918 {
7919 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
7920
7921 setUpProgram();
7922 uploadTexture(false, false, 0);
7923 drawQuad(mProgram, "position", 0.5f);
7924 ASSERT_GL_NO_ERROR();
7925
7926 checkTextureSampling();
7927 }
7928
7929 class TextureMirrorClampToEdgeTestES3 : public TextureMirrorClampToEdgeTest
7930 {
7931 protected:
TextureMirrorClampToEdgeTestES3()7932 TextureMirrorClampToEdgeTestES3() : TextureMirrorClampToEdgeTest() {}
7933 };
7934
7935 // Test that the texture is correctly mirrored in negative directions and clamped
7936 // to edge pixels outside of the normalized range with mode set via glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeTestES3,SamplerParameter)7937 TEST_P(TextureMirrorClampToEdgeTestES3, SamplerParameter)
7938 {
7939 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
7940
7941 GLSampler sampler;
7942 glBindSampler(0, sampler);
7943
7944 setUpProgram();
7945 uploadTexture(false, false, sampler);
7946 drawQuad(mProgram, "position", 0.5f);
7947 ASSERT_GL_NO_ERROR();
7948
7949 checkTextureSampling();
7950 }
7951
7952 class TextureMirrorClampToEdgeIntegerTestES3 : public TextureMirrorClampToEdgeTestES3
7953 {
7954 protected:
TextureMirrorClampToEdgeIntegerTestES3()7955 TextureMirrorClampToEdgeIntegerTestES3() : TextureMirrorClampToEdgeTestES3() {}
7956
getVertexShaderSource()7957 const char *getVertexShaderSource() override
7958 {
7959 return R"(#version 300 es
7960 precision highp float;
7961 in vec4 position;
7962 out vec2 texcoord;
7963
7964 void main()
7965 {
7966 gl_Position = vec4(position.xy, 0.0, 1.0);
7967 texcoord = position.xy * 2.0;
7968 })";
7969 }
7970
getFragmentShaderSource()7971 const char *getFragmentShaderSource() override
7972 {
7973 if (mIsSigned)
7974 {
7975 return R"(#version 300 es
7976 precision highp float;
7977 uniform highp isampler2D tex;
7978 in vec2 texcoord;
7979 out vec4 fragColor;
7980 void main() { fragColor = vec4(-texture(tex, texcoord)); })";
7981 }
7982 else
7983 {
7984 return R"(#version 300 es
7985 precision highp float;
7986 uniform highp usampler2D tex;
7987 in vec2 texcoord;
7988 out vec4 fragColor;
7989 void main() { fragColor = vec4(texture(tex, texcoord)); })";
7990 }
7991 }
7992
7993 bool mIsSigned = false;
7994 };
7995
7996 // Test that the texture is correctly mirrored in negative directions and clamped
7997 // to edge pixels outside of the normalized range with mode set with glTexParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,TexParameterSigned)7998 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, TexParameterSigned)
7999 {
8000 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8001
8002 mIsSigned = true;
8003 setUpProgram();
8004 uploadTexture(true, true, 0);
8005 drawQuad(mProgram, "position", 0.5f);
8006 ASSERT_GL_NO_ERROR();
8007
8008 checkTextureSampling();
8009 }
8010
8011 // Test that the texture is correctly mirrored in negative directions and clamped
8012 // to edge pixels outside of the normalized range with mode set with glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,SamplerParameterSigned)8013 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, SamplerParameterSigned)
8014 {
8015 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8016
8017 GLSampler sampler;
8018 glBindSampler(0, sampler);
8019
8020 mIsSigned = true;
8021 setUpProgram();
8022 uploadTexture(true, true, sampler);
8023 drawQuad(mProgram, "position", 0.5f);
8024 ASSERT_GL_NO_ERROR();
8025
8026 checkTextureSampling();
8027 }
8028
8029 // Test that the unsigned integer texture is correctly mirrored in negative directions and clamped
8030 // to edge pixels outside of the normalized range with mode set with glTexParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,TexParameterUnsigned)8031 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, TexParameterUnsigned)
8032 {
8033 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8034
8035 setUpProgram();
8036 uploadTexture(true, false, 0);
8037 drawQuad(mProgram, "position", 0.5f);
8038 ASSERT_GL_NO_ERROR();
8039
8040 checkTextureSampling();
8041 }
8042
8043 // Test that the unsigned integer texture is correctly mirrored in negative directions and clamped
8044 // to edge pixels outside of the normalized range with mode set with glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,SamplerParameterUnsigned)8045 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, SamplerParameterUnsigned)
8046 {
8047 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8048
8049 GLSampler sampler;
8050 glBindSampler(0, sampler);
8051
8052 setUpProgram();
8053 uploadTexture(true, false, sampler);
8054 drawQuad(mProgram, "position", 0.5f);
8055 ASSERT_GL_NO_ERROR();
8056
8057 checkTextureSampling();
8058 }
8059 // ~GL_EXT_texture_mirror_clamp_to_edge
8060
8061 class TextureLimitsTest : public ANGLETest<>
8062 {
8063 protected:
8064 struct RGBA8
8065 {
8066 uint8_t R, G, B, A;
8067 };
8068
TextureLimitsTest()8069 TextureLimitsTest()
8070 : mProgram(0), mMaxVertexTextures(0), mMaxFragmentTextures(0), mMaxCombinedTextures(0)
8071 {
8072 setWindowWidth(128);
8073 setWindowHeight(128);
8074 setConfigRedBits(8);
8075 setConfigGreenBits(8);
8076 setConfigBlueBits(8);
8077 setConfigAlphaBits(8);
8078 }
8079
testSetUp()8080 void testSetUp() override
8081 {
8082 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mMaxVertexTextures);
8083 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mMaxFragmentTextures);
8084 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxCombinedTextures);
8085
8086 ASSERT_GL_NO_ERROR();
8087 }
8088
testTearDown()8089 void testTearDown() override
8090 {
8091 if (mProgram != 0)
8092 {
8093 glDeleteProgram(mProgram);
8094 mProgram = 0;
8095
8096 if (!mTextures.empty())
8097 {
8098 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), &mTextures[0]);
8099 }
8100 }
8101 }
8102
compileProgramWithTextureCounts(const std::string & vertexPrefix,GLint vertexTextureCount,GLint vertexActiveTextureCount,const std::string & fragPrefix,GLint fragmentTextureCount,GLint fragmentActiveTextureCount)8103 void compileProgramWithTextureCounts(const std::string &vertexPrefix,
8104 GLint vertexTextureCount,
8105 GLint vertexActiveTextureCount,
8106 const std::string &fragPrefix,
8107 GLint fragmentTextureCount,
8108 GLint fragmentActiveTextureCount)
8109 {
8110 std::stringstream vertexShaderStr;
8111 vertexShaderStr << "attribute vec2 position;\n"
8112 << "varying vec4 color;\n"
8113 << "varying vec2 texCoord;\n";
8114
8115 for (GLint textureIndex = 0; textureIndex < vertexTextureCount; ++textureIndex)
8116 {
8117 vertexShaderStr << "uniform sampler2D " << vertexPrefix << textureIndex << ";\n";
8118 }
8119
8120 vertexShaderStr << "void main() {\n"
8121 << " gl_Position = vec4(position, 0, 1);\n"
8122 << " texCoord = (position * 0.5) + 0.5;\n"
8123 << " color = vec4(0);\n";
8124
8125 for (GLint textureIndex = 0; textureIndex < vertexActiveTextureCount; ++textureIndex)
8126 {
8127 vertexShaderStr << " color += texture2D(" << vertexPrefix << textureIndex
8128 << ", texCoord);\n";
8129 }
8130
8131 vertexShaderStr << "}";
8132
8133 std::stringstream fragmentShaderStr;
8134 fragmentShaderStr << "varying mediump vec4 color;\n"
8135 << "varying mediump vec2 texCoord;\n";
8136
8137 for (GLint textureIndex = 0; textureIndex < fragmentTextureCount; ++textureIndex)
8138 {
8139 fragmentShaderStr << "uniform sampler2D " << fragPrefix << textureIndex << ";\n";
8140 }
8141
8142 fragmentShaderStr << "void main() {\n"
8143 << " gl_FragColor = color;\n";
8144
8145 for (GLint textureIndex = 0; textureIndex < fragmentActiveTextureCount; ++textureIndex)
8146 {
8147 fragmentShaderStr << " gl_FragColor += texture2D(" << fragPrefix << textureIndex
8148 << ", texCoord);\n";
8149 }
8150
8151 fragmentShaderStr << "}";
8152
8153 const std::string &vertexShaderSource = vertexShaderStr.str();
8154 const std::string &fragmentShaderSource = fragmentShaderStr.str();
8155
8156 mProgram = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
8157 }
8158
getPixel(GLint texIndex)8159 RGBA8 getPixel(GLint texIndex)
8160 {
8161 RGBA8 pixel = {static_cast<uint8_t>(texIndex & 0x7u), static_cast<uint8_t>(texIndex >> 3),
8162 0, 255u};
8163 return pixel;
8164 }
8165
initTextures(GLint tex2DCount,GLint texCubeCount)8166 void initTextures(GLint tex2DCount, GLint texCubeCount)
8167 {
8168 GLint totalCount = tex2DCount + texCubeCount;
8169 mTextures.assign(totalCount, 0);
8170 glGenTextures(totalCount, &mTextures[0]);
8171 ASSERT_GL_NO_ERROR();
8172
8173 std::vector<RGBA8> texData(16 * 16);
8174
8175 GLint texIndex = 0;
8176 for (; texIndex < tex2DCount; ++texIndex)
8177 {
8178 texData.assign(texData.size(), getPixel(texIndex));
8179 glActiveTexture(GL_TEXTURE0 + texIndex);
8180 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
8181 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8182 &texData[0]);
8183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
8186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
8187 }
8188
8189 ASSERT_GL_NO_ERROR();
8190
8191 for (; texIndex < texCubeCount; ++texIndex)
8192 {
8193 texData.assign(texData.size(), getPixel(texIndex));
8194 glActiveTexture(GL_TEXTURE0 + texIndex);
8195 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[texIndex]);
8196 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
8197 GL_UNSIGNED_BYTE, &texData[0]);
8198 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
8199 GL_UNSIGNED_BYTE, &texData[0]);
8200 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
8201 GL_UNSIGNED_BYTE, &texData[0]);
8202 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
8203 GL_UNSIGNED_BYTE, &texData[0]);
8204 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
8205 GL_UNSIGNED_BYTE, &texData[0]);
8206 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
8207 GL_UNSIGNED_BYTE, &texData[0]);
8208 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8209 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8210 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
8211 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
8212 }
8213
8214 ASSERT_GL_NO_ERROR();
8215 }
8216
testWithTextures(GLint vertexTextureCount,const std::string & vertexTexturePrefix,GLint fragmentTextureCount,const std::string & fragmentTexturePrefix)8217 void testWithTextures(GLint vertexTextureCount,
8218 const std::string &vertexTexturePrefix,
8219 GLint fragmentTextureCount,
8220 const std::string &fragmentTexturePrefix)
8221 {
8222 // Generate textures
8223 initTextures(vertexTextureCount + fragmentTextureCount, 0);
8224
8225 glUseProgram(mProgram);
8226 RGBA8 expectedSum = {0};
8227 for (GLint texIndex = 0; texIndex < vertexTextureCount; ++texIndex)
8228 {
8229 std::stringstream uniformNameStr;
8230 uniformNameStr << vertexTexturePrefix << texIndex;
8231 const std::string &uniformName = uniformNameStr.str();
8232 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
8233 ASSERT_NE(-1, location);
8234
8235 glUniform1i(location, texIndex);
8236 RGBA8 contribution = getPixel(texIndex);
8237 expectedSum.R += contribution.R;
8238 expectedSum.G += contribution.G;
8239 }
8240
8241 for (GLint texIndex = 0; texIndex < fragmentTextureCount; ++texIndex)
8242 {
8243 std::stringstream uniformNameStr;
8244 uniformNameStr << fragmentTexturePrefix << texIndex;
8245 const std::string &uniformName = uniformNameStr.str();
8246 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
8247 ASSERT_NE(-1, location);
8248
8249 glUniform1i(location, texIndex + vertexTextureCount);
8250 RGBA8 contribution = getPixel(texIndex + vertexTextureCount);
8251 expectedSum.R += contribution.R;
8252 expectedSum.G += contribution.G;
8253 }
8254
8255 ASSERT_GE(256u, expectedSum.G);
8256
8257 drawQuad(mProgram, "position", 0.5f);
8258 ASSERT_GL_NO_ERROR();
8259 EXPECT_PIXEL_NEAR(0, 0, expectedSum.R, expectedSum.G, 0, 255, 1);
8260 }
8261
8262 GLuint mProgram;
8263 std::vector<GLuint> mTextures;
8264 GLint mMaxVertexTextures;
8265 GLint mMaxFragmentTextures;
8266 GLint mMaxCombinedTextures;
8267 };
8268
8269 // Test rendering with the maximum vertex texture units.
TEST_P(TextureLimitsTest,MaxVertexTextures)8270 TEST_P(TextureLimitsTest, MaxVertexTextures)
8271 {
8272 compileProgramWithTextureCounts("tex", mMaxVertexTextures, mMaxVertexTextures, "tex", 0, 0);
8273 ASSERT_NE(0u, mProgram);
8274 ASSERT_GL_NO_ERROR();
8275
8276 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
8277 }
8278
8279 // Test rendering with the maximum fragment texture units.
TEST_P(TextureLimitsTest,MaxFragmentTextures)8280 TEST_P(TextureLimitsTest, MaxFragmentTextures)
8281 {
8282 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures, mMaxFragmentTextures);
8283 ASSERT_NE(0u, mProgram);
8284 ASSERT_GL_NO_ERROR();
8285
8286 testWithTextures(mMaxFragmentTextures, "tex", 0, "tex");
8287 }
8288
8289 // Test rendering with maximum combined texture units.
TEST_P(TextureLimitsTest,MaxCombinedTextures)8290 TEST_P(TextureLimitsTest, MaxCombinedTextures)
8291 {
8292 GLint vertexTextures = mMaxVertexTextures;
8293
8294 if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
8295 {
8296 vertexTextures = mMaxCombinedTextures - mMaxFragmentTextures;
8297 }
8298
8299 compileProgramWithTextureCounts("vtex", vertexTextures, vertexTextures, "ftex",
8300 mMaxFragmentTextures, mMaxFragmentTextures);
8301 ASSERT_NE(0u, mProgram);
8302 ASSERT_GL_NO_ERROR();
8303
8304 testWithTextures(vertexTextures, "vtex", mMaxFragmentTextures, "ftex");
8305 }
8306
8307 // Negative test for exceeding the number of vertex textures
TEST_P(TextureLimitsTest,ExcessiveVertexTextures)8308 TEST_P(TextureLimitsTest, ExcessiveVertexTextures)
8309 {
8310 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 1, mMaxVertexTextures + 1, "tex", 0,
8311 0);
8312 ASSERT_EQ(0u, mProgram);
8313 }
8314
8315 // Negative test for exceeding the number of fragment textures
TEST_P(TextureLimitsTest,ExcessiveFragmentTextures)8316 TEST_P(TextureLimitsTest, ExcessiveFragmentTextures)
8317 {
8318 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 1,
8319 mMaxFragmentTextures + 1);
8320 ASSERT_EQ(0u, mProgram);
8321 }
8322
8323 // Test active vertex textures under the limit, but excessive textures specified.
TEST_P(TextureLimitsTest,MaxActiveVertexTextures)8324 TEST_P(TextureLimitsTest, MaxActiveVertexTextures)
8325 {
8326 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 4, mMaxVertexTextures, "tex", 0, 0);
8327 ASSERT_NE(0u, mProgram);
8328 ASSERT_GL_NO_ERROR();
8329
8330 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
8331 }
8332
8333 // Test active fragment textures under the limit, but excessive textures specified.
TEST_P(TextureLimitsTest,MaxActiveFragmentTextures)8334 TEST_P(TextureLimitsTest, MaxActiveFragmentTextures)
8335 {
8336 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 4,
8337 mMaxFragmentTextures);
8338 ASSERT_NE(0u, mProgram);
8339 ASSERT_GL_NO_ERROR();
8340
8341 testWithTextures(0, "tex", mMaxFragmentTextures, "tex");
8342 }
8343
8344 // Negative test for pointing two sampler uniforms of different types to the same texture.
8345 // GLES 2.0.25 section 2.10.4 page 39.
TEST_P(TextureLimitsTest,TextureTypeConflict)8346 TEST_P(TextureLimitsTest, TextureTypeConflict)
8347 {
8348 constexpr char kVS[] =
8349 "attribute vec2 position;\n"
8350 "varying float color;\n"
8351 "uniform sampler2D tex2D;\n"
8352 "uniform samplerCube texCube;\n"
8353 "void main() {\n"
8354 " gl_Position = vec4(position, 0, 1);\n"
8355 " vec2 texCoord = (position * 0.5) + 0.5;\n"
8356 " color = texture2D(tex2D, texCoord).x;\n"
8357 " color += textureCube(texCube, vec3(texCoord, 0)).x;\n"
8358 "}";
8359 constexpr char kFS[] =
8360 "varying mediump float color;\n"
8361 "void main() {\n"
8362 " gl_FragColor = vec4(color, 0, 0, 1);\n"
8363 "}";
8364
8365 mProgram = CompileProgram(kVS, kFS);
8366 ASSERT_NE(0u, mProgram);
8367
8368 initTextures(1, 0);
8369
8370 glUseProgram(mProgram);
8371 GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
8372 ASSERT_NE(-1, tex2DLocation);
8373 GLint texCubeLocation = glGetUniformLocation(mProgram, "texCube");
8374 ASSERT_NE(-1, texCubeLocation);
8375
8376 glUniform1i(tex2DLocation, 0);
8377 glUniform1i(texCubeLocation, 0);
8378 ASSERT_GL_NO_ERROR();
8379
8380 drawQuad(mProgram, "position", 0.5f);
8381 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8382 }
8383
8384 class Texture2DNorm16TestES3 : public Texture2DTestES3
8385 {
8386 protected:
Texture2DNorm16TestES3()8387 Texture2DNorm16TestES3() : Texture2DTestES3(), mTextures{0, 0, 0}, mFBO(0), mRenderbuffer(0) {}
8388
testSetUp()8389 void testSetUp() override
8390 {
8391 Texture2DTestES3::testSetUp();
8392
8393 glActiveTexture(GL_TEXTURE0);
8394 glGenTextures(3, mTextures);
8395 glGenFramebuffers(1, &mFBO);
8396 glGenRenderbuffers(1, &mRenderbuffer);
8397
8398 for (size_t textureIndex = 0; textureIndex < 3; textureIndex++)
8399 {
8400 glBindTexture(GL_TEXTURE_2D, mTextures[textureIndex]);
8401 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8402 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8403 }
8404
8405 glBindTexture(GL_TEXTURE_2D, 0);
8406
8407 ASSERT_GL_NO_ERROR();
8408 }
8409
testTearDown()8410 void testTearDown() override
8411 {
8412 glDeleteTextures(3, mTextures);
8413 glDeleteFramebuffers(1, &mFBO);
8414 glDeleteRenderbuffers(1, &mRenderbuffer);
8415
8416 Texture2DTestES3::testTearDown();
8417 }
8418
testNorm16Texture(GLint internalformat,GLenum format,GLenum type)8419 void testNorm16Texture(GLint internalformat, GLenum format, GLenum type)
8420 {
8421 // TODO(http://anglebug.com/4089) Fails on Win Intel OpenGL driver
8422 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
8423 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
8424
8425 GLushort pixelValue = (type == GL_SHORT) ? 0x7FFF : 0x6A35;
8426 GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
8427
8428 setUpProgram();
8429
8430 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
8431 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
8432 0);
8433
8434 for (int i = 0; i < 2; ++i)
8435 {
8436 bool isSubImage = i == 1;
8437 SCOPED_TRACE("is subimage:" + std::to_string(isSubImage));
8438 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
8439 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16_EXT, 1, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT,
8440 nullptr);
8441
8442 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
8443 if (isSubImage)
8444 {
8445 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, nullptr);
8446 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, format, type, imageData);
8447 }
8448 else
8449 {
8450 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
8451 }
8452 EXPECT_GL_NO_ERROR();
8453
8454 drawQuad(mProgram, "position", 0.5f);
8455
8456 GLubyte expectedValue =
8457 (type == GL_SHORT) ? 0xFF : static_cast<GLubyte>(pixelValue >> 8);
8458
8459 EXPECT_PIXEL_COLOR_EQ(0, 0,
8460 SliceFormatColor(format, GLColor(expectedValue, expectedValue,
8461 expectedValue, expectedValue)));
8462 }
8463 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8464
8465 ASSERT_GL_NO_ERROR();
8466 }
8467
testReadPixelsRGBAWithRangeAndPixelStoreMode(GLuint x,GLuint y,GLuint width,GLuint height,GLint packRowLength,GLint packAlignment,GLint packSkipPixels,GLint packSkipRows,GLenum type,GLColor16UI color)8468 void testReadPixelsRGBAWithRangeAndPixelStoreMode(GLuint x,
8469 GLuint y,
8470 GLuint width,
8471 GLuint height,
8472 GLint packRowLength,
8473 GLint packAlignment,
8474 GLint packSkipPixels,
8475 GLint packSkipRows,
8476 GLenum type,
8477 GLColor16UI color)
8478 {
8479 // PACK modes debugging
8480 GLint s = 2; // single component size in bytes, UNSIGNED_SHORT -> 2 in our case
8481 GLint n = 4; // 4 components per pixel, stands for GL_RGBA
8482
8483 GLuint l = packRowLength == 0 ? width : packRowLength;
8484 const GLint &a = packAlignment;
8485
8486 // According to
8487 // https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml
8488 GLint k = (s >= a) ? n * l : a / s * (1 + (s * n * l - 1) / a);
8489 std::size_t componentCount = n * packSkipPixels + k * (packSkipRows + height);
8490 if (static_cast<GLuint>(packRowLength) < width)
8491 {
8492 componentCount += width * n * s - k;
8493 }
8494
8495 // Populate the pixels array with random dirty value
8496 constexpr GLushort kDirtyValue = 0x1234;
8497 std::vector<GLushort> pixels(componentCount, kDirtyValue);
8498 glReadPixels(x, y, width, height, GL_RGBA, type, pixels.data());
8499
8500 EXPECT_GL_NO_ERROR();
8501
8502 GLushort *pixelRowStart = pixels.data();
8503 pixelRowStart += n * packSkipPixels + k * packSkipRows;
8504
8505 std::vector<bool> modifiedPixels(componentCount, false);
8506
8507 char errorInfo[200];
8508
8509 for (GLuint row = 0; row < height; ++row)
8510 {
8511 GLushort *curPixel = pixelRowStart;
8512 for (GLuint col = 0, len = (row == height - 1) ? width : std::min(l, width); col < len;
8513 ++col)
8514 {
8515 snprintf(errorInfo, sizeof(errorInfo),
8516 "extent: {%u, %u}, coord: (%u, %u), rowLength: %d, alignment: %d, "
8517 "skipPixels: %d, skipRows: %d\n",
8518 width, height, col, row, packRowLength, packAlignment, packSkipPixels,
8519 packSkipRows);
8520 EXPECT_EQ(color.R, curPixel[0]) << errorInfo;
8521 EXPECT_EQ(color.G, curPixel[1]) << errorInfo;
8522 EXPECT_EQ(color.B, curPixel[2]) << errorInfo;
8523 EXPECT_EQ(color.A, curPixel[3]) << errorInfo;
8524
8525 std::ptrdiff_t diff = curPixel - pixels.data();
8526 modifiedPixels[diff + 0] = true;
8527 modifiedPixels[diff + 1] = true;
8528 modifiedPixels[diff + 2] = true;
8529 modifiedPixels[diff + 3] = true;
8530
8531 curPixel += n;
8532 }
8533 pixelRowStart += k;
8534 }
8535
8536 for (std::size_t i = 0; i < modifiedPixels.size(); ++i)
8537 {
8538 if (!modifiedPixels[i])
8539 {
8540 EXPECT_EQ(pixels[i], kDirtyValue);
8541 }
8542 }
8543 }
8544
testNorm16RenderAndReadPixels(GLint internalformat,GLenum format,GLenum type)8545 void testNorm16RenderAndReadPixels(GLint internalformat, GLenum format, GLenum type)
8546 {
8547 // TODO(http://anglebug.com/4089) Fails on Win Intel OpenGL driver
8548 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
8549 // TODO(http://anglebug.com/4245) Fails on Win AMD OpenGL driver
8550 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
8551 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
8552
8553 GLushort pixelValue = 0x6A35;
8554 GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
8555 GLColor16UI color = SliceFormatColor16UI(
8556 format, GLColor16UI(pixelValue, pixelValue, pixelValue, pixelValue));
8557 // Size of drawing viewport
8558 constexpr GLint width = 8, height = 8;
8559
8560 setUpProgram();
8561
8562 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
8563 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, type, nullptr);
8564
8565 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
8566 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
8567 0);
8568
8569 glBindTexture(GL_TEXTURE_2D, mTextures[2]);
8570 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
8571 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8572 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8573
8574 EXPECT_GL_NO_ERROR();
8575
8576 drawQuad(mProgram, "position", 0.5f);
8577
8578 // ReadPixels against different width, height, pixel pack mode combinations to test
8579 // workaround of pixels rearrangement
8580
8581 // {x, y, width, height}
8582 std::vector<std::array<GLint, 4>> areas = {
8583 {0, 0, 1, 1}, {0, 0, 1, 2}, {0, 0, 2, 1}, {0, 0, 2, 2},
8584 {0, 0, 3, 2}, {0, 0, 3, 3}, {0, 0, 4, 3}, {0, 0, 4, 4},
8585
8586 {1, 3, 3, 2}, {1, 3, 3, 3}, {3, 2, 4, 3}, {3, 2, 4, 4},
8587
8588 {0, 0, 5, 6}, {2, 1, 5, 6}, {0, 0, 6, 1}, {0, 0, 7, 1},
8589 {0, 0, 7, 3}, {0, 0, 7, 8}, {1, 0, 7, 8}, {0, 0, 8, 8},
8590 };
8591
8592 // Put default settings at the last
8593 std::vector<GLint> paramsPackRowLength = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0};
8594 std::vector<GLint> paramsPackAlignment = {1, 2, 8, 4};
8595 std::vector<std::array<GLint, 2>> paramsPackSkipPixelsAndRows = {{1, 0}, {0, 1}, {1, 1},
8596 {3, 1}, {20, 20}, {0, 0}};
8597
8598 // Restore pixel pack modes later
8599 GLint restorePackAlignment;
8600 glGetIntegerv(GL_PACK_ALIGNMENT, &restorePackAlignment);
8601 GLint restorePackRowLength;
8602 glGetIntegerv(GL_PACK_ROW_LENGTH, &restorePackRowLength);
8603 GLint restorePackSkipPixels;
8604 glGetIntegerv(GL_PACK_SKIP_PIXELS, &restorePackSkipPixels);
8605 GLint restorePackSkipRows;
8606 glGetIntegerv(GL_PACK_SKIP_ROWS, &restorePackSkipRows);
8607
8608 // Variable symbols are based on:
8609 // https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml
8610 for (const auto &skipped : paramsPackSkipPixelsAndRows)
8611 {
8612 glPixelStorei(GL_PACK_SKIP_PIXELS, skipped[0]);
8613 glPixelStorei(GL_PACK_SKIP_ROWS, skipped[1]);
8614 for (GLint a : paramsPackAlignment)
8615 {
8616 glPixelStorei(GL_PACK_ALIGNMENT, a);
8617 for (GLint l : paramsPackRowLength)
8618 {
8619 glPixelStorei(GL_PACK_ROW_LENGTH, l);
8620
8621 for (const auto &area : areas)
8622 {
8623 ASSERT(area[0] + area[2] <= width);
8624 ASSERT(area[1] + area[3] <= height);
8625 testReadPixelsRGBAWithRangeAndPixelStoreMode(area[0], area[1], area[2],
8626 area[3], l, a, skipped[0],
8627 skipped[1], type, color);
8628 }
8629 }
8630 }
8631 }
8632
8633 glPixelStorei(GL_PACK_ALIGNMENT, restorePackAlignment);
8634 glPixelStorei(GL_PACK_ROW_LENGTH, restorePackRowLength);
8635 glPixelStorei(GL_PACK_SKIP_PIXELS, restorePackSkipPixels);
8636 glPixelStorei(GL_PACK_SKIP_ROWS, restorePackSkipRows);
8637
8638 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
8639 glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
8640 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
8641 mRenderbuffer);
8642 glBindRenderbuffer(GL_RENDERBUFFER, 0);
8643 EXPECT_GL_NO_ERROR();
8644
8645 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
8646 glClear(GL_COLOR_BUFFER_BIT);
8647
8648 EXPECT_PIXEL_16UI_COLOR(
8649 0, 0, SliceFormatColor16UI(format, GLColor16UI(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)));
8650
8651 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
8652 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
8653
8654 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
8655 0);
8656 EXPECT_PIXEL_16UI_COLOR(
8657 0, 0, SliceFormatColor16UI(format, GLColor16UI(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)));
8658
8659 ASSERT_GL_NO_ERROR();
8660
8661 glBindFramebuffer(GL_FRAMEBUFFER, 0);
8662 }
8663
8664 GLuint mTextures[3];
8665 GLuint mFBO;
8666 GLuint mRenderbuffer;
8667 };
8668
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16TextureTest)8669 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16TextureTest)
8670 {
8671 testNorm16Texture(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
8672 }
8673
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16SNORMTextureTest)8674 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16SNORMTextureTest)
8675 {
8676 testNorm16Texture(GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
8677 }
8678
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16TextureTest)8679 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16TextureTest)
8680 {
8681 testNorm16Texture(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
8682 }
8683
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16SNORMTextureTest)8684 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16SNORMTextureTest)
8685 {
8686 testNorm16Texture(GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
8687 }
8688
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGB16TextureTest)8689 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGB16TextureTest)
8690 {
8691 // (http://anglebug.com/4215) Driver bug on some Qualcomm Adreno gpu
8692 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
8693
8694 testNorm16Texture(GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
8695 }
8696
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGB16SNORMTextureTest)8697 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGB16SNORMTextureTest)
8698 {
8699 // (http://anglebug.com/4215) Driver bug on some Qualcomm Adreno gpu
8700 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
8701
8702 testNorm16Texture(GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
8703 }
8704
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16TextureTest)8705 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16TextureTest)
8706 {
8707 testNorm16Texture(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
8708 }
8709
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16SNORMTextureTest)8710 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16SNORMTextureTest)
8711 {
8712 testNorm16Texture(GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
8713 }
8714
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16RenderTest)8715 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16RenderTest)
8716 {
8717 // http://anglebug.com/5153
8718 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
8719
8720 testNorm16RenderAndReadPixels(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
8721 }
8722
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16RenderTest)8723 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16RenderTest)
8724 {
8725 // http://anglebug.com/5153
8726 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
8727
8728 testNorm16RenderAndReadPixels(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
8729 }
8730
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16RenderTest)8731 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16RenderTest)
8732 {
8733 // http://anglebug.com/5153
8734 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
8735
8736 testNorm16RenderAndReadPixels(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
8737 }
8738
8739 class Texture2DRGTest : public Texture2DTest
8740 {
8741 protected:
Texture2DRGTest()8742 Texture2DRGTest()
8743 : Texture2DTest(), mRenderableTexture(0), mTestTexture(0), mFBO(0), mRenderbuffer(0)
8744 {}
8745
testSetUp()8746 void testSetUp() override
8747 {
8748 Texture2DTest::testSetUp();
8749
8750 glActiveTexture(GL_TEXTURE0);
8751 glGenTextures(1, &mRenderableTexture);
8752 glGenTextures(1, &mTestTexture);
8753 glGenFramebuffers(1, &mFBO);
8754 glGenRenderbuffers(1, &mRenderbuffer);
8755
8756 glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
8757 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8758 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8759 glBindTexture(GL_TEXTURE_2D, mTestTexture);
8760 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8761 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8762
8763 glBindTexture(GL_TEXTURE_2D, 0);
8764
8765 setUpProgram();
8766 glUseProgram(mProgram);
8767 glUniform1i(mTexture2DUniformLocation, 0);
8768
8769 ASSERT_GL_NO_ERROR();
8770 }
8771
testTearDown()8772 void testTearDown() override
8773 {
8774 glDeleteTextures(1, &mRenderableTexture);
8775 glDeleteTextures(1, &mTestTexture);
8776 glDeleteFramebuffers(1, &mFBO);
8777 glDeleteRenderbuffers(1, &mRenderbuffer);
8778
8779 Texture2DTest::testTearDown();
8780 }
8781
setupFormatTextures(GLenum internalformat,GLenum format,GLenum type,GLvoid * imageData)8782 void setupFormatTextures(GLenum internalformat, GLenum format, GLenum type, GLvoid *imageData)
8783 {
8784 glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
8785 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
8786
8787 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
8788 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
8789 mRenderableTexture, 0);
8790
8791 glBindTexture(GL_TEXTURE_2D, mTestTexture);
8792 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
8793
8794 EXPECT_GL_NO_ERROR();
8795 }
8796
testRGTexture(GLColor expectedColor)8797 void testRGTexture(GLColor expectedColor)
8798 {
8799 drawQuad(mProgram, "position", 0.5f);
8800
8801 EXPECT_GL_NO_ERROR();
8802 EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, kPixelTolerance);
8803 }
8804
testRGRender(GLenum internalformat,GLenum format)8805 void testRGRender(GLenum internalformat, GLenum format)
8806 {
8807 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
8808 glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
8809 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
8810 mRenderbuffer);
8811 glBindRenderbuffer(GL_RENDERBUFFER, 0);
8812 EXPECT_GL_NO_ERROR();
8813
8814 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
8815 glClear(GL_COLOR_BUFFER_BIT);
8816
8817 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
8818
8819 ASSERT_GL_NO_ERROR();
8820 EXPECT_PIXEL_COLOR_EQ(0, 0, SliceFormatColor(format, GLColor(255u, 255u, 255u, 255u)));
8821 }
8822
8823 GLuint mRenderableTexture;
8824 GLuint mTestTexture;
8825 GLuint mFBO;
8826 GLuint mRenderbuffer;
8827 };
8828
8829 // Test unorm texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGUNormTest)8830 TEST_P(Texture2DRGTest, TextureRGUNormTest)
8831 {
8832 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
8833 // This workaround causes a GL error on Windows AMD, which is likely a driver bug.
8834 // The workaround is not intended to be enabled in this configuration so skip it.
8835 ANGLE_SKIP_TEST_IF(
8836 getEGLWindow()->isFeatureEnabled(Feature::EmulateCopyTexImage2DFromRenderbuffers) &&
8837 IsWindows() && IsAMD());
8838
8839 GLubyte pixelValue = 0xab;
8840 GLubyte imageData[] = {pixelValue, pixelValue};
8841
8842 setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_UNSIGNED_BYTE, imageData);
8843 testRGTexture(
8844 SliceFormatColor(GL_RED_EXT, GLColor(pixelValue, pixelValue, pixelValue, pixelValue)));
8845 testRGRender(GL_R8_EXT, GL_RED_EXT);
8846
8847 setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_UNSIGNED_BYTE, imageData);
8848 testRGTexture(
8849 SliceFormatColor(GL_RG_EXT, GLColor(pixelValue, pixelValue, pixelValue, pixelValue)));
8850 testRGRender(GL_RG8_EXT, GL_RG_EXT);
8851 }
8852
8853 // Test float texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGFloatTest)8854 TEST_P(Texture2DRGTest, TextureRGFloatTest)
8855 {
8856 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
8857 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
8858
8859 GLfloat pixelValue = 0.54321;
8860 GLfloat imageData[] = {pixelValue, pixelValue};
8861
8862 GLubyte expectedValue = static_cast<GLubyte>(pixelValue * 255.0f);
8863 GLColor expectedColor = GLColor(expectedValue, expectedValue, expectedValue, expectedValue);
8864
8865 setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_FLOAT, imageData);
8866 testRGTexture(SliceFormatColor(GL_RED_EXT, expectedColor));
8867
8868 setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_FLOAT, imageData);
8869 testRGTexture(SliceFormatColor(GL_RG_EXT, expectedColor));
8870 }
8871
8872 // Test half-float texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGHalfFloatTest)8873 TEST_P(Texture2DRGTest, TextureRGHalfFloatTest)
8874 {
8875 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
8876 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
8877
8878 GLfloat pixelValueFloat = 0.543f;
8879 GLhalf pixelValue = 0x3858;
8880 GLhalf imageData[] = {pixelValue, pixelValue};
8881
8882 GLubyte expectedValue = static_cast<GLubyte>(pixelValueFloat * 255.0f);
8883 GLColor expectedColor = GLColor(expectedValue, expectedValue, expectedValue, expectedValue);
8884
8885 setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES, imageData);
8886 testRGTexture(SliceFormatColor(GL_RED_EXT, expectedColor));
8887
8888 setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_HALF_FLOAT_OES, imageData);
8889 testRGTexture(SliceFormatColor(GL_RG_EXT, expectedColor));
8890 }
8891
8892 class Texture2DFloatTest : public Texture2DTest
8893 {
8894 protected:
Texture2DFloatTest()8895 Texture2DFloatTest()
8896 : Texture2DTest(), mRenderableTexture(0), mTestTexture(0), mFBO(0), mRenderbuffer(0)
8897 {}
8898
testSetUp()8899 void testSetUp() override
8900 {
8901 Texture2DTest::testSetUp();
8902
8903 glActiveTexture(GL_TEXTURE0);
8904 glGenTextures(1, &mRenderableTexture);
8905 glGenTextures(1, &mTestTexture);
8906 glGenFramebuffers(1, &mFBO);
8907 glGenRenderbuffers(1, &mRenderbuffer);
8908
8909 setUpProgram();
8910 glUseProgram(mProgram);
8911 glUniform1i(mTexture2DUniformLocation, 0);
8912
8913 glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
8914 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
8915
8916 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
8917 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
8918 mRenderableTexture, 0);
8919
8920 ASSERT_GL_NO_ERROR();
8921 }
8922
testTearDown()8923 void testTearDown() override
8924 {
8925 glDeleteTextures(1, &mRenderableTexture);
8926 glDeleteTextures(1, &mTestTexture);
8927 glDeleteFramebuffers(1, &mFBO);
8928 glDeleteRenderbuffers(1, &mRenderbuffer);
8929
8930 Texture2DTest::testTearDown();
8931 }
8932
testFloatTextureSample(GLenum internalFormat,GLenum format,GLenum type)8933 void testFloatTextureSample(GLenum internalFormat, GLenum format, GLenum type)
8934 {
8935 constexpr GLfloat imageDataFloat[] = {
8936 0.2f,
8937 0.3f,
8938 0.4f,
8939 0.5f,
8940 };
8941 constexpr GLhalf imageDataHalf[] = {
8942 0x3266,
8943 0x34CD,
8944 0x3666,
8945 0x3800,
8946 };
8947 GLColor expectedValue;
8948 for (int i = 0; i < 4; i++)
8949 {
8950 expectedValue[i] = static_cast<GLubyte>(imageDataFloat[i] * 255.0f);
8951 }
8952
8953 const GLvoid *imageData;
8954 switch (type)
8955 {
8956 case GL_FLOAT:
8957 imageData = imageDataFloat;
8958 break;
8959 case GL_HALF_FLOAT:
8960 case GL_HALF_FLOAT_OES:
8961 imageData = imageDataHalf;
8962 break;
8963 default:
8964 imageData = nullptr;
8965 }
8966 ASSERT(imageData != nullptr);
8967
8968 glBindTexture(GL_TEXTURE_2D, mTestTexture);
8969 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, imageData);
8970
8971 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8972 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8973
8974 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
8975 drawQuad(mProgram, "position", 0.5f);
8976
8977 EXPECT_GL_NO_ERROR();
8978 EXPECT_PIXEL_COLOR_NEAR(0, 0, SliceFormatColor(format, expectedValue), kPixelTolerance);
8979 }
8980
testFloatTextureLinear(GLenum internalFormat,GLenum format,GLenum type)8981 void testFloatTextureLinear(GLenum internalFormat, GLenum format, GLenum type)
8982 {
8983 int numComponents;
8984 switch (format)
8985 {
8986 case GL_RGBA:
8987 numComponents = 4;
8988 break;
8989 case GL_RGB:
8990 numComponents = 3;
8991 break;
8992 case GL_LUMINANCE_ALPHA:
8993 numComponents = 2;
8994 break;
8995 case GL_LUMINANCE:
8996 case GL_ALPHA:
8997 numComponents = 1;
8998 break;
8999 default:
9000 numComponents = 0;
9001 }
9002 ASSERT(numComponents > 0);
9003
9004 constexpr GLfloat pixelIntensitiesFloat[] = {0.0f, 1.0f, 0.0f, 1.0f};
9005 constexpr GLhalf pixelIntensitiesHalf[] = {0x0000, 0x3C00, 0x0000, 0x3C00};
9006
9007 GLfloat imageDataFloat[16];
9008 GLhalf imageDataHalf[16];
9009 for (int i = 0; i < 4; i++)
9010 {
9011 for (int c = 0; c < numComponents; c++)
9012 {
9013 imageDataFloat[i * numComponents + c] = pixelIntensitiesFloat[i];
9014 imageDataHalf[i * numComponents + c] = pixelIntensitiesHalf[i];
9015 }
9016 }
9017
9018 const GLvoid *imageData;
9019 switch (type)
9020 {
9021 case GL_FLOAT:
9022 imageData = imageDataFloat;
9023 break;
9024 case GL_HALF_FLOAT:
9025 case GL_HALF_FLOAT_OES:
9026 imageData = imageDataHalf;
9027 break;
9028 default:
9029 imageData = nullptr;
9030 }
9031 ASSERT(imageData != nullptr);
9032
9033 glBindTexture(GL_TEXTURE_2D, mTestTexture);
9034 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 2, 2, 0, format, type, imageData);
9035
9036 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9037 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9038
9039 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9040 drawQuad(mProgram, "position", 0.5f);
9041
9042 EXPECT_GL_NO_ERROR();
9043 // Source texture contains 2 black pixels and 2 white pixels, we sample in the center so we
9044 // should expect the final value to be gray (halfway in-between)
9045 EXPECT_PIXEL_COLOR_NEAR(0, 0, SliceFormatColor(format, GLColor(127u, 127u, 127u, 127u)),
9046 kPixelTolerance);
9047 }
9048
performFloatTextureRender(GLenum internalFormat,GLenum renderBufferFormat,GLenum format,GLenum type)9049 bool performFloatTextureRender(GLenum internalFormat,
9050 GLenum renderBufferFormat,
9051 GLenum format,
9052 GLenum type)
9053 {
9054 glBindTexture(GL_TEXTURE_2D, mTestTexture);
9055 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, nullptr);
9056 glBindTexture(GL_TEXTURE_2D, 0);
9057
9058 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
9059 glRenderbufferStorage(GL_RENDERBUFFER, renderBufferFormat, 1, 1);
9060 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
9061 mRenderbuffer);
9062 glBindRenderbuffer(GL_RENDERBUFFER, 0);
9063 EXPECT_GL_NO_ERROR();
9064
9065 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
9066 {
9067 return false;
9068 }
9069
9070 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9071
9072 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
9073 glClear(GL_COLOR_BUFFER_BIT);
9074
9075 EXPECT_GL_NO_ERROR();
9076 return true;
9077 }
9078
9079 GLuint mRenderableTexture;
9080 GLuint mTestTexture;
9081 GLuint mFBO;
9082 GLuint mRenderbuffer;
9083 };
9084
9085 class Texture2DFloatTestES3 : public Texture2DFloatTest
9086 {
9087 protected:
testFloatTextureRender(GLenum internalFormat,GLenum format,GLenum type)9088 void testFloatTextureRender(GLenum internalFormat, GLenum format, GLenum type)
9089 {
9090 bool framebufferComplete =
9091 performFloatTextureRender(internalFormat, internalFormat, format, type);
9092 EXPECT_TRUE(framebufferComplete);
9093 EXPECT_PIXEL_COLOR32F_NEAR(0, 0,
9094 SliceFormatColor32F(format, GLColor32F(1.0f, 1.0f, 1.0f, 1.0f)),
9095 kPixelTolerance32F);
9096 }
9097 };
9098
9099 class Texture2DFloatTestES2 : public Texture2DFloatTest
9100 {
9101 protected:
checkFloatTextureRender(GLenum renderBufferFormat,GLenum format,GLenum type)9102 bool checkFloatTextureRender(GLenum renderBufferFormat, GLenum format, GLenum type)
9103 {
9104 bool framebufferComplete =
9105 performFloatTextureRender(format, renderBufferFormat, format, type);
9106
9107 if (!framebufferComplete)
9108 {
9109 return false;
9110 }
9111
9112 EXPECT_PIXEL_COLOR32F_NEAR(0, 0,
9113 SliceFormatColor32F(format, GLColor32F(1.0f, 1.0f, 1.0f, 1.0f)),
9114 kPixelTolerance32F);
9115 return true;
9116 }
9117 };
9118
9119 // Test texture sampling for ES3 float texture formats
TEST_P(Texture2DFloatTestES3,TextureFloatSampleBasicTest)9120 TEST_P(Texture2DFloatTestES3, TextureFloatSampleBasicTest)
9121 {
9122 testFloatTextureSample(GL_RGBA32F, GL_RGBA, GL_FLOAT);
9123 testFloatTextureSample(GL_RGB32F, GL_RGB, GL_FLOAT);
9124 }
9125
9126 // Test texture sampling for ES2 float texture formats
TEST_P(Texture2DFloatTestES2,TextureFloatSampleBasicTest)9127 TEST_P(Texture2DFloatTestES2, TextureFloatSampleBasicTest)
9128 {
9129 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
9130 testFloatTextureSample(GL_RGBA, GL_RGBA, GL_FLOAT);
9131 testFloatTextureSample(GL_RGB, GL_RGB, GL_FLOAT);
9132 }
9133
9134 // Test texture sampling for ES3 half float texture formats
TEST_P(Texture2DFloatTestES3,TextureHalfFloatSampleBasicTest)9135 TEST_P(Texture2DFloatTestES3, TextureHalfFloatSampleBasicTest)
9136 {
9137 testFloatTextureSample(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
9138 testFloatTextureSample(GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
9139 }
9140
9141 // Test texture sampling for ES2 half float texture formats
TEST_P(Texture2DFloatTestES2,TextureHalfFloatSampleBasicTest)9142 TEST_P(Texture2DFloatTestES2, TextureHalfFloatSampleBasicTest)
9143 {
9144 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
9145 testFloatTextureSample(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES);
9146 testFloatTextureSample(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES);
9147 }
9148
9149 // Test texture sampling for legacy GLES 2.0 float texture formats in ES3
TEST_P(Texture2DFloatTestES3,TextureFloatSampleLegacyTest)9150 TEST_P(Texture2DFloatTestES3, TextureFloatSampleLegacyTest)
9151 {
9152 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
9153
9154 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
9155 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_FLOAT);
9156 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
9157
9158 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
9159 {
9160 testFloatTextureSample(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT);
9161 testFloatTextureSample(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT);
9162 testFloatTextureSample(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT);
9163 }
9164 }
9165
9166 // Test texture sampling for legacy GLES 2.0 float texture formats in ES2
TEST_P(Texture2DFloatTestES2,TextureFloatSampleLegacyTest)9167 TEST_P(Texture2DFloatTestES2, TextureFloatSampleLegacyTest)
9168 {
9169 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
9170
9171 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
9172 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_FLOAT);
9173 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
9174 }
9175
9176 // Test texture sampling for legacy GLES 2.0 half float texture formats in ES3
TEST_P(Texture2DFloatTestES3,TextureHalfFloatSampleLegacyTest)9177 TEST_P(Texture2DFloatTestES3, TextureHalfFloatSampleLegacyTest)
9178 {
9179 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
9180
9181 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
9182 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
9183 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
9184
9185 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
9186 {
9187 testFloatTextureSample(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT);
9188 testFloatTextureSample(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT);
9189 testFloatTextureSample(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT);
9190 }
9191 }
9192 // Test texture sampling for legacy GLES 2.0 half float texture formats in ES2
TEST_P(Texture2DFloatTestES2,TextureHalfFloatSampleLegacyTest)9193 TEST_P(Texture2DFloatTestES2, TextureHalfFloatSampleLegacyTest)
9194 {
9195 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
9196
9197 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
9198 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
9199 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
9200 }
9201
9202 // Test linear sampling for ES3 32F formats
TEST_P(Texture2DFloatTestES3,TextureFloatLinearTest)9203 TEST_P(Texture2DFloatTestES3, TextureFloatLinearTest)
9204 {
9205 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
9206 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
9207
9208 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
9209
9210 testFloatTextureLinear(GL_RGBA32F, GL_RGBA, GL_FLOAT);
9211 testFloatTextureLinear(GL_RGB32F, GL_RGB, GL_FLOAT);
9212 }
9213 // Test linear sampling for ES2 32F formats
TEST_P(Texture2DFloatTestES2,TextureFloatLinearTest)9214 TEST_P(Texture2DFloatTestES2, TextureFloatLinearTest)
9215 {
9216 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
9217 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
9218
9219 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
9220
9221 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
9222
9223 testFloatTextureLinear(GL_RGBA, GL_RGBA, GL_FLOAT);
9224 }
9225
9226 // Test linear sampling for ES3 16F formats
TEST_P(Texture2DFloatTestES3,TextureHalfFloatLinearTest)9227 TEST_P(Texture2DFloatTestES3, TextureHalfFloatLinearTest)
9228 {
9229 // Half float formats must be linearly filterable in GLES 3.0 core
9230 testFloatTextureLinear(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
9231 testFloatTextureLinear(GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
9232 }
9233 // Test linear sampling for ES2 16F formats
TEST_P(Texture2DFloatTestES2,TextureHalfFloatLinearTest)9234 TEST_P(Texture2DFloatTestES2, TextureHalfFloatLinearTest)
9235 {
9236 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
9237 testFloatTextureLinear(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES);
9238 testFloatTextureLinear(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES);
9239 }
9240
9241 // Test linear sampling for legacy GLES 2.0 32F formats in ES3
TEST_P(Texture2DFloatTestES3,TextureFloatLinearLegacyTest)9242 TEST_P(Texture2DFloatTestES3, TextureFloatLinearLegacyTest)
9243 {
9244 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
9245 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
9246
9247 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
9248 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
9249
9250 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
9251 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_FLOAT);
9252 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
9253
9254 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
9255 {
9256 testFloatTextureLinear(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT);
9257 testFloatTextureLinear(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT);
9258 testFloatTextureLinear(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT);
9259 }
9260 }
9261 // Test linear sampling for legacy GLES 2.0 32F formats in ES2
TEST_P(Texture2DFloatTestES2,TextureFloatLinearLegacyTest)9262 TEST_P(Texture2DFloatTestES2, TextureFloatLinearLegacyTest)
9263 {
9264 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
9265 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
9266
9267 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
9268 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
9269
9270 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
9271 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_FLOAT);
9272 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
9273 }
9274
9275 // Test linear sampling for legacy GLES 2.0 16F formats in ES3
TEST_P(Texture2DFloatTestES3,TextureHalfFloatLinearLegacyTest)9276 TEST_P(Texture2DFloatTestES3, TextureHalfFloatLinearLegacyTest)
9277 {
9278 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
9279 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
9280
9281 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
9282 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
9283 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
9284
9285 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
9286 {
9287 testFloatTextureLinear(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT);
9288 testFloatTextureLinear(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT);
9289 testFloatTextureLinear(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT);
9290 }
9291 }
9292 // Test linear sampling for legacy GLES 2.0 16F formats in ES2
TEST_P(Texture2DFloatTestES2,TextureHalfFloatLinearLegacyTest)9293 TEST_P(Texture2DFloatTestES2, TextureHalfFloatLinearLegacyTest)
9294 {
9295 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
9296 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
9297
9298 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
9299 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
9300 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
9301 }
9302
9303 // Test color-renderability for ES3 float and half float textures
TEST_P(Texture2DFloatTestES3,TextureFloatRenderTest)9304 TEST_P(Texture2DFloatTestES3, TextureFloatRenderTest)
9305 {
9306 // http://anglebug.com/4092
9307 ANGLE_SKIP_TEST_IF(IsD3D9());
9308 // EXT_color_buffer_float covers float, half float, and 11-11-10 float formats
9309 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
9310
9311 testFloatTextureRender(GL_R32F, GL_RED, GL_FLOAT);
9312 testFloatTextureRender(GL_RG32F, GL_RG, GL_FLOAT);
9313 testFloatTextureRender(GL_RGBA32F, GL_RGBA, GL_FLOAT);
9314
9315 testFloatTextureRender(GL_R16F, GL_RED, GL_HALF_FLOAT);
9316 testFloatTextureRender(GL_RG16F, GL_RG, GL_HALF_FLOAT);
9317 testFloatTextureRender(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
9318
9319 testFloatTextureRender(GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT);
9320 }
9321
9322 // Test color-renderability for ES2 half float textures
TEST_P(Texture2DFloatTestES2,TextureFloatRenderTest)9323 TEST_P(Texture2DFloatTestES2, TextureFloatRenderTest)
9324 {
9325 // EXT_color_buffer_half_float requires at least one format to be renderable, but does not
9326 // require a specific one
9327 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
9328 // https://crbug.com/1003971
9329 ANGLE_SKIP_TEST_IF(IsOzone());
9330 // http://anglebug.com/4092
9331 ANGLE_SKIP_TEST_IF(IsD3D9());
9332
9333 bool atLeastOneSupported = false;
9334
9335 if (IsGLExtensionEnabled("GL_OES_texture_half_float") ||
9336 IsGLExtensionEnabled("GL_OES_texture_half_float"))
9337 {
9338 atLeastOneSupported |= checkFloatTextureRender(GL_R16F_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES);
9339 atLeastOneSupported |= checkFloatTextureRender(GL_RG16F_EXT, GL_RG_EXT, GL_HALF_FLOAT_OES);
9340 }
9341 if (IsGLExtensionEnabled("GL_OES_texture_half_float"))
9342 {
9343 atLeastOneSupported |= checkFloatTextureRender(GL_RGB16F_EXT, GL_RGB, GL_HALF_FLOAT_OES);
9344
9345 // If OES_texture_half_float is supported, then RGBA half float textures must be renderable
9346 bool rgbaSupported = checkFloatTextureRender(GL_RGBA16F_EXT, GL_RGBA, GL_HALF_FLOAT_OES);
9347 EXPECT_TRUE(rgbaSupported);
9348 atLeastOneSupported |= rgbaSupported;
9349 }
9350
9351 EXPECT_TRUE(atLeastOneSupported);
9352 }
9353
9354 // Test that UNPACK_SKIP_IMAGES doesn't have an effect on 2D texture uploads.
9355 // GLES 3.0.4 section 3.8.3.
TEST_P(Texture2DTestES3,UnpackSkipImages2D)9356 TEST_P(Texture2DTestES3, UnpackSkipImages2D)
9357 {
9358 // Crashes on Nexus 5X due to a driver bug. http://anglebug.com/1429
9359 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
9360
9361 glBindTexture(GL_TEXTURE_2D, mTexture2D);
9362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9364 ASSERT_GL_NO_ERROR();
9365
9366 // SKIP_IMAGES should not have an effect on uploading 2D textures
9367 glPixelStorei(GL_UNPACK_SKIP_IMAGES, 1000);
9368 ASSERT_GL_NO_ERROR();
9369
9370 std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
9371
9372 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9373 pixelsGreen.data());
9374 ASSERT_GL_NO_ERROR();
9375
9376 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE,
9377 pixelsGreen.data());
9378 ASSERT_GL_NO_ERROR();
9379
9380 glUseProgram(mProgram);
9381 drawQuad(mProgram, "position", 0.5f);
9382 ASSERT_GL_NO_ERROR();
9383
9384 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9385 }
9386
9387 // Test that skip defined in unpack parameters is taken into account when determining whether
9388 // unpacking source extends outside unpack buffer bounds.
TEST_P(Texture2DTestES3,UnpackSkipPixelsOutOfBounds)9389 TEST_P(Texture2DTestES3, UnpackSkipPixelsOutOfBounds)
9390 {
9391 glBindTexture(GL_TEXTURE_2D, mTexture2D);
9392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9393 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9394 ASSERT_GL_NO_ERROR();
9395
9396 GLBuffer buf;
9397 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf.get());
9398 std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
9399 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
9400 GL_DYNAMIC_COPY);
9401 ASSERT_GL_NO_ERROR();
9402
9403 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
9404 ASSERT_GL_NO_ERROR();
9405
9406 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 1);
9407 ASSERT_GL_NO_ERROR();
9408
9409 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
9410 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
9411
9412 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
9413 glPixelStorei(GL_UNPACK_SKIP_ROWS, 1);
9414 ASSERT_GL_NO_ERROR();
9415
9416 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
9417 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
9418 }
9419
9420 // Test that unpacking rows that overlap in a pixel unpack buffer works as expected.
TEST_P(Texture2DTestES3,UnpackOverlappingRowsFromUnpackBuffer)9421 TEST_P(Texture2DTestES3, UnpackOverlappingRowsFromUnpackBuffer)
9422 {
9423 ANGLE_SKIP_TEST_IF(IsD3D11());
9424
9425 // Incorrect rendering results seen on OSX AMD.
9426 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac() && IsAMD());
9427
9428 const GLuint width = 8u;
9429 const GLuint height = 8u;
9430 const GLuint unpackRowLength = 5u;
9431 const GLuint unpackSkipPixels = 1u;
9432
9433 setWindowWidth(width);
9434 setWindowHeight(height);
9435
9436 glBindTexture(GL_TEXTURE_2D, mTexture2D);
9437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9438 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9439 ASSERT_GL_NO_ERROR();
9440
9441 GLBuffer buf;
9442 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf.get());
9443 std::vector<GLColor> pixelsGreen((height - 1u) * unpackRowLength + width + unpackSkipPixels,
9444 GLColor::green);
9445
9446 for (GLuint skippedPixel = 0u; skippedPixel < unpackSkipPixels; ++skippedPixel)
9447 {
9448 pixelsGreen[skippedPixel] = GLColor(255, 0, 0, 255);
9449 }
9450
9451 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
9452 GL_DYNAMIC_COPY);
9453 ASSERT_GL_NO_ERROR();
9454
9455 glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackRowLength);
9456 glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels);
9457 ASSERT_GL_NO_ERROR();
9458
9459 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
9460 ASSERT_GL_NO_ERROR();
9461
9462 glUseProgram(mProgram);
9463 drawQuad(mProgram, "position", 0.5f);
9464 ASSERT_GL_NO_ERROR();
9465
9466 GLuint windowPixelCount = getWindowWidth() * getWindowHeight();
9467 std::vector<GLColor> actual(windowPixelCount, GLColor::black);
9468 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
9469 actual.data());
9470 std::vector<GLColor> expected(windowPixelCount, GLColor::green);
9471 EXPECT_EQ(expected, actual);
9472 }
9473
9474 template <typename T>
UNorm(double value)9475 T UNorm(double value)
9476 {
9477 return static_cast<T>(value * static_cast<double>(std::numeric_limits<T>::max()));
9478 }
9479
9480 // Test rendering a depth texture with mipmaps.
TEST_P(Texture2DTestES3,DepthTexturesWithMipmaps)9481 TEST_P(Texture2DTestES3, DepthTexturesWithMipmaps)
9482 {
9483 // TODO(cwallez) this is failing on Intel Win7 OpenGL.
9484 // TODO(zmo) this is faling on Win Intel HD 530 Debug.
9485 // http://anglebug.com/1706
9486 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
9487
9488 // Seems to fail on AMD D3D11. Possibly driver bug. http://anglebug.com/3342
9489 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsD3D11());
9490
9491 // TODO(cnorthrop): Also failing on Vulkan/Windows/AMD. http://anglebug.com/3950
9492 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
9493
9494 const int size = getWindowWidth();
9495
9496 auto dim = [size](int level) { return size >> level; };
9497 int levels = gl::log2(size);
9498
9499 glActiveTexture(GL_TEXTURE0);
9500 glBindTexture(GL_TEXTURE_2D, mTexture2D);
9501 glTexStorage2D(GL_TEXTURE_2D, levels, GL_DEPTH_COMPONENT24, size, size);
9502 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
9503 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9504 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9505 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9506 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
9507 ASSERT_GL_NO_ERROR();
9508
9509 glUseProgram(mProgram);
9510 glUniform1i(mTexture2DUniformLocation, 0);
9511
9512 std::vector<unsigned char> expected;
9513
9514 for (int level = 0; level < levels; ++level)
9515 {
9516 double value = (static_cast<double>(level) / static_cast<double>(levels - 1));
9517 expected.push_back(UNorm<unsigned char>(value));
9518
9519 int levelDim = dim(level);
9520
9521 ASSERT_GT(levelDim, 0);
9522
9523 std::vector<unsigned int> initData(levelDim * levelDim, UNorm<unsigned int>(value));
9524 glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, levelDim, levelDim, GL_DEPTH_COMPONENT,
9525 GL_UNSIGNED_INT, initData.data());
9526 }
9527 ASSERT_GL_NO_ERROR();
9528
9529 for (int level = 0; level < levels; ++level)
9530 {
9531 glViewport(0, 0, dim(level), dim(level));
9532 drawQuad(mProgram, "position", 0.5f);
9533 GLColor actual = ReadColor(0, 0);
9534 EXPECT_NEAR(expected[level], actual.R, 10u);
9535 }
9536
9537 ASSERT_GL_NO_ERROR();
9538 }
9539
9540 class Texture2DDepthTest : public Texture2DTest
9541 {
9542 protected:
Texture2DDepthTest()9543 Texture2DDepthTest() : Texture2DTest() {}
9544
getVertexShaderSource()9545 const char *getVertexShaderSource() override
9546 {
9547 return "attribute vec4 vPosition;\n"
9548 "void main() {\n"
9549 " gl_Position = vPosition;\n"
9550 "}\n";
9551 }
9552
getFragmentShaderSource()9553 const char *getFragmentShaderSource() override
9554 {
9555 return "precision mediump float;\n"
9556 "uniform sampler2D ShadowMap;"
9557 "void main() {\n"
9558 " vec4 shadow_value = texture2D(ShadowMap, vec2(0.5, 0.5));"
9559 " if (shadow_value.x == shadow_value.z && shadow_value.x != 0.0) {"
9560 " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);"
9561 " } else {"
9562 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
9563 " }"
9564 "}\n";
9565 }
9566
checkTexImageFormatSupport(GLenum format,GLenum internalformat,GLenum type)9567 bool checkTexImageFormatSupport(GLenum format, GLenum internalformat, GLenum type)
9568 {
9569 EXPECT_GL_NO_ERROR();
9570
9571 GLTexture tex;
9572 glBindTexture(GL_TEXTURE_2D, tex);
9573 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, type, nullptr);
9574
9575 return (glGetError() == GL_NO_ERROR);
9576 }
9577
testBehavior(bool useSizedComponent)9578 void testBehavior(bool useSizedComponent)
9579 {
9580 int w = getWindowWidth();
9581 int h = getWindowHeight();
9582 GLuint format = GL_DEPTH_COMPONENT;
9583 GLuint internalFormat = GL_DEPTH_COMPONENT;
9584
9585 if (useSizedComponent)
9586 {
9587 internalFormat = GL_DEPTH_COMPONENT24;
9588 }
9589
9590 GLFramebuffer fbo;
9591 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
9592 ASSERT_GL_NO_ERROR();
9593
9594 GLTexture depthTexture;
9595 glBindTexture(GL_TEXTURE_2D, depthTexture);
9596 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9598 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9599 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9600
9601 TexCoordDrawTest::setUpProgram();
9602 GLint shadowMapLocation = glGetUniformLocation(mProgram, "ShadowMap");
9603 ASSERT_NE(-1, shadowMapLocation);
9604
9605 GLint positionLocation = glGetAttribLocation(mProgram, "vPosition");
9606 ASSERT_NE(-1, positionLocation);
9607
9608 ANGLE_SKIP_TEST_IF(!checkTexImageFormatSupport(format, internalFormat, GL_UNSIGNED_INT));
9609 glBindTexture(GL_TEXTURE_2D, depthTexture);
9610 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_INT, nullptr);
9611 ASSERT_GL_NO_ERROR();
9612
9613 // try adding a color buffer.
9614 GLTexture colorTex;
9615 glBindTexture(GL_TEXTURE_2D, colorTex);
9616 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9617 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9618 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9619 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9620 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9621 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
9622 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
9623 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
9624 ASSERT_GL_NO_ERROR();
9625
9626 glViewport(0, 0, w, h);
9627 // Fill depthTexture with 0.75
9628 glClearDepthf(0.75);
9629 glClear(GL_DEPTH_BUFFER_BIT);
9630
9631 // Revert to normal framebuffer to test depth shader
9632 glBindFramebuffer(GL_FRAMEBUFFER, 0);
9633 glViewport(0, 0, w, h);
9634 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
9635 glClearDepthf(0.0f);
9636 ASSERT_GL_NO_ERROR();
9637
9638 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
9639 ASSERT_GL_NO_ERROR();
9640
9641 glActiveTexture(GL_TEXTURE0);
9642 glBindTexture(GL_TEXTURE_2D, depthTexture);
9643
9644 glUseProgram(mProgram);
9645 ASSERT_GL_NO_ERROR();
9646
9647 glUniform1i(shadowMapLocation, 0);
9648
9649 const GLfloat gTriangleVertices[] = {-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f};
9650
9651 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
9652 ASSERT_GL_NO_ERROR();
9653 glEnableVertexAttribArray(positionLocation);
9654 ASSERT_GL_NO_ERROR();
9655 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9656 ASSERT_GL_NO_ERROR();
9657
9658 GLuint pixels[1];
9659 glReadPixels(w / 2, h / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
9660 ASSERT_GL_NO_ERROR();
9661
9662 // The GLES 3.x spec says that the depth texture sample can be found in the RED component.
9663 // However, the OES_depth_texture indicates that the depth value is treated as luminance and
9664 // is in all the color components. Multiple implementations implement a workaround that
9665 // follows the OES_depth_texture behavior if the internalformat given at glTexImage2D was a
9666 // unsized format (e.g. DEPTH_COMPONENT) and the GLES 3.x behavior if it was a sized
9667 // internalformat such as GL_DEPTH_COMPONENT24. The shader will write out a different color
9668 // depending on if it sees the texture sample in only the RED component.
9669 if (useSizedComponent)
9670 {
9671 ASSERT_NE(pixels[0], 0xff0000ff);
9672 }
9673 else
9674 {
9675 ASSERT_EQ(pixels[0], 0xff0000ff);
9676 }
9677
9678 glBindFramebuffer(GL_FRAMEBUFFER, 0);
9679 glDeleteProgram(mProgram);
9680 }
9681 };
9682
9683 // Test depth texture compatibility with OES_depth_texture. Uses unsized internal format.
TEST_P(Texture2DDepthTest,DepthTextureES2Compatibility)9684 TEST_P(Texture2DDepthTest, DepthTextureES2Compatibility)
9685 {
9686 ANGLE_SKIP_TEST_IF(IsD3D11());
9687 ANGLE_SKIP_TEST_IF(IsIntel() && IsD3D9());
9688 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_depth_texture") &&
9689 !IsGLExtensionEnabled("GL_OES_depth_texture"));
9690 // http://anglebug.com/4092
9691 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
9692 ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
9693
9694 // When the depth texture is specified with unsized internalformat implementations follow
9695 // OES_depth_texture behavior. Otherwise they follow GLES 3.0 behavior.
9696 testBehavior(false);
9697 }
9698
9699 // Test depth texture compatibility with GLES3 using sized internalformat.
TEST_P(Texture2DDepthTest,DepthTextureES3Compatibility)9700 TEST_P(Texture2DDepthTest, DepthTextureES3Compatibility)
9701 {
9702 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
9703
9704 // http://anglebug.com/5243
9705 ANGLE_SKIP_TEST_IF(IsMetal() && !IsMetalTextureSwizzleAvailable());
9706
9707 testBehavior(true);
9708 }
9709
9710 // Tests unpacking into the unsized GL_ALPHA format.
TEST_P(Texture2DTestES3,UnsizedAlphaUnpackBuffer)9711 TEST_P(Texture2DTestES3, UnsizedAlphaUnpackBuffer)
9712 {
9713 // Initialize the texure.
9714 glBindTexture(GL_TEXTURE_2D, mTexture2D);
9715 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, getWindowWidth(), getWindowHeight(), 0, GL_ALPHA,
9716 GL_UNSIGNED_BYTE, nullptr);
9717 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9718 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9719
9720 std::vector<GLubyte> bufferData(getWindowWidth() * getWindowHeight(), 127);
9721
9722 // Pull in the color data from the unpack buffer.
9723 GLBuffer unpackBuffer;
9724 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
9725 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer.get());
9726 glBufferData(GL_PIXEL_UNPACK_BUFFER, getWindowWidth() * getWindowHeight(), bufferData.data(),
9727 GL_STATIC_DRAW);
9728
9729 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_ALPHA,
9730 GL_UNSIGNED_BYTE, nullptr);
9731
9732 // Clear to a weird color to make sure we're drawing something.
9733 glClearColor(0.5f, 0.8f, 1.0f, 0.2f);
9734 glClear(GL_COLOR_BUFFER_BIT);
9735
9736 // Draw with the alpha texture and verify.
9737 drawQuad(mProgram, "position", 0.5f);
9738
9739 ASSERT_GL_NO_ERROR();
9740 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 127, 1);
9741 }
9742
9743 // Ensure stale unpack data doesn't propagate in D3D11.
TEST_P(Texture2DTestES3,StaleUnpackData)9744 TEST_P(Texture2DTestES3, StaleUnpackData)
9745 {
9746 // Init unpack buffer.
9747 GLsizei pixelCount = getWindowWidth() * getWindowHeight() / 2;
9748 std::vector<GLColor> pixels(pixelCount, GLColor::red);
9749
9750 GLBuffer unpackBuffer;
9751 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
9752 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer.get());
9753 GLsizei bufferSize = pixelCount * sizeof(GLColor);
9754 glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize, pixels.data(), GL_STATIC_DRAW);
9755
9756 // Create from unpack buffer.
9757 glBindTexture(GL_TEXTURE_2D, mTexture2D);
9758 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth() / 2, getWindowHeight() / 2, 0,
9759 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9760 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9761 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9762
9763 drawQuad(mProgram, "position", 0.5f);
9764
9765 ASSERT_GL_NO_ERROR();
9766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9767
9768 // Fill unpack with green, recreating buffer.
9769 pixels.assign(getWindowWidth() * getWindowHeight(), GLColor::green);
9770 GLsizei size2 = getWindowWidth() * getWindowHeight() * sizeof(GLColor);
9771 glBufferData(GL_PIXEL_UNPACK_BUFFER, size2, pixels.data(), GL_STATIC_DRAW);
9772
9773 // Reinit texture with green.
9774 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
9775 GL_UNSIGNED_BYTE, nullptr);
9776
9777 drawQuad(mProgram, "position", 0.5f);
9778
9779 ASSERT_GL_NO_ERROR();
9780 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9781 }
9782
9783 // Ensure that texture parameters passed as floats that are converted to ints are rounded before
9784 // validating they are less than 0.
TEST_P(Texture2DTestES3,TextureBaseMaxLevelRoundingValidation)9785 TEST_P(Texture2DTestES3, TextureBaseMaxLevelRoundingValidation)
9786 {
9787 GLTexture texture;
9788 glBindTexture(GL_TEXTURE_2D, texture);
9789
9790 // Use a negative number that will round to zero when converted to an integer
9791 // According to the spec(2.3.1 Data Conversion For State - Setting Commands):
9792 // "Validation of values performed by state-setting commands is performed after conversion,
9793 // unless specified otherwise for a specific command."
9794 GLfloat param = -7.30157126e-07f;
9795 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, param);
9796 EXPECT_GL_NO_ERROR();
9797
9798 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, param);
9799 EXPECT_GL_NO_ERROR();
9800 }
9801
9802 // This test covers a D3D format redefinition bug for 3D textures. The base level format was not
9803 // being properly checked, and the texture storage of the previous texture format was persisting.
9804 // This would result in an ASSERT in debug and incorrect rendering in release.
9805 // See http://anglebug.com/1609 and WebGL 2 test conformance2/misc/views-with-offsets.html.
TEST_P(Texture3DTestES3,FormatRedefinitionBug)9806 TEST_P(Texture3DTestES3, FormatRedefinitionBug)
9807 {
9808 GLTexture tex;
9809 glBindTexture(GL_TEXTURE_3D, tex.get());
9810 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9811
9812 GLFramebuffer framebuffer;
9813 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
9814 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex.get(), 0, 0);
9815
9816 glCheckFramebufferStatus(GL_FRAMEBUFFER);
9817
9818 std::vector<uint8_t> pixelData(100, 0);
9819
9820 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB565, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, nullptr);
9821 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
9822 pixelData.data());
9823
9824 ASSERT_GL_NO_ERROR();
9825 }
9826
9827 // Test glTexSubImage using PBO to 3D texture that expose the regression bug
9828 // https://issuetracker.google.com/170657065
TEST_P(Texture3DTestES3,TexSubImageWithPBO)9829 TEST_P(Texture3DTestES3, TexSubImageWithPBO)
9830 {
9831 GLTexture tex;
9832
9833 GLuint pbo;
9834 glGenBuffers(1, &pbo);
9835 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
9836 std::vector<uint8_t> pixelData(128 * 128 * 8 * 4, 0x1f);
9837 glBufferData(GL_PIXEL_UNPACK_BUFFER, 128 * 128 * 8 * 4, pixelData.data(), GL_STATIC_DRAW);
9838
9839 glBindTexture(GL_TEXTURE_3D, tex.get());
9840 glTexStorage3D(GL_TEXTURE_3D, 8, GL_RGBA8, 128, 128, 8);
9841 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
9842 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9843 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 128, 128, 8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9844 glTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 64, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9845 glTexSubImage3D(GL_TEXTURE_3D, 2, 0, 0, 0, 32, 32, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9846 glTexSubImage3D(GL_TEXTURE_3D, 3, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9847 glTexSubImage3D(GL_TEXTURE_3D, 4, 0, 0, 0, 8, 8, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9848 glTexSubImage3D(GL_TEXTURE_3D, 5, 0, 0, 0, 4, 4, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9849 glTexSubImage3D(GL_TEXTURE_3D, 6, 0, 0, 0, 2, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9850 glTexSubImage3D(GL_TEXTURE_3D, 7, 0, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9851
9852 drawQuad(mProgram, "position", 0.5f);
9853 ASSERT_GL_NO_ERROR();
9854
9855 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 128, 128, 8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9856 glTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 64, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9857 glTexSubImage3D(GL_TEXTURE_3D, 2, 0, 0, 0, 32, 32, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9858 ASSERT_GL_NO_ERROR();
9859
9860 drawQuad(mProgram, "position", 0.5f);
9861 ASSERT_GL_NO_ERROR();
9862 }
9863
9864 // Test basic pixel unpack buffer OOB checks when uploading to a 2D or 3D texture
TEST_P(Texture3DTestES3,BasicUnpackBufferOOB)9865 TEST_P(Texture3DTestES3, BasicUnpackBufferOOB)
9866 {
9867 // 2D tests
9868 {
9869 GLTexture tex;
9870 glBindTexture(GL_TEXTURE_2D, tex.get());
9871
9872 GLBuffer pbo;
9873 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.get());
9874
9875 // Test OOB
9876 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 - 1, nullptr, GL_STATIC_DRAW);
9877 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9878 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
9879
9880 // Test OOB
9881 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2, nullptr, GL_STATIC_DRAW);
9882 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9883 ASSERT_GL_NO_ERROR();
9884 }
9885
9886 // 3D tests
9887 {
9888 GLTexture tex;
9889 glBindTexture(GL_TEXTURE_3D, tex.get());
9890
9891 GLBuffer pbo;
9892 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo.get());
9893
9894 // Test OOB
9895 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2 - 1, nullptr,
9896 GL_STATIC_DRAW);
9897 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9898 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
9899
9900 // Test OOB
9901 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2, nullptr, GL_STATIC_DRAW);
9902 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9903 ASSERT_GL_NO_ERROR();
9904 }
9905 }
9906
9907 // Tests behaviour with a single texture and multiple sampler objects.
TEST_P(Texture2DTestES3,SingleTextureMultipleSamplers)9908 TEST_P(Texture2DTestES3, SingleTextureMultipleSamplers)
9909 {
9910 GLint maxTextureUnits = 0;
9911 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
9912 ANGLE_SKIP_TEST_IF(maxTextureUnits < 4);
9913
9914 constexpr int kSize = 16;
9915
9916 // Make a single-level texture, fill it with red.
9917 std::vector<GLColor> redColors(kSize * kSize, GLColor::red);
9918 GLTexture tex;
9919 glBindTexture(GL_TEXTURE_2D, tex);
9920 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9921 redColors.data());
9922 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9923 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9924
9925 // Simple confidence check.
9926 draw2DTexturedQuad(0.5f, 1.0f, true);
9927 ASSERT_GL_NO_ERROR();
9928 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9929
9930 // Bind texture to unit 1 with a sampler object making it incomplete.
9931 GLSampler sampler;
9932 glBindSampler(0, sampler);
9933 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
9934 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9935
9936 // Make a mipmap texture, fill it with blue.
9937 std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
9938 GLTexture mipmapTex;
9939 glBindTexture(GL_TEXTURE_2D, mipmapTex);
9940 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9941 blueColors.data());
9942 glGenerateMipmap(GL_TEXTURE_2D);
9943
9944 // Draw with the sampler, expect blue.
9945 draw2DTexturedQuad(0.5f, 1.0f, true);
9946 ASSERT_GL_NO_ERROR();
9947 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
9948
9949 // Simple multitexturing program.
9950 constexpr char kVS[] =
9951 "#version 300 es\n"
9952 "in vec2 position;\n"
9953 "out vec2 texCoord;\n"
9954 "void main()\n"
9955 "{\n"
9956 " gl_Position = vec4(position, 0, 1);\n"
9957 " texCoord = position * 0.5 + vec2(0.5);\n"
9958 "}";
9959
9960 constexpr char kFS[] =
9961 "#version 300 es\n"
9962 "precision mediump float;\n"
9963 "in vec2 texCoord;\n"
9964 "uniform sampler2D tex1;\n"
9965 "uniform sampler2D tex2;\n"
9966 "uniform sampler2D tex3;\n"
9967 "uniform sampler2D tex4;\n"
9968 "out vec4 color;\n"
9969 "void main()\n"
9970 "{\n"
9971 " color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
9972 " + texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
9973 "}";
9974
9975 ANGLE_GL_PROGRAM(program, kVS, kFS);
9976
9977 std::array<GLint, 4> texLocations = {
9978 {glGetUniformLocation(program, "tex1"), glGetUniformLocation(program, "tex2"),
9979 glGetUniformLocation(program, "tex3"), glGetUniformLocation(program, "tex4")}};
9980 for (GLint location : texLocations)
9981 {
9982 ASSERT_NE(-1, location);
9983 }
9984
9985 // Init the uniform data.
9986 glUseProgram(program);
9987 for (GLint location = 0; location < 4; ++location)
9988 {
9989 glUniform1i(texLocations[location], location);
9990 }
9991
9992 // Initialize four samplers
9993 GLSampler samplers[4];
9994
9995 // 0: non-mipped.
9996 glBindSampler(0, samplers[0]);
9997 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9998 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9999
10000 // 1: mipped.
10001 glBindSampler(1, samplers[1]);
10002 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10003 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10004
10005 // 2: non-mipped.
10006 glBindSampler(2, samplers[2]);
10007 glSamplerParameteri(samplers[2], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10008 glSamplerParameteri(samplers[2], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10009
10010 // 3: mipped.
10011 glBindSampler(3, samplers[3]);
10012 glSamplerParameteri(samplers[3], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10013 glSamplerParameteri(samplers[3], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10014
10015 // Bind two blue mipped textures and two single layer textures, should all draw.
10016 glActiveTexture(GL_TEXTURE0);
10017 glBindTexture(GL_TEXTURE_2D, tex);
10018
10019 glActiveTexture(GL_TEXTURE1);
10020 glBindTexture(GL_TEXTURE_2D, mipmapTex);
10021
10022 glActiveTexture(GL_TEXTURE2);
10023 glBindTexture(GL_TEXTURE_2D, tex);
10024
10025 glActiveTexture(GL_TEXTURE3);
10026 glBindTexture(GL_TEXTURE_2D, mipmapTex);
10027
10028 ASSERT_GL_NO_ERROR();
10029
10030 drawQuad(program, "position", 0.5f);
10031 ASSERT_GL_NO_ERROR();
10032 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 255, 2);
10033
10034 // Bind four single layer textures, two should be incomplete.
10035 glActiveTexture(GL_TEXTURE1);
10036 glBindTexture(GL_TEXTURE_2D, tex);
10037
10038 glActiveTexture(GL_TEXTURE3);
10039 glBindTexture(GL_TEXTURE_2D, tex);
10040
10041 drawQuad(program, "position", 0.5f);
10042 ASSERT_GL_NO_ERROR();
10043 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 2);
10044 }
10045
10046 // The test is added to cover http://anglebug.com/2153. Cubemap completeness checks used to start
10047 // always at level 0 instead of the base level resulting in an incomplete texture if the faces at
10048 // level 0 are not created. The test creates a cubemap texture, specifies the images only for mip
10049 // level 1 filled with white color, updates the base level to be 1 and renders a quad. The program
10050 // samples the cubemap using a direction vector (1,1,1).
TEST_P(TextureCubeTestES3,SpecifyAndSampleFromBaseLevel1)10051 TEST_P(TextureCubeTestES3, SpecifyAndSampleFromBaseLevel1)
10052 {
10053 // Check http://anglebug.com/2155.
10054 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
10055
10056 constexpr char kVS[] =
10057 R"(#version 300 es
10058 precision mediump float;
10059 in vec3 pos;
10060 void main() {
10061 gl_Position = vec4(pos, 1.0);
10062 })";
10063
10064 constexpr char kFS[] =
10065 R"(#version 300 es
10066 precision mediump float;
10067 out vec4 color;
10068 uniform samplerCube uTex;
10069 void main(){
10070 color = texture(uTex, vec3(1.0));
10071 })";
10072
10073 ANGLE_GL_PROGRAM(program, kVS, kFS);
10074 glUseProgram(program);
10075
10076 glUniform1i(glGetUniformLocation(program, "uTex"), 0);
10077 glActiveTexture(GL_TEXTURE0);
10078
10079 GLTexture cubeTex;
10080 glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
10081
10082 const int kFaceWidth = 1;
10083 const int kFaceHeight = 1;
10084 std::vector<uint32_t> texData(kFaceWidth * kFaceHeight, 0xFFFFFFFF);
10085 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
10086 GL_UNSIGNED_BYTE, texData.data());
10087 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
10088 GL_UNSIGNED_BYTE, texData.data());
10089 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
10090 GL_UNSIGNED_BYTE, texData.data());
10091 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
10092 GL_UNSIGNED_BYTE, texData.data());
10093 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
10094 GL_UNSIGNED_BYTE, texData.data());
10095 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
10096 GL_UNSIGNED_BYTE, texData.data());
10097 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10098 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10099 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
10100 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
10101 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
10102 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 1);
10103
10104 drawQuad(program, "pos", 0.5f, 1.0f, true);
10105 ASSERT_GL_NO_ERROR();
10106
10107 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::white);
10108 }
10109
10110 // Test GL_PIXEL_UNPACK_BUFFER with GL_TEXTURE_CUBE_MAP.
TEST_P(TextureCubeTestES3,CubeMapPixelUnpackBuffer)10111 TEST_P(TextureCubeTestES3, CubeMapPixelUnpackBuffer)
10112 {
10113 // Check http://anglebug.com/2155.
10114 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
10115
10116 constexpr char kVS[] =
10117 R"(#version 300 es
10118 precision mediump float;
10119 in vec3 pos;
10120 void main() {
10121 gl_Position = vec4(pos, 1.0);
10122 })";
10123
10124 constexpr char kFS[] =
10125 R"(#version 300 es
10126 precision mediump float;
10127 out vec4 color;
10128 uniform samplerCube uTex;
10129 void main(){
10130 color = texture(uTex, vec3(1.0));
10131 })";
10132
10133 ANGLE_GL_PROGRAM(program, kVS, kFS);
10134 glUseProgram(program);
10135
10136 glUniform1i(glGetUniformLocation(program, "uTex"), 0);
10137 glActiveTexture(GL_TEXTURE0);
10138
10139 GLTexture cubeTex;
10140 glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
10141
10142 const int kFaceWidth = 4;
10143 const int kFaceHeight = 4;
10144
10145 uint16_t kHalfFloatOne = 0x3C00;
10146 uint16_t kHalfFloatZero = 0;
10147
10148 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA16F, kFaceWidth, kFaceHeight);
10149 struct RGBA16F
10150 {
10151 uint16_t R, G, B, A;
10152 };
10153 RGBA16F redColor = {kHalfFloatOne, kHalfFloatZero, kHalfFloatZero, kHalfFloatOne};
10154
10155 std::vector<RGBA16F> pixels(kFaceWidth * kFaceHeight, redColor);
10156 GLBuffer buffer;
10157 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer.get());
10158 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(RGBA16F), pixels.data(),
10159 GL_DYNAMIC_DRAW);
10160 EXPECT_GL_NO_ERROR();
10161 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10162
10163 for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
10164 {
10165 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, 0, 0, 0, kFaceWidth,
10166 kFaceHeight, GL_RGBA, GL_HALF_FLOAT, 0);
10167 EXPECT_GL_NO_ERROR();
10168 }
10169 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
10170
10171 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10172 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10173 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
10174 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
10175 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
10176
10177 drawQuad(program, "pos", 0.5f, 1.0f, true);
10178 ASSERT_GL_NO_ERROR();
10179
10180 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::red);
10181 }
10182
10183 // Verify that using negative texture base level and max level generates GL_INVALID_VALUE.
TEST_P(Texture2DTestES3,NegativeTextureBaseLevelAndMaxLevel)10184 TEST_P(Texture2DTestES3, NegativeTextureBaseLevelAndMaxLevel)
10185 {
10186 GLuint texture = create2DTexture();
10187
10188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, -1);
10189 EXPECT_GL_ERROR(GL_INVALID_VALUE);
10190
10191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, -1);
10192 EXPECT_GL_ERROR(GL_INVALID_VALUE);
10193
10194 glDeleteTextures(1, &texture);
10195 EXPECT_GL_NO_ERROR();
10196 }
10197
10198 // Test setting base level after calling generateMipmap on a LUMA texture.
10199 // Covers http://anglebug.com/2498
TEST_P(Texture2DTestES3,GenerateMipmapAndBaseLevelLUMA)10200 TEST_P(Texture2DTestES3, GenerateMipmapAndBaseLevelLUMA)
10201 {
10202 glActiveTexture(GL_TEXTURE0);
10203 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10204
10205 constexpr const GLsizei kWidth = 8;
10206 constexpr const GLsizei kHeight = 8;
10207 std::array<GLubyte, kWidth * kHeight * 2> whiteData;
10208 whiteData.fill(255u);
10209
10210 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, kWidth, kHeight, 0, GL_LUMINANCE_ALPHA,
10211 GL_UNSIGNED_BYTE, whiteData.data());
10212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
10213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10214 glGenerateMipmap(GL_TEXTURE_2D);
10215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
10216 EXPECT_GL_NO_ERROR();
10217
10218 drawQuad(mProgram, "position", 0.5f);
10219 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::white);
10220 }
10221
10222 // Incompatible levels with non-mipmap filtering should work.
TEST_P(Texture2DTestES3,IncompatibleMipsButNoMipmapFiltering)10223 TEST_P(Texture2DTestES3, IncompatibleMipsButNoMipmapFiltering)
10224 {
10225 // http://anglebug.com/4782
10226 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && (IsAMD() || IsIntel()));
10227
10228 // http://anglebug.com/4786
10229 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIAShield());
10230
10231 glActiveTexture(GL_TEXTURE0);
10232 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10233
10234 constexpr const GLsizei kSize = 8;
10235 const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
10236 const std::vector<GLColor> kLevel1Data(kSize * kSize, GLColor::red);
10237
10238 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10239 kLevel0Data.data());
10240 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10241 kLevel1Data.data());
10242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10244 EXPECT_GL_NO_ERROR();
10245
10246 // Draw with base level 0. The GL_LINEAR filtering ensures the texture's image is not created
10247 // with mipmap.
10248 drawQuad(mProgram, "position", 0.5f);
10249 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
10250
10251 // Verify draw with level 1.
10252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
10253 drawQuad(mProgram, "position", 0.5f);
10254 EXPECT_GL_NO_ERROR();
10255 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel1Data[0]);
10256
10257 // Verify draw with level 0 again
10258 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
10259 drawQuad(mProgram, "position", 0.5f);
10260 EXPECT_GL_NO_ERROR();
10261 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
10262 }
10263
10264 // Enabling mipmap filtering after previously having used the texture without it should work.
TEST_P(Texture2DTestES3,NoMipmapDrawThenMipmapDraw)10265 TEST_P(Texture2DTestES3, NoMipmapDrawThenMipmapDraw)
10266 {
10267 glActiveTexture(GL_TEXTURE0);
10268 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10269
10270 constexpr const GLsizei kSize = 8;
10271 const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
10272 const std::vector<GLColor> kLevelOtherData(kSize * kSize, GLColor::red);
10273
10274 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10275 kLevel0Data.data());
10276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10277 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10278 EXPECT_GL_NO_ERROR();
10279
10280 // Draw so the texture's image is allocated.
10281 drawQuad(mProgram, "position", 0.5f);
10282 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
10283
10284 // Specify the rest of the image
10285 for (GLint mip = 1; (kSize >> mip) >= 1; ++mip)
10286 {
10287 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
10288 GL_UNSIGNED_BYTE, kLevelOtherData.data());
10289 }
10290 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10291
10292 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
10293 glUseProgram(program);
10294 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
10295 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
10296 ASSERT_NE(-1, textureLoc);
10297 ASSERT_NE(-1, lodLoc);
10298 glUniform1i(textureLoc, 0);
10299
10300 // Verify the mips
10301 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
10302 {
10303 glUniform1f(lodLoc, mip);
10304 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10305 EXPECT_GL_NO_ERROR();
10306 EXPECT_PIXEL_COLOR_EQ(0, 0, (mip == 0 ? kLevel0Data[0] : kLevelOtherData[0]));
10307 }
10308 }
10309
10310 // Disabling mipmap filtering after previously having used the texture with it should work.
TEST_P(Texture2DTestES3,MipmapDrawThenNoMipmapDraw)10311 TEST_P(Texture2DTestES3, MipmapDrawThenNoMipmapDraw)
10312 {
10313 glActiveTexture(GL_TEXTURE0);
10314 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10315
10316 constexpr const GLsizei kSize = 8;
10317 const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
10318 const std::vector<GLColor> kLevelOtherData(kSize * kSize, GLColor::red);
10319
10320 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10321 kLevel0Data.data());
10322 for (GLint mip = 1; (kSize >> mip) >= 1; ++mip)
10323 {
10324 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
10325 GL_UNSIGNED_BYTE, kLevelOtherData.data());
10326 }
10327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10328 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10329 EXPECT_GL_NO_ERROR();
10330
10331 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
10332 glUseProgram(program);
10333 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
10334 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
10335 ASSERT_NE(-1, textureLoc);
10336 ASSERT_NE(-1, lodLoc);
10337 glUniform1i(textureLoc, 0);
10338
10339 // Verify the mips.
10340 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
10341 {
10342 glUniform1f(lodLoc, mip);
10343 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10344 EXPECT_GL_NO_ERROR();
10345 EXPECT_PIXEL_COLOR_EQ(0, 0, (mip == 0 ? kLevel0Data[0] : kLevelOtherData[0]));
10346 }
10347
10348 // Disable mipmapping and verify mips again.
10349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10350
10351 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
10352 {
10353 glUniform1f(lodLoc, mip);
10354 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10355 EXPECT_GL_NO_ERROR();
10356 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
10357 }
10358 }
10359
10360 // Respecify texture with more mips.
TEST_P(Texture2DTestES3,RespecifyWithMoreMips)10361 TEST_P(Texture2DTestES3, RespecifyWithMoreMips)
10362 {
10363 glActiveTexture(GL_TEXTURE0);
10364 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10365
10366 constexpr const GLsizei kSize = 8;
10367 const std::vector<GLColor> kLevelEvenData(kSize * kSize, GLColor::blue);
10368 const std::vector<GLColor> kLevelOddData(kSize * kSize * 4, GLColor::red);
10369
10370 auto getLevelData = [&](GLint mip) {
10371 return mip % 2 == 0 ? kLevelEvenData.data() : kLevelOddData.data();
10372 };
10373
10374 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
10375 {
10376 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
10377 GL_UNSIGNED_BYTE, getLevelData(mip));
10378 }
10379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10380 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10381 EXPECT_GL_NO_ERROR();
10382
10383 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
10384 glUseProgram(program);
10385 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
10386 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
10387 ASSERT_NE(-1, textureLoc);
10388 ASSERT_NE(-1, lodLoc);
10389 glUniform1i(textureLoc, 0);
10390
10391 // Verify the mips.
10392 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
10393 {
10394 glUniform1f(lodLoc, mip);
10395 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10396 EXPECT_GL_NO_ERROR();
10397 EXPECT_PIXEL_COLOR_EQ(0, 0, getLevelData(mip)[0]);
10398 }
10399
10400 // Respecify the texture with more mips, without changing any parameters.
10401 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize * 2, kSize * 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10402 kLevelOddData.data());
10403 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
10404 {
10405 glTexImage2D(GL_TEXTURE_2D, mip + 1, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
10406 GL_UNSIGNED_BYTE, getLevelData(mip));
10407 }
10408
10409 // Verify the mips.
10410 for (GLint mip = 0; ((kSize * 2) >> mip) >= 1; ++mip)
10411 {
10412 glUniform1f(lodLoc, mip);
10413 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10414 EXPECT_GL_NO_ERROR();
10415 EXPECT_PIXEL_COLOR_EQ(0, 0, getLevelData(mip - 1)[0]);
10416 }
10417 }
10418
10419 // Covers a bug in the D3D11 backend: http://anglebug.com/2772
10420 // When using a sampler the texture was created as if it has mipmaps,
10421 // regardless what you specified in GL_TEXTURE_MIN_FILTER via
10422 // glSamplerParameteri() -- mistakenly the default value
10423 // GL_NEAREST_MIPMAP_LINEAR or the value set via glTexParameteri() was
10424 // evaluated.
10425 // If you didn't provide mipmaps and didn't let the driver generate them
10426 // this led to not sampling your texture data when minification occurred.
TEST_P(Texture2DTestES3,MinificationWithSamplerNoMipmapping)10427 TEST_P(Texture2DTestES3, MinificationWithSamplerNoMipmapping)
10428 {
10429 constexpr char kVS[] =
10430 "#version 300 es\n"
10431 "out vec2 texcoord;\n"
10432 "in vec4 position;\n"
10433 "void main()\n"
10434 "{\n"
10435 " gl_Position = vec4(position.xy * 0.1, 0.0, 1.0);\n"
10436 " texcoord = (position.xy * 0.5) + 0.5;\n"
10437 "}\n";
10438
10439 constexpr char kFS[] =
10440 "#version 300 es\n"
10441 "precision highp float;\n"
10442 "uniform highp sampler2D tex;\n"
10443 "in vec2 texcoord;\n"
10444 "out vec4 fragColor;\n"
10445 "void main()\n"
10446 "{\n"
10447 " fragColor = texture(tex, texcoord);\n"
10448 "}\n";
10449
10450 ANGLE_GL_PROGRAM(program, kVS, kFS);
10451
10452 GLSampler sampler;
10453 glBindSampler(0, sampler);
10454 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10455 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10456
10457 glActiveTexture(GL_TEXTURE0);
10458 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10459
10460 const GLsizei texWidth = getWindowWidth();
10461 const GLsizei texHeight = getWindowHeight();
10462 const std::vector<GLColor> whiteData(texWidth * texHeight, GLColor::white);
10463
10464 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10465 whiteData.data());
10466 EXPECT_GL_NO_ERROR();
10467
10468 drawQuad(program, "position", 0.5f);
10469 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, angle::GLColor::white);
10470 }
10471
testUploadThenUseInDifferentStages(const std::vector<UploadThenUseStageParam> & uses)10472 void Texture2DTest::testUploadThenUseInDifferentStages(
10473 const std::vector<UploadThenUseStageParam> &uses)
10474 {
10475 constexpr char kVSSampleVS[] = R"(attribute vec4 a_position;
10476 uniform sampler2D u_tex2D;
10477 varying vec4 v_color;
10478
10479 void main()
10480 {
10481 gl_Position = vec4(a_position.xy, 0.0, 1.0);
10482 v_color = texture2D(u_tex2D, a_position.xy * 0.5 + vec2(0.5));
10483 })";
10484
10485 constexpr char kVSSampleFS[] = R"(precision mediump float;
10486 varying vec4 v_color;
10487
10488 void main()
10489 {
10490 gl_FragColor = v_color;
10491 })";
10492
10493 ANGLE_GL_PROGRAM(sampleInVS, kVSSampleVS, kVSSampleFS);
10494 ANGLE_GL_PROGRAM(sampleInFS, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
10495
10496 GLFramebuffer fbo[2];
10497 GLTexture color[2];
10498 for (uint32_t i = 0; i < 2; ++i)
10499 {
10500 glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
10501 glBindTexture(GL_TEXTURE_2D, color[i]);
10502 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10503 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color[i], 0);
10504 }
10505
10506 const GLColor kImageColor(63, 31, 0, 255);
10507
10508 GLTexture tex;
10509 glBindTexture(GL_TEXTURE_2D, tex);
10510 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kImageColor);
10511 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10512 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10513 glActiveTexture(GL_TEXTURE0);
10514 ASSERT_GL_NO_ERROR();
10515
10516 glEnable(GL_BLEND);
10517 glBlendFunc(GL_ONE, GL_ONE);
10518
10519 glClearColor(0, 0, 0, 1);
10520
10521 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1]);
10522 glClear(GL_COLOR_BUFFER_BIT);
10523 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
10524 glClear(GL_COLOR_BUFFER_BIT);
10525
10526 uint32_t curFboIndex = 0;
10527 uint32_t fboDrawCount[2] = {};
10528
10529 for (const UploadThenUseStageParam &use : uses)
10530 {
10531 const GLProgram &program = use.useStage == GL_VERTEX_SHADER ? sampleInVS : sampleInFS;
10532 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10533 ASSERT_GL_NO_ERROR();
10534
10535 ++fboDrawCount[curFboIndex];
10536
10537 if (use.closeRenderPassAfterUse)
10538 {
10539 // Close the render pass without accidentally incurring additional barriers.
10540 curFboIndex = 1 - curFboIndex;
10541 glBindFramebuffer(GL_FRAMEBUFFER, fbo[curFboIndex]);
10542 }
10543 }
10544
10545 // Make sure the transfer operations below aren't reordered with the rendering above and thus
10546 // introduce additional synchronization.
10547 glFinish();
10548
10549 for (uint32_t i = 0; i < 2; ++i)
10550 {
10551 const GLColor kExpectedColor(63 * std::min(4u, fboDrawCount[i]),
10552 31 * std::min(8u, fboDrawCount[i]), 0, 255);
10553
10554 glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
10555 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor);
10556 }
10557 }
10558
10559 // Test synchronization when a texture is used in different shader stages after data upload.
10560 //
10561 // - Use in VS
10562 // - Use in FS
TEST_P(Texture2DTest,UploadThenVSThenFS)10563 TEST_P(Texture2DTest, UploadThenVSThenFS)
10564 {
10565 testUploadThenUseInDifferentStages({
10566 {GL_VERTEX_SHADER, false},
10567 {GL_FRAGMENT_SHADER, false},
10568 });
10569 }
10570
10571 // Test synchronization when a texture is used in different shader stages after data upload.
10572 //
10573 // - Use in VS
10574 // - Break render pass
10575 // - Use in FS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFS)10576 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFS)
10577 {
10578 testUploadThenUseInDifferentStages({
10579 {GL_VERTEX_SHADER, true},
10580 {GL_FRAGMENT_SHADER, false},
10581 });
10582 }
10583
10584 // Test synchronization when a texture is used in different shader stages after data upload.
10585 //
10586 // - Use in FS
10587 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenVS)10588 TEST_P(Texture2DTest, UploadThenFSThenVS)
10589 {
10590 testUploadThenUseInDifferentStages({
10591 {GL_FRAGMENT_SHADER, false},
10592 {GL_VERTEX_SHADER, false},
10593 });
10594 }
10595
10596 // Test synchronization when a texture is used in different shader stages after data upload.
10597 //
10598 // - Use in FS
10599 // - Break render pass
10600 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenVS)10601 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenVS)
10602 {
10603 testUploadThenUseInDifferentStages({
10604 {GL_FRAGMENT_SHADER, true},
10605 {GL_VERTEX_SHADER, false},
10606 });
10607 }
10608
10609 // Test synchronization when a texture is used in different shader stages after data upload.
10610 //
10611 // - Use in VS
10612 // - Use in FS
10613 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenFSThenVS)10614 TEST_P(Texture2DTest, UploadThenVSThenFSThenVS)
10615 {
10616 testUploadThenUseInDifferentStages({
10617 {GL_VERTEX_SHADER, false},
10618 {GL_FRAGMENT_SHADER, false},
10619 {GL_VERTEX_SHADER, false},
10620 });
10621 }
10622
10623 // Test synchronization when a texture is used in different shader stages after data upload.
10624 //
10625 // - Use in VS
10626 // - Break render pass
10627 // - Use in FS
10628 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFSThenVS)10629 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFSThenVS)
10630 {
10631 testUploadThenUseInDifferentStages({
10632 {GL_VERTEX_SHADER, true},
10633 {GL_FRAGMENT_SHADER, false},
10634 {GL_VERTEX_SHADER, false},
10635 });
10636 }
10637
10638 // Test synchronization when a texture is used in different shader stages after data upload.
10639 //
10640 // - Use in VS
10641 // - Break render pass
10642 // - Use in FS
10643 // - Break render pass
10644 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFSThenNewRPThenVS)10645 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFSThenNewRPThenVS)
10646 {
10647 testUploadThenUseInDifferentStages({
10648 {GL_VERTEX_SHADER, true},
10649 {GL_FRAGMENT_SHADER, true},
10650 {GL_VERTEX_SHADER, false},
10651 });
10652 }
10653
10654 // Test synchronization when a texture is used in different shader stages after data upload.
10655 //
10656 // - Use in FS
10657 // - Use in VS
10658 // - Break render pass
10659 // - Use in FS
TEST_P(Texture2DTest,UploadThenFSThenVSThenNewRPThenFS)10660 TEST_P(Texture2DTest, UploadThenFSThenVSThenNewRPThenFS)
10661 {
10662 testUploadThenUseInDifferentStages({
10663 {GL_FRAGMENT_SHADER, false},
10664 {GL_VERTEX_SHADER, true},
10665 {GL_FRAGMENT_SHADER, false},
10666 });
10667 }
10668
10669 // Test synchronization when a texture is used in different shader stages after data upload.
10670 //
10671 // - Use in FS
10672 // - Break render pass
10673 // - Use in VS
10674 // - Use in FS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenVSThenFS)10675 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenVSThenFS)
10676 {
10677 testUploadThenUseInDifferentStages({
10678 {GL_FRAGMENT_SHADER, true},
10679 {GL_VERTEX_SHADER, false},
10680 {GL_FRAGMENT_SHADER, false},
10681 });
10682 }
10683
10684 // Test synchronization when a texture is used in different shader stages after data upload.
10685 //
10686 // - Use in FS
10687 // - Break render pass
10688 // - Use in FS
10689 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenFSThenVS)10690 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenFSThenVS)
10691 {
10692 testUploadThenUseInDifferentStages({
10693 {GL_FRAGMENT_SHADER, true},
10694 {GL_FRAGMENT_SHADER, false},
10695 {GL_VERTEX_SHADER, false},
10696 });
10697 }
10698
10699 // Test that clears due to emulated formats are to the correct level given non-zero base level.
TEST_P(Texture2DTestES3,NonZeroBaseEmulatedClear)10700 TEST_P(Texture2DTestES3, NonZeroBaseEmulatedClear)
10701 {
10702 // Tests behavior of the Vulkan backend with emulated formats.
10703 ANGLE_SKIP_TEST_IF(!IsVulkan());
10704
10705 // TODO(http://anglebug.com/8036): Skip when using VMA image suballocation on Linux/Intel.
10706 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() &&
10707 getEGLWindow()->isFeatureEnabled(Feature::UseVmaForImageSuballocation));
10708
10709 // This test assumes GL_RGB is always emulated, which overrides the
10710 // Feature::AllocateNonZeroMemory memory feature, clearing the memory to zero. However, if the
10711 // format is *not* emulated and the feature Feature::AllocateNonZeroMemory is enabled, the
10712 // texture memory will contain non-zero memory, which means the color is not black (causing the
10713 // test to fail).
10714 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
10715
10716 setUpProgram();
10717
10718 glActiveTexture(GL_TEXTURE0);
10719 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10720 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
10721 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
10722 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 4, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
10723 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
10724 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
10725 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
10726 EXPECT_GL_NO_ERROR();
10727
10728 drawQuad(mProgram, "position", 0.5f);
10729
10730 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
10731 }
10732
10733 // Test that uploading data to buffer that's in use then using it as PBO to update a texture works.
TEST_P(Texture2DTestES3,UseAsUBOThenUpdateThenAsPBO)10734 TEST_P(Texture2DTestES3, UseAsUBOThenUpdateThenAsPBO)
10735 {
10736 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
10737 GLColor::red};
10738 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
10739 GLColor::blue};
10740
10741 GLBuffer buffer;
10742 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
10743 glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_COPY);
10744 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
10745 EXPECT_GL_NO_ERROR();
10746
10747 constexpr char kVerifyUBO[] = R"(#version 300 es
10748 precision mediump float;
10749 uniform block {
10750 uvec4 data;
10751 } ubo;
10752 out vec4 colorOut;
10753 void main()
10754 {
10755 if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
10756 colorOut = vec4(0, 1.0, 0, 1.0);
10757 else
10758 colorOut = vec4(1.0, 0, 0, 1.0);
10759 })";
10760
10761 ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
10762 drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
10763 EXPECT_GL_NO_ERROR();
10764
10765 // Update buffer data
10766 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
10767 EXPECT_GL_NO_ERROR();
10768
10769 // Bind as PBO
10770 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
10771 EXPECT_GL_NO_ERROR();
10772
10773 // Upload from PBO to texture
10774 GLTexture tex;
10775 glBindTexture(GL_TEXTURE_2D, tex);
10776 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
10777 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10778 EXPECT_GL_NO_ERROR();
10779
10780 // Make sure uniform data is correct.
10781 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10782
10783 // Make sure the texture data is correct.
10784 GLFramebuffer fbo;
10785 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10786 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10787 EXPECT_GL_NO_ERROR();
10788 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10789
10790 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10791 }
10792
10793 // Test if the RenderTargetCache is updated when the TextureStorage object is freed
TEST_P(Texture2DTestES3,UpdateRenderTargetCacheOnDestroyTexStorage)10794 TEST_P(Texture2DTestES3, UpdateRenderTargetCacheOnDestroyTexStorage)
10795 {
10796 ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
10797 const GLenum attachments[] = {GL_COLOR_ATTACHMENT0};
10798
10799 GLTexture tex;
10800 GLFramebuffer fb;
10801 glBindTexture(GL_TEXTURE_2D, tex);
10802 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 100, 1);
10803 glBindFramebuffer(GL_FRAMEBUFFER, fb);
10804 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10805 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments);
10806 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
10807 drawQuad(drawRed, essl3_shaders::PositionAttrib(), 1.0f);
10808 EXPECT_GL_NO_ERROR();
10809
10810 EXPECT_PIXEL_RECT_EQ(0, 0, 100, 1, GLColor::red);
10811 }
10812
10813 // Test that we can allocate at least 4096 images, which is the maximum allocation count on some
10814 // platforms. Image suballocation should enable us to allocate more than this limit.
TEST_P(Texture2DTestES3,AllocateMoreThan4096Textures)10815 TEST_P(Texture2DTestES3, AllocateMoreThan4096Textures)
10816 {
10817 ANGLE_SKIP_TEST_IF(!getEGLWindow()->isFeatureEnabled(Feature::UseVmaForImageSuballocation));
10818
10819 // The test is skipped when AllocateNonZeroMemory is enabled due to risk of timeout.
10820 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
10821
10822 constexpr size_t kTextureCount = 8000;
10823 std::vector<GLTexture> textures(kTextureCount);
10824 for (auto &texture : textures)
10825 {
10826 glBindTexture(GL_TEXTURE_2D, texture);
10827 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10828 }
10829 EXPECT_GL_NO_ERROR();
10830 }
10831
10832 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
10833 // texture is output.
TEST_P(Texture2DIntegerTestES3,IntegerTextureNonZeroBaseLevel)10834 TEST_P(Texture2DIntegerTestES3, IntegerTextureNonZeroBaseLevel)
10835 {
10836 // http://anglebug.com/3478
10837 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
10838
10839 glActiveTexture(GL_TEXTURE0);
10840 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10841 int width = getWindowWidth();
10842 int height = getWindowHeight();
10843 GLColor color = GLColor::green;
10844 std::vector<GLColor> pixels(width * height, color);
10845 GLint baseLevel = 1;
10846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel);
10847 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10848 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10849 glTexImage2D(GL_TEXTURE_2D, baseLevel, GL_RGBA8UI, width, height, 0, GL_RGBA_INTEGER,
10850 GL_UNSIGNED_BYTE, pixels.data());
10851
10852 setUpProgram();
10853 glUseProgram(mProgram);
10854 glUniform1i(mTexture2DUniformLocation, 0);
10855 drawQuad(mProgram, "position", 0.5f);
10856
10857 EXPECT_GL_NO_ERROR();
10858 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
10859 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
10860 }
10861
10862 // Draw a quad with an integer cube texture with a non-zero base level, and test that the color of
10863 // the texture is output.
TEST_P(TextureCubeIntegerTestES3,IntegerCubeTextureNonZeroBaseLevel)10864 TEST_P(TextureCubeIntegerTestES3, IntegerCubeTextureNonZeroBaseLevel)
10865 {
10866 // All output checks returned black, rather than the texture color.
10867 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
10868
10869 glActiveTexture(GL_TEXTURE0);
10870
10871 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
10872 GLint baseLevel = 1;
10873 int width = getWindowWidth();
10874 int height = getWindowHeight();
10875 GLColor color = GLColor::green;
10876 std::vector<GLColor> pixels(width * height, color);
10877 for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
10878 {
10879 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, baseLevel, GL_RGBA8UI, width,
10880 height, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
10881 EXPECT_GL_NO_ERROR();
10882 }
10883 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, baseLevel);
10884 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10885 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10886
10887 glUseProgram(mProgram);
10888 glUniform1i(mTextureCubeUniformLocation, 0);
10889 drawQuad(mProgram, "position", 0.5f);
10890
10891 EXPECT_GL_NO_ERROR();
10892 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
10893 EXPECT_PIXEL_COLOR_EQ(width - 1, 0, color);
10894 EXPECT_PIXEL_COLOR_EQ(0, height - 1, color);
10895 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
10896 }
10897
10898 // This test sets up a cube map with four distincly colored MIP levels.
10899 // The size of the texture and the geometry is chosen such that levels 1 or 2 should be chosen at
10900 // the corners of the screen.
TEST_P(TextureCubeIntegerEdgeTestES3,IntegerCubeTextureCorner)10901 TEST_P(TextureCubeIntegerEdgeTestES3, IntegerCubeTextureCorner)
10902 {
10903 glActiveTexture(GL_TEXTURE0);
10904
10905 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
10906 int width = getWindowWidth();
10907 int height = getWindowHeight();
10908 ASSERT_EQ(width, height);
10909 GLColor color[4] = {GLColor::white, GLColor::green, GLColor::blue, GLColor::red};
10910 for (GLint level = 0; level < 4; level++)
10911 {
10912 for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
10913 {
10914 int levelWidth = (2 * width) >> level;
10915 int levelHeight = (2 * height) >> level;
10916 std::vector<GLColor> pixels(levelWidth * levelHeight, color[level]);
10917 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, GL_RGBA8UI, levelWidth,
10918 levelHeight, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
10919 EXPECT_GL_NO_ERROR();
10920 }
10921 }
10922 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10923 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10924 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 3);
10925
10926 glUseProgram(mProgram);
10927 glUniform1i(mTextureCubeUniformLocation, 0);
10928 drawQuad(mProgram, "position", 0.5f);
10929
10930 ASSERT_GL_NO_ERROR();
10931 // Check that we do not read from levels 0 or 3. Levels 1 and 2 are both acceptable.
10932 EXPECT_EQ(ReadColor(0, 0).R, 0);
10933 EXPECT_EQ(ReadColor(width - 1, 0).R, 0);
10934 EXPECT_EQ(ReadColor(0, height - 1).R, 0);
10935 EXPECT_EQ(ReadColor(width - 1, height - 1).R, 0);
10936 }
10937
10938 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
10939 // texture is output.
TEST_P(Texture2DIntegerProjectiveOffsetTestES3,NonZeroBaseLevel)10940 TEST_P(Texture2DIntegerProjectiveOffsetTestES3, NonZeroBaseLevel)
10941 {
10942 // Fails on AMD: http://crbug.com/967796
10943 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
10944
10945 glActiveTexture(GL_TEXTURE0);
10946 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10947 int width = getWindowWidth();
10948 int height = getWindowHeight();
10949 GLColor color = GLColor::green;
10950 std::vector<GLColor> pixels(width * height, color);
10951 GLint baseLevel = 1;
10952 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel);
10953 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10954 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10955 glTexImage2D(GL_TEXTURE_2D, baseLevel, GL_RGBA8UI, width, height, 0, GL_RGBA_INTEGER,
10956 GL_UNSIGNED_BYTE, pixels.data());
10957
10958 setUpProgram();
10959 glUseProgram(mProgram);
10960 glUniform1i(mTexture2DUniformLocation, 0);
10961 drawQuad(mProgram, "position", 0.5f);
10962
10963 EXPECT_GL_NO_ERROR();
10964 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
10965 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
10966 }
10967
10968 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
10969 // texture is output.
TEST_P(Texture2DArrayIntegerTestES3,NonZeroBaseLevel)10970 TEST_P(Texture2DArrayIntegerTestES3, NonZeroBaseLevel)
10971 {
10972 // Test fail: http://anglebug.com/5959
10973 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
10974
10975 glActiveTexture(GL_TEXTURE0);
10976 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
10977 int width = getWindowWidth();
10978 int height = getWindowHeight();
10979 int depth = 2;
10980 GLColor color = GLColor::green;
10981 std::vector<GLColor> pixels(width * height * depth, color);
10982 GLint baseLevel = 1;
10983 glTexImage3D(GL_TEXTURE_2D_ARRAY, baseLevel, GL_RGBA8UI, width, height, depth, 0,
10984 GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
10985 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, baseLevel);
10986 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10987 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10988
10989 drawQuad(mProgram, "position", 0.5f);
10990
10991 EXPECT_GL_NO_ERROR();
10992 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
10993 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
10994 }
10995
10996 // Draw a quad with an integer 3D texture with a non-zero base level, and test that the color of the
10997 // texture is output.
TEST_P(Texture3DIntegerTestES3,NonZeroBaseLevel)10998 TEST_P(Texture3DIntegerTestES3, NonZeroBaseLevel)
10999 {
11000 glActiveTexture(GL_TEXTURE0);
11001 glBindTexture(GL_TEXTURE_3D, mTexture3D);
11002 int width = getWindowWidth();
11003 int height = getWindowHeight();
11004 int depth = 2;
11005 GLColor color = GLColor::green;
11006 std::vector<GLColor> pixels(width * height * depth, color);
11007 GLint baseLevel = 1;
11008 glTexImage3D(GL_TEXTURE_3D, baseLevel, GL_RGBA8UI, width, height, depth, 0, GL_RGBA_INTEGER,
11009 GL_UNSIGNED_BYTE, pixels.data());
11010 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, baseLevel);
11011 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11012 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11013
11014 drawQuad(mProgram, "position", 0.5f);
11015
11016 EXPECT_GL_NO_ERROR();
11017 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
11018 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
11019 }
11020
runCompressedSubImage()11021 void PBOCompressedTextureTest::runCompressedSubImage()
11022 {
11023 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
11024 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
11025 // http://anglebug.com/4115
11026 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsDesktopOpenGL());
11027 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL());
11028
11029 if (getClientMajorVersion() < 3)
11030 {
11031 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
11032 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
11033 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_ETC2_RGB8_texture"));
11034 }
11035
11036 const GLuint width = 4u;
11037 const GLuint height = 4u;
11038
11039 setWindowWidth(width);
11040 setWindowHeight(height);
11041
11042 // Setup primary Texture
11043 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11044 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11045 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11046
11047 if (getClientMajorVersion() < 3)
11048 {
11049 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, width, height);
11050 }
11051 else
11052 {
11053 glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, width, height);
11054 }
11055 ASSERT_GL_NO_ERROR();
11056
11057 // Setup PBO and fill it with a red
11058 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
11059 glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height / 2u, kCompressedImageETC2, GL_STATIC_DRAW);
11060 ASSERT_GL_NO_ERROR();
11061
11062 // Write PBO to mTexture
11063 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_COMPRESSED_RGB8_ETC2,
11064 width * height / 2u, nullptr);
11065 ASSERT_GL_NO_ERROR();
11066
11067 setUpProgram();
11068 // Draw using PBO updated texture
11069 glUseProgram(mProgram);
11070 glUniform1i(mTexture2DUniformLocation, 0);
11071 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11072 drawQuad(mProgram, "position", 0.5f);
11073 ASSERT_GL_NO_ERROR();
11074
11075 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
11076 ASSERT_GL_NO_ERROR();
11077 }
11078
11079 // Test that uses glCompressedTexSubImage2D combined with a PBO
TEST_P(PBOCompressedTextureTest,PBOCompressedSubImage)11080 TEST_P(PBOCompressedTextureTest, PBOCompressedSubImage)
11081 {
11082 runCompressedSubImage();
11083 }
11084
11085 // Verify the row length state is ignored when using compressed tex image calls.
TEST_P(PBOCompressedTextureTest,PBOCompressedSubImageWithUnpackRowLength)11086 TEST_P(PBOCompressedTextureTest, PBOCompressedSubImageWithUnpackRowLength)
11087 {
11088 // ROW_LENGTH requires ES3 or an extension.
11089 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
11090 !IsGLExtensionEnabled("GL_EXT_unpack_subimage"));
11091
11092 glPixelStorei(GL_UNPACK_ROW_LENGTH, 1);
11093 runCompressedSubImage();
11094 }
11095
11096 class PBOCompressedTexture3DTest : public ANGLETest<>
11097 {
11098 protected:
PBOCompressedTexture3DTest()11099 PBOCompressedTexture3DTest() {}
11100 };
11101
11102 // Test that uses glCompressedTexSubImage3D combined with a PBO
11103 TEST_P(PBOCompressedTexture3DTest, 2DArray)
11104 {
11105 // We use GetTexImage to determine if the internal texture format is emulated
11106 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_get_image"));
11107
11108 const GLuint width = 4u;
11109 const GLuint height = 4u;
11110 const GLuint depth = 1u;
11111
11112 setWindowWidth(width);
11113 setWindowHeight(height);
11114
11115 // Setup primary texture as a 2DArray holding ETC2 data
11116 GLTexture texture2DArray;
11117 glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
11118 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11119 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11120 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_COMPRESSED_RGB8_ETC2, width, height, depth);
11121
11122 // If the format emulated, we can't transfer it from a PBO
11123 ANGLE_SKIP_TEST_IF(IsFormatEmulated(GL_TEXTURE_2D_ARRAY));
11124
11125 // Set up a VS that simply passes through position and texcord
11126 const char kVS[] = R"(#version 300 es
11127 in vec4 position;
11128 out vec3 texCoord;
11129
11130 void main()
11131 {
11132 gl_Position = vec4(position.xy, 0.0, 1.0);
11133 texCoord = vec3(position.xy * 0.5 + vec2(0.5), 0.0);
11134 })";
11135
11136 // and FS that pulls from the 2DArray, writing out color
11137 const char kFS[] = R"(#version 300 es
11138 precision mediump float;
11139 uniform highp sampler2DArray tex2DArray;
11140 in vec3 texCoord;
11141 out vec4 fragColor;
11142
11143 void main()
11144 {
11145 fragColor = texture(tex2DArray, texCoord);
11146 })";
11147
11148 // Compile the shaders and create the program
11149 ANGLE_GL_PROGRAM(program, kVS, kFS);
11150 ASSERT_GL_NO_ERROR();
11151
11152 // Setup PBO and fill it with a red
11153 GLBuffer pbo;
11154 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
11155 glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * depth / 2u, kCompressedImageETC2,
11156 GL_STATIC_DRAW);
11157 ASSERT_GL_NO_ERROR();
11158
11159 // Write PBO to texture2DArray
11160 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, depth,
11161 GL_COMPRESSED_RGB8_ETC2, width * height * depth / 2u, nullptr);
11162
11163 ASSERT_GL_NO_ERROR();
11164
11165 // Draw using PBO updated texture
11166 glUseProgram(program);
11167 glUniform1i(glGetUniformLocation(program, "tex2DArray"), 0);
11168 glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
11169 drawQuad(program, "position", 0.5f);
11170 ASSERT_GL_NO_ERROR();
11171
11172 // Verify the texture now contains data from the PBO
11173 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
11174 ASSERT_GL_NO_ERROR();
11175 }
11176
11177 // Test using ETC1_RGB8 with subimage updates
TEST_P(ETC1CompressedTextureTest,ETC1CompressedSubImage)11178 TEST_P(ETC1CompressedTextureTest, ETC1CompressedSubImage)
11179 {
11180 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
11181 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
11182
11183 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
11184 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
11185 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
11186
11187 const GLuint width = 4u;
11188 const GLuint height = 4u;
11189
11190 setWindowWidth(width);
11191 setWindowHeight(height);
11192
11193 // Setup primary Texture
11194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11195 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11196
11197 if (getClientMajorVersion() < 3)
11198 {
11199 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
11200 }
11201 else
11202 {
11203 glTexStorage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
11204 }
11205 ASSERT_GL_NO_ERROR();
11206
11207 // Populate a subimage of the texture
11208 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ETC1_RGB8_OES,
11209 width * height / 2u, kCompressedImageETC2);
11210 ASSERT_GL_NO_ERROR();
11211
11212 // Render and ensure we get red
11213 glUseProgram(mProgram);
11214 drawQuad(mProgram, "position", 0.5f);
11215 ASSERT_GL_NO_ERROR();
11216
11217 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
11218 ASSERT_GL_NO_ERROR();
11219 }
11220
11221 // Fully-define a NPOT compressed texture and draw; set MAX_LEVEL and draw; then increase
11222 // MAX_LEVEL and draw. This used to cause Vulkan validation errors.
TEST_P(ETC1CompressedTextureTest,ETC1CompressedImageNPOT)11223 TEST_P(ETC1CompressedTextureTest, ETC1CompressedImageNPOT)
11224 {
11225 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
11226 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
11227
11228 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
11229 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
11230
11231 const GLuint width = 5u;
11232 const GLuint height = 5u;
11233 // round up to the nearest block size
11234 const GLsizei imageSize = 8 * 8 / 2;
11235 // smallest block size
11236 const GLsizei minImageSize = 4 * 4 / 2;
11237
11238 uint8_t data[imageSize] = {0};
11239
11240 setWindowWidth(width);
11241 setWindowHeight(height);
11242
11243 // Setup primary Texture
11244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
11245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
11246 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11247 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11248
11249 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, width, height, 0, imageSize, data);
11250 ASSERT_GL_NO_ERROR();
11251
11252 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width / 2, height / 2, 0,
11253 minImageSize, data);
11254 ASSERT_GL_NO_ERROR();
11255
11256 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_ETC1_RGB8_OES, width / 4, height / 4, 0,
11257 minImageSize, data);
11258 ASSERT_GL_NO_ERROR();
11259
11260 glUseProgram(mProgram);
11261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
11262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
11263 drawQuad(mProgram, "position", 0.5f);
11264 ASSERT_GL_NO_ERROR();
11265
11266 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
11267 drawQuad(mProgram, "position", 0.5f);
11268 ASSERT_GL_NO_ERROR();
11269 }
11270
11271 // Define two NPOT compressed textures, set MAX_LEVEL, draw, and swap buffers
11272 // with the two textures. This used to cause release of staging buffers
11273 // that have not been flushed.
TEST_P(ETC1CompressedTextureTest,ETC1CompressedImageDraws)11274 TEST_P(ETC1CompressedTextureTest, ETC1CompressedImageDraws)
11275 {
11276 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
11277 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
11278
11279 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
11280 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
11281
11282 const GLuint width = 384u;
11283 const GLuint height = 384u;
11284 // round up to the nearest block size
11285 const GLsizei imageSize = width * height / 2;
11286
11287 uint8_t data[imageSize] = {0};
11288
11289 setWindowWidth(width);
11290 setWindowHeight(height);
11291
11292 const GLuint smallerWidth = 384u;
11293 const GLuint smallerHeight = 320u;
11294 // round up to the nearest block size
11295 const GLsizei smallerImageSize = smallerWidth * smallerHeight / 2;
11296
11297 // Setup primary Texture
11298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
11299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
11300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11302
11303 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, smallerWidth, smallerHeight, 0,
11304 smallerImageSize, data);
11305 ASSERT_GL_NO_ERROR();
11306
11307 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 192, 160, 0, 15360, data);
11308 ASSERT_GL_NO_ERROR();
11309
11310 GLTexture largerTexture;
11311 glBindTexture(GL_TEXTURE_2D, largerTexture);
11312
11313 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, width, height, 0, imageSize, data);
11314 ASSERT_GL_NO_ERROR();
11315
11316 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 192, 192, 0, 18432, data);
11317 ASSERT_GL_NO_ERROR();
11318
11319 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11320
11321 glUseProgram(mProgram);
11322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
11323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
11324 drawQuad(mProgram, "position", 0.5f);
11325 ASSERT_GL_NO_ERROR();
11326 swapBuffers();
11327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
11328 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
11329 drawQuad(mProgram, "position", 0.5f);
11330 ASSERT_GL_NO_ERROR();
11331 swapBuffers();
11332
11333 glBindTexture(GL_TEXTURE_2D, largerTexture);
11334
11335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
11336 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
11337 drawQuad(mProgram, "position", 0.5f);
11338 ASSERT_GL_NO_ERROR();
11339 swapBuffers();
11340
11341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
11342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
11343 drawQuad(mProgram, "position", 0.5f);
11344 ASSERT_GL_NO_ERROR();
11345 swapBuffers();
11346
11347 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11348
11349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
11350 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
11351 drawQuad(mProgram, "position", 0.5f);
11352 swapBuffers();
11353 ASSERT_GL_NO_ERROR();
11354 }
11355
11356 // Fully-define a compressed texture and draw; then decrease MAX_LEVEL and draw; then increase
11357 // MAX_LEVEL and draw. This used to cause Vulkan validation errors.
TEST_P(ETC1CompressedTextureTest,ETC1ShrinkThenGrowMaxLevels)11358 TEST_P(ETC1CompressedTextureTest, ETC1ShrinkThenGrowMaxLevels)
11359 {
11360 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
11361 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
11362
11363 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
11364 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
11365
11366 const GLuint width = 4u;
11367 const GLuint height = 4u;
11368
11369 setWindowWidth(width);
11370 setWindowHeight(height);
11371
11372 // Setup primary Texture
11373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11375
11376 if (getClientMajorVersion() < 3)
11377 {
11378 glTexStorage2DEXT(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, width, height);
11379 }
11380 else
11381 {
11382 glTexStorage2D(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, width, height);
11383 }
11384 ASSERT_GL_NO_ERROR();
11385
11386 // Populate a subimage of the texture
11387 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ETC1_RGB8_OES,
11388 width * height / 2u, kCompressedImageETC2);
11389 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, width / 2, height / 2, GL_ETC1_RGB8_OES,
11390 width * height / 2u, kCompressedImageETC2);
11391 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, width / 4, height / 4, GL_ETC1_RGB8_OES,
11392 width * height / 2u, kCompressedImageETC2);
11393 ASSERT_GL_NO_ERROR();
11394
11395 // Set MAX_LEVEL to 2 (the highest level)
11396 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
11397
11398 // Render and ensure we get red
11399 glUseProgram(mProgram);
11400 drawQuad(mProgram, "position", 0.5f);
11401 ASSERT_GL_NO_ERROR();
11402 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
11403 ASSERT_GL_NO_ERROR();
11404
11405 // Decrease MAX_LEVEL to 0, render, and ensure we still get red
11406 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
11407 drawQuad(mProgram, "position", 0.5f);
11408 ASSERT_GL_NO_ERROR();
11409 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
11410 ASSERT_GL_NO_ERROR();
11411
11412 // Increase MAX_LEVEL back to 2, render, and ensure we still get red
11413 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
11414 drawQuad(mProgram, "position", 0.5f);
11415 ASSERT_GL_NO_ERROR();
11416 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
11417 ASSERT_GL_NO_ERROR();
11418 }
11419
11420 class TextureBufferTestES31 : public ANGLETest<>
11421 {
11422 protected:
TextureBufferTestES31()11423 TextureBufferTestES31() {}
11424 };
11425
11426 // Test that mutating a buffer attached to a texture returns correct results in query.
TEST_P(TextureBufferTestES31,QueryWidthAfterBufferResize)11427 TEST_P(TextureBufferTestES31, QueryWidthAfterBufferResize)
11428 {
11429 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
11430
11431 constexpr GLint kInitialSize = 128;
11432 constexpr std::array<GLint, 4> kModifiedSizes = {96, 192, 32, 256};
11433
11434 GLTexture texture;
11435 glBindTexture(GL_TEXTURE_BUFFER, texture);
11436
11437 GLBuffer buffer;
11438 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
11439 glBufferData(GL_TEXTURE_BUFFER, kInitialSize, nullptr, GL_STATIC_DRAW);
11440
11441 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
11442 ASSERT_GL_NO_ERROR();
11443
11444 GLint queryResult = 0;
11445 glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
11446 ASSERT_GL_NO_ERROR();
11447 EXPECT_EQ(queryResult, kInitialSize / 4);
11448
11449 for (GLint modifiedSize : kModifiedSizes)
11450 {
11451 glBufferData(GL_TEXTURE_BUFFER, modifiedSize, nullptr, GL_STATIC_DRAW);
11452 glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
11453 ASSERT_GL_NO_ERROR();
11454 EXPECT_EQ(queryResult, modifiedSize / 4);
11455 }
11456 }
11457
11458 // Test that glTexBufferEXT can be used in two draw calls.
11459 // Covers a bug where TextureVk::setBuffer releases buffer views and doesn't init them.
TEST_P(TextureBufferTestES31,TexBufferDrawTwice)11460 TEST_P(TextureBufferTestES31, TexBufferDrawTwice)
11461 {
11462 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
11463
11464 // TODO(http://anglebug.com/5832): Claims to support GL_OES_texture_buffer, but fails
11465 // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported".
11466 ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
11467
11468 const std::array<GLColor, 1> kTexData = {GLColor::red};
11469
11470 GLBuffer buffer;
11471 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
11472 glBufferData(GL_TEXTURE_BUFFER, sizeof(kTexData), kTexData.data(), GL_DYNAMIC_DRAW);
11473 EXPECT_GL_NO_ERROR();
11474
11475 constexpr char kSamplerBuffer[] = R"(#version 310 es
11476 #extension GL_OES_texture_buffer : require
11477 precision mediump float;
11478 uniform highp samplerBuffer s;
11479 out vec4 colorOut;
11480 void main()
11481 {
11482 colorOut = texelFetch(s, 0);
11483 })";
11484
11485 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kSamplerBuffer);
11486
11487 // Draw once
11488 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
11489 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
11490 EXPECT_GL_NO_ERROR();
11491
11492 // Draw twice
11493 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
11494 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
11495 EXPECT_GL_NO_ERROR();
11496
11497 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11498 }
11499
11500 // Test that uploading data to buffer that's in use then using it as texture buffer works.
TEST_P(TextureBufferTestES31,UseAsUBOThenUpdateThenAsTextureBuffer)11501 TEST_P(TextureBufferTestES31, UseAsUBOThenUpdateThenAsTextureBuffer)
11502 {
11503 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
11504
11505 // Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension
11506 // 'GL_OES_texture_buffer' is not supported". http://anglebug.com/5832
11507 ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
11508
11509 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
11510 GLColor::red};
11511 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
11512 GLColor::blue};
11513
11514 GLBuffer buffer;
11515 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
11516 glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
11517 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
11518 EXPECT_GL_NO_ERROR();
11519
11520 constexpr char kVerifyUBO[] = R"(#version 310 es
11521 precision mediump float;
11522 layout(binding = 0) uniform block {
11523 uvec4 data;
11524 } ubo;
11525 out vec4 colorOut;
11526 void main()
11527 {
11528 if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
11529 colorOut = vec4(0, 1.0, 0, 1.0);
11530 else
11531 colorOut = vec4(1.0, 0, 0, 1.0);
11532 })";
11533
11534 ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
11535 drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
11536 EXPECT_GL_NO_ERROR();
11537
11538 // Update buffer data
11539 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
11540 EXPECT_GL_NO_ERROR();
11541
11542 // Bind as texture buffer
11543 GLTexture texture;
11544 glBindTexture(GL_TEXTURE_BUFFER, texture);
11545 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
11546 EXPECT_GL_NO_ERROR();
11547
11548 constexpr char kVerifySamplerBuffer[] = R"(#version 310 es
11549 #extension GL_OES_texture_buffer : require
11550 precision mediump float;
11551 uniform highp samplerBuffer s;
11552 out vec4 colorOut;
11553 void main()
11554 {
11555 colorOut = texelFetch(s, 0);
11556 })";
11557
11558 ANGLE_GL_PROGRAM(verifySamplerBuffer, essl31_shaders::vs::Simple(), kVerifySamplerBuffer);
11559
11560 glEnable(GL_BLEND);
11561 glBlendFunc(GL_ONE, GL_ONE);
11562 drawQuad(verifySamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
11563 EXPECT_GL_NO_ERROR();
11564
11565 // Make sure both draw calls succeed
11566 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
11567 }
11568
11569 // Test that mapping a texture buffer with GL_MAP_INVALIDATE_BUFFER_BIT and writing to it works
11570 // correctly.
TEST_P(TextureBufferTestES31,MapTextureBufferInvalidateThenWrite)11571 TEST_P(TextureBufferTestES31, MapTextureBufferInvalidateThenWrite)
11572 {
11573 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
11574
11575 // TODO(http://anglebug.com/5832): Claims to support GL_OES_texture_buffer, but fails
11576 // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported".
11577 ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
11578 // TODO(http://anglebug.com/6396): The OpenGL backend doesn't correctly handle texture buffers
11579 // being invalidated when mapped.
11580 ANGLE_SKIP_TEST_IF(IsOpenGL());
11581
11582 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
11583 GLColor::red};
11584 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
11585 GLColor::blue};
11586
11587 GLBuffer buffer;
11588 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
11589 glBufferData(GL_TEXTURE_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
11590 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
11591 EXPECT_GL_NO_ERROR();
11592
11593 // Bind as texture buffer
11594 GLTexture texture;
11595 glBindTexture(GL_TEXTURE_BUFFER, texture);
11596 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
11597 EXPECT_GL_NO_ERROR();
11598
11599 constexpr char kSamplerBuffer[] = R"(#version 310 es
11600 #extension GL_OES_texture_buffer : require
11601 precision mediump float;
11602 uniform highp samplerBuffer s;
11603 out vec4 colorOut;
11604 void main()
11605 {
11606 colorOut = texelFetch(s, 0);
11607 })";
11608
11609 ANGLE_GL_PROGRAM(initialSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
11610 drawQuad(initialSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
11611 EXPECT_GL_NO_ERROR();
11612
11613 // Don't read back, so we don't break the render pass.
11614
11615 // Map the buffer and update it.
11616 void *mappedBuffer = glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(kInitialData),
11617 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
11618 memcpy(mappedBuffer, kUpdateData.data(), sizeof(kInitialData));
11619
11620 glUnmapBuffer(GL_TEXTURE_BUFFER);
11621
11622 // Draw with the updated buffer data.
11623 ANGLE_GL_PROGRAM(updateSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
11624 drawQuad(updateSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
11625 EXPECT_GL_NO_ERROR();
11626
11627 // Make sure both draw calls succeed
11628 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
11629 }
11630
11631 // Test that calling glBufferData on a buffer that is used as texture buffer still works correctly.
TEST_P(TextureBufferTestES31,TextureBufferThenBufferData)11632 TEST_P(TextureBufferTestES31, TextureBufferThenBufferData)
11633 {
11634 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
11635
11636 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
11637 GLColor::red};
11638 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
11639 GLColor::blue};
11640 // Create buffer and initialize with data
11641 GLBuffer buffer;
11642 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
11643 glBufferData(GL_TEXTURE_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
11644
11645 // Bind as texture buffer
11646 GLTexture texture;
11647 glBindTexture(GL_TEXTURE_BUFFER, texture);
11648 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
11649 EXPECT_GL_NO_ERROR();
11650
11651 constexpr char kSamplerBuffer[] = R"(#version 310 es
11652 #extension GL_OES_texture_buffer : require
11653 precision mediump float;
11654 uniform highp samplerBuffer s;
11655 out vec4 colorOut;
11656 void main()
11657 {
11658 colorOut = texelFetch(s, 0);
11659 })";
11660
11661 ANGLE_GL_PROGRAM(initialSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
11662 drawQuad(initialSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
11663
11664 // Don't read back, so we keep the original buffer busy. Issue a glBufferData call with same
11665 // size and nullptr so that the old buffer storage gets orphaned.
11666 glBufferData(GL_TEXTURE_BUFFER, sizeof(kUpdateData), nullptr, GL_DYNAMIC_DRAW);
11667 glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(kUpdateData), kUpdateData.data());
11668
11669 // Draw with the updated buffer data.
11670 ANGLE_GL_PROGRAM(updateSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
11671 drawQuad(updateSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
11672 EXPECT_GL_NO_ERROR();
11673 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
11674 }
11675
11676 // Test that the correct error is generated if texture buffer support used anyway when not enabled.
TEST_P(TextureBufferTestES31,TestErrorWhenNotEnabled)11677 TEST_P(TextureBufferTestES31, TestErrorWhenNotEnabled)
11678 {
11679 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_texture_buffer"));
11680
11681 GLTexture texture;
11682 glBindTexture(GL_TEXTURE_BUFFER, texture);
11683 ASSERT_GL_ERROR(GL_INVALID_ENUM);
11684 }
11685
11686 class CopyImageTestES31 : public ANGLETest<>
11687 {
11688 protected:
CopyImageTestES31()11689 CopyImageTestES31() {}
11690 };
11691
11692 // Test that copies between RGB formats doesn't affect the emulated alpha channel, if any.
TEST_P(CopyImageTestES31,PreserveEmulatedAlpha)11693 TEST_P(CopyImageTestES31, PreserveEmulatedAlpha)
11694 {
11695 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
11696
11697 constexpr GLsizei kSize = 1;
11698
11699 GLTexture src, dst;
11700
11701 // Set up the textures
11702 glBindTexture(GL_TEXTURE_2D, src);
11703 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, kSize, kSize);
11704
11705 const GLColor kInitColor(50, 100, 150, 200);
11706 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGB, GL_UNSIGNED_BYTE, &kInitColor);
11707
11708 glBindTexture(GL_TEXTURE_2D, dst);
11709 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8UI, kSize, kSize);
11710 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11711 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11712
11713 // Copy from src to dst
11714 glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
11715 kSize, 1);
11716
11717 // Bind dst as image
11718 glBindImageTexture(0, dst, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
11719
11720 // Create a buffer for output
11721 constexpr GLsizei kBufferSize = kSize * kSize * sizeof(uint32_t) * 4;
11722 GLBuffer buffer;
11723 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
11724 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
11725 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer);
11726
11727 constexpr char kCS[] = R"(#version 310 es
11728 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
11729 layout(rgba8ui, binding = 0) readonly uniform highp uimage2D imageIn;
11730 layout(std140, binding = 1) buffer dataOut {
11731 uvec4 data[];
11732 };
11733 void main()
11734 {
11735 uvec4 color = imageLoad(imageIn, ivec2(0));
11736 data[0] = color;
11737 })";
11738
11739 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11740 glUseProgram(program);
11741 glDispatchCompute(1, 1, 1);
11742 EXPECT_GL_NO_ERROR();
11743
11744 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
11745
11746 const uint32_t *ptr = reinterpret_cast<uint32_t *>(
11747 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
11748
11749 EXPECT_EQ(ptr[0], kInitColor.R);
11750 EXPECT_EQ(ptr[1], kInitColor.G);
11751 EXPECT_EQ(ptr[2], kInitColor.B);
11752
11753 // Expect alpha to be 1, even if the RGB format is emulated with RGBA.
11754 EXPECT_EQ(ptr[3], 1u);
11755
11756 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11757 }
11758
11759 // Verify a common pattern used by the Unreal Engine that trips up the tracer
TEST_P(CopyImageTestES31,CubeMapCopyImageSubData)11760 TEST_P(CopyImageTestES31, CubeMapCopyImageSubData)
11761 {
11762 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
11763
11764 constexpr char kVS[] =
11765 R"(#version 300 es
11766 precision mediump float;
11767 in vec3 pos;
11768 void main() {
11769 gl_Position = vec4(pos, 1.0);
11770 })";
11771
11772 constexpr char kFS[] =
11773 R"(#version 300 es
11774 precision mediump float;
11775 out vec4 color;
11776 uniform samplerCube uTex;
11777 void main(){
11778 // sample from lod 1.0
11779 color = textureLod(uTex, vec3(1.0), 1.0);
11780 })";
11781
11782 ANGLE_GL_PROGRAM(program, kVS, kFS);
11783 glUseProgram(program);
11784
11785 // Set up two cube maps, then verify we can copy between them
11786 constexpr size_t kSize = 2;
11787 constexpr int levels = 2;
11788 std::vector<GLColor> pixelsGreen(kSize * kSize, GLColor::green);
11789 std::vector<GLColor> pixelsRed(kSize * kSize, GLColor::red);
11790
11791 // Initialize src to green
11792 GLTexture texCubeSrc;
11793 glBindTexture(GL_TEXTURE_CUBE_MAP, texCubeSrc);
11794 for (int i = 0; i < levels; i++)
11795 {
11796 for (GLenum face = 0; face < 6; face++)
11797 {
11798 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, GL_RGBA, kSize >> i, kSize >> i,
11799 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsGreen.data());
11800 }
11801 }
11802 ASSERT_GL_NO_ERROR();
11803
11804 // Initialize dst to red
11805 GLTexture texCubeDst;
11806 glBindTexture(GL_TEXTURE_CUBE_MAP, texCubeDst);
11807 for (int i = 0; i < levels; i++)
11808 {
11809 for (GLenum face = 0; face < 6; face++)
11810 {
11811 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, GL_RGBA, kSize >> i, kSize >> i,
11812 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
11813 }
11814 }
11815 ASSERT_GL_NO_ERROR();
11816
11817 // Clear to blue
11818 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11819 glClear(GL_COLOR_BUFFER_BIT);
11820 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
11821
11822 // Sample from the dst texture to ensure it has the right color
11823 GLint textureLoc = glGetUniformLocation(program, "uTex");
11824 ASSERT_NE(-1, textureLoc);
11825 glUniform1i(textureLoc, 0);
11826
11827 // Draw once and sample from level 1, which is red
11828 drawQuad(program, "pos", 0.5f);
11829 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11830
11831 // Swap to trigger MEC
11832 swapBuffers();
11833
11834 // Copy level 1 from src to dst
11835 glCopyImageSubDataEXT(texCubeSrc, GL_TEXTURE_CUBE_MAP, 1, 0, 0, 0, texCubeDst,
11836 GL_TEXTURE_CUBE_MAP, 1, 0, 0, 0, kSize >> 1, kSize >> 1, 6);
11837 ASSERT_GL_NO_ERROR();
11838
11839 // Draw again and verify we get green
11840 drawQuad(program, "pos", 0.5f);
11841 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11842
11843 // Swap again to end the capture
11844 swapBuffers();
11845
11846 ASSERT_GL_NO_ERROR();
11847 }
11848
11849 class TextureChangeStorageUploadTest : public ANGLETest<>
11850 {
11851 protected:
TextureChangeStorageUploadTest()11852 TextureChangeStorageUploadTest()
11853 {
11854 setWindowWidth(256);
11855 setWindowHeight(256);
11856 setConfigRedBits(8);
11857 setConfigGreenBits(8);
11858 setConfigBlueBits(8);
11859 setConfigAlphaBits(8);
11860 }
11861
testSetUp()11862 void testSetUp() override
11863 {
11864 mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
11865 if (mProgram == 0)
11866 {
11867 FAIL() << "shader compilation failed.";
11868 }
11869
11870 glUseProgram(mProgram);
11871
11872 glClearColor(0, 0, 0, 0);
11873 glClearDepthf(0.0);
11874 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
11875
11876 glEnable(GL_BLEND);
11877 glDisable(GL_DEPTH_TEST);
11878
11879 glGenTextures(1, &mTexture);
11880 ASSERT_GL_NO_ERROR();
11881 }
11882
testTearDown()11883 void testTearDown() override
11884 {
11885 glDeleteTextures(1, &mTexture);
11886 glDeleteProgram(mProgram);
11887 }
11888
11889 GLuint mProgram;
11890 GLint mColorLocation;
11891 GLuint mTexture;
11892 };
11893
11894 // Verify that respecifying storage and re-uploading doesn't crash.
TEST_P(TextureChangeStorageUploadTest,Basic)11895 TEST_P(TextureChangeStorageUploadTest, Basic)
11896 {
11897 constexpr int kImageSize = 8; // 4 doesn't trip ASAN
11898 constexpr int kSmallerImageSize = kImageSize / 2;
11899 EXPECT_GT(kImageSize, kSmallerImageSize);
11900 EXPECT_GT(kSmallerImageSize / 2, 0);
11901
11902 std::array<GLColor, kImageSize * kImageSize> kColor;
11903
11904 glBindTexture(GL_TEXTURE_2D, mTexture);
11905 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11906 kColor.data());
11907 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSmallerImageSize, kSmallerImageSize);
11908 // need partial update to sidestep optimizations that remove the full upload
11909 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSmallerImageSize / 2, kSmallerImageSize / 2, GL_RGBA,
11910 GL_UNSIGNED_BYTE, kColor.data());
11911 EXPECT_GL_NO_ERROR();
11912 }
11913
11914 class ExtraSamplerCubeShadowUseTest : public ANGLETest<>
11915 {
11916 protected:
ExtraSamplerCubeShadowUseTest()11917 ExtraSamplerCubeShadowUseTest() : ANGLETest() {}
11918
getVertexShaderSource()11919 const char *getVertexShaderSource() { return "#version 300 es\nvoid main() {}"; }
11920
getFragmentShaderSource()11921 const char *getFragmentShaderSource()
11922 {
11923 return R"(#version 300 es
11924 precision mediump float;
11925
11926 uniform mediump samplerCube var_0002; // this has to be there
11927 uniform highp samplerCubeShadow var_0004; // this has to be a cube shadow sampler
11928 out vec4 color;
11929 void main() {
11930
11931 vec4 var_0031 = texture(var_0002, vec3(1,1,1));
11932 ivec2 size = textureSize(var_0004, 0) ;
11933 var_0031.x += float(size.y);
11934
11935 color = var_0031;
11936 })";
11937 }
11938
testSetUp()11939 void testSetUp() override
11940 {
11941 mProgram = CompileProgram(getVertexShaderSource(), getFragmentShaderSource());
11942 if (mProgram == 0)
11943 {
11944 FAIL() << "shader compilation failed.";
11945 }
11946 glUseProgram(mProgram);
11947 ASSERT_GL_NO_ERROR();
11948 }
11949
testTearDown()11950 void testTearDown() override { glDeleteProgram(mProgram); }
11951
11952 GLuint mProgram;
11953 };
11954
TEST_P(ExtraSamplerCubeShadowUseTest,Basic)11955 TEST_P(ExtraSamplerCubeShadowUseTest, Basic)
11956 {
11957 glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
11958 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11959 }
11960
11961 // Tests covering RBG->RGBA emulation path
11962 class RGBTextureBufferTestES31 : public ANGLETest<>
11963 {
11964 protected:
RGBTextureBufferTestES31()11965 RGBTextureBufferTestES31()
11966 {
11967 setWindowWidth(128);
11968 setWindowHeight(128);
11969 setConfigRedBits(8);
11970 setConfigGreenBits(8);
11971 setConfigBlueBits(8);
11972 setConfigAlphaBits(8);
11973 }
11974 void TestInt(GLuint format);
11975 };
11976
SetupTextureBufferDrawProgram(GLProgram & program,GLuint format)11977 void SetupTextureBufferDrawProgram(GLProgram &program, GLuint format)
11978 {
11979 constexpr char kVS[] = R"(#version 310 es
11980 precision highp float;
11981 in vec4 inputAttribute;
11982
11983 void main()
11984 {
11985 gl_Position = inputAttribute;
11986 })";
11987
11988 if (format == GL_RGB32UI)
11989 {
11990 constexpr char kFS[] = R"(#version 310 es
11991 #extension GL_EXT_texture_buffer : require
11992 precision mediump float;
11993 uniform highp usamplerBuffer tex;
11994 layout(location = 0) out mediump vec4 color;
11995
11996 void main()
11997 {
11998 uvec4 v = texelFetch(tex, 1);
11999 color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
12000 })";
12001 program.makeRaster(kVS, kFS);
12002 }
12003 if (format == GL_RGB32I)
12004 {
12005 constexpr char kFS[] = R"(#version 310 es
12006 #extension GL_EXT_texture_buffer : require
12007 precision mediump float;
12008 uniform highp isamplerBuffer tex;
12009 layout(location = 0) out mediump vec4 color;
12010
12011 void main()
12012 {
12013 ivec4 v = texelFetch(tex, 1);
12014 color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
12015 })";
12016 program.makeRaster(kVS, kFS);
12017 }
12018 if (format == GL_RGB32F)
12019 {
12020 constexpr char kFS[] = R"(#version 310 es
12021 #extension GL_EXT_texture_buffer : require
12022 precision mediump float;
12023 uniform highp samplerBuffer tex;
12024 layout(location = 0) out mediump vec4 color;
12025
12026 void main()
12027 {
12028 vec4 v = texelFetch(tex, 1);
12029 color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
12030 })";
12031 program.makeRaster(kVS, kFS);
12032 }
12033 ASSERT_TRUE(program.valid());
12034 }
12035
TestInt(GLuint format)12036 void RGBTextureBufferTestES31::TestInt(GLuint format)
12037 {
12038 const GLint pixelSize = sizeof(GLuint) * 3;
12039
12040 // Offset must be aligned to GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT (16, 64, ...)
12041 GLint offsetAlignment = 0;
12042 glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment);
12043 ASSERT(offsetAlignment % sizeof(GLuint) == 0);
12044 GLint byteOffset = ((pixelSize * 2) / offsetAlignment + 1) * offsetAlignment;
12045
12046 GLint intOffset = byteOffset / sizeof(GLuint);
12047
12048 std::vector<GLuint> texData(intOffset + 3 * 2);
12049
12050 // first texel(1) col
12051 GLColor col = MakeGLColor(11, 22, 33, 255);
12052 texData[3] = col.R;
12053 texData[4] = col.G;
12054 texData[5] = col.B;
12055
12056 // second texel(1) col2
12057 GLColor col2 = MakeGLColor(44, 55, 66, 255);
12058 texData[intOffset + 3] = col2.R;
12059 texData[intOffset + 4] = col2.G;
12060 texData[intOffset + 5] = col2.B;
12061
12062 GLTexture texture;
12063 glBindTexture(GL_TEXTURE_BUFFER, texture);
12064
12065 GLBuffer buffer;
12066 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
12067 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * texData.size(), texData.data(),
12068 GL_STATIC_DRAW);
12069 ASSERT_GL_NO_ERROR();
12070
12071 GLProgram program;
12072 SetupTextureBufferDrawProgram(program, format);
12073
12074 glTexBufferEXT(GL_TEXTURE_BUFFER, format, buffer);
12075
12076 drawQuad(program.get(), "inputAttribute", 0.5f);
12077 ASSERT_GL_NO_ERROR();
12078 EXPECT_PIXEL_COLOR_NEAR(0, 0, col, 1);
12079
12080 glTexBufferRangeEXT(GL_TEXTURE_BUFFER, format, buffer, byteOffset, pixelSize * 2);
12081 ASSERT_GL_NO_ERROR();
12082 drawQuad(program.get(), "inputAttribute", 0.5f);
12083 EXPECT_PIXEL_COLOR_NEAR(0, 0, col2, 1);
12084
12085 // Now update the buffer to check the converted data also gets updated.
12086 GLColor colUpd = MakeGLColor(77, 88, 99, 255);
12087 GLuint texDataUpd[] = {0, 0, 0, colUpd.R, colUpd.G, colUpd.B}; // second texel(1) colUpd
12088 glBufferSubData(GL_TEXTURE_BUFFER, byteOffset, sizeof(texDataUpd), texDataUpd);
12089 ASSERT_GL_NO_ERROR();
12090 drawQuad(program.get(), "inputAttribute", 0.5f);
12091 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd, 1);
12092
12093 // Update with glMapBuffer (hits a different code path...)
12094 GLColor colUpd2 = MakeGLColor(111, 122, 133, 255);
12095 GLuint texDataUpd2[] = {0, 0, 0, colUpd2.R, colUpd2.G, colUpd2.B}; // second texel(1) colUpd2
12096 void *mappedBuffer =
12097 glMapBufferRange(GL_TEXTURE_BUFFER, byteOffset, sizeof(texDataUpd2), GL_MAP_WRITE_BIT);
12098 memcpy(mappedBuffer, texDataUpd2, sizeof(texDataUpd2));
12099 glUnmapBuffer(GL_TEXTURE_BUFFER);
12100 ASSERT_GL_NO_ERROR();
12101 drawQuad(program.get(), "inputAttribute", 0.5f);
12102 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd2, 1);
12103 }
12104
12105 // Tests GL_RGB32UI texture buffer
TEST_P(RGBTextureBufferTestES31,Uint)12106 TEST_P(RGBTextureBufferTestES31, Uint)
12107 {
12108 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
12109
12110 TestInt(GL_RGB32UI);
12111 }
12112
12113 // Tests GL_RGB32I texture buffer
TEST_P(RGBTextureBufferTestES31,Sint)12114 TEST_P(RGBTextureBufferTestES31, Sint)
12115 {
12116 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
12117
12118 TestInt(GL_RGB32I);
12119 }
12120
12121 // Tests GL_RGB32F texture buffer
TEST_P(RGBTextureBufferTestES31,Float)12122 TEST_P(RGBTextureBufferTestES31, Float)
12123 {
12124 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
12125
12126 // first texel(1) col
12127 GLColor col = MakeGLColor(11, 22, 33, 255);
12128 GLfloat texData[6]{};
12129 texData[3] = col.R;
12130 texData[4] = col.G;
12131 texData[5] = col.B;
12132
12133 GLTexture texture;
12134 glBindTexture(GL_TEXTURE_BUFFER, texture);
12135
12136 GLBuffer buffer;
12137 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
12138 glBufferData(GL_TEXTURE_BUFFER, sizeof(texData), texData, GL_STATIC_DRAW);
12139 ASSERT_GL_NO_ERROR();
12140
12141 GLProgram program;
12142 SetupTextureBufferDrawProgram(program, GL_RGB32F);
12143
12144 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGB32F, buffer);
12145
12146 drawQuad(program.get(), "inputAttribute", 0.5f);
12147 ASSERT_GL_NO_ERROR();
12148 EXPECT_PIXEL_COLOR_NEAR(0, 0, col, 1);
12149
12150 // Now update the buffer to check the converted data also gets updated.
12151 GLColor colUpd = MakeGLColor(77, 88, 99, 255);
12152 GLfloat texDataUpd[6]{};
12153 texDataUpd[3] = colUpd.R;
12154 texDataUpd[4] = colUpd.G;
12155 texDataUpd[5] = colUpd.B;
12156 glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(texDataUpd), texDataUpd);
12157 ASSERT_GL_NO_ERROR();
12158 drawQuad(program.get(), "inputAttribute", 0.5f);
12159 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd, 1);
12160
12161 // Update with glMapBuffer (hits a different code path...)
12162 GLColor colUpd2 = MakeGLColor(111, 122, 133, 255);
12163 GLfloat texDataUpd2[6]{};
12164 texDataUpd2[3] = colUpd2.R;
12165 texDataUpd2[4] = colUpd2.G;
12166 texDataUpd2[5] = colUpd2.B;
12167 void *mappedBuffer =
12168 glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(texDataUpd2), GL_MAP_WRITE_BIT);
12169 memcpy(mappedBuffer, texDataUpd2, sizeof(texDataUpd2));
12170 glUnmapBuffer(GL_TEXTURE_BUFFER);
12171 ASSERT_GL_NO_ERROR();
12172 drawQuad(program.get(), "inputAttribute", 0.5f);
12173 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd2, 1);
12174 }
12175
SetupSSBOProgram(GLProgram & program)12176 void SetupSSBOProgram(GLProgram &program)
12177 {
12178 constexpr char kVS[] = R"(#version 310 es
12179 precision highp float;
12180 in vec4 inputAttribute;
12181
12182 void main()
12183 {
12184 gl_Position = inputAttribute;
12185 })";
12186
12187 constexpr char kFS[] = R"(#version 310 es
12188 layout(location = 0) out mediump vec4 color;
12189 layout(std140, binding = 0) buffer outBlock {
12190 uvec4 data[2]; // uvec4 to avoid padding
12191 };
12192 void main (void)
12193 {
12194 data[0] = uvec4(11u, 22u, 33u, 44u);
12195 data[1] = uvec4(55u, 66u, 0u, 0u);
12196 color = vec4(0);
12197 })";
12198
12199 program.makeRaster(kVS, kFS);
12200 ASSERT_TRUE(program.valid());
12201 }
12202
12203 // Tests RGB32 texture buffer with a SSBO write
TEST_P(RGBTextureBufferTestES31,SSBOWrite)12204 TEST_P(RGBTextureBufferTestES31, SSBOWrite)
12205 {
12206 GLProgram programSSBO;
12207 SetupSSBOProgram(programSSBO);
12208
12209 GLProgram programBufferDraw;
12210 SetupTextureBufferDrawProgram(programBufferDraw, GL_RGB32UI);
12211
12212 constexpr GLint kBufferSize = 2 * 4 * sizeof(GLuint);
12213 GLBuffer buffer;
12214 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
12215 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
12216 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize);
12217
12218 drawQuad(programSSBO.get(), "inputAttribute", 0.5f);
12219 ASSERT_GL_NO_ERROR();
12220
12221 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
12222
12223 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGB32UI, buffer);
12224 drawQuad(programBufferDraw.get(), "inputAttribute", 0.5f);
12225 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(44, 55, 66, 255), 1);
12226 }
12227
12228 class TextureTestES31 : public ANGLETest<>
12229 {
12230 protected:
TextureTestES31()12231 TextureTestES31() {}
12232 };
12233
12234 // Verify that image uniforms can link in separable programs
TEST_P(TextureTestES31,LinkedImageUniforms)12235 TEST_P(TextureTestES31, LinkedImageUniforms)
12236 {
12237 ANGLE_SKIP_TEST_IF(!IsVulkan());
12238
12239 GLint maxVertexImageUniforms;
12240 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
12241 ANGLE_SKIP_TEST_IF(maxVertexImageUniforms == 0);
12242
12243 constexpr char kVS[] = R"(#version 310 es
12244 precision highp float;
12245 precision highp image2D;
12246 layout(binding = 0, r32f) uniform image2D img;
12247
12248 void main()
12249 {
12250 vec2 position = -imageLoad(img, ivec2(0, 0)).rr;
12251 if (gl_VertexID == 1)
12252 position = vec2(3, -1);
12253 else if (gl_VertexID == 2)
12254 position = vec2(-1, 3);
12255
12256 gl_Position = vec4(position, 0, 1);
12257 })";
12258
12259 constexpr char kFS[] = R"(#version 310 es
12260 precision highp float;
12261 precision highp image2D;
12262 layout(binding = 0, r32f) uniform image2D img;
12263 layout(location = 0) out vec4 color;
12264
12265 void main()
12266 {
12267 color = imageLoad(img, ivec2(0, 0));
12268 })";
12269
12270 ANGLE_GL_PROGRAM(program, kVS, kFS);
12271
12272 GLTexture texture;
12273 GLfloat value = 1.0;
12274
12275 glBindTexture(GL_TEXTURE_2D, texture);
12276 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
12277 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &value);
12278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12280
12281 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
12282
12283 glUseProgram(program);
12284 glDrawArrays(GL_TRIANGLES, 0, 3);
12285
12286 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12287 ASSERT_GL_NO_ERROR();
12288 }
12289
12290 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
12291 // tests should be run against.
12292 #define ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB() \
12293 ES2_OPENGL().enable(Feature::EmulateCopyTexImage2D), \
12294 ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2D)
12295 #define ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB() \
12296 ES3_OPENGL().enable(Feature::EmulateCopyTexImage2D), \
12297 ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2D)
12298 #define ES2_EMULATE_COPY_TEX_IMAGE() \
12299 ES2_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers), \
12300 ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers)
12301 #define ES3_EMULATE_COPY_TEX_IMAGE() \
12302 ES3_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers), \
12303 ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers)
12304 ANGLE_INSTANTIATE_TEST(Texture2DTest,
12305 ANGLE_ALL_TEST_PLATFORMS_ES2,
12306 ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
12307 ES2_EMULATE_COPY_TEX_IMAGE());
12308 ANGLE_INSTANTIATE_TEST_ES2(TextureCubeTest);
12309 ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale);
12310 ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest);
12311 ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayTest);
12312 ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayAsFunctionParameterTest);
12313
12314 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3);
12315 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3,
12316 ES3_VULKAN().enable(Feature::AllocateNonZeroMemory),
12317 ES3_VULKAN().enable(Feature::ForceFallbackFormat));
12318
12319 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3YUV);
12320 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3YUV,
12321 ES3_VULKAN().enable(Feature::PreferLinearFilterForYUV));
12322
12323 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3RobustInit);
12324 ANGLE_INSTANTIATE_TEST_ES3(Texture2DTestES3RobustInit);
12325
12326 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES31PPO);
12327 ANGLE_INSTANTIATE_TEST_ES31(Texture2DTestES31PPO);
12328
12329 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DBaseMaxTestES3);
12330 ANGLE_INSTANTIATE_TEST_ES3(Texture2DBaseMaxTestES3);
12331
12332 ANGLE_INSTANTIATE_TEST_ES2(Texture3DTestES2);
12333
12334 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DTestES3);
12335 ANGLE_INSTANTIATE_TEST_ES3(Texture3DTestES3);
12336
12337 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerAlpha1TestES3);
12338 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerAlpha1TestES3);
12339
12340 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DUnsignedIntegerAlpha1TestES3);
12341 ANGLE_INSTANTIATE_TEST_ES3(Texture2DUnsignedIntegerAlpha1TestES3);
12342
12343 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShadowSamplerPlusSampler3DTestES3);
12344 ANGLE_INSTANTIATE_TEST_ES3(ShadowSamplerPlusSampler3DTestES3);
12345
12346 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SamplerTypeMixTestES3);
12347 ANGLE_INSTANTIATE_TEST_ES3(SamplerTypeMixTestES3);
12348
12349 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayTestES3);
12350 ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayTestES3);
12351
12352 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSizeTextureArrayTest);
12353 ANGLE_INSTANTIATE_TEST_ES3(TextureSizeTextureArrayTest);
12354
12355 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructTest);
12356 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAsFunctionParameterTest);
12357 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructArrayAsFunctionParameterTest);
12358 ANGLE_INSTANTIATE_TEST_ES2(SamplerInNestedStructAsFunctionParameterTest);
12359 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAndOtherVariableTest);
12360 ANGLE_INSTANTIATE_TEST_ES2(TextureAnisotropyTest);
12361 ANGLE_INSTANTIATE_TEST_ES2(TextureBorderClampTest);
12362
12363 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampTestES3);
12364 ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampTestES3);
12365
12366 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampIntegerTestES3);
12367 ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampIntegerTestES3);
12368
12369 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(TextureMirrorClampToEdgeTest);
12370
12371 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMirrorClampToEdgeTestES3);
12372 ANGLE_INSTANTIATE_TEST_ES3(TextureMirrorClampToEdgeTestES3);
12373
12374 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMirrorClampToEdgeIntegerTestES3);
12375 ANGLE_INSTANTIATE_TEST_ES3(TextureMirrorClampToEdgeIntegerTestES3);
12376
12377 ANGLE_INSTANTIATE_TEST_ES2(TextureLimitsTest);
12378
12379 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DNorm16TestES3);
12380 ANGLE_INSTANTIATE_TEST_ES3(Texture2DNorm16TestES3);
12381
12382 ANGLE_INSTANTIATE_TEST(Texture2DRGTest,
12383 ANGLE_ALL_TEST_PLATFORMS_ES2,
12384 ANGLE_ALL_TEST_PLATFORMS_ES3,
12385 ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
12386 ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
12387 ES2_EMULATE_COPY_TEX_IMAGE(),
12388 ES3_EMULATE_COPY_TEX_IMAGE());
12389
12390 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DFloatTestES3);
12391 ANGLE_INSTANTIATE_TEST_ES3(Texture2DFloatTestES3);
12392
12393 ANGLE_INSTANTIATE_TEST_ES2(Texture2DFloatTestES2);
12394
12395 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeTestES3);
12396 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeTestES3);
12397
12398 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerTestES3);
12399 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerTestES3);
12400
12401 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerTestES3);
12402 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerTestES3);
12403
12404 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerEdgeTestES3);
12405 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerEdgeTestES3);
12406
12407 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerProjectiveOffsetTestES3);
12408 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerProjectiveOffsetTestES3);
12409
12410 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayIntegerTestES3);
12411 ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayIntegerTestES3);
12412
12413 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DIntegerTestES3);
12414 ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3);
12415
12416 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest);
12417 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest);
12418 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest);
12419 ANGLE_INSTANTIATE_TEST_ES3(PBOCompressedTexture3DTest);
12420
12421 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBufferTestES31);
12422 ANGLE_INSTANTIATE_TEST_ES31(TextureBufferTestES31);
12423
12424 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureTestES31);
12425 ANGLE_INSTANTIATE_TEST_ES31(TextureTestES31);
12426
12427 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyImageTestES31);
12428 ANGLE_INSTANTIATE_TEST_ES31(CopyImageTestES31);
12429
12430 ANGLE_INSTANTIATE_TEST_ES3(TextureChangeStorageUploadTest);
12431
12432 ANGLE_INSTANTIATE_TEST_ES3(ExtraSamplerCubeShadowUseTest);
12433
12434 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DDepthStencilTestES3);
12435 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DDepthStencilTestES3,
12436 ES3_VULKAN().enable(Feature::ForceFallbackFormat));
12437
12438 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RGBTextureBufferTestES31);
12439 ANGLE_INSTANTIATE_TEST_ES31(RGBTextureBufferTestES31);
12440
12441 } // anonymous namespace
12442