xref: /aosp_15_r20/external/angle/src/tests/gl_tests/TextureTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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