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 #include <limits>
12
13 using namespace angle;
14
15 namespace
16 {
17
18 constexpr GLuint kPixelTolerance = 1u;
19 constexpr GLfloat kPixelTolerance32F = 0.01f;
20
21 // Single compressed ETC2 block of source pixels all set red
22 constexpr uint8_t kCompressedImageETC2[] = {0x7E, 0x80, 0x04, 0x7F, 0x00, 0x07, 0xE0, 0x00};
23
24 // Take a pixel, and reset the components not covered by the format to default
25 // values. In particular, the default value for the alpha component is 255
26 // (1.0 as unsigned normalized fixed point value).
27 // For legacy formats, the components may be reordered to match the color that
28 // would be created if a pixel of that format was initialized from the given color
SliceFormatColor(GLenum format,GLColor full)29 GLColor SliceFormatColor(GLenum format, GLColor full)
30 {
31 switch (format)
32 {
33 case GL_RED:
34 return GLColor(full.R, 0, 0, 255u);
35 case GL_RG:
36 return GLColor(full.R, full.G, 0, 255u);
37 case GL_RGB:
38 return GLColor(full.R, full.G, full.B, 255u);
39 case GL_RGBA:
40 return full;
41 case GL_LUMINANCE:
42 return GLColor(full.R, full.R, full.R, 255u);
43 case GL_ALPHA:
44 return GLColor(0, 0, 0, full.R);
45 case GL_LUMINANCE_ALPHA:
46 return GLColor(full.R, full.R, full.R, full.G);
47 default:
48 EXPECT_TRUE(false);
49 return GLColor::white;
50 }
51 }
52
SliceFormatColor16(GLenum format,GLColor16 full)53 GLColor16 SliceFormatColor16(GLenum format, GLColor16 full)
54 {
55 switch (format)
56 {
57 case GL_RED:
58 return GLColor16(full.R, 0, 0, 0xFFFF);
59 case GL_RG:
60 return GLColor16(full.R, full.G, 0, 0xFFFF);
61 case GL_RGB:
62 return GLColor16(full.R, full.G, full.B, 0xFFFF);
63 case GL_RGBA:
64 return full;
65 case GL_LUMINANCE:
66 return GLColor16(full.R, full.R, full.R, 0xFFFF);
67 case GL_ALPHA:
68 return GLColor16(0, 0, 0, full.R);
69 case GL_LUMINANCE_ALPHA:
70 return GLColor16(full.R, full.R, full.R, full.G);
71 default:
72 EXPECT_TRUE(false);
73 return GLColor16(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
74 }
75 }
76
77 // As above, for 32F colors
SliceFormatColor32F(GLenum format,GLColor32F full)78 GLColor32F SliceFormatColor32F(GLenum format, GLColor32F full)
79 {
80 switch (format)
81 {
82 case GL_RED:
83 return GLColor32F(full.R, 0.0f, 0.0f, 1.0f);
84 case GL_RG:
85 return GLColor32F(full.R, full.G, 0.0f, 1.0f);
86 case GL_RGB:
87 return GLColor32F(full.R, full.G, full.B, 1.0f);
88 case GL_RGBA:
89 return full;
90 case GL_LUMINANCE:
91 return GLColor32F(full.R, full.R, full.R, 1.0f);
92 case GL_ALPHA:
93 return GLColor32F(0.0f, 0.0f, 0.0f, full.R);
94 case GL_LUMINANCE_ALPHA:
95 return GLColor32F(full.R, full.R, full.R, full.G);
96 default:
97 EXPECT_TRUE(false);
98 return GLColor32F(1.0f, 1.0f, 1.0f, 1.0f);
99 }
100 }
101
102 class TexCoordDrawTest : public ANGLETest<>
103 {
104 protected:
TexCoordDrawTest()105 TexCoordDrawTest() : ANGLETest(), mProgram(0), mFramebuffer(0), mFramebufferColorTexture(0)
106 {
107 setWindowWidth(128);
108 setWindowHeight(128);
109 setConfigRedBits(8);
110 setConfigGreenBits(8);
111 setConfigBlueBits(8);
112 setConfigAlphaBits(8);
113 }
114
getVertexShaderSource()115 virtual const char *getVertexShaderSource()
116 {
117 return R"(precision highp float;
118 attribute vec4 position;
119 varying vec2 texcoord;
120
121 void main()
122 {
123 gl_Position = vec4(position.xy, 0.0, 1.0);
124 texcoord = (position.xy * 0.5) + 0.5;
125 })";
126 }
127
128 virtual const char *getFragmentShaderSource() = 0;
129
setUpProgram()130 virtual void setUpProgram()
131 {
132 const char *vertexShaderSource = getVertexShaderSource();
133 const char *fragmentShaderSource = getFragmentShaderSource();
134
135 mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
136 ASSERT_NE(0u, mProgram);
137 ASSERT_GL_NO_ERROR();
138 }
139
testSetUp()140 void testSetUp() override { setUpFramebuffer(); }
141
testTearDown()142 void testTearDown() override
143 {
144 glBindFramebuffer(GL_FRAMEBUFFER, 0);
145 glDeleteFramebuffers(1, &mFramebuffer);
146 glDeleteTextures(1, &mFramebufferColorTexture);
147 glDeleteProgram(mProgram);
148 }
149
setUpFramebuffer()150 void setUpFramebuffer()
151 {
152 // We use an FBO to work around an issue where the default framebuffer applies SRGB
153 // conversion (particularly known to happen incorrectly on Intel GL drivers). It's not
154 // clear whether this issue can even be fixed on all backends. For example GLES 3.0.4 spec
155 // section 4.4 says that the format of the default framebuffer is entirely up to the window
156 // system, so it might be SRGB, and GLES 3.0 doesn't have a "FRAMEBUFFER_SRGB" to turn off
157 // SRGB conversion like desktop GL does.
158 // TODO(oetuaho): Get rid of this if the underlying issue is fixed.
159 glGenFramebuffers(1, &mFramebuffer);
160 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
161
162 glGenTextures(1, &mFramebufferColorTexture);
163 glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
164 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
165 GL_UNSIGNED_BYTE, nullptr);
166 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
167 mFramebufferColorTexture, 0);
168 ASSERT_GL_NO_ERROR();
169 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
170 glBindTexture(GL_TEXTURE_2D, 0);
171 }
172
173 // Returns the created texture ID.
create2DTexture()174 GLuint create2DTexture()
175 {
176 GLuint texture2D;
177 glGenTextures(1, &texture2D);
178 glBindTexture(GL_TEXTURE_2D, texture2D);
179 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
180 EXPECT_GL_NO_ERROR();
181 return texture2D;
182 }
183
184 GLuint mProgram;
185 GLuint mFramebuffer;
186
187 protected:
188 GLuint mFramebufferColorTexture;
189 };
190
191 class Texture2DTest : public TexCoordDrawTest
192 {
193 protected:
Texture2DTest()194 Texture2DTest() : TexCoordDrawTest(), mTexture2D(0), mTexture2DUniformLocation(-1) {}
195
getFragmentShaderSource()196 const char *getFragmentShaderSource() override
197 {
198 return R"(precision highp float;
199 uniform sampler2D tex;
200 varying vec2 texcoord;
201
202 void main()
203 {
204 gl_FragColor = texture2D(tex, texcoord);
205 })";
206 }
207
getTextureUniformName()208 virtual const char *getTextureUniformName() { return "tex"; }
209
setUpProgram()210 void setUpProgram() override
211 {
212 TexCoordDrawTest::setUpProgram();
213 mTexture2DUniformLocation = glGetUniformLocation(mProgram, getTextureUniformName());
214 ASSERT_NE(-1, mTexture2DUniformLocation);
215 }
216
testSetUp()217 void testSetUp() override
218 {
219 TexCoordDrawTest::testSetUp();
220 mTexture2D = create2DTexture();
221
222 ASSERT_GL_NO_ERROR();
223 }
224
testTearDown()225 void testTearDown() override
226 {
227 glDeleteTextures(1, &mTexture2D);
228 TexCoordDrawTest::testTearDown();
229 }
230
231 // Tests CopyTexSubImage with floating point textures of various formats.
testFloatCopySubImage(int sourceImageChannels,int destImageChannels)232 void testFloatCopySubImage(int sourceImageChannels, int destImageChannels)
233 {
234 setUpProgram();
235
236 if (getClientMajorVersion() < 3)
237 {
238 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage") ||
239 !IsGLExtensionEnabled("GL_OES_texture_float"));
240
241 ANGLE_SKIP_TEST_IF((sourceImageChannels < 3 || destImageChannels < 3) &&
242 !IsGLExtensionEnabled("GL_EXT_texture_rg"));
243
244 ANGLE_SKIP_TEST_IF(destImageChannels == 3 &&
245 !IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"));
246
247 ANGLE_SKIP_TEST_IF(destImageChannels == 4 &&
248 !IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"));
249
250 ANGLE_SKIP_TEST_IF(destImageChannels <= 2);
251 }
252 else
253 {
254 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_color_buffer_float"));
255
256 ANGLE_SKIP_TEST_IF(destImageChannels == 3 &&
257 !IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"));
258 }
259
260 // clang-format off
261 GLfloat sourceImageData[4][16] =
262 {
263 { // R
264 1.0f,
265 0.0f,
266 0.0f,
267 1.0f
268 },
269 { // RG
270 1.0f, 0.0f,
271 0.0f, 1.0f,
272 0.0f, 0.0f,
273 1.0f, 1.0f
274 },
275 { // RGB
276 1.0f, 0.0f, 0.0f,
277 0.0f, 1.0f, 0.0f,
278 0.0f, 0.0f, 1.0f,
279 1.0f, 1.0f, 0.0f
280 },
281 { // RGBA
282 1.0f, 0.0f, 0.0f, 1.0f,
283 0.0f, 1.0f, 0.0f, 1.0f,
284 0.0f, 0.0f, 1.0f, 1.0f,
285 1.0f, 1.0f, 0.0f, 1.0f
286 },
287 };
288 // clang-format on
289
290 GLenum imageFormats[] = {
291 GL_R32F,
292 GL_RG32F,
293 GL_RGB32F,
294 GL_RGBA32F,
295 };
296
297 GLenum sourceUnsizedFormats[] = {
298 GL_RED,
299 GL_RG,
300 GL_RGB,
301 GL_RGBA,
302 };
303
304 GLTexture textures[2];
305
306 GLfloat *imageData = sourceImageData[sourceImageChannels - 1];
307 GLenum sourceImageFormat = imageFormats[sourceImageChannels - 1];
308 GLenum sourceUnsizedFormat = sourceUnsizedFormats[sourceImageChannels - 1];
309 GLenum destImageFormat = imageFormats[destImageChannels - 1];
310
311 glBindTexture(GL_TEXTURE_2D, textures[0]);
312 if (getClientMajorVersion() >= 3)
313 {
314 glTexStorage2D(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
315 }
316 else
317 {
318 glTexStorage2DEXT(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
319 }
320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
322 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, sourceUnsizedFormat, GL_FLOAT, imageData);
323
324 if (sourceImageChannels < 3 && !IsGLExtensionEnabled("GL_EXT_texture_rg"))
325 {
326 // This is not supported
327 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
328 }
329 else
330 {
331 ASSERT_GL_NO_ERROR();
332 }
333
334 GLuint fbo;
335 glGenFramebuffers(1, &fbo);
336 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
337 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
338
339 glBindTexture(GL_TEXTURE_2D, textures[1]);
340 if (getClientMajorVersion() >= 3)
341 {
342 glTexStorage2D(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
343 }
344 else
345 {
346 glTexStorage2DEXT(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
347 }
348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
350
351 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2);
352 ASSERT_GL_NO_ERROR();
353
354 glBindFramebuffer(GL_FRAMEBUFFER, 0);
355 drawQuad(mProgram, "position", 0.5f);
356
357 int testImageChannels = std::min(sourceImageChannels, destImageChannels);
358
359 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
360 if (testImageChannels > 1)
361 {
362 EXPECT_PIXEL_EQ(getWindowHeight() - 1, 0, 0, 255, 0, 255);
363 EXPECT_PIXEL_EQ(getWindowHeight() - 1, getWindowWidth() - 1, 255, 255, 0, 255);
364 if (testImageChannels > 2)
365 {
366 EXPECT_PIXEL_EQ(0, getWindowWidth() - 1, 0, 0, 255, 255);
367 }
368 }
369
370 glDeleteFramebuffers(1, &fbo);
371
372 ASSERT_GL_NO_ERROR();
373 }
374
375 void testTextureSize(int testCaseIndex);
376 void testTextureSizeError();
377
378 struct UploadThenUseStageParam
379 {
380 GLenum useStage;
381 bool closeRenderPassAfterUse;
382 };
383
384 void testUploadThenUseInDifferentStages(const std::vector<UploadThenUseStageParam> &uses);
385
386 GLuint mTexture2D;
387 GLint mTexture2DUniformLocation;
388 };
389
390 class Texture2DTestES3 : public Texture2DTest
391 {
392 protected:
Texture2DTestES3()393 Texture2DTestES3() : Texture2DTest() {}
394
getVertexShaderSource()395 const char *getVertexShaderSource() override
396 {
397 return "#version 300 es\n"
398 "out vec2 texcoord;\n"
399 "in vec4 position;\n"
400 "void main()\n"
401 "{\n"
402 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
403 " texcoord = (position.xy * 0.5) + 0.5;\n"
404 "}\n";
405 }
406
getFragmentShaderSource()407 const char *getFragmentShaderSource() override
408 {
409 return "#version 300 es\n"
410 "precision highp float;\n"
411 "uniform highp sampler2D tex;\n"
412 "in vec2 texcoord;\n"
413 "out vec4 fragColor;\n"
414 "void main()\n"
415 "{\n"
416 " fragColor = texture(tex, texcoord);\n"
417 "}\n";
418 }
419
testSetUp()420 void testSetUp() override
421 {
422 Texture2DTest::testSetUp();
423 setUpProgram();
424 }
425
createImmutableTexture2D(GLuint texture,size_t width,size_t height,GLenum format,GLenum internalFormat,GLenum type,GLsizei levels,GLubyte data[4])426 void createImmutableTexture2D(GLuint texture,
427 size_t width,
428 size_t height,
429 GLenum format,
430 GLenum internalFormat,
431 GLenum type,
432 GLsizei levels,
433 GLubyte data[4])
434 {
435 // Support only 1 level for now
436 ASSERT(levels == 1);
437
438 glBindTexture(GL_TEXTURE_2D, texture);
439
440 glTexStorage2D(GL_TEXTURE_2D, levels, internalFormat, width, height);
441 ASSERT_GL_NO_ERROR();
442
443 if (data != nullptr)
444 {
445 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
446 ASSERT_GL_NO_ERROR();
447 }
448
449 // Disable mipmapping
450 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
451 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
452 ASSERT_GL_NO_ERROR();
453 }
454
verifyResults2D(GLuint texture,GLubyte referenceColor[4])455 void verifyResults2D(GLuint texture, GLubyte referenceColor[4])
456 {
457 // Draw a quad with the target texture
458 glUseProgram(mProgram);
459 glBindTexture(GL_TEXTURE_2D, texture);
460 glUniform1i(mTexture2DUniformLocation, 0);
461
462 drawQuad(mProgram, "position", 0.5f);
463
464 // Expect that the rendered quad's color is the same as the reference color with a tolerance
465 // of 1
466 EXPECT_PIXEL_NEAR(0, 0, referenceColor[0], referenceColor[1], referenceColor[2],
467 referenceColor[3], 1);
468 }
469
470 void testCopyImage(const APIExtensionVersion usedExtension);
471 void testCopyImageDepthStencil(const APIExtensionVersion usedExtension);
472 };
473
474 class Texture2DMemoryTestES3 : public Texture2DTestES3
475 {
476 protected:
getPerfCounters()477 angle::VulkanPerfCounters getPerfCounters()
478 {
479 if (mIndexMap.empty())
480 {
481 mIndexMap = BuildCounterNameToIndexMap();
482 }
483
484 return GetPerfCounters(mIndexMap);
485 }
486
487 CounterNameToIndexMap mIndexMap;
488 };
489
490 class Texture2DTestES3YUV : public Texture2DTestES3
491 {};
492
493 class Texture2DTestES3RobustInit : public Texture2DTestES3
494 {
495 protected:
Texture2DTestES3RobustInit()496 Texture2DTestES3RobustInit() : Texture2DTestES3() { setRobustResourceInit(true); }
497 };
498
499 class Texture2DTestES3Foveation : public Texture2DTestES3
500 {
501 protected:
Texture2DTestES3Foveation()502 Texture2DTestES3Foveation() : Texture2DTestES3()
503 {
504 setWindowWidth(256);
505 setWindowHeight(256);
506 }
507 };
508
509 class Texture2DTestES31Foveation : public Texture2DTestES3Foveation
510 {};
511
512 class Texture2DBaseMaxTestES3 : public ANGLETest<>
513 {
514 protected:
515 static constexpr size_t kMip0Size = 13;
516 static constexpr uint32_t kMipCount = 4;
517
Texture2DBaseMaxTestES3()518 Texture2DBaseMaxTestES3() : ANGLETest(), mTextureLocation(0), mLodLocation(0)
519 {
520 setWindowWidth(128);
521 setWindowHeight(128);
522 setConfigRedBits(8);
523 setConfigGreenBits(8);
524 setConfigBlueBits(8);
525 setConfigAlphaBits(8);
526 }
527
getMipDataSize(size_t mip0Size,size_t mip)528 static constexpr size_t getMipDataSize(size_t mip0Size, size_t mip)
529 {
530 size_t mipSize = std::max<size_t>(1u, mip0Size >> mip);
531 return mipSize * mipSize;
532 }
533
getTotalMipDataSize(size_t mip0Size)534 static constexpr size_t getTotalMipDataSize(size_t mip0Size)
535 {
536 size_t totalCount = 0;
537 for (size_t mip = 0; mip < kMipCount; ++mip)
538 {
539 totalCount += getMipDataSize(mip0Size, mip);
540 }
541 return totalCount;
542 }
543
getMipDataOffset(size_t mip0Size,size_t mip)544 static constexpr size_t getMipDataOffset(size_t mip0Size, size_t mip)
545 {
546 // This calculates:
547 //
548 // mip == 0: 0
549 // o.w.: sum(0, mip-1) getMipDataSize(i)
550 //
551 // The above can be calculated simply as:
552 //
553 // (mip0 >> (kMipCount-1))^2 * (0x55555555 & ((1 << (2*mip)) - 1))
554 // \__________ ___________/ \_______________ ________________/
555 // \/ \/
556 // last mip size sum(0, mip-1) (4^i)
557 //
558 // But let's loop explicitly for clarity.
559 size_t offset = 0;
560 for (size_t m = 0; m < mip; ++m)
561 {
562 offset += getMipDataSize(mip0Size, m);
563 }
564 return offset;
565 }
566
567 template <typename colorType = GLColor>
fillMipData(colorType * data,size_t mip0Size,const colorType mipColors[kMipCount])568 void fillMipData(colorType *data, size_t mip0Size, const colorType mipColors[kMipCount])
569 {
570 for (size_t mip = 0; mip < kMipCount; ++mip)
571 {
572 size_t offset = getMipDataOffset(mip0Size, mip);
573 size_t size = getMipDataSize(mip0Size, mip);
574 std::fill(data + offset, data + offset + size, mipColors[mip]);
575 }
576 }
577
initTest(bool immutable)578 void initTest(bool immutable)
579 {
580 // Set up program to sample from specific lod level.
581 mProgram.makeRaster(essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
582 ASSERT(mProgram.valid());
583
584 glUseProgram(mProgram);
585
586 mTextureLocation = glGetUniformLocation(mProgram, essl3_shaders::Texture2DUniform());
587 ASSERT_NE(-1, mTextureLocation);
588
589 mLodLocation = glGetUniformLocation(mProgram, essl3_shaders::LodUniform());
590 ASSERT_NE(-1, mLodLocation);
591
592 // Set up texture with a handful of lods.
593 glActiveTexture(GL_TEXTURE0);
594 glBindTexture(GL_TEXTURE_2D, mTexture);
595
596 std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
597 fillMipData(mipData.data(), kMip0Size, kMipColors);
598
599 if (immutable)
600 {
601 glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size);
602 for (size_t mip = 0; mip < kMipCount; ++mip)
603 {
604 glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip,
605 GL_RGBA, GL_UNSIGNED_BYTE,
606 mipData.data() + getMipDataOffset(kMip0Size, mip));
607 }
608 }
609 else
610 {
611 for (size_t mip = 0; mip < kMipCount; ++mip)
612 {
613 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, kMip0Size >> mip, kMip0Size >> mip, 0,
614 GL_RGBA, GL_UNSIGNED_BYTE,
615 mipData.data() + getMipDataOffset(kMip0Size, mip));
616 }
617 }
618
619 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
620 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
621
622 EXPECT_GL_NO_ERROR();
623 }
624
setLodUniform(uint32_t lod)625 void setLodUniform(uint32_t lod) { glUniform1f(mLodLocation, lod); }
626
627 void testPingPongBaseLevel(bool immutable);
628 void testGenerateMipmapAfterRebase(bool immutable);
629
630 GLProgram mProgram;
631 GLTexture mTexture;
632 GLint mTextureLocation;
633 GLint mLodLocation;
634
635 const GLColor kMipColors[kMipCount] = {
636 GLColor::red,
637 GLColor::green,
638 GLColor::blue,
639 GLColor::magenta,
640 };
641 };
642
643 class TextureES31PPO
644 {
645 protected:
TextureES31PPO()646 TextureES31PPO() : mVertProg(0), mFragProg(0), mPipeline(0) {}
647
get2DTexturedVertexShaderSource()648 const char *get2DTexturedVertexShaderSource()
649 {
650 return "#version 310 es\n"
651 "precision mediump float;\n"
652 "in vec2 position;\n"
653 "out vec2 texCoord;\n"
654 "void main()\n"
655 "{\n"
656 " gl_Position = vec4(position, 0, 1);\n"
657 " texCoord = position * 0.5 + vec2(0.5);\n"
658 "}";
659 }
660
get2DTexturedFragmentShaderSource()661 const char *get2DTexturedFragmentShaderSource()
662 {
663 return "#version 310 es\n"
664 "precision mediump float;\n"
665 "in vec2 texCoord;\n"
666 "uniform sampler2D tex1;\n"
667 "uniform sampler2D tex2;\n"
668 "uniform sampler2D tex3;\n"
669 "uniform sampler2D tex4;\n"
670 "out vec4 color;\n"
671 "void main()\n"
672 "{\n"
673 " color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
674 " + texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
675 "}";
676 }
677
bindProgramPipeline(const GLchar * vertString,const GLchar * fragString)678 void bindProgramPipeline(const GLchar *vertString, const GLchar *fragString)
679 {
680 mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertString);
681 ASSERT_NE(mVertProg, 0u);
682 mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
683 ASSERT_NE(mFragProg, 0u);
684
685 // Generate a program pipeline and attach the programs to their respective stages
686 glGenProgramPipelines(1, &mPipeline);
687 EXPECT_GL_NO_ERROR();
688 glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
689 EXPECT_GL_NO_ERROR();
690 glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
691 EXPECT_GL_NO_ERROR();
692 glBindProgramPipeline(mPipeline);
693 EXPECT_GL_NO_ERROR();
694 }
695
bind2DTexturedQuadProgramPipeline()696 void bind2DTexturedQuadProgramPipeline()
697 {
698 const char *vertexShaderSource = get2DTexturedVertexShaderSource();
699 const char *fragmentShaderSource = get2DTexturedFragmentShaderSource();
700
701 m2DTexturedQuadVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertexShaderSource);
702 ASSERT_NE(m2DTexturedQuadVertProg, 0u);
703 m2DTexturedQuadFragProg =
704 glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragmentShaderSource);
705 ASSERT_NE(m2DTexturedQuadFragProg, 0u);
706
707 // Generate a program pipeline and attach the programs to their respective stages
708 glGenProgramPipelines(1, &m2DTexturedQuadPipeline);
709 EXPECT_GL_NO_ERROR();
710 glUseProgramStages(m2DTexturedQuadPipeline, GL_VERTEX_SHADER_BIT, m2DTexturedQuadVertProg);
711 EXPECT_GL_NO_ERROR();
712 glUseProgramStages(m2DTexturedQuadPipeline, GL_FRAGMENT_SHADER_BIT,
713 m2DTexturedQuadFragProg);
714 EXPECT_GL_NO_ERROR();
715 glBindProgramPipeline(m2DTexturedQuadPipeline);
716 EXPECT_GL_NO_ERROR();
717 }
718
ppoDrawQuad(std::array<Vector3,6> & quadVertices,const std::string & positionAttribName,const GLfloat positionAttribZ,const GLfloat positionAttribXYScale)719 void ppoDrawQuad(std::array<Vector3, 6> &quadVertices,
720 const std::string &positionAttribName,
721 const GLfloat positionAttribZ,
722 const GLfloat positionAttribXYScale)
723 {
724 glUseProgram(0);
725
726 for (Vector3 &vertex : quadVertices)
727 {
728 vertex.x() *= positionAttribXYScale;
729 vertex.y() *= positionAttribXYScale;
730 vertex.z() = positionAttribZ;
731 }
732
733 GLint positionLocation = glGetAttribLocation(mVertProg, positionAttribName.c_str());
734
735 glBindBuffer(GL_ARRAY_BUFFER, 0);
736 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
737 glEnableVertexAttribArray(positionLocation);
738
739 glDrawArrays(GL_TRIANGLES, 0, 6);
740
741 glDisableVertexAttribArray(positionLocation);
742 glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
743 }
744
745 GLuint mVertProg;
746 GLuint mFragProg;
747 GLuint mPipeline;
748 GLuint m2DTexturedQuadVertProg;
749 GLuint m2DTexturedQuadFragProg;
750 GLuint m2DTexturedQuadPipeline;
751 };
752
753 class Texture2DTestES31PPO : public TextureES31PPO, public Texture2DTest
754 {
755 protected:
Texture2DTestES31PPO()756 Texture2DTestES31PPO() : TextureES31PPO(), Texture2DTest() {}
757
testSetUp()758 void testSetUp() override { Texture2DTest::testSetUp(); }
759 };
760
761 class Texture2DIntegerAlpha1TestES3 : public Texture2DTest
762 {
763 protected:
Texture2DIntegerAlpha1TestES3()764 Texture2DIntegerAlpha1TestES3() : Texture2DTest() {}
765
getVertexShaderSource()766 const char *getVertexShaderSource() override
767 {
768 return "#version 300 es\n"
769 "out vec2 texcoord;\n"
770 "in vec4 position;\n"
771 "void main()\n"
772 "{\n"
773 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
774 " texcoord = (position.xy * 0.5) + 0.5;\n"
775 "}\n";
776 }
777
getFragmentShaderSource()778 const char *getFragmentShaderSource() override
779 {
780 return "#version 300 es\n"
781 "precision highp float;\n"
782 "uniform highp isampler2D tex;\n"
783 "in vec2 texcoord;\n"
784 "out vec4 fragColor;\n"
785 "void main()\n"
786 "{\n"
787 " vec4 green = vec4(0, 1, 0, 1);\n"
788 " vec4 black = vec4(0, 0, 0, 0);\n"
789 " fragColor = (texture(tex, texcoord).a == 1) ? green : black;\n"
790 "}\n";
791 }
792
testSetUp()793 void testSetUp() override
794 {
795 Texture2DTest::testSetUp();
796 setUpProgram();
797 }
798 };
799
800 class Texture2DUnsignedIntegerAlpha1TestES3 : public Texture2DTest
801 {
802 protected:
Texture2DUnsignedIntegerAlpha1TestES3()803 Texture2DUnsignedIntegerAlpha1TestES3() : Texture2DTest() {}
804
getVertexShaderSource()805 const char *getVertexShaderSource() override
806 {
807 return "#version 300 es\n"
808 "out vec2 texcoord;\n"
809 "in vec4 position;\n"
810 "void main()\n"
811 "{\n"
812 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
813 " texcoord = (position.xy * 0.5) + 0.5;\n"
814 "}\n";
815 }
816
getFragmentShaderSource()817 const char *getFragmentShaderSource() override
818 {
819 return "#version 300 es\n"
820 "precision highp float;\n"
821 "uniform highp usampler2D tex;\n"
822 "in vec2 texcoord;\n"
823 "out vec4 fragColor;\n"
824 "void main()\n"
825 "{\n"
826 " vec4 green = vec4(0, 1, 0, 1);\n"
827 " vec4 black = vec4(0, 0, 0, 0);\n"
828 " fragColor = (texture(tex, texcoord).a == 1u) ? green : black;\n"
829 "}\n";
830 }
831
testSetUp()832 void testSetUp() override
833 {
834 Texture2DTest::testSetUp();
835 setUpProgram();
836 }
837 };
838
839 class Texture2DTestWithDrawScale : public Texture2DTest
840 {
841 protected:
Texture2DTestWithDrawScale()842 Texture2DTestWithDrawScale() : Texture2DTest(), mDrawScaleUniformLocation(-1) {}
843
getVertexShaderSource()844 const char *getVertexShaderSource() override
845 {
846 return
847 R"(precision highp float;
848 attribute vec4 position;
849 varying vec2 texcoord;
850
851 uniform vec2 drawScale;
852
853 void main()
854 {
855 gl_Position = vec4(position.xy * drawScale, 0.0, 1.0);
856 texcoord = (position.xy * 0.5) + 0.5;
857 })";
858 }
859
testSetUp()860 void testSetUp() override
861 {
862 Texture2DTest::testSetUp();
863
864 setUpProgram();
865
866 mDrawScaleUniformLocation = glGetUniformLocation(mProgram, "drawScale");
867 ASSERT_NE(-1, mDrawScaleUniformLocation);
868
869 glUseProgram(mProgram);
870 glUniform2f(mDrawScaleUniformLocation, 1.0f, 1.0f);
871 glUseProgram(0);
872 ASSERT_GL_NO_ERROR();
873 }
874
875 GLint mDrawScaleUniformLocation;
876 };
877
878 class Sampler2DAsFunctionParameterTest : public Texture2DTest
879 {
880 protected:
Sampler2DAsFunctionParameterTest()881 Sampler2DAsFunctionParameterTest() : Texture2DTest() {}
882
getFragmentShaderSource()883 const char *getFragmentShaderSource() override
884 {
885 return
886 R"(precision highp float;
887 uniform sampler2D tex;
888 varying vec2 texcoord;
889
890 vec4 computeFragColor(sampler2D aTex)
891 {
892 return texture2D(aTex, texcoord);
893 }
894
895 void main()
896 {
897 gl_FragColor = computeFragColor(tex);
898 })";
899 }
900
testSetUp()901 void testSetUp() override
902 {
903 Texture2DTest::testSetUp();
904 setUpProgram();
905 }
906 };
907
908 class TextureCubeTest : public TexCoordDrawTest
909 {
910 protected:
TextureCubeTest()911 TextureCubeTest()
912 : TexCoordDrawTest(),
913 mTexture2D(0),
914 mTextureCube(0),
915 mTexture2DUniformLocation(-1),
916 mTextureCubeUniformLocation(-1)
917 {}
918
getFragmentShaderSource()919 const char *getFragmentShaderSource() override
920 {
921 return
922 R"(precision highp float;
923 uniform sampler2D tex2D;
924 uniform samplerCube texCube;
925 uniform int cubeFace;
926 varying vec2 texcoord;
927
928 void main()
929 {
930 gl_FragColor = texture2D(tex2D, texcoord);
931
932 vec2 scaled = vec2(1) - vec2(2) * texcoord.xy;
933 vec3 cubecoord = vec3(1, scaled.xy);
934 if (cubeFace == 1)
935 cubecoord = vec3(-1, scaled.xy);
936 else if (cubeFace == 2)
937 cubecoord = vec3(scaled.x, 1, scaled.y);
938 else if (cubeFace == 3)
939 cubecoord = vec3(scaled.x, -1, scaled.y);
940 else if (cubeFace == 4)
941 cubecoord = vec3(scaled.xy, 1);
942 else if (cubeFace == 5)
943 cubecoord = vec3(scaled.xy, -1);
944
945 gl_FragColor += textureCube(texCube, cubecoord);
946 })";
947 }
948
testSetUp()949 void testSetUp() override
950 {
951 TexCoordDrawTest::testSetUp();
952
953 glGenTextures(1, &mTextureCube);
954 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
955 for (GLenum face = 0; face < 6; face++)
956 {
957 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
958 GL_UNSIGNED_BYTE, nullptr);
959 }
960 EXPECT_GL_NO_ERROR();
961
962 mTexture2D = create2DTexture();
963
964 setUpProgram();
965
966 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
967 ASSERT_NE(-1, mTexture2DUniformLocation);
968 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
969 ASSERT_NE(-1, mTextureCubeUniformLocation);
970 mTextureCubeFaceUniformLocation = glGetUniformLocation(mProgram, "cubeFace");
971 ASSERT_NE(-1, mTextureCubeFaceUniformLocation);
972 }
973
testTearDown()974 void testTearDown() override
975 {
976 glDeleteTextures(1, &mTextureCube);
977 TexCoordDrawTest::testTearDown();
978 }
979
980 GLuint mTexture2D;
981 GLuint mTextureCube;
982 GLint mTexture2DUniformLocation;
983 GLint mTextureCubeUniformLocation;
984 GLint mTextureCubeFaceUniformLocation;
985 };
986
987 class TextureCubeTestES3 : public TextureCubeTest
988 {
989 protected:
TextureCubeTestES3()990 TextureCubeTestES3() {}
991 };
992
993 class TextureCubeTestES32 : public TextureCubeTest
994 {
995 protected:
TextureCubeTestES32()996 TextureCubeTestES32() {}
997 };
998
999 class SamplerArrayTest : public TexCoordDrawTest
1000 {
1001 protected:
SamplerArrayTest()1002 SamplerArrayTest()
1003 : TexCoordDrawTest(),
1004 mTexture2DA(0),
1005 mTexture2DB(0),
1006 mTexture0UniformLocation(-1),
1007 mTexture1UniformLocation(-1)
1008 {}
1009
getFragmentShaderSource()1010 const char *getFragmentShaderSource() override
1011 {
1012 return
1013 R"(precision mediump float;
1014 uniform highp sampler2D tex2DArray[2];
1015 varying vec2 texcoord;
1016 void main()
1017 {
1018 gl_FragColor = texture2D(tex2DArray[0], texcoord);
1019 gl_FragColor += texture2D(tex2DArray[1], texcoord);
1020 })";
1021 }
1022
testSetUp()1023 void testSetUp() override
1024 {
1025 TexCoordDrawTest::testSetUp();
1026
1027 setUpProgram();
1028
1029 mTexture0UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[0]");
1030 ASSERT_NE(-1, mTexture0UniformLocation);
1031 mTexture1UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[1]");
1032 ASSERT_NE(-1, mTexture1UniformLocation);
1033
1034 mTexture2DA = create2DTexture();
1035 mTexture2DB = create2DTexture();
1036 ASSERT_GL_NO_ERROR();
1037 }
1038
testTearDown()1039 void testTearDown() override
1040 {
1041 glDeleteTextures(1, &mTexture2DA);
1042 glDeleteTextures(1, &mTexture2DB);
1043 TexCoordDrawTest::testTearDown();
1044 }
1045
testSamplerArrayDraw()1046 void testSamplerArrayDraw()
1047 {
1048 GLubyte texData[4];
1049 texData[0] = 0;
1050 texData[1] = 60;
1051 texData[2] = 0;
1052 texData[3] = 255;
1053
1054 glActiveTexture(GL_TEXTURE0);
1055 glBindTexture(GL_TEXTURE_2D, mTexture2DA);
1056 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1057
1058 texData[1] = 120;
1059 glActiveTexture(GL_TEXTURE1);
1060 glBindTexture(GL_TEXTURE_2D, mTexture2DB);
1061 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1062 EXPECT_GL_ERROR(GL_NO_ERROR);
1063
1064 glUseProgram(mProgram);
1065 glUniform1i(mTexture0UniformLocation, 0);
1066 glUniform1i(mTexture1UniformLocation, 1);
1067 drawQuad(mProgram, "position", 0.5f);
1068 EXPECT_GL_NO_ERROR();
1069
1070 EXPECT_PIXEL_NEAR(0, 0, 0, 180, 0, 255, 2);
1071 }
1072
1073 GLuint mTexture2DA;
1074 GLuint mTexture2DB;
1075 GLint mTexture0UniformLocation;
1076 GLint mTexture1UniformLocation;
1077 };
1078
1079 class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
1080 {
1081 protected:
SamplerArrayAsFunctionParameterTest()1082 SamplerArrayAsFunctionParameterTest() : SamplerArrayTest() {}
1083
getFragmentShaderSource()1084 const char *getFragmentShaderSource() override
1085 {
1086 return
1087 R"(precision mediump float;
1088 uniform highp sampler2D tex2DArray[2];
1089 varying vec2 texcoord;
1090
1091 vec4 computeFragColor(highp sampler2D aTex2DArray[2])
1092 {
1093 return texture2D(aTex2DArray[0], texcoord) + texture2D(aTex2DArray[1], texcoord);
1094 }
1095
1096 void main()
1097 {
1098 gl_FragColor = computeFragColor(tex2DArray);
1099 })";
1100 }
1101 };
1102
1103 class Texture2DArrayTestES3 : public TexCoordDrawTest
1104 {
1105 protected:
Texture2DArrayTestES3()1106 Texture2DArrayTestES3()
1107 : TexCoordDrawTest(),
1108 m2DArrayTexture(0),
1109 mTextureArrayLocation(-1),
1110 mTextureArraySliceUniformLocation(-1)
1111 {}
1112
getVertexShaderSource()1113 const char *getVertexShaderSource() override
1114 {
1115 return R"(#version 300 es
1116 out vec2 texcoord;
1117 in vec4 position;
1118 void main()
1119 {
1120 gl_Position = vec4(position.xy, 0.0, 1.0);
1121 texcoord = (position.xy * 0.5) + 0.5;
1122 })";
1123 }
1124
getFragmentShaderSource()1125 const char *getFragmentShaderSource() override
1126 {
1127 return R"(#version 300 es
1128 precision highp float;
1129 uniform highp sampler2DArray tex2DArray;
1130 uniform int slice;
1131 in vec2 texcoord;
1132 out vec4 fragColor;
1133 void main()
1134 {
1135 fragColor = texture(tex2DArray, vec3(texcoord, float(slice)));
1136 })";
1137 }
1138
testSetUp()1139 void testSetUp() override
1140 {
1141 TexCoordDrawTest::testSetUp();
1142
1143 setUpProgram();
1144
1145 mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
1146 ASSERT_NE(-1, mTextureArrayLocation);
1147
1148 mTextureArraySliceUniformLocation = glGetUniformLocation(mProgram, "slice");
1149 ASSERT_NE(-1, mTextureArraySliceUniformLocation);
1150
1151 glGenTextures(1, &m2DArrayTexture);
1152 ASSERT_GL_NO_ERROR();
1153 }
1154
testTearDown()1155 void testTearDown() override
1156 {
1157 glDeleteTextures(1, &m2DArrayTexture);
1158 TexCoordDrawTest::testTearDown();
1159 }
1160
1161 GLuint m2DArrayTexture;
1162 GLint mTextureArrayLocation;
1163 GLint mTextureArraySliceUniformLocation;
1164 };
1165
1166 class TextureSizeTextureArrayTest : public TexCoordDrawTest
1167 {
1168 protected:
TextureSizeTextureArrayTest()1169 TextureSizeTextureArrayTest()
1170 : TexCoordDrawTest(),
1171 mTexture2DA(0),
1172 mTexture2DB(0),
1173 mTexture0Location(-1),
1174 mTexture1Location(-1)
1175 {}
1176
getVertexShaderSource()1177 const char *getVertexShaderSource() override { return essl3_shaders::vs::Simple(); }
1178
getFragmentShaderSource()1179 const char *getFragmentShaderSource() override
1180 {
1181 return "#version 300 es\n"
1182 "precision highp float;\n"
1183 "uniform highp sampler2D tex2DArray[2];\n"
1184 "out vec4 fragColor;\n"
1185 "void main()\n"
1186 "{\n"
1187 " float red = float(textureSize(tex2DArray[0], 0).x) / 255.0;\n"
1188 " float green = float(textureSize(tex2DArray[1], 0).x) / 255.0;\n"
1189 " fragColor = vec4(red, green, 0.0, 1.0);\n"
1190 "}\n";
1191 }
1192
testSetUp()1193 void testSetUp() override
1194 {
1195 TexCoordDrawTest::testSetUp();
1196
1197 setUpProgram();
1198
1199 mTexture0Location = glGetUniformLocation(mProgram, "tex2DArray[0]");
1200 ASSERT_NE(-1, mTexture0Location);
1201 mTexture1Location = glGetUniformLocation(mProgram, "tex2DArray[1]");
1202 ASSERT_NE(-1, mTexture1Location);
1203
1204 mTexture2DA = create2DTexture();
1205 mTexture2DB = create2DTexture();
1206 ASSERT_GL_NO_ERROR();
1207 }
1208
testTearDown()1209 void testTearDown() override
1210 {
1211 glDeleteTextures(1, &mTexture2DA);
1212 glDeleteTextures(1, &mTexture2DB);
1213 TexCoordDrawTest::testTearDown();
1214 }
1215
1216 GLuint mTexture2DA;
1217 GLuint mTexture2DB;
1218 GLint mTexture0Location;
1219 GLint mTexture1Location;
1220 };
1221
1222 // Test for GL_OES_texture_3D extension
1223 class Texture3DTestES2 : public TexCoordDrawTest
1224 {
1225 protected:
Texture3DTestES2()1226 Texture3DTestES2() : TexCoordDrawTest(), mTexture3D(0), mTexture3DUniformLocation(-1) {}
1227
getVertexShaderSource()1228 const char *getVertexShaderSource() override
1229 {
1230 return "#version 100\n"
1231 "varying vec2 texcoord;\n"
1232 "attribute vec4 position;\n"
1233 "void main()\n"
1234 "{\n"
1235 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1236 " texcoord = (position.xy * 0.5) + 0.5;\n"
1237 "}\n";
1238 }
1239
getFragmentShaderSource()1240 const char *getFragmentShaderSource() override
1241 {
1242 if (!hasTexture3DExt())
1243 {
1244 return "#version 100\n"
1245 "precision highp float;\n"
1246 "varying vec2 texcoord;\n"
1247 "void main()\n"
1248 "{\n"
1249 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
1250 "}\n";
1251 }
1252 return "#version 100\n"
1253 "#extension GL_OES_texture_3D : enable\n"
1254 "precision highp float;\n"
1255 "uniform highp sampler3D tex3D;\n"
1256 "uniform highp float level;\n"
1257 "varying vec2 texcoord;\n"
1258 "void main()\n"
1259 "{\n"
1260 " gl_FragColor = texture3DLod(tex3D, vec3(texcoord, 0.0), level);\n"
1261 "}\n";
1262 }
1263
testSetUp()1264 void testSetUp() override
1265 {
1266 // http://anglebug.com/42264265
1267 ANGLE_SKIP_TEST_IF(IsOzone());
1268
1269 TexCoordDrawTest::testSetUp();
1270
1271 glGenTextures(1, &mTexture3D);
1272
1273 setUpProgram();
1274
1275 mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
1276 if (hasTexture3DExt())
1277 {
1278 ASSERT_NE(-1, mTexture3DUniformLocation);
1279 }
1280 }
1281
testTearDown()1282 void testTearDown() override
1283 {
1284 glDeleteTextures(1, &mTexture3D);
1285 TexCoordDrawTest::testTearDown();
1286 }
1287
hasTexture3DExt() const1288 bool hasTexture3DExt() const
1289 {
1290 // http://anglebug.com/42263501
1291 if ((IsPixel2() || IsNexus5X()) && IsOpenGLES())
1292 {
1293 return false;
1294 }
1295 return IsGLExtensionEnabled("GL_OES_texture_3D");
1296 }
1297
1298 GLuint mTexture3D;
1299 GLint mTexture3DUniformLocation;
1300 };
1301
1302 class Texture3DTestES3 : public Texture3DTestES2
1303 {
1304 protected:
Texture3DTestES3()1305 Texture3DTestES3() : Texture3DTestES2() {}
1306
getVertexShaderSource()1307 const char *getVertexShaderSource() override
1308 {
1309 return "#version 300 es\n"
1310 "out vec2 texcoord;\n"
1311 "in vec4 position;\n"
1312 "void main()\n"
1313 "{\n"
1314 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1315 " texcoord = (position.xy * 0.5) + 0.5;\n"
1316 "}\n";
1317 }
1318
getFragmentShaderSource()1319 const char *getFragmentShaderSource() override
1320 {
1321 return "#version 300 es\n"
1322 "precision highp float;\n"
1323 "uniform highp sampler3D tex3D;\n"
1324 "in vec2 texcoord;\n"
1325 "out vec4 fragColor;\n"
1326 "void main()\n"
1327 "{\n"
1328 " fragColor = texture(tex3D, vec3(texcoord, 0.0));\n"
1329 "}\n";
1330 }
1331 };
1332
1333 class ShadowSamplerPlusSampler3DTestES3 : public TexCoordDrawTest
1334 {
1335 protected:
ShadowSamplerPlusSampler3DTestES3()1336 ShadowSamplerPlusSampler3DTestES3()
1337 : TexCoordDrawTest(),
1338 mTextureShadow(0),
1339 mTexture3D(0),
1340 mTextureShadowUniformLocation(-1),
1341 mTexture3DUniformLocation(-1),
1342 mDepthRefUniformLocation(-1)
1343 {}
1344
getVertexShaderSource()1345 const char *getVertexShaderSource() override
1346 {
1347 return "#version 300 es\n"
1348 "out vec2 texcoord;\n"
1349 "in vec4 position;\n"
1350 "void main()\n"
1351 "{\n"
1352 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1353 " texcoord = (position.xy * 0.5) + 0.5;\n"
1354 "}\n";
1355 }
1356
getFragmentShaderSource()1357 const char *getFragmentShaderSource() override
1358 {
1359 return "#version 300 es\n"
1360 "precision highp float;\n"
1361 "uniform highp sampler2DShadow tex2DShadow;\n"
1362 "uniform highp sampler3D tex3D;\n"
1363 "in vec2 texcoord;\n"
1364 "uniform float depthRef;\n"
1365 "out vec4 fragColor;\n"
1366 "void main()\n"
1367 "{\n"
1368 " fragColor = vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.5);\n"
1369 " fragColor += texture(tex3D, vec3(texcoord, 0.0));\n"
1370 "}\n";
1371 }
1372
testSetUp()1373 void testSetUp() override
1374 {
1375 TexCoordDrawTest::testSetUp();
1376
1377 glGenTextures(1, &mTexture3D);
1378
1379 glGenTextures(1, &mTextureShadow);
1380 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
1381 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1382
1383 setUpProgram();
1384
1385 mTextureShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
1386 ASSERT_NE(-1, mTextureShadowUniformLocation);
1387 mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
1388 ASSERT_NE(-1, mTexture3DUniformLocation);
1389 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
1390 ASSERT_NE(-1, mDepthRefUniformLocation);
1391 }
1392
testTearDown()1393 void testTearDown() override
1394 {
1395 glDeleteTextures(1, &mTextureShadow);
1396 glDeleteTextures(1, &mTexture3D);
1397 TexCoordDrawTest::testTearDown();
1398 }
1399
1400 GLuint mTextureShadow;
1401 GLuint mTexture3D;
1402 GLint mTextureShadowUniformLocation;
1403 GLint mTexture3DUniformLocation;
1404 GLint mDepthRefUniformLocation;
1405 };
1406
1407 class SamplerTypeMixTestES3 : public TexCoordDrawTest
1408 {
1409 protected:
SamplerTypeMixTestES3()1410 SamplerTypeMixTestES3()
1411 : TexCoordDrawTest(),
1412 mTexture2D(0),
1413 mTextureCube(0),
1414 mTexture2DShadow(0),
1415 mTextureCubeShadow(0),
1416 mTexture2DUniformLocation(-1),
1417 mTextureCubeUniformLocation(-1),
1418 mTexture2DShadowUniformLocation(-1),
1419 mTextureCubeShadowUniformLocation(-1),
1420 mDepthRefUniformLocation(-1)
1421 {}
1422
getVertexShaderSource()1423 const char *getVertexShaderSource() override
1424 {
1425 return "#version 300 es\n"
1426 "out vec2 texcoord;\n"
1427 "in vec4 position;\n"
1428 "void main()\n"
1429 "{\n"
1430 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1431 " texcoord = (position.xy * 0.5) + 0.5;\n"
1432 "}\n";
1433 }
1434
getFragmentShaderSource()1435 const char *getFragmentShaderSource() override
1436 {
1437 return "#version 300 es\n"
1438 "precision highp float;\n"
1439 "uniform highp sampler2D tex2D;\n"
1440 "uniform highp samplerCube texCube;\n"
1441 "uniform highp sampler2DShadow tex2DShadow;\n"
1442 "uniform highp samplerCubeShadow texCubeShadow;\n"
1443 "in vec2 texcoord;\n"
1444 "uniform float depthRef;\n"
1445 "out vec4 fragColor;\n"
1446 "void main()\n"
1447 "{\n"
1448 " fragColor = texture(tex2D, texcoord);\n"
1449 " fragColor += texture(texCube, vec3(1.0, 0.0, 0.0));\n"
1450 " fragColor += vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.25);\n"
1451 " fragColor += vec4(texture(texCubeShadow, vec4(1.0, 0.0, 0.0, depthRef)) * "
1452 "0.125);\n"
1453 "}\n";
1454 }
1455
testSetUp()1456 void testSetUp() override
1457 {
1458 TexCoordDrawTest::testSetUp();
1459
1460 glGenTextures(1, &mTexture2D);
1461 glGenTextures(1, &mTextureCube);
1462
1463 glGenTextures(1, &mTexture2DShadow);
1464 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
1465 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1466
1467 glGenTextures(1, &mTextureCubeShadow);
1468 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
1469 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1470
1471 setUpProgram();
1472
1473 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
1474 ASSERT_NE(-1, mTexture2DUniformLocation);
1475 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
1476 ASSERT_NE(-1, mTextureCubeUniformLocation);
1477 mTexture2DShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
1478 ASSERT_NE(-1, mTexture2DShadowUniformLocation);
1479 mTextureCubeShadowUniformLocation = glGetUniformLocation(mProgram, "texCubeShadow");
1480 ASSERT_NE(-1, mTextureCubeShadowUniformLocation);
1481 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
1482 ASSERT_NE(-1, mDepthRefUniformLocation);
1483
1484 ASSERT_GL_NO_ERROR();
1485 }
1486
testTearDown()1487 void testTearDown() override
1488 {
1489 glDeleteTextures(1, &mTexture2D);
1490 glDeleteTextures(1, &mTextureCube);
1491 glDeleteTextures(1, &mTexture2DShadow);
1492 glDeleteTextures(1, &mTextureCubeShadow);
1493 TexCoordDrawTest::testTearDown();
1494 }
1495
1496 GLuint mTexture2D;
1497 GLuint mTextureCube;
1498 GLuint mTexture2DShadow;
1499 GLuint mTextureCubeShadow;
1500 GLint mTexture2DUniformLocation;
1501 GLint mTextureCubeUniformLocation;
1502 GLint mTexture2DShadowUniformLocation;
1503 GLint mTextureCubeShadowUniformLocation;
1504 GLint mDepthRefUniformLocation;
1505 };
1506
1507 class SamplerInStructTest : public Texture2DTest
1508 {
1509 protected:
SamplerInStructTest()1510 SamplerInStructTest() : Texture2DTest() {}
1511
getTextureUniformName()1512 const char *getTextureUniformName() override { return "us.tex"; }
1513
getFragmentShaderSource()1514 const char *getFragmentShaderSource() override
1515 {
1516 return "precision highp float;\n"
1517 "struct S\n"
1518 "{\n"
1519 " vec4 a;\n"
1520 " highp sampler2D tex;\n"
1521 "};\n"
1522 "uniform S us;\n"
1523 "varying vec2 texcoord;\n"
1524 "void main()\n"
1525 "{\n"
1526 " gl_FragColor = texture2D(us.tex, texcoord + us.a.x);\n"
1527 "}\n";
1528 }
1529
runSamplerInStructTest()1530 void runSamplerInStructTest()
1531 {
1532 setUpProgram();
1533
1534 glActiveTexture(GL_TEXTURE0);
1535 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1536 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1537 &GLColor::green);
1538 drawQuad(mProgram, "position", 0.5f);
1539 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1540 }
1541 };
1542
1543 class SamplerInStructAsFunctionParameterTest : public SamplerInStructTest
1544 {
1545 protected:
SamplerInStructAsFunctionParameterTest()1546 SamplerInStructAsFunctionParameterTest() : SamplerInStructTest() {}
1547
getFragmentShaderSource()1548 const char *getFragmentShaderSource() override
1549 {
1550 return "precision highp float;\n"
1551 "struct S\n"
1552 "{\n"
1553 " vec4 a;\n"
1554 " highp sampler2D tex;\n"
1555 "};\n"
1556 "uniform S us;\n"
1557 "varying vec2 texcoord;\n"
1558 "vec4 sampleFrom(S 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);\n"
1564 "}\n";
1565 }
1566 };
1567
1568 class SamplerInStructArrayAsFunctionParameterTest : public SamplerInStructTest
1569 {
1570 protected:
SamplerInStructArrayAsFunctionParameterTest()1571 SamplerInStructArrayAsFunctionParameterTest() : SamplerInStructTest() {}
1572
getTextureUniformName()1573 const char *getTextureUniformName() override { return "us[0].tex"; }
1574
getFragmentShaderSource()1575 const char *getFragmentShaderSource() override
1576 {
1577 return "precision highp float;\n"
1578 "struct S\n"
1579 "{\n"
1580 " vec4 a;\n"
1581 " highp sampler2D tex;\n"
1582 "};\n"
1583 "uniform S us[1];\n"
1584 "varying vec2 texcoord;\n"
1585 "vec4 sampleFrom(S s) {\n"
1586 " return texture2D(s.tex, texcoord + s.a.x);\n"
1587 "}\n"
1588 "void main()\n"
1589 "{\n"
1590 " gl_FragColor = sampleFrom(us[0]);\n"
1591 "}\n";
1592 }
1593 };
1594
1595 class SamplerInNestedStructAsFunctionParameterTest : public SamplerInStructTest
1596 {
1597 protected:
SamplerInNestedStructAsFunctionParameterTest()1598 SamplerInNestedStructAsFunctionParameterTest() : SamplerInStructTest() {}
1599
getTextureUniformName()1600 const char *getTextureUniformName() override { return "us[0].sub.tex"; }
1601
getFragmentShaderSource()1602 const char *getFragmentShaderSource() override
1603 {
1604 return "precision highp float;\n"
1605 "struct SUB\n"
1606 "{\n"
1607 " vec4 a;\n"
1608 " highp sampler2D tex;\n"
1609 "};\n"
1610 "struct S\n"
1611 "{\n"
1612 " SUB sub;\n"
1613 "};\n"
1614 "uniform S us[1];\n"
1615 "varying vec2 texcoord;\n"
1616 "vec4 sampleFrom(SUB s) {\n"
1617 " return texture2D(s.tex, texcoord + s.a.x);\n"
1618 "}\n"
1619 "void main()\n"
1620 "{\n"
1621 " gl_FragColor = sampleFrom(us[0].sub);\n"
1622 "}\n";
1623 }
1624 };
1625
1626 class SamplerInStructAndOtherVariableTest : public SamplerInStructTest
1627 {
1628 protected:
SamplerInStructAndOtherVariableTest()1629 SamplerInStructAndOtherVariableTest() : SamplerInStructTest() {}
1630
getFragmentShaderSource()1631 const char *getFragmentShaderSource() override
1632 {
1633 return "precision highp float;\n"
1634 "struct S\n"
1635 "{\n"
1636 " vec4 a;\n"
1637 " highp sampler2D tex;\n"
1638 "};\n"
1639 "uniform S us;\n"
1640 "uniform float us_tex;\n"
1641 "varying vec2 texcoord;\n"
1642 "void main()\n"
1643 "{\n"
1644 " gl_FragColor = texture2D(us.tex, texcoord + us.a.x + us_tex);\n"
1645 "}\n";
1646 }
1647 };
1648
1649 class Texture2DIntegerTestES3 : public Texture2DTest
1650 {
1651 protected:
Texture2DIntegerTestES3()1652 Texture2DIntegerTestES3() : Texture2DTest() {}
1653
getVertexShaderSource()1654 const char *getVertexShaderSource() override
1655 {
1656 return "#version 300 es\n"
1657 "out vec2 texcoord;\n"
1658 "in vec4 position;\n"
1659 "void main()\n"
1660 "{\n"
1661 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1662 " texcoord = (position.xy * 0.5) + 0.5;\n"
1663 "}\n";
1664 }
1665
getFragmentShaderSource()1666 const char *getFragmentShaderSource() override
1667 {
1668 return "#version 300 es\n"
1669 "precision highp float;\n"
1670 "precision highp usampler2D;\n"
1671 "uniform usampler2D tex;\n"
1672 "in vec2 texcoord;\n"
1673 "out vec4 fragColor;\n"
1674 "void main()\n"
1675 "{\n"
1676 " fragColor = vec4(texture(tex, texcoord))/255.0;\n"
1677 "}\n";
1678 }
1679 };
1680
1681 class TextureCubeIntegerTestES3 : public TexCoordDrawTest
1682 {
1683 protected:
TextureCubeIntegerTestES3()1684 TextureCubeIntegerTestES3()
1685 : TexCoordDrawTest(), mTextureCube(0), mTextureCubeUniformLocation(-1)
1686 {}
1687
getVertexShaderSource()1688 const char *getVertexShaderSource() override
1689 {
1690 return "#version 300 es\n"
1691 "out vec2 texcoord;\n"
1692 "in vec4 position;\n"
1693 "void main()\n"
1694 "{\n"
1695 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1696 " texcoord = 0.5*position.xy;\n"
1697 "}\n";
1698 }
1699
getFragmentShaderSource()1700 const char *getFragmentShaderSource() override
1701 {
1702 return "#version 300 es\n"
1703 "precision highp float;\n"
1704 "precision highp usamplerCube;\n"
1705 "uniform usamplerCube texCube;\n"
1706 "in vec2 texcoord;\n"
1707 "out vec4 fragColor;\n"
1708 "void main()\n"
1709 "{\n"
1710 " fragColor = vec4(texture(texCube, vec3(texcoord, 1)))/255.0;\n"
1711 "}\n";
1712 }
1713
testSetUp()1714 void testSetUp() override
1715 {
1716 TexCoordDrawTest::testSetUp();
1717 glGenTextures(1, &mTextureCube);
1718 setUpProgram();
1719
1720 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
1721 ASSERT_NE(-1, mTextureCubeUniformLocation);
1722 }
1723
testTearDown()1724 void testTearDown() override
1725 {
1726 glDeleteTextures(1, &mTextureCube);
1727 TexCoordDrawTest::testTearDown();
1728 }
1729
1730 GLuint mTextureCube;
1731 GLint mTextureCubeUniformLocation;
1732 };
1733
1734 class TextureCubeIntegerEdgeTestES3 : public TextureCubeIntegerTestES3
1735 {
1736 protected:
TextureCubeIntegerEdgeTestES3()1737 TextureCubeIntegerEdgeTestES3() : TextureCubeIntegerTestES3() {}
1738
getVertexShaderSource()1739 const char *getVertexShaderSource() override
1740 {
1741 return "#version 300 es\n"
1742 "out vec2 texcoord;\n"
1743 "in vec4 position;\n"
1744 "void main()\n"
1745 "{\n"
1746 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1747 " texcoord = position.xy;\n"
1748 "}\n";
1749 }
1750
getFragmentShaderSource()1751 const char *getFragmentShaderSource() override
1752 {
1753 return "#version 300 es\n"
1754 "precision highp float;\n"
1755 "precision highp usamplerCube;\n"
1756 "uniform usamplerCube texCube;\n"
1757 "in vec2 texcoord;\n"
1758 "out vec4 fragColor;\n"
1759 "void main()\n"
1760 "{\n"
1761 " fragColor = vec4(texture(texCube, vec3(texcoord, 0)))/255.0;\n"
1762 "}\n";
1763 }
1764 };
1765
1766 class Texture2DIntegerProjectiveOffsetTestES3 : public Texture2DTest
1767 {
1768 protected:
Texture2DIntegerProjectiveOffsetTestES3()1769 Texture2DIntegerProjectiveOffsetTestES3() : Texture2DTest() {}
1770
getVertexShaderSource()1771 const char *getVertexShaderSource() override
1772 {
1773 return "#version 300 es\n"
1774 "out vec2 texcoord;\n"
1775 "in vec4 position;\n"
1776 "void main()\n"
1777 "{\n"
1778 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1779 " texcoord = 0.5*position.xy + vec2(0.5, 0.5);\n"
1780 "}\n";
1781 }
1782
getFragmentShaderSource()1783 const char *getFragmentShaderSource() override
1784 {
1785 return "#version 300 es\n"
1786 "precision highp float;\n"
1787 "precision highp usampler2D;\n"
1788 "uniform usampler2D tex;\n"
1789 "in vec2 texcoord;\n"
1790 "out vec4 fragColor;\n"
1791 "void main()\n"
1792 "{\n"
1793 " fragColor = vec4(textureProjOffset(tex, vec3(texcoord, 1), ivec2(0,0), "
1794 "0.0))/255.0;\n"
1795 "}\n";
1796 }
1797 };
1798
1799 class Texture2DArrayIntegerTestES3 : public Texture2DArrayTestES3
1800 {
1801 protected:
Texture2DArrayIntegerTestES3()1802 Texture2DArrayIntegerTestES3() : Texture2DArrayTestES3() {}
1803
getVertexShaderSource()1804 const char *getVertexShaderSource() override
1805 {
1806 return R"(#version 300 es
1807 out vec2 texcoord;
1808 in vec4 position;
1809 void main()
1810 {
1811 gl_Position = vec4(position.xy, 0.0, 1.0);
1812 texcoord = (position.xy * 0.5) + 0.5;
1813 })";
1814 }
1815
getFragmentShaderSource()1816 const char *getFragmentShaderSource() override
1817 {
1818 return R"(#version 300 es
1819 precision highp float;
1820 uniform highp usampler2DArray tex2DArray;
1821 uniform int slice;
1822 in vec2 texcoord;
1823 out vec4 fragColor;
1824 void main()
1825 {
1826 fragColor = vec4(texture(tex2DArray, vec3(texcoord, slice)))/255.0;
1827 })";
1828 }
1829 };
1830
1831 class Texture3DIntegerTestES3 : public Texture3DTestES3
1832 {
1833 protected:
Texture3DIntegerTestES3()1834 Texture3DIntegerTestES3() : Texture3DTestES3() {}
1835
getVertexShaderSource()1836 const char *getVertexShaderSource() override
1837 {
1838 return "#version 300 es\n"
1839 "out vec2 texcoord;\n"
1840 "in vec4 position;\n"
1841 "void main()\n"
1842 "{\n"
1843 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1844 " texcoord = (position.xy * 0.5) + 0.5;\n"
1845 "}\n";
1846 }
1847
getFragmentShaderSource()1848 const char *getFragmentShaderSource() override
1849 {
1850 return "#version 300 es\n"
1851 "precision highp float;\n"
1852 "uniform highp usampler3D tex3D;\n"
1853 "in vec2 texcoord;\n"
1854 "out vec4 fragColor;\n"
1855 "void main()\n"
1856 "{\n"
1857 " fragColor = vec4(texture(tex3D, vec3(texcoord, 0.0)))/255.0;\n"
1858 "}\n";
1859 }
1860 };
1861
1862 class PBOCompressedTextureTest : public Texture2DTest
1863 {
1864 protected:
PBOCompressedTextureTest()1865 PBOCompressedTextureTest() : Texture2DTest() {}
1866
testSetUp()1867 void testSetUp() override
1868 {
1869 TexCoordDrawTest::testSetUp();
1870 glGenTextures(1, &mTexture2D);
1871 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1872 EXPECT_GL_NO_ERROR();
1873
1874 setUpProgram();
1875
1876 glGenBuffers(1, &mPBO);
1877 }
1878
testTearDown()1879 void testTearDown() override
1880 {
1881 glDeleteBuffers(1, &mPBO);
1882 Texture2DTest::testTearDown();
1883 }
1884
1885 void runCompressedSubImage();
1886
1887 GLuint mPBO;
1888 };
1889
1890 class ETC1CompressedTextureTest : public Texture2DTest
1891 {
1892 protected:
ETC1CompressedTextureTest()1893 ETC1CompressedTextureTest() : Texture2DTest() {}
1894
testSetUp()1895 void testSetUp() override
1896 {
1897 TexCoordDrawTest::testSetUp();
1898 glGenTextures(1, &mTexture2D);
1899 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1900 EXPECT_GL_NO_ERROR();
1901
1902 setUpProgram();
1903 }
1904
testTearDown()1905 void testTearDown() override { Texture2DTest::testTearDown(); }
1906 };
1907
1908 class Texture2DDepthStencilTestES3 : public Texture2DTest
1909 {
1910 protected:
Texture2DDepthStencilTestES3()1911 Texture2DDepthStencilTestES3() : Texture2DTest() {}
1912
1913 void TestSampleWithDepthStencilMode(GLenum format, GLenum mode, bool swizzle);
1914 };
1915
TestSampleWithDepthStencilMode(GLenum format,GLenum mode,bool swizzle)1916 void Texture2DDepthStencilTestES3::TestSampleWithDepthStencilMode(GLenum format,
1917 GLenum mode,
1918 bool swizzle)
1919 {
1920 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_stencil_texturing"));
1921
1922 constexpr GLsizei kSize = 4;
1923
1924 ASSERT(mode == GL_STENCIL_INDEX || mode == GL_DEPTH_COMPONENT);
1925
1926 bool isStencilMode;
1927 GLenum attachment;
1928 switch (format)
1929 {
1930 case GL_DEPTH_COMPONENT16:
1931 case GL_DEPTH_COMPONENT24:
1932 case GL_DEPTH_COMPONENT32F:
1933 attachment = GL_DEPTH_ATTACHMENT;
1934 isStencilMode = false;
1935 break;
1936 case GL_DEPTH24_STENCIL8:
1937 case GL_DEPTH32F_STENCIL8:
1938 attachment = GL_DEPTH_STENCIL_ATTACHMENT;
1939 isStencilMode = mode == GL_STENCIL_INDEX;
1940 break;
1941 case GL_STENCIL_INDEX8:
1942 attachment = GL_STENCIL_ATTACHMENT;
1943 isStencilMode = true;
1944 break;
1945 default:
1946 UNREACHABLE();
1947 }
1948
1949 // Set up a color texture.
1950 GLTexture colorTexture;
1951 glBindTexture(GL_TEXTURE_2D, colorTexture);
1952 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
1953 ASSERT_GL_NO_ERROR();
1954
1955 // Set up a depth/stencil texture to be sampled as mode.
1956 GLTexture depthStencilTexture;
1957 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
1958 glTexStorage2D(GL_TEXTURE_2D, 1, format, kSize, kSize);
1959 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1960 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1961 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, mode);
1962 if (swizzle)
1963 {
1964 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ALPHA);
1965 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
1966 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_GREEN);
1967 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
1968 }
1969 ASSERT_GL_NO_ERROR();
1970
1971 constexpr char kStencilFS[] =
1972 R"(#version 300 es
1973 precision mediump float;
1974 uniform highp usampler2D tex;
1975 out vec4 color;
1976 void main()
1977 {
1978 color = vec4(texelFetch(tex, ivec2(0, 0), 0)) / 255.0f;
1979 })";
1980
1981 constexpr char kDepthFS[] =
1982 R"(#version 300 es
1983 precision mediump float;
1984 uniform highp sampler2D tex;
1985 out vec4 color;
1986 void main()
1987 {
1988 color = texture(tex, vec2(0, 0));
1989 })";
1990
1991 // Clear stencil to 42.
1992 GLFramebuffer clearFBO;
1993 glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
1994 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, depthStencilTexture, 0);
1995 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1996 glClearDepthf(0.5);
1997 glClearStencil(42);
1998 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1999 ASSERT_GL_NO_ERROR();
2000
2001 glActiveTexture(GL_TEXTURE0);
2002 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
2003 EXPECT_GL_ERROR(GL_NO_ERROR);
2004
2005 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), isStencilMode ? kStencilFS : kDepthFS);
2006 GLint texLocation = glGetUniformLocation(program, "tex");
2007 ASSERT_NE(-1, texLocation);
2008 ASSERT_GL_NO_ERROR();
2009
2010 glUseProgram(program);
2011 glUniform1i(texLocation, 0);
2012
2013 GLFramebuffer drawFBO;
2014 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
2015 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2016 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2017 ASSERT_GL_NO_ERROR();
2018
2019 drawQuad(program, essl3_shaders::PositionAttrib(), 0.95f);
2020 ASSERT_GL_NO_ERROR();
2021
2022 if (isStencilMode)
2023 {
2024 GLColor expected = swizzle ? GLColor(1, 0, 0, 42) : GLColor(42, 0, 0, 1);
2025 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, expected);
2026 }
2027 else
2028 {
2029 GLColor expected = swizzle ? GLColor(255, 0, 0, 127) : GLColor(127, 0, 0, 255);
2030 EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
2031 }
2032 }
2033
TEST_P(Texture2DTest,NegativeAPISubImage)2034 TEST_P(Texture2DTest, NegativeAPISubImage)
2035 {
2036 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2037 EXPECT_GL_ERROR(GL_NO_ERROR);
2038
2039 setUpProgram();
2040
2041 const GLubyte *pixels[20] = {0};
2042 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2043 EXPECT_GL_ERROR(GL_INVALID_VALUE);
2044
2045 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
2046 {
2047 // Create a 1-level immutable texture.
2048 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
2049
2050 // Try calling sub image on the second level.
2051 glTexSubImage2D(GL_TEXTURE_2D, 1, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2052 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2053 }
2054 }
2055
2056 // Test that querying GL_TEXTURE_BINDING* doesn't cause an unexpected error.
TEST_P(Texture2DTest,QueryBinding)2057 TEST_P(Texture2DTest, QueryBinding)
2058 {
2059 glBindTexture(GL_TEXTURE_2D, 0);
2060 EXPECT_GL_ERROR(GL_NO_ERROR);
2061
2062 GLint textureBinding;
2063 glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
2064 EXPECT_GL_NO_ERROR();
2065 EXPECT_EQ(0, textureBinding);
2066
2067 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &textureBinding);
2068 if (IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
2069 IsGLExtensionEnabled("GL_NV_EGL_stream_consumer_external"))
2070 {
2071 EXPECT_GL_NO_ERROR();
2072 EXPECT_EQ(0, textureBinding);
2073 }
2074 else
2075 {
2076 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2077 }
2078 }
2079
TEST_P(Texture2DTest,ZeroSizedUploads)2080 TEST_P(Texture2DTest, ZeroSizedUploads)
2081 {
2082 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2083 EXPECT_GL_ERROR(GL_NO_ERROR);
2084
2085 setUpProgram();
2086
2087 // Use the texture first to make sure it's in video memory
2088 glUseProgram(mProgram);
2089 glUniform1i(mTexture2DUniformLocation, 0);
2090 drawQuad(mProgram, "position", 0.5f);
2091
2092 const GLubyte *pixel[4] = {0};
2093
2094 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2095 EXPECT_GL_NO_ERROR();
2096
2097 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2098 EXPECT_GL_NO_ERROR();
2099
2100 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2101 EXPECT_GL_NO_ERROR();
2102 }
2103
2104 // Tests uploading a red texture and immediately reading from it.
TEST_P(Texture2DTest,SimpleUpload)2105 TEST_P(Texture2DTest, SimpleUpload)
2106 {
2107 const GLuint width = getWindowWidth();
2108 const GLuint height = getWindowHeight();
2109 const GLuint windowPixelCount = width * height;
2110 std::vector<GLColor> pixelsRed(windowPixelCount, GLColor::red);
2111 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2112 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2113 pixelsRed.data());
2114 EXPECT_GL_ERROR(GL_NO_ERROR);
2115
2116 GLFramebuffer fbo;
2117 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2118
2119 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0);
2120
2121 EXPECT_GL_ERROR(GL_NO_ERROR);
2122 std::vector<GLColor> output(windowPixelCount, GLColor::green);
2123 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, output.data());
2124 EXPECT_EQ(pixelsRed, output);
2125 }
2126
2127 // Test that interleaved superseded updates work as expected
TEST_P(Texture2DTest,InterleavedSupersedingTextureUpdates)2128 TEST_P(Texture2DTest, InterleavedSupersedingTextureUpdates)
2129 {
2130 constexpr uint32_t kTexWidth = 3840;
2131 constexpr uint32_t kTexHeight = 2160;
2132 constexpr uint32_t kBpp = 4;
2133
2134 // Create the texture
2135 glActiveTexture(GL_TEXTURE0);
2136 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2138 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2139 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2140 nullptr);
2141 EXPECT_GL_ERROR(GL_NO_ERROR);
2142
2143 // 1. One big upload followed by many small identical uploads
2144 // Update the entire texture
2145 std::vector<GLubyte> fullTextureData(kTexWidth * kTexHeight * kBpp, 128);
2146 constexpr GLColor kFullTextureColor = GLColor(128u, 128u, 128u, 128u);
2147 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2148 fullTextureData.data());
2149
2150 // Make a number of identical updates to the right half of the texture
2151 std::vector<GLubyte> rightHalfData(kTexWidth * kTexHeight * kBpp, 201);
2152 constexpr GLColor kRightHalfColor = GLColor(201u, 201u, 201u, 201u);
2153 for (uint32_t iteration = 0; iteration < 10; iteration++)
2154 {
2155 glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, 0, kTexWidth / 2, kTexHeight, GL_RGBA,
2156 GL_UNSIGNED_BYTE, rightHalfData.data());
2157 }
2158
2159 setUpProgram();
2160 glUseProgram(mProgram);
2161 glUniform1i(mTexture2DUniformLocation, 0);
2162 drawQuad(mProgram, "position", 0.5f);
2163 EXPECT_GL_NO_ERROR();
2164 EXPECT_PIXEL_COLOR_EQ(1 * getWindowWidth() / 4, getWindowHeight() / 2, kFullTextureColor);
2165 EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 2, kRightHalfColor);
2166
2167 // 2. Some small uploads followed by one big upload followed by many identical uploads
2168 // Clear the entire texture
2169 std::vector<GLubyte> zeroTextureData(kTexWidth * kTexHeight * kBpp, 255);
2170 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2171 zeroTextureData.data());
2172
2173 // Update the top left quadrant of the texture
2174 std::vector<GLubyte> topLeftQuadrantData(kTexWidth * kTexHeight * kBpp, 128);
2175 constexpr GLColor kTopLeftQuandrantTextureColor = GLColor(128u, 128u, 128u, 128u);
2176 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2, GL_RGBA,
2177 GL_UNSIGNED_BYTE, topLeftQuadrantData.data());
2178
2179 // Update the top right quadrant of the texture
2180 std::vector<GLubyte> topRightQuadrantData(kTexWidth * kTexHeight * kBpp, 156);
2181 constexpr GLColor kTopRightQuadrantTextureColor = GLColor(156u, 156u, 156u, 156u);
2182 glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2,
2183 GL_RGBA, GL_UNSIGNED_BYTE, topRightQuadrantData.data());
2184
2185 // Update the bottom half of the texture
2186 std::vector<GLubyte> bottomHalfTextureData(kTexWidth * kTexHeight * kBpp, 187);
2187 constexpr GLColor kBottomHalfTextureColor = GLColor(187u, 187u, 187u, 187u);
2188 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight / 2, GL_RGBA, GL_UNSIGNED_BYTE,
2189 bottomHalfTextureData.data());
2190
2191 // Make a number of identical updates to the bottom right quadrant of the texture
2192 std::vector<GLubyte> bottomRightQuadrantData(kTexWidth * kTexHeight * kBpp, 201);
2193 constexpr GLColor kBottomRightQuadrantColor = GLColor(201u, 201u, 201u, 201u);
2194 for (uint32_t iteration = 0; iteration < 10; iteration++)
2195 {
2196 glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, 0, kTexWidth / 2, kTexHeight / 2, GL_RGBA,
2197 GL_UNSIGNED_BYTE, bottomRightQuadrantData.data());
2198 }
2199
2200 setUpProgram();
2201 glUseProgram(mProgram);
2202 glUniform1i(mTexture2DUniformLocation, 0);
2203 drawQuad(mProgram, "position", 0.5f);
2204 EXPECT_GL_NO_ERROR();
2205 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, kTopLeftQuandrantTextureColor);
2206 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1,
2207 kTopRightQuadrantTextureColor);
2208 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, kBottomHalfTextureColor);
2209 EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4,
2210 kBottomRightQuadrantColor);
2211
2212 // 3. Many small uploads folloed by one big upload
2213 // Clear the entire texture
2214 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2215 zeroTextureData.data());
2216
2217 // Make a number of small updates to different parts of the texture
2218 std::vector<std::pair<GLint, GLint>> xyOffsets = {
2219 {1, 4}, {128, 34}, {1208, 1090}, {2560, 2022}};
2220 constexpr GLColor kRandomColor = GLColor(55u, 128u, 201u, 255u);
2221 for (const std::pair<GLint, GLint> &xyOffset : xyOffsets)
2222 {
2223 glTexSubImage2D(GL_TEXTURE_2D, 0, xyOffset.first, xyOffset.second, 1, 1, GL_RGBA,
2224 GL_UNSIGNED_BYTE, kRandomColor.data());
2225 }
2226
2227 // Update the entire texture
2228 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2229 fullTextureData.data());
2230
2231 setUpProgram();
2232 glUseProgram(mProgram);
2233 glUniform1i(mTexture2DUniformLocation, 0);
2234 drawQuad(mProgram, "position", 0.5f);
2235 EXPECT_GL_NO_ERROR();
2236 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth() - 1, getWindowHeight() - 1, kFullTextureColor);
2237 }
2238
2239 // Test that repeated calls to glTexSubImage2D with superseding updates works
TEST_P(Texture2DTest,ManySupersedingTextureUpdates)2240 TEST_P(Texture2DTest, ManySupersedingTextureUpdates)
2241 {
2242 constexpr uint32_t kTexWidth = 3840;
2243 constexpr uint32_t kTexHeight = 2160;
2244 constexpr uint32_t kBpp = 4;
2245 std::vector<GLubyte> data(kTexWidth * kTexHeight * kBpp, 0);
2246
2247 // Create the texture
2248 glActiveTexture(GL_TEXTURE0);
2249 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2252 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2253 nullptr);
2254 EXPECT_GL_ERROR(GL_NO_ERROR);
2255
2256 // Make a large number of superseding updates
2257 for (uint32_t width = kTexWidth / 2, height = kTexHeight / 2;
2258 width < kTexWidth && height < kTexHeight; width++, height++)
2259 {
2260 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
2261 data.data());
2262 }
2263
2264 // Upload different color to the whole texture thus superseding all prior updates.
2265 std::vector<GLubyte> supersedingData(kTexWidth * kTexHeight * kBpp, 128);
2266 constexpr GLColor kGray = GLColor(128u, 128u, 128u, 128u);
2267 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2268 supersedingData.data());
2269
2270 setUpProgram();
2271 glUseProgram(mProgram);
2272 glUniform1i(mTexture2DUniformLocation, 0);
2273 drawQuad(mProgram, "position", 0.5f);
2274 EXPECT_GL_NO_ERROR();
2275 EXPECT_PIXEL_COLOR_EQ(0, 0, kGray);
2276 }
2277
TEST_P(Texture2DTest,DefineMultipleLevelsWithoutMipmapping)2278 TEST_P(Texture2DTest, DefineMultipleLevelsWithoutMipmapping)
2279 {
2280 setUpProgram();
2281
2282 constexpr size_t kImageSize = 256;
2283 std::array<GLColor, kImageSize * kImageSize> kMipColors[2];
2284
2285 std::fill(kMipColors[0].begin(), kMipColors[0].end(), GLColor::red);
2286 std::fill(kMipColors[1].begin(), kMipColors[1].end(), GLColor::green);
2287
2288 glActiveTexture(GL_TEXTURE0);
2289 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2290 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2291 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2292
2293 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2294 kMipColors[0].data());
2295 EXPECT_GL_NO_ERROR();
2296
2297 // Draw so the image is created.
2298 glUseProgram(mProgram);
2299 glUniform1i(mTexture2DUniformLocation, 0);
2300 drawQuad(mProgram, "position", 0.5f);
2301
2302 // Define level 1 of the texture.
2303 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2304 kMipColors[1].data());
2305 EXPECT_GL_NO_ERROR();
2306
2307 // Draw again.
2308 drawQuad(mProgram, "position", 0.5f);
2309 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0][0]);
2310 }
2311
2312 // Test drawing with two texture types, to trigger an ANGLE bug in validation
TEST_P(TextureCubeTest,CubeMapBug)2313 TEST_P(TextureCubeTest, CubeMapBug)
2314 {
2315 glActiveTexture(GL_TEXTURE0);
2316 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2317 glActiveTexture(GL_TEXTURE1);
2318 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2319 EXPECT_GL_ERROR(GL_NO_ERROR);
2320
2321 glUseProgram(mProgram);
2322 glUniform1i(mTexture2DUniformLocation, 0);
2323 glUniform1i(mTextureCubeUniformLocation, 1);
2324 drawQuad(mProgram, "position", 0.5f);
2325 EXPECT_GL_NO_ERROR();
2326 }
2327
2328 // Test drawing with two texture types accessed from the same shader and check that the result of
2329 // drawing is correct.
TEST_P(TextureCubeTest,CubeMapDraw)2330 TEST_P(TextureCubeTest, CubeMapDraw)
2331 {
2332 GLubyte texData[4];
2333 texData[0] = 0;
2334 texData[1] = 60;
2335 texData[2] = 0;
2336 texData[3] = 255;
2337
2338 glActiveTexture(GL_TEXTURE0);
2339 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2340 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
2341
2342 glActiveTexture(GL_TEXTURE1);
2343 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2344 texData[1] = 120;
2345 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2346 texData);
2347 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2348 texData);
2349 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2350 texData);
2351 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2352 texData);
2353 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2354 texData);
2355 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2356 texData);
2357 EXPECT_GL_ERROR(GL_NO_ERROR);
2358
2359 glUseProgram(mProgram);
2360 glUniform1i(mTexture2DUniformLocation, 0);
2361 glUniform1i(mTextureCubeUniformLocation, 1);
2362 drawQuad(mProgram, "position", 0.5f);
2363 EXPECT_GL_NO_ERROR();
2364
2365 int px = getWindowWidth() - 1;
2366 int py = 0;
2367 EXPECT_PIXEL_NEAR(px, py, 0, 180, 0, 255, 2);
2368 }
2369
TEST_P(Sampler2DAsFunctionParameterTest,Sampler2DAsFunctionParameter)2370 TEST_P(Sampler2DAsFunctionParameterTest, Sampler2DAsFunctionParameter)
2371 {
2372 glActiveTexture(GL_TEXTURE0);
2373 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2374 GLubyte texData[4];
2375 texData[0] = 0;
2376 texData[1] = 128;
2377 texData[2] = 0;
2378 texData[3] = 255;
2379 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
2380 glUseProgram(mProgram);
2381 glUniform1i(mTexture2DUniformLocation, 0);
2382 drawQuad(mProgram, "position", 0.5f);
2383 EXPECT_GL_NO_ERROR();
2384
2385 EXPECT_PIXEL_NEAR(0, 0, 0, 128, 0, 255, 2);
2386 }
2387
2388 // Test drawing with two textures passed to the shader in a sampler array.
TEST_P(SamplerArrayTest,SamplerArrayDraw)2389 TEST_P(SamplerArrayTest, SamplerArrayDraw)
2390 {
2391 testSamplerArrayDraw();
2392 }
2393
2394 // Test drawing with two textures passed to the shader in a sampler array which is passed to a
2395 // user-defined function in the shader.
TEST_P(SamplerArrayAsFunctionParameterTest,SamplerArrayAsFunctionParameter)2396 TEST_P(SamplerArrayAsFunctionParameterTest, SamplerArrayAsFunctionParameter)
2397 {
2398 // TODO: Diagnose and fix. http://anglebug.com/42261649
2399 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
2400
2401 testSamplerArrayDraw();
2402 }
2403
2404 // Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
TEST_P(Texture2DTestWithDrawScale,MipmapsTwice)2405 TEST_P(Texture2DTestWithDrawScale, MipmapsTwice)
2406 {
2407 int px = getWindowWidth() / 2;
2408 int py = getWindowHeight() / 2;
2409
2410 glActiveTexture(GL_TEXTURE0);
2411 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2412
2413 std::vector<GLColor> pixelsRed(16u * 16u, GLColor::red);
2414
2415 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
2416 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
2417 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2418 glGenerateMipmap(GL_TEXTURE_2D);
2419
2420 glUseProgram(mProgram);
2421 glUniform1i(mTexture2DUniformLocation, 0);
2422 glUniform2f(mDrawScaleUniformLocation, 0.0625f, 0.0625f);
2423 drawQuad(mProgram, "position", 0.5f);
2424 EXPECT_GL_NO_ERROR();
2425 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
2426
2427 std::vector<GLColor> pixelsBlue(16u * 16u, GLColor::blue);
2428
2429 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2430 pixelsBlue.data());
2431 glGenerateMipmap(GL_TEXTURE_2D);
2432
2433 drawQuad(mProgram, "position", 0.5f);
2434
2435 EXPECT_GL_NO_ERROR();
2436 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::blue);
2437
2438 std::vector<GLColor> pixelsGreen(16u * 16u, GLColor::green);
2439
2440 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2441 pixelsGreen.data());
2442 glGenerateMipmap(GL_TEXTURE_2D);
2443
2444 drawQuad(mProgram, "position", 0.5f);
2445
2446 EXPECT_GL_NO_ERROR();
2447 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
2448 }
2449
2450 // Test creating a FBO with a cube map render target, to test an ANGLE bug
2451 // https://code.google.com/p/angleproject/issues/detail?id=849
TEST_P(TextureCubeTest,CubeMapFBO)2452 TEST_P(TextureCubeTest, CubeMapFBO)
2453 {
2454 // http://anglebug.com/42261821
2455 ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
2456
2457 GLFramebuffer fbo;
2458 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2459
2460 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2461 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
2462 mTextureCube, 0);
2463
2464 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2465 EXPECT_GL_NO_ERROR();
2466
2467 // Test clearing the six mip faces individually.
2468 std::array<GLColor, 6> faceColors = {{GLColor::red, GLColor::green, GLColor::blue,
2469 GLColor::yellow, GLColor::cyan, GLColor::magenta}};
2470
2471 for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
2472 {
2473 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2474 GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
2475
2476 Vector4 clearColorF = faceColors[faceIndex].toNormalizedVector();
2477 glClearColor(clearColorF.x(), clearColorF.y(), clearColorF.z(), clearColorF.w());
2478 glClear(GL_COLOR_BUFFER_BIT);
2479
2480 EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex]);
2481 }
2482
2483 // Iterate the faces again to make sure the colors haven't changed.
2484 for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
2485 {
2486 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2487 GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
2488 EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex])
2489 << "face color " << faceIndex << " shouldn't change";
2490 }
2491 }
2492
2493 // Tests clearing a cube map with a scissor enabled.
TEST_P(TextureCubeTest,CubeMapFBOScissoredClear)2494 TEST_P(TextureCubeTest, CubeMapFBOScissoredClear)
2495 {
2496 // http://anglebug.com/42261821
2497 ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
2498
2499 constexpr size_t kSize = 16;
2500
2501 GLFramebuffer fbo;
2502 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2503 glViewport(0, 0, kSize, kSize);
2504
2505 GLTexture texcube;
2506 glBindTexture(GL_TEXTURE_CUBE_MAP, texcube);
2507 for (GLenum face = 0; face < 6; face++)
2508 {
2509 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
2510 GL_UNSIGNED_BYTE, nullptr);
2511 }
2512 ASSERT_GL_NO_ERROR();
2513
2514 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
2515 texcube, 0);
2516
2517 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2518 ASSERT_GL_NO_ERROR();
2519
2520 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2521 glClear(GL_COLOR_BUFFER_BIT);
2522 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2523
2524 glEnable(GL_SCISSOR_TEST);
2525 glScissor(kSize / 2, 0, kSize / 2, kSize);
2526 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2527 glClear(GL_COLOR_BUFFER_BIT);
2528
2529 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2530 EXPECT_PIXEL_COLOR_EQ(kSize / 2 + 1, 0, GLColor::green);
2531
2532 ASSERT_GL_NO_ERROR();
2533 }
2534
2535 // Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
2536 // default color.
TEST_P(Texture2DTest,TexStorage)2537 TEST_P(Texture2DTest, TexStorage)
2538 {
2539 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
2540 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
2541
2542 int width = getWindowWidth();
2543 int height = getWindowHeight();
2544
2545 GLTexture tex2D;
2546 glActiveTexture(GL_TEXTURE0);
2547 glBindTexture(GL_TEXTURE_2D, tex2D);
2548
2549 // Fill with red
2550 std::vector<GLubyte> pixels(3 * 16 * 16);
2551 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2552 {
2553 pixels[pixelId * 3 + 0] = 255;
2554 pixels[pixelId * 3 + 1] = 0;
2555 pixels[pixelId * 3 + 2] = 0;
2556 }
2557
2558 // ANGLE internally uses RGBA as the DirectX format for RGB images
2559 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent
2560 // alpha color. The data is kept in a CPU-side image and the image is marked as dirty.
2561 if (getClientMajorVersion() >= 3)
2562 {
2563 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2564 }
2565 else
2566 {
2567 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2568 }
2569
2570 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2571 // glTexSubImage2D should take into account that the image is dirty.
2572 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
2573 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2574 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2575
2576 setUpProgram();
2577
2578 glUseProgram(mProgram);
2579 glUniform1i(mTexture2DUniformLocation, 0);
2580 drawQuad(mProgram, "position", 0.5f);
2581 EXPECT_GL_NO_ERROR();
2582 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2583
2584 // Validate that the region of the texture without data has an alpha of 1.0
2585 angle::GLColor pixel = ReadColor(3 * width / 4, 3 * height / 4);
2586 EXPECT_EQ(255, pixel.A);
2587 }
2588
2589 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2590 // initialized the image with a default color.
TEST_P(Texture2DTest,TexStorageWithPBO)2591 TEST_P(Texture2DTest, TexStorageWithPBO)
2592 {
2593 if (getClientMajorVersion() < 3)
2594 {
2595 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2596 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2597 }
2598
2599 const int width = getWindowWidth();
2600 const int height = getWindowHeight();
2601 const size_t pixelCount = width * height;
2602 const int componentCount = 3;
2603
2604 GLTexture tex2D;
2605 glActiveTexture(GL_TEXTURE0);
2606 glBindTexture(GL_TEXTURE_2D, tex2D);
2607
2608 // Fill with red
2609 std::vector<GLubyte> pixels(componentCount * pixelCount);
2610 for (size_t pixelId = 0; pixelId < pixelCount; ++pixelId)
2611 {
2612 pixels[pixelId * componentCount + 0] = 255;
2613 pixels[pixelId * componentCount + 1] = 0;
2614 pixels[pixelId * componentCount + 2] = 0;
2615 }
2616
2617 // Read 16x16 region from red backbuffer to PBO
2618 GLuint pbo;
2619 glGenBuffers(1, &pbo);
2620 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2621 glBufferData(GL_PIXEL_UNPACK_BUFFER, componentCount * pixelCount, pixels.data(),
2622 GL_STATIC_DRAW);
2623
2624 // ANGLE internally uses RGBA as the DirectX format for RGB images
2625 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent
2626 // alpha color. The data is kept in a CPU-side image and the image is marked as dirty.
2627 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, width, height);
2628
2629 // Initializes the color of the upper-left quadrant of pixels, leaves the other pixels
2630 // untouched. glTexSubImage2D should take into account that the image is dirty.
2631 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RGB, GL_UNSIGNED_BYTE,
2632 nullptr);
2633 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2634 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2635
2636 setUpProgram();
2637
2638 glUseProgram(mProgram);
2639 glUniform1i(mTexture2DUniformLocation, 0);
2640 drawQuad(mProgram, "position", 0.5f);
2641 glDeleteBuffers(1, &pbo);
2642 EXPECT_GL_NO_ERROR();
2643 EXPECT_PIXEL_RECT_EQ(0, 0, width / 2, height / 2, GLColor(255, 0, 0, 255));
2644 }
2645
2646 // Test that glTexSubImage2D combined with a PBO works properly after deleting the PBO
2647 // and drawing with the texture
2648 // Pseudo code for the follow test:
2649 // 1. Upload PBO to mTexture2D
2650 // 2. Delete PBO
2651 // 3. Draw with otherTexture (x5)
2652 // 4. Draw with mTexture2D
2653 // 5. Validate color output
TEST_P(Texture2DTest,PBOWithMultipleDraws)2654 TEST_P(Texture2DTest, PBOWithMultipleDraws)
2655 {
2656 if (getClientMajorVersion() < 3)
2657 {
2658 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2659 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2660 }
2661
2662 const GLuint width = getWindowWidth();
2663 const GLuint height = getWindowHeight();
2664 const GLuint windowPixelCount = width * height;
2665 std::vector<GLColor> pixelsRed(windowPixelCount, GLColor::red);
2666 std::vector<GLColor> pixelsGreen(windowPixelCount, GLColor::green);
2667
2668 // Create secondary draw that does not use mTexture
2669 const char *vertexShaderSource = getVertexShaderSource();
2670 const char *fragmentShaderSource = getFragmentShaderSource();
2671 ANGLE_GL_PROGRAM(otherProgram, vertexShaderSource, fragmentShaderSource);
2672
2673 GLint uniformLoc = glGetUniformLocation(otherProgram, getTextureUniformName());
2674 ASSERT_NE(-1, uniformLoc);
2675 glUseProgram(0);
2676
2677 // Create secondary Texture to draw with
2678 GLTexture otherTexture;
2679 glActiveTexture(GL_TEXTURE0);
2680 glBindTexture(GL_TEXTURE_2D, otherTexture);
2681 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2682 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
2683 pixelsRed.data());
2684 ASSERT_GL_NO_ERROR();
2685
2686 // Setup primary Texture
2687 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2688 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2689 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2690 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2691 ASSERT_GL_NO_ERROR();
2692
2693 // Setup PBO
2694 GLuint pbo = 0;
2695 glGenBuffers(1, &pbo);
2696 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2697 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
2698 GL_STATIC_DRAW);
2699 ASSERT_GL_NO_ERROR();
2700
2701 // Write PBO to mTexture
2702 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2703 ASSERT_GL_NO_ERROR();
2704 // Delete PBO as ANGLE should be properly handling refcount of this buffer
2705 glDeleteBuffers(1, &pbo);
2706 pixelsGreen.clear();
2707
2708 // Do 5 draws not involving primary texture that the PBO updated
2709 glUseProgram(otherProgram);
2710 glUniform1i(uniformLoc, 0);
2711 glBindTexture(GL_TEXTURE_2D, otherTexture);
2712 drawQuad(otherProgram, "position", 0.5f);
2713 glBindTexture(GL_TEXTURE_2D, 0);
2714 glUseProgram(0);
2715
2716 glUseProgram(otherProgram);
2717 glUniform1i(uniformLoc, 0);
2718 glBindTexture(GL_TEXTURE_2D, otherTexture);
2719 drawQuad(otherProgram, "position", 0.5f);
2720 glBindTexture(GL_TEXTURE_2D, 0);
2721 glUseProgram(0);
2722
2723 glUseProgram(otherProgram);
2724 glUniform1i(uniformLoc, 0);
2725 glBindTexture(GL_TEXTURE_2D, otherTexture);
2726 drawQuad(otherProgram, "position", 0.5f);
2727 glBindTexture(GL_TEXTURE_2D, 0);
2728 glUseProgram(0);
2729
2730 glUseProgram(otherProgram);
2731 glUniform1i(uniformLoc, 0);
2732 glBindTexture(GL_TEXTURE_2D, otherTexture);
2733 drawQuad(otherProgram, "position", 0.5f);
2734 glBindTexture(GL_TEXTURE_2D, 0);
2735 glUseProgram(0);
2736 ASSERT_GL_NO_ERROR();
2737
2738 std::vector<GLColor> output(windowPixelCount, GLColor::black);
2739 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2740 output.data());
2741 EXPECT_EQ(pixelsRed, output);
2742
2743 setUpProgram();
2744 // Draw using PBO updated texture
2745 glUseProgram(mProgram);
2746 glUniform1i(mTexture2DUniformLocation, 0);
2747 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2748 drawQuad(mProgram, "position", 0.5f);
2749 ASSERT_GL_NO_ERROR();
2750
2751 std::vector<GLColor> actual(windowPixelCount, GLColor::black);
2752 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2753 actual.data());
2754 // Value should be green as it was updated during PBO transfer to mTexture
2755 std::vector<GLColor> expected(windowPixelCount, GLColor::green);
2756 EXPECT_EQ(expected, actual);
2757 }
2758
2759 // Almost mirrors UnitTest_DMSAA_dst_read test from Android skqp test suite
TEST_P(Texture2DTestES3,UnitTest_DMSAA_dst_read)2760 TEST_P(Texture2DTestES3, UnitTest_DMSAA_dst_read)
2761 {
2762 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB_write_control"));
2763
2764 GLTexture texture;
2765 glActiveTexture(GL_TEXTURE31);
2766 glBindTexture(GL_TEXTURE_2D, texture);
2767 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2768 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2769 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2771 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
2772 glBindTexture(GL_TEXTURE_2D, 0);
2773
2774 GLFramebuffer fboTexture;
2775 glBindFramebuffer(GL_FRAMEBUFFER, fboTexture);
2776 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2777 glCheckFramebufferStatus(GL_FRAMEBUFFER);
2778
2779 GLFramebuffer fboRenderbuffer;
2780 GLRenderbuffer renderbuffer;
2781 glBindFramebuffer(GL_FRAMEBUFFER, fboRenderbuffer);
2782 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
2783 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 16, 16);
2784 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
2785 glCheckFramebufferStatus(GL_FRAMEBUFFER);
2786
2787 glActiveTexture(GL_TEXTURE0);
2788 glBindTexture(GL_TEXTURE_2D, texture);
2789 GLSampler sampler;
2790 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2791 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2792 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2793 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2794 glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.000000);
2795 glBindSampler(0, sampler);
2796 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
2797
2798 glBindFramebuffer(GL_FRAMEBUFFER, fboRenderbuffer);
2799 glViewport(0, 0, 16, 16);
2800 glDisable(GL_FRAMEBUFFER_SRGB_EXT);
2801
2802 // Create texture program
2803 ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
2804 ASSERT_GL_NO_ERROR();
2805 GLint texLocation = glGetUniformLocation(drawTexture, "u_tex2D");
2806 ASSERT_NE(-1, texLocation);
2807 glUniform1i(texLocation, 0);
2808
2809 glDisable(GL_BLEND);
2810 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2811 glDisable(GL_SCISSOR_TEST);
2812 glDisable(GL_STENCIL_TEST);
2813
2814 glEnable(GL_FRAMEBUFFER_SRGB_EXT);
2815 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
2816
2817 glDisable(GL_FRAMEBUFFER_SRGB_EXT);
2818 glEnable(GL_SCISSOR_TEST);
2819 glScissor(0, 6, 10, 10);
2820
2821 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
2822
2823 // Blit fboRenderbuffer onto fboTexture
2824 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboRenderbuffer);
2825 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboTexture);
2826 glDisable(GL_SCISSOR_TEST);
2827 glBlitFramebuffer(0, 6, 10, 16, 0, 6, 10, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2828 GLenum attachment = GL_COLOR_ATTACHMENT0;
2829 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &attachment);
2830
2831 glBindFramebuffer(GL_FRAMEBUFFER, fboTexture);
2832 std::array<GLubyte, 10 * 10 * 4> pixelData;
2833 glReadPixels(0, 6, 10, 10, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data());
2834 glFinish();
2835
2836 glClearColor(1.000000, 1.000000, 1.000000, 1.000000);
2837 glClear(GL_COLOR_BUFFER_BIT);
2838
2839 glBindFramebuffer(GL_FRAMEBUFFER, fboRenderbuffer);
2840 glEnable(GL_FRAMEBUFFER_SRGB_EXT);
2841 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
2842
2843 glDisable(GL_FRAMEBUFFER_SRGB_EXT);
2844 glEnable(GL_SCISSOR_TEST);
2845 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
2846
2847 // Blit fboRenderbuffer onto fboTexture
2848 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboRenderbuffer);
2849 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboTexture);
2850 glDisable(GL_SCISSOR_TEST);
2851 glBlitFramebuffer(0, 6, 10, 16, 0, 6, 10, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2852 attachment = GL_COLOR_ATTACHMENT0;
2853 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &attachment);
2854 glFinish();
2855
2856 glBindFramebuffer(GL_FRAMEBUFFER, fboRenderbuffer);
2857 glEnable(GL_FRAMEBUFFER_SRGB_EXT);
2858 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
2859
2860 glDisable(GL_FRAMEBUFFER_SRGB_EXT);
2861 glEnable(GL_SCISSOR_TEST);
2862 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
2863
2864 // Blit fboRenderbuffer onto fboTexture
2865 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboRenderbuffer);
2866 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboTexture);
2867 glDisable(GL_SCISSOR_TEST);
2868 glBlitFramebuffer(0, 6, 10, 16, 0, 6, 10, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2869 attachment = GL_COLOR_ATTACHMENT0;
2870 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &attachment);
2871 glFinish();
2872
2873 glBindFramebuffer(GL_FRAMEBUFFER, fboTexture);
2874 glReadPixels(0, 6, 10, 10, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data());
2875 glFinish();
2876 }
2877
2878 // Test that stencil texture uploads work.
TEST_P(Texture2DTestES3,TexImageWithStencilData)2879 TEST_P(Texture2DTestES3, TexImageWithStencilData)
2880 {
2881 constexpr GLsizei kSize = 4;
2882
2883 const std::array<std::tuple<GLenum, GLenum, int, int>, 3> testConfigs = {
2884 std::make_tuple(GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, 4),
2885 std::make_tuple(GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, 4, 0),
2886 std::make_tuple(GL_STENCIL_INDEX8, GL_UNSIGNED_BYTE, 1, 0)};
2887
2888 for (auto testConfig : testConfigs)
2889 {
2890 const GLenum format = std::get<0>(testConfig);
2891 const GLenum type = std::get<1>(testConfig);
2892 const GLenum typeLength = std::get<2>(testConfig);
2893 const GLenum typeOffset = std::get<3>(testConfig);
2894
2895 ANGLE_SKIP_TEST_IF(format == GL_STENCIL_INDEX8 &&
2896 !IsGLExtensionEnabled("GL_OES_texture_stencil8"));
2897
2898 // Set up the framebuffer
2899 GLTexture colorTexture;
2900 glBindTexture(GL_TEXTURE_2D, colorTexture);
2901 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2902 nullptr);
2903 ASSERT_GL_NO_ERROR();
2904
2905 GLTexture depthStencilTexture;
2906 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
2907
2908 GLubyte pixels[kSize * kSize * 8] = {};
2909 for (size_t pixelId = 0; pixelId < kSize * kSize; ++pixelId)
2910 {
2911 pixels[pixelId * typeLength + typeOffset] = 0xD5;
2912 }
2913 glTexImage2D(GL_TEXTURE_2D, 0, format, kSize, kSize, 0,
2914 format == GL_STENCIL_INDEX8 ? GL_STENCIL_INDEX : GL_DEPTH_STENCIL, type,
2915 pixels);
2916 ASSERT_GL_NO_ERROR();
2917
2918 GLFramebuffer fbo;
2919 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2920 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
2921 0);
2922 glFramebufferTexture2D(
2923 GL_FRAMEBUFFER,
2924 format == GL_STENCIL_INDEX8 ? GL_STENCIL_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT,
2925 GL_TEXTURE_2D, depthStencilTexture, 0);
2926 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2927 ASSERT_GL_NO_ERROR();
2928
2929 // Clear only color.
2930 glClearColor(0, 0, 0, 1);
2931 glClear(GL_COLOR_BUFFER_BIT);
2932 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
2933
2934 // If stencil is not set to 0xD5, rendering would fail.
2935 glEnable(GL_STENCIL_TEST);
2936 glStencilFunc(GL_EQUAL, 0xD5, 0xFF);
2937 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2938 glStencilMask(0xFF);
2939
2940 // Draw red
2941 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2942 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f);
2943 ASSERT_GL_NO_ERROR();
2944
2945 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
2946 }
2947 }
2948
2949 // Test that glTexSubImage2D combined with a PBO works properly. PBO has all pixels as red
2950 // except the middle one being green.
TEST_P(Texture2DTest,TexStorageWithPBOMiddlePixelDifferent)2951 TEST_P(Texture2DTest, TexStorageWithPBOMiddlePixelDifferent)
2952 {
2953 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2954 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2955
2956 int width = getWindowWidth();
2957 int height = getWindowHeight();
2958
2959 GLTexture tex2D;
2960 glActiveTexture(GL_TEXTURE0);
2961 glBindTexture(GL_TEXTURE_2D, tex2D);
2962
2963 std::vector<GLubyte> pixels(3 * 16 * 16);
2964
2965 // Initialize texture with default black color.
2966 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2967 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
2968
2969 // Fill PBO's data with red, with middle one as green
2970 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2971 {
2972 if (pixelId == 8 * 7 + 7)
2973 {
2974 pixels[pixelId * 3 + 0] = 0;
2975 pixels[pixelId * 3 + 1] = 255;
2976 pixels[pixelId * 3 + 2] = 0;
2977 }
2978 else
2979 {
2980 pixels[pixelId * 3 + 0] = 255;
2981 pixels[pixelId * 3 + 1] = 0;
2982 pixels[pixelId * 3 + 2] = 0;
2983 }
2984 }
2985
2986 GLuint pbo;
2987 glGenBuffers(1, &pbo);
2988 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2989 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
2990
2991 // Update the color of the texture's upper-left 8x8 pixels, leaves the other pixels untouched.
2992 // glTexSubImage2D should take into account that the image is dirty.
2993 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
2994 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2995 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2996
2997 setUpProgram();
2998
2999 glUseProgram(mProgram);
3000 glUniform1i(mTexture2DUniformLocation, 0);
3001 drawQuad(mProgram, "position", 0.5f);
3002 glDeleteBuffers(1, &pbo);
3003 EXPECT_GL_NO_ERROR();
3004 EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
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 combined with a PBO works properly when glTexImage2D has
3010 // initialized the image with a luminance color
TEST_P(Texture2DTest,TexImageWithLuminancePBO)3011 TEST_P(Texture2DTest, TexImageWithLuminancePBO)
3012 {
3013 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3014
3015 int width = getWindowWidth();
3016 int height = getWindowHeight();
3017
3018 GLTexture tex2D;
3019 glActiveTexture(GL_TEXTURE0);
3020 glBindTexture(GL_TEXTURE_2D, tex2D);
3021
3022 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 16, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
3023 nullptr);
3024
3025 // Fill PBO with white, with middle one as grey
3026 std::vector<GLubyte> pixels(16 * 16);
3027 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
3028 {
3029 if (pixelId == 8 * 7 + 7)
3030 {
3031 pixels[pixelId] = 128;
3032 }
3033 else
3034 {
3035 pixels[pixelId] = 255;
3036 }
3037 }
3038
3039 GLuint pbo;
3040 glGenBuffers(1, &pbo);
3041 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3042 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16, pixels.data(), GL_STATIC_DRAW);
3043
3044 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
3045 // glTexSubImage2D should take into account that the image is dirty.
3046 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
3047 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3048 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3049
3050 setUpProgram();
3051
3052 glUseProgram(mProgram);
3053 glUniform1i(mTexture2DUniformLocation, 0);
3054 drawQuad(mProgram, "position", 0.5f);
3055 glDeleteBuffers(1, &pbo);
3056 EXPECT_GL_NO_ERROR();
3057 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 255, 255, 255);
3058 EXPECT_PIXEL_NEAR(width / 2 - 1, height / 2 - 1, 128, 128, 128, 255, 1);
3059 }
3060
3061 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
3062 // initialized the image with a RGB656 color
TEST_P(Texture2DTest,TexImageWithRGB565PBO)3063 TEST_P(Texture2DTest, TexImageWithRGB565PBO)
3064 {
3065 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3066 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3067
3068 int width = getWindowWidth();
3069 int height = getWindowHeight();
3070
3071 GLTexture tex2D;
3072 glActiveTexture(GL_TEXTURE0);
3073 glBindTexture(GL_TEXTURE_2D, tex2D);
3074
3075 // Fill PBO with red, with middle one as green
3076 std::vector<GLushort> pixels(16 * 16);
3077 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
3078 {
3079 if (pixelId == 8 * 7 + 8)
3080 {
3081 pixels[pixelId] = 0x7E0;
3082 }
3083 else
3084 {
3085 pixels[pixelId] = 0xF800;
3086 }
3087 }
3088
3089 GLuint pbo;
3090 glGenBuffers(1, &pbo);
3091 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3092 glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
3093
3094 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB565, 16, 16);
3095
3096 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
3097 // glTexSubImage2D should take into account that the image is dirty.
3098 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
3099 reinterpret_cast<void *>(2));
3100 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3101 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3102
3103 setUpProgram();
3104
3105 glUseProgram(mProgram);
3106 glUniform1i(mTexture2DUniformLocation, 0);
3107 drawQuad(mProgram, "position", 0.5f);
3108 glDeleteBuffers(1, &pbo);
3109 EXPECT_GL_NO_ERROR();
3110 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
3111 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
3112 }
3113
3114 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
3115 // initialized the image with a RGBA4444 color
TEST_P(Texture2DTest,TexImageWithRGBA4444PBO)3116 TEST_P(Texture2DTest, TexImageWithRGBA4444PBO)
3117 {
3118 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3119 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3120
3121 int width = getWindowWidth();
3122 int height = getWindowHeight();
3123
3124 GLTexture tex2D;
3125 glActiveTexture(GL_TEXTURE0);
3126 glBindTexture(GL_TEXTURE_2D, tex2D);
3127
3128 // Fill PBO with red, with middle one as green
3129 std::vector<GLushort> pixels(16 * 16);
3130 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
3131 {
3132 if (pixelId == 8 * 7 + 8)
3133 {
3134 pixels[pixelId] = 0xF0F;
3135 }
3136 else
3137 {
3138 pixels[pixelId] = 0xF00F;
3139 }
3140 }
3141
3142 GLuint pbo;
3143 glGenBuffers(1, &pbo);
3144 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3145 glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
3146
3147 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA4, 16, 16);
3148
3149 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
3150 // glTexSubImage2D should take into account that the image is dirty.
3151 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
3152 reinterpret_cast<void *>(2));
3153 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3155
3156 setUpProgram();
3157
3158 glUseProgram(mProgram);
3159 glUniform1i(mTexture2DUniformLocation, 0);
3160 drawQuad(mProgram, "position", 0.5f);
3161 glDeleteBuffers(1, &pbo);
3162 EXPECT_GL_NO_ERROR();
3163 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
3164 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
3165 }
3166
3167 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
3168 // initialized the image with a RGBA5551 color
TEST_P(Texture2DTest,TexImageWithRGBA5551PBO)3169 TEST_P(Texture2DTest, TexImageWithRGBA5551PBO)
3170 {
3171 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3172 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3173
3174 int width = getWindowWidth();
3175 int height = getWindowHeight();
3176
3177 GLTexture tex2D;
3178 glActiveTexture(GL_TEXTURE0);
3179 glBindTexture(GL_TEXTURE_2D, tex2D);
3180
3181 // Fill PBO with red, with middle one as green
3182 std::vector<GLushort> pixels(16 * 16);
3183 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
3184 {
3185 if (pixelId == 8 * 7 + 7)
3186 {
3187 pixels[pixelId] = 0x7C1;
3188 }
3189 else
3190 {
3191 pixels[pixelId] = 0xF801;
3192 }
3193 }
3194
3195 GLuint pbo;
3196 glGenBuffers(1, &pbo);
3197 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3198 glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
3199
3200 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB5_A1, 16, 16);
3201
3202 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
3203 // glTexSubImage2D should take into account that the image is dirty.
3204 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, nullptr);
3205 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3206 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3207
3208 setUpProgram();
3209
3210 glUseProgram(mProgram);
3211 glUniform1i(mTexture2DUniformLocation, 0);
3212 drawQuad(mProgram, "position", 0.5f);
3213 glDeleteBuffers(1, &pbo);
3214 EXPECT_GL_NO_ERROR();
3215 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
3216 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
3217 }
3218
3219 // Test that glTexSubImage2D from a PBO respects GL_UNPACK_ROW_LENGTH.
TEST_P(Texture2DTest,TexImageUnpackRowLengthPBO)3220 TEST_P(Texture2DTest, TexImageUnpackRowLengthPBO)
3221 {
3222 if (getClientMajorVersion() < 3)
3223 {
3224 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3225 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3226 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_unpack_subimage"));
3227 }
3228
3229 const int width = getWindowWidth() / 2;
3230 const int height = getWindowHeight();
3231 const int rowLength = getWindowWidth();
3232 const int bufferSize = rowLength * height;
3233
3234 GLTexture tex2D;
3235 glActiveTexture(GL_TEXTURE0);
3236 glBindTexture(GL_TEXTURE_2D, tex2D);
3237
3238 std::vector<GLColor> pixels(bufferSize);
3239 for (int y = 0; y < rowLength; ++y)
3240 {
3241 for (int x = 0; x < width; ++x)
3242 {
3243 pixels[y * rowLength + x] =
3244 x < width ? (y < height / 2 ? GLColor::green : GLColor::blue) : GLColor::red;
3245 }
3246 }
3247
3248 GLuint pbo;
3249 glGenBuffers(1, &pbo);
3250 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3251 glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize * sizeof(GLColor), pixels.data(),
3252 GL_STATIC_DRAW);
3253
3254 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
3255
3256 // Initializes the texture from width x height of the PBO.
3257 glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength);
3258 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3259 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3261
3262 setUpProgram();
3263
3264 glUseProgram(mProgram);
3265 glUniform1i(mTexture2DUniformLocation, 0);
3266 drawQuad(mProgram, "position", 0.5f);
3267 glDeleteBuffers(1, &pbo);
3268 EXPECT_GL_NO_ERROR();
3269 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3270 EXPECT_PIXEL_COLOR_EQ(0, height - 1, GLColor::blue);
3271 }
3272
3273 // Test if the KHR debug label is set and passed to D3D correctly using glCopyTexImage2D.
TEST_P(Texture2DTest,TextureKHRDebugLabelWithCopyTexImage2D)3274 TEST_P(Texture2DTest, TextureKHRDebugLabelWithCopyTexImage2D)
3275 {
3276 GLTexture texture2D;
3277 glBindTexture(GL_TEXTURE_2D, texture2D);
3278
3279 // Create a texture and copy into, to initialize storage object.
3280 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 32, 32, 0);
3281
3282 // Set KHR Debug Label.
3283 std::string label = "TestKHR.DebugLabel";
3284 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3285
3286 std::vector<char> labelBuf(label.length() + 1);
3287 GLsizei labelLengthBuf = 0;
3288
3289 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3290 &labelLengthBuf, labelBuf.data());
3291
3292 EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
3293 EXPECT_STREQ(label.c_str(), labelBuf.data());
3294
3295 // Delete the texture.
3296 texture2D.reset();
3297 EXPECT_GL_NO_ERROR();
3298
3299 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3300 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3301
3302 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3303 &labelLengthBuf, labelBuf.data());
3304 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3305 }
3306
3307 // Test to call labeling API before the storage texture is created.
TEST_P(Texture2DTest,CallKHRDebugLabelBeforeTexStorageCreation)3308 TEST_P(Texture2DTest, CallKHRDebugLabelBeforeTexStorageCreation)
3309 {
3310 GLTexture texture2D;
3311 glBindTexture(GL_TEXTURE_2D, texture2D);
3312
3313 // Set label before texture storage creation.
3314 std::string label = "TestKHR.DebugLabel";
3315 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3316
3317 // Create a texture and copy into, to initialize storage object.
3318 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 32, 32, 0);
3319
3320 std::vector<char> labelBuf(label.length() + 1);
3321 GLsizei labelLengthBuf = 0;
3322
3323 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3324 &labelLengthBuf, labelBuf.data());
3325
3326 EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
3327 EXPECT_STREQ(label.c_str(), labelBuf.data());
3328
3329 // Delete the texture.
3330 texture2D.reset();
3331 EXPECT_GL_NO_ERROR();
3332
3333 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3334 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3335
3336 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3337 &labelLengthBuf, labelBuf.data());
3338 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3339 }
3340
3341 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3342 // initialized the image with a depth-only format.
TEST_P(Texture2DTestES3,TexImageWithDepthPBO)3343 TEST_P(Texture2DTestES3, TexImageWithDepthPBO)
3344 {
3345 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3346 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3347
3348 // http://anglebug.com/42263861
3349 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3350
3351 constexpr GLsizei kSize = 4;
3352
3353 // Set up the framebuffer.
3354 GLTexture colorTexture;
3355 glBindTexture(GL_TEXTURE_2D, colorTexture);
3356 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3357 ASSERT_GL_NO_ERROR();
3358
3359 GLTexture depthTexture;
3360 glBindTexture(GL_TEXTURE_2D, depthTexture);
3361 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, kSize, kSize);
3362 ASSERT_GL_NO_ERROR();
3363
3364 GLFramebuffer fbo;
3365 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3366 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3367 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
3368 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3369 ASSERT_GL_NO_ERROR();
3370
3371 // Clear depth to 0, ensuring the texture's image is allocated.
3372 glClearDepthf(0);
3373 glClearColor(0, 0, 0, 1);
3374 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3375 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3376
3377 // Fill depth with 1.0f.
3378 std::vector<GLushort> pixels(kSize * kSize);
3379 for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3380 {
3381 pixels[pixelId] = 0xFFFF;
3382 }
3383
3384 GLuint pbo;
3385 glGenBuffers(1, &pbo);
3386 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3387 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3388 GL_STATIC_DRAW);
3389 ASSERT_GL_NO_ERROR();
3390
3391 // Upload PBO data.
3392 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
3393 nullptr);
3394
3395 // If depth is not set to 1, rendering would fail.
3396 glEnable(GL_DEPTH_TEST);
3397 glDepthFunc(GL_LESS);
3398
3399 // Draw red
3400 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3401 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3402 ASSERT_GL_NO_ERROR();
3403
3404 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3405 }
3406
3407 // Test sampling modes with a DEPTH_COMPONENT16 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth16)3408 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth16)
3409 {
3410 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, false);
3411 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX, false);
3412 }
3413
3414 // Test sampling modes with a swizzled DEPTH_COMPONENT16 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth16Swizzled)3415 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth16Swizzled)
3416 {
3417 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, true);
3418 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX, true);
3419 }
3420
3421 // Test sampling modes with a DEPTH_COMPONENT24 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24)3422 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24)
3423 {
3424 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, false);
3425 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_STENCIL_INDEX, false);
3426 }
3427
3428 // Test sampling modes with a swizzled DEPTH_COMPONENT24 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Swizzled)3429 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Swizzled)
3430 {
3431 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, true);
3432 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_STENCIL_INDEX, true);
3433 }
3434
3435 // Test depth sampling with a DEPTH_COMPONENT32F texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32f)3436 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32f)
3437 {
3438 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, false);
3439 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_STENCIL_INDEX, false);
3440 }
3441
3442 // Test depth sampling with a swizzled DEPTH_COMPONENT32F texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fSwizzled)3443 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fSwizzled)
3444 {
3445 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, true);
3446 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_STENCIL_INDEX, true);
3447 }
3448
3449 // Test sampling modes with a DEPTH24_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Stencil8)3450 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Stencil8)
3451 {
3452 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT, false);
3453 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX, false);
3454 }
3455
3456 // Test sampling modes with a swizzled DEPTH24_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Stencil8Swizzled)3457 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Stencil8Swizzled)
3458 {
3459 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT, true);
3460 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX, true);
3461 }
3462
3463 // Test sampling modes with a DEPTH32F_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fStencil8)3464 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fStencil8)
3465 {
3466 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT, false);
3467 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_STENCIL_INDEX, false);
3468 }
3469
3470 // Test sampling modes with a swizzled DEPTH32F_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fStencil8Swizzled)3471 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fStencil8Swizzled)
3472 {
3473 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT, true);
3474 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_STENCIL_INDEX, true);
3475 }
3476
3477 // Test sampling modes with a STENCIL_INDEX8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithStencil8)3478 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithStencil8)
3479 {
3480 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_stencil8"));
3481 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_DEPTH_COMPONENT, false);
3482 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, false);
3483 }
3484
3485 // Test sampling modes with a swizzled STENCIL_INDEX8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithStencil8Swizzled)3486 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithStencil8Swizzled)
3487 {
3488 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_stencil8"));
3489 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_DEPTH_COMPONENT, true);
3490 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, true);
3491 }
3492
3493 // Test that updating a texture format triggers depth/stencil mode resync.
TEST_P(Texture2DDepthStencilTestES3,Redefinition)3494 TEST_P(Texture2DDepthStencilTestES3, Redefinition)
3495 {
3496 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_stencil_texturing"));
3497
3498 constexpr char kDepthFS[] =
3499 R"(#version 300 es
3500 precision mediump float;
3501 uniform highp sampler2D tex;
3502 out vec4 color;
3503 void main()
3504 {
3505 color = texture(tex, vec2(0, 0));
3506 })";
3507 ANGLE_GL_PROGRAM(programDepth, essl3_shaders::vs::Simple(), kDepthFS);
3508
3509 constexpr char kStencilFS[] =
3510 R"(#version 300 es
3511 precision mediump float;
3512 uniform highp usampler2D tex;
3513 out vec4 color;
3514 void main()
3515 {
3516 color = vec4(texelFetch(tex, ivec2(0, 0), 0)) / 255.0;
3517 })";
3518 ANGLE_GL_PROGRAM(programStencil, essl3_shaders::vs::Simple(), kStencilFS);
3519
3520 // Set up a D32F with stencil mode.
3521 GLTexture texture;
3522 glBindTexture(GL_TEXTURE_2D, texture);
3523 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3524 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3525 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, GL_STENCIL_INDEX);
3526
3527 const GLfloat d32f = 0.5f;
3528 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
3529 &d32f);
3530 ASSERT_GL_NO_ERROR();
3531
3532 drawQuad(programDepth, essl3_shaders::PositionAttrib(), 0.5f);
3533 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
3534
3535 // Redefine the same texture as D24S8
3536 const GLuint d24s8 = 0xC0;
3537 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 1, 1, 0, GL_DEPTH_STENCIL,
3538 GL_UNSIGNED_INT_24_8, &d24s8);
3539 ASSERT_GL_NO_ERROR();
3540
3541 drawQuad(programStencil, essl3_shaders::PositionAttrib(), 0.5f);
3542 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(192, 0, 0, 1), 1);
3543
3544 // Redefine the same texture as D16
3545 const GLushort d16 = 0x4000;
3546 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 1, 1, 0, GL_DEPTH_COMPONENT,
3547 GL_UNSIGNED_SHORT, &d16);
3548 ASSERT_GL_NO_ERROR();
3549
3550 drawQuad(programDepth, essl3_shaders::PositionAttrib(), 0.5f);
3551 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(64, 0, 0, 255), 1);
3552 }
3553
3554 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3555 // initialized the image with a stencil-only format.
TEST_P(Texture2DTestES3,TexImageWithStencilPBO)3556 TEST_P(Texture2DTestES3, TexImageWithStencilPBO)
3557 {
3558 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3559 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3560
3561 // http://anglebug.com/42263861
3562 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3563
3564 constexpr GLsizei kSize = 4;
3565
3566 // Set up the framebuffer.
3567 GLTexture colorTexture;
3568 glBindTexture(GL_TEXTURE_2D, colorTexture);
3569 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3570 ASSERT_GL_NO_ERROR();
3571
3572 GLTexture stencilTexture;
3573 glBindTexture(GL_TEXTURE_2D, stencilTexture);
3574 glTexStorage2D(GL_TEXTURE_2D, 1, GL_STENCIL_INDEX8, kSize, kSize);
3575 ASSERT_GL_NO_ERROR();
3576
3577 GLFramebuffer fbo;
3578 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3579 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3580 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, stencilTexture, 0);
3581 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3582 ASSERT_GL_NO_ERROR();
3583
3584 // Clear stencil to 0, ensuring the texture's image is allocated.
3585 glClearStencil(0);
3586 glClearColor(0, 0, 0, 1);
3587 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3588 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3589
3590 // Fill stencil with 0x4E
3591 std::vector<GLubyte> pixels(kSize * kSize);
3592 for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3593 {
3594 pixels[pixelId] = 0x4E;
3595 }
3596
3597 GLuint pbo;
3598 glGenBuffers(1, &pbo);
3599 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3600 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3601 GL_STATIC_DRAW);
3602 ASSERT_GL_NO_ERROR();
3603
3604 // Upload PBO data.
3605 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
3606 nullptr);
3607 ASSERT_GL_NO_ERROR();
3608
3609 // If stencil is not set to 0x4E, rendering would fail.
3610 glEnable(GL_STENCIL_TEST);
3611 glStencilFunc(GL_EQUAL, 0x4E, 0xFF);
3612 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3613 glStencilMask(0xFF);
3614
3615 // Draw red
3616 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3617 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3618 ASSERT_GL_NO_ERROR();
3619
3620 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3621 }
3622
3623 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3624 // initialized the image with a depth/stencil format.
TEST_P(Texture2DTestES3,TexImageWithDepthStencilPBO)3625 TEST_P(Texture2DTestES3, TexImageWithDepthStencilPBO)
3626 {
3627 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3628 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3629
3630 // http://anglebug.com/42263861
3631 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3632
3633 constexpr GLsizei kSize = 4;
3634
3635 // Set up the framebuffer.
3636 GLTexture colorTexture;
3637 glBindTexture(GL_TEXTURE_2D, colorTexture);
3638 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3639 ASSERT_GL_NO_ERROR();
3640
3641 GLTexture depthStencilTexture;
3642 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
3643 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
3644 ASSERT_GL_NO_ERROR();
3645
3646 GLFramebuffer fbo;
3647 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3648 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3649 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
3650 depthStencilTexture, 0);
3651 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3652 ASSERT_GL_NO_ERROR();
3653
3654 // Clear depth and stencil to 0, ensuring the texture's image is allocated.
3655 glClearDepthf(0);
3656 glClearStencil(0);
3657 glClearColor(0, 0, 0, 1);
3658 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3659 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3660
3661 // Fill depth with 1.0f and stencil with 0xD5
3662 std::vector<GLuint> pixels(kSize * kSize);
3663 for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3664 {
3665 pixels[pixelId] = 0xFFFFFFD5;
3666 }
3667
3668 GLuint pbo;
3669 glGenBuffers(1, &pbo);
3670 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3671 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3672 GL_STATIC_DRAW);
3673 ASSERT_GL_NO_ERROR();
3674
3675 // Upload PBO data.
3676 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8,
3677 nullptr);
3678
3679 // If depth is not set to 1, rendering would fail.
3680 glEnable(GL_DEPTH_TEST);
3681 glDepthFunc(GL_LESS);
3682
3683 // If stencil is not set to 0xD5, rendering would fail.
3684 glEnable(GL_STENCIL_TEST);
3685 glStencilFunc(GL_EQUAL, 0xD5, 0xFF);
3686 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3687 glStencilMask(0xFF);
3688
3689 // Draw red
3690 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3691 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3692 ASSERT_GL_NO_ERROR();
3693
3694 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3695 }
3696
3697 // Test that it is possible to upload to a texture, upload a second texture and delete the first.
TEST_P(Texture2DTestES3,Texture1UploadThenTexture2UploadThenTexture1Delete)3698 TEST_P(Texture2DTestES3, Texture1UploadThenTexture2UploadThenTexture1Delete)
3699 {
3700 constexpr size_t kMaxBufferToImageCopySize = 64 * 1024 * 1024;
3701 constexpr size_t kTexSize = 4096;
3702 constexpr uint32_t kPixelSizeRGBA = 4;
3703 static_assert(kTexSize * kTexSize * kPixelSizeRGBA == kMaxBufferToImageCopySize);
3704
3705 std::vector<GLColor> textureColors(kTexSize * kTexSize, GLColor::red);
3706
3707 // A mutable texture is defined here. The second texture is used to flush the first one when the
3708 // relevant feature (mutableMipmapTextureUpload) is enabled. If flushed, the update on level 0
3709 // is large enough to trigger one submission using Vulkan, but the rest of its updates will not
3710 // trigger a second one. In that case, the texture should not be deleted until all updates are
3711 // processed.
3712 GLuint texture1;
3713 glGenTextures(1, &texture1);
3714 glBindTexture(GL_TEXTURE_2D, texture1);
3715 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3716 textureColors.data());
3717 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTexSize / 2, kTexSize / 2, 0, GL_RGBA,
3718 GL_UNSIGNED_BYTE, textureColors.data());
3719 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3720 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3721 ASSERT_GL_NO_ERROR();
3722
3723 GLTexture texture2;
3724 glBindTexture(GL_TEXTURE_2D, texture2);
3725 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3726 textureColors.data());
3727 ASSERT_GL_NO_ERROR();
3728
3729 glDeleteTextures(1, &texture1);
3730 ASSERT_GL_NO_ERROR();
3731 }
3732
3733 // Test that the driver performs a flush when there is a large amount of image updates.
TEST_P(Texture2DMemoryTestES3,TextureDataInLoopUntilFlush)3734 TEST_P(Texture2DMemoryTestES3, TextureDataInLoopUntilFlush)
3735 {
3736 // Run this test for Vulkan only.
3737 ANGLE_SKIP_TEST_IF(!IsVulkan());
3738
3739 // If VK_EXT_host_image_copy is used, uploads will all be done on the CPU and there would be no
3740 // submissions.
3741 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::SupportsHostImageCopy));
3742
3743 GLPerfMonitor monitor;
3744 glBeginPerfMonitorAMD(monitor);
3745
3746 uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1;
3747
3748 // Set up program
3749 const char *kFS = R"(#version 300 es
3750 precision highp float;
3751 uniform uni { vec4 color; };
3752 out vec4 fragColor;
3753 void main()
3754 {
3755 fragColor = color;
3756 })";
3757 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3758 ASSERT_NE(program, 0u);
3759
3760 // Set up the uniform buffer and framebuffer
3761 GLint uniformBufferIndex;
3762 uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
3763 ASSERT_NE(uniformBufferIndex, -1);
3764
3765 glClear(GL_COLOR_BUFFER_BIT);
3766 constexpr size_t kBufferSize = 4 * 1024 * 1024;
3767 std::vector<float> floatData;
3768 floatData.resize(kBufferSize / (sizeof(float)), 0.0f);
3769 floatData[0] = 0.5f;
3770 floatData[1] = 0.75f;
3771 floatData[2] = 0.25f;
3772 floatData[3] = 1.0f;
3773
3774 GLBuffer uniformBuffer;
3775 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
3776 glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW);
3777 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
3778 glUniformBlockBinding(program, uniformBufferIndex, 0);
3779
3780 GLFramebuffer fbo;
3781 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3782
3783 // Create textures and draw
3784 constexpr uint32_t kTextureWidth = 512;
3785 constexpr uint32_t kTextureHeight = 512;
3786 std::vector<GLColor> textureColor(kTextureWidth * kTextureHeight, GLColor::red);
3787 constexpr uint32_t kIterationCount = 4096;
3788 GLTexture textures[kIterationCount];
3789
3790 for (auto &texture : textures)
3791 {
3792 glBindTexture(GL_TEXTURE_2D, texture);
3793 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureWidth, kTextureHeight);
3794 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RGBA,
3795 GL_UNSIGNED_BYTE, textureColor.data());
3796
3797 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3798 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3799 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3800
3801 if (getPerfCounters().commandQueueSubmitCallsTotal == expectedSubmitCalls)
3802 {
3803 break;
3804 }
3805 }
3806 glEndPerfMonitorAMD(monitor);
3807
3808 EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls);
3809 ASSERT_GL_NO_ERROR();
3810 EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
3811 }
3812
3813 // Creating a texture and drawing with it in a loop without glFlush() should still work. Driver is
3814 // supposedly to issue flush if needed. There should be no fallbacks to allocate outside the device
3815 // memory.
TEST_P(Texture2DMemoryTestES3,TextureDataInLoopManyTimes)3816 TEST_P(Texture2DMemoryTestES3, TextureDataInLoopManyTimes)
3817 {
3818 // Run this test for Vulkan only.
3819 ANGLE_SKIP_TEST_IF(!IsVulkan());
3820
3821 GLPerfMonitor monitor;
3822 glBeginPerfMonitorAMD(monitor);
3823
3824 uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1;
3825 uint64_t expectedDeviceMemoryFallbacks = getPerfCounters().deviceMemoryImageAllocationFallbacks;
3826
3827 // Set up program
3828 const char *kFS = R"(#version 300 es
3829 precision highp float;
3830 uniform uni { vec4 color; };
3831 out vec4 fragColor;
3832 void main()
3833 {
3834 fragColor = color;
3835 })";
3836 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3837 ASSERT_NE(program, 0u);
3838
3839 // Set up the uniform buffer and framebuffer
3840 GLint uniformBufferIndex;
3841 uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
3842 ASSERT_NE(uniformBufferIndex, -1);
3843
3844 glClear(GL_COLOR_BUFFER_BIT);
3845 constexpr size_t kBufferSize = 4 * 1024 * 1024;
3846 std::vector<float> floatData;
3847 floatData.resize(kBufferSize / (sizeof(float)), 0.0f);
3848 floatData[0] = 0.5f;
3849 floatData[1] = 0.75f;
3850 floatData[2] = 0.25f;
3851 floatData[3] = 1.0f;
3852
3853 GLBuffer uniformBuffer;
3854 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
3855 glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW);
3856 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
3857 glUniformBlockBinding(program, uniformBufferIndex, 0);
3858
3859 GLFramebuffer fbo;
3860 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3861
3862 // Create textures and draw. We will use very small image updates to prevent flush before the
3863 // device runs out of memory.
3864 constexpr uint32_t kTextureWidth = 4096;
3865 constexpr uint32_t kTextureHeight = 4096;
3866 std::vector<GLColor> textureColor(kTextureWidth * kTextureHeight, GLColor::red);
3867 constexpr uint32_t kIterationCount = 4096;
3868
3869 uint32_t iteration = 0;
3870 for (; iteration < kIterationCount; iteration++)
3871 {
3872 GLTexture texture;
3873 glBindTexture(GL_TEXTURE_2D, texture);
3874 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0, GL_RGBA,
3875 GL_UNSIGNED_BYTE, nullptr);
3876 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
3877 textureColor.data());
3878
3879 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3880 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3881 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3882
3883 if (getPerfCounters().commandQueueSubmitCallsTotal >= expectedSubmitCalls)
3884 {
3885 break;
3886 }
3887 }
3888
3889 glEndPerfMonitorAMD(monitor);
3890 EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls)
3891 << "iteration " << iteration;
3892 EXPECT_EQ(getPerfCounters().deviceMemoryImageAllocationFallbacks,
3893 expectedDeviceMemoryFallbacks);
3894 ASSERT_GL_NO_ERROR();
3895 }
3896
3897 // Test functionality of GL_ANGLE_yuv_internal_format with min/mag filters
3898 // set to nearest and linear modes.
TEST_P(Texture2DTestES3YUV,TexStorage2DYuvFilterModes)3899 TEST_P(Texture2DTestES3YUV, TexStorage2DYuvFilterModes)
3900 {
3901 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3902
3903 // Create YUV texture
3904 GLTexture yuvTexture;
3905 GLubyte yuvColor[] = {40, 40, 40, 40, 40, 40, 40, 40, 240, 109, 240, 109};
3906 GLubyte expectedRgbColor[] = {0, 0, 255, 255};
3907 createImmutableTexture2D(yuvTexture, 2, 4, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3908 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3909
3910 // Default is nearest filter mode
3911 verifyResults2D(yuvTexture, expectedRgbColor);
3912 ASSERT_GL_NO_ERROR();
3913
3914 // Enable linear filter mode
3915 glBindTexture(GL_TEXTURE_2D, yuvTexture);
3916 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3917 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3918 verifyResults2D(yuvTexture, expectedRgbColor);
3919 ASSERT_GL_NO_ERROR();
3920
3921 const int windowHeight = getWindowHeight();
3922 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::blue, 1);
3923 EXPECT_PIXEL_COLOR_NEAR(0, windowHeight - 1, GLColor::blue, 1);
3924 EXPECT_PIXEL_COLOR_NEAR(0, windowHeight / 2, GLColor::blue, 1);
3925 }
3926
3927 // Test functionality of GL_ANGLE_yuv_internal_format while cycling through RGB and YUV sources
TEST_P(Texture2DTestES3,TexStorage2DCycleThroughYuvAndRgbSources)3928 TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvAndRgbSources)
3929 {
3930 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3931
3932 // Create YUV texture
3933 GLTexture yuvTexture;
3934 GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109};
3935 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
3936 createImmutableTexture2D(yuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3937 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3938
3939 // Create RGBA texture
3940 GLTexture rgbaTexture;
3941 GLubyte rgbaColor[4] = {0, 0, 255, 255};
3942 createImmutableTexture2D(rgbaTexture, 1, 1, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, 1, rgbaColor);
3943
3944 // Cycle through source textures
3945 // RGBA source
3946 verifyResults2D(rgbaTexture, rgbaColor);
3947 ASSERT_GL_NO_ERROR();
3948
3949 // YUV source
3950 verifyResults2D(yuvTexture, expectedRgbColor);
3951 ASSERT_GL_NO_ERROR();
3952
3953 // RGBA source
3954 verifyResults2D(rgbaTexture, rgbaColor);
3955 ASSERT_GL_NO_ERROR();
3956 }
3957
3958 // Test functionality of GL_ANGLE_yuv_internal_format with large number of YUV sources
TEST_P(Texture2DTestES3,TexStorage2DLargeYuvTextureCount)3959 TEST_P(Texture2DTestES3, TexStorage2DLargeYuvTextureCount)
3960 {
3961 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3962
3963 constexpr uint32_t kTextureCount = 16;
3964
3965 // Create YUV texture
3966 GLTexture yuvTexture[kTextureCount];
3967 for (uint32_t i = 0; i < kTextureCount; i++)
3968 {
3969 // Create 2 plane YCbCr 420 texture
3970 createImmutableTexture2D(yuvTexture[i], 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3971 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3972 }
3973
3974 // Cycle through YUV source textures
3975 glUseProgram(mProgram);
3976 glUniform1i(mTexture2DUniformLocation, 0);
3977
3978 for (uint32_t i = 0; i < kTextureCount; i++)
3979 {
3980 glBindTexture(GL_TEXTURE_2D, yuvTexture[i]);
3981 drawQuad(mProgram, "position", 0.5f);
3982 ASSERT_GL_NO_ERROR();
3983 }
3984 }
3985
3986 // Test functionality of GL_ANGLE_yuv_internal_format with simultaneous use of multiple YUV sources
TEST_P(Texture2DTestES3,TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData)3987 TEST_P(Texture2DTestES3, TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData)
3988 {
3989 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3990
3991 // Create YUV texture
3992 // Create 2 plane YCbCr 420 texture
3993 GLTexture twoPlaneYuvTexture;
3994 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3995 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3996
3997 // Create 3 plane YCbCr 420 texture
3998 GLTexture threePlaneYuvTexture;
3999 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
4000 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
4001
4002 // Cycle through YUV source textures
4003 // Create program with 2 samplers
4004 const char *vertexShaderSource = getVertexShaderSource();
4005 const char *fragmentShaderSource = R"(#version 300 es
4006 precision highp float;
4007 uniform sampler2D tex0;
4008 uniform sampler2D tex1;
4009 in vec2 texcoord;
4010 out vec4 fragColor;
4011
4012 void main()
4013 {
4014 vec4 color0 = texture(tex0, texcoord);
4015 vec4 color1 = texture(tex1, texcoord);
4016 fragColor = color0 + color1;
4017 })";
4018
4019 ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
4020 glUseProgram(twoSamplersProgram);
4021 GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
4022 ASSERT_NE(-1, tex0Location);
4023 GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
4024 ASSERT_NE(-1, tex1Location);
4025
4026 glUniform1i(tex0Location, 0);
4027 glUniform1i(tex1Location, 1);
4028
4029 // Bind 2 plane YUV source
4030 glActiveTexture(GL_TEXTURE0);
4031 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4032 ASSERT_GL_NO_ERROR();
4033
4034 // Bind 3 plane YUV source
4035 glActiveTexture(GL_TEXTURE1);
4036 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4037 ASSERT_GL_NO_ERROR();
4038
4039 drawQuad(twoSamplersProgram, "position", 0.5f);
4040 ASSERT_GL_NO_ERROR();
4041
4042 // Switch active texture index and draw again
4043 // Bind 2 plane YUV source
4044 glActiveTexture(GL_TEXTURE1);
4045 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4046 ASSERT_GL_NO_ERROR();
4047
4048 // Bind 3 plane YUV source
4049 glActiveTexture(GL_TEXTURE0);
4050 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4051 ASSERT_GL_NO_ERROR();
4052
4053 drawQuad(twoSamplersProgram, "position", 0.5f);
4054 ASSERT_GL_NO_ERROR();
4055 }
4056
4057 // Test functional of GL_ANGLE_yuv_internal_format while cycling through YUV sources
TEST_P(Texture2DTestES3,TexStorage2DCycleThroughYuvSourcesNoData)4058 TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvSourcesNoData)
4059 {
4060 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
4061
4062 // Create YUV texture
4063 // Create 2 plane YCbCr 420 texture
4064 GLTexture twoPlaneYuvTexture;
4065 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
4066 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
4067
4068 // Create 3 plane YCbCr 420 texture
4069 GLTexture threePlaneYuvTexture;
4070 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
4071 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
4072
4073 // Cycle through YUV source textures
4074 glUseProgram(mProgram);
4075 glUniform1i(mTexture2DUniformLocation, 0);
4076
4077 // 2 plane YUV source
4078 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4079 drawQuad(mProgram, "position", 0.5f);
4080 ASSERT_GL_NO_ERROR();
4081
4082 // 3 plane YUV source
4083 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4084 drawQuad(mProgram, "position", 0.5f);
4085 ASSERT_GL_NO_ERROR();
4086
4087 // 2 plane YUV source
4088 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4089 drawQuad(mProgram, "position", 0.5f);
4090 ASSERT_GL_NO_ERROR();
4091 }
4092
4093 // Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while
4094 // switching sampler uniform values.
TEST_P(Texture2DTestES3,TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues)4095 TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues)
4096 {
4097 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
4098
4099 // Create YUV texture
4100 GLTexture yuvTexture;
4101 GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109};
4102 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
4103
4104 // Create YUV texture
4105 // Create 2 plane YCbCr 420 texture
4106 GLTexture twoPlaneYuvTexture;
4107 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
4108 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
4109 // Create 3 plane YCbCr 420 texture
4110 GLTexture threePlaneYuvTexture;
4111 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
4112 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
4113 // Create program with 2 samplers
4114 const char *vertexShaderSource = getVertexShaderSource();
4115 const char *fragmentShaderSource = R"(#version 300 es
4116 precision highp float;
4117 uniform sampler2D tex0;
4118 uniform sampler2D tex1;
4119 uniform int texIndex;
4120 in vec2 texcoord;
4121 out vec4 fragColor;
4122 void main()
4123 {
4124 vec4 color0 = texture(tex0, texcoord);
4125 vec4 color1 = texture(tex1, texcoord);
4126 if (texIndex == 0)
4127 {
4128 fragColor = color0;
4129 }
4130 else
4131 {
4132 fragColor = color1;
4133 }
4134 })";
4135 ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
4136 glUseProgram(twoSamplersProgram);
4137 GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
4138 ASSERT_NE(-1, tex0Location);
4139 GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
4140 ASSERT_NE(-1, tex1Location);
4141 GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex");
4142 ASSERT_NE(-1, texIndexLocation);
4143 // Bind 2 plane YUV source
4144 glActiveTexture(GL_TEXTURE0);
4145 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4146 ASSERT_GL_NO_ERROR();
4147 // Bind 3 plane YUV source
4148 glActiveTexture(GL_TEXTURE1);
4149 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4150 ASSERT_GL_NO_ERROR();
4151
4152 // Set sampler uniform values and draw
4153 glUniform1i(tex0Location, 0);
4154 glUniform1i(tex1Location, 1);
4155 // Set texture index selector to the 2 plane texture unit
4156 glUniform1i(texIndexLocation, 0);
4157 drawQuad(twoSamplersProgram, "position", 0.5f);
4158 ASSERT_GL_NO_ERROR();
4159 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4160 expectedRgbColor[3], 1);
4161 ASSERT_GL_NO_ERROR();
4162
4163 // Switch sampler uniform values and draw
4164 glUniform1i(tex0Location, 1);
4165 glUniform1i(tex1Location, 0);
4166 // Set texture index selector to the 2 plane texture unit
4167 glUniform1i(texIndexLocation, 1);
4168 drawQuad(twoSamplersProgram, "position", 0.5f);
4169 ASSERT_GL_NO_ERROR();
4170 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4171 expectedRgbColor[3], 1);
4172 ASSERT_GL_NO_ERROR();
4173
4174 // Switch back sampler uniform values and draw
4175 glUniform1i(tex0Location, 0);
4176 glUniform1i(tex1Location, 1);
4177 // Set texture index selector to the 2 plane texture unit
4178 glUniform1i(texIndexLocation, 0);
4179 drawQuad(twoSamplersProgram, "position", 0.5f);
4180 ASSERT_GL_NO_ERROR();
4181 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4182 expectedRgbColor[3], 1);
4183 ASSERT_GL_NO_ERROR();
4184 }
4185
4186 // Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while
4187 // switching bound textures.
TEST_P(Texture2DTestES3,TexStorage2DMultipleYuvSamplersSwitchBoundTextures)4188 TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchBoundTextures)
4189 {
4190 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
4191
4192 // Create YUV texture
4193 GLTexture yuvTexture;
4194 GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109};
4195 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
4196
4197 // Create YUV texture
4198 // Create 2 plane YCbCr 420 texture
4199 GLTexture twoPlaneYuvTexture;
4200 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
4201 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
4202 // Create 3 plane YCbCr 420 texture
4203 GLTexture threePlaneYuvTexture;
4204 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
4205 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
4206 // Create program with 2 samplers
4207 const char *vertexShaderSource = getVertexShaderSource();
4208 const char *fragmentShaderSource = R"(#version 300 es
4209 precision highp float;
4210 uniform sampler2D tex0;
4211 uniform sampler2D tex1;
4212 uniform int texIndex;
4213 in vec2 texcoord;
4214 out vec4 fragColor;
4215 void main()
4216 {
4217 vec4 color0 = texture(tex0, texcoord);
4218 vec4 color1 = texture(tex1, texcoord);
4219 if (texIndex == 0)
4220 {
4221 fragColor = color0;
4222 }
4223 else
4224 {
4225 fragColor = color1;
4226 }
4227 })";
4228 ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
4229 glUseProgram(twoSamplersProgram);
4230 GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
4231 ASSERT_NE(-1, tex0Location);
4232 GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
4233 ASSERT_NE(-1, tex1Location);
4234 GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex");
4235 ASSERT_NE(-1, texIndexLocation);
4236 // Set sampler uniform values
4237 glUniform1i(tex0Location, 0);
4238 glUniform1i(tex1Location, 1);
4239
4240 // Bind 2 plane YUV source
4241 glActiveTexture(GL_TEXTURE0);
4242 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4243 ASSERT_GL_NO_ERROR();
4244 // Bind 3 plane YUV source
4245 glActiveTexture(GL_TEXTURE1);
4246 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4247 ASSERT_GL_NO_ERROR();
4248 // Set texture index selector to the 2 plane texture unit
4249 glUniform1i(texIndexLocation, 0);
4250 // Draw
4251 drawQuad(twoSamplersProgram, "position", 0.5f);
4252 ASSERT_GL_NO_ERROR();
4253 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4254 expectedRgbColor[3], 1);
4255 ASSERT_GL_NO_ERROR();
4256
4257 // Bind 3 plane YUV source
4258 glActiveTexture(GL_TEXTURE0);
4259 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4260 ASSERT_GL_NO_ERROR();
4261 // Bind 2 plane YUV source
4262 glActiveTexture(GL_TEXTURE1);
4263 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4264 ASSERT_GL_NO_ERROR();
4265 // Set texture index selector to the 2 plane texture unit
4266 glUniform1i(texIndexLocation, 1);
4267 // Draw
4268 drawQuad(twoSamplersProgram, "position", 0.5f);
4269 ASSERT_GL_NO_ERROR();
4270 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4271 expectedRgbColor[3], 1);
4272 ASSERT_GL_NO_ERROR();
4273 }
4274
4275 // Tests CopySubImage for float formats
TEST_P(Texture2DTest,CopySubImageFloat_R_R)4276 TEST_P(Texture2DTest, CopySubImageFloat_R_R)
4277 {
4278 testFloatCopySubImage(1, 1);
4279 }
4280
TEST_P(Texture2DTest,CopySubImageFloat_RG_R)4281 TEST_P(Texture2DTest, CopySubImageFloat_RG_R)
4282 {
4283 testFloatCopySubImage(2, 1);
4284 }
4285
TEST_P(Texture2DTest,CopySubImageFloat_RG_RG)4286 TEST_P(Texture2DTest, CopySubImageFloat_RG_RG)
4287 {
4288 testFloatCopySubImage(2, 2);
4289 }
4290
TEST_P(Texture2DTest,CopySubImageFloat_RGB_R)4291 TEST_P(Texture2DTest, CopySubImageFloat_RGB_R)
4292 {
4293 testFloatCopySubImage(3, 1);
4294 }
4295
TEST_P(Texture2DTest,CopySubImageFloat_RGB_RG)4296 TEST_P(Texture2DTest, CopySubImageFloat_RGB_RG)
4297 {
4298 testFloatCopySubImage(3, 2);
4299 }
4300
TEST_P(Texture2DTest,CopySubImageFloat_RGB_RGB)4301 TEST_P(Texture2DTest, CopySubImageFloat_RGB_RGB)
4302 {
4303 // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/40096350)
4304 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4305
4306 testFloatCopySubImage(3, 3);
4307 }
4308
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_R)4309 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_R)
4310 {
4311 testFloatCopySubImage(4, 1);
4312 }
4313
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RG)4314 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RG)
4315 {
4316 testFloatCopySubImage(4, 2);
4317 }
4318
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RGB)4319 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGB)
4320 {
4321 testFloatCopySubImage(4, 3);
4322 }
4323
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RGBA)4324 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGBA)
4325 {
4326 testFloatCopySubImage(4, 4);
4327 }
4328
4329 // Port of
4330 // https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html
4331 // Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly
4332 // handles GL_ALPHA
TEST_P(Texture2DTest,TextureNPOT_GL_ALPHA_UBYTE)4333 TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE)
4334 {
4335 const int npotTexSize = 5;
4336 const int potTexSize = 4; // Should be less than npotTexSize
4337 GLTexture tex2D;
4338
4339 if (IsGLExtensionEnabled("GL_OES_texture_npot"))
4340 {
4341 // This test isn't applicable if texture_npot is enabled
4342 return;
4343 }
4344
4345 setUpProgram();
4346
4347 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4348
4349 // Default unpack alignment is 4. The values of 'pixels' below needs it to be 1.
4350 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4351
4352 glActiveTexture(GL_TEXTURE0);
4353 glBindTexture(GL_TEXTURE_2D, tex2D);
4354
4355 const std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize, 64);
4356
4357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4359
4360 // Check that an NPOT texture not on level 0 generates INVALID_VALUE
4361 glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA,
4362 GL_UNSIGNED_BYTE, pixels.data());
4363 EXPECT_GL_ERROR(GL_INVALID_VALUE);
4364
4365 // Check that an NPOT texture on level 0 succeeds
4366 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA,
4367 GL_UNSIGNED_BYTE, pixels.data());
4368 EXPECT_GL_NO_ERROR();
4369
4370 // Check that generateMipmap fails on NPOT
4371 glGenerateMipmap(GL_TEXTURE_2D);
4372 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4373
4374 // Check that nothing is drawn if filtering is not correct for NPOT
4375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
4378 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
4379 glClear(GL_COLOR_BUFFER_BIT);
4380 drawQuad(mProgram, "position", 1.0f);
4381 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
4382
4383 // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
4384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4386 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
4387 glClear(GL_COLOR_BUFFER_BIT);
4388 drawQuad(mProgram, "position", 1.0f);
4389 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
4390
4391 // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw
4392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4393 glClear(GL_COLOR_BUFFER_BIT);
4394 drawQuad(mProgram, "position", 1.0f);
4395 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
4396
4397 // Check that glTexImage2D for POT texture succeeds
4398 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
4399 pixels.data());
4400 EXPECT_GL_NO_ERROR();
4401
4402 // Check that generateMipmap for an POT texture succeeds
4403 glGenerateMipmap(GL_TEXTURE_2D);
4404 EXPECT_GL_NO_ERROR();
4405
4406 // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw
4407 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
4408 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4409 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
4410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
4411 glClear(GL_COLOR_BUFFER_BIT);
4412 drawQuad(mProgram, "position", 1.0f);
4413 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
4414 EXPECT_GL_NO_ERROR();
4415 }
4416
4417 // Test to ensure that glTexSubImage2D always accepts data for non-power-of-two subregions.
4418 // ANGLE previously rejected this if GL_OES_texture_npot wasn't active, which is incorrect.
TEST_P(Texture2DTest,NPOTSubImageParameters)4419 TEST_P(Texture2DTest, NPOTSubImageParameters)
4420 {
4421 glActiveTexture(GL_TEXTURE0);
4422 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4423
4424 // Create an 8x8 (i.e. power-of-two) texture.
4425 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4426 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4427 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4428 glGenerateMipmap(GL_TEXTURE_2D);
4429
4430 // Supply a 3x3 (i.e. non-power-of-two) subimage to the texture.
4431 // This should always work, even if GL_OES_texture_npot isn't active.
4432 std::array<GLColor, 3 * 3> data;
4433 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
4434
4435 EXPECT_GL_NO_ERROR();
4436 }
4437
4438 // Regression test for https://crbug.com/1222516 to prevent integer overflow during validation.
TEST_P(Texture2DTest,SubImageValidationOverflow)4439 TEST_P(Texture2DTest, SubImageValidationOverflow)
4440 {
4441 glActiveTexture(GL_TEXTURE0);
4442 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4443
4444 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4445 EXPECT_GL_NO_ERROR();
4446
4447 glTexSubImage2D(GL_TEXTURE_2D, 0, -4, 0, 2147483647, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4448 EXPECT_GL_ERROR(GL_INVALID_VALUE);
4449
4450 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, -4, 1, 2147483647, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4451 EXPECT_GL_ERROR(GL_INVALID_VALUE);
4452 }
4453
4454 // Test that when a mutable texture is deleted, its corresponding pointer in the Vulkan backend,
4455 // which is used for mutable texture flushing, is also deleted, and is not accessed by the new
4456 // mutable texture after it.
TEST_P(Texture2DTest,MutableUploadThenDeleteThenMutableUpload)4457 TEST_P(Texture2DTest, MutableUploadThenDeleteThenMutableUpload)
4458 {
4459 GLTexture texture1;
4460 glBindTexture(GL_TEXTURE_2D, texture1);
4461 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4462 GLColor::red.data());
4463 texture1.reset();
4464 EXPECT_GL_NO_ERROR();
4465
4466 GLTexture texture2;
4467 glBindTexture(GL_TEXTURE_2D, texture2);
4468 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4469 GLColor::green.data());
4470 texture2.reset();
4471 EXPECT_GL_NO_ERROR();
4472 }
4473
4474 // Test to ensure that glTexStorage3D accepts ASTC sliced 3D. https://crbug.com/1060012
TEST_P(Texture3DTestES3,ImmutableASTCSliced3D)4475 TEST_P(Texture3DTestES3, ImmutableASTCSliced3D)
4476 {
4477 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_texture_compression_astc_sliced_3d"));
4478
4479 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4480 glTexStorage3D(GL_TEXTURE_3D, 1, GL_COMPRESSED_RGBA_ASTC_4x4, 4, 4, 1);
4481 EXPECT_GL_NO_ERROR();
4482 }
4483
FillLevel(GLint level,GLuint width,GLuint height,const GLColor & color,bool cubemap,bool subTex)4484 void FillLevel(GLint level,
4485 GLuint width,
4486 GLuint height,
4487 const GLColor &color,
4488 bool cubemap,
4489 bool subTex)
4490 {
4491 std::vector<GLColor> pixels(width * height, color);
4492 std::vector<GLenum> targets;
4493 if (cubemap)
4494 {
4495 targets = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
4496 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
4497 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
4498 }
4499 else
4500 {
4501 targets = {GL_TEXTURE_2D};
4502 }
4503
4504 for (GLenum target : targets)
4505 {
4506 if (subTex)
4507 {
4508 glTexSubImage2D(target, level, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
4509 pixels.data());
4510 }
4511 else
4512 {
4513 glTexImage2D(target, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4514 pixels.data());
4515 }
4516 }
4517 }
4518
4519 // This is part of tests that webgl_conformance_vulkan_passthrough_tests
4520 // conformance/textures/misc/texture-size.html does
testTextureSize(int testCaseIndex)4521 void Texture2DTest::testTextureSize(int testCaseIndex)
4522 {
4523 std::array<GLColor, 6> kNewMipColors = {
4524 GLColor::green, GLColor::red, GLColor::blue,
4525 GLColor::yellow, GLColor::magenta, GLColor::cyan,
4526 };
4527 GLuint colorCount = 0;
4528
4529 setUpProgram();
4530
4531 constexpr char kVS[] =
4532 R"(precision highp float;
4533 attribute vec4 position;
4534 varying vec3 texcoord;
4535 void main()
4536 {
4537 gl_Position = position;
4538 texcoord = (position.xyz * 0.5) + 0.5;
4539 }
4540 )";
4541 constexpr char kFS[] =
4542 R"(precision mediump float;
4543 uniform samplerCube tex;
4544 varying vec3 texcoord;
4545 void main()
4546 {
4547 gl_FragColor = textureCube(tex, texcoord);
4548 })";
4549 ANGLE_GL_PROGRAM(programCubeMap, kVS, kFS);
4550 GLint textureCubeUniformLocation = glGetUniformLocation(programCubeMap, "tex");
4551 ASSERT_NE(-1, textureCubeUniformLocation);
4552 ASSERT_GL_NO_ERROR();
4553
4554 GLint max2DSize = 0;
4555 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize);
4556 GLint maxCubeMapSize = 0;
4557 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapSize);
4558 // Assuming 2048x2048xRGBA (22 mb with mips) will run on all WebGL platforms
4559 GLint max2DSquareSize = std::min(max2DSize, 2048);
4560 // I'd prefer this to be 2048 but that's 16 mb x 6 faces or 128 mb (with mips)
4561 // 1024 is 33.5 mb (with mips)
4562 maxCubeMapSize = std::min(maxCubeMapSize, 1024);
4563 ASSERT_GL_NO_ERROR();
4564
4565 for (GLint size = 1; size <= max2DSize; size *= 2)
4566 {
4567 bool cubeMap = testCaseIndex == 3;
4568 GLenum texTarget = cubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
4569 GLuint program = cubeMap ? programCubeMap : mProgram;
4570 GLint texWidth = 0, texHeight = 0;
4571
4572 switch (testCaseIndex)
4573 {
4574 case 0:
4575 texWidth = size;
4576 texHeight = 1;
4577 break;
4578 case 1:
4579 texWidth = 1;
4580 texHeight = size;
4581 break;
4582 case 2:
4583 case 3:
4584 texWidth = size;
4585 texHeight = size;
4586 break;
4587 }
4588
4589 if (texWidth == texHeight && size > max2DSquareSize)
4590 {
4591 return;
4592 }
4593
4594 if (cubeMap && size > maxCubeMapSize)
4595 {
4596 return;
4597 }
4598
4599 GLTexture texture;
4600 glActiveTexture(GL_TEXTURE0);
4601 glBindTexture(texTarget, texture);
4602 FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false);
4603 glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4604 glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4605 glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4606 glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4607 ASSERT_GL_NO_ERROR();
4608
4609 glClear(GL_COLOR_BUFFER_BIT);
4610 ASSERT_GL_NO_ERROR();
4611
4612 glUseProgram(program);
4613 if (cubeMap)
4614 {
4615 glUniform1i(textureCubeUniformLocation, 0);
4616 }
4617 else
4618 {
4619 glUniform1i(mTexture2DUniformLocation, 0);
4620 }
4621
4622 drawQuad(program, "position", 1.0f);
4623 ASSERT_GL_NO_ERROR();
4624 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
4625
4626 colorCount = (colorCount + 1) % kNewMipColors.size();
4627 FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false);
4628 glGenerateMipmap(texTarget);
4629 ASSERT_GL_NO_ERROR();
4630
4631 glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4632 glClear(GL_COLOR_BUFFER_BIT);
4633 drawQuad(program, "position", 1.0f);
4634 ASSERT_GL_NO_ERROR();
4635 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
4636
4637 colorCount = (colorCount + 1) % kNewMipColors.size();
4638 FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, true);
4639 glGenerateMipmap(texTarget);
4640
4641 glClear(GL_COLOR_BUFFER_BIT);
4642 drawQuad(program, "position", 1.0f);
4643 ASSERT_GL_NO_ERROR();
4644 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
4645 }
4646 }
4647
testTextureSizeError()4648 void Texture2DTest::testTextureSizeError()
4649 {
4650 GLint max2DSize = 0;
4651 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize);
4652 glActiveTexture(GL_TEXTURE0);
4653 GLTexture texture;
4654 glBindTexture(GL_TEXTURE_2D, texture);
4655 FillLevel(0, max2DSize, max2DSize, GLColor::red, false, false);
4656 GLenum err = glGetError();
4657 bool passed = (err == GL_NO_ERROR || err == GL_OUT_OF_MEMORY);
4658 ASSERT_TRUE(passed);
4659 }
4660
4661 // Permutation 0 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase0)4662 TEST_P(Texture2DTest, TextureSizeCase0)
4663 {
4664 testTextureSize(0);
4665 }
4666
4667 // Permutation 1 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase1)4668 TEST_P(Texture2DTest, TextureSizeCase1)
4669 {
4670 testTextureSize(1);
4671 }
4672
4673 // Permutation 2 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase2)4674 TEST_P(Texture2DTest, TextureSizeCase2)
4675 {
4676 testTextureSize(2);
4677 }
4678
4679 // Permutation 3 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase3)4680 TEST_P(Texture2DTest, TextureSizeCase3)
4681 {
4682 testTextureSize(3);
4683 }
4684
4685 // Test allocating a very large texture
TEST_P(Texture2DTest,TextureMaxSize)4686 TEST_P(Texture2DTest, TextureMaxSize)
4687 {
4688 testTextureSizeError();
4689 }
4690
4691 // Test that drawing works correctly RGBA 3D texture
TEST_P(Texture3DTestES2,RGBA)4692 TEST_P(Texture3DTestES2, RGBA)
4693 {
4694 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4695
4696 // http://anglebug.com/42264265
4697 ANGLE_SKIP_TEST_IF(IsOzone());
4698
4699 glActiveTexture(GL_TEXTURE0);
4700 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4701 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
4702 std::vector<GLColor> texDataRed(1u * 1u * 1u, GLColor::red);
4703 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4704 texDataGreen.data());
4705 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4706 texDataRed.data());
4707 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4708 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4709
4710 EXPECT_GL_NO_ERROR();
4711
4712 drawQuad(mProgram, "position", 0.5f);
4713
4714 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4715 }
4716
4717 // Test that drawing works correctly Luminance 3D texture
TEST_P(Texture3DTestES2,Luminance)4718 TEST_P(Texture3DTestES2, Luminance)
4719 {
4720 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4721
4722 // http://anglebug.com/42264265
4723 ANGLE_SKIP_TEST_IF(IsOzone());
4724
4725 glActiveTexture(GL_TEXTURE0);
4726 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4727 std::vector<GLubyte> texData(2u * 2u * 2u, 125);
4728 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4729 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4730 texData.data());
4731 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4732 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4733
4734 EXPECT_GL_NO_ERROR();
4735
4736 drawQuad(mProgram, "position", 0.5f);
4737
4738 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(125, 125, 125, 255));
4739 }
4740
4741 // Test that drawing works correctly with glCopyTexSubImage3D
TEST_P(Texture3DTestES2,CopySubImageRGBA)4742 TEST_P(Texture3DTestES2, CopySubImageRGBA)
4743 {
4744 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4745
4746 // http://anglebug.com/42264265
4747 ANGLE_SKIP_TEST_IF(IsOzone());
4748
4749 glClearColor(0, 0, 1, 1);
4750 glClear(GL_COLOR_BUFFER_BIT);
4751
4752 glActiveTexture(GL_TEXTURE0);
4753 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4754 std::vector<GLColor> texDataRed(4u * 4u * 4u, GLColor::red);
4755 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4756 texDataRed.data());
4757 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4758 texDataRed.data());
4759 glTexImage3DOES(GL_TEXTURE_3D, 2, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4760 texDataRed.data());
4761 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4762 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4763 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4764 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4765
4766 EXPECT_GL_NO_ERROR();
4767
4768 glClearColor(0, 1, 0, 1);
4769 glClear(GL_COLOR_BUFFER_BIT);
4770 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4771
4772 glUseProgram(mProgram);
4773 glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4774 drawQuad(mProgram, "position", 0.5f);
4775
4776 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4777 }
4778
TEST_P(Texture3DTestES2,CopySubImageLuminance)4779 TEST_P(Texture3DTestES2, CopySubImageLuminance)
4780 {
4781 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4782
4783 // http://anglebug.com/42264265
4784 ANGLE_SKIP_TEST_IF(IsOzone());
4785
4786 glClearColor(1, 0, 0, 1);
4787 glClear(GL_COLOR_BUFFER_BIT);
4788
4789 glActiveTexture(GL_TEXTURE0);
4790 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4791 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 4, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4792 nullptr);
4793 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4794 nullptr);
4795 glTexImage3DOES(GL_TEXTURE_3D, 2, GL_LUMINANCE, 1, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4796 nullptr);
4797 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4798 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4799 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4800 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4801
4802 EXPECT_GL_NO_ERROR();
4803
4804 glClearColor(0, 1, 0, 1);
4805 glClear(GL_COLOR_BUFFER_BIT);
4806 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4807
4808 glUseProgram(mProgram);
4809 glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4810 drawQuad(mProgram, "position", 0.5f);
4811
4812 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
4813 }
4814
TEST_P(Texture3DTestES2,CopySubImageAlpha)4815 TEST_P(Texture3DTestES2, CopySubImageAlpha)
4816 {
4817 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4818
4819 // http://anglebug.com/42264265
4820 ANGLE_SKIP_TEST_IF(IsOzone());
4821
4822 glClearColor(1, 0, 0, 0.5);
4823 glClear(GL_COLOR_BUFFER_BIT);
4824
4825 glActiveTexture(GL_TEXTURE0);
4826 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4827 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_ALPHA, 4, 4, 4, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4828 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_ALPHA, 2, 2, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4829 glTexImage3DOES(GL_TEXTURE_3D, 2, GL_ALPHA, 1, 1, 1, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4830 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4831 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4832 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4833 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4834
4835 EXPECT_GL_NO_ERROR();
4836
4837 glClearColor(0, 1, 0, 1);
4838 glClear(GL_COLOR_BUFFER_BIT);
4839 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4840
4841 glUseProgram(mProgram);
4842 glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4843 drawQuad(mProgram, "position", 0.5f);
4844
4845 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 128), 1.0);
4846 }
4847
4848 // Test that defining a 2D texture array fails with Texture3DOES on ES2.
TEST_P(Texture3DTestES2,DefineTexture2DArrayShouldFail)4849 TEST_P(Texture3DTestES2, DefineTexture2DArrayShouldFail)
4850 {
4851 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4852
4853 // http://anglebug.com/42264265
4854 ANGLE_SKIP_TEST_IF(IsOzone());
4855
4856 glClearColor(1, 0, 0, 1);
4857 glClear(GL_COLOR_BUFFER_BIT);
4858
4859 glActiveTexture(GL_TEXTURE0);
4860 glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
4861 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4862
4863 glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4864 nullptr);
4865 glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4866 nullptr);
4867 glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4868 nullptr);
4869 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4870 }
4871
4872 // Verify shrinking a texture with glTexStorage2D works correctly
TEST_P(Texture2DTestES3,ChangeTexSizeWithTexStorage)4873 TEST_P(Texture2DTestES3, ChangeTexSizeWithTexStorage)
4874 {
4875 // TODO: http://anglebug.com/42263810
4876 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL());
4877
4878 constexpr uint32_t kSizeLarge = 128;
4879 constexpr uint32_t kSizeSmall = 64;
4880
4881 glActiveTexture(GL_TEXTURE0);
4882 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4883 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4884 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4885
4886 // Create the texture with 'large' dimensions
4887 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4888 nullptr);
4889 ASSERT_GL_NO_ERROR();
4890
4891 GLFramebuffer destFbo;
4892 glBindFramebuffer(GL_FRAMEBUFFER, destFbo);
4893 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0);
4894 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4895
4896 // Draw with the new texture so it's created in the back end
4897 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
4898 glUseProgram(blueProgram);
4899 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
4900 ASSERT_GL_NO_ERROR();
4901 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::blue);
4902
4903 // Shrink the texture
4904 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall);
4905 ASSERT_GL_NO_ERROR();
4906
4907 // Create a source texture/FBO to blit from
4908 GLTexture sourceTex;
4909 glBindTexture(GL_TEXTURE_2D, sourceTex);
4910 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall);
4911 ASSERT_GL_NO_ERROR();
4912 GLFramebuffer sourceFbo;
4913 glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo);
4914 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTex, 0);
4915 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4916 // Fill the source texture with green
4917 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4918 glUseProgram(greenProgram);
4919 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
4920 ASSERT_GL_NO_ERROR();
4921 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::green);
4922
4923 // Blit the source (green) to the destination
4924 glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo);
4925 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFbo);
4926 glBlitFramebuffer(0, 0, kSizeSmall, kSizeSmall, 0, 0, kSizeSmall, kSizeSmall,
4927 GL_COLOR_BUFFER_BIT, GL_NEAREST);
4928 ASSERT_GL_NO_ERROR();
4929
4930 // Render to the default framebuffer sampling from the blited texture and verify it's green
4931 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4932 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4933 ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
4934 glUseProgram(texProgram);
4935 drawQuad(texProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
4936 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4937 }
4938
4939 // Regression test for http://crbug.com/949985 to make sure dirty bits are propagated up from
4940 // TextureImpl and the texture is synced before being used in a draw call.
TEST_P(Texture2DTestES3,TextureImplPropogatesDirtyBits)4941 TEST_P(Texture2DTestES3, TextureImplPropogatesDirtyBits)
4942 {
4943 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
4944 // Flaky hangs on Win10 AMD RX 550 GL. http://anglebug.com/42262039
4945 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4946 // D3D Debug device reports an error. http://anglebug.com/40096590
4947 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
4948 // Support copy from levels outside the image range. http://anglebug.com/42263331
4949 ANGLE_SKIP_TEST_IF(IsVulkan());
4950
4951 // The workaround in the GL backend required to trigger this bug generates driver warning
4952 // messages.
4953 ScopedIgnorePlatformMessages ignoreMessages;
4954
4955 setUpProgram();
4956 glUseProgram(mProgram);
4957 glActiveTexture(GL_TEXTURE0 + mTexture2DUniformLocation);
4958
4959 GLTexture dest;
4960 glBindTexture(GL_TEXTURE_2D, dest);
4961
4962 GLTexture source;
4963 glBindTexture(GL_TEXTURE_2D, source);
4964
4965 // Put data in mip 0 and 1
4966 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4967 GLColor::red.data());
4968 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4969 GLColor::green.data());
4970
4971 // Disable mipmapping so source is complete
4972 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4973 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4974
4975 // Force the dirty bits to be synchronized in source
4976 drawQuad(mProgram, "position", 1.0f);
4977
4978 // Copy from mip 1 of the source. In the GL backend this internally sets the base level to mip
4979 // 1 and sets a dirty bit.
4980 glCopyTextureCHROMIUM(source, 1, GL_TEXTURE_2D, dest, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_FALSE,
4981 GL_FALSE, GL_FALSE);
4982
4983 // Draw again, assertions are generated if the texture has internal dirty bits at draw time
4984 drawQuad(mProgram, "position", 1.0f);
4985 }
4986
4987 // This test case changes the base level of a texture that's attached to a framebuffer, clears every
4988 // level to green, and then samples the texture when rendering. Test is taken from
4989 // https://www.khronos.org/registry/webgl/sdk/tests/conformance2/rendering/framebuffer-texture-changing-base-level.html
TEST_P(Texture2DTestES3,FramebufferTextureChangingBaselevel)4990 TEST_P(Texture2DTestES3, FramebufferTextureChangingBaselevel)
4991 {
4992 // TODO(cnorthrop): Failing on Vulkan/Windows/AMD. http://anglebug.com/42262633
4993 ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
4994
4995 setUpProgram();
4996
4997 constexpr GLint width = 8;
4998 constexpr GLint height = 4;
4999
5000 GLTexture texture;
5001 glBindTexture(GL_TEXTURE_2D, texture);
5002 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5003 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5004 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5005 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5006
5007 // Create all mipmap levels for the texture from level 0 to the 1x1 pixel level.
5008 GLint level = 0;
5009 GLint levelW = width;
5010 GLint levelH = height;
5011 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5012 nullptr);
5013 while (levelW > 1 || levelH > 1)
5014 {
5015 ++level;
5016 levelW = static_cast<GLint>(std::max(1.0, std::floor(width / std::pow(2, level))));
5017 levelH = static_cast<GLint>(std::max(1.0, std::floor(height / std::pow(2, level))));
5018 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5019 nullptr);
5020 }
5021
5022 // Clear each level of the texture using an FBO. Change the base level to match the level used
5023 // for the FBO on each iteration.
5024 GLFramebuffer fbo;
5025 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5026 level = 0;
5027 levelW = width;
5028 levelH = height;
5029 while (levelW > 1 || levelH > 1)
5030 {
5031 levelW = static_cast<GLint>(std::floor(width / std::pow(2, level)));
5032 levelH = static_cast<GLint>(std::floor(height / std::pow(2, level)));
5033
5034 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
5035 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, level);
5036
5037 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5038 EXPECT_GL_NO_ERROR();
5039
5040 glClearColor(0, 1, 0, 1);
5041 glClear(GL_COLOR_BUFFER_BIT);
5042
5043 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5044
5045 ++level;
5046 }
5047
5048 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5049 glViewport(0, 0, 16, 16);
5050 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5051
5052 drawQuad(mProgram, "position", 0.5f);
5053
5054 EXPECT_GL_NO_ERROR();
5055 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5056 }
5057
5058 // Test that changing the base level of a texture after redefining a level outside the mip-chain
5059 // preserves the other mips' data.
TEST_P(Texture2DBaseMaxTestES3,ExtendMipChainAfterRedefine)5060 TEST_P(Texture2DBaseMaxTestES3, ExtendMipChainAfterRedefine)
5061 {
5062 // http://anglebug.com/42263298
5063 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
5064
5065 // http://anglebug.com/42263714
5066 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA() && IsMac());
5067
5068 GLFramebuffer framebuffer;
5069 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5070
5071 GLTexture texture;
5072 glBindTexture(GL_TEXTURE_2D, texture);
5073
5074 std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
5075 fillMipData(mipData.data(), kMip0Size, kMipColors);
5076
5077 for (size_t mip = 1; mip < kMipCount; ++mip)
5078 {
5079 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA,
5080 GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip));
5081 }
5082
5083 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5084 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
5085 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5086
5087 // Mip 1 is green. Verify this.
5088 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]);
5089
5090 // http://anglebug.com/42263308
5091 ANGLE_SKIP_TEST_IF(IsOpenGL() && (IsIntel() || IsAMD()) && IsWindows());
5092
5093 // Add mip 0 and rebase the mip chain.
5094 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5095 mipData.data() + getMipDataOffset(kMip0Size, 0));
5096 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5097
5098 // Mip 1 should still be green.
5099 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]);
5100
5101 // Verify the other mips too.
5102 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
5103 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5104 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[2]);
5105
5106 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
5107 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5108 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[3]);
5109
5110 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
5111 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5112
5113 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]);
5114 }
5115
5116 // Test that changing the base level of a texture multiple times preserves the data.
TEST_P(Texture2DBaseMaxTestES3,PingPongBaseLevel)5117 TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevel)
5118 {
5119 testPingPongBaseLevel(false);
5120 }
TEST_P(Texture2DBaseMaxTestES3,PingPongBaseLevelImmutable)5121 TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevelImmutable)
5122 {
5123 testPingPongBaseLevel(true);
5124 }
testPingPongBaseLevel(bool immutable)5125 void Texture2DBaseMaxTestES3::testPingPongBaseLevel(bool immutable)
5126 {
5127 // http://anglebug.com/42263310
5128 ANGLE_SKIP_TEST_IF(IsD3D());
5129
5130 // http://anglebug.com/42263311
5131 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsWindows());
5132
5133 // http://anglebug.com/42263301
5134 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
5135
5136 initTest(immutable);
5137
5138 // Ping pong a few times.
5139 for (uint32_t tries = 0; tries < 2; ++tries)
5140 {
5141 // Rebase to different mips and verify mips.
5142 for (uint32_t base = 0; base < kMipCount; ++base)
5143 {
5144 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base);
5145 for (uint32_t lod = 0; lod < kMipCount - base; ++lod)
5146 {
5147 setLodUniform(lod);
5148 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5149 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]);
5150 }
5151 }
5152
5153 // Rebase backwards and verify mips.
5154 for (uint32_t base = kMipCount - 2; base > 0; --base)
5155 {
5156 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base);
5157 for (uint32_t lod = 0; lod < kMipCount - base; ++lod)
5158 {
5159 setLodUniform(lod);
5160 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5161 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]);
5162 }
5163 }
5164 }
5165 }
5166
5167 // Test that glTexSubImage2D after incompatibly redefining a mip level correctly applies the update
5168 // after the redefine data.
TEST_P(Texture2DBaseMaxTestES3,SubImageAfterRedefine)5169 TEST_P(Texture2DBaseMaxTestES3, SubImageAfterRedefine)
5170 {
5171 initTest(false);
5172
5173 // Test that all mips have the expected data initially (this makes sure the texture image is
5174 // created already).
5175 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5176 {
5177 setLodUniform(lod);
5178 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5179 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5180 }
5181
5182 // Redefine every level, followed by a glTexSubImage2D
5183 const GLColor kNewMipColors[kMipCount] = {
5184 GLColor::yellow,
5185 GLColor::cyan,
5186 GLColor(127, 0, 0, 255),
5187 GLColor(0, 127, 0, 255),
5188 };
5189 std::array<GLColor, getTotalMipDataSize(kMip0Size * 2)> newMipData;
5190 fillMipData(newMipData.data(), kMip0Size * 2, kNewMipColors);
5191
5192 const GLColor kSubImageMipColors[kMipCount] = {
5193 GLColor(0, 0, 127, 255),
5194 GLColor(127, 127, 0, 255),
5195 GLColor(0, 127, 127, 255),
5196 GLColor(127, 0, 127, 255),
5197 };
5198 std::array<GLColor, getTotalMipDataSize(kMip0Size)> subImageMipData;
5199 fillMipData(subImageMipData.data(), kMip0Size, kSubImageMipColors);
5200
5201 for (size_t mip = 0; mip < kMipCount; ++mip)
5202 {
5203 // Redefine the level.
5204 size_t newMipSize = (kMip0Size * 2) >> mip;
5205 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, newMipSize, newMipSize, 0, GL_RGBA,
5206 GL_UNSIGNED_BYTE, newMipData.data() + getMipDataOffset(kMip0Size * 2, mip));
5207
5208 // Immediately follow that with a subimage update.
5209 glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA,
5210 GL_UNSIGNED_BYTE,
5211 subImageMipData.data() + getMipDataOffset(kMip0Size, mip));
5212 }
5213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1);
5214
5215 // Test that the texture looks as expected.
5216 const int w = getWindowWidth() - 1;
5217 const int h = getWindowHeight() - 1;
5218 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5219 {
5220 setLodUniform(lod);
5221 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5222 EXPECT_PIXEL_COLOR_EQ(0, 0, kSubImageMipColors[lod]);
5223 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColors[lod]);
5224 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColors[lod]);
5225 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColors[lod]);
5226 }
5227 }
5228
5229 // Test that incompatibly redefining a level then redefining it back to its original size works.
TEST_P(Texture2DBaseMaxTestES3,IncompatiblyRedefineLevelThenRevert)5230 TEST_P(Texture2DBaseMaxTestES3, IncompatiblyRedefineLevelThenRevert)
5231 {
5232 initTest(false);
5233
5234 // Test that all mips have the expected data initially (this makes sure the texture image is
5235 // created already).
5236 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5237 {
5238 setLodUniform(lod);
5239 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5240 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5241 }
5242
5243 // Redefine Mip 1 to be larger.
5244 constexpr size_t kLargeMip1Size = getMipDataSize(kMip0Size * 2, 1);
5245 std::array<GLColor, kLargeMip1Size> interimMipData;
5246 std::fill(interimMipData.data(), interimMipData.data() + kLargeMip1Size, GLColor::yellow);
5247
5248 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5249 interimMipData.data());
5250
5251 // Redefine Mip 1 back to its original size.
5252 constexpr size_t kNormalMip1Size = getMipDataSize(kMip0Size, 1);
5253 std::array<GLColor, kLargeMip1Size> newMipData;
5254 std::fill(newMipData.data(), newMipData.data() + kNormalMip1Size, GLColor::cyan);
5255
5256 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size / 2, kMip0Size / 2, 0, GL_RGBA,
5257 GL_UNSIGNED_BYTE, newMipData.data());
5258
5259 // Verify texture colors.
5260 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5261 {
5262 setLodUniform(lod);
5263 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5264 EXPECT_PIXEL_COLOR_EQ(0, 0, lod == 1 ? GLColor::cyan : kMipColors[lod]);
5265 }
5266 }
5267
5268 // Test that redefining every level of a texture to another format works. The format uses more
5269 // bits per component, to ensure alignment requirements for the new format are taken into account.
TEST_P(Texture2DBaseMaxTestES3,RedefineEveryLevelToAnotherFormat)5270 TEST_P(Texture2DBaseMaxTestES3, RedefineEveryLevelToAnotherFormat)
5271 {
5272 initTest(false);
5273
5274 // Test that all mips have the expected data initially (this makes sure the texture image is
5275 // created already).
5276 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5277 {
5278 setLodUniform(lod);
5279 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5280 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5281 }
5282
5283 const GLColor32F kNewMipColors[kMipCount] = {
5284 GLColor32F(1.0, 1.0, 0.0, 1.0f),
5285 GLColor32F(1.0, 0.0, 1.0, 1.0f),
5286 GLColor32F(0.0, 1.0, 1.0, 1.0f),
5287 GLColor32F(1.0, 1.0, 1.0, 1.0f),
5288 };
5289
5290 std::array<GLColor32F, getTotalMipDataSize(kMip0Size)> newMipData;
5291 fillMipData(newMipData.data(), kMip0Size, kNewMipColors);
5292
5293 // Redefine every level with the new format.
5294 for (size_t mip = 0; mip < kMipCount; ++mip)
5295 {
5296 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA32F, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA,
5297 GL_FLOAT, newMipData.data() + getMipDataOffset(kMip0Size, mip));
5298 }
5299
5300 // Verify texture colors.
5301 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5302 {
5303 setLodUniform(lod);
5304 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5305
5306 GLColor32F mipColor32F = kNewMipColors[lod];
5307 GLColor mipColor(static_cast<GLubyte>(std::roundf(mipColor32F.R * 255)),
5308 static_cast<GLubyte>(std::roundf(mipColor32F.G * 255)),
5309 static_cast<GLubyte>(std::roundf(mipColor32F.B * 255)),
5310 static_cast<GLubyte>(std::roundf(mipColor32F.A * 255)));
5311
5312 EXPECT_PIXEL_COLOR_EQ(0, 0, mipColor);
5313 }
5314 }
5315
5316 // Test that generating mipmaps after change base level.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRebase)5317 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebase)
5318 {
5319 // http://anglebug.com/42264421
5320 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
5321
5322 testGenerateMipmapAfterRebase(false);
5323 }
5324
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRebaseImmutable)5325 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebaseImmutable)
5326 {
5327 // http://anglebug.com/42263310
5328 ANGLE_SKIP_TEST_IF(IsD3D());
5329 // http://anglebug.com/42264332
5330 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
5331 // http://anglebug.com/42264421
5332 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
5333
5334 testGenerateMipmapAfterRebase(true);
5335 }
5336
testGenerateMipmapAfterRebase(bool immutable)5337 void Texture2DBaseMaxTestES3::testGenerateMipmapAfterRebase(bool immutable)
5338 {
5339 initTest(immutable);
5340
5341 // Test that all mips have the expected data initially (this makes sure the texture image is
5342 // created already).
5343 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5344 {
5345 setLodUniform(lod);
5346 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5347 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5348 }
5349
5350 // Update level 1 (any level would do other than 0) with new data
5351 const GLColor kNewMipColor = GLColor::yellow;
5352 std::array<GLColor, getMipDataSize(kMip0Size >> 1, 0)> newMipData;
5353 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5354
5355 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kMip0Size >> 1, kMip0Size >> 1, GL_RGBA,
5356 GL_UNSIGNED_BYTE, newMipData.data());
5357
5358 // Change base level and max level and then generate mipmaps. This should redefine level 1 and 2
5359 // with kNewMipColor and leave levels 0 and 3 unchanged.
5360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 2);
5362 glGenerateMipmap(GL_TEXTURE_2D);
5363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1);
5365
5366 // Test that the texture looks as expected.
5367 const int w = getWindowWidth() - 1;
5368 const int h = getWindowHeight() - 1;
5369 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5370 {
5371 setLodUniform(lod);
5372 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5373 if (lod == 0)
5374 {
5375 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
5376 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
5377 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
5378 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
5379 }
5380 else if (lod == kMipCount - 1)
5381 {
5382 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
5383 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
5384 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
5385 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
5386 }
5387 else
5388 {
5389 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor) << "lod " << lod;
5390 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor) << "lod " << lod;
5391 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor) << "lod " << lod;
5392 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor) << "lod " << lod;
5393 }
5394 }
5395 }
5396
5397 // Test that generating mipmaps after incompatibly redefining a level works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefine)5398 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefine)
5399 {
5400 initTest(false);
5401
5402 // Test that all mips have the expected data initially (this makes sure the texture image is
5403 // created already).
5404 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5405 {
5406 setLodUniform(lod);
5407 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5408 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5409 }
5410
5411 // Redefine level 1 (any level would do other than 0) to an incompatible size, say the same size
5412 // as level 0.
5413 const GLColor kNewMipColor = GLColor::yellow;
5414 std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5415 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5416
5417 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5418 newMipData.data());
5419
5420 // Generate mipmaps. This should redefine level 1 back to being compatible with level 0.
5421 glGenerateMipmap(GL_TEXTURE_2D);
5422
5423 // Test that the texture looks as expected.
5424 const int w = getWindowWidth() - 1;
5425 const int h = getWindowHeight() - 1;
5426 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5427 {
5428 setLodUniform(lod);
5429 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5430 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]);
5431 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]);
5432 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]);
5433 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]);
5434 }
5435 }
5436
5437 // Test that generating mipmaps after incompatibly redefining a level while simultaneously changing
5438 // the base level works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefineAndRebase)5439 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefineAndRebase)
5440 {
5441 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
5442
5443 // http://crbug.com/1100613
5444 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
5445
5446 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
5447 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
5448
5449 initTest(false);
5450
5451 // Test that all mips have the expected data initially (this makes sure the texture image is
5452 // created already).
5453 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5454 {
5455 setLodUniform(lod);
5456 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5457 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << lod;
5458 }
5459
5460 // Redefine level 2 to an incompatible size, say the same size as level 0.
5461 const GLColor kNewMipColor = GLColor::yellow;
5462 std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5463 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5464
5465 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5466 newMipData.data());
5467
5468 // Set base level of the texture to 1 then generate mipmaps. Level 2 that's redefined should
5469 // go back to being compatibly defined.
5470 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5471 glGenerateMipmap(GL_TEXTURE_2D);
5472
5473 // Test that the texture looks as expected.
5474 const int w = getWindowWidth() - 1;
5475 const int h = getWindowHeight() - 1;
5476 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5477 {
5478 setLodUniform(lod);
5479 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5480 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]) << lod;
5481 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[1]) << lod;
5482 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[1]) << lod;
5483 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[1]) << lod;
5484 }
5485
5486 // Redefine level 1 (current base level) to an incompatible size.
5487 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5488 newMipData.data());
5489
5490 // Set base level of the texture back to 0 then generate mipmaps. Level 1 should go back to
5491 // being compatibly defined.
5492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5493 glGenerateMipmap(GL_TEXTURE_2D);
5494
5495 // Test that the texture looks as expected.
5496 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5497 {
5498 setLodUniform(lod);
5499 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5500 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]) << lod;
5501 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]) << lod;
5502 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]) << lod;
5503 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]) << lod;
5504 }
5505 }
5506
5507 // Test that generating mipmaps after incompatibly redefining the base level of the texture works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefiningBase)5508 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBase)
5509 {
5510 initTest(false);
5511
5512 // Test that all mips have the expected data initially (this makes sure the texture image is
5513 // created already).
5514 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5515 {
5516 setLodUniform(lod);
5517 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5518 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5519 }
5520
5521 // Redefine level 0 to an incompatible size.
5522 const GLColor kNewMipColor = GLColor::yellow;
5523 std::array<GLColor, getMipDataSize(kMip0Size * 2, 0)> newMipData;
5524 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5525
5526 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA,
5527 GL_UNSIGNED_BYTE, newMipData.data());
5528
5529 // Generate mipmaps.
5530 glGenerateMipmap(GL_TEXTURE_2D);
5531
5532 // Test that the texture looks as expected.
5533 const int w = getWindowWidth() - 1;
5534 const int h = getWindowHeight() - 1;
5535 for (uint32_t lod = 0; lod < kMipCount + 1; ++lod)
5536 {
5537 setLodUniform(lod);
5538 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5539 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor);
5540 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor);
5541 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor);
5542 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor);
5543 }
5544 }
5545
5546 // Test that generating mipmaps after incompatibly redefining the base level while simultaneously
5547 // changing MAX_LEVEL works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefiningBaseAndChangingMax)5548 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBaseAndChangingMax)
5549 {
5550 initTest(false);
5551
5552 // Test that all mips have the expected data initially (this makes sure the texture image is
5553 // created already).
5554 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5555 {
5556 setLodUniform(lod);
5557 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5558 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5559 }
5560
5561 // Redefine level 0 to an incompatible size.
5562 const GLColor kNewMipColor = GLColor::yellow;
5563 std::array<GLColor, getMipDataSize(kMip0Size * 2, 0)> newMipData;
5564 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5565
5566 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA,
5567 GL_UNSIGNED_BYTE, newMipData.data());
5568
5569 // Set max level of the texture to 2 then generate mipmaps.
5570 constexpr uint32_t kMaxLevel = 2;
5571 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMaxLevel);
5572 glGenerateMipmap(GL_TEXTURE_2D);
5573
5574 // Test that the texture looks as expected.
5575 const int w = getWindowWidth() - 1;
5576 const int h = getWindowHeight() - 1;
5577 for (uint32_t lod = 0; lod <= kMaxLevel; ++lod)
5578 {
5579 setLodUniform(lod);
5580 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5581 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor);
5582 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor);
5583 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor);
5584 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor);
5585 }
5586 }
5587
5588 // Test that stage invalid texture levels work.
TEST_P(Texture2DBaseMaxTestES3,StageInvalidLevels)5589 TEST_P(Texture2DBaseMaxTestES3, StageInvalidLevels)
5590 {
5591 constexpr uint32_t kMaxLevel = 2;
5592 const GLColor kMipColor[kMaxLevel + 1] = {GLColor::red, GLColor::green, GLColor::blue};
5593
5594 initTest(false);
5595
5596 GLTexture texture;
5597 glBindTexture(GL_TEXTURE_2D, texture);
5598
5599 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5600 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5601 std::vector<GLColor> texDataCyan(2u * 2u, GLColor::cyan);
5602 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataCyan.data());
5603 setLodUniform(0);
5604 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5605 EXPECT_GL_NO_ERROR();
5606
5607 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
5608 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5609 texDataGreen.data());
5610 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::blue);
5611 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5612 EXPECT_GL_NO_ERROR();
5613
5614 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5615 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5616 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5617 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5618
5619 // Test that the texture looks as expected.
5620 const int w = getWindowWidth() - 1;
5621 const int h = getWindowHeight() - 1;
5622 for (uint32_t lod = 0; lod <= kMaxLevel; ++lod)
5623 {
5624 setLodUniform(lod);
5625 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5626 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColor[lod]);
5627 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColor[lod]);
5628 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColor[lod]);
5629 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColor[lod]);
5630 }
5631 }
5632
5633 // Test redefine a mutable texture into an immutable texture.
TEST_P(Texture2DBaseMaxTestES3,RedefineMutableToImmutable)5634 TEST_P(Texture2DBaseMaxTestES3, RedefineMutableToImmutable)
5635 {
5636 // http://anglebug.com/42263310
5637 ANGLE_SKIP_TEST_IF(IsD3D());
5638
5639 // http://anglebug.com/42263301
5640 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
5641
5642 constexpr uint32_t kBaseLevel = 1;
5643 const GLColor kNewMipColors[kMipCount] = {
5644 GLColor::yellow,
5645 GLColor::cyan,
5646 GLColor::white,
5647 GLColor(127u, 127u, 127u, 255u),
5648 };
5649
5650 initTest(false);
5651
5652 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, kBaseLevel);
5653
5654 // Test that all mips have the expected data
5655 for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
5656 {
5657 setLodUniform(lod - kBaseLevel);
5658 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5659 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5660 }
5661
5662 glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size);
5663 std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
5664 fillMipData(mipData.data(), kMip0Size, kNewMipColors);
5665 for (size_t mip = 0; mip < kMipCount; ++mip)
5666 {
5667 glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA,
5668 GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip));
5669 }
5670
5671 // Test that all enabled mips have the expected data
5672 for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
5673 {
5674 setLodUniform(lod - kBaseLevel);
5675 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5676 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
5677 }
5678
5679 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5680 for (uint32_t lod = 0; lod < kBaseLevel; ++lod)
5681 {
5682 setLodUniform(lod);
5683 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5684 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
5685 }
5686 }
5687
5688 // Test that redefine a level with incompatible size beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,RedefineIncompatibleLevelBeyondMaxLevel)5689 TEST_P(Texture2DBaseMaxTestES3, RedefineIncompatibleLevelBeyondMaxLevel)
5690 {
5691 initTest(false);
5692
5693 // Test that all mips have the expected data initially (this makes sure the texture image is
5694 // created already).
5695 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5696 {
5697 setLodUniform(lod);
5698 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5699 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5700 }
5701
5702 uint32_t maxLevel = 1;
5703 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
5704
5705 // Update level 0
5706 const GLColor kNewMipLevle0Color = GLColor::yellow;
5707 std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5708 std::fill(newMipData.begin(), newMipData.end(), kNewMipLevle0Color);
5709 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kMip0Size, kMip0Size, GL_RGBA, GL_UNSIGNED_BYTE,
5710 newMipData.data());
5711
5712 // Update level 2 with incompatible data
5713 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5714 newMipData.data());
5715 EXPECT_GL_NO_ERROR();
5716
5717 // Test that the texture looks as expected.
5718 const int w = getWindowWidth() - 1;
5719 const int h = getWindowHeight() - 1;
5720 for (uint32_t lod = 0; lod < maxLevel; ++lod)
5721 {
5722 setLodUniform(lod);
5723 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5724 if (lod == 0)
5725 {
5726 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipLevle0Color);
5727 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipLevle0Color);
5728 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipLevle0Color);
5729 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipLevle0Color);
5730 }
5731 else
5732 {
5733 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5734 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]);
5735 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]);
5736 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]);
5737 }
5738 }
5739 }
5740
5741 // Port test from web_gl/conformance2/textures/misc/fuzz-545-immutable-tex-render-feedback.html.
5742 // What this tries to do is create a render feedback loop and ensure it is not crashing.
TEST_P(Texture2DBaseMaxTestES3,Fuzz545ImmutableTexRenderFeedback)5743 TEST_P(Texture2DBaseMaxTestES3, Fuzz545ImmutableTexRenderFeedback)
5744 {
5745 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5746
5747 constexpr uint32_t MIPS = 2;
5748 constexpr uint32_t SIZE = 10;
5749
5750 GLTexture immutTex;
5751 glBindTexture(GL_TEXTURE_2D, immutTex);
5752 glTexStorage2D(GL_TEXTURE_2D, MIPS, GL_RGBA8, SIZE, SIZE);
5753
5754 GLTexture mutTex;
5755 glBindTexture(GL_TEXTURE_2D, mutTex);
5756 for (uint32_t mip = 0; mip < MIPS; mip++)
5757 {
5758 const uint32_t size = SIZE >> mip;
5759 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5760 nullptr);
5761 }
5762
5763 constexpr GLenum MAG_FILTERS[] = {GL_LINEAR, GL_NEAREST};
5764 constexpr GLenum MIN_FILTERS[] = {
5765 GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST,
5766 GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST};
5767
5768 GLFramebuffer fbo;
5769 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5770
5771 const GLuint texs[] = {immutTex, mutTex};
5772 for (const GLuint tex : texs)
5773 {
5774 glBindTexture(GL_TEXTURE_2D, tex);
5775
5776 for (GLuint level_prime_base = 0; level_prime_base < (MIPS + 1); level_prime_base++)
5777 { // `level_base` in GLES
5778 // ES 3.0.6 p150
5779 GLuint _level_base = level_prime_base;
5780 if (tex == immutTex)
5781 {
5782 _level_base = std::min(_level_base, MIPS - 1);
5783 }
5784 const GLuint level_base = _level_base;
5785
5786 for (GLuint _level_prime_max = (level_prime_base - 1); _level_prime_max < (MIPS + 2);
5787 _level_prime_max++)
5788 { // `q` in GLES
5789 if (_level_prime_max < 0)
5790 continue;
5791 if (_level_prime_max == (MIPS + 1))
5792 {
5793 _level_prime_max = 10000; // This is the default, after all!
5794 }
5795 const GLuint level_prime_max = _level_prime_max;
5796
5797 // ES 3.0.6 p150
5798 GLuint _level_max = level_prime_max;
5799 if (tex == immutTex)
5800 {
5801 _level_max = std::min(std::max(level_base, level_prime_max), MIPS - 1);
5802 }
5803 const GLuint level_max = _level_max;
5804
5805 const GLuint p = std::floor((float)std::log2(SIZE)) + level_base;
5806 const GLuint q = std::min(p, level_max);
5807
5808 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level_prime_base);
5809 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level_prime_max);
5810
5811 const bool mipComplete = (q <= MIPS - 1);
5812
5813 for (const GLenum minFilter : MIN_FILTERS)
5814 {
5815 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
5816
5817 for (const GLenum magFilter : MAG_FILTERS)
5818 {
5819 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
5820
5821 for (GLuint dstMip = 0; dstMip < (MIPS + 1); dstMip++)
5822 {
5823 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5824 GL_TEXTURE_2D, tex, dstMip);
5825
5826 // ES3.0 p213-214
5827 bool fbComplete = true;
5828
5829 // * "The width and height of `image` are non-zero"
5830 fbComplete &= (0 <= dstMip && dstMip <= MIPS - 1);
5831
5832 if (tex != immutTex)
5833 { // "...does not name an immutable-format texture..."
5834 // * "...the value of [level] must be in the range `[level_base,
5835 // q]`"
5836 fbComplete &= (level_base <= dstMip && dstMip <= q);
5837
5838 // * "...the value of [level] is not `level_base`, then the texture
5839 // must be mipmap complete"
5840 if (dstMip != level_base)
5841 {
5842 fbComplete &= mipComplete;
5843 }
5844 }
5845
5846 // -
5847 GLenum expectError = 0;
5848 GLenum expectStatus = GL_FRAMEBUFFER_COMPLETE;
5849 if (!fbComplete)
5850 {
5851 expectStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
5852 expectError = GL_INVALID_FRAMEBUFFER_OPERATION;
5853 }
5854
5855 // -
5856 EXPECT_GLENUM_EQ(expectStatus,
5857 glCheckFramebufferStatus(GL_FRAMEBUFFER));
5858
5859 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
5860 EXPECT_EQ(expectError, glGetError());
5861 }
5862 }
5863 }
5864 }
5865 }
5866 }
5867 }
5868
5869 // Test sampling from a texture of a (usually) not color-renderable
5870 // base format with a color-renderable level beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,NotColorRenderableWithColorRenderableBeyondMaxLevel)5871 TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableWithColorRenderableBeyondMaxLevel)
5872 {
5873 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5874
5875 GLTexture texture;
5876 glBindTexture(GL_TEXTURE_2D, texture);
5877 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5878 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5879
5880 const GLuint data[4] = {0xC0040200, 0xC0040200, 0xC0040200, 0xC0040200};
5881 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 2, 2, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data);
5882 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5883 ASSERT_GL_NO_ERROR();
5884
5885 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5886 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5887 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5888 }
5889
5890 // Test sampling from a texture of a depth-renderable base format
5891 // with a color-renderable level beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,DepthRenderableWithColorRenderableBeyondMaxLevel)5892 TEST_P(Texture2DBaseMaxTestES3, DepthRenderableWithColorRenderableBeyondMaxLevel)
5893 {
5894 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5895
5896 GLTexture texture;
5897 glBindTexture(GL_TEXTURE_2D, texture);
5898 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5899 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5900
5901 const GLfloat data[4] = {1.0f, 1.0f, 1.0f, 1.0f};
5902 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
5903 data);
5904 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5905 ASSERT_GL_NO_ERROR();
5906
5907 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5908 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5909 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5910 }
5911
5912 // Test texture sampling while changing the base format from color-renderable
5913 // to (usually) not color-renderable by manipulating base and max levels.
TEST_P(Texture2DBaseMaxTestES3,NotColorRenderableAfterColorRenderableBelowBaseLevel)5914 TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableAfterColorRenderableBelowBaseLevel)
5915 {
5916 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5917
5918 GLTexture texture;
5919 glBindTexture(GL_TEXTURE_2D, texture);
5920 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5921 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5922
5923 std::array<GLColor, 4> data0;
5924 data0.fill(GLColor::green);
5925 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data());
5926
5927 const GLuint data1[1] = {0xC0040200};
5928 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data1);
5929 ASSERT_GL_NO_ERROR();
5930
5931 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5932 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5933 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5934
5935 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5936 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5937 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5938 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5939 }
5940
5941 // Test texture sampling while changing the base format from color-renderable
5942 // to depth-renderable by manipulating base and max levels.
TEST_P(Texture2DBaseMaxTestES3,DepthRenderableAfterColorRenderableBelowBaseLevel)5943 TEST_P(Texture2DBaseMaxTestES3, DepthRenderableAfterColorRenderableBelowBaseLevel)
5944 {
5945 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5946
5947 GLTexture texture;
5948 glBindTexture(GL_TEXTURE_2D, texture);
5949 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5950 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5951
5952 std::array<GLColor, 4> data0;
5953 data0.fill(GLColor::green);
5954 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data());
5955
5956 const GLfloat data1[1] = {1.0f};
5957 glTexImage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
5958 data1);
5959 ASSERT_GL_NO_ERROR();
5960
5961 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5962 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5963 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5964
5965 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5966 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5967 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5968 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5969 }
5970
5971 // Test that the following scenario works:
5972 // - change a texture's max level to 0.
5973 // - clear the texture with glClear.
5974 // - sample the texture and draw to another FBO.
5975 // - draw to the texture again.
5976 // - The texture's final color should be clear color in 1st pass + draw color.
TEST_P(Texture2DBaseMaxTestES3,SetMaxLevelToZeroThenClearThenSampleThenDraw)5977 TEST_P(Texture2DBaseMaxTestES3, SetMaxLevelToZeroThenClearThenSampleThenDraw)
5978 {
5979 ANGLE_GL_PROGRAM(textureProgram, angle::essl3_shaders::vs::Texture2DLod(),
5980 angle::essl3_shaders::fs::Texture2DLod());
5981 ANGLE_GL_PROGRAM(blueProgram, angle::essl1_shaders::vs::Simple(),
5982 angle::essl1_shaders::fs::Blue());
5983
5984 GLTexture texture;
5985 glBindTexture(GL_TEXTURE_2D, texture);
5986 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5987 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5988 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5989
5990 // 1. Change the texture's max level to 0.
5991 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5992 EXPECT_GL_NO_ERROR();
5993
5994 // 2. Attach the texture to a FBO and clear it.
5995 GLFramebuffer fbo;
5996 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5997 EXPECT_GL_NO_ERROR();
5998 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
5999 glEnable(GL_BLEND);
6000 glBlendFunc(GL_ONE, GL_ONE);
6001 glClearColor(1.0f / 255.0f, 2.0f / 255.0f, 3.0f / 255.0f, 4.0f / 255.0f);
6002 glClear(GL_COLOR_BUFFER_BIT);
6003
6004 // 3. Draw the bound texture to default FBO.
6005 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6006 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6007 glClear(GL_COLOR_BUFFER_BIT);
6008 glUseProgram(textureProgram);
6009 drawQuad(textureProgram, angle::essl1_shaders::PositionAttrib(), 0.5f);
6010
6011 // 4. Draw to the texture again
6012 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6013 glUseProgram(blueProgram);
6014 drawQuad(blueProgram, angle::essl1_shaders::PositionAttrib(), 0.5f);
6015
6016 // Expect the final color to be accumulated color
6017 EXPECT_GL_NO_ERROR();
6018 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(1, 2, 255, 255));
6019 }
6020
6021 // Test that the following scenario works:
6022 // - change a texture's max level to 1.
6023 // - clear the texture with glClear.
6024 // - change the texture's max level to 0.
6025 // - sample the texture and draw to another FBO.
6026 // - draw to the texture again.
6027 // - The texture's final color should be clear color in 1st pass + draw color.
TEST_P(Texture2DBaseMaxTestES3,SetMaxLevelToOneThenClearThenSetMaxLevelToZeroThenSampleThenDraw)6028 TEST_P(Texture2DBaseMaxTestES3, SetMaxLevelToOneThenClearThenSetMaxLevelToZeroThenSampleThenDraw)
6029 {
6030 ANGLE_GL_PROGRAM(textureProgram, angle::essl3_shaders::vs::Texture2DLod(),
6031 angle::essl3_shaders::fs::Texture2DLod());
6032 ANGLE_GL_PROGRAM(blueProgram, angle::essl1_shaders::vs::Simple(),
6033 angle::essl1_shaders::fs::Blue());
6034
6035 GLTexture texture;
6036 glBindTexture(GL_TEXTURE_2D, texture);
6037 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6038 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6039 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6040 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6041
6042 // 1. Change the texture's max level to 1.
6043 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6044 EXPECT_GL_NO_ERROR();
6045
6046 // 2. Attach the texture to a FBO and clear it.
6047 GLFramebuffer fbo;
6048 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6049 EXPECT_GL_NO_ERROR();
6050 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6051 glEnable(GL_BLEND);
6052 glBlendFunc(GL_ONE, GL_ONE);
6053 glClearColor(1.0f / 255.0f, 2.0f / 255.0f, 3.0f / 255.0f, 4.0f / 255.0f);
6054 glClear(GL_COLOR_BUFFER_BIT);
6055
6056 // 3. Change the texture's max level to 0.
6057 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6058
6059 // 4. Draw the bound texture to default FBO.
6060 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6061 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6062 glClear(GL_COLOR_BUFFER_BIT);
6063 glUseProgram(textureProgram);
6064 drawQuad(textureProgram, angle::essl1_shaders::PositionAttrib(), 0.5f);
6065
6066 // 5. Draw to the texture again
6067 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6068 glUseProgram(blueProgram);
6069 drawQuad(blueProgram, angle::essl1_shaders::PositionAttrib(), 0.5f);
6070
6071 // Expect the final color to be accumulated color
6072 EXPECT_GL_NO_ERROR();
6073 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(1, 2, 255, 255));
6074 }
6075
6076 // Test to check that texture completeness is determined correctly when the texture base level is
6077 // greater than 0, and also that level 0 is not sampled when base level is greater than 0.
TEST_P(Texture2DTestES3,DrawWithBaseLevel1)6078 TEST_P(Texture2DTestES3, DrawWithBaseLevel1)
6079 {
6080 glActiveTexture(GL_TEXTURE0);
6081 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6082
6083 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
6084 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6085 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6086 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6087 texDataGreen.data());
6088 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6089 texDataGreen.data());
6090 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6091 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6092 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6093
6094 EXPECT_GL_NO_ERROR();
6095
6096 drawQuad(mProgram, "position", 0.5f);
6097
6098 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6099 }
6100
testCopyImage(const APIExtensionVersion usedExtension)6101 void Texture2DTestES3::testCopyImage(const APIExtensionVersion usedExtension)
6102 {
6103 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
6104
6105 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
6106 GLTexture srcTexture;
6107 GLTexture destTexture;
6108
6109 glActiveTexture(GL_TEXTURE0);
6110 glBindTexture(GL_TEXTURE_2D, destTexture);
6111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6115 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6116
6117 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6118 glBindTexture(GL_TEXTURE_2D, srcTexture);
6119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6120 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6123 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6124 texDataGreen.data());
6125
6126 glBindTexture(GL_TEXTURE_2D, 0);
6127
6128 // copy
6129 if (usedExtension == APIExtensionVersion::OES)
6130 {
6131 glCopyImageSubDataOES(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0,
6132 2, 2, 0, 2, 2, 1);
6133 }
6134 else
6135 {
6136 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0,
6137 2, 2, 0, 2, 2, 1);
6138 }
6139 glBindTexture(GL_TEXTURE_2D, destTexture);
6140 EXPECT_GL_NO_ERROR();
6141
6142 glViewport(0, 0, 4, 4);
6143 drawQuad(mProgram, "position", 0.5f);
6144 EXPECT_GL_NO_ERROR();
6145
6146 EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green);
6147 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red);
6148 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red);
6149 }
6150
6151 // Test basic GL_EXT_copy_image copy without any bound textures
TEST_P(Texture2DTestES3,CopyImageEXT)6152 TEST_P(Texture2DTestES3, CopyImageEXT)
6153 {
6154 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6155 testCopyImage(APIExtensionVersion::EXT);
6156 }
6157
6158 // Test basic GL_OES_copy_image copy without any bound textures
TEST_P(Texture2DTestES3,CopyImageOES)6159 TEST_P(Texture2DTestES3, CopyImageOES)
6160 {
6161 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image"));
6162 testCopyImage(APIExtensionVersion::OES);
6163 }
6164
testCopyImageDepthStencil(const APIExtensionVersion usedExtension)6165 void Texture2DTestES3::testCopyImageDepthStencil(const APIExtensionVersion usedExtension)
6166 {
6167 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
6168
6169 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
6170 GLTexture srcTexture;
6171 GLTexture destTexture;
6172
6173 constexpr GLsizei kSize = 4;
6174
6175 GLTexture src;
6176 glBindTexture(GL_TEXTURE_2D, src);
6177 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
6178
6179 GLTexture dst;
6180 glBindTexture(GL_TEXTURE_2D, dst);
6181 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
6182
6183 // A color image for testing depth/stencil
6184 GLTexture color;
6185 glBindTexture(GL_TEXTURE_2D, color);
6186 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
6187
6188 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
6189 glUseProgram(program);
6190 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
6191 ASSERT_NE(colorLoc, -1);
6192
6193 // Initialize the src depth image
6194 GLFramebuffer fbo;
6195 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6196 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
6197 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, src, 0);
6198 glClearDepthf(0.3f);
6199 glClearStencil(0x57);
6200 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
6201
6202 glEnable(GL_DEPTH_TEST);
6203 glDepthMask(GL_FALSE);
6204 glEnable(GL_STENCIL_TEST);
6205 glStencilFunc(GL_EQUAL, 0x57, 0xFF);
6206 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
6207 glStencilMask(0xFF);
6208
6209 glDepthFunc(GL_LESS);
6210 glUniform4f(colorLoc, 1, 0, 0, 1);
6211 drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f);
6212 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6213
6214 glDepthFunc(GL_GREATER);
6215 glUniform4f(colorLoc, 0, 1, 0, 1);
6216 drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f);
6217 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6218 ASSERT_GL_NO_ERROR();
6219
6220 // Now that the depth stencil image is definitely initialized, copy it into the destination
6221 if (usedExtension == APIExtensionVersion::OES)
6222 {
6223 glCopyImageSubDataOES(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
6224 kSize, 1);
6225 }
6226 else
6227 {
6228 glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
6229 kSize, 1);
6230 }
6231 ASSERT_GL_NO_ERROR();
6232
6233 // Verify the dst texture has the right depth/stencil values
6234 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dst, 0);
6235
6236 glDepthFunc(GL_LESS);
6237 glUniform4f(colorLoc, 0, 0, 1, 1);
6238 drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f);
6239 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
6240
6241 glDepthFunc(GL_GREATER);
6242 glUniform4f(colorLoc, 1, 1, 0, 1);
6243 drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f);
6244 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
6245 ASSERT_GL_NO_ERROR();
6246 }
6247
6248 // Test basic GL_EXT_copy_image copy with a depth/stencil texture
TEST_P(Texture2DTestES3,CopyImageEXTDepthStencil)6249 TEST_P(Texture2DTestES3, CopyImageEXTDepthStencil)
6250 {
6251 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6252 testCopyImageDepthStencil(APIExtensionVersion::EXT);
6253 }
6254
6255 // Test basic GL_OES_copy_image copy with a depth/stencil texture
TEST_P(Texture2DTestES3,CopyImageOESDepthStencil)6256 TEST_P(Texture2DTestES3, CopyImageOESDepthStencil)
6257 {
6258 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image"));
6259 testCopyImageDepthStencil(APIExtensionVersion::OES);
6260 }
6261
6262 // Test GL_EXT_copy_image compressed texture copy with mipmaps smaller than the block size
TEST_P(Texture2DTestES3,CopyCompressedImageMipMaps)6263 TEST_P(Texture2DTestES3, CopyCompressedImageMipMaps)
6264 {
6265 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6266 // TODO(http://anglebug.com/42264170): Fix calls to vkCmdCopyBufferToImage() with images smaller
6267 // than the compressed format block size.
6268 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
6269
6270 constexpr uint32_t kSize = 4;
6271 constexpr size_t kNumLevels = 3;
6272 const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0};
6273
6274 GLTexture srcTexture;
6275 glBindTexture(GL_TEXTURE_2D, srcTexture);
6276 for (size_t level = 0; level < kNumLevels; ++level)
6277 {
6278 glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
6279 kSize >> level, 0, 8, CompressedImageETC1);
6280 EXPECT_GL_NO_ERROR();
6281 }
6282
6283 GLTexture destTexture;
6284 glBindTexture(GL_TEXTURE_2D, destTexture);
6285 for (size_t level = 0; level < kNumLevels; ++level)
6286 {
6287 glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
6288 kSize >> level, 0, 8, nullptr);
6289 EXPECT_GL_NO_ERROR();
6290 }
6291
6292 glBindTexture(GL_TEXTURE_2D, 0);
6293
6294 // copy
6295 for (size_t level = 0; level < kNumLevels; ++level)
6296 {
6297 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, level, 0, 0, 0, destTexture, GL_TEXTURE_2D,
6298 level, 0, 0, 0, kSize >> level, kSize >> level, 1);
6299 EXPECT_GL_NO_ERROR();
6300 }
6301 }
6302
6303 // Test GL_EXT_copy_image copy with a non-zero base level
TEST_P(Texture2DTestES3,CopyImageBaseLevel1)6304 TEST_P(Texture2DTestES3, CopyImageBaseLevel1)
6305 {
6306 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6307
6308 std::vector<GLColor> texDataBlack(8u * 8u, GLColor::black);
6309 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
6310 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6311 std::vector<GLColor> texDataBlue(4u * 4u, GLColor::blue);
6312
6313 GLTexture srcTexture;
6314 GLTexture destTexture;
6315
6316 glActiveTexture(GL_TEXTURE0);
6317 glBindTexture(GL_TEXTURE_2D, destTexture);
6318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6320 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6321 texDataBlack.data());
6322 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6323 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6324 texDataGreen.data());
6325 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data());
6326 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6328
6329 glBindTexture(GL_TEXTURE_2D, srcTexture);
6330 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6331 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6332 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6333 texDataBlack.data());
6334 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6335 texDataGreen.data());
6336 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data());
6337 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6338 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6340
6341 glBindTexture(GL_TEXTURE_2D, 0);
6342
6343 // copy
6344 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 1, 2, 2, 0, destTexture, GL_TEXTURE_2D, 1, 2,
6345 2, 0, 2, 2, 1);
6346
6347 glBindTexture(GL_TEXTURE_2D, destTexture);
6348
6349 EXPECT_GL_NO_ERROR();
6350
6351 glViewport(0, 0, 4, 4);
6352 drawQuad(mProgram, "position", 0.5f);
6353 EXPECT_GL_NO_ERROR();
6354
6355 EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green);
6356 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red);
6357 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red);
6358 }
6359
6360 // Test basic GL_EXT_copy_image copy without any draw calls by attaching the texture
6361 // to a framebuffer and reads from the framebuffer to validate the copy
TEST_P(Texture2DTestES3,CopyImageFB)6362 TEST_P(Texture2DTestES3, CopyImageFB)
6363 {
6364 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6365
6366 glViewport(0, 0, 4, 4);
6367 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
6368 GLTexture srcTexture;
6369 GLTexture destTexture;
6370
6371 glActiveTexture(GL_TEXTURE0);
6372 glBindTexture(GL_TEXTURE_2D, destTexture);
6373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6377 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6378
6379 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6380 glBindTexture(GL_TEXTURE_2D, srcTexture);
6381 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6382 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6385 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6386 texDataGreen.data());
6387 glBindTexture(GL_TEXTURE_2D, 0);
6388
6389 // copy
6390 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, destTexture, GL_TEXTURE_2D, 0, 0,
6391 1, 0, 3, 3, 1);
6392
6393 EXPECT_GL_NO_ERROR();
6394
6395 GLFramebuffer fb;
6396 glBindFramebuffer(GL_FRAMEBUFFER, fb);
6397 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0);
6398 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6399
6400 EXPECT_PIXEL_RECT_EQ(0, 1, 3, 3, GLColor::green);
6401 EXPECT_PIXEL_RECT_EQ(3, 0, 1, 4, GLColor::red);
6402 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 1, GLColor::red);
6403
6404 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6405 }
6406
6407 // Test GL_EXT_copy_image copy to a framebuffer attachment after
6408 // invalidation. Then draw with blending onto the framebuffer.
TEST_P(Texture2DTestES3,CopyImageFBInvalidateThenBlend)6409 TEST_P(Texture2DTestES3, CopyImageFBInvalidateThenBlend)
6410 {
6411 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6412
6413 ANGLE_GL_PROGRAM(drawBlueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6414 ANGLE_GL_PROGRAM(drawRedProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6415
6416 glViewport(0, 0, 4, 4);
6417 GLTexture srcTexture;
6418 GLTexture textureAttachment;
6419
6420 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6421 glBindTexture(GL_TEXTURE_2D, srcTexture);
6422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6424 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6425 texDataGreen.data());
6426 glBindTexture(GL_TEXTURE_2D, 0);
6427
6428 glBindTexture(GL_TEXTURE_2D, textureAttachment);
6429 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6430 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6431 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6432 glBindTexture(GL_TEXTURE_2D, 0);
6433
6434 GLFramebuffer fb;
6435 glBindFramebuffer(GL_FRAMEBUFFER, fb);
6436 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureAttachment,
6437 0);
6438 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6439
6440 // Draw something in the texture to make sure it's image is defined.
6441 drawQuad(drawRedProgram, essl1_shaders::PositionAttrib(), 0.0f);
6442
6443 // Invalidate the framebuffer.
6444 const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
6445 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
6446 ASSERT_GL_NO_ERROR();
6447
6448 // Copy into the framebuffer attachment.
6449 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, textureAttachment, GL_TEXTURE_2D,
6450 0, 0, 0, 0, 4, 4, 1);
6451 EXPECT_GL_NO_ERROR();
6452
6453 // Draw and blend, making sure both the copy and draw happen correctly.
6454 glEnable(GL_BLEND);
6455 glBlendFunc(GL_ONE, GL_ONE);
6456 drawQuad(drawBlueProgram, essl1_shaders::PositionAttrib(), 0.0f);
6457 ASSERT_GL_NO_ERROR();
6458
6459 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::cyan);
6460
6461 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6462 }
6463
6464 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
6465 // have images defined.
TEST_P(Texture2DTestES3,DrawWithLevelsOutsideRangeUndefined)6466 TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeUndefined)
6467 {
6468 // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
6469 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
6470
6471 glActiveTexture(GL_TEXTURE0);
6472 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6473 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6474 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6475 texDataGreen.data());
6476 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6477 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6478 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6479 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6480
6481 EXPECT_GL_NO_ERROR();
6482
6483 drawQuad(mProgram, "position", 0.5f);
6484
6485 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6486 }
6487
6488 // Test that drawing works correctly when level 0 is undefined and base level is 1.
TEST_P(Texture2DTestES3,DrawWithLevelZeroUndefined)6489 TEST_P(Texture2DTestES3, DrawWithLevelZeroUndefined)
6490 {
6491 // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
6492 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
6493
6494 glActiveTexture(GL_TEXTURE0);
6495 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6496 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6497 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6498 texDataGreen.data());
6499 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6500 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6501 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6502 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
6503
6504 EXPECT_GL_NO_ERROR();
6505
6506 // Texture is incomplete.
6507 drawQuad(mProgram, "position", 0.5f);
6508 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6509
6510 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6511 texDataGreen.data());
6512
6513 // Texture is now complete.
6514 drawQuad(mProgram, "position", 0.5f);
6515 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6516 }
6517
6518 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
6519 // dimensions that don't fit the images inside the range.
6520 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)6521 TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
6522 {
6523 glActiveTexture(GL_TEXTURE0);
6524 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6525 std::vector<GLColor> texDataRed(8u * 8u, GLColor::red);
6526 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6527 std::vector<GLColor> texDataCyan(2u * 2u, GLColor::cyan);
6528
6529 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6531
6532 // Two levels that are initially unused.
6533 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6534 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6535 texDataCyan.data());
6536
6537 // One level that is used - only this level should affect completeness.
6538 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6539 texDataGreen.data());
6540
6541 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6542 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6543
6544 EXPECT_GL_NO_ERROR();
6545
6546 drawQuad(mProgram, "position", 0.5f);
6547
6548 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6549
6550 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6551
6552 // Switch the level that is being used to the cyan level 2.
6553 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
6554 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
6555
6556 EXPECT_GL_NO_ERROR();
6557
6558 drawQuad(mProgram, "position", 0.5f);
6559
6560 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6561 }
6562
6563 // Depth/Stencil textures cannot be 3D.
TEST_P(Texture3DTestES3,DepthStencil3DDisallowed)6564 TEST_P(Texture3DTestES3, DepthStencil3DDisallowed)
6565 {
6566 const std::array<std::tuple<GLenum, GLenum, GLenum>, 6> testConfigs = {
6567 std::make_tuple(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT),
6568 std::make_tuple(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT),
6569 std::make_tuple(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT),
6570 std::make_tuple(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV),
6571 std::make_tuple(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8),
6572 std::make_tuple(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE)};
6573
6574 for (auto testConfig : testConfigs)
6575 {
6576 const GLenum internalformat = std::get<0>(testConfig);
6577 const GLenum format = std::get<1>(testConfig);
6578 const GLenum type = std::get<2>(testConfig);
6579
6580 if (internalformat == GL_STENCIL_INDEX8 && !IsGLExtensionEnabled("GL_OES_texture_stencil8"))
6581 {
6582 continue;
6583 }
6584
6585 GLTexture depthTexture;
6586 glBindTexture(GL_TEXTURE_3D, depthTexture);
6587 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, 16, 16, 16, 0, format, type, nullptr);
6588 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6589
6590 glTexStorage3D(GL_TEXTURE_3D, 2, internalformat, 16, 16, 16);
6591 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6592 }
6593 }
6594
6595 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
6596 // have images defined.
TEST_P(Texture3DTestES3,DrawWithLevelsOutsideRangeUndefined)6597 TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeUndefined)
6598 {
6599 glActiveTexture(GL_TEXTURE0);
6600 glBindTexture(GL_TEXTURE_3D, mTexture3D);
6601 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6602 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6603 texDataGreen.data());
6604 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6605 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6606 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
6607 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
6608
6609 EXPECT_GL_NO_ERROR();
6610
6611 drawQuad(mProgram, "position", 0.5f);
6612
6613 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6614 }
6615
6616 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
6617 // dimensions that don't fit the images inside the range.
6618 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture3DTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)6619 TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
6620 {
6621 glActiveTexture(GL_TEXTURE0);
6622 glBindTexture(GL_TEXTURE_3D, mTexture3D);
6623 std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
6624 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6625 std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
6626
6627 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6628 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6629
6630 // Two levels that are initially unused.
6631 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6632 texDataRed.data());
6633 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6634 texDataCyan.data());
6635
6636 // One level that is used - only this level should affect completeness.
6637 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6638 texDataGreen.data());
6639
6640 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
6641 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
6642
6643 EXPECT_GL_NO_ERROR();
6644
6645 drawQuad(mProgram, "position", 0.5f);
6646
6647 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6648
6649 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6650
6651 // Switch the level that is being used to the cyan level 2.
6652 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 2);
6653 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 2);
6654
6655 EXPECT_GL_NO_ERROR();
6656
6657 drawQuad(mProgram, "position", 0.5f);
6658
6659 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6660 }
6661
6662 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
6663 // have images defined.
TEST_P(Texture2DArrayTestES3,DrawWithLevelsOutsideRangeUndefined)6664 TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeUndefined)
6665 {
6666 glActiveTexture(GL_TEXTURE0);
6667 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6668 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6669 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6670 texDataGreen.data());
6671 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6672 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6673 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
6674 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
6675
6676 EXPECT_GL_NO_ERROR();
6677
6678 drawQuad(mProgram, "position", 0.5f);
6679
6680 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6681 }
6682
6683 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
6684 // dimensions that don't fit the images inside the range.
6685 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DArrayTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)6686 TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
6687 {
6688 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
6689 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
6690
6691 glActiveTexture(GL_TEXTURE0);
6692 glBindTexture(GL_TEXTURE_3D, m2DArrayTexture);
6693 std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
6694 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6695 std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
6696
6697 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6698 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6699
6700 // Two levels that are initially unused.
6701 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6702 texDataRed.data());
6703 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6704 texDataCyan.data());
6705
6706 // One level that is used - only this level should affect completeness.
6707 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6708 texDataGreen.data());
6709
6710 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
6711 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
6712
6713 EXPECT_GL_NO_ERROR();
6714
6715 drawQuad(mProgram, "position", 0.5f);
6716
6717 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6718
6719 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6720
6721 // Switch the level that is being used to the cyan level 2.
6722 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 2);
6723 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 2);
6724
6725 EXPECT_GL_NO_ERROR();
6726
6727 drawQuad(mProgram, "position", 0.5f);
6728
6729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6730 }
6731
6732 // Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
6733 // in the Vulkan backend where the old higher-layer-count data upload was not removed.
TEST_P(Texture2DArrayTestES3,TextureArrayRedefineThenUse)6734 TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse)
6735 {
6736 int px = getWindowWidth() / 2;
6737 int py = getWindowHeight() / 2;
6738
6739 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6740
6741 // Fill the whole texture with red, then redefine it and fill with green
6742 std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
6743 std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
6744 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6745 pixelsRed.data());
6746 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6747 pixelsGreen.data());
6748
6749 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6750 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6751 EXPECT_GL_NO_ERROR();
6752
6753 glUseProgram(mProgram);
6754 EXPECT_GL_NO_ERROR();
6755
6756 // Draw the first slice
6757 glUniform1i(mTextureArraySliceUniformLocation, 0);
6758 drawQuad(mProgram, "position", 0.5f);
6759 EXPECT_GL_NO_ERROR();
6760 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6761
6762 // Draw the second slice
6763 glUniform1i(mTextureArraySliceUniformLocation, 1);
6764 drawQuad(mProgram, "position", 0.5f);
6765 EXPECT_GL_NO_ERROR();
6766 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6767 }
6768
6769 // Create a 2D array texture and update layers with data and test that pruning
6770 // of superseded updates works as expected.
TEST_P(Texture2DArrayTestES3,TextureArrayPruneSupersededUpdates)6771 TEST_P(Texture2DArrayTestES3, TextureArrayPruneSupersededUpdates)
6772 {
6773 constexpr uint32_t kTexWidth = 256;
6774 constexpr uint32_t kTexHeight = 256;
6775 constexpr uint32_t kTexLayers = 3;
6776
6777 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6778 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6779 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6780 EXPECT_GL_NO_ERROR();
6781
6782 // Initialize entire texture.
6783 constexpr GLColor kInitialExpectedColor = GLColor(201u, 201u, 201u, 201u);
6784 std::vector<GLColor> initialData(kTexWidth * kTexHeight * kTexLayers, kInitialExpectedColor);
6785 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kTexWidth, kTexHeight, kTexLayers, 0, GL_RGBA,
6786 GL_UNSIGNED_BYTE, initialData.data());
6787
6788 // Upate different layers with different colors, these together should supersed
6789 // the entire init update
6790 constexpr GLColor kExpectedColor[] = {GLColor(32u, 32u, 32u, 32u), GLColor(64u, 64u, 64u, 64u),
6791 GLColor(128u, 128u, 128u, 128u)};
6792 std::vector<GLColor> supersedingData[] = {
6793 std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[0]),
6794 std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[1]),
6795 std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[2])};
6796
6797 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kTexWidth, kTexHeight, 1, GL_RGBA,
6798 GL_UNSIGNED_BYTE, supersedingData[0].data());
6799 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, kTexWidth, kTexHeight, 1, GL_RGBA,
6800 GL_UNSIGNED_BYTE, supersedingData[1].data());
6801 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, kTexWidth, kTexHeight, 1, GL_RGBA,
6802 GL_UNSIGNED_BYTE, supersedingData[2].data());
6803
6804 glUseProgram(mProgram);
6805 EXPECT_GL_NO_ERROR();
6806
6807 // Draw layer 0
6808 glUniform1i(mTextureArraySliceUniformLocation, 0);
6809 drawQuad(mProgram, "position", 0.5f);
6810 EXPECT_GL_NO_ERROR();
6811 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[0]);
6812
6813 // Draw layer 1
6814 glUniform1i(mTextureArraySliceUniformLocation, 1);
6815 drawQuad(mProgram, "position", 0.5f);
6816 EXPECT_GL_NO_ERROR();
6817 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[1]);
6818
6819 // Draw layer 2
6820 glUniform1i(mTextureArraySliceUniformLocation, 2);
6821 drawQuad(mProgram, "position", 0.5f);
6822 EXPECT_GL_NO_ERROR();
6823 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[2]);
6824 }
6825
6826 // Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
6827 // the Vulkan backend where the old higher-layer-count data upload was not removed.
TEST_P(Texture2DArrayTestES3,TextureArrayUseThenRedefineThenUse)6828 TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse)
6829 {
6830 int px = getWindowWidth() / 2;
6831 int py = getWindowHeight() / 2;
6832
6833 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6834
6835 // Fill the whole texture with red.
6836 std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
6837 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6838 pixelsRed.data());
6839
6840 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6841 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6842 EXPECT_GL_NO_ERROR();
6843
6844 glUseProgram(mProgram);
6845 EXPECT_GL_NO_ERROR();
6846
6847 // Draw the first slice
6848 glUniform1i(mTextureArraySliceUniformLocation, 0);
6849 drawQuad(mProgram, "position", 0.5f);
6850 EXPECT_GL_NO_ERROR();
6851 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
6852
6853 // Draw the fourth slice
6854 glUniform1i(mTextureArraySliceUniformLocation, 3);
6855 drawQuad(mProgram, "position", 0.5f);
6856 EXPECT_GL_NO_ERROR();
6857 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
6858
6859 // Redefine the image and fill with green
6860 std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
6861 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6862 pixelsGreen.data());
6863
6864 // Draw the first slice
6865 glUniform1i(mTextureArraySliceUniformLocation, 0);
6866 drawQuad(mProgram, "position", 0.5f);
6867 EXPECT_GL_NO_ERROR();
6868 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6869
6870 // Draw the second slice
6871 glUniform1i(mTextureArraySliceUniformLocation, 1);
6872 drawQuad(mProgram, "position", 0.5f);
6873 EXPECT_GL_NO_ERROR();
6874 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6875 }
6876
6877 // Create a 2D array texture, use it, then redefine one level without changing dimensions.
TEST_P(Texture2DArrayTestES3,RedefineLevelData)6878 TEST_P(Texture2DArrayTestES3, RedefineLevelData)
6879 {
6880 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6881
6882 // Fill both levels with red
6883 std::vector<GLColor> pixelsRed(2 * 2 * 1, GLColor::red);
6884 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6885 pixelsRed.data());
6886 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6887 pixelsRed.data());
6888 ASSERT_GL_NO_ERROR();
6889
6890 // Check that both levels are red
6891 GLFramebuffer fbo;
6892 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6893 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
6894 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6895 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0);
6896 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6897
6898 // Redefine level 1 with green
6899 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6900 &GLColor::green);
6901 ASSERT_GL_NO_ERROR();
6902
6903 // Check that level 0 is red and level 1 is green
6904 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
6905 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6906 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0);
6907 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6908 }
6909
6910 // Create a 3D texture, use it, then redefine one level without changing dimensions.
TEST_P(Texture3DTestES3,RedefineLevelData)6911 TEST_P(Texture3DTestES3, RedefineLevelData)
6912 {
6913 glBindTexture(GL_TEXTURE_3D, mTexture3D);
6914
6915 // Fill both levels with red
6916 std::vector<GLColor> pixelsRed(2 * 2 * 1, GLColor::red);
6917 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6918 pixelsRed.data());
6919 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6920 pixelsRed.data());
6921 ASSERT_GL_NO_ERROR();
6922
6923 // Check that both levels are red
6924 GLFramebuffer fbo;
6925 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6926 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0);
6927 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6928 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0);
6929 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6930
6931 // Redefine level 1 with green
6932 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6933 &GLColor::green);
6934 ASSERT_GL_NO_ERROR();
6935
6936 // Check that level 0 is red and level 1 is green
6937 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0);
6938 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6939 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0);
6940 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6941 }
6942
6943 // Test that texture completeness is updated if texture max level changes.
6944 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureCompletenessChangesWithMaxLevel)6945 TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
6946 {
6947 glActiveTexture(GL_TEXTURE0);
6948 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6949 std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
6950
6951 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6952 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6953
6954 // A level that is initially unused.
6955 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6956 texDataGreen.data());
6957
6958 // One level that is initially used - only this level should affect completeness.
6959 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6960 texDataGreen.data());
6961
6962 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6963 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6964
6965 EXPECT_GL_NO_ERROR();
6966
6967 drawQuad(mProgram, "position", 0.5f);
6968
6969 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6970
6971 // Switch the max level to level 1. The levels within the used range now have inconsistent
6972 // dimensions and the texture should be incomplete.
6973 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6974
6975 EXPECT_GL_NO_ERROR();
6976
6977 drawQuad(mProgram, "position", 0.5f);
6978
6979 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6980 }
6981
6982 // Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly
6983 // keep the staged clear. http://anglebug.com/345532371
TEST_P(Texture2DArrayTestES3,ClearThenTexSubImageWithOverlappingLayersThenRead)6984 TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenRead)
6985 {
6986 constexpr GLsizei kTexWidth = 128;
6987 constexpr GLsizei kTexHeight = 128;
6988 constexpr GLsizei kTexDepth = 6;
6989 // Create a single leveled texture with 6 layers
6990 GLTexture tex;
6991 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
6992 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth);
6993
6994 // Stage clear to red on all layers
6995 GLFramebuffer drawFBO;
6996 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
6997 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
6998 for (GLsizei layer = 0; layer < kTexDepth; layer++)
6999 {
7000 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
7001 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
7002 glClear(GL_COLOR_BUFFER_BIT);
7003 }
7004
7005 // TexSubImage with green color on half of the image of layer 2,3,4
7006 std::vector<GLColor> updateData((kTexWidth / 2) * kTexHeight * 3, GLColor::green);
7007 GLsizei layerStart = 2;
7008 GLsizei layerCount = 3;
7009 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerStart, kTexWidth / 2, kTexHeight, layerCount,
7010 GL_RGBA, GL_UNSIGNED_BYTE, updateData.data());
7011
7012 // Now read out layer 2/3/4
7013 GLFramebuffer readFBO;
7014 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
7015 for (GLsizei layer = layerStart; layer < layerStart + layerCount; layer++)
7016 {
7017 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
7018 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
7019 EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::green.R, GLColor::green.G,
7020 GLColor::green.B, GLColor::green.A);
7021 EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::red.R, GLColor::red.G,
7022 GLColor::red.B, GLColor::red.A);
7023 }
7024 ASSERT_GL_NO_ERROR();
7025 }
7026
7027 // Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly
7028 // keep the staged clear. http://anglebug.com/345532371
TEST_P(Texture2DArrayTestES3,ClearThenTexSubImageWithOverlappingLayersThenDrawAndRead)7029 TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenDrawAndRead)
7030 {
7031 constexpr GLsizei kTexWidth = 128;
7032 constexpr GLsizei kTexHeight = 128;
7033 constexpr GLsizei kTexDepth = 6;
7034 // Create a single leveled texture with 6 layers
7035 GLTexture tex;
7036 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
7037 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth);
7038
7039 // Stage clear to red on all layers
7040 GLFramebuffer drawFBO;
7041 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
7042 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7043 for (GLsizei layer = 0; layer < kTexDepth; layer++)
7044 {
7045 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
7046 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
7047 glClear(GL_COLOR_BUFFER_BIT);
7048 }
7049
7050 // TexSubImage with green color on half of the image of layer 2,3,4
7051 std::vector<GLColor> updateData((kTexWidth / 2) * kTexHeight * 3, GLColor::green);
7052 GLsizei layerStart = 2;
7053 GLsizei layerCount = 3;
7054 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerStart, kTexWidth / 2, kTexHeight, layerCount,
7055 GL_RGBA, GL_UNSIGNED_BYTE, updateData.data());
7056
7057 // Now Draw to fbo on layerStart with blue color
7058 GLsizei blueQuadLayer = 2;
7059 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, blueQuadLayer);
7060 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
7061 glEnable(GL_BLEND);
7062 glBlendFunc(GL_ONE, GL_ONE);
7063 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Blue());
7064 glUseProgram(blueProgram);
7065 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f);
7066
7067 // Now read out layer 2/3/4
7068 GLFramebuffer readFBO;
7069 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
7070 for (GLsizei layer = layerStart; layer < layerStart + layerCount; layer++)
7071 {
7072 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
7073 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
7074 if (layer == blueQuadLayer)
7075 {
7076 // green + blue = cyan
7077 EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::cyan.R, GLColor::cyan.G,
7078 GLColor::cyan.B, GLColor::cyan.A);
7079 // red + blue = magenta
7080 EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::magenta.R,
7081 GLColor::magenta.G, GLColor::magenta.B, GLColor::magenta.A);
7082 }
7083 else
7084 {
7085 EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::green.R, GLColor::green.G,
7086 GLColor::green.B, GLColor::green.A);
7087 EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::red.R, GLColor::red.G,
7088 GLColor::red.B, GLColor::red.A);
7089 }
7090 }
7091 ASSERT_GL_NO_ERROR();
7092 }
7093
7094 // Test that compressed textures ignore the pixel unpack state.
7095 // (https://crbug.org/1267496)
TEST_P(Texture3DTestES3,PixelUnpackStateTexImage)7096 TEST_P(Texture3DTestES3, PixelUnpackStateTexImage)
7097 {
7098 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
7099 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
7100
7101 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
7102 glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
7103
7104 uint8_t data[64] = {0};
7105 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
7106 data);
7107 EXPECT_GL_NO_ERROR();
7108 }
7109
7110 // Test that compressed textures ignore the pixel unpack state.
7111 // (https://crbug.org/1267496)
TEST_P(Texture3DTestES3,PixelUnpackStateTexSubImage)7112 TEST_P(Texture3DTestES3, PixelUnpackStateTexSubImage)
7113 {
7114 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
7115 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
7116
7117 glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
7118
7119 uint8_t data[64] = {0};
7120 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
7121 data);
7122 EXPECT_GL_NO_ERROR();
7123
7124 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
7125
7126 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 4,
7127 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, data);
7128 EXPECT_GL_NO_ERROR();
7129 }
7130
7131 // Test that 3D texture completeness is updated if texture max level changes.
7132 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture3DTestES3,Texture3DCompletenessChangesWithMaxLevel)7133 TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel)
7134 {
7135 glActiveTexture(GL_TEXTURE0);
7136 glBindTexture(GL_TEXTURE_3D, mTexture3D);
7137 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
7138
7139 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7140 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
7141
7142 // A level that is initially unused.
7143 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7144 texDataGreen.data());
7145
7146 // One level that is initially used - only this level should affect completeness.
7147 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7148 texDataGreen.data());
7149
7150 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
7151 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
7152
7153 EXPECT_GL_NO_ERROR();
7154
7155 drawQuad(mProgram, "position", 0.5f);
7156
7157 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7158
7159 // Switch the max level to level 1. The levels within the used range now have inconsistent
7160 // dimensions and the texture should be incomplete.
7161 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
7162
7163 EXPECT_GL_NO_ERROR();
7164
7165 drawQuad(mProgram, "position", 0.5f);
7166
7167 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7168 }
7169
7170 // Test that texture completeness is updated if texture base level changes.
7171 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureCompletenessChangesWithBaseLevel)7172 TEST_P(Texture2DTestES3, TextureCompletenessChangesWithBaseLevel)
7173 {
7174 glActiveTexture(GL_TEXTURE0);
7175 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7176 std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
7177
7178 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7179 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
7180
7181 // Two levels that are initially unused.
7182 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7183 texDataGreen.data());
7184 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7185 texDataGreen.data());
7186
7187 // One level that is initially used - only this level should affect completeness.
7188 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7189 texDataGreen.data());
7190
7191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
7192 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
7193
7194 EXPECT_GL_NO_ERROR();
7195
7196 drawQuad(mProgram, "position", 0.5f);
7197
7198 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7199
7200 // Switch the base level to level 1. The levels within the used range now have inconsistent
7201 // dimensions and the texture should be incomplete.
7202 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
7203
7204 EXPECT_GL_NO_ERROR();
7205
7206 drawQuad(mProgram, "position", 0.5f);
7207
7208 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7209 }
7210
7211 // Test that texture is not complete if base level is greater than max level.
7212 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureBaseLevelGreaterThanMaxLevel)7213 TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMaxLevel)
7214 {
7215 glActiveTexture(GL_TEXTURE0);
7216 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7217
7218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7220
7221 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
7222
7223 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
7224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7225
7226 EXPECT_GL_NO_ERROR();
7227
7228 drawQuad(mProgram, "position", 0.5f);
7229
7230 // Texture should be incomplete.
7231 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7232 }
7233
7234 // Test that immutable texture base level and max level are clamped.
7235 // GLES 3.0.4 section 3.8.10 subsection Mipmapping
TEST_P(Texture2DTestES3,ImmutableTextureBaseLevelOutOfRange)7236 TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange)
7237 {
7238 glActiveTexture(GL_TEXTURE0);
7239 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7240
7241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7243
7244 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
7245
7246 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
7247
7248 // For immutable-format textures, base level should be clamped to [0, levels - 1], and max level
7249 // should be clamped to [base_level, levels - 1].
7250 // GLES 3.0.4 section 3.8.10 subsection Mipmapping
7251 // In the case of this test, those rules make the effective base level and max level 0.
7252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
7253 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
7254
7255 EXPECT_GL_NO_ERROR();
7256
7257 drawQuad(mProgram, "position", 0.5f);
7258
7259 // Texture should be complete.
7260 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7261 }
7262
7263 // Test that changing base level works when it affects the format of the texture.
TEST_P(Texture2DTestES3,TextureFormatChangesWithBaseLevel)7264 TEST_P(Texture2DTestES3, TextureFormatChangesWithBaseLevel)
7265 {
7266 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
7267 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
7268
7269 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL());
7270
7271 // Observed incorrect rendering on AMD OpenGL.
7272 ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
7273
7274 glActiveTexture(GL_TEXTURE0);
7275 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7276 std::vector<GLColor> texDataCyan(4u * 4u, GLColor::cyan);
7277 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
7278
7279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
7281
7282 // RGBA8 level that's initially unused.
7283 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7284 texDataCyan.data());
7285
7286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
7287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
7288
7289 // RG8 level that's initially used, with consistent dimensions with level 0 but a different
7290 // format. It reads green channel data from the green and alpha channels of texDataGreen
7291 // (this is a bit hacky but works).
7292 glTexImage2D(GL_TEXTURE_2D, 1, GL_RG8, 2, 2, 0, GL_RG, GL_UNSIGNED_BYTE, texDataGreen.data());
7293
7294 EXPECT_GL_NO_ERROR();
7295
7296 drawQuad(mProgram, "position", 0.5f);
7297
7298 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7299
7300 // Switch the texture to use the cyan level 0 with the RGBA format.
7301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7303
7304 EXPECT_GL_NO_ERROR();
7305
7306 drawQuad(mProgram, "position", 0.5f);
7307
7308 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7309 }
7310
7311 // Test that setting a texture image works when base level is out of range.
TEST_P(Texture2DTestES3,SetImageWhenBaseLevelOutOfRange)7312 TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange)
7313 {
7314 glActiveTexture(GL_TEXTURE0);
7315 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7316
7317 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7319
7320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
7321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
7322
7323 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
7324
7325 EXPECT_GL_NO_ERROR();
7326
7327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7328
7329 drawQuad(mProgram, "position", 0.5f);
7330
7331 // Texture should be complete.
7332 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7333 }
7334
7335 // In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG
7336 // RBA->RGBA8, with 1.0 in the alpha channel. This test covers a bug where redefining array textures
7337 // with these formats does not work as expected.
TEST_P(Texture2DArrayTestES3,RedefineInittableArray)7338 TEST_P(Texture2DArrayTestES3, RedefineInittableArray)
7339 {
7340 std::vector<GLubyte> pixelData;
7341 for (size_t count = 0; count < 5000; count++)
7342 {
7343 pixelData.push_back(0u);
7344 pixelData.push_back(255u);
7345 pixelData.push_back(0u);
7346 }
7347
7348 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
7349 glUseProgram(mProgram);
7350 glUniform1i(mTextureArrayLocation, 0);
7351
7352 // The first draw worked correctly.
7353 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
7354 &pixelData[0]);
7355
7356 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7357 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7358 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
7359 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
7360 drawQuad(mProgram, "position", 1.0f);
7361 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7362
7363 // The dimension of the respecification must match the original exactly to trigger the bug.
7364 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
7365 &pixelData[0]);
7366 drawQuad(mProgram, "position", 1.0f);
7367 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7368
7369 ASSERT_GL_NO_ERROR();
7370 }
7371
7372 // Test shadow sampler and regular non-shadow sampler coexisting in the same shader.
7373 // This test is needed especially to confirm that sampler registers get assigned correctly on
7374 // the HLSL backend even when there's a mix of different HLSL sampler and texture types.
TEST_P(ShadowSamplerPlusSampler3DTestES3,ShadowSamplerPlusSampler3DDraw)7375 TEST_P(ShadowSamplerPlusSampler3DTestES3, ShadowSamplerPlusSampler3DDraw)
7376 {
7377 glActiveTexture(GL_TEXTURE0);
7378 glBindTexture(GL_TEXTURE_3D, mTexture3D);
7379 GLubyte texData[4];
7380 texData[0] = 0;
7381 texData[1] = 60;
7382 texData[2] = 0;
7383 texData[3] = 255;
7384 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7385
7386 glActiveTexture(GL_TEXTURE1);
7387 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
7388 GLfloat depthTexData[1];
7389 depthTexData[0] = 0.5f;
7390 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
7391 depthTexData);
7392
7393 glUseProgram(mProgram);
7394 glUniform1f(mDepthRefUniformLocation, 0.3f);
7395 glUniform1i(mTexture3DUniformLocation, 0);
7396 glUniform1i(mTextureShadowUniformLocation, 1);
7397
7398 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
7399 drawQuad(mProgram, "position", 0.5f);
7400 EXPECT_GL_NO_ERROR();
7401 // The shader writes 0.5 * <comparison result (1.0)> + <texture color>
7402 EXPECT_PIXEL_NEAR(0, 0, 128, 188, 128, 255, 2);
7403
7404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);
7405 drawQuad(mProgram, "position", 0.5f);
7406 EXPECT_GL_NO_ERROR();
7407 // The shader writes 0.5 * <comparison result (0.0)> + <texture color>
7408 EXPECT_PIXEL_NEAR(0, 0, 0, 60, 0, 255, 2);
7409 }
7410
7411 // Test multiple different sampler types in the same shader.
7412 // This test makes sure that even if sampler / texture registers get grouped together based on type
7413 // or otherwise get shuffled around in the HLSL backend of the shader translator, the D3D renderer
7414 // still has the right register index information for each ESSL sampler.
7415 // The tested ESSL samplers have the following types in D3D11 HLSL:
7416 // sampler2D: Texture2D + SamplerState
7417 // samplerCube: TextureCube + SamplerState
7418 // sampler2DShadow: Texture2D + SamplerComparisonState
7419 // samplerCubeShadow: TextureCube + SamplerComparisonState
TEST_P(SamplerTypeMixTestES3,SamplerTypeMixDraw)7420 TEST_P(SamplerTypeMixTestES3, SamplerTypeMixDraw)
7421 {
7422 glActiveTexture(GL_TEXTURE0);
7423 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7424 GLubyte texData[4];
7425 texData[0] = 0;
7426 texData[1] = 0;
7427 texData[2] = 120;
7428 texData[3] = 255;
7429 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7430
7431 glActiveTexture(GL_TEXTURE1);
7432 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
7433 texData[0] = 0;
7434 texData[1] = 90;
7435 texData[2] = 0;
7436 texData[3] = 255;
7437 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
7438 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
7439 texData);
7440
7441 glActiveTexture(GL_TEXTURE2);
7442 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
7443 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
7444 GLfloat depthTexData[1];
7445 depthTexData[0] = 0.5f;
7446 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
7447 depthTexData);
7448
7449 glActiveTexture(GL_TEXTURE3);
7450 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
7451 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
7452 depthTexData[0] = 0.2f;
7453 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT32F, 1, 1);
7454 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT,
7455 depthTexData);
7456
7457 // http://anglebug.com/42262588: TODO: Add a DS texture case
7458
7459 EXPECT_GL_NO_ERROR();
7460
7461 glUseProgram(mProgram);
7462 glUniform1f(mDepthRefUniformLocation, 0.3f);
7463 glUniform1i(mTexture2DUniformLocation, 0);
7464 glUniform1i(mTextureCubeUniformLocation, 1);
7465 glUniform1i(mTexture2DShadowUniformLocation, 2);
7466 glUniform1i(mTextureCubeShadowUniformLocation, 3);
7467
7468 drawQuad(mProgram, "position", 0.5f);
7469 EXPECT_GL_NO_ERROR();
7470 // The shader writes:
7471 // <texture 2d color> +
7472 // <cube map color> +
7473 // 0.25 * <comparison result (1.0)> +
7474 // 0.125 * <comparison result (0.0)>
7475 EXPECT_PIXEL_NEAR(0, 0, 64, 154, 184, 255, 2);
7476 }
7477
7478 // Test different base levels on textures accessed through the same sampler array.
7479 // Calling textureSize() on the samplers hits the D3D sampler metadata workaround.
TEST_P(TextureSizeTextureArrayTest,BaseLevelVariesInTextureArray)7480 TEST_P(TextureSizeTextureArrayTest, BaseLevelVariesInTextureArray)
7481 {
7482 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D11());
7483
7484 // http://anglebug.com/42263017
7485 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsWindows() && IsD3D11());
7486
7487 glActiveTexture(GL_TEXTURE0);
7488 glBindTexture(GL_TEXTURE_2D, mTexture2DA);
7489 GLsizei size = 64;
7490 for (GLint level = 0; level < 7; ++level)
7491 {
7492 ASSERT_LT(0, size);
7493 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7494 nullptr);
7495 size = size / 2;
7496 }
7497 ASSERT_EQ(0, size);
7498 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
7499
7500 glActiveTexture(GL_TEXTURE1);
7501 glBindTexture(GL_TEXTURE_2D, mTexture2DB);
7502 size = 128;
7503 for (GLint level = 0; level < 8; ++level)
7504 {
7505 ASSERT_LT(0, size);
7506 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7507 nullptr);
7508 size = size / 2;
7509 }
7510 ASSERT_EQ(0, size);
7511 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 3);
7512 EXPECT_GL_NO_ERROR();
7513
7514 glUseProgram(mProgram);
7515 glUniform1i(mTexture0Location, 0);
7516 glUniform1i(mTexture1Location, 1);
7517
7518 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
7519 EXPECT_GL_NO_ERROR();
7520 // Red channel: width of level 1 of texture A: 32.
7521 // Green channel: width of level 3 of texture B: 16.
7522 EXPECT_PIXEL_NEAR(0, 0, 32, 16, 0, 255, 2);
7523 }
7524
7525 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7526 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBImplicitAlpha1)7527 TEST_P(Texture2DTestES3, TextureRGBImplicitAlpha1)
7528 {
7529 glActiveTexture(GL_TEXTURE0);
7530 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7531 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
7532 EXPECT_GL_NO_ERROR();
7533
7534 drawQuad(mProgram, "position", 0.5f);
7535
7536 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7537 }
7538
7539 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7540 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBXImplicitAlpha1)7541 TEST_P(Texture2DTestES3, TextureRGBXImplicitAlpha1)
7542 {
7543 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
7544
7545 GLTexture texture2D;
7546 glBindTexture(GL_TEXTURE_2D, texture2D);
7547 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBX8_ANGLE, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
7548 glActiveTexture(GL_TEXTURE0);
7549 EXPECT_GL_NO_ERROR();
7550
7551 drawQuad(mProgram, "position", 0.5f);
7552
7553 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7554 }
7555
7556 // Test that data upload to RGBX works.
TEST_P(Texture2DTestES3,TextureRGBXUpload)7557 TEST_P(Texture2DTestES3, TextureRGBXUpload)
7558 {
7559 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
7560
7561 const size_t kWidth = 32;
7562 const size_t kHeight = 32;
7563
7564 GLTexture color;
7565 glBindTexture(GL_TEXTURE_2D, color);
7566 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
7567
7568 GLFramebuffer fbo;
7569 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7570 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
7571 ASSERT_GL_NO_ERROR();
7572 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7573
7574 // Upload data to an RGBX texture
7575 const GLColorRGB kColor(100, 200, 55);
7576 std::vector<GLColorRGB> data(kWidth * kHeight, kColor);
7577
7578 GLTexture texture;
7579 glBindTexture(GL_TEXTURE_2D, texture);
7580 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight);
7581 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7582 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7583 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, data.data());
7584 ASSERT_GL_NO_ERROR();
7585
7586 // Sample from the texture
7587 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7588 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
7589
7590 const GLColor kExpect(kColor.R, kColor.G, kColor.B, 255);
7591 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
7592 EXPECT_PIXEL_COLOR_NEAR(0, 1, kExpect, 1);
7593 EXPECT_PIXEL_COLOR_NEAR(1, 0, kExpect, 1);
7594 EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, kExpect, 1);
7595 EXPECT_PIXEL_COLOR_NEAR(0, kHeight - 1, kExpect, 1);
7596 EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, kExpect, 1);
7597 EXPECT_PIXEL_COLOR_NEAR(kWidth / 2, kHeight / 2, kExpect, 1);
7598 ASSERT_GL_NO_ERROR();
7599 }
7600
7601 // Test that data download from RGBX works.
TEST_P(Texture2DTestES3,TextureRGBXDownload)7602 TEST_P(Texture2DTestES3, TextureRGBXDownload)
7603 {
7604 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
7605
7606 const size_t kWidth = 32;
7607 const size_t kHeight = 32;
7608
7609 GLTexture color;
7610 glBindTexture(GL_TEXTURE_2D, color);
7611 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight);
7612
7613 GLFramebuffer fbo;
7614 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7615 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
7616 ASSERT_GL_NO_ERROR();
7617 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7618
7619 // Render to the RGBX texture
7620 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7621 glUseProgram(program);
7622 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7623 ASSERT_NE(colorLoc, -1);
7624
7625 glUniform4f(colorLoc, 0.3f, 0.6f, 0.8f, 0.2f);
7626 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
7627 ASSERT_GL_NO_ERROR();
7628
7629 // Readback as RGBX.
7630 std::vector<GLColor> readback(kWidth * kHeight);
7631 glReadPixels(0, 0, kWidth, kHeight, GL_RGBX8_ANGLE, GL_UNSIGNED_BYTE, readback.data());
7632 ASSERT_GL_NO_ERROR();
7633
7634 const GLColor kExpect(76, // 0.3f * 255
7635 153, // 0.6f * 255
7636 204, // 0.8f * 255
7637 255);
7638
7639 for (size_t y = 0; y < kHeight; y++)
7640 {
7641 for (size_t x = 0; x < kWidth; x++)
7642 {
7643 const GLColor actualColor = readback[y * kWidth + x];
7644
7645 EXPECT_NEAR(actualColor.R, kExpect.R, 1) << x << "x" << y;
7646 EXPECT_NEAR(actualColor.G, kExpect.G, 1) << x << "x" << y;
7647 EXPECT_NEAR(actualColor.B, kExpect.B, 1) << x << "x" << y;
7648 EXPECT_EQ(actualColor.A, kExpect.A) << x << "x" << y;
7649 }
7650 }
7651 ASSERT_GL_NO_ERROR();
7652 }
7653
7654 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7655 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminanceImplicitAlpha1)7656 TEST_P(Texture2DTest, TextureLuminanceImplicitAlpha1)
7657 {
7658 setUpProgram();
7659
7660 glActiveTexture(GL_TEXTURE0);
7661 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7662 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
7663 EXPECT_GL_NO_ERROR();
7664
7665 drawQuad(mProgram, "position", 0.5f);
7666
7667 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7668 }
7669
7670 // Validate that every component of the pixel will be equal to the luminance value we've set
7671 // and that the alpha channel will be 1 (or 255 to be exact).
TEST_P(Texture2DTest,TextureLuminanceRGBSame)7672 TEST_P(Texture2DTest, TextureLuminanceRGBSame)
7673 {
7674 setUpProgram();
7675
7676 glActiveTexture(GL_TEXTURE0);
7677 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7678 uint8_t pixel = 50;
7679 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pixel);
7680 EXPECT_GL_NO_ERROR();
7681
7682 drawQuad(mProgram, "position", 0.5f);
7683
7684 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel, pixel, pixel, 255));
7685 }
7686
7687 // Validate that every component of the pixel will be equal to the luminance value we've set
7688 // and that the alpha channel will be the second component.
TEST_P(Texture2DTest,TextureLuminanceAlphaRGBSame)7689 TEST_P(Texture2DTest, TextureLuminanceAlphaRGBSame)
7690 {
7691 setUpProgram();
7692
7693 glActiveTexture(GL_TEXTURE0);
7694 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7695 uint8_t pixel[] = {50, 25};
7696 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 1, 1, 0, GL_LUMINANCE_ALPHA,
7697 GL_UNSIGNED_BYTE, pixel);
7698 EXPECT_GL_NO_ERROR();
7699
7700 drawQuad(mProgram, "position", 0.5f);
7701
7702 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel[0], pixel[0], pixel[0], pixel[1]));
7703 }
7704
7705 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7706 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminance32ImplicitAlpha1)7707 TEST_P(Texture2DTest, TextureLuminance32ImplicitAlpha1)
7708 {
7709 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
7710 ANGLE_SKIP_TEST_IF(IsD3D9());
7711 ANGLE_SKIP_TEST_IF(IsVulkan());
7712
7713 setUpProgram();
7714
7715 glActiveTexture(GL_TEXTURE0);
7716 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7717 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_FLOAT, nullptr);
7718 EXPECT_GL_NO_ERROR();
7719
7720 drawQuad(mProgram, "position", 0.5f);
7721
7722 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7723 }
7724
7725 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7726 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminance16ImplicitAlpha1)7727 TEST_P(Texture2DTest, TextureLuminance16ImplicitAlpha1)
7728 {
7729 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
7730 ANGLE_SKIP_TEST_IF(IsD3D9());
7731 ANGLE_SKIP_TEST_IF(IsVulkan());
7732 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/42260416 is fixed
7733 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
7734
7735 setUpProgram();
7736
7737 glActiveTexture(GL_TEXTURE0);
7738 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7739 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, nullptr);
7740 EXPECT_GL_NO_ERROR();
7741
7742 drawQuad(mProgram, "position", 0.5f);
7743
7744 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7745 }
7746
7747 // Test that CopyTexImage2D does not trigger assertion after CompressedTexImage2D.
7748 // https://crbug.com/1216276
TEST_P(Texture2DTest,CopyAfterCompressed)7749 TEST_P(Texture2DTest, CopyAfterCompressed)
7750 {
7751 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
7752
7753 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7754 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8, nullptr);
7755 EXPECT_GL_NO_ERROR();
7756
7757 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 0, 0, 4, 4, 0);
7758 EXPECT_GL_NO_ERROR();
7759 }
7760
7761 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7762 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB8UIImplicitAlpha1)7763 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB8UIImplicitAlpha1)
7764 {
7765 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7766
7767 glActiveTexture(GL_TEXTURE0);
7768 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7769 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, nullptr);
7770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7771 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7772 EXPECT_GL_NO_ERROR();
7773
7774 drawQuad(mProgram, "position", 0.5f);
7775
7776 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7777 }
7778
7779 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7780 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB8IImplicitAlpha1)7781 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB8IImplicitAlpha1)
7782 {
7783 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7784
7785 glActiveTexture(GL_TEXTURE0);
7786 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7787
7788 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8I, 1, 1, 0, GL_RGB_INTEGER, GL_BYTE, nullptr);
7789 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7790 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7791 EXPECT_GL_NO_ERROR();
7792
7793 drawQuad(mProgram, "position", 0.5f);
7794
7795 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7796 }
7797
7798 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7799 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB16UIImplicitAlpha1)7800 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB16UIImplicitAlpha1)
7801 {
7802 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7803
7804 glActiveTexture(GL_TEXTURE0);
7805 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7806 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, nullptr);
7807 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7808 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7809 EXPECT_GL_NO_ERROR();
7810
7811 drawQuad(mProgram, "position", 0.5f);
7812
7813 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7814 }
7815
7816 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7817 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB16IImplicitAlpha1)7818 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB16IImplicitAlpha1)
7819 {
7820 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7821
7822 glActiveTexture(GL_TEXTURE0);
7823 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7824 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16I, 1, 1, 0, GL_RGB_INTEGER, GL_SHORT, nullptr);
7825 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7826 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7827 EXPECT_GL_NO_ERROR();
7828
7829 drawQuad(mProgram, "position", 0.5f);
7830
7831 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7832 }
7833
7834 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7835 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB32UIImplicitAlpha1)7836 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB32UIImplicitAlpha1)
7837 {
7838 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7839
7840 glActiveTexture(GL_TEXTURE0);
7841 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7842 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, nullptr);
7843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7844 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7845 EXPECT_GL_NO_ERROR();
7846
7847 drawQuad(mProgram, "position", 0.5f);
7848
7849 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7850 }
7851
7852 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7853 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB32IImplicitAlpha1)7854 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB32IImplicitAlpha1)
7855 {
7856 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7857
7858 glActiveTexture(GL_TEXTURE0);
7859 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7860 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, nullptr);
7861 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7862 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7863 EXPECT_GL_NO_ERROR();
7864
7865 drawQuad(mProgram, "position", 0.5f);
7866
7867 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7868 }
7869
7870 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7871 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBSNORMImplicitAlpha1)7872 TEST_P(Texture2DTestES3, TextureRGBSNORMImplicitAlpha1)
7873 {
7874 glActiveTexture(GL_TEXTURE0);
7875 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7876 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8_SNORM, 1, 1, 0, GL_RGB, GL_BYTE, nullptr);
7877 EXPECT_GL_NO_ERROR();
7878
7879 drawQuad(mProgram, "position", 0.5f);
7880
7881 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7882 }
7883
7884 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7885 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGB9E5ImplicitAlpha1)7886 TEST_P(Texture2DTestES3, TextureRGB9E5ImplicitAlpha1)
7887 {
7888 glActiveTexture(GL_TEXTURE0);
7889 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7890 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV,
7891 nullptr);
7892 EXPECT_GL_NO_ERROR();
7893
7894 drawQuad(mProgram, "position", 0.5f);
7895
7896 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7897 }
7898
7899 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7900 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)7901 TEST_P(Texture2DTestES3, TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)
7902 {
7903 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497
7904 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
7905
7906 glActiveTexture(GL_TEXTURE0);
7907 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7908 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 1, 1, 0, 8, nullptr);
7909 EXPECT_GL_NO_ERROR();
7910
7911 drawQuad(mProgram, "position", 0.5f);
7912
7913 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7914 }
7915
7916 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7917 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)7918 TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)
7919 {
7920 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497
7921 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
7922
7923 glActiveTexture(GL_TEXTURE0);
7924 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7925 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, 1, 1, 0, 8, nullptr);
7926 EXPECT_GL_NO_ERROR();
7927
7928 drawQuad(mProgram, "position", 0.5f);
7929
7930 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7931 }
7932
7933 // ETC2 punchthrough alpha formats must be initialized to opaque black when emulated
7934 // http://anglebug.com/42265413
TEST_P(Texture2DTestES3RobustInit,TextureCOMPRESSEDRGB8A1ETC2)7935 TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDRGB8A1ETC2)
7936 {
7937 glActiveTexture(GL_TEXTURE0);
7938 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7939 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0,
7940 8, nullptr);
7941 EXPECT_GL_NO_ERROR();
7942
7943 drawQuad(mProgram, "position", 0.5f);
7944
7945 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7946 }
7947
7948 // ETC2 punchthrough alpha formats must be initialized to opaque black when emulated
7949 // http://anglebug.com/42265413
TEST_P(Texture2DTestES3RobustInit,TextureCOMPRESSEDSRGB8A1ETC2)7950 TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDSRGB8A1ETC2)
7951 {
7952 glActiveTexture(GL_TEXTURE0);
7953 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7954 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0,
7955 8, nullptr);
7956 EXPECT_GL_NO_ERROR();
7957
7958 drawQuad(mProgram, "position", 0.5f);
7959
7960 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7961 }
7962
7963 // Test that compressed textures ignore the pixel unpack state.
7964 // (https://crbug.org/1267496)
TEST_P(Texture2DTestES3,PixelUnpackStateTexImage)7965 TEST_P(Texture2DTestES3, PixelUnpackStateTexImage)
7966 {
7967 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
7968 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
7969
7970 glPixelStorei(GL_UNPACK_ROW_LENGTH, 9);
7971 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7972
7973 uint8_t data[64] = {0};
7974 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data);
7975 EXPECT_GL_NO_ERROR();
7976 }
7977
7978 // Test that compressed textures ignore the pixel unpack state.
7979 // (https://crbug.org/1267496)
TEST_P(Texture2DTestES3,PixelUnpackStateTexSubImage)7980 TEST_P(Texture2DTestES3, PixelUnpackStateTexSubImage)
7981 {
7982 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
7983 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
7984
7985 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7986
7987 uint8_t data[64] = {0};
7988 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data);
7989 EXPECT_GL_NO_ERROR();
7990
7991 glPixelStorei(GL_UNPACK_ROW_LENGTH, 9);
7992
7993 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64,
7994 data);
7995 EXPECT_GL_NO_ERROR();
7996 }
7997
7998 // Test for http://anglebug.com/42265405.
TEST_P(Texture2DTestES3,TextureRGBUpdateWithPBO)7999 TEST_P(Texture2DTestES3, TextureRGBUpdateWithPBO)
8000 {
8001 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
8002
8003 glViewport(0, 0, 16, 16);
8004
8005 GLTexture tex1;
8006 std::vector<GLColor> texDataRed(16u * 16u, GLColor::red);
8007 std::vector<GLColor> texDataGreen(16u * 16u, GLColor::green);
8008
8009 glBindTexture(GL_TEXTURE_2D, tex1);
8010 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
8011 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, texDataRed.data());
8012 ASSERT_GL_NO_ERROR();
8013
8014 GLBuffer pbo;
8015 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
8016 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, texDataGreen.data(), GL_STATIC_DRAW);
8017 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
8018 ASSERT_GL_NO_ERROR();
8019
8020 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8021 ASSERT_GL_NO_ERROR();
8022
8023 glBindTexture(GL_TEXTURE_2D, 0);
8024 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
8025 EXPECT_PIXEL_COLOR_EQ(4, 4, GLColor::green);
8026 }
8027
8028 // Copied from Texture2DTest::TexStorage
8029 // Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
8030 // default color.
TEST_P(Texture2DTestES31PPO,TexStorage)8031 TEST_P(Texture2DTestES31PPO, TexStorage)
8032 {
8033 ANGLE_SKIP_TEST_IF(!IsVulkan());
8034 ANGLE_SKIP_TEST_IF((getClientMajorVersion() < 3 && getClientMinorVersion() < 1) &&
8035 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
8036
8037 const char *vertexShaderSource = getVertexShaderSource();
8038 const char *fragmentShaderSource = getFragmentShaderSource();
8039
8040 bindProgramPipeline(vertexShaderSource, fragmentShaderSource);
8041 mTexture2DUniformLocation = glGetUniformLocation(mFragProg, getTextureUniformName());
8042
8043 int width = getWindowWidth();
8044 int height = getWindowHeight();
8045
8046 GLTexture tex2D;
8047 glActiveTexture(GL_TEXTURE0);
8048 glBindTexture(GL_TEXTURE_2D, tex2D);
8049
8050 // Fill with red
8051 std::vector<GLubyte> pixels(3 * 16 * 16);
8052 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
8053 {
8054 pixels[pixelId * 3 + 0] = 255;
8055 pixels[pixelId * 3 + 1] = 0;
8056 pixels[pixelId * 3 + 2] = 0;
8057 }
8058
8059 // ANGLE internally uses RGBA as the internal format for RGB images, therefore glTexStorage2DEXT
8060 // initializes the image to a default color to get a consistent alpha color. The data is kept in
8061 // a CPU-side image and the image is marked as dirty.
8062 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
8063
8064 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
8065 // glTexSubImage2D should take into account that the image is dirty.
8066 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
8067 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8068 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8069
8070 glActiveShaderProgram(mPipeline, mFragProg);
8071 glUniform1i(mTexture2DUniformLocation, 0);
8072
8073 std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
8074 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
8075
8076 EXPECT_GL_NO_ERROR();
8077 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
8078
8079 // Validate that the region of the texture without data has an alpha of 1.0
8080 angle::GLColor pixel = ReadColor(3 * width / 4, 3 * height / 4);
8081 EXPECT_EQ(255, pixel.A);
8082 }
8083
8084 // Copied from Texture2DTestES3::SingleTextureMultipleSamplers
8085 // Tests behaviour with a single texture and multiple sampler objects.
TEST_P(Texture2DTestES31PPO,SingleTextureMultipleSamplers)8086 TEST_P(Texture2DTestES31PPO, SingleTextureMultipleSamplers)
8087 {
8088 ANGLE_SKIP_TEST_IF(!IsVulkan());
8089
8090 const char *vertexShaderSource = getVertexShaderSource();
8091 const char *fragmentShaderSource = getFragmentShaderSource();
8092
8093 bindProgramPipeline(vertexShaderSource, fragmentShaderSource);
8094 mTexture2DUniformLocation = glGetUniformLocation(mFragProg, getTextureUniformName());
8095
8096 GLint maxTextureUnits = 0;
8097 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
8098 ANGLE_SKIP_TEST_IF(maxTextureUnits < 4);
8099
8100 constexpr int kSize = 16;
8101 std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
8102
8103 // Make a single-level texture, fill it with red.
8104 std::vector<GLColor> redColors(kSize * kSize, GLColor::red);
8105 GLTexture tex;
8106 glBindTexture(GL_TEXTURE_2D, tex);
8107 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8108 redColors.data());
8109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8111
8112 // Simple confidence check.
8113 bind2DTexturedQuadProgramPipeline();
8114 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
8115 ASSERT_GL_NO_ERROR();
8116 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8117
8118 // Bind texture to unit 1 with a sampler object making it incomplete.
8119 GLSampler sampler;
8120 glBindSampler(0, sampler);
8121 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
8122 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8123
8124 // Make a mipmap texture, fill it with blue.
8125 std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
8126 GLTexture mipmapTex;
8127 glBindTexture(GL_TEXTURE_2D, mipmapTex);
8128 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8129 blueColors.data());
8130 glGenerateMipmap(GL_TEXTURE_2D);
8131
8132 // Draw with the sampler, expect blue.
8133 draw2DTexturedQuad(0.5f, 1.0f, true);
8134 ASSERT_GL_NO_ERROR();
8135 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
8136
8137 // Simple multitexturing program.
8138 constexpr char kVS[] =
8139 "#version 310 es\n"
8140 "precision mediump float;\n"
8141 "in vec2 position;\n"
8142 "out vec2 texCoord;\n"
8143 "void main()\n"
8144 "{\n"
8145 " gl_Position = vec4(position, 0, 1);\n"
8146 " texCoord = position * 0.5 + vec2(0.5);\n"
8147 "}";
8148
8149 constexpr char kFS[] =
8150 "#version 310 es\n"
8151 "precision mediump float;\n"
8152 "in vec2 texCoord;\n"
8153 "uniform sampler2D tex1;\n"
8154 "uniform sampler2D tex2;\n"
8155 "uniform sampler2D tex3;\n"
8156 "uniform sampler2D tex4;\n"
8157 "out vec4 color;\n"
8158 "void main()\n"
8159 "{\n"
8160 " color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
8161 " + texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
8162 "}";
8163
8164 bindProgramPipeline(kVS, kFS);
8165
8166 std::array<GLint, 4> texLocations = {
8167 {glGetUniformLocation(mFragProg, "tex1"), glGetUniformLocation(mFragProg, "tex2"),
8168 glGetUniformLocation(mFragProg, "tex3"), glGetUniformLocation(mFragProg, "tex4")}};
8169 for (GLint location : texLocations)
8170 {
8171 ASSERT_NE(-1, location);
8172 }
8173
8174 // Init the uniform data.
8175 glActiveShaderProgram(mPipeline, mFragProg);
8176 for (GLint location = 0; location < 4; ++location)
8177 {
8178 glUniform1i(texLocations[location], location);
8179 }
8180
8181 // Initialize four samplers
8182 GLSampler samplers[4];
8183
8184 // 0: non-mipped.
8185 glBindSampler(0, samplers[0]);
8186 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8187 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8188
8189 // 1: mipped.
8190 glBindSampler(1, samplers[1]);
8191 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
8192 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8193
8194 // 2: non-mipped.
8195 glBindSampler(2, samplers[2]);
8196 glSamplerParameteri(samplers[2], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8197 glSamplerParameteri(samplers[2], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8198
8199 // 3: mipped.
8200 glBindSampler(3, samplers[3]);
8201 glSamplerParameteri(samplers[3], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
8202 glSamplerParameteri(samplers[3], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8203
8204 // Bind two blue mipped textures and two single layer textures, should all draw.
8205 glActiveTexture(GL_TEXTURE0);
8206 glBindTexture(GL_TEXTURE_2D, tex);
8207
8208 glActiveTexture(GL_TEXTURE1);
8209 glBindTexture(GL_TEXTURE_2D, mipmapTex);
8210
8211 glActiveTexture(GL_TEXTURE2);
8212 glBindTexture(GL_TEXTURE_2D, tex);
8213
8214 glActiveTexture(GL_TEXTURE3);
8215 glBindTexture(GL_TEXTURE_2D, mipmapTex);
8216
8217 ASSERT_GL_NO_ERROR();
8218
8219 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
8220 ASSERT_GL_NO_ERROR();
8221 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 255, 2);
8222
8223 // Bind four single layer textures, two should be incomplete.
8224 glActiveTexture(GL_TEXTURE1);
8225 glBindTexture(GL_TEXTURE_2D, tex);
8226
8227 glActiveTexture(GL_TEXTURE3);
8228 glBindTexture(GL_TEXTURE_2D, tex);
8229
8230 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
8231 ASSERT_GL_NO_ERROR();
8232 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 2);
8233 }
8234
8235 // Use a sampler in a uniform struct.
TEST_P(SamplerInStructTest,SamplerInStruct)8236 TEST_P(SamplerInStructTest, SamplerInStruct)
8237 {
8238 runSamplerInStructTest();
8239 }
8240
8241 // Use a sampler in a uniform struct that's passed as a function parameter.
TEST_P(SamplerInStructAsFunctionParameterTest,SamplerInStructAsFunctionParameter)8242 TEST_P(SamplerInStructAsFunctionParameterTest, SamplerInStructAsFunctionParameter)
8243 {
8244 // Fails on Nexus 5X due to a driver bug. http://anglebug.com/42260422
8245 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
8246
8247 runSamplerInStructTest();
8248 }
8249
8250 // Use a sampler in a uniform struct array with a struct from the array passed as a function
8251 // parameter.
TEST_P(SamplerInStructArrayAsFunctionParameterTest,SamplerInStructArrayAsFunctionParameter)8252 TEST_P(SamplerInStructArrayAsFunctionParameterTest, SamplerInStructArrayAsFunctionParameter)
8253 {
8254 // Fails on Nexus 5X due to a driver bug. http://anglebug.com/42260422
8255 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
8256
8257 runSamplerInStructTest();
8258 }
8259
8260 // Use a sampler in a struct inside a uniform struct with the nested struct passed as a function
8261 // parameter.
TEST_P(SamplerInNestedStructAsFunctionParameterTest,SamplerInNestedStructAsFunctionParameter)8262 TEST_P(SamplerInNestedStructAsFunctionParameterTest, SamplerInNestedStructAsFunctionParameter)
8263 {
8264 // Fails on Nexus 5X due to a driver bug. http://anglebug.com/42260422
8265 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
8266
8267 runSamplerInStructTest();
8268 }
8269
8270 // Make sure that there isn't a name conflict between sampler extracted from a struct and a
8271 // similarly named uniform.
TEST_P(SamplerInStructAndOtherVariableTest,SamplerInStructAndOtherVariable)8272 TEST_P(SamplerInStructAndOtherVariableTest, SamplerInStructAndOtherVariable)
8273 {
8274 runSamplerInStructTest();
8275 }
8276
8277 // GL_EXT_texture_filter_anisotropic
8278 class TextureAnisotropyTest : public Texture2DTest
8279 {
8280 protected:
uploadTexture()8281 void uploadTexture()
8282 {
8283 glActiveTexture(GL_TEXTURE0);
8284 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8285 GLColor texDataRed[1] = {GLColor::red};
8286 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed);
8287 EXPECT_GL_NO_ERROR();
8288 }
8289 };
8290
8291 // Tests that setting anisotropic filtering doesn't cause failures at draw time.
TEST_P(TextureAnisotropyTest,AnisotropyFunctional)8292 TEST_P(TextureAnisotropyTest, AnisotropyFunctional)
8293 {
8294 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_filter_anisotropic"));
8295
8296 setUpProgram();
8297
8298 uploadTexture();
8299
8300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8302 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
8303 EXPECT_GL_NO_ERROR();
8304
8305 drawQuad(mProgram, "position", 0.5f);
8306
8307 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8308 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8309 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
8310 }
8311
8312 // GL_OES_texture_border_clamp
8313 class TextureBorderClampTest : public Texture2DTest
8314 {
8315 protected:
TextureBorderClampTest()8316 TextureBorderClampTest() : Texture2DTest() {}
8317
getVertexShaderSource()8318 const char *getVertexShaderSource() override
8319 {
8320 return
8321 R"(precision highp float;
8322 attribute vec4 position;
8323 varying vec2 texcoord;
8324
8325 void main()
8326 {
8327 gl_Position = vec4(position.xy, 0.0, 1.0);
8328 // texcoords in [-0.5, 1.5]
8329 texcoord = (position.xy) + 0.5;
8330 })";
8331 }
8332
uploadTexture()8333 void uploadTexture()
8334 {
8335 glActiveTexture(GL_TEXTURE0);
8336 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8337 std::vector<GLColor> texDataRed(1, GLColor::red);
8338 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8339 texDataRed.data());
8340 EXPECT_GL_NO_ERROR();
8341 }
8342
testFormat(GLenum format,GLenum type,GLColor32F borderColor)8343 void testFormat(GLenum format, GLenum type, GLColor32F borderColor)
8344 {
8345 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8346 glActiveTexture(GL_TEXTURE0);
8347 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &borderColor.R);
8348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8350 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8351 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8352 glTexImage2D(GL_TEXTURE_2D, 0, format, 2, 2, 0, format, type, nullptr);
8353 drawQuad(mProgram, "position", 0.5f);
8354 }
8355
testCompressedFormat(GLenum format,GLsizei size,GLColor32F borderColor)8356 void testCompressedFormat(GLenum format, GLsizei size, GLColor32F borderColor)
8357 {
8358 setUpProgram();
8359 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8360 glActiveTexture(GL_TEXTURE0);
8361 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &borderColor.R);
8362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8365 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8366 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, 4, 4, 0, size, nullptr);
8367 drawQuad(mProgram, "position", 0.5f);
8368 }
8369 };
8370
8371 // Test if the color set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the texture in
8372 // GL_CLAMP_TO_BORDER wrap mode (set with glTexParameter).
TEST_P(TextureBorderClampTest,TextureBorderClampFunctional)8373 TEST_P(TextureBorderClampTest, TextureBorderClampFunctional)
8374 {
8375 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8376
8377 setUpProgram();
8378
8379 uploadTexture();
8380
8381 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8382 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8385 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8386 EXPECT_GL_NO_ERROR();
8387
8388 drawQuad(mProgram, "position", 0.5f);
8389
8390 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8391 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8392 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8393 }
8394
8395 // Test reading back GL_TEXTURE_BORDER_COLOR by glGetTexParameter.
TEST_P(TextureBorderClampTest,TextureBorderClampFunctional2)8396 TEST_P(TextureBorderClampTest, TextureBorderClampFunctional2)
8397 {
8398 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8399
8400 glActiveTexture(GL_TEXTURE0);
8401 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8402
8403 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8404
8405 GLint colorFixedPoint[4] = {0};
8406 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorFixedPoint);
8407 constexpr GLint colorGreenFixedPoint[4] = {0, std::numeric_limits<GLint>::max(), 0,
8408 std::numeric_limits<GLint>::max()};
8409 EXPECT_EQ(colorFixedPoint[0], colorGreenFixedPoint[0]);
8410 EXPECT_EQ(colorFixedPoint[1], colorGreenFixedPoint[1]);
8411 EXPECT_EQ(colorFixedPoint[2], colorGreenFixedPoint[2]);
8412 EXPECT_EQ(colorFixedPoint[3], colorGreenFixedPoint[3]);
8413
8414 constexpr GLint colorBlueFixedPoint[4] = {0, 0, std::numeric_limits<GLint>::max(),
8415 std::numeric_limits<GLint>::max()};
8416 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorBlueFixedPoint);
8417
8418 GLfloat color[4] = {0.0f};
8419 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
8420 EXPECT_EQ(color[0], kFloatBlue.R);
8421 EXPECT_EQ(color[1], kFloatBlue.G);
8422 EXPECT_EQ(color[2], kFloatBlue.B);
8423 EXPECT_EQ(color[3], kFloatBlue.A);
8424 }
8425
8426 // Test GL_TEXTURE_BORDER_COLOR parameter validation at glTexParameter.
TEST_P(TextureBorderClampTest,TextureBorderClampValidation)8427 TEST_P(TextureBorderClampTest, TextureBorderClampValidation)
8428 {
8429 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8430
8431 glActiveTexture(GL_TEXTURE0);
8432 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8433
8434 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, 1.0f);
8435 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8436
8437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::numeric_limits<GLint>::max());
8438 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8439
8440 glTexParameterfv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8441 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8442
8443 GLint colorInt[4] = {0};
8444 glTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_BORDER_COLOR, colorInt);
8445 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8446
8447 if (getClientMajorVersion() < 3)
8448 {
8449 glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
8450 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8451 glGetTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
8452 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8453
8454 GLuint colorUInt[4] = {0};
8455 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
8456 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8457 glGetTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
8458 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8459
8460 GLSampler sampler;
8461 glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
8462 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8463 glGetSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
8464 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8465
8466 glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
8467 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8468 glGetSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
8469 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8470 }
8471 }
8472
8473 // Test GL_TEXTURE_BORDER_COLOR parameter with unorm formats.
TEST_P(TextureBorderClampTest,TextureBorderClampUnorm8)8474 TEST_P(TextureBorderClampTest, TextureBorderClampUnorm8)
8475 {
8476 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8477
8478 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8479
8480 setUpProgram();
8481
8482 testFormat(GL_ALPHA, GL_UNSIGNED_BYTE, kBorder);
8483 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8484
8485 testFormat(GL_RGB, GL_UNSIGNED_BYTE, kBorder);
8486 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8487
8488 testFormat(GL_RGBA, GL_UNSIGNED_BYTE, kBorder);
8489 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8490
8491 testFormat(GL_LUMINANCE, GL_UNSIGNED_BYTE, kBorder);
8492 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
8493
8494 testFormat(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, kBorder);
8495 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8496 }
8497
8498 // Test GL_TEXTURE_BORDER_COLOR parameter with sRGB formats.
TEST_P(TextureBorderClampTest,TextureBorderClampSrgb)8499 TEST_P(TextureBorderClampTest, TextureBorderClampSrgb)
8500 {
8501 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8502 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB"));
8503
8504 // AMD D3D9 drivers always sample sRGB formats with (0, 0, 0, 0) border color, won't fix.
8505 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
8506
8507 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8508
8509 setUpProgram();
8510
8511 testFormat(GL_SRGB_EXT, GL_UNSIGNED_BYTE, kBorder);
8512 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8513
8514 testFormat(GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, kBorder);
8515 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8516 }
8517
8518 // Test GL_TEXTURE_BORDER_COLOR parameter with half-float formats.
TEST_P(TextureBorderClampTest,TextureBorderClampFloat16)8519 TEST_P(TextureBorderClampTest, TextureBorderClampFloat16)
8520 {
8521 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8522 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
8523
8524 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8525
8526 setUpProgram();
8527
8528 testFormat(GL_ALPHA, GL_HALF_FLOAT_OES, kBorder);
8529 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8530
8531 testFormat(GL_RGB, GL_HALF_FLOAT_OES, kBorder);
8532 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8533
8534 testFormat(GL_RGBA, GL_HALF_FLOAT_OES, kBorder);
8535 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8536
8537 testFormat(GL_LUMINANCE, GL_HALF_FLOAT_OES, kBorder);
8538 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
8539
8540 testFormat(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, kBorder);
8541 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8542 }
8543
8544 // Test GL_TEXTURE_BORDER_COLOR parameter with float formats.
TEST_P(TextureBorderClampTest,TextureBorderClampFloat32)8545 TEST_P(TextureBorderClampTest, TextureBorderClampFloat32)
8546 {
8547 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8548 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
8549
8550 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8551
8552 setUpProgram();
8553
8554 testFormat(GL_ALPHA, GL_FLOAT, kBorder);
8555 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8556
8557 testFormat(GL_RGB, GL_FLOAT, kBorder);
8558 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8559
8560 testFormat(GL_RGBA, GL_FLOAT, kBorder);
8561 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8562
8563 testFormat(GL_LUMINANCE, GL_FLOAT, kBorder);
8564 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
8565
8566 testFormat(GL_LUMINANCE_ALPHA, GL_FLOAT, kBorder);
8567 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8568 }
8569
8570 // Test GL_TEXTURE_BORDER_COLOR parameter with red and red-green formats.
TEST_P(TextureBorderClampTest,TextureBorderClampRG)8571 TEST_P(TextureBorderClampTest, TextureBorderClampRG)
8572 {
8573 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8574 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
8575
8576 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8577
8578 setUpProgram();
8579
8580 testFormat(GL_RED_EXT, GL_UNSIGNED_BYTE, kBorder);
8581 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
8582
8583 testFormat(GL_RG_EXT, GL_UNSIGNED_BYTE, kBorder);
8584 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
8585
8586 if (IsGLExtensionEnabled("GL_OES_texture_half_float"))
8587 {
8588 testFormat(GL_RED_EXT, GL_HALF_FLOAT_OES, kBorder);
8589 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
8590
8591 testFormat(GL_RG_EXT, GL_HALF_FLOAT_OES, kBorder);
8592 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
8593 }
8594
8595 if (IsGLExtensionEnabled("GL_OES_texture_float"))
8596 {
8597 testFormat(GL_RED_EXT, GL_FLOAT, kBorder);
8598 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
8599
8600 testFormat(GL_RG_EXT, GL_FLOAT, kBorder);
8601 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
8602 }
8603 }
8604
8605 // Test GL_TEXTURE_BORDER_COLOR parameter with DXT1 formats.
TEST_P(TextureBorderClampTest,TextureBorderClampDXT1)8606 TEST_P(TextureBorderClampTest, TextureBorderClampDXT1)
8607 {
8608 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8609 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
8610
8611 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8612
8613 setUpProgram();
8614
8615 testCompressedFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 8, kBorder);
8616 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8617
8618 testCompressedFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, kBorder);
8619 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8620 }
8621
8622 // Test GL_TEXTURE_BORDER_COLOR parameter with DXT1 sRGB formats.
TEST_P(TextureBorderClampTest,TextureBorderClampDXT1Srgb)8623 TEST_P(TextureBorderClampTest, TextureBorderClampDXT1Srgb)
8624 {
8625 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8626 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc_srgb"));
8627
8628 // AMD D3D9 drivers always sample sRGB formats with (0, 0, 0, 0) border color, won't fix.
8629 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
8630
8631 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8632
8633 setUpProgram();
8634
8635 testCompressedFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 8, kBorder);
8636 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8637
8638 testCompressedFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 8, kBorder);
8639 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8640 }
8641
8642 // Test GL_TEXTURE_BORDER_COLOR parameter with texture redefinition.
TEST_P(TextureBorderClampTest,Redefinition)8643 TEST_P(TextureBorderClampTest, Redefinition)
8644 {
8645 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8646
8647 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8648
8649 setUpProgram();
8650
8651 testFormat(GL_ALPHA, GL_UNSIGNED_BYTE, kBorder);
8652 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8653
8654 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 2, 2, 0, GL_LUMINANCE_ALPHA,
8655 GL_UNSIGNED_BYTE, nullptr);
8656 drawQuad(mProgram, "position", 0.5f);
8657 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8658
8659 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
8660 drawQuad(mProgram, "position", 0.5f);
8661 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8662 }
8663
8664 class TextureBorderClampTestES3 : public TextureBorderClampTest
8665 {
8666 protected:
TextureBorderClampTestES3()8667 TextureBorderClampTestES3() : TextureBorderClampTest() {}
8668 };
8669
8670 // Test if the color set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the texture in
8671 // GL_CLAMP_TO_BORDER wrap mode (set with glSamplerParameter).
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Functional)8672 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Functional)
8673 {
8674 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8675
8676 setUpProgram();
8677
8678 uploadTexture();
8679
8680 GLSampler sampler;
8681 glBindSampler(0, sampler);
8682 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8683 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8684 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8685 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8686 glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8687 EXPECT_GL_NO_ERROR();
8688
8689 drawQuad(mProgram, "position", 0.5f);
8690
8691 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8692 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8693 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8694 }
8695
8696 // Test reading back GL_TEXTURE_BORDER_COLOR by glGetSamplerParameter.
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Functional2)8697 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Functional2)
8698 {
8699 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8700
8701 glActiveTexture(GL_TEXTURE0);
8702
8703 GLSampler sampler;
8704 glBindSampler(0, sampler);
8705
8706 glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8707
8708 GLint colorFixedPoint[4] = {0};
8709 glGetSamplerParameteriv(sampler, GL_TEXTURE_BORDER_COLOR, colorFixedPoint);
8710 constexpr GLint colorGreenFixedPoint[4] = {0, std::numeric_limits<GLint>::max(), 0,
8711 std::numeric_limits<GLint>::max()};
8712 EXPECT_EQ(colorFixedPoint[0], colorGreenFixedPoint[0]);
8713 EXPECT_EQ(colorFixedPoint[1], colorGreenFixedPoint[1]);
8714 EXPECT_EQ(colorFixedPoint[2], colorGreenFixedPoint[2]);
8715 EXPECT_EQ(colorFixedPoint[3], colorGreenFixedPoint[3]);
8716
8717 constexpr GLint colorBlueFixedPoint[4] = {0, 0, std::numeric_limits<GLint>::max(),
8718 std::numeric_limits<GLint>::max()};
8719 glSamplerParameteriv(sampler, GL_TEXTURE_BORDER_COLOR, colorBlueFixedPoint);
8720
8721 GLfloat color[4] = {0.0f};
8722 glGetSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, color);
8723 EXPECT_EQ(color[0], kFloatBlue.R);
8724 EXPECT_EQ(color[1], kFloatBlue.G);
8725 EXPECT_EQ(color[2], kFloatBlue.B);
8726 EXPECT_EQ(color[3], kFloatBlue.A);
8727
8728 constexpr GLint colorSomewhatRedInt[4] = {500000, 0, 0, std::numeric_limits<GLint>::max()};
8729 glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorSomewhatRedInt);
8730 GLint colorInt[4] = {0};
8731 glGetSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
8732 EXPECT_EQ(colorInt[0], colorSomewhatRedInt[0]);
8733 EXPECT_EQ(colorInt[1], colorSomewhatRedInt[1]);
8734 EXPECT_EQ(colorInt[2], colorSomewhatRedInt[2]);
8735 EXPECT_EQ(colorInt[3], colorSomewhatRedInt[3]);
8736
8737 constexpr GLuint colorSomewhatRedUInt[4] = {500000, 0, 0, std::numeric_limits<GLuint>::max()};
8738 glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorSomewhatRedUInt);
8739 GLuint colorUInt[4] = {0};
8740 glGetSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
8741 EXPECT_EQ(colorUInt[0], colorSomewhatRedUInt[0]);
8742 EXPECT_EQ(colorUInt[1], colorSomewhatRedUInt[1]);
8743 EXPECT_EQ(colorUInt[2], colorSomewhatRedUInt[2]);
8744 EXPECT_EQ(colorUInt[3], colorSomewhatRedUInt[3]);
8745
8746 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8747
8748 constexpr GLint colorSomewhatGreenInt[4] = {0, 500000, 0, std::numeric_limits<GLint>::max()};
8749 glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorSomewhatGreenInt);
8750 glGetTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
8751 EXPECT_EQ(colorInt[0], colorSomewhatGreenInt[0]);
8752 EXPECT_EQ(colorInt[1], colorSomewhatGreenInt[1]);
8753 EXPECT_EQ(colorInt[2], colorSomewhatGreenInt[2]);
8754 EXPECT_EQ(colorInt[3], colorSomewhatGreenInt[3]);
8755
8756 constexpr GLuint colorSomewhatGreenUInt[4] = {0, 500000, 0, std::numeric_limits<GLuint>::max()};
8757 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorSomewhatGreenUInt);
8758 glGetTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
8759 EXPECT_EQ(colorUInt[0], colorSomewhatGreenUInt[0]);
8760 EXPECT_EQ(colorUInt[1], colorSomewhatGreenUInt[1]);
8761 EXPECT_EQ(colorUInt[2], colorSomewhatGreenUInt[2]);
8762 EXPECT_EQ(colorUInt[3], colorSomewhatGreenUInt[3]);
8763 }
8764
8765 // Test GL_TEXTURE_BORDER_COLOR parameter validation at glSamplerParameter.
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Validation)8766 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Validation)
8767 {
8768 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8769
8770 glActiveTexture(GL_TEXTURE0);
8771
8772 GLSampler sampler;
8773 glBindSampler(0, sampler);
8774
8775 glSamplerParameterf(sampler, GL_TEXTURE_BORDER_COLOR, 1.0f);
8776 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8777
8778 glSamplerParameteri(sampler, GL_TEXTURE_BORDER_COLOR, std::numeric_limits<GLint>::max());
8779 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8780 }
8781
8782 // Test that format-specific adjustments are applied
8783 // when the border color type does not match the texture type.
TEST_P(TextureBorderClampTestES3,TextureBorderTypeMismatch)8784 TEST_P(TextureBorderClampTestES3, TextureBorderTypeMismatch)
8785 {
8786 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8787
8788 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8789 glActiveTexture(GL_TEXTURE0);
8790 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8791 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8792 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8793 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8794
8795 GLColor32UI kBorder = {1, 2, 3, 0};
8796 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kBorder.R);
8797 ASSERT_GL_NO_ERROR();
8798
8799 setUpProgram();
8800
8801 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
8802 drawQuad(mProgram, "position", 0.5f);
8803 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
8804 }
8805
8806 class TextureBorderClampIntegerTestES3 : public Texture2DTest
8807 {
8808 protected:
TextureBorderClampIntegerTestES3()8809 TextureBorderClampIntegerTestES3() : Texture2DTest(), isUnsignedIntTest(false) {}
8810
getVertexShaderSource()8811 const char *getVertexShaderSource() override
8812 {
8813 return
8814 R"(#version 300 es
8815 out vec2 texcoord;
8816 in vec4 position;
8817
8818 void main()
8819 {
8820 gl_Position = vec4(position.xy, 0.0, 1.0);
8821 // texcoords in [-0.5, 1.5]
8822 texcoord = (position.xy) + 0.5;
8823 })";
8824 }
8825
getFragmentShaderSource()8826 const char *getFragmentShaderSource() override
8827 {
8828 if (isUnsignedIntTest)
8829 {
8830 return "#version 300 es\n"
8831 "precision highp float;\n"
8832 "uniform highp usampler2D tex;\n"
8833 "in vec2 texcoord;\n"
8834 "out vec4 fragColor;\n"
8835
8836 "void main()\n"
8837 "{\n"
8838 "vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
8839 "vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
8840 "fragColor = (texture(tex, texcoord).r == 150u)"
8841 " ? green : red;\n"
8842 "}\n";
8843 }
8844 else
8845 {
8846 return "#version 300 es\n"
8847 "precision highp float;\n"
8848 "uniform highp isampler2D tex;\n"
8849 "in vec2 texcoord;\n"
8850 "out vec4 fragColor;\n"
8851
8852 "void main()\n"
8853 "{\n"
8854 "vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
8855 "vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
8856 "fragColor = (texture(tex, texcoord).r == -50)"
8857 " ? green : red;\n"
8858 "}\n";
8859 }
8860 }
8861
uploadTexture()8862 void uploadTexture()
8863 {
8864 glActiveTexture(GL_TEXTURE0);
8865 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8866 if (isUnsignedIntTest)
8867 {
8868 std::vector<GLubyte> texData(4, 100);
8869 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
8870 texData.data());
8871 }
8872 else
8873 {
8874 std::vector<GLbyte> texData(4, 100);
8875 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, 1, 1, 0, GL_RGBA_INTEGER, GL_BYTE,
8876 texData.data());
8877 }
8878 EXPECT_GL_NO_ERROR();
8879 }
8880
8881 bool isUnsignedIntTest;
8882 };
8883
8884 // Test if the integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the
8885 // integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampInteger)8886 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampInteger)
8887 {
8888 // Fails on Win10 FYI x64 Release (AMD RX 550). http://anglebug.com/40096617
8889 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
8890
8891 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8892
8893 setUpProgram();
8894
8895 uploadTexture();
8896
8897 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8898 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8899 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8900 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8901
8902 constexpr GLint borderColor[4] = {-50, -50, -50, -50};
8903 glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
8904
8905 EXPECT_GL_NO_ERROR();
8906
8907 drawQuad(mProgram, "position", 0.5f);
8908
8909 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8910 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8911 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8912 }
8913
8914 // Test if the integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the
8915 // integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampInteger2)8916 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampInteger2)
8917 {
8918 // Fails on Win10 FYI x64 Release (AMD RX 550). http://anglebug.com/40096617
8919 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
8920
8921 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8922
8923 setUpProgram();
8924
8925 uploadTexture();
8926
8927 GLSampler sampler;
8928 glBindSampler(0, sampler);
8929 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8930 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8931 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8932 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8933
8934 constexpr GLint borderColor[4] = {-50, -50, -50, -50};
8935 glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, borderColor);
8936
8937 EXPECT_GL_NO_ERROR();
8938
8939 drawQuad(mProgram, "position", 0.5f);
8940
8941 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8942 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8943 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8944 }
8945
8946 // Test if the unsigned integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside
8947 // of the unsigned integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIuivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampIntegerUnsigned)8948 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampIntegerUnsigned)
8949 {
8950 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8951
8952 isUnsignedIntTest = true;
8953
8954 setUpProgram();
8955
8956 uploadTexture();
8957
8958 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8959 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8960 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8961 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8962
8963 constexpr GLuint borderColor[4] = {150, 150, 150, 150};
8964 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
8965
8966 EXPECT_GL_NO_ERROR();
8967
8968 drawQuad(mProgram, "position", 0.5f);
8969
8970 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8971 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8972 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8973 }
8974
8975 // Test if the unsigned integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside
8976 // of the unsigned integer texture in GL_CLAMP_TO_BORDER wrap mode (set with
8977 // glSamplerParameterIuivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampIntegerUnsigned2)8978 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampIntegerUnsigned2)
8979 {
8980 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8981
8982 isUnsignedIntTest = true;
8983
8984 setUpProgram();
8985
8986 uploadTexture();
8987
8988 GLSampler sampler;
8989 glBindSampler(0, sampler);
8990 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8991 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8992 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8993 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8994
8995 constexpr GLuint borderColor[4] = {150, 150, 150, 150};
8996 glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, borderColor);
8997
8998 EXPECT_GL_NO_ERROR();
8999
9000 drawQuad(mProgram, "position", 0.5f);
9001
9002 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
9003 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9004 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
9005 }
9006
9007 // ~GL_OES_texture_border_clamp
9008
9009 // GL_EXT_texture_mirror_clamp_to_edge
9010 class TextureMirrorClampToEdgeTest : public Texture2DTest
9011 {
9012 protected:
TextureMirrorClampToEdgeTest()9013 TextureMirrorClampToEdgeTest() : Texture2DTest() {}
9014
getVertexShaderSource()9015 const char *getVertexShaderSource() override
9016 {
9017 return R"(precision highp float;
9018 attribute vec4 position;
9019 varying vec2 texcoord;
9020
9021 void main()
9022 {
9023 gl_Position = vec4(position.xy, 0.0, 1.0);
9024 texcoord = position.xy * 2.0;
9025 })";
9026 }
9027
uploadTexture(bool isInteger,bool isSigned,GLuint sampler)9028 void uploadTexture(bool isInteger, bool isSigned, GLuint sampler)
9029 {
9030 glActiveTexture(GL_TEXTURE0);
9031 glBindTexture(GL_TEXTURE_2D, mTexture2D);
9032 if (isInteger && isSigned)
9033 {
9034 const int8_t data[] = {0, 0, 0, -1, -1, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, -1};
9035 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, 2, 2, 0, GL_RGBA_INTEGER, GL_BYTE, data);
9036 }
9037 else if (isInteger)
9038 {
9039 const uint8_t data[] = {0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1};
9040 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
9041 data);
9042 }
9043 else
9044 {
9045 const uint8_t data[] = {0, 0, 0, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255};
9046 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
9047 }
9048
9049 if (sampler != 0)
9050 {
9051 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_MIRROR_CLAMP_TO_EDGE_EXT);
9052 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_MIRROR_CLAMP_TO_EDGE_EXT);
9053 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9054 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9055 }
9056 else
9057 {
9058 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRROR_CLAMP_TO_EDGE_EXT);
9059 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRROR_CLAMP_TO_EDGE_EXT);
9060 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9061 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9062 }
9063 ASSERT_GL_NO_ERROR();
9064 }
9065
checkTextureSampling()9066 void checkTextureSampling()
9067 {
9068 auto screenX = [&](float x) { return getWindowWidth() * (x * 0.25 + 0.5); };
9069 auto screenY = [&](float y) { return getWindowHeight() * (y * 0.25 + 0.5); };
9070
9071 // +S, +T
9072 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(0.25), GLColor::black);
9073 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(0.25), GLColor::red);
9074 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(0.25), GLColor::red);
9075 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(0.75), GLColor::green);
9076 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(1.50), GLColor::green);
9077 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(0.75), GLColor::blue);
9078 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(0.75), GLColor::blue);
9079 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(1.50), GLColor::blue);
9080 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(1.50), GLColor::blue);
9081
9082 // -S, +T
9083 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(0.25), GLColor::black);
9084 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(0.25), GLColor::red);
9085 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(0.25), GLColor::red);
9086 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(0.75), GLColor::green);
9087 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(1.50), GLColor::green);
9088 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(0.75), GLColor::blue);
9089 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(0.75), GLColor::blue);
9090 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(1.50), GLColor::blue);
9091 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(1.50), GLColor::blue);
9092
9093 // +S, -T
9094 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-0.25), GLColor::black);
9095 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-0.25), GLColor::red);
9096 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-0.25), GLColor::red);
9097 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-0.75), GLColor::green);
9098 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-1.50), GLColor::green);
9099 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-0.75), GLColor::blue);
9100 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-0.75), GLColor::blue);
9101 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-1.50), GLColor::blue);
9102 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-1.50), GLColor::blue);
9103
9104 // -S, -T
9105 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-0.25), GLColor::black);
9106 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-0.25), GLColor::red);
9107 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-0.25), GLColor::red);
9108 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-0.75), GLColor::green);
9109 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-1.50), GLColor::green);
9110 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-0.75), GLColor::blue);
9111 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-0.75), GLColor::blue);
9112 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-1.50), GLColor::blue);
9113 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-1.50), GLColor::blue);
9114 }
9115 };
9116
9117 // Test that the texture is correctly mirrored in negative directions
9118 // and clamped to edge pixels outside of the normalized range.
TEST_P(TextureMirrorClampToEdgeTest,TexParameter)9119 TEST_P(TextureMirrorClampToEdgeTest, TexParameter)
9120 {
9121 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
9122
9123 setUpProgram();
9124 uploadTexture(false, false, 0);
9125 drawQuad(mProgram, "position", 0.5f);
9126 ASSERT_GL_NO_ERROR();
9127
9128 checkTextureSampling();
9129 }
9130
9131 class TextureMirrorClampToEdgeTestES3 : public TextureMirrorClampToEdgeTest
9132 {
9133 protected:
TextureMirrorClampToEdgeTestES3()9134 TextureMirrorClampToEdgeTestES3() : TextureMirrorClampToEdgeTest() {}
9135 };
9136
9137 // Test that the texture is correctly mirrored in negative directions and clamped
9138 // to edge pixels outside of the normalized range with mode set via glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeTestES3,SamplerParameter)9139 TEST_P(TextureMirrorClampToEdgeTestES3, SamplerParameter)
9140 {
9141 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
9142
9143 GLSampler sampler;
9144 glBindSampler(0, sampler);
9145
9146 setUpProgram();
9147 uploadTexture(false, false, sampler);
9148 drawQuad(mProgram, "position", 0.5f);
9149 ASSERT_GL_NO_ERROR();
9150
9151 checkTextureSampling();
9152 }
9153
9154 class TextureMirrorClampToEdgeIntegerTestES3 : public TextureMirrorClampToEdgeTestES3
9155 {
9156 protected:
TextureMirrorClampToEdgeIntegerTestES3()9157 TextureMirrorClampToEdgeIntegerTestES3() : TextureMirrorClampToEdgeTestES3() {}
9158
getVertexShaderSource()9159 const char *getVertexShaderSource() override
9160 {
9161 return R"(#version 300 es
9162 precision highp float;
9163 in vec4 position;
9164 out vec2 texcoord;
9165
9166 void main()
9167 {
9168 gl_Position = vec4(position.xy, 0.0, 1.0);
9169 texcoord = position.xy * 2.0;
9170 })";
9171 }
9172
getFragmentShaderSource()9173 const char *getFragmentShaderSource() override
9174 {
9175 if (mIsSigned)
9176 {
9177 return R"(#version 300 es
9178 precision highp float;
9179 uniform highp isampler2D tex;
9180 in vec2 texcoord;
9181 out vec4 fragColor;
9182 void main() { fragColor = vec4(-texture(tex, texcoord)); })";
9183 }
9184 else
9185 {
9186 return R"(#version 300 es
9187 precision highp float;
9188 uniform highp usampler2D tex;
9189 in vec2 texcoord;
9190 out vec4 fragColor;
9191 void main() { fragColor = vec4(texture(tex, texcoord)); })";
9192 }
9193 }
9194
9195 bool mIsSigned = false;
9196 };
9197
9198 // Test that the texture is correctly mirrored in negative directions and clamped
9199 // to edge pixels outside of the normalized range with mode set with glTexParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,TexParameterSigned)9200 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, TexParameterSigned)
9201 {
9202 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
9203
9204 mIsSigned = true;
9205 setUpProgram();
9206 uploadTexture(true, true, 0);
9207 drawQuad(mProgram, "position", 0.5f);
9208 ASSERT_GL_NO_ERROR();
9209
9210 checkTextureSampling();
9211 }
9212
9213 // Test that the texture is correctly mirrored in negative directions and clamped
9214 // to edge pixels outside of the normalized range with mode set with glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,SamplerParameterSigned)9215 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, SamplerParameterSigned)
9216 {
9217 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
9218
9219 GLSampler sampler;
9220 glBindSampler(0, sampler);
9221
9222 mIsSigned = true;
9223 setUpProgram();
9224 uploadTexture(true, true, sampler);
9225 drawQuad(mProgram, "position", 0.5f);
9226 ASSERT_GL_NO_ERROR();
9227
9228 checkTextureSampling();
9229 }
9230
9231 // Test that the unsigned integer texture is correctly mirrored in negative directions and clamped
9232 // to edge pixels outside of the normalized range with mode set with glTexParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,TexParameterUnsigned)9233 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, TexParameterUnsigned)
9234 {
9235 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
9236
9237 setUpProgram();
9238 uploadTexture(true, false, 0);
9239 drawQuad(mProgram, "position", 0.5f);
9240 ASSERT_GL_NO_ERROR();
9241
9242 checkTextureSampling();
9243 }
9244
9245 // Test that the unsigned integer texture is correctly mirrored in negative directions and clamped
9246 // to edge pixels outside of the normalized range with mode set with glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,SamplerParameterUnsigned)9247 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, SamplerParameterUnsigned)
9248 {
9249 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
9250
9251 GLSampler sampler;
9252 glBindSampler(0, sampler);
9253
9254 setUpProgram();
9255 uploadTexture(true, false, sampler);
9256 drawQuad(mProgram, "position", 0.5f);
9257 ASSERT_GL_NO_ERROR();
9258
9259 checkTextureSampling();
9260 }
9261 // ~GL_EXT_texture_mirror_clamp_to_edge
9262
9263 class TextureLimitsTest : public ANGLETest<>
9264 {
9265 protected:
9266 struct RGBA8
9267 {
9268 uint8_t R, G, B, A;
9269 };
9270
TextureLimitsTest()9271 TextureLimitsTest()
9272 : mProgram(0), mMaxVertexTextures(0), mMaxFragmentTextures(0), mMaxCombinedTextures(0)
9273 {
9274 setWindowWidth(128);
9275 setWindowHeight(128);
9276 setConfigRedBits(8);
9277 setConfigGreenBits(8);
9278 setConfigBlueBits(8);
9279 setConfigAlphaBits(8);
9280 }
9281
testSetUp()9282 void testSetUp() override
9283 {
9284 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mMaxVertexTextures);
9285 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mMaxFragmentTextures);
9286 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxCombinedTextures);
9287
9288 ASSERT_GL_NO_ERROR();
9289 }
9290
testTearDown()9291 void testTearDown() override
9292 {
9293 if (mProgram != 0)
9294 {
9295 glDeleteProgram(mProgram);
9296 mProgram = 0;
9297
9298 if (!mTextures.empty())
9299 {
9300 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), &mTextures[0]);
9301 }
9302 }
9303 }
9304
compileProgramWithTextureCounts(const std::string & vertexPrefix,GLint vertexTextureCount,GLint vertexActiveTextureCount,const std::string & fragPrefix,GLint fragmentTextureCount,GLint fragmentActiveTextureCount)9305 void compileProgramWithTextureCounts(const std::string &vertexPrefix,
9306 GLint vertexTextureCount,
9307 GLint vertexActiveTextureCount,
9308 const std::string &fragPrefix,
9309 GLint fragmentTextureCount,
9310 GLint fragmentActiveTextureCount)
9311 {
9312 std::stringstream vertexShaderStr;
9313 vertexShaderStr << "attribute vec2 position;\n"
9314 << "varying vec4 color;\n"
9315 << "varying vec2 texCoord;\n";
9316
9317 for (GLint textureIndex = 0; textureIndex < vertexTextureCount; ++textureIndex)
9318 {
9319 vertexShaderStr << "uniform sampler2D " << vertexPrefix << textureIndex << ";\n";
9320 }
9321
9322 vertexShaderStr << "void main() {\n"
9323 << " gl_Position = vec4(position, 0, 1);\n"
9324 << " texCoord = (position * 0.5) + 0.5;\n"
9325 << " color = vec4(0);\n";
9326
9327 for (GLint textureIndex = 0; textureIndex < vertexActiveTextureCount; ++textureIndex)
9328 {
9329 vertexShaderStr << " color += texture2D(" << vertexPrefix << textureIndex
9330 << ", texCoord);\n";
9331 }
9332
9333 vertexShaderStr << "}";
9334
9335 std::stringstream fragmentShaderStr;
9336 fragmentShaderStr << "varying mediump vec4 color;\n" << "varying mediump vec2 texCoord;\n";
9337
9338 for (GLint textureIndex = 0; textureIndex < fragmentTextureCount; ++textureIndex)
9339 {
9340 fragmentShaderStr << "uniform sampler2D " << fragPrefix << textureIndex << ";\n";
9341 }
9342
9343 fragmentShaderStr << "void main() {\n" << " gl_FragColor = color;\n";
9344
9345 for (GLint textureIndex = 0; textureIndex < fragmentActiveTextureCount; ++textureIndex)
9346 {
9347 fragmentShaderStr << " gl_FragColor += texture2D(" << fragPrefix << textureIndex
9348 << ", texCoord);\n";
9349 }
9350
9351 fragmentShaderStr << "}";
9352
9353 const std::string &vertexShaderSource = vertexShaderStr.str();
9354 const std::string &fragmentShaderSource = fragmentShaderStr.str();
9355
9356 mProgram = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
9357 }
9358
getPixel(GLint texIndex)9359 RGBA8 getPixel(GLint texIndex)
9360 {
9361 RGBA8 pixel = {static_cast<uint8_t>(texIndex & 0x7u), static_cast<uint8_t>(texIndex >> 3),
9362 0, 255u};
9363 return pixel;
9364 }
9365
initTextures(GLint tex2DCount,GLint texCubeCount)9366 void initTextures(GLint tex2DCount, GLint texCubeCount)
9367 {
9368 GLint totalCount = tex2DCount + texCubeCount;
9369 mTextures.assign(totalCount, 0);
9370 glGenTextures(totalCount, &mTextures[0]);
9371 ASSERT_GL_NO_ERROR();
9372
9373 std::vector<RGBA8> texData(16 * 16);
9374
9375 GLint texIndex = 0;
9376 for (; texIndex < tex2DCount; ++texIndex)
9377 {
9378 texData.assign(texData.size(), getPixel(texIndex));
9379 glActiveTexture(GL_TEXTURE0 + texIndex);
9380 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
9381 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9382 &texData[0]);
9383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9386 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9387 }
9388
9389 ASSERT_GL_NO_ERROR();
9390
9391 for (; texIndex < texCubeCount; ++texIndex)
9392 {
9393 texData.assign(texData.size(), getPixel(texIndex));
9394 glActiveTexture(GL_TEXTURE0 + texIndex);
9395 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[texIndex]);
9396 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9397 GL_UNSIGNED_BYTE, &texData[0]);
9398 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9399 GL_UNSIGNED_BYTE, &texData[0]);
9400 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9401 GL_UNSIGNED_BYTE, &texData[0]);
9402 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9403 GL_UNSIGNED_BYTE, &texData[0]);
9404 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9405 GL_UNSIGNED_BYTE, &texData[0]);
9406 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9407 GL_UNSIGNED_BYTE, &texData[0]);
9408 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9409 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9410 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9411 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9412 }
9413
9414 ASSERT_GL_NO_ERROR();
9415 }
9416
testWithTextures(GLint vertexTextureCount,const std::string & vertexTexturePrefix,GLint fragmentTextureCount,const std::string & fragmentTexturePrefix)9417 void testWithTextures(GLint vertexTextureCount,
9418 const std::string &vertexTexturePrefix,
9419 GLint fragmentTextureCount,
9420 const std::string &fragmentTexturePrefix)
9421 {
9422 // Generate textures
9423 initTextures(vertexTextureCount + fragmentTextureCount, 0);
9424
9425 glUseProgram(mProgram);
9426 RGBA8 expectedSum = {0};
9427 for (GLint texIndex = 0; texIndex < vertexTextureCount; ++texIndex)
9428 {
9429 std::stringstream uniformNameStr;
9430 uniformNameStr << vertexTexturePrefix << texIndex;
9431 const std::string &uniformName = uniformNameStr.str();
9432 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
9433 ASSERT_NE(-1, location);
9434
9435 glUniform1i(location, texIndex);
9436 RGBA8 contribution = getPixel(texIndex);
9437 expectedSum.R += contribution.R;
9438 expectedSum.G += contribution.G;
9439 }
9440
9441 for (GLint texIndex = 0; texIndex < fragmentTextureCount; ++texIndex)
9442 {
9443 std::stringstream uniformNameStr;
9444 uniformNameStr << fragmentTexturePrefix << texIndex;
9445 const std::string &uniformName = uniformNameStr.str();
9446 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
9447 ASSERT_NE(-1, location);
9448
9449 glUniform1i(location, texIndex + vertexTextureCount);
9450 RGBA8 contribution = getPixel(texIndex + vertexTextureCount);
9451 expectedSum.R += contribution.R;
9452 expectedSum.G += contribution.G;
9453 }
9454
9455 ASSERT_GE(256u, expectedSum.G);
9456
9457 drawQuad(mProgram, "position", 0.5f);
9458 ASSERT_GL_NO_ERROR();
9459 EXPECT_PIXEL_NEAR(0, 0, expectedSum.R, expectedSum.G, 0, 255, 1);
9460 }
9461
9462 GLuint mProgram;
9463 std::vector<GLuint> mTextures;
9464 GLint mMaxVertexTextures;
9465 GLint mMaxFragmentTextures;
9466 GLint mMaxCombinedTextures;
9467 };
9468
9469 // Test rendering with the maximum vertex texture units.
TEST_P(TextureLimitsTest,MaxVertexTextures)9470 TEST_P(TextureLimitsTest, MaxVertexTextures)
9471 {
9472 compileProgramWithTextureCounts("tex", mMaxVertexTextures, mMaxVertexTextures, "tex", 0, 0);
9473 ASSERT_NE(0u, mProgram);
9474 ASSERT_GL_NO_ERROR();
9475
9476 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
9477 }
9478
9479 // Test rendering with the maximum fragment texture units.
TEST_P(TextureLimitsTest,MaxFragmentTextures)9480 TEST_P(TextureLimitsTest, MaxFragmentTextures)
9481 {
9482 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures, mMaxFragmentTextures);
9483 ASSERT_NE(0u, mProgram);
9484 ASSERT_GL_NO_ERROR();
9485
9486 testWithTextures(mMaxFragmentTextures, "tex", 0, "tex");
9487 }
9488
9489 // Test rendering with maximum combined texture units.
TEST_P(TextureLimitsTest,MaxCombinedTextures)9490 TEST_P(TextureLimitsTest, MaxCombinedTextures)
9491 {
9492 GLint vertexTextures = mMaxVertexTextures;
9493
9494 if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
9495 {
9496 vertexTextures = mMaxCombinedTextures - mMaxFragmentTextures;
9497 }
9498
9499 compileProgramWithTextureCounts("vtex", vertexTextures, vertexTextures, "ftex",
9500 mMaxFragmentTextures, mMaxFragmentTextures);
9501 ASSERT_NE(0u, mProgram);
9502 ASSERT_GL_NO_ERROR();
9503
9504 testWithTextures(vertexTextures, "vtex", mMaxFragmentTextures, "ftex");
9505 }
9506
9507 // Negative test for exceeding the number of vertex textures
TEST_P(TextureLimitsTest,ExcessiveVertexTextures)9508 TEST_P(TextureLimitsTest, ExcessiveVertexTextures)
9509 {
9510 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 1, mMaxVertexTextures + 1, "tex", 0,
9511 0);
9512 ASSERT_EQ(0u, mProgram);
9513 }
9514
9515 // Negative test for exceeding the number of fragment textures
TEST_P(TextureLimitsTest,ExcessiveFragmentTextures)9516 TEST_P(TextureLimitsTest, ExcessiveFragmentTextures)
9517 {
9518 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 1,
9519 mMaxFragmentTextures + 1);
9520 ASSERT_EQ(0u, mProgram);
9521 }
9522
9523 // Test active vertex textures under the limit, but excessive textures specified.
TEST_P(TextureLimitsTest,MaxActiveVertexTextures)9524 TEST_P(TextureLimitsTest, MaxActiveVertexTextures)
9525 {
9526 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 4, mMaxVertexTextures, "tex", 0, 0);
9527 ASSERT_NE(0u, mProgram);
9528 ASSERT_GL_NO_ERROR();
9529
9530 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
9531 }
9532
9533 // Test active fragment textures under the limit, but excessive textures specified.
TEST_P(TextureLimitsTest,MaxActiveFragmentTextures)9534 TEST_P(TextureLimitsTest, MaxActiveFragmentTextures)
9535 {
9536 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 4,
9537 mMaxFragmentTextures);
9538 ASSERT_NE(0u, mProgram);
9539 ASSERT_GL_NO_ERROR();
9540
9541 testWithTextures(0, "tex", mMaxFragmentTextures, "tex");
9542 }
9543
9544 // Negative test for pointing two sampler uniforms of different types to the same texture.
9545 // GLES 2.0.25 section 2.10.4 page 39.
TEST_P(TextureLimitsTest,TextureTypeConflict)9546 TEST_P(TextureLimitsTest, TextureTypeConflict)
9547 {
9548 constexpr char kVS[] =
9549 "attribute vec2 position;\n"
9550 "varying float color;\n"
9551 "uniform sampler2D tex2D;\n"
9552 "uniform samplerCube texCube;\n"
9553 "void main() {\n"
9554 " gl_Position = vec4(position, 0, 1);\n"
9555 " vec2 texCoord = (position * 0.5) + 0.5;\n"
9556 " color = texture2D(tex2D, texCoord).x;\n"
9557 " color += textureCube(texCube, vec3(texCoord, 0)).x;\n"
9558 "}";
9559 constexpr char kFS[] =
9560 "varying mediump float color;\n"
9561 "void main() {\n"
9562 " gl_FragColor = vec4(color, 0, 0, 1);\n"
9563 "}";
9564
9565 mProgram = CompileProgram(kVS, kFS);
9566 ASSERT_NE(0u, mProgram);
9567
9568 initTextures(1, 0);
9569
9570 glUseProgram(mProgram);
9571 GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
9572 ASSERT_NE(-1, tex2DLocation);
9573 GLint texCubeLocation = glGetUniformLocation(mProgram, "texCube");
9574 ASSERT_NE(-1, texCubeLocation);
9575
9576 glUniform1i(tex2DLocation, 0);
9577 glUniform1i(texCubeLocation, 0);
9578 ASSERT_GL_NO_ERROR();
9579
9580 drawQuad(mProgram, "position", 0.5f);
9581 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
9582 }
9583
9584 class Texture2DNorm16TestES3 : public Texture2DTestES3
9585 {
9586 protected:
Texture2DNorm16TestES3()9587 Texture2DNorm16TestES3() : Texture2DTestES3(), mTextures{0, 0, 0}, mFBO(0), mRenderbuffer(0) {}
9588
testSetUp()9589 void testSetUp() override
9590 {
9591 Texture2DTestES3::testSetUp();
9592
9593 glActiveTexture(GL_TEXTURE0);
9594 glGenTextures(3, mTextures);
9595 glGenFramebuffers(1, &mFBO);
9596 glGenRenderbuffers(1, &mRenderbuffer);
9597
9598 for (size_t textureIndex = 0; textureIndex < 3; textureIndex++)
9599 {
9600 glBindTexture(GL_TEXTURE_2D, mTextures[textureIndex]);
9601 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9602 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9603 }
9604
9605 glBindTexture(GL_TEXTURE_2D, 0);
9606
9607 ASSERT_GL_NO_ERROR();
9608 }
9609
testTearDown()9610 void testTearDown() override
9611 {
9612 glDeleteTextures(3, mTextures);
9613 glDeleteFramebuffers(1, &mFBO);
9614 glDeleteRenderbuffers(1, &mRenderbuffer);
9615
9616 Texture2DTestES3::testTearDown();
9617 }
9618
testNorm16Texture(GLint internalformat,GLenum format,GLenum type)9619 void testNorm16Texture(GLint internalformat, GLenum format, GLenum type)
9620 {
9621 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
9622
9623 GLushort pixelValue = (type == GL_SHORT) ? 0x7FFF : 0x6A35;
9624 GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
9625
9626 setUpProgram();
9627
9628 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9629 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
9630 0);
9631
9632 for (int i = 0; i < 2; ++i)
9633 {
9634 bool isSubImage = i == 1;
9635 SCOPED_TRACE("is subimage:" + std::to_string(isSubImage));
9636 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
9637 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9638
9639 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
9640 if (isSubImage)
9641 {
9642 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, nullptr);
9643 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, format, type, imageData);
9644 }
9645 else
9646 {
9647 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
9648 }
9649 EXPECT_GL_NO_ERROR();
9650
9651 drawQuad(mProgram, "position", 0.5f);
9652
9653 GLubyte expectedValue =
9654 (type == GL_SHORT) ? 0xFF : static_cast<GLubyte>(pixelValue >> 8);
9655
9656 EXPECT_PIXEL_COLOR_EQ(0, 0,
9657 SliceFormatColor(format, GLColor(expectedValue, expectedValue,
9658 expectedValue, expectedValue)));
9659 }
9660 glBindFramebuffer(GL_FRAMEBUFFER, 0);
9661
9662 ASSERT_GL_NO_ERROR();
9663 }
9664
testReadPixelsRGBAWithRangeAndPixelStoreMode(GLuint x,GLuint y,GLuint width,GLuint height,GLint packRowLength,GLint packAlignment,GLint packSkipPixels,GLint packSkipRows,GLenum type,GLColor16 color)9665 void testReadPixelsRGBAWithRangeAndPixelStoreMode(GLuint x,
9666 GLuint y,
9667 GLuint width,
9668 GLuint height,
9669 GLint packRowLength,
9670 GLint packAlignment,
9671 GLint packSkipPixels,
9672 GLint packSkipRows,
9673 GLenum type,
9674 GLColor16 color)
9675 {
9676 // PACK modes debugging
9677 GLint s = 2; // single component size in bytes, UNSIGNED_SHORT -> 2 in our case
9678 GLint n = 4; // 4 components per pixel, stands for GL_RGBA
9679
9680 GLuint l = packRowLength == 0 ? width : packRowLength;
9681 const GLint &a = packAlignment;
9682
9683 // According to
9684 // https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml
9685 GLint k = (s >= a) ? n * l : a / s * (1 + (s * n * l - 1) / a);
9686 std::size_t componentCount = n * packSkipPixels + k * (packSkipRows + height);
9687 if (static_cast<GLuint>(packRowLength) < width)
9688 {
9689 componentCount += width * n * s - k;
9690 }
9691
9692 // Populate the pixels array with random dirty value
9693 constexpr GLushort kDirtyValue = 0x1234;
9694 std::vector<GLushort> pixels(componentCount, kDirtyValue);
9695 glReadPixels(x, y, width, height, GL_RGBA, type, pixels.data());
9696
9697 EXPECT_GL_NO_ERROR();
9698
9699 GLushort *pixelRowStart = pixels.data();
9700 pixelRowStart += n * packSkipPixels + k * packSkipRows;
9701
9702 std::vector<bool> modifiedPixels(componentCount, false);
9703
9704 char errorInfo[200];
9705
9706 for (GLuint row = 0; row < height; ++row)
9707 {
9708 GLushort *curPixel = pixelRowStart;
9709 for (GLuint col = 0, len = (row == height - 1) ? width : std::min(l, width); col < len;
9710 ++col)
9711 {
9712 snprintf(errorInfo, sizeof(errorInfo),
9713 "extent: {%u, %u}, coord: (%u, %u), rowLength: %d, alignment: %d, "
9714 "skipPixels: %d, skipRows: %d\n",
9715 width, height, col, row, packRowLength, packAlignment, packSkipPixels,
9716 packSkipRows);
9717 EXPECT_EQ(color.R, curPixel[0]) << errorInfo;
9718 EXPECT_EQ(color.G, curPixel[1]) << errorInfo;
9719 EXPECT_EQ(color.B, curPixel[2]) << errorInfo;
9720 EXPECT_EQ(color.A, curPixel[3]) << errorInfo;
9721
9722 std::ptrdiff_t diff = curPixel - pixels.data();
9723 modifiedPixels[diff + 0] = true;
9724 modifiedPixels[diff + 1] = true;
9725 modifiedPixels[diff + 2] = true;
9726 modifiedPixels[diff + 3] = true;
9727
9728 curPixel += n;
9729 }
9730 pixelRowStart += k;
9731 }
9732
9733 for (std::size_t i = 0; i < modifiedPixels.size(); ++i)
9734 {
9735 if (!modifiedPixels[i])
9736 {
9737 EXPECT_EQ(pixels[i], kDirtyValue);
9738 }
9739 }
9740 }
9741
testNorm16RenderAndReadPixels(GLint internalformat,GLenum format,GLenum type)9742 void testNorm16RenderAndReadPixels(GLint internalformat, GLenum format, GLenum type)
9743 {
9744 // TODO(http://anglebug.com/40096653) Fails on Win Intel OpenGL driver
9745 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
9746 // TODO(http://anglebug.com/42262873) Fails on Win AMD OpenGL driver
9747 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
9748 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
9749
9750 GLushort pixelValue = 0x6A35;
9751 GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
9752 GLColor16 color =
9753 SliceFormatColor16(format, GLColor16(pixelValue, pixelValue, pixelValue, pixelValue));
9754 // Size of drawing viewport
9755 constexpr GLint width = 8, height = 8;
9756
9757 setUpProgram();
9758
9759 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
9760 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, type, nullptr);
9761
9762 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9763 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
9764 0);
9765
9766 glBindTexture(GL_TEXTURE_2D, mTextures[2]);
9767 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
9768 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9769 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9770
9771 EXPECT_GL_NO_ERROR();
9772
9773 drawQuad(mProgram, "position", 0.5f);
9774
9775 // ReadPixels against different width, height, pixel pack mode combinations to test
9776 // workaround of pixels rearrangement
9777
9778 // {x, y, width, height}
9779 std::vector<std::array<GLint, 4>> areas = {
9780 {0, 0, 1, 1}, {0, 0, 1, 2}, {0, 0, 2, 1}, {0, 0, 2, 2},
9781 {0, 0, 3, 2}, {0, 0, 3, 3}, {0, 0, 4, 3}, {0, 0, 4, 4},
9782
9783 {1, 3, 3, 2}, {1, 3, 3, 3}, {3, 2, 4, 3}, {3, 2, 4, 4},
9784
9785 {0, 0, 5, 6}, {2, 1, 5, 6}, {0, 0, 6, 1}, {0, 0, 7, 1},
9786 {0, 0, 7, 3}, {0, 0, 7, 8}, {1, 0, 7, 8}, {0, 0, 8, 8},
9787 };
9788
9789 // Put default settings at the last
9790 std::vector<GLint> paramsPackRowLength = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0};
9791 std::vector<GLint> paramsPackAlignment = {1, 2, 8, 4};
9792 std::vector<std::array<GLint, 2>> paramsPackSkipPixelsAndRows = {{1, 0}, {0, 1}, {1, 1},
9793 {3, 1}, {20, 20}, {0, 0}};
9794
9795 // Restore pixel pack modes later
9796 GLint restorePackAlignment;
9797 glGetIntegerv(GL_PACK_ALIGNMENT, &restorePackAlignment);
9798 GLint restorePackRowLength;
9799 glGetIntegerv(GL_PACK_ROW_LENGTH, &restorePackRowLength);
9800 GLint restorePackSkipPixels;
9801 glGetIntegerv(GL_PACK_SKIP_PIXELS, &restorePackSkipPixels);
9802 GLint restorePackSkipRows;
9803 glGetIntegerv(GL_PACK_SKIP_ROWS, &restorePackSkipRows);
9804
9805 // Variable symbols are based on:
9806 // https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml
9807 for (const auto &skipped : paramsPackSkipPixelsAndRows)
9808 {
9809 glPixelStorei(GL_PACK_SKIP_PIXELS, skipped[0]);
9810 glPixelStorei(GL_PACK_SKIP_ROWS, skipped[1]);
9811 for (GLint a : paramsPackAlignment)
9812 {
9813 glPixelStorei(GL_PACK_ALIGNMENT, a);
9814 for (GLint l : paramsPackRowLength)
9815 {
9816 glPixelStorei(GL_PACK_ROW_LENGTH, l);
9817
9818 for (const auto &area : areas)
9819 {
9820 ASSERT(area[0] + area[2] <= width);
9821 ASSERT(area[1] + area[3] <= height);
9822 testReadPixelsRGBAWithRangeAndPixelStoreMode(area[0], area[1], area[2],
9823 area[3], l, a, skipped[0],
9824 skipped[1], type, color);
9825 }
9826 }
9827 }
9828 }
9829
9830 glPixelStorei(GL_PACK_ALIGNMENT, restorePackAlignment);
9831 glPixelStorei(GL_PACK_ROW_LENGTH, restorePackRowLength);
9832 glPixelStorei(GL_PACK_SKIP_PIXELS, restorePackSkipPixels);
9833 glPixelStorei(GL_PACK_SKIP_ROWS, restorePackSkipRows);
9834
9835 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
9836 glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
9837 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
9838 mRenderbuffer);
9839 glBindRenderbuffer(GL_RENDERBUFFER, 0);
9840 EXPECT_GL_NO_ERROR();
9841
9842 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
9843 glClear(GL_COLOR_BUFFER_BIT);
9844
9845 EXPECT_PIXEL_COLOR16_NEAR(
9846 0, 0, SliceFormatColor16(format, GLColor16(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)), 0);
9847
9848 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
9849 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
9850
9851 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
9852 0);
9853 EXPECT_PIXEL_COLOR16_NEAR(
9854 0, 0, SliceFormatColor16(format, GLColor16(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)), 0);
9855
9856 ASSERT_GL_NO_ERROR();
9857
9858 glBindFramebuffer(GL_FRAMEBUFFER, 0);
9859 }
9860
9861 GLuint mTextures[3];
9862 GLuint mFBO;
9863 GLuint mRenderbuffer;
9864 };
9865
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16TextureTest)9866 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16TextureTest)
9867 {
9868 testNorm16Texture(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
9869 }
9870
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16SNORMTextureTest)9871 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16SNORMTextureTest)
9872 {
9873 testNorm16Texture(GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
9874 }
9875
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16TextureTest)9876 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16TextureTest)
9877 {
9878 testNorm16Texture(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
9879 }
9880
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16SNORMTextureTest)9881 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16SNORMTextureTest)
9882 {
9883 testNorm16Texture(GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
9884 }
9885
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGB16TextureTest)9886 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGB16TextureTest)
9887 {
9888 // (http://anglebug.com/40096662) Driver bug on some Qualcomm Adreno gpu
9889 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
9890
9891 testNorm16Texture(GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
9892 }
9893
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGB16SNORMTextureTest)9894 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGB16SNORMTextureTest)
9895 {
9896 // (http://anglebug.com/40096662) Driver bug on some Qualcomm Adreno gpu
9897 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
9898
9899 testNorm16Texture(GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
9900 }
9901
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16TextureTest)9902 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16TextureTest)
9903 {
9904 testNorm16Texture(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
9905 }
9906
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16SNORMTextureTest)9907 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16SNORMTextureTest)
9908 {
9909 testNorm16Texture(GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
9910 }
9911
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16RenderTest)9912 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16RenderTest)
9913 {
9914 // http://anglebug.com/42263714
9915 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
9916
9917 testNorm16RenderAndReadPixels(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
9918 }
9919
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16RenderTest)9920 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16RenderTest)
9921 {
9922 // http://anglebug.com/42263714
9923 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
9924
9925 testNorm16RenderAndReadPixels(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
9926 }
9927
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16RenderTest)9928 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16RenderTest)
9929 {
9930 // http://anglebug.com/42263714
9931 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
9932
9933 testNorm16RenderAndReadPixels(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
9934 }
9935
9936 class Texture2DRGTest : public Texture2DTest
9937 {
9938 protected:
Texture2DRGTest()9939 Texture2DRGTest()
9940 : Texture2DTest(), mRenderableTexture(0), mTestTexture(0), mFBO(0), mRenderbuffer(0)
9941 {}
9942
testSetUp()9943 void testSetUp() override
9944 {
9945 Texture2DTest::testSetUp();
9946
9947 glActiveTexture(GL_TEXTURE0);
9948 glGenTextures(1, &mRenderableTexture);
9949 glGenTextures(1, &mTestTexture);
9950 glGenFramebuffers(1, &mFBO);
9951 glGenRenderbuffers(1, &mRenderbuffer);
9952
9953 glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
9954 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9955 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9956 glBindTexture(GL_TEXTURE_2D, mTestTexture);
9957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9958 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9959
9960 glBindTexture(GL_TEXTURE_2D, 0);
9961
9962 setUpProgram();
9963 glUseProgram(mProgram);
9964 glUniform1i(mTexture2DUniformLocation, 0);
9965
9966 ASSERT_GL_NO_ERROR();
9967 }
9968
testTearDown()9969 void testTearDown() override
9970 {
9971 glDeleteTextures(1, &mRenderableTexture);
9972 glDeleteTextures(1, &mTestTexture);
9973 glDeleteFramebuffers(1, &mFBO);
9974 glDeleteRenderbuffers(1, &mRenderbuffer);
9975
9976 Texture2DTest::testTearDown();
9977 }
9978
setupFormatTextures(GLenum internalformat,GLenum format,GLenum type,GLvoid * imageData)9979 void setupFormatTextures(GLenum internalformat, GLenum format, GLenum type, GLvoid *imageData)
9980 {
9981 glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
9982 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9983
9984 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9985 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
9986 mRenderableTexture, 0);
9987
9988 glBindTexture(GL_TEXTURE_2D, mTestTexture);
9989 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
9990
9991 EXPECT_GL_NO_ERROR();
9992 }
9993
testRGTexture(GLColor expectedColor)9994 void testRGTexture(GLColor expectedColor)
9995 {
9996 drawQuad(mProgram, "position", 0.5f);
9997
9998 EXPECT_GL_NO_ERROR();
9999 EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, kPixelTolerance);
10000 }
10001
testRGRender(GLenum internalformat,GLenum format)10002 void testRGRender(GLenum internalformat, GLenum format)
10003 {
10004 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
10005 glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
10006 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
10007 mRenderbuffer);
10008 glBindRenderbuffer(GL_RENDERBUFFER, 0);
10009 EXPECT_GL_NO_ERROR();
10010
10011 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
10012 glClear(GL_COLOR_BUFFER_BIT);
10013
10014 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
10015
10016 ASSERT_GL_NO_ERROR();
10017 EXPECT_PIXEL_COLOR_EQ(0, 0, SliceFormatColor(format, GLColor(255u, 255u, 255u, 255u)));
10018 }
10019
10020 GLuint mRenderableTexture;
10021 GLuint mTestTexture;
10022 GLuint mFBO;
10023 GLuint mRenderbuffer;
10024 };
10025
10026 // Test unorm texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGUNormTest)10027 TEST_P(Texture2DRGTest, TextureRGUNormTest)
10028 {
10029 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
10030 // This workaround causes a GL error on Windows AMD, which is likely a driver bug.
10031 // The workaround is not intended to be enabled in this configuration so skip it.
10032 ANGLE_SKIP_TEST_IF(
10033 getEGLWindow()->isFeatureEnabled(Feature::EmulateCopyTexImage2DFromRenderbuffers) &&
10034 IsWindows() && IsAMD());
10035
10036 GLubyte pixelValue = 0xab;
10037 GLubyte imageData[] = {pixelValue, pixelValue};
10038
10039 setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_UNSIGNED_BYTE, imageData);
10040 testRGTexture(
10041 SliceFormatColor(GL_RED_EXT, GLColor(pixelValue, pixelValue, pixelValue, pixelValue)));
10042 testRGRender(GL_R8_EXT, GL_RED_EXT);
10043
10044 setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_UNSIGNED_BYTE, imageData);
10045 testRGTexture(
10046 SliceFormatColor(GL_RG_EXT, GLColor(pixelValue, pixelValue, pixelValue, pixelValue)));
10047 testRGRender(GL_RG8_EXT, GL_RG_EXT);
10048 }
10049
10050 // Test float texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGFloatTest)10051 TEST_P(Texture2DRGTest, TextureRGFloatTest)
10052 {
10053 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
10054 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10055
10056 GLfloat pixelValue = 0.54321;
10057 GLfloat imageData[] = {pixelValue, pixelValue};
10058
10059 GLubyte expectedValue = static_cast<GLubyte>(pixelValue * 255.0f);
10060 GLColor expectedColor = GLColor(expectedValue, expectedValue, expectedValue, expectedValue);
10061
10062 setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_FLOAT, imageData);
10063 testRGTexture(SliceFormatColor(GL_RED_EXT, expectedColor));
10064
10065 setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_FLOAT, imageData);
10066 testRGTexture(SliceFormatColor(GL_RG_EXT, expectedColor));
10067 }
10068
10069 // Test half-float texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGHalfFloatTest)10070 TEST_P(Texture2DRGTest, TextureRGHalfFloatTest)
10071 {
10072 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
10073 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10074
10075 GLfloat pixelValueFloat = 0.543f;
10076 GLhalf pixelValue = 0x3858;
10077 GLhalf imageData[] = {pixelValue, pixelValue};
10078
10079 GLubyte expectedValue = static_cast<GLubyte>(pixelValueFloat * 255.0f);
10080 GLColor expectedColor = GLColor(expectedValue, expectedValue, expectedValue, expectedValue);
10081
10082 setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES, imageData);
10083 testRGTexture(SliceFormatColor(GL_RED_EXT, expectedColor));
10084
10085 setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_HALF_FLOAT_OES, imageData);
10086 testRGTexture(SliceFormatColor(GL_RG_EXT, expectedColor));
10087 }
10088
10089 class Texture2DFloatTest : public Texture2DTest
10090 {
10091 protected:
Texture2DFloatTest()10092 Texture2DFloatTest()
10093 : Texture2DTest(), mRenderableTexture(0), mTestTexture(0), mFBO(0), mRenderbuffer(0)
10094 {}
10095
testSetUp()10096 void testSetUp() override
10097 {
10098 Texture2DTest::testSetUp();
10099
10100 glActiveTexture(GL_TEXTURE0);
10101 glGenTextures(1, &mRenderableTexture);
10102 glGenTextures(1, &mTestTexture);
10103 glGenFramebuffers(1, &mFBO);
10104 glGenRenderbuffers(1, &mRenderbuffer);
10105
10106 setUpProgram();
10107 glUseProgram(mProgram);
10108 glUniform1i(mTexture2DUniformLocation, 0);
10109
10110 glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
10111 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10112
10113 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
10114 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
10115 mRenderableTexture, 0);
10116
10117 ASSERT_GL_NO_ERROR();
10118 }
10119
testTearDown()10120 void testTearDown() override
10121 {
10122 glDeleteTextures(1, &mRenderableTexture);
10123 glDeleteTextures(1, &mTestTexture);
10124 glDeleteFramebuffers(1, &mFBO);
10125 glDeleteRenderbuffers(1, &mRenderbuffer);
10126
10127 Texture2DTest::testTearDown();
10128 }
10129
testFloatTextureSample(GLenum internalFormat,GLenum format,GLenum type)10130 void testFloatTextureSample(GLenum internalFormat, GLenum format, GLenum type)
10131 {
10132 constexpr GLfloat imageDataFloat[] = {
10133 0.2f,
10134 0.3f,
10135 0.4f,
10136 0.5f,
10137 };
10138 constexpr GLhalf imageDataHalf[] = {
10139 0x3266,
10140 0x34CD,
10141 0x3666,
10142 0x3800,
10143 };
10144 GLColor expectedValue;
10145 for (int i = 0; i < 4; i++)
10146 {
10147 expectedValue[i] = static_cast<GLubyte>(imageDataFloat[i] * 255.0f);
10148 }
10149
10150 const GLvoid *imageData;
10151 switch (type)
10152 {
10153 case GL_FLOAT:
10154 imageData = imageDataFloat;
10155 break;
10156 case GL_HALF_FLOAT:
10157 case GL_HALF_FLOAT_OES:
10158 imageData = imageDataHalf;
10159 break;
10160 default:
10161 imageData = nullptr;
10162 }
10163 ASSERT(imageData != nullptr);
10164
10165 glBindTexture(GL_TEXTURE_2D, mTestTexture);
10166 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, imageData);
10167
10168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10170
10171 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
10172 drawQuad(mProgram, "position", 0.5f);
10173
10174 EXPECT_GL_NO_ERROR();
10175 EXPECT_PIXEL_COLOR_NEAR(0, 0, SliceFormatColor(format, expectedValue), kPixelTolerance);
10176 }
10177
testFloatTextureLinear(GLenum internalFormat,GLenum format,GLenum type)10178 void testFloatTextureLinear(GLenum internalFormat, GLenum format, GLenum type)
10179 {
10180 int numComponents;
10181 switch (format)
10182 {
10183 case GL_RGBA:
10184 numComponents = 4;
10185 break;
10186 case GL_RGB:
10187 numComponents = 3;
10188 break;
10189 case GL_LUMINANCE_ALPHA:
10190 numComponents = 2;
10191 break;
10192 case GL_LUMINANCE:
10193 case GL_ALPHA:
10194 numComponents = 1;
10195 break;
10196 default:
10197 numComponents = 0;
10198 }
10199 ASSERT(numComponents > 0);
10200
10201 constexpr GLfloat pixelIntensitiesFloat[] = {0.0f, 1.0f, 0.0f, 1.0f};
10202 constexpr GLhalf pixelIntensitiesHalf[] = {0x0000, 0x3C00, 0x0000, 0x3C00};
10203
10204 GLfloat imageDataFloat[16];
10205 GLhalf imageDataHalf[16];
10206 for (int i = 0; i < 4; i++)
10207 {
10208 for (int c = 0; c < numComponents; c++)
10209 {
10210 imageDataFloat[i * numComponents + c] = pixelIntensitiesFloat[i];
10211 imageDataHalf[i * numComponents + c] = pixelIntensitiesHalf[i];
10212 }
10213 }
10214
10215 const GLvoid *imageData;
10216 switch (type)
10217 {
10218 case GL_FLOAT:
10219 imageData = imageDataFloat;
10220 break;
10221 case GL_HALF_FLOAT:
10222 case GL_HALF_FLOAT_OES:
10223 imageData = imageDataHalf;
10224 break;
10225 default:
10226 imageData = nullptr;
10227 }
10228 ASSERT(imageData != nullptr);
10229
10230 glBindTexture(GL_TEXTURE_2D, mTestTexture);
10231 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 2, 2, 0, format, type, imageData);
10232
10233 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10235
10236 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
10237 drawQuad(mProgram, "position", 0.5f);
10238
10239 EXPECT_GL_NO_ERROR();
10240 // Source texture contains 2 black pixels and 2 white pixels, we sample in the center so we
10241 // should expect the final value to be gray (halfway in-between)
10242 EXPECT_PIXEL_COLOR_NEAR(0, 0, SliceFormatColor(format, GLColor(127u, 127u, 127u, 127u)),
10243 kPixelTolerance);
10244 }
10245
performFloatTextureRender(GLenum internalFormat,GLenum renderBufferFormat,GLenum format,GLenum type)10246 bool performFloatTextureRender(GLenum internalFormat,
10247 GLenum renderBufferFormat,
10248 GLenum format,
10249 GLenum type)
10250 {
10251 glBindTexture(GL_TEXTURE_2D, mTestTexture);
10252 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, nullptr);
10253 glBindTexture(GL_TEXTURE_2D, 0);
10254
10255 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
10256 glRenderbufferStorage(GL_RENDERBUFFER, renderBufferFormat, 1, 1);
10257 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
10258 mRenderbuffer);
10259 glBindRenderbuffer(GL_RENDERBUFFER, 0);
10260 EXPECT_GL_NO_ERROR();
10261
10262 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
10263 {
10264 return false;
10265 }
10266
10267 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
10268
10269 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
10270 glClear(GL_COLOR_BUFFER_BIT);
10271
10272 EXPECT_GL_NO_ERROR();
10273 return true;
10274 }
10275
10276 GLuint mRenderableTexture;
10277 GLuint mTestTexture;
10278 GLuint mFBO;
10279 GLuint mRenderbuffer;
10280 };
10281
10282 class Texture2DFloatTestES3 : public Texture2DFloatTest
10283 {
10284 protected:
testFloatTextureRender(GLenum internalFormat,GLenum format,GLenum type)10285 void testFloatTextureRender(GLenum internalFormat, GLenum format, GLenum type)
10286 {
10287 bool framebufferComplete =
10288 performFloatTextureRender(internalFormat, internalFormat, format, type);
10289 EXPECT_TRUE(framebufferComplete);
10290 EXPECT_PIXEL_COLOR32F_NEAR(0, 0,
10291 SliceFormatColor32F(format, GLColor32F(1.0f, 1.0f, 1.0f, 1.0f)),
10292 kPixelTolerance32F);
10293 }
10294 };
10295
10296 class Texture2DFloatTestES2 : public Texture2DFloatTest
10297 {
10298 protected:
checkFloatTextureRender(GLenum renderBufferFormat,GLenum format,GLenum type)10299 bool checkFloatTextureRender(GLenum renderBufferFormat, GLenum format, GLenum type)
10300 {
10301 bool framebufferComplete =
10302 performFloatTextureRender(format, renderBufferFormat, format, type);
10303
10304 if (!framebufferComplete)
10305 {
10306 return false;
10307 }
10308
10309 EXPECT_PIXEL_COLOR32F_NEAR(0, 0,
10310 SliceFormatColor32F(format, GLColor32F(1.0f, 1.0f, 1.0f, 1.0f)),
10311 kPixelTolerance32F);
10312 return true;
10313 }
10314 };
10315
10316 // Test texture sampling for ES3 float texture formats
TEST_P(Texture2DFloatTestES3,TextureFloatSampleBasicTest)10317 TEST_P(Texture2DFloatTestES3, TextureFloatSampleBasicTest)
10318 {
10319 testFloatTextureSample(GL_RGBA32F, GL_RGBA, GL_FLOAT);
10320 testFloatTextureSample(GL_RGB32F, GL_RGB, GL_FLOAT);
10321 }
10322
10323 // Test texture sampling for ES2 float texture formats
TEST_P(Texture2DFloatTestES2,TextureFloatSampleBasicTest)10324 TEST_P(Texture2DFloatTestES2, TextureFloatSampleBasicTest)
10325 {
10326 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10327 testFloatTextureSample(GL_RGBA, GL_RGBA, GL_FLOAT);
10328 testFloatTextureSample(GL_RGB, GL_RGB, GL_FLOAT);
10329 }
10330
10331 // Test texture sampling for ES3 half float texture formats
TEST_P(Texture2DFloatTestES3,TextureHalfFloatSampleBasicTest)10332 TEST_P(Texture2DFloatTestES3, TextureHalfFloatSampleBasicTest)
10333 {
10334 testFloatTextureSample(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
10335 testFloatTextureSample(GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
10336 }
10337
10338 // Test texture sampling for ES2 half float texture formats
TEST_P(Texture2DFloatTestES2,TextureHalfFloatSampleBasicTest)10339 TEST_P(Texture2DFloatTestES2, TextureHalfFloatSampleBasicTest)
10340 {
10341 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10342 testFloatTextureSample(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES);
10343 testFloatTextureSample(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES);
10344 }
10345
10346 // Test texture sampling for legacy GLES 2.0 float texture formats in ES3
TEST_P(Texture2DFloatTestES3,TextureFloatSampleLegacyTest)10347 TEST_P(Texture2DFloatTestES3, TextureFloatSampleLegacyTest)
10348 {
10349 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10350
10351 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10352 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10353 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10354
10355 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10356 {
10357 testFloatTextureSample(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT);
10358 testFloatTextureSample(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT);
10359 testFloatTextureSample(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT);
10360 }
10361 }
10362
10363 // Test texture sampling for legacy GLES 2.0 float texture formats in ES2
TEST_P(Texture2DFloatTestES2,TextureFloatSampleLegacyTest)10364 TEST_P(Texture2DFloatTestES2, TextureFloatSampleLegacyTest)
10365 {
10366 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10367
10368 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10369 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10370 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10371 }
10372
10373 // Test texture sampling for legacy GLES 2.0 half float texture formats in ES3
TEST_P(Texture2DFloatTestES3,TextureHalfFloatSampleLegacyTest)10374 TEST_P(Texture2DFloatTestES3, TextureHalfFloatSampleLegacyTest)
10375 {
10376 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10377
10378 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10379 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10380 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10381
10382 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10383 {
10384 testFloatTextureSample(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT);
10385 testFloatTextureSample(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT);
10386 testFloatTextureSample(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT);
10387 }
10388 }
10389 // Test texture sampling for legacy GLES 2.0 half float texture formats in ES2
TEST_P(Texture2DFloatTestES2,TextureHalfFloatSampleLegacyTest)10390 TEST_P(Texture2DFloatTestES2, TextureHalfFloatSampleLegacyTest)
10391 {
10392 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10393
10394 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10395 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10396 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10397 }
10398
10399 // Test linear sampling for ES3 32F formats
TEST_P(Texture2DFloatTestES3,TextureFloatLinearTest)10400 TEST_P(Texture2DFloatTestES3, TextureFloatLinearTest)
10401 {
10402 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
10403 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10404
10405 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10406
10407 testFloatTextureLinear(GL_RGBA32F, GL_RGBA, GL_FLOAT);
10408 testFloatTextureLinear(GL_RGB32F, GL_RGB, GL_FLOAT);
10409 }
10410 // Test linear sampling for ES2 32F formats
TEST_P(Texture2DFloatTestES2,TextureFloatLinearTest)10411 TEST_P(Texture2DFloatTestES2, TextureFloatLinearTest)
10412 {
10413 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
10414 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10415
10416 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10417
10418 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10419
10420 testFloatTextureLinear(GL_RGBA, GL_RGBA, GL_FLOAT);
10421 }
10422
10423 // Test linear sampling for ES3 16F formats
TEST_P(Texture2DFloatTestES3,TextureHalfFloatLinearTest)10424 TEST_P(Texture2DFloatTestES3, TextureHalfFloatLinearTest)
10425 {
10426 // Half float formats must be linearly filterable in GLES 3.0 core
10427 testFloatTextureLinear(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
10428 testFloatTextureLinear(GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
10429 }
10430 // Test linear sampling for ES2 16F formats
TEST_P(Texture2DFloatTestES2,TextureHalfFloatLinearTest)10431 TEST_P(Texture2DFloatTestES2, TextureHalfFloatLinearTest)
10432 {
10433 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
10434 testFloatTextureLinear(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES);
10435 testFloatTextureLinear(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES);
10436 }
10437
10438 // Test linear sampling for legacy GLES 2.0 32F formats in ES3
TEST_P(Texture2DFloatTestES3,TextureFloatLinearLegacyTest)10439 TEST_P(Texture2DFloatTestES3, TextureFloatLinearLegacyTest)
10440 {
10441 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
10442 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10443
10444 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10445 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10446
10447 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10448 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10449 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10450
10451 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10452 {
10453 testFloatTextureLinear(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT);
10454 testFloatTextureLinear(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT);
10455 testFloatTextureLinear(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT);
10456 }
10457 }
10458 // Test linear sampling for legacy GLES 2.0 32F formats in ES2
TEST_P(Texture2DFloatTestES2,TextureFloatLinearLegacyTest)10459 TEST_P(Texture2DFloatTestES2, TextureFloatLinearLegacyTest)
10460 {
10461 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
10462 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10463
10464 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10465 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10466
10467 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10468 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10469 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10470 }
10471
10472 // Test linear sampling for legacy GLES 2.0 16F formats in ES3
TEST_P(Texture2DFloatTestES3,TextureHalfFloatLinearLegacyTest)10473 TEST_P(Texture2DFloatTestES3, TextureHalfFloatLinearLegacyTest)
10474 {
10475 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10476 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
10477
10478 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10479 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10480 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10481
10482 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10483 {
10484 testFloatTextureLinear(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT);
10485 testFloatTextureLinear(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT);
10486 testFloatTextureLinear(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT);
10487 }
10488 }
10489 // Test linear sampling for legacy GLES 2.0 16F formats in ES2
TEST_P(Texture2DFloatTestES2,TextureHalfFloatLinearLegacyTest)10490 TEST_P(Texture2DFloatTestES2, TextureHalfFloatLinearLegacyTest)
10491 {
10492 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10493 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
10494
10495 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10496 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10497 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10498 }
10499
10500 // Test color-renderability for ES3 float and half float textures
TEST_P(Texture2DFloatTestES3,TextureFloatRenderTest)10501 TEST_P(Texture2DFloatTestES3, TextureFloatRenderTest)
10502 {
10503 // http://anglebug.com/40096654
10504 ANGLE_SKIP_TEST_IF(IsD3D9());
10505 // EXT_color_buffer_float covers float, half float, and 11-11-10 float formats
10506 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
10507
10508 testFloatTextureRender(GL_R32F, GL_RED, GL_FLOAT);
10509 testFloatTextureRender(GL_RG32F, GL_RG, GL_FLOAT);
10510 testFloatTextureRender(GL_RGBA32F, GL_RGBA, GL_FLOAT);
10511
10512 testFloatTextureRender(GL_R16F, GL_RED, GL_HALF_FLOAT);
10513 testFloatTextureRender(GL_RG16F, GL_RG, GL_HALF_FLOAT);
10514 testFloatTextureRender(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
10515
10516 testFloatTextureRender(GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT);
10517 }
10518
10519 // Test color-renderability for ES2 half float textures
TEST_P(Texture2DFloatTestES2,TextureFloatRenderTest)10520 TEST_P(Texture2DFloatTestES2, TextureFloatRenderTest)
10521 {
10522 // EXT_color_buffer_half_float requires at least one format to be renderable, but does not
10523 // require a specific one
10524 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
10525 // https://crbug.com/1003971
10526 ANGLE_SKIP_TEST_IF(IsOzone());
10527 // http://anglebug.com/40096654
10528 ANGLE_SKIP_TEST_IF(IsD3D9());
10529
10530 bool atLeastOneSupported = false;
10531
10532 if (IsGLExtensionEnabled("GL_OES_texture_half_float") ||
10533 IsGLExtensionEnabled("GL_OES_texture_half_float"))
10534 {
10535 atLeastOneSupported |= checkFloatTextureRender(GL_R16F_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES);
10536 atLeastOneSupported |= checkFloatTextureRender(GL_RG16F_EXT, GL_RG_EXT, GL_HALF_FLOAT_OES);
10537 }
10538 if (IsGLExtensionEnabled("GL_OES_texture_half_float"))
10539 {
10540 atLeastOneSupported |= checkFloatTextureRender(GL_RGB16F_EXT, GL_RGB, GL_HALF_FLOAT_OES);
10541
10542 // If OES_texture_half_float is supported, then RGBA half float textures must be renderable
10543 bool rgbaSupported = checkFloatTextureRender(GL_RGBA16F_EXT, GL_RGBA, GL_HALF_FLOAT_OES);
10544 EXPECT_TRUE(rgbaSupported);
10545 atLeastOneSupported |= rgbaSupported;
10546 }
10547
10548 EXPECT_TRUE(atLeastOneSupported);
10549 }
10550
10551 // Test that UNPACK_SKIP_IMAGES doesn't have an effect on 2D texture uploads.
10552 // GLES 3.0.4 section 3.8.3.
TEST_P(Texture2DTestES3,UnpackSkipImages2D)10553 TEST_P(Texture2DTestES3, UnpackSkipImages2D)
10554 {
10555 // Crashes on Nexus 5X due to a driver bug. http://anglebug.com/42260424
10556 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
10557
10558 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10559 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10560 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10561 ASSERT_GL_NO_ERROR();
10562
10563 // SKIP_IMAGES should not have an effect on uploading 2D textures
10564 glPixelStorei(GL_UNPACK_SKIP_IMAGES, 1000);
10565 ASSERT_GL_NO_ERROR();
10566
10567 std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
10568
10569 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10570 pixelsGreen.data());
10571 ASSERT_GL_NO_ERROR();
10572
10573 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE,
10574 pixelsGreen.data());
10575 ASSERT_GL_NO_ERROR();
10576
10577 glUseProgram(mProgram);
10578 drawQuad(mProgram, "position", 0.5f);
10579 ASSERT_GL_NO_ERROR();
10580
10581 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10582 }
10583
10584 // Test that skip defined in unpack parameters is taken into account when determining whether
10585 // unpacking source extends outside unpack buffer bounds.
TEST_P(Texture2DTestES3,UnpackSkipPixelsOutOfBounds)10586 TEST_P(Texture2DTestES3, UnpackSkipPixelsOutOfBounds)
10587 {
10588 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10589 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10590 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10591 ASSERT_GL_NO_ERROR();
10592
10593 GLBuffer buf;
10594 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
10595 std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
10596 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
10597 GL_DYNAMIC_COPY);
10598 ASSERT_GL_NO_ERROR();
10599
10600 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10601 ASSERT_GL_NO_ERROR();
10602
10603 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 1);
10604 ASSERT_GL_NO_ERROR();
10605
10606 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10607 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
10608
10609 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
10610 glPixelStorei(GL_UNPACK_SKIP_ROWS, 1);
10611 ASSERT_GL_NO_ERROR();
10612
10613 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10614 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
10615 }
10616
10617 // Test unpacking to texture from a buffer with a compatible format but different type.
10618 // Compatible formats can be found in "Table 8.2: Valid combinations of format, type, and sized
10619 // internal format." of the OpenGL ES 3.2 spec.
TEST_P(Texture2DTestES3,UnpackCompatibleFormatButDifferentType)10620 TEST_P(Texture2DTestES3, UnpackCompatibleFormatButDifferentType)
10621 {
10622 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10623 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10624 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10625 ASSERT_GL_NO_ERROR();
10626
10627 // Create texture with GL_RGBA4 format and fill with red
10628 std::vector<GLColor> pixelsRed(128u * 128u, GLColor::red);
10629 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10630 pixelsRed.data());
10631 ASSERT_GL_NO_ERROR();
10632
10633 // Call glTexSubImage2D with incompatible format and expect an error
10634 std::array<GLubyte, 2> rgColor = {255, 255};
10635 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RG, GL_UNSIGNED_BYTE, rgColor.data());
10636 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
10637
10638 glUseProgram(mProgram);
10639 drawQuad(mProgram, "position", 0.5f);
10640 ASSERT_GL_NO_ERROR();
10641 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10642
10643 // Create unpack buffer with GL_RGBA8
10644 GLBuffer buf;
10645 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
10646 std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
10647 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
10648 GL_DYNAMIC_COPY);
10649 ASSERT_GL_NO_ERROR();
10650
10651 // Unpack GL_RGBA8 buffer data to GL_RGBA4 texture
10652 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10653 ASSERT_GL_NO_ERROR();
10654
10655 // Validate that the data was unpacked correctly
10656 glUseProgram(mProgram);
10657 drawQuad(mProgram, "position", 0.5f);
10658 ASSERT_GL_NO_ERROR();
10659
10660 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10661 }
10662
10663 // Test that unpacking rows that overlap in a pixel unpack buffer works as expected.
TEST_P(Texture2DTestES3,UnpackOverlappingRowsFromUnpackBuffer)10664 TEST_P(Texture2DTestES3, UnpackOverlappingRowsFromUnpackBuffer)
10665 {
10666 ANGLE_SKIP_TEST_IF(IsD3D11());
10667
10668 // Incorrect rendering results seen on OSX AMD.
10669 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac() && IsAMD());
10670
10671 const GLuint width = 8u;
10672 const GLuint height = 8u;
10673 const GLuint unpackRowLength = 5u;
10674 const GLuint unpackSkipPixels = 1u;
10675
10676 setWindowWidth(width);
10677 setWindowHeight(height);
10678
10679 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10680 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10681 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10682 ASSERT_GL_NO_ERROR();
10683
10684 GLBuffer buf;
10685 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
10686 std::vector<GLColor> pixelsGreen((height - 1u) * unpackRowLength + width + unpackSkipPixels,
10687 GLColor::green);
10688
10689 for (GLuint skippedPixel = 0u; skippedPixel < unpackSkipPixels; ++skippedPixel)
10690 {
10691 pixelsGreen[skippedPixel] = GLColor(255, 0, 0, 255);
10692 }
10693
10694 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
10695 GL_DYNAMIC_COPY);
10696 ASSERT_GL_NO_ERROR();
10697
10698 glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackRowLength);
10699 glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels);
10700 ASSERT_GL_NO_ERROR();
10701
10702 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10703 ASSERT_GL_NO_ERROR();
10704
10705 glUseProgram(mProgram);
10706 drawQuad(mProgram, "position", 0.5f);
10707 ASSERT_GL_NO_ERROR();
10708
10709 GLuint windowPixelCount = getWindowWidth() * getWindowHeight();
10710 std::vector<GLColor> actual(windowPixelCount, GLColor::black);
10711 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10712 actual.data());
10713 std::vector<GLColor> expected(windowPixelCount, GLColor::green);
10714 EXPECT_EQ(expected, actual);
10715 }
10716
10717 template <typename T>
UNorm(double value)10718 T UNorm(double value)
10719 {
10720 return static_cast<T>(value * static_cast<double>(std::numeric_limits<T>::max()));
10721 }
10722
10723 // Test rendering a depth texture with mipmaps.
TEST_P(Texture2DTestES3,DepthTexturesWithMipmaps)10724 TEST_P(Texture2DTestES3, DepthTexturesWithMipmaps)
10725 {
10726 // TODO(cwallez) this is failing on Intel Win7 OpenGL.
10727 // TODO(zmo) this is faling on Win Intel HD 530 Debug.
10728 // http://anglebug.com/42260646
10729 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
10730
10731 // Seems to fail on AMD D3D11. Possibly driver bug. http://anglebug.com/40096577
10732 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsD3D11());
10733
10734 // TODO(cnorthrop): Also failing on Vulkan/Windows/AMD. http://anglebug.com/42262590
10735 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
10736
10737 const int size = getWindowWidth();
10738
10739 auto dim = [size](int level) { return size >> level; };
10740 int levels = gl::log2(size);
10741
10742 glActiveTexture(GL_TEXTURE0);
10743 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10744 glTexStorage2D(GL_TEXTURE_2D, levels, GL_DEPTH_COMPONENT24, size, size);
10745 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10746 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10747 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
10748 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
10749 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10750 ASSERT_GL_NO_ERROR();
10751
10752 glUseProgram(mProgram);
10753 glUniform1i(mTexture2DUniformLocation, 0);
10754
10755 std::vector<unsigned char> expected;
10756
10757 for (int level = 0; level < levels; ++level)
10758 {
10759 double value = (static_cast<double>(level) / static_cast<double>(levels - 1));
10760 expected.push_back(UNorm<unsigned char>(value));
10761
10762 int levelDim = dim(level);
10763
10764 ASSERT_GT(levelDim, 0);
10765
10766 std::vector<unsigned int> initData(levelDim * levelDim, UNorm<unsigned int>(value));
10767 glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, levelDim, levelDim, GL_DEPTH_COMPONENT,
10768 GL_UNSIGNED_INT, initData.data());
10769 }
10770 ASSERT_GL_NO_ERROR();
10771
10772 for (int level = 0; level < levels; ++level)
10773 {
10774 glViewport(0, 0, dim(level), dim(level));
10775 drawQuad(mProgram, "position", 0.5f);
10776 GLColor actual = ReadColor(0, 0);
10777 EXPECT_NEAR(expected[level], actual.R, 10u);
10778 }
10779
10780 ASSERT_GL_NO_ERROR();
10781 }
10782
10783 class Texture2DDepthTest : public Texture2DTest
10784 {
10785 protected:
Texture2DDepthTest()10786 Texture2DDepthTest() : Texture2DTest() {}
10787
getVertexShaderSource()10788 const char *getVertexShaderSource() override
10789 {
10790 return "attribute vec4 vPosition;\n"
10791 "void main() {\n"
10792 " gl_Position = vPosition;\n"
10793 "}\n";
10794 }
10795
getFragmentShaderSource()10796 const char *getFragmentShaderSource() override
10797 {
10798 return "precision mediump float;\n"
10799 "uniform sampler2D ShadowMap;"
10800 "void main() {\n"
10801 " vec4 shadow_value = texture2D(ShadowMap, vec2(0.5, 0.5));"
10802 " if (shadow_value.x == shadow_value.z && shadow_value.x != 0.0) {"
10803 " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);"
10804 " } else {"
10805 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
10806 " }"
10807 "}\n";
10808 }
10809
checkTexImageFormatSupport(GLenum format,GLenum internalformat,GLenum type)10810 bool checkTexImageFormatSupport(GLenum format, GLenum internalformat, GLenum type)
10811 {
10812 EXPECT_GL_NO_ERROR();
10813
10814 GLTexture tex;
10815 glBindTexture(GL_TEXTURE_2D, tex);
10816 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, type, nullptr);
10817
10818 return (glGetError() == GL_NO_ERROR);
10819 }
10820
testBehavior(bool useSizedComponent)10821 void testBehavior(bool useSizedComponent)
10822 {
10823 int w = getWindowWidth();
10824 int h = getWindowHeight();
10825 GLuint format = GL_DEPTH_COMPONENT;
10826 GLuint internalFormat = GL_DEPTH_COMPONENT;
10827
10828 if (useSizedComponent)
10829 {
10830 internalFormat = GL_DEPTH_COMPONENT24;
10831 }
10832
10833 GLFramebuffer fbo;
10834 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10835 ASSERT_GL_NO_ERROR();
10836
10837 GLTexture depthTexture;
10838 glBindTexture(GL_TEXTURE_2D, depthTexture);
10839 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10840 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10841 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
10842 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
10843
10844 TexCoordDrawTest::setUpProgram();
10845 GLint shadowMapLocation = glGetUniformLocation(mProgram, "ShadowMap");
10846 ASSERT_NE(-1, shadowMapLocation);
10847
10848 GLint positionLocation = glGetAttribLocation(mProgram, "vPosition");
10849 ASSERT_NE(-1, positionLocation);
10850
10851 ANGLE_SKIP_TEST_IF(!checkTexImageFormatSupport(format, internalFormat, GL_UNSIGNED_INT));
10852 glBindTexture(GL_TEXTURE_2D, depthTexture);
10853 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_INT, nullptr);
10854 ASSERT_GL_NO_ERROR();
10855
10856 // try adding a color buffer.
10857 GLTexture colorTex;
10858 glBindTexture(GL_TEXTURE_2D, colorTex);
10859 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
10860 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
10861 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10862 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10863 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10864 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
10865 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
10866 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10867 ASSERT_GL_NO_ERROR();
10868
10869 glViewport(0, 0, w, h);
10870 // Fill depthTexture with 0.75
10871 glClearDepthf(0.75);
10872 glClear(GL_DEPTH_BUFFER_BIT);
10873
10874 // Revert to normal framebuffer to test depth shader
10875 glBindFramebuffer(GL_FRAMEBUFFER, 0);
10876 glViewport(0, 0, w, h);
10877 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
10878 glClearDepthf(0.0f);
10879 ASSERT_GL_NO_ERROR();
10880
10881 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
10882 ASSERT_GL_NO_ERROR();
10883
10884 glActiveTexture(GL_TEXTURE0);
10885 glBindTexture(GL_TEXTURE_2D, depthTexture);
10886
10887 glUseProgram(mProgram);
10888 ASSERT_GL_NO_ERROR();
10889
10890 glUniform1i(shadowMapLocation, 0);
10891
10892 const GLfloat gTriangleVertices[] = {-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f};
10893
10894 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
10895 ASSERT_GL_NO_ERROR();
10896 glEnableVertexAttribArray(positionLocation);
10897 ASSERT_GL_NO_ERROR();
10898 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10899 ASSERT_GL_NO_ERROR();
10900
10901 GLuint pixels[1];
10902 glReadPixels(w / 2, h / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
10903 ASSERT_GL_NO_ERROR();
10904
10905 // The GLES 3.x spec says that the depth texture sample can be found in the RED component.
10906 // However, the OES_depth_texture indicates that the depth value is treated as luminance and
10907 // is in all the color components. Multiple implementations implement a workaround that
10908 // follows the OES_depth_texture behavior if the internalformat given at glTexImage2D was a
10909 // unsized format (e.g. DEPTH_COMPONENT) and the GLES 3.x behavior if it was a sized
10910 // internalformat such as GL_DEPTH_COMPONENT24. The shader will write out a different color
10911 // depending on if it sees the texture sample in only the RED component.
10912 if (useSizedComponent)
10913 {
10914 ASSERT_NE(pixels[0], 0xff0000ff);
10915 }
10916 else
10917 {
10918 ASSERT_EQ(pixels[0], 0xff0000ff);
10919 }
10920
10921 glBindFramebuffer(GL_FRAMEBUFFER, 0);
10922 glDeleteProgram(mProgram);
10923 }
10924 };
10925
10926 // Test depth texture compatibility with OES_depth_texture. Uses unsized internal format.
TEST_P(Texture2DDepthTest,DepthTextureES2Compatibility)10927 TEST_P(Texture2DDepthTest, DepthTextureES2Compatibility)
10928 {
10929 ANGLE_SKIP_TEST_IF(IsD3D11());
10930 ANGLE_SKIP_TEST_IF(IsIntel() && IsD3D9());
10931 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_depth_texture") &&
10932 !IsGLExtensionEnabled("GL_OES_depth_texture"));
10933 // http://anglebug.com/40096654
10934 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
10935 ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
10936
10937 // When the depth texture is specified with unsized internalformat implementations follow
10938 // OES_depth_texture behavior. Otherwise they follow GLES 3.0 behavior.
10939 testBehavior(false);
10940 }
10941
10942 // Test depth texture compatibility with GLES3 using sized internalformat.
TEST_P(Texture2DDepthTest,DepthTextureES3Compatibility)10943 TEST_P(Texture2DDepthTest, DepthTextureES3Compatibility)
10944 {
10945 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
10946
10947 // http://anglebug.com/42263796
10948 ANGLE_SKIP_TEST_IF(IsMetal() && !IsMetalTextureSwizzleAvailable());
10949
10950 testBehavior(true);
10951 }
10952
10953 // Tests unpacking into the unsized GL_ALPHA format.
TEST_P(Texture2DTestES3,UnsizedAlphaUnpackBuffer)10954 TEST_P(Texture2DTestES3, UnsizedAlphaUnpackBuffer)
10955 {
10956 // Initialize the texure.
10957 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10958 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, getWindowWidth(), getWindowHeight(), 0, GL_ALPHA,
10959 GL_UNSIGNED_BYTE, nullptr);
10960 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10961 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10962
10963 std::vector<GLubyte> bufferData(getWindowWidth() * getWindowHeight(), 127);
10964
10965 // Pull in the color data from the unpack buffer.
10966 GLBuffer unpackBuffer;
10967 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10968 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
10969 glBufferData(GL_PIXEL_UNPACK_BUFFER, getWindowWidth() * getWindowHeight(), bufferData.data(),
10970 GL_STATIC_DRAW);
10971
10972 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_ALPHA,
10973 GL_UNSIGNED_BYTE, nullptr);
10974
10975 // Clear to a weird color to make sure we're drawing something.
10976 glClearColor(0.5f, 0.8f, 1.0f, 0.2f);
10977 glClear(GL_COLOR_BUFFER_BIT);
10978
10979 // Draw with the alpha texture and verify.
10980 drawQuad(mProgram, "position", 0.5f);
10981
10982 ASSERT_GL_NO_ERROR();
10983 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 127, 1);
10984 }
10985
10986 // Ensure stale unpack data doesn't propagate in D3D11.
TEST_P(Texture2DTestES3,StaleUnpackData)10987 TEST_P(Texture2DTestES3, StaleUnpackData)
10988 {
10989 // Init unpack buffer.
10990 GLsizei pixelCount = getWindowWidth() * getWindowHeight() / 2;
10991 std::vector<GLColor> pixels(pixelCount, GLColor::red);
10992
10993 GLBuffer unpackBuffer;
10994 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10995 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
10996 GLsizei bufferSize = pixelCount * sizeof(GLColor);
10997 glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize, pixels.data(), GL_STATIC_DRAW);
10998
10999 // Create from unpack buffer.
11000 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11001 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth() / 2, getWindowHeight() / 2, 0,
11002 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11003 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11004 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11005
11006 drawQuad(mProgram, "position", 0.5f);
11007
11008 ASSERT_GL_NO_ERROR();
11009 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11010
11011 // Fill unpack with green, recreating buffer.
11012 pixels.assign(getWindowWidth() * getWindowHeight(), GLColor::green);
11013 GLsizei size2 = getWindowWidth() * getWindowHeight() * sizeof(GLColor);
11014 glBufferData(GL_PIXEL_UNPACK_BUFFER, size2, pixels.data(), GL_STATIC_DRAW);
11015
11016 // Reinit texture with green.
11017 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
11018 GL_UNSIGNED_BYTE, nullptr);
11019
11020 drawQuad(mProgram, "position", 0.5f);
11021
11022 ASSERT_GL_NO_ERROR();
11023 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11024 }
11025
11026 // Ensure that texture parameters passed as floats that are converted to ints are rounded before
11027 // validating they are less than 0.
TEST_P(Texture2DTestES3,TextureBaseMaxLevelRoundingValidation)11028 TEST_P(Texture2DTestES3, TextureBaseMaxLevelRoundingValidation)
11029 {
11030 GLTexture texture;
11031 glBindTexture(GL_TEXTURE_2D, texture);
11032
11033 // Use a negative number that will round to zero when converted to an integer
11034 // According to the spec(2.3.1 Data Conversion For State - Setting Commands):
11035 // "Validation of values performed by state-setting commands is performed after conversion,
11036 // unless specified otherwise for a specific command."
11037 GLfloat param = -7.30157126e-07f;
11038 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, param);
11039 EXPECT_GL_NO_ERROR();
11040
11041 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, param);
11042 EXPECT_GL_NO_ERROR();
11043 }
11044
11045 // This test covers a D3D format redefinition bug for 3D textures. The base level format was not
11046 // being properly checked, and the texture storage of the previous texture format was persisting.
11047 // This would result in an ASSERT in debug and incorrect rendering in release.
11048 // See http://anglebug.com/42260575 and WebGL 2 test conformance2/misc/views-with-offsets.html.
TEST_P(Texture3DTestES3,FormatRedefinitionBug)11049 TEST_P(Texture3DTestES3, FormatRedefinitionBug)
11050 {
11051 GLTexture tex;
11052 glBindTexture(GL_TEXTURE_3D, tex);
11053 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11054
11055 GLFramebuffer framebuffer;
11056 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
11057 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
11058
11059 glCheckFramebufferStatus(GL_FRAMEBUFFER);
11060
11061 std::vector<uint8_t> pixelData(100, 0);
11062
11063 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB565, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, nullptr);
11064 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
11065 pixelData.data());
11066
11067 ASSERT_GL_NO_ERROR();
11068 }
11069
11070 // Test glTexSubImage using PBO to 3D texture that expose the regression bug
11071 // https://issuetracker.google.com/170657065
TEST_P(Texture3DTestES3,TexSubImageWithPBO)11072 TEST_P(Texture3DTestES3, TexSubImageWithPBO)
11073 {
11074 GLTexture tex;
11075
11076 GLuint pbo;
11077 glGenBuffers(1, &pbo);
11078 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
11079 std::vector<uint8_t> pixelData(128 * 128 * 8 * 4, 0x1f);
11080 glBufferData(GL_PIXEL_UNPACK_BUFFER, 128 * 128 * 8 * 4, pixelData.data(), GL_STATIC_DRAW);
11081
11082 glBindTexture(GL_TEXTURE_3D, tex);
11083 glTexStorage3D(GL_TEXTURE_3D, 8, GL_RGBA8, 128, 128, 8);
11084 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
11085 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11086 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 128, 128, 8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11087 glTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 64, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11088 glTexSubImage3D(GL_TEXTURE_3D, 2, 0, 0, 0, 32, 32, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11089 glTexSubImage3D(GL_TEXTURE_3D, 3, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11090 glTexSubImage3D(GL_TEXTURE_3D, 4, 0, 0, 0, 8, 8, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11091 glTexSubImage3D(GL_TEXTURE_3D, 5, 0, 0, 0, 4, 4, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11092 glTexSubImage3D(GL_TEXTURE_3D, 6, 0, 0, 0, 2, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11093 glTexSubImage3D(GL_TEXTURE_3D, 7, 0, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11094
11095 drawQuad(mProgram, "position", 0.5f);
11096 ASSERT_GL_NO_ERROR();
11097
11098 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 128, 128, 8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11099 glTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 64, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11100 glTexSubImage3D(GL_TEXTURE_3D, 2, 0, 0, 0, 32, 32, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11101 ASSERT_GL_NO_ERROR();
11102
11103 drawQuad(mProgram, "position", 0.5f);
11104 ASSERT_GL_NO_ERROR();
11105 }
11106
11107 // Test basic pixel unpack buffer OOB checks when uploading to a 2D or 3D texture
TEST_P(Texture3DTestES3,BasicUnpackBufferOOB)11108 TEST_P(Texture3DTestES3, BasicUnpackBufferOOB)
11109 {
11110 // 2D tests
11111 {
11112 GLTexture tex;
11113 glBindTexture(GL_TEXTURE_2D, tex);
11114
11115 GLBuffer pbo;
11116 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
11117
11118 // Test OOB
11119 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 - 1, nullptr, GL_STATIC_DRAW);
11120 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11121 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
11122
11123 // Test OOB
11124 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2, nullptr, GL_STATIC_DRAW);
11125 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11126 ASSERT_GL_NO_ERROR();
11127 }
11128
11129 // 3D tests
11130 {
11131 GLTexture tex;
11132 glBindTexture(GL_TEXTURE_3D, tex);
11133
11134 GLBuffer pbo;
11135 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
11136
11137 // Test OOB
11138 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2 - 1, nullptr,
11139 GL_STATIC_DRAW);
11140 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11141 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
11142
11143 // Test OOB
11144 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2, nullptr, GL_STATIC_DRAW);
11145 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11146 ASSERT_GL_NO_ERROR();
11147 }
11148 }
11149
11150 // Tests behaviour with a single texture and multiple sampler objects.
TEST_P(Texture2DTestES3,SingleTextureMultipleSamplers)11151 TEST_P(Texture2DTestES3, SingleTextureMultipleSamplers)
11152 {
11153 GLint maxTextureUnits = 0;
11154 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
11155 ANGLE_SKIP_TEST_IF(maxTextureUnits < 4);
11156
11157 constexpr int kSize = 16;
11158
11159 // Make a single-level texture, fill it with red.
11160 std::vector<GLColor> redColors(kSize * kSize, GLColor::red);
11161 GLTexture tex;
11162 glBindTexture(GL_TEXTURE_2D, tex);
11163 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11164 redColors.data());
11165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11167
11168 // Simple confidence check.
11169 draw2DTexturedQuad(0.5f, 1.0f, true);
11170 ASSERT_GL_NO_ERROR();
11171 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11172
11173 // Bind texture to unit 1 with a sampler object making it incomplete.
11174 GLSampler sampler;
11175 glBindSampler(0, sampler);
11176 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
11177 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11178
11179 // Make a mipmap texture, fill it with blue.
11180 std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
11181 GLTexture mipmapTex;
11182 glBindTexture(GL_TEXTURE_2D, mipmapTex);
11183 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11184 blueColors.data());
11185 glGenerateMipmap(GL_TEXTURE_2D);
11186
11187 // Draw with the sampler, expect blue.
11188 draw2DTexturedQuad(0.5f, 1.0f, true);
11189 ASSERT_GL_NO_ERROR();
11190 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
11191
11192 // Simple multitexturing program.
11193 constexpr char kVS[] =
11194 "#version 300 es\n"
11195 "in vec2 position;\n"
11196 "out vec2 texCoord;\n"
11197 "void main()\n"
11198 "{\n"
11199 " gl_Position = vec4(position, 0, 1);\n"
11200 " texCoord = position * 0.5 + vec2(0.5);\n"
11201 "}";
11202
11203 constexpr char kFS[] =
11204 "#version 300 es\n"
11205 "precision mediump float;\n"
11206 "in vec2 texCoord;\n"
11207 "uniform sampler2D tex1;\n"
11208 "uniform sampler2D tex2;\n"
11209 "uniform sampler2D tex3;\n"
11210 "uniform sampler2D tex4;\n"
11211 "out vec4 color;\n"
11212 "void main()\n"
11213 "{\n"
11214 " color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
11215 " + texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
11216 "}";
11217
11218 ANGLE_GL_PROGRAM(program, kVS, kFS);
11219
11220 std::array<GLint, 4> texLocations = {
11221 {glGetUniformLocation(program, "tex1"), glGetUniformLocation(program, "tex2"),
11222 glGetUniformLocation(program, "tex3"), glGetUniformLocation(program, "tex4")}};
11223 for (GLint location : texLocations)
11224 {
11225 ASSERT_NE(-1, location);
11226 }
11227
11228 // Init the uniform data.
11229 glUseProgram(program);
11230 for (GLint location = 0; location < 4; ++location)
11231 {
11232 glUniform1i(texLocations[location], location);
11233 }
11234
11235 // Initialize four samplers
11236 GLSampler samplers[4];
11237
11238 // 0: non-mipped.
11239 glBindSampler(0, samplers[0]);
11240 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11241 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11242
11243 // 1: mipped.
11244 glBindSampler(1, samplers[1]);
11245 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
11246 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11247
11248 // 2: non-mipped.
11249 glBindSampler(2, samplers[2]);
11250 glSamplerParameteri(samplers[2], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11251 glSamplerParameteri(samplers[2], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11252
11253 // 3: mipped.
11254 glBindSampler(3, samplers[3]);
11255 glSamplerParameteri(samplers[3], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
11256 glSamplerParameteri(samplers[3], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11257
11258 // Bind two blue mipped textures and two single layer textures, should all draw.
11259 glActiveTexture(GL_TEXTURE0);
11260 glBindTexture(GL_TEXTURE_2D, tex);
11261
11262 glActiveTexture(GL_TEXTURE1);
11263 glBindTexture(GL_TEXTURE_2D, mipmapTex);
11264
11265 glActiveTexture(GL_TEXTURE2);
11266 glBindTexture(GL_TEXTURE_2D, tex);
11267
11268 glActiveTexture(GL_TEXTURE3);
11269 glBindTexture(GL_TEXTURE_2D, mipmapTex);
11270
11271 ASSERT_GL_NO_ERROR();
11272
11273 drawQuad(program, "position", 0.5f);
11274 ASSERT_GL_NO_ERROR();
11275 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 255, 2);
11276
11277 // Bind four single layer textures, two should be incomplete.
11278 glActiveTexture(GL_TEXTURE1);
11279 glBindTexture(GL_TEXTURE_2D, tex);
11280
11281 glActiveTexture(GL_TEXTURE3);
11282 glBindTexture(GL_TEXTURE_2D, tex);
11283
11284 drawQuad(program, "position", 0.5f);
11285 ASSERT_GL_NO_ERROR();
11286 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 2);
11287 }
11288
11289 // The test is added to cover http://anglebug.com/42260889. Cubemap completeness checks used to
11290 // start always at level 0 instead of the base level resulting in an incomplete texture if the faces
11291 // at level 0 are not created. The test creates a cubemap texture, specifies the images only for mip
11292 // level 1 filled with white color, updates the base level to be 1 and renders a quad. The program
11293 // samples the cubemap using a direction vector (1,1,1).
TEST_P(TextureCubeTestES3,SpecifyAndSampleFromBaseLevel1)11294 TEST_P(TextureCubeTestES3, SpecifyAndSampleFromBaseLevel1)
11295 {
11296 // Check http://anglebug.com/42260891.
11297 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
11298
11299 constexpr char kVS[] =
11300 R"(#version 300 es
11301 precision mediump float;
11302 in vec3 pos;
11303 void main() {
11304 gl_Position = vec4(pos, 1.0);
11305 })";
11306
11307 constexpr char kFS[] =
11308 R"(#version 300 es
11309 precision mediump float;
11310 out vec4 color;
11311 uniform samplerCube uTex;
11312 void main(){
11313 color = texture(uTex, vec3(1.0));
11314 })";
11315
11316 ANGLE_GL_PROGRAM(program, kVS, kFS);
11317 glUseProgram(program);
11318
11319 glUniform1i(glGetUniformLocation(program, "uTex"), 0);
11320 glActiveTexture(GL_TEXTURE0);
11321
11322 GLTexture cubeTex;
11323 glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
11324
11325 const int kFaceWidth = 1;
11326 const int kFaceHeight = 1;
11327 std::vector<uint32_t> texData(kFaceWidth * kFaceHeight, 0xFFFFFFFF);
11328 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11329 GL_UNSIGNED_BYTE, texData.data());
11330 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11331 GL_UNSIGNED_BYTE, texData.data());
11332 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11333 GL_UNSIGNED_BYTE, texData.data());
11334 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11335 GL_UNSIGNED_BYTE, texData.data());
11336 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11337 GL_UNSIGNED_BYTE, texData.data());
11338 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11339 GL_UNSIGNED_BYTE, texData.data());
11340 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11341 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11342 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
11343 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
11344 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
11345 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 1);
11346
11347 drawQuad(program, "pos", 0.5f, 1.0f, true);
11348 ASSERT_GL_NO_ERROR();
11349
11350 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::white);
11351 }
11352
11353 // Test GL_PIXEL_UNPACK_BUFFER with GL_TEXTURE_CUBE_MAP.
TEST_P(TextureCubeTestES3,CubeMapPixelUnpackBuffer)11354 TEST_P(TextureCubeTestES3, CubeMapPixelUnpackBuffer)
11355 {
11356 // Check http://anglebug.com/42260891.
11357 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
11358
11359 constexpr char kVS[] =
11360 R"(#version 300 es
11361 precision mediump float;
11362 in vec3 pos;
11363 void main() {
11364 gl_Position = vec4(pos, 1.0);
11365 })";
11366
11367 constexpr char kFS[] =
11368 R"(#version 300 es
11369 precision mediump float;
11370 out vec4 color;
11371 uniform samplerCube uTex;
11372 void main(){
11373 color = texture(uTex, vec3(1.0));
11374 })";
11375
11376 ANGLE_GL_PROGRAM(program, kVS, kFS);
11377 glUseProgram(program);
11378
11379 glUniform1i(glGetUniformLocation(program, "uTex"), 0);
11380 glActiveTexture(GL_TEXTURE0);
11381
11382 GLTexture cubeTex;
11383 glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
11384
11385 const int kFaceWidth = 4;
11386 const int kFaceHeight = 4;
11387
11388 uint16_t kHalfFloatOne = 0x3C00;
11389 uint16_t kHalfFloatZero = 0;
11390
11391 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA16F, kFaceWidth, kFaceHeight);
11392 struct RGBA16F
11393 {
11394 uint16_t R, G, B, A;
11395 };
11396 RGBA16F redColor = {kHalfFloatOne, kHalfFloatZero, kHalfFloatZero, kHalfFloatOne};
11397
11398 std::vector<RGBA16F> pixels(kFaceWidth * kFaceHeight, redColor);
11399 GLBuffer buffer;
11400 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
11401 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(RGBA16F), pixels.data(),
11402 GL_DYNAMIC_DRAW);
11403 EXPECT_GL_NO_ERROR();
11404 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
11405
11406 for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
11407 {
11408 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, 0, 0, 0, kFaceWidth,
11409 kFaceHeight, GL_RGBA, GL_HALF_FLOAT, 0);
11410 EXPECT_GL_NO_ERROR();
11411 }
11412 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
11413
11414 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11415 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11416 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
11417 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
11418 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
11419
11420 drawQuad(program, "pos", 0.5f, 1.0f, true);
11421 ASSERT_GL_NO_ERROR();
11422
11423 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::red);
11424 }
11425
11426 // Test creating a mutable cubemap, committing it, and then incomaptibly redefining one layer, while
11427 // compatibly redefining another layer.
TEST_P(TextureCubeTestES3,IncompatibleLayerAThenCompatibleLayerB)11428 TEST_P(TextureCubeTestES3, IncompatibleLayerAThenCompatibleLayerB)
11429 {
11430 GLTexture tex;
11431 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11432
11433 std::vector<uint32_t> data(32 * 32 * 4, 0xC00FFC00);
11434
11435 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11436 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11437 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11438 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11439 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11440 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11441 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11442 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11443 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11444 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11445 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11446 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11447 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11448 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11449 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11450 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11451 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11452 EXPECT_GL_NO_ERROR();
11453 }
11454
11455 // Test creating a mutable cubemap, committing it, and then comaptibly redefining one layer, while
11456 // incompatibly redefining another layer.
TEST_P(TextureCubeTestES3,CompatibleLayerAThenIncompatibleLayerB)11457 TEST_P(TextureCubeTestES3, CompatibleLayerAThenIncompatibleLayerB)
11458 {
11459 GLTexture tex;
11460 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11461
11462 std::vector<uint32_t> data(32 * 32 * 4, 0xC00FFC00);
11463
11464 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11465 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11466 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11467 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11468 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11469 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11470 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11471 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11472 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11473 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11474 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11475 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11476 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11477 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11478 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11479 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11480 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11481 EXPECT_GL_NO_ERROR();
11482 }
11483
11484 // Test creating a mutable cubemap, committing it, and then incomaptibly redefining two layers,
11485 // while compatibly redefining another layer.
TEST_P(TextureCubeTestES3,IncompatibleLayerABThenCompatibleLayerC)11486 TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerC)
11487 {
11488 GLTexture tex;
11489 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11490
11491 std::vector<uint32_t> data(32 * 32 * 4, 0xC00FFC00);
11492
11493 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11494 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11495 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11496 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11497 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11498 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11499 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11500 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11501 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11502 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11503 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11504 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11505 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11506 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11507 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11508 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11509 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11510 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11511 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11512 EXPECT_GL_NO_ERROR();
11513 }
11514
11515 // Test creating a mutable cubemap, committing it, and then incomaptibly redefining two layers and
11516 // compatibly redefining them again.
TEST_P(TextureCubeTestES3,IncompatibleLayerABThenCompatibleLayerAB)11517 TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerAB)
11518 {
11519 GLTexture tex;
11520 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11521
11522 constexpr uint32_t kSize = 64;
11523
11524 std::vector<uint32_t> data(kSize * kSize * 4 * 4, 0xC00FFC00);
11525 std::vector<uint32_t> data2(kSize * kSize * 4 * 4, 0xC00003FF);
11526
11527 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11528 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11529 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11530 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11531 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11532 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11533 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11534 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11535 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11536 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11537 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11538 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11539 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11540 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11541 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11542 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11543 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11544 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11545 GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11546 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11547 GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11548
11549 glActiveTexture(GL_TEXTURE0);
11550 glBindTexture(GL_TEXTURE_2D, 0);
11551 glActiveTexture(GL_TEXTURE1);
11552 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11553
11554 glUseProgram(mProgram);
11555 glUniform1i(mTexture2DUniformLocation, 0);
11556 glUniform1i(mTextureCubeUniformLocation, 1);
11557
11558 const int w = getWindowWidth();
11559 const int h = getWindowHeight();
11560
11561 for (uint32_t i = 0; i < 6; ++i)
11562 {
11563 glUniform1i(mTextureCubeFaceUniformLocation, i);
11564 glClear(GL_COLOR_BUFFER_BIT);
11565 drawQuad(mProgram, "position", 0.5f);
11566
11567 const bool expectRed = i == 2 || i == 5;
11568 const GLColor expect = expectRed ? GLColor::red : GLColor::green;
11569 EXPECT_PIXEL_RECT_EQ(2, 2, w - 4, h - 4, expect);
11570 EXPECT_GL_NO_ERROR();
11571 }
11572 }
11573
11574 // Similar to IncompatibleLayerABThenCompatibleLayerAB, but with a single-level texture
TEST_P(TextureCubeTestES3,IncompatibleLayerABThenCompatibleLayerABSingleLevel)11575 TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerABSingleLevel)
11576 {
11577 GLTexture tex;
11578 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11579
11580 constexpr uint32_t kSize = 64;
11581
11582 std::vector<uint32_t> data(kSize * kSize * 4 * 4, 0xC00FFC00);
11583 std::vector<uint32_t> data2(kSize * kSize * 4 * 4, 0xC00003FF);
11584
11585 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11586 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11587 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11588 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11589 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11590 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11591 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11592 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11593 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11594 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11595 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11596 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11597
11598 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11599 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11600
11601 glActiveTexture(GL_TEXTURE0);
11602 glBindTexture(GL_TEXTURE_2D, 0);
11603 glActiveTexture(GL_TEXTURE1);
11604 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11605
11606 glUseProgram(mProgram);
11607 glUniform1i(mTexture2DUniformLocation, 0);
11608 glUniform1i(mTextureCubeUniformLocation, 1);
11609
11610 const int w = getWindowWidth();
11611 const int h = getWindowHeight();
11612
11613 for (uint32_t i = 0; i < 6; ++i)
11614 {
11615 glUniform1i(mTextureCubeFaceUniformLocation, i);
11616 glClear(GL_COLOR_BUFFER_BIT);
11617 drawQuad(mProgram, "position", 0.5f);
11618
11619 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
11620 EXPECT_GL_NO_ERROR();
11621 }
11622
11623 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11624 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11625 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11626 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11627 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11628 GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11629 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11630 GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11631
11632 for (uint32_t i = 0; i < 6; ++i)
11633 {
11634 glUniform1i(mTextureCubeFaceUniformLocation, i);
11635 glClear(GL_COLOR_BUFFER_BIT);
11636 drawQuad(mProgram, "position", 0.5f);
11637
11638 const bool expectRed = i == 2 || i == 5;
11639 const GLColor expect = expectRed ? GLColor::red : GLColor::green;
11640 EXPECT_PIXEL_RECT_EQ(2, 2, w - 4, h - 4, expect);
11641 EXPECT_GL_NO_ERROR();
11642 }
11643 }
11644
11645 // Tests defining a cube map array texture using glTexImage3D().
TEST_P(TextureCubeTestES32,ValidateCubeMapArrayTexImage)11646 TEST_P(TextureCubeTestES32, ValidateCubeMapArrayTexImage)
11647 {
11648 GLTexture cubeMapArrayTexture;
11649 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubeMapArrayTexture);
11650
11651 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 256, 256, 24, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11652 nullptr);
11653 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA, 128, 128, 24, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11654 nullptr);
11655 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, GL_RGBA, 64, 64, 24, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11656 nullptr);
11657 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 3, GL_RGBA, 32, 32, 24, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11658 nullptr);
11659 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 4, GL_RGBA, 16, 16, 24, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11660 nullptr);
11661 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 5, GL_RGBA, 8, 8, 24, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11662 nullptr);
11663 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 6, GL_RGBA, 4, 4, 24, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11664 nullptr);
11665 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 7, GL_RGBA, 2, 2, 24, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11666 nullptr);
11667 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 8, GL_RGBA, 1, 1, 24, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11668 nullptr);
11669 EXPECT_GL_NO_ERROR();
11670 }
11671
11672 // Tests defining a cube map array texture using glTexStorage3D() and filling all levels using
11673 // glTexSubImage3D().
TEST_P(TextureCubeTestES32,ValidateCubeMapArrayTexStorage)11674 TEST_P(TextureCubeTestES32, ValidateCubeMapArrayTexStorage)
11675 {
11676 GLTexture cubeMapArrayTexture;
11677 std::vector<GLColor> cubeMapArrayData(256 * 256 * 24, GLColor::red);
11678 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubeMapArrayTexture);
11679
11680 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 9, GL_RGBA8, 256, 256, 24);
11681 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, 256, 256, 24, GL_RGBA, GL_UNSIGNED_BYTE,
11682 cubeMapArrayData.data());
11683 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, 0, 0, 0, 128, 128, 24, GL_RGBA, GL_UNSIGNED_BYTE,
11684 cubeMapArrayData.data());
11685 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, 0, 0, 0, 64, 64, 24, GL_RGBA, GL_UNSIGNED_BYTE,
11686 cubeMapArrayData.data());
11687 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 3, 0, 0, 0, 32, 32, 24, GL_RGBA, GL_UNSIGNED_BYTE,
11688 cubeMapArrayData.data());
11689 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 4, 0, 0, 0, 16, 16, 24, GL_RGBA, GL_UNSIGNED_BYTE,
11690 cubeMapArrayData.data());
11691 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 5, 0, 0, 0, 8, 8, 24, GL_RGBA, GL_UNSIGNED_BYTE,
11692 cubeMapArrayData.data());
11693 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 6, 0, 0, 0, 4, 4, 24, GL_RGBA, GL_UNSIGNED_BYTE,
11694 cubeMapArrayData.data());
11695 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 7, 0, 0, 0, 2, 2, 24, GL_RGBA, GL_UNSIGNED_BYTE,
11696 cubeMapArrayData.data());
11697 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 8, 0, 0, 0, 1, 1, 24, GL_RGBA, GL_UNSIGNED_BYTE,
11698 cubeMapArrayData.data());
11699 EXPECT_GL_NO_ERROR();
11700 }
11701
11702 // Tests defining a single-level cube map array texture and modifying a part of it with unequal
11703 // width and height and a depth that is not a multiple of 6.
TEST_P(TextureCubeTestES32,ValidateCubeMapArrayTexStorageModifyPartially)11704 TEST_P(TextureCubeTestES32, ValidateCubeMapArrayTexStorageModifyPartially)
11705 {
11706 GLTexture cubeMapArrayTexture;
11707 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubeMapArrayTexture);
11708
11709 std::vector<GLColor> cubeMapArrayData(256 * 256 * 6, GLColor::red);
11710 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 256, 256, 6);
11711 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, 256, 100, 1, GL_RGBA, GL_UNSIGNED_BYTE,
11712 cubeMapArrayData.data());
11713 EXPECT_GL_NO_ERROR();
11714 }
11715
11716 // Tests TexSubImage3D with cube map arrays using dims beyond the size limit.
TEST_P(TextureCubeTestES32,ValidateCubeMapArrayTexSubImageGreaterThanSizeLimit)11717 TEST_P(TextureCubeTestES32, ValidateCubeMapArrayTexSubImageGreaterThanSizeLimit)
11718 {
11719 GLTexture cubeMapArrayTexture;
11720 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubeMapArrayTexture);
11721
11722 GLint max3DTextureSize = -1;
11723 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
11724 EXPECT_GT(max3DTextureSize, 0);
11725
11726 GLint maxCubeTextureSize = -1;
11727 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeTextureSize);
11728 EXPECT_GT(maxCubeTextureSize, 0);
11729
11730 GLint maxSizeLimit = std::min(maxCubeTextureSize, max3DTextureSize);
11731 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, maxSizeLimit, maxSizeLimit, 6, 0, GL_RGBA,
11732 GL_UNSIGNED_BYTE, nullptr);
11733 ASSERT_GL_NO_ERROR();
11734
11735 // TexSubImage3D can take unequal values for width and height for cube map arrays. However, they
11736 // should stay below the size limit.
11737 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, maxSizeLimit + 1, maxSizeLimit, 6,
11738 GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
11739 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11740
11741 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, maxSizeLimit, maxSizeLimit + 1, 6,
11742 GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
11743 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11744 }
11745
11746 // Tests invalid dim/level input for TexImage3D with cube map arrays.
TEST_P(TextureCubeTestES32,ValidateCubeMapArrayTexImageInvalidInputs)11747 TEST_P(TextureCubeTestES32, ValidateCubeMapArrayTexImageInvalidInputs)
11748 {
11749 GLTexture cubeMapArrayTexture;
11750 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubeMapArrayTexture);
11751
11752 // Negative level and dimensions are not accepted.
11753 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, -1, GL_RGBA, 256, 256, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11754 nullptr);
11755 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11756
11757 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, -1, 256, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11758 nullptr);
11759 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11760
11761 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 256, -1, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11762 nullptr);
11763 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11764
11765 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 256, 256, -6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11766 nullptr);
11767 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11768
11769 // As the number of layer-faces, depth should be a multiple of 6, unless it is partially being
11770 // modified (via TexSubImage).
11771 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 256, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11772 nullptr);
11773 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11774
11775 // Width and height should be equal, unless it is partially being modified (via TexSubImage).
11776 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 256, 100, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11777 nullptr);
11778 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11779
11780 // Width and height should not exceed the maximum cube map texture size for that mip level.
11781 GLint maxCubeTextureSize = -1;
11782 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeTextureSize);
11783 EXPECT_GT(maxCubeTextureSize, 0);
11784
11785 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, maxCubeTextureSize + 1, maxCubeTextureSize,
11786 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11787 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11788
11789 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, maxCubeTextureSize, maxCubeTextureSize + 1,
11790 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11791 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11792
11793 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, maxCubeTextureSize + 1,
11794 maxCubeTextureSize + 1, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11795 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11796
11797 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA, maxCubeTextureSize / 2 + 1,
11798 maxCubeTextureSize / 2 + 1, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11799 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11800
11801 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, GL_RGBA, maxCubeTextureSize / 4 + 1,
11802 maxCubeTextureSize / 4 + 1, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11803 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11804
11805 // Width and height and depth should not exceed the maximum 3D texture size.
11806 GLint max3DTextureSize = -1;
11807 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
11808 EXPECT_GT(max3DTextureSize, 0);
11809
11810 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 256, 256, max3DTextureSize + 1, 0, GL_RGBA,
11811 GL_UNSIGNED_BYTE, nullptr);
11812 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11813
11814 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, max3DTextureSize + 1, max3DTextureSize + 1,
11815 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11816 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11817
11818 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA, max3DTextureSize / 2 + 1,
11819 max3DTextureSize / 2 + 1, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11820 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11821
11822 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 2, GL_RGBA, max3DTextureSize / 4 + 1,
11823 max3DTextureSize / 4 + 1, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
11824 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11825 }
11826
11827 // Tests invalid dim/level input for TexStorage3D with cube map arrays.
TEST_P(TextureCubeTestES32,ValidateCubeMapArrayTexStorageInvalidInputs)11828 TEST_P(TextureCubeTestES32, ValidateCubeMapArrayTexStorageInvalidInputs)
11829 {
11830 GLTexture cubeMapArrayTexture;
11831 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubeMapArrayTexture);
11832
11833 // Negative level and dimensions are not accepted.
11834 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, -1, GL_RGBA8, 256, 256, 6);
11835 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11836
11837 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, -1, 256, 6);
11838 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11839
11840 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 256, -1, 6);
11841 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11842
11843 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 256, 256, -6);
11844 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11845
11846 // As the number of layer-faces, depth should be a multiple of 6.
11847 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 256, 256, 1);
11848 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11849
11850 // Width and height should be equal.
11851 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 256, 100, 6);
11852 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11853
11854 // Width and height should not exceed the maximum cube map texture size.
11855 GLint maxCubeTextureSize = -1;
11856 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeTextureSize);
11857 EXPECT_GT(maxCubeTextureSize, 0);
11858
11859 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, maxCubeTextureSize + 1,
11860 maxCubeTextureSize + 1, 6);
11861 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11862
11863 // Width and height and depth should not exceed the maximum 3D texture size.
11864 GLint max3DTextureSize = -1;
11865 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize);
11866 EXPECT_GT(max3DTextureSize, 0);
11867
11868 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, max3DTextureSize + 1,
11869 max3DTextureSize + 1, 6);
11870 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11871
11872 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA8, 256, 256, max3DTextureSize + 1);
11873 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11874
11875 // Level count must not exceed log2(max(width, height)) + 1.
11876 GLint maxLevelCount256 = 1 + static_cast<GLint>(std::log2(256));
11877 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, maxLevelCount256 + 1, GL_RGBA8, 256, 256, 6);
11878 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11879 }
11880
11881 // Verify that using negative texture base level and max level generates GL_INVALID_VALUE.
TEST_P(Texture2DTestES3,NegativeTextureBaseLevelAndMaxLevel)11882 TEST_P(Texture2DTestES3, NegativeTextureBaseLevelAndMaxLevel)
11883 {
11884 GLuint texture = create2DTexture();
11885
11886 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, -1);
11887 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11888
11889 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, -1);
11890 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11891
11892 glDeleteTextures(1, &texture);
11893 EXPECT_GL_NO_ERROR();
11894 }
11895
11896 // Test setting base level after calling generateMipmap on a LUMA texture.
11897 // Covers http://anglebug.com/42261204
TEST_P(Texture2DTestES3,GenerateMipmapAndBaseLevelLUMA)11898 TEST_P(Texture2DTestES3, GenerateMipmapAndBaseLevelLUMA)
11899 {
11900 glActiveTexture(GL_TEXTURE0);
11901 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11902
11903 constexpr const GLsizei kWidth = 8;
11904 constexpr const GLsizei kHeight = 8;
11905 std::array<GLubyte, kWidth * kHeight * 2> whiteData;
11906 whiteData.fill(255u);
11907
11908 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, kWidth, kHeight, 0, GL_LUMINANCE_ALPHA,
11909 GL_UNSIGNED_BYTE, whiteData.data());
11910 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
11911 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11912 glGenerateMipmap(GL_TEXTURE_2D);
11913 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
11914 EXPECT_GL_NO_ERROR();
11915
11916 drawQuad(mProgram, "position", 0.5f);
11917 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::white);
11918 }
11919
11920 // Incompatible levels with non-mipmap filtering should work.
TEST_P(Texture2DTestES3,IncompatibleMipsButNoMipmapFiltering)11921 TEST_P(Texture2DTestES3, IncompatibleMipsButNoMipmapFiltering)
11922 {
11923 // http://anglebug.com/42263372
11924 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && (IsAMD() || IsIntel()));
11925
11926 // http://anglebug.com/40096708
11927 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIAShield());
11928
11929 glActiveTexture(GL_TEXTURE0);
11930 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11931
11932 constexpr const GLsizei kSize = 8;
11933 const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
11934 const std::vector<GLColor> kLevel1Data(kSize * kSize, GLColor::red);
11935
11936 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11937 kLevel0Data.data());
11938 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11939 kLevel1Data.data());
11940 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11941 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11942 EXPECT_GL_NO_ERROR();
11943
11944 // Draw with base level 0. The GL_LINEAR filtering ensures the texture's image is not created
11945 // with mipmap.
11946 drawQuad(mProgram, "position", 0.5f);
11947 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
11948
11949 // Verify draw with level 1.
11950 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
11951 drawQuad(mProgram, "position", 0.5f);
11952 EXPECT_GL_NO_ERROR();
11953 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel1Data[0]);
11954
11955 // Verify draw with level 0 again
11956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
11957 drawQuad(mProgram, "position", 0.5f);
11958 EXPECT_GL_NO_ERROR();
11959 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
11960 }
11961
11962 // A collection of negative tests for QCOM foveated rendering extensions
TEST_P(Texture2DTestES3Foveation,NegativeTests)11963 TEST_P(Texture2DTestES3Foveation, NegativeTests)
11964 {
11965 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated") ||
11966 !IsGLExtensionEnabled("GL_QCOM_texture_foveated"));
11967
11968 // Switch to foveated framebuffer
11969 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11970
11971 // QCOM framebuffer foveated tests
11972 GLuint providedFeatures = 0;
11973
11974 // Test invalid numLayers
11975 glFramebufferFoveationConfigQCOM(mFramebuffer, std::numeric_limits<uint32_t>::max(), 1,
11976 GL_FOVEATION_ENABLE_BIT_QCOM, &providedFeatures);
11977 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11978
11979 // Test invalid focal points
11980 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, std::numeric_limits<uint32_t>::max(),
11981 GL_FOVEATION_ENABLE_BIT_QCOM, &providedFeatures);
11982 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11983
11984 // Test setting foveation parameters on a framebuffer that is not configured
11985 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11986 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11987
11988 // Configure framebuffer correctly
11989 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11990 &providedFeatures);
11991 EXPECT_GL_NO_ERROR();
11992 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11993
11994 // Try to configure it again
11995 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11996 &providedFeatures);
11997 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11998
11999 // Set foveation parameters
12000 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12001 EXPECT_GL_NO_ERROR();
12002
12003 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12004
12005 GLTexture texture;
12006 glActiveTexture(GL_TEXTURE0);
12007 glBindTexture(GL_TEXTURE_2D, texture);
12008 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
12009 GL_UNSIGNED_BYTE, nullptr);
12010 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12011 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12012 EXPECT_GL_NO_ERROR();
12013
12014 // Change attachments and try to perform a clear and draw
12015 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
12016 ASSERT_GL_NO_ERROR();
12017
12018 glUseProgram(mProgram);
12019
12020 // Clear
12021 glClearColor(0.5f, 0.8f, 1.0f, 0.2f);
12022 glClear(GL_COLOR_BUFFER_BIT);
12023 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
12024
12025 // Draw
12026 drawQuad(mProgram, "position", 0.5f);
12027 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
12028
12029 // QCOM texture foveated tests
12030 glBindTexture(GL_TEXTURE_2D, texture);
12031 // Test invalid feature bit
12032 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
12033 GL_FOVEATION_SCALED_BIN_METHOD_BIT_QCOM);
12034 EXPECT_GL_ERROR(GL_INVALID_ENUM);
12035
12036 // Test setting foveation parameters on a framebuffer that is not configured
12037 glTextureFoveationParametersQCOM(texture, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12038 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
12039
12040 // Configure texture
12041 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
12042 GL_FOVEATION_ENABLE_BIT_QCOM);
12043 EXPECT_GL_NO_ERROR();
12044
12045 // Test invalid focal points
12046 GLint supportedNumFocalPoints = 0;
12047 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM,
12048 &supportedNumFocalPoints);
12049 EXPECT_GL_NO_ERROR();
12050
12051 glTextureFoveationParametersQCOM(texture, 0, supportedNumFocalPoints + 1, 0.0f, 0.0f, 8.0f,
12052 8.0f, 0.0f);
12053 EXPECT_GL_ERROR(GL_INVALID_VALUE);
12054
12055 // Attach foveated texture while framebuffer is also fovated and check framebuffer completeness
12056 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
12057 ASSERT_GL_NO_ERROR();
12058 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM,
12059 glCheckFramebufferStatus(GL_FRAMEBUFFER));
12060
12061 // Attach multiple foveated textures to an un-foveated framebuffer and check completeness
12062 GLFramebuffer fbo;
12063 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12064 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
12065 ASSERT_GL_NO_ERROR();
12066 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12067
12068 glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
12069 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
12070 GL_UNSIGNED_BYTE, nullptr);
12071 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12072 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12073 EXPECT_GL_NO_ERROR();
12074 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
12075 GL_FOVEATION_ENABLE_BIT_QCOM);
12076 EXPECT_GL_NO_ERROR();
12077
12078 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
12079 mFramebufferColorTexture, 0);
12080 ASSERT_GL_NO_ERROR();
12081 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM,
12082 glCheckFramebufferStatus(GL_FRAMEBUFFER));
12083 }
12084
12085 // QCOM framebuffer foveated rendering + clear
TEST_P(Texture2DTestES3Foveation,Clear)12086 TEST_P(Texture2DTestES3Foveation, Clear)
12087 {
12088 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12089
12090 // Switch to foveated framebuffer
12091 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12092
12093 // Just need 1 focal point
12094 GLuint providedFeatures = 0;
12095 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12096 &providedFeatures);
12097 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12098 // Set foveation parameters
12099 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12100 EXPECT_GL_NO_ERROR();
12101
12102 // Clear
12103 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12104 glClear(GL_COLOR_BUFFER_BIT);
12105 EXPECT_GL_NO_ERROR();
12106
12107 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
12108 }
12109
12110 // QCOM framebuffer foveated rendering + clear then draw
TEST_P(Texture2DTestES3Foveation,ClearThenDraw)12111 TEST_P(Texture2DTestES3Foveation, ClearThenDraw)
12112 {
12113 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12114
12115 // Switch to foveated framebuffer
12116 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12117
12118 // Just need 1 focal point
12119 GLuint providedFeatures = 0;
12120 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12121 &providedFeatures);
12122 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12123 // Set foveation parameters
12124 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12125 EXPECT_GL_NO_ERROR();
12126
12127 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12128 glUseProgram(program);
12129
12130 // Clear
12131 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12132 glClear(GL_COLOR_BUFFER_BIT);
12133 EXPECT_GL_NO_ERROR();
12134
12135 // Draw
12136 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
12137 EXPECT_GL_NO_ERROR();
12138
12139 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
12140 }
12141
12142 // QCOM framebuffer foveated rendering with rendebuffer attachment + clear then draw
TEST_P(Texture2DTestES3Foveation,RenderbufferAttachmentClearThenDraw)12143 TEST_P(Texture2DTestES3Foveation, RenderbufferAttachmentClearThenDraw)
12144 {
12145 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12146
12147 // Switch to foveated framebuffer and attach a renderbuffer
12148 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12149 GLRenderbuffer renderbuffer;
12150 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
12151 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight());
12152 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
12153 EXPECT_GL_NO_ERROR();
12154
12155 // Just need 1 focal point
12156 GLuint providedFeatures = 0;
12157 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12158 &providedFeatures);
12159 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12160 // Set foveation parameters
12161 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12162 EXPECT_GL_NO_ERROR();
12163
12164 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12165 glUseProgram(program);
12166
12167 // Clear
12168 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12169 glClear(GL_COLOR_BUFFER_BIT);
12170 EXPECT_GL_NO_ERROR();
12171
12172 // Draw
12173 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
12174 EXPECT_GL_NO_ERROR();
12175
12176 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
12177 }
12178
12179 // QCOM framebuffer foveated rendering + draw, clear then draw
TEST_P(Texture2DTestES3Foveation,DrawClearDraw)12180 TEST_P(Texture2DTestES3Foveation, DrawClearDraw)
12181 {
12182 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12183
12184 // Switch to foveated framebuffer
12185 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12186
12187 // Just need 1 focal point
12188 GLuint providedFeatures = 0;
12189 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12190 &providedFeatures);
12191 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12192 // Set foveation parameters
12193 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12194 EXPECT_GL_NO_ERROR();
12195
12196 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12197 glUseProgram(greenProgram);
12198
12199 // Draw
12200 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
12201 EXPECT_GL_NO_ERROR();
12202
12203 // Clear
12204 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
12205 glClear(GL_COLOR_BUFFER_BIT);
12206 EXPECT_GL_NO_ERROR();
12207
12208 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
12209 glUseProgram(blueProgram);
12210
12211 // Draw
12212 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
12213 EXPECT_GL_NO_ERROR();
12214
12215 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
12216 }
12217
12218 // QCOM framebuffer foveated rendering - draw before and after enabling foveation
TEST_P(Texture2DTestES3Foveation,DrawThenEnableFoveationAndDraw)12219 TEST_P(Texture2DTestES3Foveation, DrawThenEnableFoveationAndDraw)
12220 {
12221 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12222
12223 // Switch to foveated framebuffer
12224 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12225
12226 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12227
12228 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12229 glUseProgram(program);
12230
12231 // Clear
12232 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12233 glClear(GL_COLOR_BUFFER_BIT);
12234 EXPECT_GL_NO_ERROR();
12235
12236 // Draw
12237 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
12238 EXPECT_GL_NO_ERROR();
12239
12240 // Configure foveated rendering for framebuffer
12241 // Just need 1 focal point
12242 GLuint providedFeatures = 0;
12243 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12244 &providedFeatures);
12245 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12246 // Set foveation parameters
12247 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12248 EXPECT_GL_NO_ERROR();
12249
12250 // Draw
12251 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
12252 EXPECT_GL_NO_ERROR();
12253
12254 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
12255 }
12256
12257 // QCOM framebuffer foveated rendering + draw, change foveation parameters and then draw
TEST_P(Texture2DTestES3Foveation,DrawChangeFoveationParametersThenDraw)12258 TEST_P(Texture2DTestES3Foveation, DrawChangeFoveationParametersThenDraw)
12259 {
12260 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12261
12262 // Switch to foveated framebuffer
12263 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12264
12265 // Just need 1 focal point
12266 GLuint providedFeatures = 0;
12267 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12268 &providedFeatures);
12269 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12270 // Set foveation parameters
12271 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12272 EXPECT_GL_NO_ERROR();
12273
12274 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12275 glUseProgram(greenProgram);
12276
12277 // Draw
12278 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
12279 EXPECT_GL_NO_ERROR();
12280
12281 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
12282
12283 // Change foveation parameters
12284 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.5f, 0.5f, 3.0f, 3.0f, 3.0f);
12285 EXPECT_GL_NO_ERROR();
12286
12287 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
12288 glUseProgram(blueProgram);
12289
12290 // Draw
12291 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
12292 EXPECT_GL_NO_ERROR();
12293
12294 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
12295 }
12296
12297 // QCOM framebuffer foveated rendering + draw and use as blit source
TEST_P(Texture2DTestES3Foveation,DrawThenUseAsBlitSource)12298 TEST_P(Texture2DTestES3Foveation, DrawThenUseAsBlitSource)
12299 {
12300 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12301
12302 // Switch to foveated framebuffer
12303 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12304
12305 glActiveTexture(GL_TEXTURE0);
12306 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12307
12308 const GLsizei kSizeW = getWindowWidth();
12309 const GLsizei kSizeH = getWindowHeight();
12310 std::vector<GLColor> data(kSizeW * kSizeH, GLColor::blue);
12311 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSizeW, kSizeH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12312 data.data());
12313 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12314 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12315 EXPECT_GL_NO_ERROR();
12316
12317 // Just need 1 focal point
12318 GLuint providedFeatures = 0;
12319 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12320 &providedFeatures);
12321 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12322 // Set foveation parameters
12323 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12324 EXPECT_GL_NO_ERROR();
12325
12326 glUseProgram(mProgram);
12327
12328 // Verify
12329 drawQuad(mProgram, "position", 0.5f);
12330 EXPECT_GL_NO_ERROR();
12331
12332 // Blit data from foveated framebuffer into default framebuffer
12333 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
12334 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
12335 glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
12336 getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
12337
12338 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
12339 }
12340
12341 // QCOM framebuffer foveated rendering + draw and use as blit target
TEST_P(Texture2DTestES3Foveation,DrawThenUseAsBlitTarget)12342 TEST_P(Texture2DTestES3Foveation, DrawThenUseAsBlitTarget)
12343 {
12344 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12345
12346 // Switch to foveated framebuffer
12347 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12348
12349 // Just need 1 focal point
12350 GLuint providedFeatures = 0;
12351 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12352 &providedFeatures);
12353 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12354 // Set foveation parameters
12355 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12356 EXPECT_GL_NO_ERROR();
12357
12358 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12359 glUseProgram(greenProgram);
12360
12361 // Draw
12362 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
12363 EXPECT_GL_NO_ERROR();
12364 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
12365
12366 // Switch to default framebuffer and clear to blue
12367 glBindFramebuffer(GL_FRAMEBUFFER, 0);
12368 EXPECT_GL_NO_ERROR();
12369 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12370 glClear(GL_COLOR_BUFFER_BIT);
12371 EXPECT_GL_NO_ERROR();
12372
12373 // Blit data from default framebuffer into foveated framebuffer
12374 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
12375 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
12376 glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
12377 getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
12378
12379 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
12380 }
12381
12382 // QCOM framebuffer foveated rendering, reuse texture between 2 foveated framebuffers
TEST_P(Texture2DTestES3Foveation,ReuseTextureForFoveatedDraw)12383 TEST_P(Texture2DTestES3Foveation, ReuseTextureForFoveatedDraw)
12384 {
12385 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12386
12387 // Switch to foveated framebuffer
12388 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12389
12390 // Just need 1 focal point
12391 GLuint providedFeatures = 0;
12392 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12393 &providedFeatures);
12394 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12395 // Set foveation parameters
12396 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12397 EXPECT_GL_NO_ERROR();
12398
12399 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12400 glUseProgram(greenProgram);
12401
12402 // Draw
12403 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
12404 EXPECT_GL_NO_ERROR();
12405
12406 // Create another framebuffer
12407 GLFramebuffer framebuffer;
12408 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
12409
12410 // Resuse texture from mFramebuffer
12411 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
12412 mFramebufferColorTexture, 0);
12413
12414 // Configure foveation parameters of the new framebuffer
12415 // Just need 1 focal point
12416 providedFeatures = 0;
12417 glFramebufferFoveationConfigQCOM(framebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12418 &providedFeatures);
12419 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12420 // Set foveation parameters
12421 glFramebufferFoveationParametersQCOM(framebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12422 EXPECT_GL_NO_ERROR();
12423
12424 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
12425 glUseProgram(blueProgram);
12426
12427 // Draw
12428 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
12429 EXPECT_GL_NO_ERROR();
12430
12431 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
12432 }
12433
12434 // QCOM framebuffer foveated rendering with MSAA framebuffer
TEST_P(Texture2DTestES3Foveation,DrawWithMsaaFramebuffer)12435 TEST_P(Texture2DTestES3Foveation, DrawWithMsaaFramebuffer)
12436 {
12437 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12438 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
12439
12440 // Create a new MSAA framebuffer
12441 GLFramebuffer msaaFramebuffer;
12442 glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebuffer);
12443 GLTexture texture;
12444 glActiveTexture(GL_TEXTURE0);
12445 glBindTexture(GL_TEXTURE_2D, texture);
12446 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
12447 GL_UNSIGNED_BYTE, nullptr);
12448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12450 EXPECT_GL_NO_ERROR();
12451
12452 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
12453 texture, 0, 4);
12454 ASSERT_GL_NO_ERROR();
12455 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12456
12457 // Just need 1 focal point
12458 GLuint providedFeatures = 0;
12459 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12460 &providedFeatures);
12461 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12462 // Set foveation parameters
12463 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12464 EXPECT_GL_NO_ERROR();
12465
12466 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12467 glUseProgram(program);
12468
12469 // Clear
12470 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12471 glClear(GL_COLOR_BUFFER_BIT);
12472 EXPECT_GL_NO_ERROR();
12473
12474 // Draw
12475 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
12476 EXPECT_GL_NO_ERROR();
12477
12478 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
12479 }
12480
12481 // QCOM framebuffer foveated rendering with multiple attachments
TEST_P(Texture2DTestES3Foveation,DrawWithMultipleAttachments)12482 TEST_P(Texture2DTestES3Foveation, DrawWithMultipleAttachments)
12483 {
12484 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
12485
12486 const GLsizei kSizeW = getWindowWidth();
12487 const GLsizei kSizeH = getWindowHeight();
12488
12489 // Setup sampling texture
12490 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12491
12492 std::vector<GLColor> data(kSizeW * kSizeH);
12493 // Generate red / blue checkered pattern
12494 for (int i = 0; i < kSizeH; i++)
12495 {
12496 for (int j = 0; j < kSizeW; j++)
12497 {
12498 data[(i * kSizeW) + j] = ((i + j) % 2 == 0) ? GLColor::red : GLColor::blue;
12499 }
12500 }
12501
12502 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSizeW, kSizeH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12503 data.data());
12504 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12505 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12506 EXPECT_GL_NO_ERROR();
12507
12508 // Draw without foveation
12509 glActiveTexture(GL_TEXTURE0);
12510 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12511
12512 glBindFramebuffer(GL_FRAMEBUFFER, 0);
12513 glUseProgram(mProgram);
12514 drawQuad(mProgram, "position", 0.5f);
12515 EXPECT_GL_NO_ERROR();
12516
12517 // Record original data
12518 std::vector<GLColor> originalData(kSizeW * kSizeH, {0, 0, 0, 0});
12519 glReadPixels(0, 0, kSizeW, kSizeH, GL_RGBA, GL_UNSIGNED_BYTE, originalData.data());
12520
12521 // Switch to foveated framebuffer
12522 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
12523
12524 // Setup mutliple color attachments
12525 std::array<GLTexture, 3> colorAttachments;
12526 GLenum attachmentBase = GL_COLOR_ATTACHMENT0;
12527 GLuint attachmentIndex = 0;
12528 for (GLTexture &attachment : colorAttachments)
12529 {
12530 glBindTexture(GL_TEXTURE_2D, attachment);
12531 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSizeW, kSizeH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12532 nullptr);
12533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12534 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12535 EXPECT_GL_NO_ERROR();
12536
12537 glFramebufferTexture2D(GL_FRAMEBUFFER, attachmentBase + attachmentIndex, GL_TEXTURE_2D,
12538 attachment, 0);
12539 ASSERT_GL_NO_ERROR();
12540 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12541
12542 glBindTexture(GL_TEXTURE_2D, 0);
12543
12544 attachmentIndex++;
12545 }
12546
12547 // Setup foveation parameters, just need 1 focal point
12548 GLuint providedFeatures = 0;
12549 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
12550 &providedFeatures);
12551 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
12552
12553 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12554 EXPECT_GL_NO_ERROR();
12555
12556 constexpr char kFS[] = R"(#version 300 es
12557 precision highp float;
12558
12559 in vec2 texcoord;
12560 uniform sampler2D tex;
12561
12562 layout(location = 0) out vec4 color0;
12563 layout(location = 1) out vec4 color1;
12564 layout(location = 2) out vec4 color2;
12565
12566 void main()
12567 {
12568 vec4 fragColor = texture(tex, texcoord);
12569 color0 = fragColor;
12570 color1 = fragColor;
12571 color2 = fragColor;
12572 })";
12573
12574 ANGLE_GL_PROGRAM(program, getVertexShaderSource(), kFS);
12575 glUseProgram(program);
12576
12577 std::array<GLenum, 3> drawBuffers = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
12578 GL_COLOR_ATTACHMENT2};
12579 glDrawBuffers(3, drawBuffers.data());
12580
12581 // Draw with foveation into multiple attachments
12582 glActiveTexture(GL_TEXTURE0);
12583 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12584 drawQuad(program, "position", 0.5f);
12585 EXPECT_GL_NO_ERROR();
12586
12587 // Verify
12588 GLFramebuffer readFBO;
12589 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
12590
12591 // Use colorAttachments[0]'s content as reference data
12592 std::vector<GLColor> referenceData(kSizeW * kSizeH, {0, 0, 0, 0});
12593 std::vector<GLColor> result(kSizeW * kSizeH, {0, 0, 0, 0});
12594 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
12595 colorAttachments[0], 0);
12596 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
12597 glReadPixels(0, 0, kSizeW, kSizeH, GL_RGBA, GL_UNSIGNED_BYTE, referenceData.data());
12598
12599 // Foveated rendering should produce content that differs from original data
12600 ASSERT(originalData != referenceData);
12601
12602 // Verify rest of the attachments
12603 for (size_t index = 1; index < colorAttachments.size(); index++)
12604 {
12605 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
12606 colorAttachments[index], 0);
12607 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
12608
12609 result.assign(result.size(), {0, 0, 0, 0});
12610 glReadPixels(0, 0, kSizeW, kSizeH, GL_RGBA, GL_UNSIGNED_BYTE, result.data());
12611
12612 ASSERT(referenceData == result);
12613 }
12614 }
12615
12616 // QCOM texture foveated rendering, basic draw
TEST_P(Texture2DTestES3Foveation,FoveatedTextureDraw)12617 TEST_P(Texture2DTestES3Foveation, FoveatedTextureDraw)
12618 {
12619 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_texture_foveated"));
12620
12621 // Create non-foveated framebuffer
12622 GLFramebuffer framebuffer;
12623 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
12624 glActiveTexture(GL_TEXTURE0);
12625 glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
12626 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
12627 mFramebufferColorTexture, 0);
12628 ASSERT_GL_NO_ERROR();
12629 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12630
12631 // Render before configuring foveation on the texture
12632 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12633 glUseProgram(greenProgram);
12634
12635 // Clear
12636 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12637 glClear(GL_COLOR_BUFFER_BIT);
12638 EXPECT_GL_NO_ERROR();
12639
12640 // Draw
12641 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
12642 EXPECT_GL_NO_ERROR();
12643
12644 // Configure foveation for the texture
12645 GLint supportedFoveationFeatures = 0;
12646 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_QUERY_QCOM,
12647 &supportedFoveationFeatures);
12648 ASSERT_EQ(supportedFoveationFeatures & GL_FOVEATION_ENABLE_BIT_QCOM,
12649 GL_FOVEATION_ENABLE_BIT_QCOM);
12650 GLint supportedNumFocalPoints = 0;
12651 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM,
12652 &supportedNumFocalPoints);
12653 ASSERT_GE(supportedNumFocalPoints, 1);
12654 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
12655 GL_FOVEATION_ENABLE_BIT_QCOM);
12656 EXPECT_GL_NO_ERROR();
12657
12658 // Set foveation parameters
12659 glTextureFoveationParametersQCOM(mFramebufferColorTexture, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12660 EXPECT_GL_NO_ERROR();
12661
12662 // Render and verify after configuring foveation on the texture
12663 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
12664 glUseProgram(blueProgram);
12665
12666 // Clear
12667 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
12668 glClear(GL_COLOR_BUFFER_BIT);
12669 EXPECT_GL_NO_ERROR();
12670
12671 // Draw
12672 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
12673 EXPECT_GL_NO_ERROR();
12674
12675 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
12676 }
12677
12678 // QCOM texture foveated rendering to MSAA texture followed by a blit
TEST_P(Texture2DTestES31Foveation,MsaaTextureDrawThenUseAsBlitSource)12679 TEST_P(Texture2DTestES31Foveation, MsaaTextureDrawThenUseAsBlitSource)
12680 {
12681 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_texture_foveated"));
12682
12683 // Create a non-foveated framebuffer
12684 GLFramebuffer framebuffer;
12685 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
12686
12687 // Create an msaa texture and bind to framebuffer
12688 GLTexture textureMS;
12689 glActiveTexture(GL_TEXTURE0);
12690 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureMS);
12691 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, getWindowWidth(),
12692 getWindowHeight(), GL_TRUE);
12693 EXPECT_GL_NO_ERROR();
12694
12695 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
12696 textureMS, 0);
12697 ASSERT_GL_NO_ERROR();
12698 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12699
12700 // Just need 1 focal point
12701 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
12702 GL_FOVEATION_ENABLE_BIT_QCOM);
12703 EXPECT_GL_NO_ERROR();
12704
12705 // Set foveation parameters
12706 glTextureFoveationParametersQCOM(textureMS, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12707 EXPECT_GL_NO_ERROR();
12708
12709 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12710 glUseProgram(program);
12711
12712 // Clear
12713 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12714 glClear(GL_COLOR_BUFFER_BIT);
12715 EXPECT_GL_NO_ERROR();
12716
12717 // Draw
12718 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
12719 EXPECT_GL_NO_ERROR();
12720
12721 // Blit data from framebuffer with foveated texture into default framebuffer
12722 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
12723 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
12724 glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
12725 getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
12726
12727 glBindFramebuffer(GL_FRAMEBUFFER, 0);
12728 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
12729 }
12730
12731 // Enabling mipmap filtering after previously having used the texture without it should work.
TEST_P(Texture2DTestES3,NoMipmapDrawThenMipmapDraw)12732 TEST_P(Texture2DTestES3, NoMipmapDrawThenMipmapDraw)
12733 {
12734 glActiveTexture(GL_TEXTURE0);
12735 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12736
12737 constexpr const GLsizei kSize = 8;
12738 const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
12739 const std::vector<GLColor> kLevelOtherData(kSize * kSize, GLColor::red);
12740
12741 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12742 kLevel0Data.data());
12743 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12744 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12745 EXPECT_GL_NO_ERROR();
12746
12747 // Draw so the texture's image is allocated.
12748 drawQuad(mProgram, "position", 0.5f);
12749 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
12750
12751 // Specify the rest of the image
12752 for (GLint mip = 1; (kSize >> mip) >= 1; ++mip)
12753 {
12754 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12755 GL_UNSIGNED_BYTE, kLevelOtherData.data());
12756 }
12757 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12758
12759 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
12760 glUseProgram(program);
12761 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
12762 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
12763 ASSERT_NE(-1, textureLoc);
12764 ASSERT_NE(-1, lodLoc);
12765 glUniform1i(textureLoc, 0);
12766
12767 // Verify the mips
12768 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12769 {
12770 glUniform1f(lodLoc, mip);
12771 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12772 EXPECT_GL_NO_ERROR();
12773 EXPECT_PIXEL_COLOR_EQ(0, 0, (mip == 0 ? kLevel0Data[0] : kLevelOtherData[0]));
12774 }
12775 }
12776
12777 // Disabling mipmap filtering after previously having used the texture with it should work.
TEST_P(Texture2DTestES3,MipmapDrawThenNoMipmapDraw)12778 TEST_P(Texture2DTestES3, MipmapDrawThenNoMipmapDraw)
12779 {
12780 glActiveTexture(GL_TEXTURE0);
12781 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12782
12783 constexpr const GLsizei kSize = 8;
12784 const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
12785 const std::vector<GLColor> kLevelOtherData(kSize * kSize, GLColor::red);
12786
12787 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12788 kLevel0Data.data());
12789 for (GLint mip = 1; (kSize >> mip) >= 1; ++mip)
12790 {
12791 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12792 GL_UNSIGNED_BYTE, kLevelOtherData.data());
12793 }
12794 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12795 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12796 EXPECT_GL_NO_ERROR();
12797
12798 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
12799 glUseProgram(program);
12800 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
12801 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
12802 ASSERT_NE(-1, textureLoc);
12803 ASSERT_NE(-1, lodLoc);
12804 glUniform1i(textureLoc, 0);
12805
12806 // Verify the mips.
12807 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12808 {
12809 glUniform1f(lodLoc, mip);
12810 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12811 EXPECT_GL_NO_ERROR();
12812 EXPECT_PIXEL_COLOR_EQ(0, 0, (mip == 0 ? kLevel0Data[0] : kLevelOtherData[0]));
12813 }
12814
12815 // Disable mipmapping and verify mips again.
12816 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12817
12818 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12819 {
12820 glUniform1f(lodLoc, mip);
12821 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12822 EXPECT_GL_NO_ERROR();
12823 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
12824 }
12825 }
12826
12827 // Respecify texture with more mips.
TEST_P(Texture2DTestES3,RespecifyWithMoreMips)12828 TEST_P(Texture2DTestES3, RespecifyWithMoreMips)
12829 {
12830 glActiveTexture(GL_TEXTURE0);
12831 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12832
12833 constexpr const GLsizei kSize = 8;
12834 const std::vector<GLColor> kLevelEvenData(kSize * kSize, GLColor::blue);
12835 const std::vector<GLColor> kLevelOddData(kSize * kSize * 4, GLColor::red);
12836
12837 auto getLevelData = [&](GLint mip) {
12838 return mip % 2 == 0 ? kLevelEvenData.data() : kLevelOddData.data();
12839 };
12840
12841 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12842 {
12843 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12844 GL_UNSIGNED_BYTE, getLevelData(mip));
12845 }
12846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12847 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12848 EXPECT_GL_NO_ERROR();
12849
12850 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
12851 glUseProgram(program);
12852 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
12853 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
12854 ASSERT_NE(-1, textureLoc);
12855 ASSERT_NE(-1, lodLoc);
12856 glUniform1i(textureLoc, 0);
12857
12858 // Verify the mips.
12859 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12860 {
12861 glUniform1f(lodLoc, mip);
12862 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12863 EXPECT_GL_NO_ERROR();
12864 EXPECT_PIXEL_COLOR_EQ(0, 0, getLevelData(mip)[0]);
12865 }
12866
12867 // Respecify the texture with more mips, without changing any parameters.
12868 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize * 2, kSize * 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12869 kLevelOddData.data());
12870 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12871 {
12872 glTexImage2D(GL_TEXTURE_2D, mip + 1, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12873 GL_UNSIGNED_BYTE, getLevelData(mip));
12874 }
12875
12876 // Verify the mips.
12877 for (GLint mip = 0; ((kSize * 2) >> mip) >= 1; ++mip)
12878 {
12879 glUniform1f(lodLoc, mip);
12880 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12881 EXPECT_GL_NO_ERROR();
12882 EXPECT_PIXEL_COLOR_EQ(0, 0, getLevelData(mip - 1)[0]);
12883 }
12884 }
12885
12886 // Covers a bug in the D3D11 backend: http://anglebug.com/42261476
12887 // When using a sampler the texture was created as if it has mipmaps,
12888 // regardless what you specified in GL_TEXTURE_MIN_FILTER via
12889 // glSamplerParameteri() -- mistakenly the default value
12890 // GL_NEAREST_MIPMAP_LINEAR or the value set via glTexParameteri() was
12891 // evaluated.
12892 // If you didn't provide mipmaps and didn't let the driver generate them
12893 // this led to not sampling your texture data when minification occurred.
TEST_P(Texture2DTestES3,MinificationWithSamplerNoMipmapping)12894 TEST_P(Texture2DTestES3, MinificationWithSamplerNoMipmapping)
12895 {
12896 constexpr char kVS[] =
12897 "#version 300 es\n"
12898 "out vec2 texcoord;\n"
12899 "in vec4 position;\n"
12900 "void main()\n"
12901 "{\n"
12902 " gl_Position = vec4(position.xy * 0.1, 0.0, 1.0);\n"
12903 " texcoord = (position.xy * 0.5) + 0.5;\n"
12904 "}\n";
12905
12906 constexpr char kFS[] =
12907 "#version 300 es\n"
12908 "precision highp float;\n"
12909 "uniform highp sampler2D tex;\n"
12910 "in vec2 texcoord;\n"
12911 "out vec4 fragColor;\n"
12912 "void main()\n"
12913 "{\n"
12914 " fragColor = texture(tex, texcoord);\n"
12915 "}\n";
12916
12917 ANGLE_GL_PROGRAM(program, kVS, kFS);
12918
12919 GLSampler sampler;
12920 glBindSampler(0, sampler);
12921 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
12922 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
12923
12924 glActiveTexture(GL_TEXTURE0);
12925 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12926
12927 const GLsizei texWidth = getWindowWidth();
12928 const GLsizei texHeight = getWindowHeight();
12929 const std::vector<GLColor> whiteData(texWidth * texHeight, GLColor::white);
12930
12931 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12932 whiteData.data());
12933 EXPECT_GL_NO_ERROR();
12934
12935 drawQuad(program, "position", 0.5f);
12936 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, angle::GLColor::white);
12937 }
12938
testUploadThenUseInDifferentStages(const std::vector<UploadThenUseStageParam> & uses)12939 void Texture2DTest::testUploadThenUseInDifferentStages(
12940 const std::vector<UploadThenUseStageParam> &uses)
12941 {
12942 constexpr char kVSSampleVS[] = R"(attribute vec4 a_position;
12943 uniform sampler2D u_tex2D;
12944 varying vec4 v_color;
12945
12946 void main()
12947 {
12948 gl_Position = vec4(a_position.xy, 0.0, 1.0);
12949 v_color = texture2D(u_tex2D, a_position.xy * 0.5 + vec2(0.5));
12950 })";
12951
12952 constexpr char kVSSampleFS[] = R"(precision mediump float;
12953 varying vec4 v_color;
12954
12955 void main()
12956 {
12957 gl_FragColor = v_color;
12958 })";
12959
12960 ANGLE_GL_PROGRAM(sampleInVS, kVSSampleVS, kVSSampleFS);
12961 ANGLE_GL_PROGRAM(sampleInFS, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
12962
12963 GLFramebuffer fbo[2];
12964 GLTexture color[2];
12965 for (uint32_t i = 0; i < 2; ++i)
12966 {
12967 glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
12968 glBindTexture(GL_TEXTURE_2D, color[i]);
12969 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
12970 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color[i], 0);
12971 }
12972
12973 const GLColor kImageColor(63, 31, 0, 255);
12974
12975 GLTexture tex;
12976 glBindTexture(GL_TEXTURE_2D, tex);
12977 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kImageColor);
12978 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12979 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12980 glActiveTexture(GL_TEXTURE0);
12981 ASSERT_GL_NO_ERROR();
12982
12983 glEnable(GL_BLEND);
12984 glBlendFunc(GL_ONE, GL_ONE);
12985
12986 glClearColor(0, 0, 0, 1);
12987
12988 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1]);
12989 glClear(GL_COLOR_BUFFER_BIT);
12990 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
12991 glClear(GL_COLOR_BUFFER_BIT);
12992
12993 uint32_t curFboIndex = 0;
12994 uint32_t fboDrawCount[2] = {};
12995
12996 for (const UploadThenUseStageParam &use : uses)
12997 {
12998 const GLProgram &program = use.useStage == GL_VERTEX_SHADER ? sampleInVS : sampleInFS;
12999 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
13000 ASSERT_GL_NO_ERROR();
13001
13002 ++fboDrawCount[curFboIndex];
13003
13004 if (use.closeRenderPassAfterUse)
13005 {
13006 // Close the render pass without accidentally incurring additional barriers.
13007 curFboIndex = 1 - curFboIndex;
13008 glBindFramebuffer(GL_FRAMEBUFFER, fbo[curFboIndex]);
13009 }
13010 }
13011
13012 // Make sure the transfer operations below aren't reordered with the rendering above and thus
13013 // introduce additional synchronization.
13014 glFinish();
13015
13016 for (uint32_t i = 0; i < 2; ++i)
13017 {
13018 const GLColor kExpectedColor(63 * std::min(4u, fboDrawCount[i]),
13019 31 * std::min(8u, fboDrawCount[i]), 0, 255);
13020
13021 glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
13022 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor);
13023 }
13024 }
13025
13026 // Test synchronization when a texture is used in different shader stages after data upload.
13027 //
13028 // - Use in VS
13029 // - Use in FS
TEST_P(Texture2DTest,UploadThenVSThenFS)13030 TEST_P(Texture2DTest, UploadThenVSThenFS)
13031 {
13032 testUploadThenUseInDifferentStages({
13033 {GL_VERTEX_SHADER, false},
13034 {GL_FRAGMENT_SHADER, false},
13035 });
13036 }
13037
13038 // Test synchronization when a texture is used in different shader stages after data upload.
13039 //
13040 // - Use in VS
13041 // - Break render pass
13042 // - Use in FS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFS)13043 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFS)
13044 {
13045 testUploadThenUseInDifferentStages({
13046 {GL_VERTEX_SHADER, true},
13047 {GL_FRAGMENT_SHADER, false},
13048 });
13049 }
13050
13051 // Test synchronization when a texture is used in different shader stages after data upload.
13052 //
13053 // - Use in FS
13054 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenVS)13055 TEST_P(Texture2DTest, UploadThenFSThenVS)
13056 {
13057 testUploadThenUseInDifferentStages({
13058 {GL_FRAGMENT_SHADER, false},
13059 {GL_VERTEX_SHADER, false},
13060 });
13061 }
13062
13063 // Test synchronization when a texture is used in different shader stages after data upload.
13064 //
13065 // - Use in FS
13066 // - Break render pass
13067 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenVS)13068 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenVS)
13069 {
13070 testUploadThenUseInDifferentStages({
13071 {GL_FRAGMENT_SHADER, true},
13072 {GL_VERTEX_SHADER, false},
13073 });
13074 }
13075
13076 // Test synchronization when a texture is used in different shader stages after data upload.
13077 //
13078 // - Use in VS
13079 // - Use in FS
13080 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenFSThenVS)13081 TEST_P(Texture2DTest, UploadThenVSThenFSThenVS)
13082 {
13083 testUploadThenUseInDifferentStages({
13084 {GL_VERTEX_SHADER, false},
13085 {GL_FRAGMENT_SHADER, false},
13086 {GL_VERTEX_SHADER, false},
13087 });
13088 }
13089
13090 // Test synchronization when a texture is used in different shader stages after data upload.
13091 //
13092 // - Use in VS
13093 // - Break render pass
13094 // - Use in FS
13095 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFSThenVS)13096 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFSThenVS)
13097 {
13098 testUploadThenUseInDifferentStages({
13099 {GL_VERTEX_SHADER, true},
13100 {GL_FRAGMENT_SHADER, false},
13101 {GL_VERTEX_SHADER, false},
13102 });
13103 }
13104
13105 // Test synchronization when a texture is used in different shader stages after data upload.
13106 //
13107 // - Use in VS
13108 // - Break render pass
13109 // - Use in FS
13110 // - Break render pass
13111 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFSThenNewRPThenVS)13112 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFSThenNewRPThenVS)
13113 {
13114 testUploadThenUseInDifferentStages({
13115 {GL_VERTEX_SHADER, true},
13116 {GL_FRAGMENT_SHADER, true},
13117 {GL_VERTEX_SHADER, false},
13118 });
13119 }
13120
13121 // Test synchronization when a texture is used in different shader stages after data upload.
13122 //
13123 // - Use in FS
13124 // - Use in VS
13125 // - Break render pass
13126 // - Use in FS
TEST_P(Texture2DTest,UploadThenFSThenVSThenNewRPThenFS)13127 TEST_P(Texture2DTest, UploadThenFSThenVSThenNewRPThenFS)
13128 {
13129 testUploadThenUseInDifferentStages({
13130 {GL_FRAGMENT_SHADER, false},
13131 {GL_VERTEX_SHADER, true},
13132 {GL_FRAGMENT_SHADER, false},
13133 });
13134 }
13135
13136 // Test synchronization when a texture is used in different shader stages after data upload.
13137 //
13138 // - Use in FS
13139 // - Break render pass
13140 // - Use in VS
13141 // - Use in FS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenVSThenFS)13142 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenVSThenFS)
13143 {
13144 testUploadThenUseInDifferentStages({
13145 {GL_FRAGMENT_SHADER, true},
13146 {GL_VERTEX_SHADER, false},
13147 {GL_FRAGMENT_SHADER, false},
13148 });
13149 }
13150
13151 // Test synchronization when a texture is used in different shader stages after data upload.
13152 //
13153 // - Use in FS
13154 // - Break render pass
13155 // - Use in FS
13156 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenFSThenVS)13157 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenFSThenVS)
13158 {
13159 testUploadThenUseInDifferentStages({
13160 {GL_FRAGMENT_SHADER, true},
13161 {GL_FRAGMENT_SHADER, false},
13162 {GL_VERTEX_SHADER, false},
13163 });
13164 }
13165
13166 // Test that interleaved updates and draw calls many times work
TEST_P(Texture2DTest,DrawThenUpdateMultipleTimes)13167 TEST_P(Texture2DTest, DrawThenUpdateMultipleTimes)
13168 {
13169 constexpr uint32_t kTexWidth = 16;
13170 constexpr uint32_t kTexHeight = 16;
13171 constexpr uint32_t kBpp = 4;
13172
13173 // Create the texture
13174 glActiveTexture(GL_TEXTURE0);
13175 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13178 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13179 nullptr);
13180 EXPECT_GL_ERROR(GL_NO_ERROR);
13181
13182 constexpr GLubyte kInitialColor = 16;
13183 GLubyte expectedFinalColorValue = kInitialColor;
13184 glEnable(GL_BLEND);
13185 glBlendFunc(GL_ONE, GL_ONE);
13186 glClearColor(0, 0, 0, 0);
13187 glClear(GL_COLOR_BUFFER_BIT);
13188
13189 // First draw the screen with initial color
13190 {
13191 ANGLE_GL_PROGRAM(colorProgram, angle::essl1_shaders::vs::Simple(),
13192 angle::essl1_shaders::fs::UniformColor());
13193 glUseProgram(colorProgram);
13194 GLint colorUniformLocation =
13195 glGetUniformLocation(colorProgram, angle::essl1_shaders::ColorUniform());
13196 ASSERT_NE(colorUniformLocation, -1);
13197 glUniform4f(colorUniformLocation, kInitialColor / 256.f, kInitialColor / 256.f,
13198 kInitialColor / 256.f, kInitialColor / 256.f);
13199 drawQuad(colorProgram, angle::essl1_shaders::PositionAttrib(), 0.5f);
13200 }
13201
13202 // Then update the texture then draw it multiple times
13203 constexpr GLubyte kColorsToUpdate[] = {16, 64, 64};
13204 setUpProgram();
13205 glUseProgram(mProgram);
13206 glUniform1i(mTexture2DUniformLocation, 0);
13207
13208 for (auto color : kColorsToUpdate)
13209 {
13210 expectedFinalColorValue += color;
13211 std::vector<GLubyte> fullTextureData(kTexWidth * kTexHeight * kBpp, color);
13212 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
13213 fullTextureData.data());
13214
13215 drawQuad(mProgram, "position", 0.5f);
13216 }
13217
13218 // The final color should be sum of all updated colors.
13219 const GLColor expectedFinalColor(expectedFinalColorValue, expectedFinalColorValue,
13220 expectedFinalColorValue, expectedFinalColorValue);
13221 EXPECT_GL_NO_ERROR();
13222 EXPECT_PIXEL_COLOR_EQ(1 * getWindowWidth() / 4, getWindowHeight() / 2, expectedFinalColor);
13223 }
13224
13225 // Test that clears due to emulated formats are to the correct level given non-zero base level.
TEST_P(Texture2DTestES3,NonZeroBaseEmulatedClear)13226 TEST_P(Texture2DTestES3, NonZeroBaseEmulatedClear)
13227 {
13228 // Tests behavior of the Vulkan backend with emulated formats.
13229 ANGLE_SKIP_TEST_IF(!IsVulkan());
13230
13231 // TODO(http://anglebug.com/42266496): Skip when using VMA image suballocation on Linux/Intel.
13232 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() &&
13233 getEGLWindow()->isFeatureEnabled(Feature::UseVmaForImageSuballocation));
13234
13235 // This test assumes GL_RGB is always emulated, which overrides the
13236 // Feature::AllocateNonZeroMemory memory feature, clearing the memory to zero. However, if the
13237 // format is *not* emulated and the feature Feature::AllocateNonZeroMemory is enabled, the
13238 // texture memory will contain non-zero memory, which means the color is not black (causing the
13239 // test to fail).
13240 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
13241
13242 setUpProgram();
13243
13244 glActiveTexture(GL_TEXTURE0);
13245 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13246 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
13247 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
13248 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 4, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
13249 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
13250 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
13251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
13252 EXPECT_GL_NO_ERROR();
13253
13254 drawQuad(mProgram, "position", 0.5f);
13255
13256 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
13257 }
13258
13259 // Test that uploading data to buffer that's in use then using it as PBO to update a texture works.
TEST_P(Texture2DTestES3,UseAsUBOThenUpdateThenAsPBO)13260 TEST_P(Texture2DTestES3, UseAsUBOThenUpdateThenAsPBO)
13261 {
13262 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
13263 GLColor::red};
13264 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
13265 GLColor::blue};
13266
13267 GLBuffer buffer;
13268 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
13269 glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_COPY);
13270 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
13271 EXPECT_GL_NO_ERROR();
13272
13273 constexpr char kVerifyUBO[] = R"(#version 300 es
13274 precision mediump float;
13275 uniform block {
13276 uvec4 data;
13277 } ubo;
13278 out vec4 colorOut;
13279 void main()
13280 {
13281 if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
13282 colorOut = vec4(0, 1.0, 0, 1.0);
13283 else
13284 colorOut = vec4(1.0, 0, 0, 1.0);
13285 })";
13286
13287 ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
13288 drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
13289 EXPECT_GL_NO_ERROR();
13290
13291 // Update buffer data
13292 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
13293 EXPECT_GL_NO_ERROR();
13294
13295 // Bind as PBO
13296 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
13297 EXPECT_GL_NO_ERROR();
13298
13299 // Upload from PBO to texture
13300 GLTexture tex;
13301 glBindTexture(GL_TEXTURE_2D, tex);
13302 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
13303 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
13304 EXPECT_GL_NO_ERROR();
13305
13306 // Make sure uniform data is correct.
13307 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
13308
13309 // Make sure the texture data is correct.
13310 GLFramebuffer fbo;
13311 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
13312 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
13313 EXPECT_GL_NO_ERROR();
13314 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
13315
13316 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13317 }
13318
13319 // Test if the RenderTargetCache is updated when the TextureStorage object is freed
TEST_P(Texture2DTestES3,UpdateRenderTargetCacheOnDestroyTexStorage)13320 TEST_P(Texture2DTestES3, UpdateRenderTargetCacheOnDestroyTexStorage)
13321 {
13322 ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
13323 const GLenum attachments[] = {GL_COLOR_ATTACHMENT0};
13324
13325 GLTexture tex;
13326 GLFramebuffer fb;
13327 glBindTexture(GL_TEXTURE_2D, tex);
13328 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 100, 1);
13329 glBindFramebuffer(GL_FRAMEBUFFER, fb);
13330 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
13331 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments);
13332 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
13333 drawQuad(drawRed, essl3_shaders::PositionAttrib(), 1.0f);
13334 EXPECT_GL_NO_ERROR();
13335
13336 EXPECT_PIXEL_RECT_EQ(0, 0, 100, 1, GLColor::red);
13337 }
13338
13339 // Test that we can allocate at least 4096 images, which is the maximum allocation count on some
13340 // platforms. Image suballocation should enable us to allocate more than this limit.
TEST_P(Texture2DTestES3,AllocateMoreThan4096Textures)13341 TEST_P(Texture2DTestES3, AllocateMoreThan4096Textures)
13342 {
13343 ANGLE_SKIP_TEST_IF(!getEGLWindow()->isFeatureEnabled(Feature::UseVmaForImageSuballocation));
13344
13345 // The test is skipped when AllocateNonZeroMemory is enabled due to risk of timeout.
13346 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
13347
13348 constexpr size_t kTextureCount = 8000;
13349 std::vector<GLTexture> textures(kTextureCount);
13350 for (auto &texture : textures)
13351 {
13352 glBindTexture(GL_TEXTURE_2D, texture);
13353 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
13354 }
13355 EXPECT_GL_NO_ERROR();
13356 }
13357
13358 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
13359 // texture is output.
TEST_P(Texture2DIntegerTestES3,IntegerTextureNonZeroBaseLevel)13360 TEST_P(Texture2DIntegerTestES3, IntegerTextureNonZeroBaseLevel)
13361 {
13362 // http://anglebug.com/40644690
13363 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
13364
13365 glActiveTexture(GL_TEXTURE0);
13366 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13367 int width = getWindowWidth();
13368 int height = getWindowHeight();
13369 GLColor color = GLColor::green;
13370 std::vector<GLColor> pixels(width * height, color);
13371 GLint baseLevel = 1;
13372 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel);
13373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13375 glTexImage2D(GL_TEXTURE_2D, baseLevel, GL_RGBA8UI, width, height, 0, GL_RGBA_INTEGER,
13376 GL_UNSIGNED_BYTE, pixels.data());
13377
13378 setUpProgram();
13379 glUseProgram(mProgram);
13380 glUniform1i(mTexture2DUniformLocation, 0);
13381 drawQuad(mProgram, "position", 0.5f);
13382
13383 EXPECT_GL_NO_ERROR();
13384 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
13385 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
13386 }
13387
13388 // Draw a quad with an integer cube texture with a non-zero base level, and test that the color of
13389 // the texture is output.
TEST_P(TextureCubeIntegerTestES3,IntegerCubeTextureNonZeroBaseLevel)13390 TEST_P(TextureCubeIntegerTestES3, IntegerCubeTextureNonZeroBaseLevel)
13391 {
13392 // All output checks returned black, rather than the texture color.
13393 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
13394
13395 glActiveTexture(GL_TEXTURE0);
13396
13397 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
13398 GLint baseLevel = 1;
13399 int width = getWindowWidth();
13400 int height = getWindowHeight();
13401 GLColor color = GLColor::green;
13402 std::vector<GLColor> pixels(width * height, color);
13403 for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
13404 {
13405 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, baseLevel, GL_RGBA8UI, width,
13406 height, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
13407 EXPECT_GL_NO_ERROR();
13408 }
13409 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, baseLevel);
13410 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13411 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13412
13413 glUseProgram(mProgram);
13414 glUniform1i(mTextureCubeUniformLocation, 0);
13415 drawQuad(mProgram, "position", 0.5f);
13416
13417 EXPECT_GL_NO_ERROR();
13418 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
13419 EXPECT_PIXEL_COLOR_EQ(width - 1, 0, color);
13420 EXPECT_PIXEL_COLOR_EQ(0, height - 1, color);
13421 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
13422 }
13423
13424 // This test sets up a cube map with four distincly colored MIP levels.
13425 // The size of the texture and the geometry is chosen such that levels 1 or 2 should be chosen at
13426 // the corners of the screen.
TEST_P(TextureCubeIntegerEdgeTestES3,IntegerCubeTextureCorner)13427 TEST_P(TextureCubeIntegerEdgeTestES3, IntegerCubeTextureCorner)
13428 {
13429 glActiveTexture(GL_TEXTURE0);
13430
13431 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
13432 int width = getWindowWidth();
13433 int height = getWindowHeight();
13434 ASSERT_EQ(width, height);
13435 GLColor color[4] = {GLColor::white, GLColor::green, GLColor::blue, GLColor::red};
13436 for (GLint level = 0; level < 4; level++)
13437 {
13438 for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
13439 {
13440 int levelWidth = (2 * width) >> level;
13441 int levelHeight = (2 * height) >> level;
13442 std::vector<GLColor> pixels(levelWidth * levelHeight, color[level]);
13443 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, GL_RGBA8UI, levelWidth,
13444 levelHeight, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
13445 EXPECT_GL_NO_ERROR();
13446 }
13447 }
13448 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
13449 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13450 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 3);
13451
13452 glUseProgram(mProgram);
13453 glUniform1i(mTextureCubeUniformLocation, 0);
13454 drawQuad(mProgram, "position", 0.5f);
13455
13456 ASSERT_GL_NO_ERROR();
13457 // Check that we do not read from levels 0 or 3. Levels 1 and 2 are both acceptable.
13458 EXPECT_EQ(ReadColor(0, 0).R, 0);
13459 EXPECT_EQ(ReadColor(width - 1, 0).R, 0);
13460 EXPECT_EQ(ReadColor(0, height - 1).R, 0);
13461 EXPECT_EQ(ReadColor(width - 1, height - 1).R, 0);
13462 }
13463
13464 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
13465 // texture is output.
TEST_P(Texture2DIntegerProjectiveOffsetTestES3,NonZeroBaseLevel)13466 TEST_P(Texture2DIntegerProjectiveOffsetTestES3, NonZeroBaseLevel)
13467 {
13468 // Fails on AMD: http://crbug.com/967796
13469 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
13470
13471 glActiveTexture(GL_TEXTURE0);
13472 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13473 int width = getWindowWidth();
13474 int height = getWindowHeight();
13475 GLColor color = GLColor::green;
13476 std::vector<GLColor> pixels(width * height, color);
13477 GLint baseLevel = 1;
13478 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel);
13479 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13480 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13481 glTexImage2D(GL_TEXTURE_2D, baseLevel, GL_RGBA8UI, width, height, 0, GL_RGBA_INTEGER,
13482 GL_UNSIGNED_BYTE, pixels.data());
13483
13484 setUpProgram();
13485 glUseProgram(mProgram);
13486 glUniform1i(mTexture2DUniformLocation, 0);
13487 drawQuad(mProgram, "position", 0.5f);
13488
13489 EXPECT_GL_NO_ERROR();
13490 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
13491 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
13492 }
13493
13494 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
13495 // texture is output.
TEST_P(Texture2DArrayIntegerTestES3,NonZeroBaseLevel)13496 TEST_P(Texture2DArrayIntegerTestES3, NonZeroBaseLevel)
13497 {
13498 // Test fail: http://anglebug.com/42264492
13499 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
13500
13501 glActiveTexture(GL_TEXTURE0);
13502 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
13503 int width = getWindowWidth();
13504 int height = getWindowHeight();
13505 int depth = 2;
13506 GLColor color = GLColor::green;
13507 std::vector<GLColor> pixels(width * height * depth, color);
13508 GLint baseLevel = 1;
13509 glTexImage3D(GL_TEXTURE_2D_ARRAY, baseLevel, GL_RGBA8UI, width, height, depth, 0,
13510 GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
13511 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, baseLevel);
13512 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13513 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13514
13515 drawQuad(mProgram, "position", 0.5f);
13516
13517 EXPECT_GL_NO_ERROR();
13518 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
13519 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
13520 }
13521
13522 // Draw a quad with an integer 3D texture with a non-zero base level, and test that the color of the
13523 // texture is output.
TEST_P(Texture3DIntegerTestES3,NonZeroBaseLevel)13524 TEST_P(Texture3DIntegerTestES3, NonZeroBaseLevel)
13525 {
13526 glActiveTexture(GL_TEXTURE0);
13527 glBindTexture(GL_TEXTURE_3D, mTexture3D);
13528 int width = getWindowWidth();
13529 int height = getWindowHeight();
13530 int depth = 2;
13531 GLColor color = GLColor::green;
13532 std::vector<GLColor> pixels(width * height * depth, color);
13533 GLint baseLevel = 1;
13534 glTexImage3D(GL_TEXTURE_3D, baseLevel, GL_RGBA8UI, width, height, depth, 0, GL_RGBA_INTEGER,
13535 GL_UNSIGNED_BYTE, pixels.data());
13536 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, baseLevel);
13537 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13538 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13539
13540 drawQuad(mProgram, "position", 0.5f);
13541
13542 EXPECT_GL_NO_ERROR();
13543 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
13544 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
13545 }
13546
runCompressedSubImage()13547 void PBOCompressedTextureTest::runCompressedSubImage()
13548 {
13549 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497
13550 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13551 // http://anglebug.com/42262750
13552 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsDesktopOpenGL());
13553 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL());
13554
13555 if (getClientMajorVersion() < 3)
13556 {
13557 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
13558 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
13559 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_ETC2_RGB8_texture"));
13560 }
13561
13562 const GLuint width = 4u;
13563 const GLuint height = 4u;
13564
13565 setWindowWidth(width);
13566 setWindowHeight(height);
13567
13568 // Setup primary Texture
13569 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13570 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
13571 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13572
13573 if (getClientMajorVersion() < 3)
13574 {
13575 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, width, height);
13576 }
13577 else
13578 {
13579 glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, width, height);
13580 }
13581 ASSERT_GL_NO_ERROR();
13582
13583 // Setup PBO and fill it with a red
13584 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
13585 glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height / 2u, kCompressedImageETC2, GL_STATIC_DRAW);
13586 ASSERT_GL_NO_ERROR();
13587
13588 // Write PBO to mTexture
13589 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_COMPRESSED_RGB8_ETC2,
13590 width * height / 2u, nullptr);
13591 ASSERT_GL_NO_ERROR();
13592
13593 setUpProgram();
13594 // Draw using PBO updated texture
13595 glUseProgram(mProgram);
13596 glUniform1i(mTexture2DUniformLocation, 0);
13597 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13598 drawQuad(mProgram, "position", 0.5f);
13599 ASSERT_GL_NO_ERROR();
13600
13601 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13602 ASSERT_GL_NO_ERROR();
13603 }
13604
13605 // Test that uses glCompressedTexSubImage2D combined with a PBO
TEST_P(PBOCompressedTextureTest,PBOCompressedSubImage)13606 TEST_P(PBOCompressedTextureTest, PBOCompressedSubImage)
13607 {
13608 runCompressedSubImage();
13609 }
13610
13611 // Verify the row length state is ignored when using compressed tex image calls.
TEST_P(PBOCompressedTextureTest,PBOCompressedSubImageWithUnpackRowLength)13612 TEST_P(PBOCompressedTextureTest, PBOCompressedSubImageWithUnpackRowLength)
13613 {
13614 // ROW_LENGTH requires ES3 or an extension.
13615 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
13616 !IsGLExtensionEnabled("GL_EXT_unpack_subimage"));
13617
13618 glPixelStorei(GL_UNPACK_ROW_LENGTH, 1);
13619 runCompressedSubImage();
13620 }
13621
13622 class PBOCompressedTexture3DTest : public ANGLETest<>
13623 {
13624 protected:
PBOCompressedTexture3DTest()13625 PBOCompressedTexture3DTest() {}
13626 };
13627
13628 // Test that uses glCompressedTexSubImage3D combined with a PBO
13629 TEST_P(PBOCompressedTexture3DTest, 2DArray)
13630 {
13631 // We use GetTexImage to determine if the internal texture format is emulated
13632 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_get_image"));
13633
13634 const GLuint width = 4u;
13635 const GLuint height = 4u;
13636 const GLuint depth = 1u;
13637
13638 setWindowWidth(width);
13639 setWindowHeight(height);
13640
13641 // Setup primary texture as a 2DArray holding ETC2 data
13642 GLTexture texture2DArray;
13643 glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
13644 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
13645 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13646 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_COMPRESSED_RGB8_ETC2, width, height, depth);
13647
13648 // If the format emulated, we can't transfer it from a PBO
13649 ANGLE_SKIP_TEST_IF(IsFormatEmulated(GL_TEXTURE_2D_ARRAY));
13650
13651 // Set up a VS that simply passes through position and texcord
13652 const char kVS[] = R"(#version 300 es
13653 in vec4 position;
13654 out vec3 texCoord;
13655
13656 void main()
13657 {
13658 gl_Position = vec4(position.xy, 0.0, 1.0);
13659 texCoord = vec3(position.xy * 0.5 + vec2(0.5), 0.0);
13660 })";
13661
13662 // and FS that pulls from the 2DArray, writing out color
13663 const char kFS[] = R"(#version 300 es
13664 precision mediump float;
13665 uniform highp sampler2DArray tex2DArray;
13666 in vec3 texCoord;
13667 out vec4 fragColor;
13668
13669 void main()
13670 {
13671 fragColor = texture(tex2DArray, texCoord);
13672 })";
13673
13674 // Compile the shaders and create the program
13675 ANGLE_GL_PROGRAM(program, kVS, kFS);
13676 ASSERT_GL_NO_ERROR();
13677
13678 // Setup PBO and fill it with a red
13679 GLBuffer pbo;
13680 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
13681 glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * depth / 2u, kCompressedImageETC2,
13682 GL_STATIC_DRAW);
13683 ASSERT_GL_NO_ERROR();
13684
13685 // Write PBO to texture2DArray
13686 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, depth,
13687 GL_COMPRESSED_RGB8_ETC2, width * height * depth / 2u, nullptr);
13688
13689 ASSERT_GL_NO_ERROR();
13690
13691 // Draw using PBO updated texture
13692 glUseProgram(program);
13693 glUniform1i(glGetUniformLocation(program, "tex2DArray"), 0);
13694 glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
13695 drawQuad(program, "position", 0.5f);
13696 ASSERT_GL_NO_ERROR();
13697
13698 // Verify the texture now contains data from the PBO
13699 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13700 ASSERT_GL_NO_ERROR();
13701 }
13702
13703 // Test using ETC1_RGB8 with subimage updates
TEST_P(ETC1CompressedTextureTest,ETC1CompressedSubImage)13704 TEST_P(ETC1CompressedTextureTest, ETC1CompressedSubImage)
13705 {
13706 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497
13707 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13708
13709 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
13710 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
13711 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13712
13713 const GLuint width = 4u;
13714 const GLuint height = 4u;
13715
13716 setWindowWidth(width);
13717 setWindowHeight(height);
13718
13719 // Setup primary Texture
13720 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
13721 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13722
13723 if (getClientMajorVersion() < 3)
13724 {
13725 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
13726 }
13727 else
13728 {
13729 glTexStorage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
13730 }
13731 ASSERT_GL_NO_ERROR();
13732
13733 // Populate a subimage of the texture
13734 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ETC1_RGB8_OES,
13735 width * height / 2u, kCompressedImageETC2);
13736 ASSERT_GL_NO_ERROR();
13737
13738 // Render and ensure we get red
13739 glUseProgram(mProgram);
13740 drawQuad(mProgram, "position", 0.5f);
13741 ASSERT_GL_NO_ERROR();
13742
13743 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13744 ASSERT_GL_NO_ERROR();
13745 }
13746
13747 // Fully-define a NPOT compressed texture and draw; set MAX_LEVEL and draw; then increase
13748 // MAX_LEVEL and draw. This used to cause Vulkan validation errors.
TEST_P(ETC1CompressedTextureTest,ETC1CompressedImageNPOT)13749 TEST_P(ETC1CompressedTextureTest, ETC1CompressedImageNPOT)
13750 {
13751 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497
13752 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13753
13754 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
13755 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13756
13757 const GLuint width = 5u;
13758 const GLuint height = 5u;
13759 // round up to the nearest block size
13760 const GLsizei imageSize = 8 * 8 / 2;
13761 // smallest block size
13762 const GLsizei minImageSize = 4 * 4 / 2;
13763
13764 uint8_t data[imageSize] = {0};
13765
13766 setWindowWidth(width);
13767 setWindowHeight(height);
13768
13769 // Setup primary Texture
13770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
13771 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
13772 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13773 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13774
13775 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, width, height, 0, imageSize, data);
13776 ASSERT_GL_NO_ERROR();
13777
13778 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width / 2, height / 2, 0,
13779 minImageSize, data);
13780 ASSERT_GL_NO_ERROR();
13781
13782 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_ETC1_RGB8_OES, width / 4, height / 4, 0,
13783 minImageSize, data);
13784 ASSERT_GL_NO_ERROR();
13785
13786 glUseProgram(mProgram);
13787 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13788 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13789 drawQuad(mProgram, "position", 0.5f);
13790 ASSERT_GL_NO_ERROR();
13791
13792 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
13793 drawQuad(mProgram, "position", 0.5f);
13794 ASSERT_GL_NO_ERROR();
13795 }
13796
13797 // Define two NPOT compressed textures, set MAX_LEVEL, draw, and swap buffers
13798 // with the two textures. This used to cause release of staging buffers
13799 // that have not been flushed.
TEST_P(ETC1CompressedTextureTest,ETC1CompressedImageDraws)13800 TEST_P(ETC1CompressedTextureTest, ETC1CompressedImageDraws)
13801 {
13802 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497
13803 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13804
13805 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
13806 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13807
13808 const GLuint width = 384u;
13809 const GLuint height = 384u;
13810 // round up to the nearest block size
13811 const GLsizei imageSize = width * height / 2;
13812
13813 uint8_t data[imageSize] = {0};
13814
13815 setWindowWidth(width);
13816 setWindowHeight(height);
13817
13818 const GLuint smallerWidth = 384u;
13819 const GLuint smallerHeight = 320u;
13820 // round up to the nearest block size
13821 const GLsizei smallerImageSize = smallerWidth * smallerHeight / 2;
13822
13823 // Setup primary Texture
13824 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
13825 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
13826 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13827 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13828
13829 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, smallerWidth, smallerHeight, 0,
13830 smallerImageSize, data);
13831 ASSERT_GL_NO_ERROR();
13832
13833 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 192, 160, 0, 15360, data);
13834 ASSERT_GL_NO_ERROR();
13835
13836 GLTexture largerTexture;
13837 glBindTexture(GL_TEXTURE_2D, largerTexture);
13838
13839 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, width, height, 0, imageSize, data);
13840 ASSERT_GL_NO_ERROR();
13841
13842 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 192, 192, 0, 18432, data);
13843 ASSERT_GL_NO_ERROR();
13844
13845 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13846
13847 glUseProgram(mProgram);
13848 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13849 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13850 drawQuad(mProgram, "position", 0.5f);
13851 ASSERT_GL_NO_ERROR();
13852 swapBuffers();
13853 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
13854 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
13855 drawQuad(mProgram, "position", 0.5f);
13856 ASSERT_GL_NO_ERROR();
13857 swapBuffers();
13858
13859 glBindTexture(GL_TEXTURE_2D, largerTexture);
13860
13861 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13862 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13863 drawQuad(mProgram, "position", 0.5f);
13864 ASSERT_GL_NO_ERROR();
13865 swapBuffers();
13866
13867 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
13868 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
13869 drawQuad(mProgram, "position", 0.5f);
13870 ASSERT_GL_NO_ERROR();
13871 swapBuffers();
13872
13873 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13874
13875 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13876 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13877 drawQuad(mProgram, "position", 0.5f);
13878 swapBuffers();
13879 ASSERT_GL_NO_ERROR();
13880 }
13881
13882 // Fully-define a compressed texture and draw; then decrease MAX_LEVEL and draw; then increase
13883 // MAX_LEVEL and draw. This used to cause Vulkan validation errors.
TEST_P(ETC1CompressedTextureTest,ETC1ShrinkThenGrowMaxLevels)13884 TEST_P(ETC1CompressedTextureTest, ETC1ShrinkThenGrowMaxLevels)
13885 {
13886 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497
13887 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13888
13889 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
13890 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13891
13892 const GLuint width = 4u;
13893 const GLuint height = 4u;
13894
13895 setWindowWidth(width);
13896 setWindowHeight(height);
13897
13898 // Setup primary Texture
13899 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
13900 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13901
13902 if (getClientMajorVersion() < 3)
13903 {
13904 glTexStorage2DEXT(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, width, height);
13905 }
13906 else
13907 {
13908 glTexStorage2D(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, width, height);
13909 }
13910 ASSERT_GL_NO_ERROR();
13911
13912 // Populate a subimage of the texture
13913 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ETC1_RGB8_OES,
13914 width * height / 2u, kCompressedImageETC2);
13915 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, width / 2, height / 2, GL_ETC1_RGB8_OES,
13916 width * height / 2u, kCompressedImageETC2);
13917 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, width / 4, height / 4, GL_ETC1_RGB8_OES,
13918 width * height / 2u, kCompressedImageETC2);
13919 ASSERT_GL_NO_ERROR();
13920
13921 // Set MAX_LEVEL to 2 (the highest level)
13922 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
13923
13924 // Render and ensure we get red
13925 glUseProgram(mProgram);
13926 drawQuad(mProgram, "position", 0.5f);
13927 ASSERT_GL_NO_ERROR();
13928 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13929 ASSERT_GL_NO_ERROR();
13930
13931 // Decrease MAX_LEVEL to 0, render, and ensure we still get red
13932 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13933 drawQuad(mProgram, "position", 0.5f);
13934 ASSERT_GL_NO_ERROR();
13935 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13936 ASSERT_GL_NO_ERROR();
13937
13938 // Increase MAX_LEVEL back to 2, render, and ensure we still get red
13939 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
13940 drawQuad(mProgram, "position", 0.5f);
13941 ASSERT_GL_NO_ERROR();
13942 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13943 ASSERT_GL_NO_ERROR();
13944 }
13945
13946 class TextureBufferTestES31 : public ANGLETest<>
13947 {
13948 protected:
TextureBufferTestES31()13949 TextureBufferTestES31() {}
13950
13951 void drawWithIncompleteOrZeroTexture(bool useCompleteTexture, bool useNonZeroTexture);
13952 };
13953
drawWithIncompleteOrZeroTexture(bool useCompleteTexture,bool useNonZeroTexture)13954 void TextureBufferTestES31::drawWithIncompleteOrZeroTexture(bool useCompleteTexture,
13955 bool useNonZeroTexture)
13956 {
13957 constexpr char kSamplerBuffer[] = R"(#version 310 es
13958 #extension GL_OES_texture_buffer : require
13959 precision mediump float;
13960 uniform highp samplerBuffer s;
13961 out vec4 colorOut;
13962 void main()
13963 {
13964 colorOut = texelFetch(s, 0);
13965 })";
13966
13967 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kSamplerBuffer);
13968 glUseProgram(program);
13969 EXPECT_GL_NO_ERROR();
13970
13971 // Bind as texture buffer
13972 GLTexture texture;
13973 glActiveTexture(GL_TEXTURE0);
13974 glBindTexture(GL_TEXTURE_BUFFER, useNonZeroTexture ? texture.get() : 0u);
13975 EXPECT_GL_NO_ERROR();
13976
13977 if (useCompleteTexture)
13978 {
13979 const std::array<GLColor, 4> kData = {GLColor::blue, GLColor::blue, GLColor::blue,
13980 GLColor::blue};
13981
13982 // Create buffer and initialize with data
13983 GLBuffer buffer;
13984 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13985 glBufferData(GL_TEXTURE_BUFFER, sizeof(kData), kData.data(), GL_DYNAMIC_DRAW);
13986 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13987 EXPECT_GL_NO_ERROR();
13988 }
13989
13990 // Draw texture buffer
13991 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
13992 EXPECT_GL_NO_ERROR();
13993
13994 if (useCompleteTexture)
13995 {
13996 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13997 }
13998 }
13999
14000 // Test that mutating a buffer attached to a texture returns correct results in query.
TEST_P(TextureBufferTestES31,QueryWidthAfterBufferResize)14001 TEST_P(TextureBufferTestES31, QueryWidthAfterBufferResize)
14002 {
14003 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
14004
14005 constexpr GLint kInitialSize = 128;
14006 constexpr std::array<GLint, 4> kModifiedSizes = {96, 192, 32, 256};
14007
14008 GLTexture texture;
14009 glBindTexture(GL_TEXTURE_BUFFER, texture);
14010
14011 GLBuffer buffer;
14012 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
14013 glBufferData(GL_TEXTURE_BUFFER, kInitialSize, nullptr, GL_STATIC_DRAW);
14014
14015 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
14016 ASSERT_GL_NO_ERROR();
14017
14018 GLint queryResult = 0;
14019 glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
14020 ASSERT_GL_NO_ERROR();
14021 EXPECT_EQ(queryResult, kInitialSize / 4);
14022
14023 for (GLint modifiedSize : kModifiedSizes)
14024 {
14025 glBufferData(GL_TEXTURE_BUFFER, modifiedSize, nullptr, GL_STATIC_DRAW);
14026 glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
14027 ASSERT_GL_NO_ERROR();
14028 EXPECT_EQ(queryResult, modifiedSize / 4);
14029 }
14030 }
14031
14032 // Test that glTexBufferEXT can be used in two draw calls.
14033 // Covers a bug where TextureVk::setBuffer releases buffer views and doesn't init them.
TEST_P(TextureBufferTestES31,TexBufferDrawTwice)14034 TEST_P(TextureBufferTestES31, TexBufferDrawTwice)
14035 {
14036 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
14037
14038 // TODO(http://anglebug.com/42264369): Claims to support GL_OES_texture_buffer, but fails
14039 // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported".
14040 ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
14041
14042 const std::array<GLColor, 1> kTexData = {GLColor::red};
14043
14044 GLBuffer buffer;
14045 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
14046 glBufferData(GL_TEXTURE_BUFFER, sizeof(kTexData), kTexData.data(), GL_DYNAMIC_DRAW);
14047 EXPECT_GL_NO_ERROR();
14048
14049 constexpr char kSamplerBuffer[] = R"(#version 310 es
14050 #extension GL_OES_texture_buffer : require
14051 precision mediump float;
14052 uniform highp samplerBuffer s;
14053 out vec4 colorOut;
14054 void main()
14055 {
14056 colorOut = texelFetch(s, 0);
14057 })";
14058
14059 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kSamplerBuffer);
14060
14061 // Draw once
14062 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
14063 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
14064 EXPECT_GL_NO_ERROR();
14065
14066 // Draw twice
14067 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
14068 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
14069 EXPECT_GL_NO_ERROR();
14070
14071 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
14072 }
14073
14074 // Test that uploading data to buffer that's in use then using it as texture buffer works.
TEST_P(TextureBufferTestES31,UseAsUBOThenUpdateThenAsTextureBuffer)14075 TEST_P(TextureBufferTestES31, UseAsUBOThenUpdateThenAsTextureBuffer)
14076 {
14077 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
14078
14079 // Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension
14080 // 'GL_OES_texture_buffer' is not supported". http://anglebug.com/42264369
14081 ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
14082
14083 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
14084 GLColor::red};
14085 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
14086 GLColor::blue};
14087
14088 GLBuffer buffer;
14089 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
14090 glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
14091 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
14092 EXPECT_GL_NO_ERROR();
14093
14094 constexpr char kVerifyUBO[] = R"(#version 310 es
14095 precision mediump float;
14096 layout(binding = 0) uniform block {
14097 uvec4 data;
14098 } ubo;
14099 out vec4 colorOut;
14100 void main()
14101 {
14102 if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
14103 colorOut = vec4(0, 1.0, 0, 1.0);
14104 else
14105 colorOut = vec4(1.0, 0, 0, 1.0);
14106 })";
14107
14108 ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
14109 drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
14110 EXPECT_GL_NO_ERROR();
14111
14112 // Update buffer data
14113 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
14114 EXPECT_GL_NO_ERROR();
14115
14116 // Bind as texture buffer
14117 GLTexture texture;
14118 glBindTexture(GL_TEXTURE_BUFFER, texture);
14119 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
14120 EXPECT_GL_NO_ERROR();
14121
14122 constexpr char kVerifySamplerBuffer[] = R"(#version 310 es
14123 #extension GL_OES_texture_buffer : require
14124 precision mediump float;
14125 uniform highp samplerBuffer s;
14126 out vec4 colorOut;
14127 void main()
14128 {
14129 colorOut = texelFetch(s, 0);
14130 })";
14131
14132 ANGLE_GL_PROGRAM(verifySamplerBuffer, essl31_shaders::vs::Simple(), kVerifySamplerBuffer);
14133
14134 glEnable(GL_BLEND);
14135 glBlendFunc(GL_ONE, GL_ONE);
14136 drawQuad(verifySamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
14137 EXPECT_GL_NO_ERROR();
14138
14139 // Make sure both draw calls succeed
14140 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
14141 }
14142
14143 // Test that mapping a texture buffer with GL_MAP_INVALIDATE_BUFFER_BIT and writing to it works
14144 // correctly.
TEST_P(TextureBufferTestES31,MapTextureBufferInvalidateThenWrite)14145 TEST_P(TextureBufferTestES31, MapTextureBufferInvalidateThenWrite)
14146 {
14147 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
14148
14149 // TODO(http://anglebug.com/42264369): Claims to support GL_OES_texture_buffer, but fails
14150 // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported".
14151 ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
14152 // TODO(http://anglebug.com/42264910): The OpenGL backend doesn't correctly handle texture
14153 // buffers being invalidated when mapped.
14154 ANGLE_SKIP_TEST_IF(IsOpenGL());
14155
14156 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
14157 GLColor::red};
14158 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
14159 GLColor::blue};
14160
14161 GLBuffer buffer;
14162 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
14163 glBufferData(GL_TEXTURE_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
14164 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
14165 EXPECT_GL_NO_ERROR();
14166
14167 // Bind as texture buffer
14168 GLTexture texture;
14169 glBindTexture(GL_TEXTURE_BUFFER, texture);
14170 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
14171 EXPECT_GL_NO_ERROR();
14172
14173 constexpr char kSamplerBuffer[] = R"(#version 310 es
14174 #extension GL_OES_texture_buffer : require
14175 precision mediump float;
14176 uniform highp samplerBuffer s;
14177 out vec4 colorOut;
14178 void main()
14179 {
14180 colorOut = texelFetch(s, 0);
14181 })";
14182
14183 ANGLE_GL_PROGRAM(initialSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
14184 drawQuad(initialSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
14185 EXPECT_GL_NO_ERROR();
14186
14187 // Don't read back, so we don't break the render pass.
14188
14189 // Map the buffer and update it.
14190 void *mappedBuffer = glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(kInitialData),
14191 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
14192 memcpy(mappedBuffer, kUpdateData.data(), sizeof(kInitialData));
14193
14194 glUnmapBuffer(GL_TEXTURE_BUFFER);
14195
14196 // Draw with the updated buffer data.
14197 ANGLE_GL_PROGRAM(updateSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
14198 drawQuad(updateSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
14199 EXPECT_GL_NO_ERROR();
14200
14201 // Make sure both draw calls succeed
14202 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
14203 }
14204
14205 // Test that calling glBufferData on a buffer that is used as texture buffer still works correctly.
TEST_P(TextureBufferTestES31,TextureBufferThenBufferData)14206 TEST_P(TextureBufferTestES31, TextureBufferThenBufferData)
14207 {
14208 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
14209
14210 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
14211 GLColor::red};
14212 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
14213 GLColor::blue};
14214 // Create buffer and initialize with data
14215 GLBuffer buffer;
14216 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
14217 glBufferData(GL_TEXTURE_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
14218
14219 // Bind as texture buffer
14220 GLTexture texture;
14221 glBindTexture(GL_TEXTURE_BUFFER, texture);
14222 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
14223 EXPECT_GL_NO_ERROR();
14224
14225 constexpr char kSamplerBuffer[] = R"(#version 310 es
14226 #extension GL_OES_texture_buffer : require
14227 precision mediump float;
14228 uniform highp samplerBuffer s;
14229 out vec4 colorOut;
14230 void main()
14231 {
14232 colorOut = texelFetch(s, 0);
14233 })";
14234
14235 ANGLE_GL_PROGRAM(initialSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
14236 drawQuad(initialSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
14237
14238 // Don't read back, so we keep the original buffer busy. Issue a glBufferData call with same
14239 // size and nullptr so that the old buffer storage gets orphaned.
14240 glBufferData(GL_TEXTURE_BUFFER, sizeof(kUpdateData), nullptr, GL_DYNAMIC_DRAW);
14241 glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(kUpdateData), kUpdateData.data());
14242
14243 // Draw with the updated buffer data.
14244 ANGLE_GL_PROGRAM(updateSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
14245 drawQuad(updateSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
14246 EXPECT_GL_NO_ERROR();
14247 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
14248 }
14249
14250 // Test workaround in Vulkan backend for mismatched texture buffer and sampler formats
TEST_P(TextureBufferTestES31,TexBufferFormatMismatch)14251 TEST_P(TextureBufferTestES31, TexBufferFormatMismatch)
14252 {
14253 ANGLE_SKIP_TEST_IF(!IsVulkan());
14254 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
14255
14256 auto runTestCase = [&](auto texData, GLenum format, const char *samplerType) {
14257 std::stringstream fsStream;
14258 fsStream << R"(#version 310 es
14259 #extension GL_EXT_texture_buffer : require
14260 precision mediump float;
14261 uniform highp )"
14262 << samplerType << R"( s;
14263 out vec4 colorOut;
14264 void main()
14265 {
14266 colorOut = vec4(texelFetch(s, 0).r, 0, 0, 1);
14267 })";
14268 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fsStream.str().c_str());
14269
14270 GLBuffer buffer;
14271 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
14272
14273 glBufferData(GL_TEXTURE_BUFFER, sizeof(texData), texData.data(), GL_DYNAMIC_DRAW);
14274 glTexBufferEXT(GL_TEXTURE_BUFFER, format, buffer);
14275
14276 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
14277 EXPECT_GL_NO_ERROR();
14278 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
14279 };
14280
14281 const std::array<uint8_t, 4> kTexData8n{255}; // 8-bit normalized {1,0,0,0}
14282 const std::array<uint8_t, 4> kTexData8i{1}; // 8-bit (u)int {1,0,0,0}
14283
14284 // Test all 8-bit formats from EXT_texture_buffer.txt Table texbo.1
14285 for (auto format :
14286 {GL_R8, GL_R8I, GL_R8UI, GL_RG8, GL_RG8I, GL_RG8UI, GL_RGBA8, GL_RGBA8I, GL_RGBA8UI})
14287 {
14288 // float sampler
14289 runTestCase(kTexData8n, format, "samplerBuffer");
14290 // integer samplers
14291 runTestCase(kTexData8i, format, "isamplerBuffer");
14292 runTestCase(kTexData8i, format, "usamplerBuffer");
14293 }
14294
14295 const uint16_t kHalfFloatOne = 0x3C00;
14296 const std::array<uint16_t, 4> kTexData16f{kHalfFloatOne}; // 16-bit float {1,0,0,0}
14297 const std::array<uint16_t, 4> kTexData16i{1}; // 16-bit (u)int {1,0,0,0}
14298
14299 // Test all 16-bit formats from EXT_texture_buffer.txt Table texbo.1
14300 for (auto format : {GL_R16F, GL_R16I, GL_R16UI, GL_RG16F, GL_RG16I, GL_RG16UI, GL_RGBA16F,
14301 GL_RGBA16I, GL_RGBA16UI})
14302 {
14303 // float sampler
14304 runTestCase(kTexData16f, format, "samplerBuffer");
14305 // integer samplers
14306 runTestCase(kTexData16i, format, "isamplerBuffer");
14307 runTestCase(kTexData16i, format, "usamplerBuffer");
14308 }
14309
14310 const std::array<GLfloat, 4> kTexData32f{1.0f}; // 32-bit float {1,0,0,0}
14311 const std::array<uint32_t, 4> kTexData32i{1}; // 32-bit (u)int {1,0,0,0}
14312
14313 // Test all 32-bit formats from EXT_texture_buffer.txt Table texbo.1
14314 for (auto format : {GL_R32F, GL_R32I, GL_R32UI, GL_RG32F, GL_RG32I, GL_RG32UI, GL_RGB32F,
14315 GL_RGB32I, GL_RGB32UI, GL_RGBA32F, GL_RGBA32I, GL_RGBA32UI})
14316 {
14317 // float sampler
14318 runTestCase(kTexData32f, format, "samplerBuffer");
14319 // integer samplers
14320 runTestCase(kTexData32i, format, "isamplerBuffer");
14321 runTestCase(kTexData32i, format, "usamplerBuffer");
14322 }
14323 }
14324
14325 // Create an integer format texture but specify a FLOAT sampler. OpenGL
14326 // tolerates this but it causes a Vulkan validation error.
TEST_P(Texture2DTestES3,TexImageFormatMismatch)14327 TEST_P(Texture2DTestES3, TexImageFormatMismatch)
14328 {
14329 GLint textureUnit = 2;
14330 GLuint genericBuffer;
14331 GLubyte genericBufferMemory[1024];
14332 GLuint texture;
14333 GLuint sampler;
14334 GLuint vertexArray;
14335
14336 glGenBuffers(1, &genericBuffer);
14337 glBindBuffer(GL_ARRAY_BUFFER, genericBuffer);
14338 glBufferData(GL_ARRAY_BUFFER, 1024, &genericBufferMemory, GL_STATIC_DRAW);
14339
14340 glGenTextures(1, &texture);
14341 glBindTexture(GL_TEXTURE_2D, texture);
14342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
14343 glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, 8, 8, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT,
14344 &genericBufferMemory);
14345
14346 const char *vertexShaderSource = getVertexShaderSource();
14347 const char *fragmentShaderSource = getFragmentShaderSource();
14348 ANGLE_GL_PROGRAM(testProgram, vertexShaderSource, fragmentShaderSource);
14349
14350 GLint texLocation = glGetUniformLocation(testProgram, "tex");
14351 glUseProgram(testProgram);
14352
14353 glUniform1iv(texLocation, 1, &textureUnit);
14354
14355 glGenSamplers(1, &sampler);
14356 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14357 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14358
14359 glBindBuffer(GL_UNIFORM_BUFFER, genericBuffer);
14360
14361 glActiveTexture(GL_TEXTURE0 + textureUnit);
14362 glBindTexture(GL_TEXTURE_2D, texture);
14363 glBindSampler(textureUnit, sampler);
14364
14365 glGenVertexArrays(1, &vertexArray);
14366 glBindVertexArray(vertexArray);
14367 glBindBuffer(GL_ARRAY_BUFFER, genericBuffer);
14368
14369 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, genericBuffer);
14370 glBindVertexArray(vertexArray);
14371 glDrawElementsInstanced(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, 0, 1);
14372 }
14373
14374 // Checks that drawing incomplete zero texture buffer does not crash.
TEST_P(TextureBufferTestES31,DrawIncompleteZeroTexture)14375 TEST_P(TextureBufferTestES31, DrawIncompleteZeroTexture)
14376 {
14377 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
14378
14379 drawWithIncompleteOrZeroTexture(false, false);
14380 }
14381
14382 // Checks that drawing incomplete non-zero texture buffer does not crash.
TEST_P(TextureBufferTestES31,DrawIncompleteNonZeroTexture)14383 TEST_P(TextureBufferTestES31, DrawIncompleteNonZeroTexture)
14384 {
14385 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
14386
14387 drawWithIncompleteOrZeroTexture(false, true);
14388 }
14389
14390 // Checks that drawing complete zero texture buffer produces expected results.
TEST_P(TextureBufferTestES31,DrawCompleteZeroTexture)14391 TEST_P(TextureBufferTestES31, DrawCompleteZeroTexture)
14392 {
14393 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
14394
14395 drawWithIncompleteOrZeroTexture(true, false);
14396 }
14397
14398 // Checks that drawing complete non-zero texture buffer produces expected results.
TEST_P(TextureBufferTestES31,DrawCompleteNonZeroTexture)14399 TEST_P(TextureBufferTestES31, DrawCompleteNonZeroTexture)
14400 {
14401 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
14402
14403 drawWithIncompleteOrZeroTexture(true, true);
14404 }
14405
14406 // Test that the correct error is generated if texture buffer support used anyway when not enabled.
TEST_P(TextureBufferTestES31,TestErrorWhenNotEnabled)14407 TEST_P(TextureBufferTestES31, TestErrorWhenNotEnabled)
14408 {
14409 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_texture_buffer"));
14410
14411 GLTexture texture;
14412 glBindTexture(GL_TEXTURE_BUFFER, texture);
14413 ASSERT_GL_ERROR(GL_INVALID_ENUM);
14414 }
14415
14416 class CopyImageTestES31 : public ANGLETest<>
14417 {
14418 protected:
CopyImageTestES31()14419 CopyImageTestES31() {}
14420 };
14421
14422 // Test that copies between RGB formats doesn't affect the emulated alpha channel, if any.
TEST_P(CopyImageTestES31,PreserveEmulatedAlpha)14423 TEST_P(CopyImageTestES31, PreserveEmulatedAlpha)
14424 {
14425 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
14426
14427 constexpr GLsizei kSize = 1;
14428
14429 GLTexture src, dst;
14430
14431 // Set up the textures
14432 glBindTexture(GL_TEXTURE_2D, src);
14433 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, kSize, kSize);
14434
14435 const GLColor kInitColor(50, 100, 150, 200);
14436 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGB, GL_UNSIGNED_BYTE, &kInitColor);
14437
14438 glBindTexture(GL_TEXTURE_2D, dst);
14439 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8UI, kSize, kSize);
14440 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14441 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14442
14443 // Copy from src to dst
14444 glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
14445 kSize, 1);
14446
14447 // Bind dst as image
14448 glBindImageTexture(0, dst, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
14449
14450 // Create a buffer for output
14451 constexpr GLsizei kBufferSize = kSize * kSize * sizeof(uint32_t) * 4;
14452 GLBuffer buffer;
14453 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
14454 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
14455 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer);
14456
14457 constexpr char kCS[] = R"(#version 310 es
14458 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
14459 layout(rgba8ui, binding = 0) readonly uniform highp uimage2D imageIn;
14460 layout(std140, binding = 1) buffer dataOut {
14461 uvec4 data[];
14462 };
14463 void main()
14464 {
14465 uvec4 color = imageLoad(imageIn, ivec2(0));
14466 data[0] = color;
14467 })";
14468
14469 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14470 glUseProgram(program);
14471 glDispatchCompute(1, 1, 1);
14472 EXPECT_GL_NO_ERROR();
14473
14474 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
14475
14476 const uint32_t *ptr = reinterpret_cast<uint32_t *>(
14477 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
14478
14479 EXPECT_EQ(ptr[0], kInitColor.R);
14480 EXPECT_EQ(ptr[1], kInitColor.G);
14481 EXPECT_EQ(ptr[2], kInitColor.B);
14482
14483 // Expect alpha to be 1, even if the RGB format is emulated with RGBA.
14484 EXPECT_EQ(ptr[3], 1u);
14485
14486 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
14487 }
14488
14489 // Verify a common pattern used by the Unreal Engine that trips up the tracer
TEST_P(CopyImageTestES31,CubeMapCopyImageSubData)14490 TEST_P(CopyImageTestES31, CubeMapCopyImageSubData)
14491 {
14492 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
14493
14494 constexpr char kVS[] =
14495 R"(#version 300 es
14496 precision mediump float;
14497 in vec3 pos;
14498 void main() {
14499 gl_Position = vec4(pos, 1.0);
14500 })";
14501
14502 constexpr char kFS[] =
14503 R"(#version 300 es
14504 precision mediump float;
14505 out vec4 color;
14506 uniform samplerCube uTex;
14507 void main(){
14508 // sample from lod 1.0
14509 color = textureLod(uTex, vec3(1.0), 1.0);
14510 })";
14511
14512 ANGLE_GL_PROGRAM(program, kVS, kFS);
14513 glUseProgram(program);
14514
14515 // Set up two cube maps, then verify we can copy between them
14516 constexpr size_t kSize = 2;
14517 constexpr int levels = 2;
14518 std::vector<GLColor> pixelsGreen(kSize * kSize, GLColor::green);
14519 std::vector<GLColor> pixelsRed(kSize * kSize, GLColor::red);
14520
14521 // Initialize src to green
14522 GLTexture texCubeSrc;
14523 glBindTexture(GL_TEXTURE_CUBE_MAP, texCubeSrc);
14524 for (int i = 0; i < levels; i++)
14525 {
14526 for (GLenum face = 0; face < 6; face++)
14527 {
14528 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, GL_RGBA, kSize >> i, kSize >> i,
14529 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsGreen.data());
14530 }
14531 }
14532 ASSERT_GL_NO_ERROR();
14533
14534 // Initialize dst to red
14535 GLTexture texCubeDst;
14536 glBindTexture(GL_TEXTURE_CUBE_MAP, texCubeDst);
14537 for (int i = 0; i < levels; i++)
14538 {
14539 for (GLenum face = 0; face < 6; face++)
14540 {
14541 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, GL_RGBA, kSize >> i, kSize >> i,
14542 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
14543 }
14544 }
14545 ASSERT_GL_NO_ERROR();
14546
14547 // Clear to blue
14548 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
14549 glClear(GL_COLOR_BUFFER_BIT);
14550 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
14551
14552 // Sample from the dst texture to ensure it has the right color
14553 GLint textureLoc = glGetUniformLocation(program, "uTex");
14554 ASSERT_NE(-1, textureLoc);
14555 glUniform1i(textureLoc, 0);
14556
14557 // Draw once and sample from level 1, which is red
14558 drawQuad(program, "pos", 0.5f);
14559 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
14560
14561 // Swap to trigger MEC
14562 swapBuffers();
14563
14564 // Copy level 1 from src to dst
14565 glCopyImageSubDataEXT(texCubeSrc, GL_TEXTURE_CUBE_MAP, 1, 0, 0, 0, texCubeDst,
14566 GL_TEXTURE_CUBE_MAP, 1, 0, 0, 0, kSize >> 1, kSize >> 1, 6);
14567 ASSERT_GL_NO_ERROR();
14568
14569 // Draw again and verify we get green
14570 drawQuad(program, "pos", 0.5f);
14571 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14572
14573 // Swap again to end the capture
14574 swapBuffers();
14575
14576 ASSERT_GL_NO_ERROR();
14577 }
14578
14579 // Verify that copies between texture layers works, including when there is a read after write in a
14580 // level/layer.
TEST_P(CopyImageTestES31,ArraySelfCopyImageSubDataWithReadAfterWrite)14581 TEST_P(CopyImageTestES31, ArraySelfCopyImageSubDataWithReadAfterWrite)
14582 {
14583 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
14584
14585 // Set up a texture with multiple layers, then verify we can copy between them
14586 constexpr uint32_t kWidth = 13;
14587 constexpr uint32_t kHeight = 57;
14588 constexpr uint32_t kLayers = 5;
14589 constexpr uint32_t kLevels = 2;
14590 std::vector<GLColor> pixelsRed(kWidth * kHeight, GLColor::red);
14591 std::vector<GLColor> pixelsGreen(kWidth * kHeight, GLColor::green);
14592 std::vector<GLColor> pixelsBlue(kWidth * kHeight, GLColor::blue);
14593
14594 const GLColor *colors[3] = {
14595 pixelsRed.data(),
14596 pixelsGreen.data(),
14597 pixelsBlue.data(),
14598 };
14599
14600 GLTexture tex;
14601 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
14602 glTexStorage3D(GL_TEXTURE_2D_ARRAY, kLevels, GL_RGBA8, kWidth, kHeight, kLayers);
14603 for (uint32_t level = 0; level < kLevels; ++level)
14604 {
14605 for (uint32_t layer = 0; layer < kLayers; ++layer)
14606 {
14607 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, layer, kWidth >> level,
14608 kHeight >> level, 1, GL_RGBA, GL_UNSIGNED_BYTE,
14609 colors[(level + layer) % 3]);
14610 }
14611 }
14612 ASSERT_GL_NO_ERROR();
14613
14614 // The texture has the following colors:
14615 // Layer 0 Layer 1 Layer 2 Layer 3 Layer 4
14616 // Level 0 Red Green Blue Red Green
14617 // Level 1 Green Blue Red Green Blue
14618
14619 // Copy level 0, layer 0 to level 0, layer 2
14620 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14621 2, kWidth, kHeight, 1);
14622
14623 // Copy level 1, layers 3, 4 to level 1, layers 1, 2
14624 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 1, 0, 0, 3, tex, GL_TEXTURE_2D_ARRAY, 1, 0, 0,
14625 1, kWidth >> 1, kHeight >> 1, 2);
14626
14627 // Partially copy level 1, layer 1 to level 0, layer 3
14628 // Level 1/layer 1 will be read from after being written to
14629 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 1, kWidth / 8, kHeight / 8, 1, tex,
14630 GL_TEXTURE_2D_ARRAY, 0, kWidth / 4, kHeight / 4, 3, kWidth / 4,
14631 kHeight / 4, 1);
14632 ASSERT_GL_NO_ERROR();
14633
14634 // Verify colors
14635 GLFramebuffer FBO;
14636 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
14637 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
14638 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14639
14640 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
14641 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14642
14643 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
14644 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14645
14646 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 3);
14647 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight / 4, GLColor::red);
14648 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 4, kHeight, GLColor::red);
14649 EXPECT_PIXEL_RECT_EQ(0, kHeight / 4 + kHeight / 4, kWidth,
14650 kHeight - (kHeight / 4 + kHeight / 4), GLColor::red);
14651 EXPECT_PIXEL_RECT_EQ(kWidth / 4 + kWidth / 4, 0, kWidth - (kWidth / 4 + kWidth / 4), kHeight,
14652 GLColor::red);
14653 EXPECT_PIXEL_RECT_EQ(kWidth / 4, kHeight / 4, kWidth / 4, kHeight / 4, GLColor::green);
14654
14655 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 4);
14656 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14657
14658 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 0);
14659 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
14660
14661 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 1);
14662 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
14663
14664 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 2);
14665 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14666
14667 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 3);
14668 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
14669
14670 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 4);
14671 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14672 ASSERT_GL_NO_ERROR();
14673 }
14674
14675 // Verify that copies between texture layers works, including when there is a write after read in a
14676 // level/layer.
TEST_P(CopyImageTestES31,ArraySelfCopyImageSubDataWithWriteAfterRead)14677 TEST_P(CopyImageTestES31, ArraySelfCopyImageSubDataWithWriteAfterRead)
14678 {
14679 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
14680
14681 // Set up a texture with multiple layers, then verify we can copy between them
14682 constexpr uint32_t kWidth = 13;
14683 constexpr uint32_t kHeight = 57;
14684 constexpr uint32_t kLayers = 5;
14685 constexpr uint32_t kLevels = 2;
14686 std::vector<GLColor> pixelsRed(kWidth * kHeight, GLColor::red);
14687 std::vector<GLColor> pixelsGreen(kWidth * kHeight, GLColor::green);
14688 std::vector<GLColor> pixelsBlue(kWidth * kHeight, GLColor::blue);
14689
14690 const GLColor *colors[3] = {
14691 pixelsRed.data(),
14692 pixelsGreen.data(),
14693 pixelsBlue.data(),
14694 };
14695
14696 GLTexture tex;
14697 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
14698 glTexStorage3D(GL_TEXTURE_2D_ARRAY, kLevels, GL_RGBA8, kWidth, kHeight, kLayers);
14699 for (uint32_t level = 0; level < kLevels; ++level)
14700 {
14701 for (uint32_t layer = 0; layer < kLayers; ++layer)
14702 {
14703 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, layer, kWidth >> level,
14704 kHeight >> level, 1, GL_RGBA, GL_UNSIGNED_BYTE,
14705 colors[(level + layer) % 3]);
14706 }
14707 }
14708 ASSERT_GL_NO_ERROR();
14709
14710 // The texture has the following colors:
14711 // Layer 0 Layer 1 Layer 2 Layer 3 Layer 4
14712 // Level 0 Red Green Blue Red Green
14713 // Level 1 Green Blue Red Green Blue
14714
14715 // Copy level 0, layer 0 to level 0, layer 2
14716 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14717 2, kWidth, kHeight, 1);
14718 ASSERT_GL_NO_ERROR();
14719
14720 // Copy level 0, layer 1 to level 0, layer 3
14721 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14722 3, kWidth, kHeight, 1);
14723 ASSERT_GL_NO_ERROR();
14724
14725 // Copy level 0, layer 0 to level 0, layer 1
14726 // Level 0/layer 1 will be written to from after being read from
14727 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14728 1, kWidth, kHeight, 1);
14729 ASSERT_GL_NO_ERROR();
14730
14731 // Verify colors
14732 GLFramebuffer FBO;
14733 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
14734 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
14735 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14736
14737 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
14738 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14739
14740 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
14741 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14742
14743 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 3);
14744 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14745
14746 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 4);
14747 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14748
14749 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 0);
14750 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
14751
14752 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 1);
14753 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14754
14755 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 2);
14756 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::red);
14757
14758 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 3);
14759 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
14760
14761 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 4);
14762 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14763 ASSERT_GL_NO_ERROR();
14764 }
14765
14766 // Verify that copies between 3D texture slices work
TEST_P(CopyImageTestES31,Texture3DSelfCopyImageSubData)14767 TEST_P(CopyImageTestES31, Texture3DSelfCopyImageSubData)
14768 {
14769 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
14770
14771 // Set up a texture with multiple layers, then verify we can copy between them
14772 constexpr uint32_t kWidth = 23;
14773 constexpr uint32_t kHeight = 47;
14774 constexpr uint32_t kDepth = 5;
14775 constexpr uint32_t kLevels = 2;
14776 std::vector<GLColor> pixelsRed(kWidth * kHeight, GLColor::red);
14777 std::vector<GLColor> pixelsGreen(kWidth * kHeight, GLColor::green);
14778 std::vector<GLColor> pixelsBlue(kWidth * kHeight, GLColor::blue);
14779
14780 const GLColor *colors[3] = {
14781 pixelsRed.data(),
14782 pixelsGreen.data(),
14783 pixelsBlue.data(),
14784 };
14785
14786 GLTexture tex;
14787 glBindTexture(GL_TEXTURE_3D, tex);
14788 glTexStorage3D(GL_TEXTURE_3D, kLevels, GL_RGBA8, kWidth, kHeight, kDepth);
14789 for (uint32_t level = 0; level < kLevels; ++level)
14790 {
14791 for (uint32_t depth = 0; depth < kDepth >> level; ++depth)
14792 {
14793 glTexSubImage3D(GL_TEXTURE_3D, level, 0, 0, depth, kWidth >> level, kHeight >> level, 1,
14794 GL_RGBA, GL_UNSIGNED_BYTE, colors[(level + depth) % 3]);
14795 }
14796 }
14797 ASSERT_GL_NO_ERROR();
14798
14799 // The texture has the following colors:
14800 // Slice 0 Slice 1 Slice 2 Slice 3 Slice 4
14801 // Level 0 Red Green Blue Red Green
14802 // Level 1 Green Blue
14803
14804 // Copy level 1, slice 1 to level 1, slice 0
14805 glCopyImageSubDataEXT(tex, GL_TEXTURE_3D, 1, 0, 0, 1, tex, GL_TEXTURE_3D, 1, 0, 0, 0,
14806 kWidth >> 1, kHeight >> 1, 1);
14807 ASSERT_GL_NO_ERROR();
14808
14809 // Copy level 0, slice 3, 4 to level 0, slice 1, 2
14810 glCopyImageSubDataEXT(tex, GL_TEXTURE_3D, 0, 0, 0, 3, tex, GL_TEXTURE_3D, 0, 0, 0, 1, kWidth,
14811 kHeight, 2);
14812 ASSERT_GL_NO_ERROR();
14813
14814 // Partially copy level 1, slice 1 to level 0, slice 3
14815 glCopyImageSubDataEXT(tex, GL_TEXTURE_3D, 1, kWidth / 8, kHeight / 8, 1, tex, GL_TEXTURE_3D, 0,
14816 kWidth / 4, kHeight / 4, 3, kWidth / 4, kHeight / 4, 1);
14817 ASSERT_GL_NO_ERROR();
14818
14819 // Verify colors
14820 GLFramebuffer FBO;
14821 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
14822 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
14823 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14824
14825 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
14826 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14827
14828 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
14829 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14830
14831 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 3);
14832 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight / 4, GLColor::red);
14833 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 4, kHeight, GLColor::red);
14834 EXPECT_PIXEL_RECT_EQ(0, kHeight / 4 + kHeight / 4, kWidth,
14835 kHeight - (kHeight / 4 + kHeight / 4), GLColor::red);
14836 EXPECT_PIXEL_RECT_EQ(kWidth / 4 + kWidth / 4, 0, kWidth - (kWidth / 4 + kWidth / 4), kHeight,
14837 GLColor::red);
14838 EXPECT_PIXEL_RECT_EQ(kWidth / 4, kHeight / 4, kWidth / 4, kHeight / 4, GLColor::blue);
14839
14840 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 4);
14841 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14842
14843 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 0);
14844 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14845
14846 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 1);
14847 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14848 ASSERT_GL_NO_ERROR();
14849 }
14850
14851 class TextureChangeStorageUploadTest : public ANGLETest<>
14852 {
14853 protected:
TextureChangeStorageUploadTest()14854 TextureChangeStorageUploadTest()
14855 {
14856 setWindowWidth(256);
14857 setWindowHeight(256);
14858 setConfigRedBits(8);
14859 setConfigGreenBits(8);
14860 setConfigBlueBits(8);
14861 setConfigAlphaBits(8);
14862 }
14863
testSetUp()14864 void testSetUp() override
14865 {
14866 mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
14867 if (mProgram == 0)
14868 {
14869 FAIL() << "shader compilation failed.";
14870 }
14871
14872 glUseProgram(mProgram);
14873
14874 glClearColor(0, 0, 0, 0);
14875 glClearDepthf(0.0);
14876 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
14877
14878 glEnable(GL_BLEND);
14879 glDisable(GL_DEPTH_TEST);
14880
14881 glGenTextures(1, &mTexture);
14882 ASSERT_GL_NO_ERROR();
14883 }
14884
testTearDown()14885 void testTearDown() override
14886 {
14887 glDeleteTextures(1, &mTexture);
14888 glDeleteProgram(mProgram);
14889 }
14890
14891 GLuint mProgram;
14892 GLint mColorLocation;
14893 GLuint mTexture;
14894 };
14895
14896 // Verify that respecifying storage and re-uploading doesn't crash.
TEST_P(TextureChangeStorageUploadTest,Basic)14897 TEST_P(TextureChangeStorageUploadTest, Basic)
14898 {
14899 constexpr int kImageSize = 8; // 4 doesn't trip ASAN
14900 constexpr int kSmallerImageSize = kImageSize / 2;
14901 EXPECT_GT(kImageSize, kSmallerImageSize);
14902 EXPECT_GT(kSmallerImageSize / 2, 0);
14903
14904 std::array<GLColor, kImageSize * kImageSize> kColor;
14905
14906 glBindTexture(GL_TEXTURE_2D, mTexture);
14907 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
14908 kColor.data());
14909 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSmallerImageSize, kSmallerImageSize);
14910 // need partial update to sidestep optimizations that remove the full upload
14911 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSmallerImageSize / 2, kSmallerImageSize / 2, GL_RGBA,
14912 GL_UNSIGNED_BYTE, kColor.data());
14913 EXPECT_GL_NO_ERROR();
14914 }
14915
14916 class ExtraSamplerCubeShadowUseTest : public ANGLETest<>
14917 {
14918 protected:
ExtraSamplerCubeShadowUseTest()14919 ExtraSamplerCubeShadowUseTest() : ANGLETest() {}
14920
getVertexShaderSource()14921 const char *getVertexShaderSource() { return "#version 300 es\nvoid main() {}"; }
14922
getFragmentShaderSource()14923 const char *getFragmentShaderSource()
14924 {
14925 return R"(#version 300 es
14926 precision mediump float;
14927
14928 uniform mediump samplerCube var_0002; // this has to be there
14929 uniform highp samplerCubeShadow var_0004; // this has to be a cube shadow sampler
14930 out vec4 color;
14931 void main() {
14932
14933 vec4 var_0031 = texture(var_0002, vec3(1,1,1));
14934 ivec2 size = textureSize(var_0004, 0) ;
14935 var_0031.x += float(size.y);
14936
14937 color = var_0031;
14938 })";
14939 }
14940
testSetUp()14941 void testSetUp() override
14942 {
14943 mProgram = CompileProgram(getVertexShaderSource(), getFragmentShaderSource());
14944 if (mProgram == 0)
14945 {
14946 FAIL() << "shader compilation failed.";
14947 }
14948 glUseProgram(mProgram);
14949 ASSERT_GL_NO_ERROR();
14950 }
14951
testTearDown()14952 void testTearDown() override { glDeleteProgram(mProgram); }
14953
14954 GLuint mProgram;
14955 };
14956
TEST_P(ExtraSamplerCubeShadowUseTest,Basic)14957 TEST_P(ExtraSamplerCubeShadowUseTest, Basic)
14958 {
14959 glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
14960 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
14961 }
14962
14963 // Tests covering RBG->RGBA emulation path
14964 class RGBTextureBufferTestES31 : public ANGLETest<>
14965 {
14966 protected:
RGBTextureBufferTestES31()14967 RGBTextureBufferTestES31()
14968 {
14969 setWindowWidth(128);
14970 setWindowHeight(128);
14971 setConfigRedBits(8);
14972 setConfigGreenBits(8);
14973 setConfigBlueBits(8);
14974 setConfigAlphaBits(8);
14975 }
14976 void TestInt(GLuint format);
14977 };
14978
SetupTextureBufferDrawProgram(GLProgram & program,GLuint format)14979 void SetupTextureBufferDrawProgram(GLProgram &program, GLuint format)
14980 {
14981 constexpr char kVS[] = R"(#version 310 es
14982 precision highp float;
14983 in vec4 inputAttribute;
14984
14985 void main()
14986 {
14987 gl_Position = inputAttribute;
14988 })";
14989
14990 if (format == GL_RGB32UI)
14991 {
14992 constexpr char kFS[] = R"(#version 310 es
14993 #extension GL_EXT_texture_buffer : require
14994 precision mediump float;
14995 uniform highp usamplerBuffer tex;
14996 layout(location = 0) out mediump vec4 color;
14997
14998 void main()
14999 {
15000 uvec4 v = texelFetch(tex, 1);
15001 color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
15002 })";
15003 program.makeRaster(kVS, kFS);
15004 }
15005 if (format == GL_RGB32I)
15006 {
15007 constexpr char kFS[] = R"(#version 310 es
15008 #extension GL_EXT_texture_buffer : require
15009 precision mediump float;
15010 uniform highp isamplerBuffer tex;
15011 layout(location = 0) out mediump vec4 color;
15012
15013 void main()
15014 {
15015 ivec4 v = texelFetch(tex, 1);
15016 color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
15017 })";
15018 program.makeRaster(kVS, kFS);
15019 }
15020 if (format == GL_RGB32F)
15021 {
15022 constexpr char kFS[] = R"(#version 310 es
15023 #extension GL_EXT_texture_buffer : require
15024 precision mediump float;
15025 uniform highp samplerBuffer tex;
15026 layout(location = 0) out mediump vec4 color;
15027
15028 void main()
15029 {
15030 vec4 v = texelFetch(tex, 1);
15031 color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
15032 })";
15033 program.makeRaster(kVS, kFS);
15034 }
15035 ASSERT_TRUE(program.valid());
15036 }
15037
TestInt(GLuint format)15038 void RGBTextureBufferTestES31::TestInt(GLuint format)
15039 {
15040 const GLint pixelSize = sizeof(GLuint) * 3;
15041
15042 // Offset must be aligned to GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT (16, 64, ...)
15043 GLint offsetAlignment = 0;
15044 glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment);
15045 ASSERT(offsetAlignment % sizeof(GLuint) == 0);
15046 GLint byteOffset = ((pixelSize * 2) / offsetAlignment + 1) * offsetAlignment;
15047
15048 GLint intOffset = byteOffset / sizeof(GLuint);
15049
15050 std::vector<GLuint> texData(intOffset + 3 * 2);
15051
15052 // first texel(1) col
15053 GLColor col = MakeGLColor(11, 22, 33, 255);
15054 texData[3] = col.R;
15055 texData[4] = col.G;
15056 texData[5] = col.B;
15057
15058 // second texel(1) col2
15059 GLColor col2 = MakeGLColor(44, 55, 66, 255);
15060 texData[intOffset + 3] = col2.R;
15061 texData[intOffset + 4] = col2.G;
15062 texData[intOffset + 5] = col2.B;
15063
15064 GLTexture texture;
15065 glBindTexture(GL_TEXTURE_BUFFER, texture);
15066
15067 GLBuffer buffer;
15068 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
15069 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * texData.size(), texData.data(),
15070 GL_STATIC_DRAW);
15071 ASSERT_GL_NO_ERROR();
15072
15073 GLProgram program;
15074 SetupTextureBufferDrawProgram(program, format);
15075
15076 glTexBufferEXT(GL_TEXTURE_BUFFER, format, buffer);
15077
15078 drawQuad(program, "inputAttribute", 0.5f);
15079 ASSERT_GL_NO_ERROR();
15080 EXPECT_PIXEL_COLOR_NEAR(0, 0, col, 1);
15081
15082 glTexBufferRangeEXT(GL_TEXTURE_BUFFER, format, buffer, byteOffset, pixelSize * 2);
15083 ASSERT_GL_NO_ERROR();
15084 drawQuad(program, "inputAttribute", 0.5f);
15085 EXPECT_PIXEL_COLOR_NEAR(0, 0, col2, 1);
15086
15087 // Now update the buffer to check the converted data also gets updated.
15088 GLColor colUpd = MakeGLColor(77, 88, 99, 255);
15089 GLuint texDataUpd[] = {0, 0, 0, colUpd.R, colUpd.G, colUpd.B}; // second texel(1) colUpd
15090 glBufferSubData(GL_TEXTURE_BUFFER, byteOffset, sizeof(texDataUpd), texDataUpd);
15091 ASSERT_GL_NO_ERROR();
15092 drawQuad(program, "inputAttribute", 0.5f);
15093 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd, 1);
15094
15095 // Update with glMapBuffer (hits a different code path...)
15096 GLColor colUpd2 = MakeGLColor(111, 122, 133, 255);
15097 GLuint texDataUpd2[] = {0, 0, 0, colUpd2.R, colUpd2.G, colUpd2.B}; // second texel(1) colUpd2
15098 void *mappedBuffer =
15099 glMapBufferRange(GL_TEXTURE_BUFFER, byteOffset, sizeof(texDataUpd2), GL_MAP_WRITE_BIT);
15100 memcpy(mappedBuffer, texDataUpd2, sizeof(texDataUpd2));
15101 glUnmapBuffer(GL_TEXTURE_BUFFER);
15102 ASSERT_GL_NO_ERROR();
15103 drawQuad(program, "inputAttribute", 0.5f);
15104 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd2, 1);
15105 }
15106
15107 // Tests GL_RGB32UI texture buffer
TEST_P(RGBTextureBufferTestES31,Uint)15108 TEST_P(RGBTextureBufferTestES31, Uint)
15109 {
15110 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
15111
15112 TestInt(GL_RGB32UI);
15113 }
15114
15115 // Tests GL_RGB32I texture buffer
TEST_P(RGBTextureBufferTestES31,Sint)15116 TEST_P(RGBTextureBufferTestES31, Sint)
15117 {
15118 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
15119
15120 TestInt(GL_RGB32I);
15121 }
15122
15123 // Tests GL_RGB32F texture buffer
TEST_P(RGBTextureBufferTestES31,Float)15124 TEST_P(RGBTextureBufferTestES31, Float)
15125 {
15126 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
15127
15128 // first texel(1) col
15129 GLColor col = MakeGLColor(11, 22, 33, 255);
15130 GLfloat texData[6]{};
15131 texData[3] = col.R;
15132 texData[4] = col.G;
15133 texData[5] = col.B;
15134
15135 GLTexture texture;
15136 glBindTexture(GL_TEXTURE_BUFFER, texture);
15137
15138 GLBuffer buffer;
15139 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
15140 glBufferData(GL_TEXTURE_BUFFER, sizeof(texData), texData, GL_STATIC_DRAW);
15141 ASSERT_GL_NO_ERROR();
15142
15143 GLProgram program;
15144 SetupTextureBufferDrawProgram(program, GL_RGB32F);
15145
15146 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGB32F, buffer);
15147
15148 drawQuad(program, "inputAttribute", 0.5f);
15149 ASSERT_GL_NO_ERROR();
15150 EXPECT_PIXEL_COLOR_NEAR(0, 0, col, 1);
15151
15152 // Now update the buffer to check the converted data also gets updated.
15153 GLColor colUpd = MakeGLColor(77, 88, 99, 255);
15154 GLfloat texDataUpd[6]{};
15155 texDataUpd[3] = colUpd.R;
15156 texDataUpd[4] = colUpd.G;
15157 texDataUpd[5] = colUpd.B;
15158 glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(texDataUpd), texDataUpd);
15159 ASSERT_GL_NO_ERROR();
15160 drawQuad(program, "inputAttribute", 0.5f);
15161 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd, 1);
15162
15163 // Update with glMapBuffer (hits a different code path...)
15164 GLColor colUpd2 = MakeGLColor(111, 122, 133, 255);
15165 GLfloat texDataUpd2[6]{};
15166 texDataUpd2[3] = colUpd2.R;
15167 texDataUpd2[4] = colUpd2.G;
15168 texDataUpd2[5] = colUpd2.B;
15169 void *mappedBuffer =
15170 glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(texDataUpd2), GL_MAP_WRITE_BIT);
15171 memcpy(mappedBuffer, texDataUpd2, sizeof(texDataUpd2));
15172 glUnmapBuffer(GL_TEXTURE_BUFFER);
15173 ASSERT_GL_NO_ERROR();
15174 drawQuad(program, "inputAttribute", 0.5f);
15175 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd2, 1);
15176 }
15177
SetupSSBOProgram(GLProgram & program)15178 void SetupSSBOProgram(GLProgram &program)
15179 {
15180 constexpr char kVS[] = R"(#version 310 es
15181 precision highp float;
15182 in vec4 inputAttribute;
15183
15184 void main()
15185 {
15186 gl_Position = inputAttribute;
15187 })";
15188
15189 constexpr char kFS[] = R"(#version 310 es
15190 layout(location = 0) out mediump vec4 color;
15191 layout(std140, binding = 0) buffer outBlock {
15192 uvec4 data[2]; // uvec4 to avoid padding
15193 };
15194 void main (void)
15195 {
15196 data[0] = uvec4(11u, 22u, 33u, 44u);
15197 data[1] = uvec4(55u, 66u, 0u, 0u);
15198 color = vec4(0);
15199 })";
15200
15201 program.makeRaster(kVS, kFS);
15202 ASSERT_TRUE(program.valid());
15203 }
15204
15205 // Tests RGB32 texture buffer with a SSBO write
TEST_P(RGBTextureBufferTestES31,SSBOWrite)15206 TEST_P(RGBTextureBufferTestES31, SSBOWrite)
15207 {
15208 GLProgram programSSBO;
15209 SetupSSBOProgram(programSSBO);
15210
15211 GLProgram programBufferDraw;
15212 SetupTextureBufferDrawProgram(programBufferDraw, GL_RGB32UI);
15213
15214 constexpr GLint kBufferSize = 2 * 4 * sizeof(GLuint);
15215 GLBuffer buffer;
15216 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
15217 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
15218 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize);
15219
15220 drawQuad(programSSBO, "inputAttribute", 0.5f);
15221 ASSERT_GL_NO_ERROR();
15222
15223 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
15224
15225 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGB32UI, buffer);
15226 drawQuad(programBufferDraw, "inputAttribute", 0.5f);
15227 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(44, 55, 66, 255), 1);
15228 }
15229
15230 class TextureTestES31 : public ANGLETest<>
15231 {
15232 protected:
TextureTestES31()15233 TextureTestES31()
15234 {
15235 setWindowWidth(128);
15236 setWindowHeight(128);
15237 setConfigRedBits(8);
15238 setConfigGreenBits(8);
15239 setConfigBlueBits(8);
15240 setConfigAlphaBits(8);
15241 }
15242 };
15243
15244 // Verify that image uniforms can link in separable programs
TEST_P(TextureTestES31,LinkedImageUniforms)15245 TEST_P(TextureTestES31, LinkedImageUniforms)
15246 {
15247 ANGLE_SKIP_TEST_IF(!IsVulkan());
15248
15249 GLint maxVertexImageUniforms;
15250 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
15251 ANGLE_SKIP_TEST_IF(maxVertexImageUniforms == 0);
15252
15253 constexpr char kVS[] = R"(#version 310 es
15254 precision highp float;
15255 precision highp image2D;
15256 layout(binding = 0, r32f) uniform image2D img;
15257
15258 void main()
15259 {
15260 vec2 position = -imageLoad(img, ivec2(0, 0)).rr;
15261 if (gl_VertexID == 1)
15262 position = vec2(3, -1);
15263 else if (gl_VertexID == 2)
15264 position = vec2(-1, 3);
15265
15266 gl_Position = vec4(position, 0, 1);
15267 })";
15268
15269 constexpr char kFS[] = R"(#version 310 es
15270 precision highp float;
15271 precision highp image2D;
15272 layout(binding = 0, r32f) uniform image2D img;
15273 layout(location = 0) out vec4 color;
15274
15275 void main()
15276 {
15277 color = imageLoad(img, ivec2(0, 0));
15278 })";
15279
15280 ANGLE_GL_PROGRAM(program, kVS, kFS);
15281
15282 GLTexture texture;
15283 GLfloat value = 1.0;
15284
15285 glBindTexture(GL_TEXTURE_2D, texture);
15286 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
15287 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &value);
15288 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
15289 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
15290
15291 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
15292
15293 glUseProgram(program);
15294 glDrawArrays(GL_TRIANGLES, 0, 3);
15295
15296 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
15297 ASSERT_GL_NO_ERROR();
15298 }
15299
15300 // Test that layer-related parameters are ignored when binding a 2D texture
TEST_P(TextureTestES31,Texture2DLayered)15301 TEST_P(TextureTestES31, Texture2DLayered)
15302 {
15303 constexpr char kFS[] = R"(#version 310 es
15304 precision highp float;
15305 precision highp image2D;
15306 layout(binding = 0, r32f) uniform image2D img;
15307 layout(location = 0) out vec4 color;
15308
15309 void main()
15310 {
15311 color = imageLoad(img, ivec2(0, 0));
15312 })";
15313
15314 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
15315
15316 GLTexture texture;
15317 GLfloat value = 1.0;
15318
15319 glBindTexture(GL_TEXTURE_2D, texture);
15320 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
15321 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &value);
15322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
15323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
15324
15325 glClearColor(0.0, 1.0, 0.0, 1.0);
15326 for (const bool layered : {true, false})
15327 {
15328 for (const GLint layer : {0, 1})
15329 {
15330 glClear(GL_COLOR_BUFFER_BIT);
15331 glBindImageTexture(0, texture, 0, layered, layer, GL_READ_ONLY, GL_R32F);
15332 ASSERT_GL_NO_ERROR();
15333
15334 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15335 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red)
15336 << "Layered: " << (layered ? "true" : "false") << ", Layer: " << layer;
15337 }
15338 }
15339 }
15340
15341 // Test that rebinding the shader image level without changing the program works
TEST_P(TextureTestES31,Texture2DChangeLevel)15342 TEST_P(TextureTestES31, Texture2DChangeLevel)
15343 {
15344 constexpr char kFS[] = R"(#version 310 es
15345 precision highp float;
15346 precision highp image2D;
15347 layout(binding = 0, r32f) uniform image2D img;
15348 layout(location = 0) out vec4 color;
15349
15350 void main()
15351 {
15352 color = imageLoad(img, ivec2(0, 0));
15353 })";
15354 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
15355
15356 // Must be active before calling drawQuad to avoid program switches
15357 glUseProgram(program);
15358
15359 GLTexture texture;
15360 const GLfloat level0[4] = {0.5, 0.5, 0.5, 0.5};
15361 const GLfloat level1[1] = {1.0};
15362
15363 glBindTexture(GL_TEXTURE_2D, texture);
15364 glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32F, 2, 2);
15365 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RED, GL_FLOAT, level0);
15366 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 1, 1, GL_RED, GL_FLOAT, level1);
15367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
15368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
15369
15370 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
15371 ASSERT_GL_NO_ERROR();
15372 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15373 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
15374
15375 glBindImageTexture(0, texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
15376 ASSERT_GL_NO_ERROR();
15377 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15378 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
15379 }
15380
15381 // Test that rebinding the shader image layer/level without changing the program works
TEST_P(TextureTestES31,Texture2DArrayChangeLayerLevel)15382 TEST_P(TextureTestES31, Texture2DArrayChangeLayerLevel)
15383 {
15384 constexpr char kFS[] = R"(#version 310 es
15385 precision highp float;
15386 precision highp image2D;
15387 layout(binding = 0, r32f) uniform image2D img;
15388 layout(location = 0) out vec4 color;
15389
15390 void main()
15391 {
15392 color = imageLoad(img, ivec2(0, 0));
15393 })";
15394 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
15395
15396 // Must be active before calling drawQuad to avoid program switches
15397 glUseProgram(program);
15398
15399 GLTexture texture;
15400 const GLfloat level0layer0[4] = {0.25, 0.25, 0.25, 0.25};
15401 const GLfloat level0layer1[4] = {0.50, 0.50, 0.50, 0.50};
15402 const GLfloat level1layer0[1] = {0.75};
15403 const GLfloat level1layer1[1] = {1.00};
15404
15405 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
15406 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 2, 2, 2);
15407 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 2, 2, 1, GL_RED, GL_FLOAT, level0layer0);
15408 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 2, 2, 1, GL_RED, GL_FLOAT, level0layer1);
15409 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, 1, 1, 1, GL_RED, GL_FLOAT, level1layer0);
15410 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 1, 1, 1, 1, GL_RED, GL_FLOAT, level1layer1);
15411 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
15412 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
15413
15414 // Level 0, layer 0
15415 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
15416 ASSERT_GL_NO_ERROR();
15417 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15418 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 0, 0, 255), 1);
15419
15420 // Level 0, layer 1
15421 glBindImageTexture(0, texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
15422 ASSERT_GL_NO_ERROR();
15423 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15424 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
15425
15426 // Level 1, layer 0
15427 glBindImageTexture(0, texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
15428 ASSERT_GL_NO_ERROR();
15429 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15430 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(191, 0, 0, 255), 1);
15431
15432 // Level 1, layer 1
15433 glBindImageTexture(0, texture, 1, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
15434 ASSERT_GL_NO_ERROR();
15435 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15436 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 0, 0, 255), 1);
15437 }
15438
15439 // Test that switching between a 2D texture and a layer of a 2D array texture works
TEST_P(TextureTestES31,Texture2DTo2DArraySwitch)15440 TEST_P(TextureTestES31, Texture2DTo2DArraySwitch)
15441 {
15442 constexpr char kFS[] = R"(#version 310 es
15443 precision highp float;
15444 precision highp image2D;
15445 layout(binding = 0, r32f) uniform image2D img;
15446 layout(location = 0) out vec4 color;
15447
15448 void main()
15449 {
15450 color = imageLoad(img, ivec2(0, 0));
15451 })";
15452 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
15453
15454 // Must be active before calling drawQuad to avoid program switches
15455 glUseProgram(program);
15456
15457 GLTexture texture2D;
15458 GLTexture texture2DArray;
15459 const GLfloat data2D[1] = {0.50};
15460 const GLfloat data2DArray0[1] = {0.25};
15461 const GLfloat data2DArray1[1] = {0.75};
15462
15463 glBindTexture(GL_TEXTURE_2D, texture2D);
15464 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
15465 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, data2D);
15466 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
15467 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
15468
15469 glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
15470 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 1, 1, 2);
15471 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 1, 1, 1, GL_RED, GL_FLOAT, data2DArray0);
15472 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 1, 1, 1, GL_RED, GL_FLOAT, data2DArray1);
15473 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
15474 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
15475
15476 // Texture2D
15477 glBindImageTexture(0, texture2D, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
15478 ASSERT_GL_NO_ERROR();
15479 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15480 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
15481
15482 // Texture2D array, layer 0
15483 glBindImageTexture(0, texture2DArray, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
15484 ASSERT_GL_NO_ERROR();
15485 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15486 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 0, 0, 255), 1);
15487
15488 // Texture2D again
15489 glBindImageTexture(0, texture2D, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
15490 ASSERT_GL_NO_ERROR();
15491 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15492 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
15493
15494 // Texture2D array, layer 1
15495 glBindImageTexture(0, texture2DArray, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
15496 ASSERT_GL_NO_ERROR();
15497 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
15498 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(191, 0, 0, 255), 1);
15499 }
15500
15501 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
15502 // tests should be run against.
15503 #define ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB() \
15504 ES2_OPENGL().enable(Feature::EmulateCopyTexImage2D), \
15505 ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2D)
15506 #define ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB() \
15507 ES3_OPENGL().enable(Feature::EmulateCopyTexImage2D), \
15508 ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2D)
15509 #define ES2_EMULATE_COPY_TEX_IMAGE() \
15510 ES2_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers), \
15511 ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers)
15512 #define ES3_EMULATE_COPY_TEX_IMAGE() \
15513 ES3_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers), \
15514 ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers)
15515 ANGLE_INSTANTIATE_TEST(Texture2DTest,
15516 ANGLE_ALL_TEST_PLATFORMS_ES2,
15517 ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
15518 ES2_EMULATE_COPY_TEX_IMAGE(),
15519 ES2_WEBGPU());
15520 ANGLE_INSTANTIATE_TEST_ES2(TextureCubeTest);
15521 ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale);
15522 ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest);
15523 ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayTest);
15524 ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayAsFunctionParameterTest);
15525
15526 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3);
15527 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3,
15528 ES3_VULKAN().enable(Feature::AllocateNonZeroMemory),
15529 ES3_VULKAN().enable(Feature::ForceFallbackFormat));
15530
15531 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DMemoryTestES3);
15532 ANGLE_INSTANTIATE_TEST_ES3(Texture2DMemoryTestES3);
15533
15534 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3YUV);
15535 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3YUV,
15536 ES3_VULKAN().enable(Feature::PreferLinearFilterForYUV),
15537 ES3_VULKAN().enable(Feature::DisableProgramCaching));
15538
15539 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3RobustInit);
15540 ANGLE_INSTANTIATE_TEST_ES3(Texture2DTestES3RobustInit);
15541
15542 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3Foveation);
15543 ANGLE_INSTANTIATE_TEST_ES3_AND(
15544 Texture2DTestES3Foveation,
15545 ES3_VULKAN().enable(Feature::GenerateFragmentShadingRateAttchementWithCpu));
15546
15547 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES31Foveation);
15548 ANGLE_INSTANTIATE_TEST_ES31_AND(
15549 Texture2DTestES31Foveation,
15550 ES31_VULKAN().enable(Feature::GenerateFragmentShadingRateAttchementWithCpu));
15551
15552 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES31PPO);
15553 ANGLE_INSTANTIATE_TEST_ES31(Texture2DTestES31PPO);
15554
15555 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DBaseMaxTestES3);
15556 ANGLE_INSTANTIATE_TEST_ES3(Texture2DBaseMaxTestES3);
15557
15558 ANGLE_INSTANTIATE_TEST_ES2(Texture3DTestES2);
15559
15560 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DTestES3);
15561 ANGLE_INSTANTIATE_TEST_ES3(Texture3DTestES3);
15562
15563 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerAlpha1TestES3);
15564 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerAlpha1TestES3);
15565
15566 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DUnsignedIntegerAlpha1TestES3);
15567 ANGLE_INSTANTIATE_TEST_ES3(Texture2DUnsignedIntegerAlpha1TestES3);
15568
15569 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShadowSamplerPlusSampler3DTestES3);
15570 ANGLE_INSTANTIATE_TEST_ES3(ShadowSamplerPlusSampler3DTestES3);
15571
15572 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SamplerTypeMixTestES3);
15573 ANGLE_INSTANTIATE_TEST_ES3(SamplerTypeMixTestES3);
15574
15575 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayTestES3);
15576 ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayTestES3);
15577
15578 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSizeTextureArrayTest);
15579 ANGLE_INSTANTIATE_TEST_ES3(TextureSizeTextureArrayTest);
15580
15581 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructTest);
15582 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAsFunctionParameterTest);
15583 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructArrayAsFunctionParameterTest);
15584 ANGLE_INSTANTIATE_TEST_ES2(SamplerInNestedStructAsFunctionParameterTest);
15585 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAndOtherVariableTest);
15586 ANGLE_INSTANTIATE_TEST_ES2(TextureAnisotropyTest);
15587 ANGLE_INSTANTIATE_TEST_ES2(TextureBorderClampTest);
15588
15589 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampTestES3);
15590 ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampTestES3);
15591
15592 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampIntegerTestES3);
15593 ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampIntegerTestES3);
15594
15595 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(TextureMirrorClampToEdgeTest);
15596
15597 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMirrorClampToEdgeTestES3);
15598 ANGLE_INSTANTIATE_TEST_ES3(TextureMirrorClampToEdgeTestES3);
15599
15600 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMirrorClampToEdgeIntegerTestES3);
15601 ANGLE_INSTANTIATE_TEST_ES3(TextureMirrorClampToEdgeIntegerTestES3);
15602
15603 ANGLE_INSTANTIATE_TEST_ES2(TextureLimitsTest);
15604
15605 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DNorm16TestES3);
15606 ANGLE_INSTANTIATE_TEST_ES3(Texture2DNorm16TestES3);
15607
15608 ANGLE_INSTANTIATE_TEST(Texture2DRGTest,
15609 ANGLE_ALL_TEST_PLATFORMS_ES2,
15610 ANGLE_ALL_TEST_PLATFORMS_ES3,
15611 ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
15612 ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
15613 ES2_EMULATE_COPY_TEX_IMAGE(),
15614 ES3_EMULATE_COPY_TEX_IMAGE());
15615
15616 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DFloatTestES3);
15617 ANGLE_INSTANTIATE_TEST_ES3(Texture2DFloatTestES3);
15618
15619 ANGLE_INSTANTIATE_TEST_ES2(Texture2DFloatTestES2);
15620
15621 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeTestES3);
15622 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeTestES3);
15623
15624 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeTestES32);
15625 ANGLE_INSTANTIATE_TEST_ES32(TextureCubeTestES32);
15626
15627 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerTestES3);
15628 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerTestES3);
15629
15630 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerTestES3);
15631 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerTestES3);
15632
15633 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerEdgeTestES3);
15634 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerEdgeTestES3);
15635
15636 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerProjectiveOffsetTestES3);
15637 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerProjectiveOffsetTestES3);
15638
15639 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayIntegerTestES3);
15640 ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayIntegerTestES3);
15641
15642 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DIntegerTestES3);
15643 ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3);
15644
15645 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest);
15646 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest);
15647 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest);
15648 ANGLE_INSTANTIATE_TEST_ES3(PBOCompressedTexture3DTest);
15649
15650 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBufferTestES31);
15651 ANGLE_INSTANTIATE_TEST_ES31(TextureBufferTestES31);
15652
15653 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureTestES31);
15654 ANGLE_INSTANTIATE_TEST_ES31(TextureTestES31);
15655
15656 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyImageTestES31);
15657 ANGLE_INSTANTIATE_TEST_ES31(CopyImageTestES31);
15658
15659 ANGLE_INSTANTIATE_TEST_ES3(TextureChangeStorageUploadTest);
15660
15661 ANGLE_INSTANTIATE_TEST_ES3(ExtraSamplerCubeShadowUseTest);
15662
15663 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DDepthStencilTestES3);
15664 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DDepthStencilTestES3,
15665 ES3_VULKAN().enable(Feature::ForceFallbackFormat));
15666
15667 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RGBTextureBufferTestES31);
15668 ANGLE_INSTANTIATE_TEST_ES31(RGBTextureBufferTestES31);
15669
15670 } // anonymous namespace
15671