• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SliceFormatColor16UI(GLenum format,GLColor16UI full)53 GLColor16UI SliceFormatColor16UI(GLenum format, GLColor16UI full)
54 {
55     switch (format)
56     {
57         case GL_RED:
58             return GLColor16UI(full.R, 0, 0, 0xFFFF);
59         case GL_RG:
60             return GLColor16UI(full.R, full.G, 0, 0xFFFF);
61         case GL_RGB:
62             return GLColor16UI(full.R, full.G, full.B, 0xFFFF);
63         case GL_RGBA:
64             return full;
65         case GL_LUMINANCE:
66             return GLColor16UI(full.R, full.R, full.R, 0xFFFF);
67         case GL_ALPHA:
68             return GLColor16UI(0, 0, 0, full.R);
69         case GL_LUMINANCE_ALPHA:
70             return GLColor16UI(full.R, full.R, full.R, full.G);
71         default:
72             EXPECT_TRUE(false);
73             return GLColor16UI(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 SamplerArrayTest : public TexCoordDrawTest
994 {
995   protected:
SamplerArrayTest()996     SamplerArrayTest()
997         : TexCoordDrawTest(),
998           mTexture2DA(0),
999           mTexture2DB(0),
1000           mTexture0UniformLocation(-1),
1001           mTexture1UniformLocation(-1)
1002     {}
1003 
getFragmentShaderSource()1004     const char *getFragmentShaderSource() override
1005     {
1006         return
1007             R"(precision mediump float;
1008             uniform highp sampler2D tex2DArray[2];
1009             varying vec2 texcoord;
1010             void main()
1011             {
1012                 gl_FragColor = texture2D(tex2DArray[0], texcoord);
1013                 gl_FragColor += texture2D(tex2DArray[1], texcoord);
1014             })";
1015     }
1016 
testSetUp()1017     void testSetUp() override
1018     {
1019         TexCoordDrawTest::testSetUp();
1020 
1021         setUpProgram();
1022 
1023         mTexture0UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[0]");
1024         ASSERT_NE(-1, mTexture0UniformLocation);
1025         mTexture1UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[1]");
1026         ASSERT_NE(-1, mTexture1UniformLocation);
1027 
1028         mTexture2DA = create2DTexture();
1029         mTexture2DB = create2DTexture();
1030         ASSERT_GL_NO_ERROR();
1031     }
1032 
testTearDown()1033     void testTearDown() override
1034     {
1035         glDeleteTextures(1, &mTexture2DA);
1036         glDeleteTextures(1, &mTexture2DB);
1037         TexCoordDrawTest::testTearDown();
1038     }
1039 
testSamplerArrayDraw()1040     void testSamplerArrayDraw()
1041     {
1042         GLubyte texData[4];
1043         texData[0] = 0;
1044         texData[1] = 60;
1045         texData[2] = 0;
1046         texData[3] = 255;
1047 
1048         glActiveTexture(GL_TEXTURE0);
1049         glBindTexture(GL_TEXTURE_2D, mTexture2DA);
1050         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1051 
1052         texData[1] = 120;
1053         glActiveTexture(GL_TEXTURE1);
1054         glBindTexture(GL_TEXTURE_2D, mTexture2DB);
1055         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1056         EXPECT_GL_ERROR(GL_NO_ERROR);
1057 
1058         glUseProgram(mProgram);
1059         glUniform1i(mTexture0UniformLocation, 0);
1060         glUniform1i(mTexture1UniformLocation, 1);
1061         drawQuad(mProgram, "position", 0.5f);
1062         EXPECT_GL_NO_ERROR();
1063 
1064         EXPECT_PIXEL_NEAR(0, 0, 0, 180, 0, 255, 2);
1065     }
1066 
1067     GLuint mTexture2DA;
1068     GLuint mTexture2DB;
1069     GLint mTexture0UniformLocation;
1070     GLint mTexture1UniformLocation;
1071 };
1072 
1073 class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
1074 {
1075   protected:
SamplerArrayAsFunctionParameterTest()1076     SamplerArrayAsFunctionParameterTest() : SamplerArrayTest() {}
1077 
getFragmentShaderSource()1078     const char *getFragmentShaderSource() override
1079     {
1080         return
1081             R"(precision mediump float;
1082             uniform highp sampler2D tex2DArray[2];
1083             varying vec2 texcoord;
1084 
1085             vec4 computeFragColor(highp sampler2D aTex2DArray[2])
1086             {
1087                 return texture2D(aTex2DArray[0], texcoord) + texture2D(aTex2DArray[1], texcoord);
1088             }
1089 
1090             void main()
1091             {
1092                 gl_FragColor = computeFragColor(tex2DArray);
1093             })";
1094     }
1095 };
1096 
1097 class Texture2DArrayTestES3 : public TexCoordDrawTest
1098 {
1099   protected:
Texture2DArrayTestES3()1100     Texture2DArrayTestES3()
1101         : TexCoordDrawTest(),
1102           m2DArrayTexture(0),
1103           mTextureArrayLocation(-1),
1104           mTextureArraySliceUniformLocation(-1)
1105     {}
1106 
getVertexShaderSource()1107     const char *getVertexShaderSource() override
1108     {
1109         return R"(#version 300 es
1110 out vec2 texcoord;
1111 in vec4 position;
1112 void main()
1113 {
1114     gl_Position = vec4(position.xy, 0.0, 1.0);
1115     texcoord = (position.xy * 0.5) + 0.5;
1116 })";
1117     }
1118 
getFragmentShaderSource()1119     const char *getFragmentShaderSource() override
1120     {
1121         return R"(#version 300 es
1122 precision highp float;
1123 uniform highp sampler2DArray tex2DArray;
1124 uniform int slice;
1125 in vec2 texcoord;
1126 out vec4 fragColor;
1127 void main()
1128 {
1129     fragColor = texture(tex2DArray, vec3(texcoord, float(slice)));
1130 })";
1131     }
1132 
testSetUp()1133     void testSetUp() override
1134     {
1135         TexCoordDrawTest::testSetUp();
1136 
1137         setUpProgram();
1138 
1139         mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
1140         ASSERT_NE(-1, mTextureArrayLocation);
1141 
1142         mTextureArraySliceUniformLocation = glGetUniformLocation(mProgram, "slice");
1143         ASSERT_NE(-1, mTextureArraySliceUniformLocation);
1144 
1145         glGenTextures(1, &m2DArrayTexture);
1146         ASSERT_GL_NO_ERROR();
1147     }
1148 
testTearDown()1149     void testTearDown() override
1150     {
1151         glDeleteTextures(1, &m2DArrayTexture);
1152         TexCoordDrawTest::testTearDown();
1153     }
1154 
1155     GLuint m2DArrayTexture;
1156     GLint mTextureArrayLocation;
1157     GLint mTextureArraySliceUniformLocation;
1158 };
1159 
1160 class TextureSizeTextureArrayTest : public TexCoordDrawTest
1161 {
1162   protected:
TextureSizeTextureArrayTest()1163     TextureSizeTextureArrayTest()
1164         : TexCoordDrawTest(),
1165           mTexture2DA(0),
1166           mTexture2DB(0),
1167           mTexture0Location(-1),
1168           mTexture1Location(-1)
1169     {}
1170 
getVertexShaderSource()1171     const char *getVertexShaderSource() override { return essl3_shaders::vs::Simple(); }
1172 
getFragmentShaderSource()1173     const char *getFragmentShaderSource() override
1174     {
1175         return "#version 300 es\n"
1176                "precision highp float;\n"
1177                "uniform highp sampler2D tex2DArray[2];\n"
1178                "out vec4 fragColor;\n"
1179                "void main()\n"
1180                "{\n"
1181                "    float red = float(textureSize(tex2DArray[0], 0).x) / 255.0;\n"
1182                "    float green = float(textureSize(tex2DArray[1], 0).x) / 255.0;\n"
1183                "    fragColor = vec4(red, green, 0.0, 1.0);\n"
1184                "}\n";
1185     }
1186 
testSetUp()1187     void testSetUp() override
1188     {
1189         TexCoordDrawTest::testSetUp();
1190 
1191         setUpProgram();
1192 
1193         mTexture0Location = glGetUniformLocation(mProgram, "tex2DArray[0]");
1194         ASSERT_NE(-1, mTexture0Location);
1195         mTexture1Location = glGetUniformLocation(mProgram, "tex2DArray[1]");
1196         ASSERT_NE(-1, mTexture1Location);
1197 
1198         mTexture2DA = create2DTexture();
1199         mTexture2DB = create2DTexture();
1200         ASSERT_GL_NO_ERROR();
1201     }
1202 
testTearDown()1203     void testTearDown() override
1204     {
1205         glDeleteTextures(1, &mTexture2DA);
1206         glDeleteTextures(1, &mTexture2DB);
1207         TexCoordDrawTest::testTearDown();
1208     }
1209 
1210     GLuint mTexture2DA;
1211     GLuint mTexture2DB;
1212     GLint mTexture0Location;
1213     GLint mTexture1Location;
1214 };
1215 
1216 // Test for GL_OES_texture_3D extension
1217 class Texture3DTestES2 : public TexCoordDrawTest
1218 {
1219   protected:
Texture3DTestES2()1220     Texture3DTestES2() : TexCoordDrawTest(), mTexture3D(0), mTexture3DUniformLocation(-1) {}
1221 
getVertexShaderSource()1222     const char *getVertexShaderSource() override
1223     {
1224         return "#version 100\n"
1225                "varying vec2 texcoord;\n"
1226                "attribute vec4 position;\n"
1227                "void main()\n"
1228                "{\n"
1229                "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1230                "    texcoord = (position.xy * 0.5) + 0.5;\n"
1231                "}\n";
1232     }
1233 
getFragmentShaderSource()1234     const char *getFragmentShaderSource() override
1235     {
1236         if (!hasTexture3DExt())
1237         {
1238             return "#version 100\n"
1239                    "precision highp float;\n"
1240                    "varying vec2 texcoord;\n"
1241                    "void main()\n"
1242                    "{\n"
1243                    "    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
1244                    "}\n";
1245         }
1246         return "#version 100\n"
1247                "#extension GL_OES_texture_3D : enable\n"
1248                "precision highp float;\n"
1249                "uniform highp sampler3D tex3D;\n"
1250                "uniform highp float level;\n"
1251                "varying vec2 texcoord;\n"
1252                "void main()\n"
1253                "{\n"
1254                "    gl_FragColor = texture3DLod(tex3D, vec3(texcoord, 0.0), level);\n"
1255                "}\n";
1256     }
1257 
testSetUp()1258     void testSetUp() override
1259     {
1260         // http://anglebug.com/5728
1261         ANGLE_SKIP_TEST_IF(IsOzone());
1262 
1263         TexCoordDrawTest::testSetUp();
1264 
1265         glGenTextures(1, &mTexture3D);
1266 
1267         setUpProgram();
1268 
1269         mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
1270         if (hasTexture3DExt())
1271         {
1272             ASSERT_NE(-1, mTexture3DUniformLocation);
1273         }
1274     }
1275 
testTearDown()1276     void testTearDown() override
1277     {
1278         glDeleteTextures(1, &mTexture3D);
1279         TexCoordDrawTest::testTearDown();
1280     }
1281 
hasTexture3DExt() const1282     bool hasTexture3DExt() const
1283     {
1284         // http://anglebug.com/4927
1285         if ((IsPixel2() || IsNexus5X()) && IsOpenGLES())
1286         {
1287             return false;
1288         }
1289         return IsGLExtensionEnabled("GL_OES_texture_3D");
1290     }
1291 
1292     GLuint mTexture3D;
1293     GLint mTexture3DUniformLocation;
1294 };
1295 
1296 class Texture3DTestES3 : public Texture3DTestES2
1297 {
1298   protected:
Texture3DTestES3()1299     Texture3DTestES3() : Texture3DTestES2() {}
1300 
getVertexShaderSource()1301     const char *getVertexShaderSource() override
1302     {
1303         return "#version 300 es\n"
1304                "out vec2 texcoord;\n"
1305                "in vec4 position;\n"
1306                "void main()\n"
1307                "{\n"
1308                "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1309                "    texcoord = (position.xy * 0.5) + 0.5;\n"
1310                "}\n";
1311     }
1312 
getFragmentShaderSource()1313     const char *getFragmentShaderSource() override
1314     {
1315         return "#version 300 es\n"
1316                "precision highp float;\n"
1317                "uniform highp sampler3D tex3D;\n"
1318                "in vec2 texcoord;\n"
1319                "out vec4 fragColor;\n"
1320                "void main()\n"
1321                "{\n"
1322                "    fragColor = texture(tex3D, vec3(texcoord, 0.0));\n"
1323                "}\n";
1324     }
1325 };
1326 
1327 class ShadowSamplerPlusSampler3DTestES3 : public TexCoordDrawTest
1328 {
1329   protected:
ShadowSamplerPlusSampler3DTestES3()1330     ShadowSamplerPlusSampler3DTestES3()
1331         : TexCoordDrawTest(),
1332           mTextureShadow(0),
1333           mTexture3D(0),
1334           mTextureShadowUniformLocation(-1),
1335           mTexture3DUniformLocation(-1),
1336           mDepthRefUniformLocation(-1)
1337     {}
1338 
getVertexShaderSource()1339     const char *getVertexShaderSource() override
1340     {
1341         return "#version 300 es\n"
1342                "out vec2 texcoord;\n"
1343                "in vec4 position;\n"
1344                "void main()\n"
1345                "{\n"
1346                "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1347                "    texcoord = (position.xy * 0.5) + 0.5;\n"
1348                "}\n";
1349     }
1350 
getFragmentShaderSource()1351     const char *getFragmentShaderSource() override
1352     {
1353         return "#version 300 es\n"
1354                "precision highp float;\n"
1355                "uniform highp sampler2DShadow tex2DShadow;\n"
1356                "uniform highp sampler3D tex3D;\n"
1357                "in vec2 texcoord;\n"
1358                "uniform float depthRef;\n"
1359                "out vec4 fragColor;\n"
1360                "void main()\n"
1361                "{\n"
1362                "    fragColor = vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.5);\n"
1363                "    fragColor += texture(tex3D, vec3(texcoord, 0.0));\n"
1364                "}\n";
1365     }
1366 
testSetUp()1367     void testSetUp() override
1368     {
1369         TexCoordDrawTest::testSetUp();
1370 
1371         glGenTextures(1, &mTexture3D);
1372 
1373         glGenTextures(1, &mTextureShadow);
1374         glBindTexture(GL_TEXTURE_2D, mTextureShadow);
1375         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1376 
1377         setUpProgram();
1378 
1379         mTextureShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
1380         ASSERT_NE(-1, mTextureShadowUniformLocation);
1381         mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
1382         ASSERT_NE(-1, mTexture3DUniformLocation);
1383         mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
1384         ASSERT_NE(-1, mDepthRefUniformLocation);
1385     }
1386 
testTearDown()1387     void testTearDown() override
1388     {
1389         glDeleteTextures(1, &mTextureShadow);
1390         glDeleteTextures(1, &mTexture3D);
1391         TexCoordDrawTest::testTearDown();
1392     }
1393 
1394     GLuint mTextureShadow;
1395     GLuint mTexture3D;
1396     GLint mTextureShadowUniformLocation;
1397     GLint mTexture3DUniformLocation;
1398     GLint mDepthRefUniformLocation;
1399 };
1400 
1401 class SamplerTypeMixTestES3 : public TexCoordDrawTest
1402 {
1403   protected:
SamplerTypeMixTestES3()1404     SamplerTypeMixTestES3()
1405         : TexCoordDrawTest(),
1406           mTexture2D(0),
1407           mTextureCube(0),
1408           mTexture2DShadow(0),
1409           mTextureCubeShadow(0),
1410           mTexture2DUniformLocation(-1),
1411           mTextureCubeUniformLocation(-1),
1412           mTexture2DShadowUniformLocation(-1),
1413           mTextureCubeShadowUniformLocation(-1),
1414           mDepthRefUniformLocation(-1)
1415     {}
1416 
getVertexShaderSource()1417     const char *getVertexShaderSource() override
1418     {
1419         return "#version 300 es\n"
1420                "out vec2 texcoord;\n"
1421                "in vec4 position;\n"
1422                "void main()\n"
1423                "{\n"
1424                "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1425                "    texcoord = (position.xy * 0.5) + 0.5;\n"
1426                "}\n";
1427     }
1428 
getFragmentShaderSource()1429     const char *getFragmentShaderSource() override
1430     {
1431         return "#version 300 es\n"
1432                "precision highp float;\n"
1433                "uniform highp sampler2D tex2D;\n"
1434                "uniform highp samplerCube texCube;\n"
1435                "uniform highp sampler2DShadow tex2DShadow;\n"
1436                "uniform highp samplerCubeShadow texCubeShadow;\n"
1437                "in vec2 texcoord;\n"
1438                "uniform float depthRef;\n"
1439                "out vec4 fragColor;\n"
1440                "void main()\n"
1441                "{\n"
1442                "    fragColor = texture(tex2D, texcoord);\n"
1443                "    fragColor += texture(texCube, vec3(1.0, 0.0, 0.0));\n"
1444                "    fragColor += vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.25);\n"
1445                "    fragColor += vec4(texture(texCubeShadow, vec4(1.0, 0.0, 0.0, depthRef)) * "
1446                "0.125);\n"
1447                "}\n";
1448     }
1449 
testSetUp()1450     void testSetUp() override
1451     {
1452         TexCoordDrawTest::testSetUp();
1453 
1454         glGenTextures(1, &mTexture2D);
1455         glGenTextures(1, &mTextureCube);
1456 
1457         glGenTextures(1, &mTexture2DShadow);
1458         glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
1459         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1460 
1461         glGenTextures(1, &mTextureCubeShadow);
1462         glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
1463         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1464 
1465         setUpProgram();
1466 
1467         mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
1468         ASSERT_NE(-1, mTexture2DUniformLocation);
1469         mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
1470         ASSERT_NE(-1, mTextureCubeUniformLocation);
1471         mTexture2DShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
1472         ASSERT_NE(-1, mTexture2DShadowUniformLocation);
1473         mTextureCubeShadowUniformLocation = glGetUniformLocation(mProgram, "texCubeShadow");
1474         ASSERT_NE(-1, mTextureCubeShadowUniformLocation);
1475         mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
1476         ASSERT_NE(-1, mDepthRefUniformLocation);
1477 
1478         ASSERT_GL_NO_ERROR();
1479     }
1480 
testTearDown()1481     void testTearDown() override
1482     {
1483         glDeleteTextures(1, &mTexture2D);
1484         glDeleteTextures(1, &mTextureCube);
1485         glDeleteTextures(1, &mTexture2DShadow);
1486         glDeleteTextures(1, &mTextureCubeShadow);
1487         TexCoordDrawTest::testTearDown();
1488     }
1489 
1490     GLuint mTexture2D;
1491     GLuint mTextureCube;
1492     GLuint mTexture2DShadow;
1493     GLuint mTextureCubeShadow;
1494     GLint mTexture2DUniformLocation;
1495     GLint mTextureCubeUniformLocation;
1496     GLint mTexture2DShadowUniformLocation;
1497     GLint mTextureCubeShadowUniformLocation;
1498     GLint mDepthRefUniformLocation;
1499 };
1500 
1501 class SamplerInStructTest : public Texture2DTest
1502 {
1503   protected:
SamplerInStructTest()1504     SamplerInStructTest() : Texture2DTest() {}
1505 
getTextureUniformName()1506     const char *getTextureUniformName() override { return "us.tex"; }
1507 
getFragmentShaderSource()1508     const char *getFragmentShaderSource() override
1509     {
1510         return "precision highp float;\n"
1511                "struct S\n"
1512                "{\n"
1513                "    vec4 a;\n"
1514                "    highp sampler2D tex;\n"
1515                "};\n"
1516                "uniform S us;\n"
1517                "varying vec2 texcoord;\n"
1518                "void main()\n"
1519                "{\n"
1520                "    gl_FragColor = texture2D(us.tex, texcoord + us.a.x);\n"
1521                "}\n";
1522     }
1523 
runSamplerInStructTest()1524     void runSamplerInStructTest()
1525     {
1526         setUpProgram();
1527 
1528         glActiveTexture(GL_TEXTURE0);
1529         glBindTexture(GL_TEXTURE_2D, mTexture2D);
1530         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1531                      &GLColor::green);
1532         drawQuad(mProgram, "position", 0.5f);
1533         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1534     }
1535 };
1536 
1537 class SamplerInStructAsFunctionParameterTest : public SamplerInStructTest
1538 {
1539   protected:
SamplerInStructAsFunctionParameterTest()1540     SamplerInStructAsFunctionParameterTest() : SamplerInStructTest() {}
1541 
getFragmentShaderSource()1542     const char *getFragmentShaderSource() override
1543     {
1544         return "precision highp float;\n"
1545                "struct S\n"
1546                "{\n"
1547                "    vec4 a;\n"
1548                "    highp sampler2D tex;\n"
1549                "};\n"
1550                "uniform S us;\n"
1551                "varying vec2 texcoord;\n"
1552                "vec4 sampleFrom(S s) {\n"
1553                "    return texture2D(s.tex, texcoord + s.a.x);\n"
1554                "}\n"
1555                "void main()\n"
1556                "{\n"
1557                "    gl_FragColor = sampleFrom(us);\n"
1558                "}\n";
1559     }
1560 };
1561 
1562 class SamplerInStructArrayAsFunctionParameterTest : public SamplerInStructTest
1563 {
1564   protected:
SamplerInStructArrayAsFunctionParameterTest()1565     SamplerInStructArrayAsFunctionParameterTest() : SamplerInStructTest() {}
1566 
getTextureUniformName()1567     const char *getTextureUniformName() override { return "us[0].tex"; }
1568 
getFragmentShaderSource()1569     const char *getFragmentShaderSource() override
1570     {
1571         return "precision highp float;\n"
1572                "struct S\n"
1573                "{\n"
1574                "    vec4 a;\n"
1575                "    highp sampler2D tex;\n"
1576                "};\n"
1577                "uniform S us[1];\n"
1578                "varying vec2 texcoord;\n"
1579                "vec4 sampleFrom(S s) {\n"
1580                "    return texture2D(s.tex, texcoord + s.a.x);\n"
1581                "}\n"
1582                "void main()\n"
1583                "{\n"
1584                "    gl_FragColor = sampleFrom(us[0]);\n"
1585                "}\n";
1586     }
1587 };
1588 
1589 class SamplerInNestedStructAsFunctionParameterTest : public SamplerInStructTest
1590 {
1591   protected:
SamplerInNestedStructAsFunctionParameterTest()1592     SamplerInNestedStructAsFunctionParameterTest() : SamplerInStructTest() {}
1593 
getTextureUniformName()1594     const char *getTextureUniformName() override { return "us[0].sub.tex"; }
1595 
getFragmentShaderSource()1596     const char *getFragmentShaderSource() override
1597     {
1598         return "precision highp float;\n"
1599                "struct SUB\n"
1600                "{\n"
1601                "    vec4 a;\n"
1602                "    highp sampler2D tex;\n"
1603                "};\n"
1604                "struct S\n"
1605                "{\n"
1606                "    SUB sub;\n"
1607                "};\n"
1608                "uniform S us[1];\n"
1609                "varying vec2 texcoord;\n"
1610                "vec4 sampleFrom(SUB s) {\n"
1611                "    return texture2D(s.tex, texcoord + s.a.x);\n"
1612                "}\n"
1613                "void main()\n"
1614                "{\n"
1615                "    gl_FragColor = sampleFrom(us[0].sub);\n"
1616                "}\n";
1617     }
1618 };
1619 
1620 class SamplerInStructAndOtherVariableTest : public SamplerInStructTest
1621 {
1622   protected:
SamplerInStructAndOtherVariableTest()1623     SamplerInStructAndOtherVariableTest() : SamplerInStructTest() {}
1624 
getFragmentShaderSource()1625     const char *getFragmentShaderSource() override
1626     {
1627         return "precision highp float;\n"
1628                "struct S\n"
1629                "{\n"
1630                "    vec4 a;\n"
1631                "    highp sampler2D tex;\n"
1632                "};\n"
1633                "uniform S us;\n"
1634                "uniform float us_tex;\n"
1635                "varying vec2 texcoord;\n"
1636                "void main()\n"
1637                "{\n"
1638                "    gl_FragColor = texture2D(us.tex, texcoord + us.a.x + us_tex);\n"
1639                "}\n";
1640     }
1641 };
1642 
1643 class Texture2DIntegerTestES3 : public Texture2DTest
1644 {
1645   protected:
Texture2DIntegerTestES3()1646     Texture2DIntegerTestES3() : Texture2DTest() {}
1647 
getVertexShaderSource()1648     const char *getVertexShaderSource() override
1649     {
1650         return "#version 300 es\n"
1651                "out vec2 texcoord;\n"
1652                "in vec4 position;\n"
1653                "void main()\n"
1654                "{\n"
1655                "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1656                "    texcoord = (position.xy * 0.5) + 0.5;\n"
1657                "}\n";
1658     }
1659 
getFragmentShaderSource()1660     const char *getFragmentShaderSource() override
1661     {
1662         return "#version 300 es\n"
1663                "precision highp float;\n"
1664                "precision highp usampler2D;\n"
1665                "uniform usampler2D tex;\n"
1666                "in vec2 texcoord;\n"
1667                "out vec4 fragColor;\n"
1668                "void main()\n"
1669                "{\n"
1670                "    fragColor = vec4(texture(tex, texcoord))/255.0;\n"
1671                "}\n";
1672     }
1673 };
1674 
1675 class TextureCubeIntegerTestES3 : public TexCoordDrawTest
1676 {
1677   protected:
TextureCubeIntegerTestES3()1678     TextureCubeIntegerTestES3()
1679         : TexCoordDrawTest(), mTextureCube(0), mTextureCubeUniformLocation(-1)
1680     {}
1681 
getVertexShaderSource()1682     const char *getVertexShaderSource() override
1683     {
1684         return "#version 300 es\n"
1685                "out vec2 texcoord;\n"
1686                "in vec4 position;\n"
1687                "void main()\n"
1688                "{\n"
1689                "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1690                "    texcoord = 0.5*position.xy;\n"
1691                "}\n";
1692     }
1693 
getFragmentShaderSource()1694     const char *getFragmentShaderSource() override
1695     {
1696         return "#version 300 es\n"
1697                "precision highp float;\n"
1698                "precision highp usamplerCube;\n"
1699                "uniform usamplerCube texCube;\n"
1700                "in vec2 texcoord;\n"
1701                "out vec4 fragColor;\n"
1702                "void main()\n"
1703                "{\n"
1704                "    fragColor = vec4(texture(texCube, vec3(texcoord, 1)))/255.0;\n"
1705                "}\n";
1706     }
1707 
testSetUp()1708     void testSetUp() override
1709     {
1710         TexCoordDrawTest::testSetUp();
1711         glGenTextures(1, &mTextureCube);
1712         setUpProgram();
1713 
1714         mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
1715         ASSERT_NE(-1, mTextureCubeUniformLocation);
1716     }
1717 
testTearDown()1718     void testTearDown() override
1719     {
1720         glDeleteTextures(1, &mTextureCube);
1721         TexCoordDrawTest::testTearDown();
1722     }
1723 
1724     GLuint mTextureCube;
1725     GLint mTextureCubeUniformLocation;
1726 };
1727 
1728 class TextureCubeIntegerEdgeTestES3 : public TextureCubeIntegerTestES3
1729 {
1730   protected:
TextureCubeIntegerEdgeTestES3()1731     TextureCubeIntegerEdgeTestES3() : TextureCubeIntegerTestES3() {}
1732 
getVertexShaderSource()1733     const char *getVertexShaderSource() override
1734     {
1735         return "#version 300 es\n"
1736                "out vec2 texcoord;\n"
1737                "in vec4 position;\n"
1738                "void main()\n"
1739                "{\n"
1740                "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1741                "    texcoord = position.xy;\n"
1742                "}\n";
1743     }
1744 
getFragmentShaderSource()1745     const char *getFragmentShaderSource() override
1746     {
1747         return "#version 300 es\n"
1748                "precision highp float;\n"
1749                "precision highp usamplerCube;\n"
1750                "uniform usamplerCube texCube;\n"
1751                "in vec2 texcoord;\n"
1752                "out vec4 fragColor;\n"
1753                "void main()\n"
1754                "{\n"
1755                "    fragColor = vec4(texture(texCube, vec3(texcoord, 0)))/255.0;\n"
1756                "}\n";
1757     }
1758 };
1759 
1760 class Texture2DIntegerProjectiveOffsetTestES3 : public Texture2DTest
1761 {
1762   protected:
Texture2DIntegerProjectiveOffsetTestES3()1763     Texture2DIntegerProjectiveOffsetTestES3() : Texture2DTest() {}
1764 
getVertexShaderSource()1765     const char *getVertexShaderSource() override
1766     {
1767         return "#version 300 es\n"
1768                "out vec2 texcoord;\n"
1769                "in vec4 position;\n"
1770                "void main()\n"
1771                "{\n"
1772                "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1773                "    texcoord = 0.5*position.xy + vec2(0.5, 0.5);\n"
1774                "}\n";
1775     }
1776 
getFragmentShaderSource()1777     const char *getFragmentShaderSource() override
1778     {
1779         return "#version 300 es\n"
1780                "precision highp float;\n"
1781                "precision highp usampler2D;\n"
1782                "uniform usampler2D tex;\n"
1783                "in vec2 texcoord;\n"
1784                "out vec4 fragColor;\n"
1785                "void main()\n"
1786                "{\n"
1787                "    fragColor = vec4(textureProjOffset(tex, vec3(texcoord, 1), ivec2(0,0), "
1788                "0.0))/255.0;\n"
1789                "}\n";
1790     }
1791 };
1792 
1793 class Texture2DArrayIntegerTestES3 : public Texture2DArrayTestES3
1794 {
1795   protected:
Texture2DArrayIntegerTestES3()1796     Texture2DArrayIntegerTestES3() : Texture2DArrayTestES3() {}
1797 
getVertexShaderSource()1798     const char *getVertexShaderSource() override
1799     {
1800         return R"(#version 300 es
1801 out vec2 texcoord;
1802 in vec4 position;
1803 void main()
1804 {
1805     gl_Position = vec4(position.xy, 0.0, 1.0);
1806     texcoord = (position.xy * 0.5) + 0.5;
1807 })";
1808     }
1809 
getFragmentShaderSource()1810     const char *getFragmentShaderSource() override
1811     {
1812         return R"(#version 300 es
1813 precision highp float;
1814 uniform highp usampler2DArray tex2DArray;
1815 uniform int slice;
1816 in vec2 texcoord;
1817 out vec4 fragColor;
1818 void main()
1819 {
1820     fragColor = vec4(texture(tex2DArray, vec3(texcoord, slice)))/255.0;
1821 })";
1822     }
1823 };
1824 
1825 class Texture3DIntegerTestES3 : public Texture3DTestES3
1826 {
1827   protected:
Texture3DIntegerTestES3()1828     Texture3DIntegerTestES3() : Texture3DTestES3() {}
1829 
getVertexShaderSource()1830     const char *getVertexShaderSource() override
1831     {
1832         return "#version 300 es\n"
1833                "out vec2 texcoord;\n"
1834                "in vec4 position;\n"
1835                "void main()\n"
1836                "{\n"
1837                "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1838                "    texcoord = (position.xy * 0.5) + 0.5;\n"
1839                "}\n";
1840     }
1841 
getFragmentShaderSource()1842     const char *getFragmentShaderSource() override
1843     {
1844         return "#version 300 es\n"
1845                "precision highp float;\n"
1846                "uniform highp usampler3D tex3D;\n"
1847                "in vec2 texcoord;\n"
1848                "out vec4 fragColor;\n"
1849                "void main()\n"
1850                "{\n"
1851                "    fragColor = vec4(texture(tex3D, vec3(texcoord, 0.0)))/255.0;\n"
1852                "}\n";
1853     }
1854 };
1855 
1856 class PBOCompressedTextureTest : public Texture2DTest
1857 {
1858   protected:
PBOCompressedTextureTest()1859     PBOCompressedTextureTest() : Texture2DTest() {}
1860 
testSetUp()1861     void testSetUp() override
1862     {
1863         TexCoordDrawTest::testSetUp();
1864         glGenTextures(1, &mTexture2D);
1865         glBindTexture(GL_TEXTURE_2D, mTexture2D);
1866         EXPECT_GL_NO_ERROR();
1867 
1868         setUpProgram();
1869 
1870         glGenBuffers(1, &mPBO);
1871     }
1872 
testTearDown()1873     void testTearDown() override
1874     {
1875         glDeleteBuffers(1, &mPBO);
1876         Texture2DTest::testTearDown();
1877     }
1878 
1879     void runCompressedSubImage();
1880 
1881     GLuint mPBO;
1882 };
1883 
1884 class ETC1CompressedTextureTest : public Texture2DTest
1885 {
1886   protected:
ETC1CompressedTextureTest()1887     ETC1CompressedTextureTest() : Texture2DTest() {}
1888 
testSetUp()1889     void testSetUp() override
1890     {
1891         TexCoordDrawTest::testSetUp();
1892         glGenTextures(1, &mTexture2D);
1893         glBindTexture(GL_TEXTURE_2D, mTexture2D);
1894         EXPECT_GL_NO_ERROR();
1895 
1896         setUpProgram();
1897     }
1898 
testTearDown()1899     void testTearDown() override { Texture2DTest::testTearDown(); }
1900 };
1901 
1902 class Texture2DDepthStencilTestES3 : public Texture2DTest
1903 {
1904   protected:
Texture2DDepthStencilTestES3()1905     Texture2DDepthStencilTestES3() : Texture2DTest() {}
1906 
1907     void TestSampleWithDepthStencilMode(GLenum format, GLenum mode, bool swizzle);
1908 };
1909 
TestSampleWithDepthStencilMode(GLenum format,GLenum mode,bool swizzle)1910 void Texture2DDepthStencilTestES3::TestSampleWithDepthStencilMode(GLenum format,
1911                                                                   GLenum mode,
1912                                                                   bool swizzle)
1913 {
1914     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_stencil_texturing"));
1915 
1916     constexpr GLsizei kSize = 4;
1917 
1918     ASSERT(mode == GL_STENCIL_INDEX || mode == GL_DEPTH_COMPONENT);
1919 
1920     bool isStencilMode;
1921     GLenum attachment;
1922     switch (format)
1923     {
1924         case GL_DEPTH_COMPONENT16:
1925         case GL_DEPTH_COMPONENT24:
1926         case GL_DEPTH_COMPONENT32F:
1927             attachment    = GL_DEPTH_ATTACHMENT;
1928             isStencilMode = false;
1929             break;
1930         case GL_DEPTH24_STENCIL8:
1931         case GL_DEPTH32F_STENCIL8:
1932             attachment    = GL_DEPTH_STENCIL_ATTACHMENT;
1933             isStencilMode = mode == GL_STENCIL_INDEX;
1934             break;
1935         case GL_STENCIL_INDEX8:
1936             attachment    = GL_STENCIL_ATTACHMENT;
1937             isStencilMode = true;
1938             break;
1939         default:
1940             UNREACHABLE();
1941     }
1942 
1943     // Set up a color texture.
1944     GLTexture colorTexture;
1945     glBindTexture(GL_TEXTURE_2D, colorTexture);
1946     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
1947     ASSERT_GL_NO_ERROR();
1948 
1949     // Set up a depth/stencil texture to be sampled as mode.
1950     GLTexture depthStencilTexture;
1951     glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
1952     glTexStorage2D(GL_TEXTURE_2D, 1, format, kSize, kSize);
1953     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1954     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1955     glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, mode);
1956     if (swizzle)
1957     {
1958         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ALPHA);
1959         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
1960         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_GREEN);
1961         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
1962     }
1963     ASSERT_GL_NO_ERROR();
1964 
1965     constexpr char kStencilFS[] =
1966         R"(#version 300 es
1967 precision mediump float;
1968 uniform highp usampler2D tex;
1969 out vec4 color;
1970 void main()
1971 {
1972     color = vec4(texelFetch(tex, ivec2(0, 0), 0)) / 255.0f;
1973 })";
1974 
1975     constexpr char kDepthFS[] =
1976         R"(#version 300 es
1977 precision mediump float;
1978 uniform highp sampler2D tex;
1979 out vec4 color;
1980 void main()
1981 {
1982     color = texture(tex, vec2(0, 0));
1983 })";
1984 
1985     // Clear stencil to 42.
1986     GLFramebuffer clearFBO;
1987     glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
1988     glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, depthStencilTexture, 0);
1989     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1990     glClearDepthf(0.5);
1991     glClearStencil(42);
1992     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1993     ASSERT_GL_NO_ERROR();
1994 
1995     glActiveTexture(GL_TEXTURE0);
1996     glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
1997     EXPECT_GL_ERROR(GL_NO_ERROR);
1998 
1999     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), isStencilMode ? kStencilFS : kDepthFS);
2000     GLint texLocation = glGetUniformLocation(program, "tex");
2001     ASSERT_NE(-1, texLocation);
2002     ASSERT_GL_NO_ERROR();
2003 
2004     glUseProgram(program);
2005     glUniform1i(texLocation, 0);
2006 
2007     GLFramebuffer drawFBO;
2008     glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
2009     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2010     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2011     ASSERT_GL_NO_ERROR();
2012 
2013     drawQuad(program, essl3_shaders::PositionAttrib(), 0.95f);
2014     ASSERT_GL_NO_ERROR();
2015 
2016     if (isStencilMode)
2017     {
2018         GLColor expected = swizzle ? GLColor(1, 0, 0, 42) : GLColor(42, 0, 0, 1);
2019         EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, expected);
2020     }
2021     else
2022     {
2023         GLColor expected = swizzle ? GLColor(255, 0, 0, 127) : GLColor(127, 0, 0, 255);
2024         EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
2025     }
2026 }
2027 
TEST_P(Texture2DTest,NegativeAPISubImage)2028 TEST_P(Texture2DTest, NegativeAPISubImage)
2029 {
2030     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2031     EXPECT_GL_ERROR(GL_NO_ERROR);
2032 
2033     setUpProgram();
2034 
2035     const GLubyte *pixels[20] = {0};
2036     glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2037     EXPECT_GL_ERROR(GL_INVALID_VALUE);
2038 
2039     if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
2040     {
2041         // Create a 1-level immutable texture.
2042         glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
2043 
2044         // Try calling sub image on the second level.
2045         glTexSubImage2D(GL_TEXTURE_2D, 1, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2046         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2047     }
2048 }
2049 
2050 // Test that querying GL_TEXTURE_BINDING* doesn't cause an unexpected error.
TEST_P(Texture2DTest,QueryBinding)2051 TEST_P(Texture2DTest, QueryBinding)
2052 {
2053     glBindTexture(GL_TEXTURE_2D, 0);
2054     EXPECT_GL_ERROR(GL_NO_ERROR);
2055 
2056     GLint textureBinding;
2057     glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
2058     EXPECT_GL_NO_ERROR();
2059     EXPECT_EQ(0, textureBinding);
2060 
2061     glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &textureBinding);
2062     if (IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
2063         IsGLExtensionEnabled("GL_NV_EGL_stream_consumer_external"))
2064     {
2065         EXPECT_GL_NO_ERROR();
2066         EXPECT_EQ(0, textureBinding);
2067     }
2068     else
2069     {
2070         EXPECT_GL_ERROR(GL_INVALID_ENUM);
2071     }
2072 }
2073 
TEST_P(Texture2DTest,ZeroSizedUploads)2074 TEST_P(Texture2DTest, ZeroSizedUploads)
2075 {
2076     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2077     EXPECT_GL_ERROR(GL_NO_ERROR);
2078 
2079     setUpProgram();
2080 
2081     // Use the texture first to make sure it's in video memory
2082     glUseProgram(mProgram);
2083     glUniform1i(mTexture2DUniformLocation, 0);
2084     drawQuad(mProgram, "position", 0.5f);
2085 
2086     const GLubyte *pixel[4] = {0};
2087 
2088     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2089     EXPECT_GL_NO_ERROR();
2090 
2091     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2092     EXPECT_GL_NO_ERROR();
2093 
2094     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2095     EXPECT_GL_NO_ERROR();
2096 }
2097 
2098 // Tests uploading a red texture and immediately reading from it.
TEST_P(Texture2DTest,SimpleUpload)2099 TEST_P(Texture2DTest, SimpleUpload)
2100 {
2101     const GLuint width            = getWindowWidth();
2102     const GLuint height           = getWindowHeight();
2103     const GLuint windowPixelCount = width * height;
2104     std::vector<GLColor> pixelsRed(windowPixelCount, GLColor::red);
2105     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2106     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2107                  pixelsRed.data());
2108     EXPECT_GL_ERROR(GL_NO_ERROR);
2109 
2110     GLFramebuffer fbo;
2111     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2112 
2113     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0);
2114 
2115     EXPECT_GL_ERROR(GL_NO_ERROR);
2116     std::vector<GLColor> output(windowPixelCount, GLColor::green);
2117     glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, output.data());
2118     EXPECT_EQ(pixelsRed, output);
2119 }
2120 
2121 // Test that interleaved superseded updates work as expected
TEST_P(Texture2DTest,InterleavedSupersedingTextureUpdates)2122 TEST_P(Texture2DTest, InterleavedSupersedingTextureUpdates)
2123 {
2124     constexpr uint32_t kTexWidth  = 3840;
2125     constexpr uint32_t kTexHeight = 2160;
2126     constexpr uint32_t kBpp       = 4;
2127 
2128     // Create the texture
2129     glActiveTexture(GL_TEXTURE0);
2130     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2131     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2132     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2133     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2134                  nullptr);
2135     EXPECT_GL_ERROR(GL_NO_ERROR);
2136 
2137     // 1. One big upload followed by many small identical uploads
2138     // Update the entire texture
2139     std::vector<GLubyte> fullTextureData(kTexWidth * kTexHeight * kBpp, 128);
2140     constexpr GLColor kFullTextureColor = GLColor(128u, 128u, 128u, 128u);
2141     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2142                     fullTextureData.data());
2143 
2144     // Make a number of identical updates to the right half of the texture
2145     std::vector<GLubyte> rightHalfData(kTexWidth * kTexHeight * kBpp, 201);
2146     constexpr GLColor kRightHalfColor = GLColor(201u, 201u, 201u, 201u);
2147     for (uint32_t iteration = 0; iteration < 10; iteration++)
2148     {
2149         glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, 0, kTexWidth / 2, kTexHeight, GL_RGBA,
2150                         GL_UNSIGNED_BYTE, rightHalfData.data());
2151     }
2152 
2153     setUpProgram();
2154     glUseProgram(mProgram);
2155     glUniform1i(mTexture2DUniformLocation, 0);
2156     drawQuad(mProgram, "position", 0.5f);
2157     EXPECT_GL_NO_ERROR();
2158     EXPECT_PIXEL_COLOR_EQ(1 * getWindowWidth() / 4, getWindowHeight() / 2, kFullTextureColor);
2159     EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 2, kRightHalfColor);
2160 
2161     // 2. Some small uploads followed by one big upload followed by many identical uploads
2162     // Clear the entire texture
2163     std::vector<GLubyte> zeroTextureData(kTexWidth * kTexHeight * kBpp, 255);
2164     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2165                     zeroTextureData.data());
2166 
2167     // Update the top left quadrant of the texture
2168     std::vector<GLubyte> topLeftQuadrantData(kTexWidth * kTexHeight * kBpp, 128);
2169     constexpr GLColor kTopLeftQuandrantTextureColor = GLColor(128u, 128u, 128u, 128u);
2170     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2, GL_RGBA,
2171                     GL_UNSIGNED_BYTE, topLeftQuadrantData.data());
2172 
2173     // Update the top right quadrant of the texture
2174     std::vector<GLubyte> topRightQuadrantData(kTexWidth * kTexHeight * kBpp, 156);
2175     constexpr GLColor kTopRightQuadrantTextureColor = GLColor(156u, 156u, 156u, 156u);
2176     glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2,
2177                     GL_RGBA, GL_UNSIGNED_BYTE, topRightQuadrantData.data());
2178 
2179     // Update the bottom half of the texture
2180     std::vector<GLubyte> bottomHalfTextureData(kTexWidth * kTexHeight * kBpp, 187);
2181     constexpr GLColor kBottomHalfTextureColor = GLColor(187u, 187u, 187u, 187u);
2182     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight / 2, GL_RGBA, GL_UNSIGNED_BYTE,
2183                     bottomHalfTextureData.data());
2184 
2185     // Make a number of identical updates to the bottom right quadrant of the texture
2186     std::vector<GLubyte> bottomRightQuadrantData(kTexWidth * kTexHeight * kBpp, 201);
2187     constexpr GLColor kBottomRightQuadrantColor = GLColor(201u, 201u, 201u, 201u);
2188     for (uint32_t iteration = 0; iteration < 10; iteration++)
2189     {
2190         glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, 0, kTexWidth / 2, kTexHeight / 2, GL_RGBA,
2191                         GL_UNSIGNED_BYTE, bottomRightQuadrantData.data());
2192     }
2193 
2194     setUpProgram();
2195     glUseProgram(mProgram);
2196     glUniform1i(mTexture2DUniformLocation, 0);
2197     drawQuad(mProgram, "position", 0.5f);
2198     EXPECT_GL_NO_ERROR();
2199     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, kTopLeftQuandrantTextureColor);
2200     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1,
2201                           kTopRightQuadrantTextureColor);
2202     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, kBottomHalfTextureColor);
2203     EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4,
2204                           kBottomRightQuadrantColor);
2205 
2206     // 3. Many small uploads folloed by one big upload
2207     // Clear the entire texture
2208     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2209                     zeroTextureData.data());
2210 
2211     // Make a number of small updates to different parts of the texture
2212     std::vector<std::pair<GLint, GLint>> xyOffsets = {
2213         {1, 4}, {128, 34}, {1208, 1090}, {2560, 2022}};
2214     constexpr GLColor kRandomColor = GLColor(55u, 128u, 201u, 255u);
2215     for (const std::pair<GLint, GLint> &xyOffset : xyOffsets)
2216     {
2217         glTexSubImage2D(GL_TEXTURE_2D, 0, xyOffset.first, xyOffset.second, 1, 1, GL_RGBA,
2218                         GL_UNSIGNED_BYTE, kRandomColor.data());
2219     }
2220 
2221     // Update the entire texture
2222     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2223                     fullTextureData.data());
2224 
2225     setUpProgram();
2226     glUseProgram(mProgram);
2227     glUniform1i(mTexture2DUniformLocation, 0);
2228     drawQuad(mProgram, "position", 0.5f);
2229     EXPECT_GL_NO_ERROR();
2230     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth() - 1, getWindowHeight() - 1, kFullTextureColor);
2231 }
2232 
2233 // Test that repeated calls to glTexSubImage2D with superseding updates works
TEST_P(Texture2DTest,ManySupersedingTextureUpdates)2234 TEST_P(Texture2DTest, ManySupersedingTextureUpdates)
2235 {
2236     constexpr uint32_t kTexWidth  = 3840;
2237     constexpr uint32_t kTexHeight = 2160;
2238     constexpr uint32_t kBpp       = 4;
2239     std::vector<GLubyte> data(kTexWidth * kTexHeight * kBpp, 0);
2240 
2241     // Create the texture
2242     glActiveTexture(GL_TEXTURE0);
2243     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2244     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2245     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2246     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2247                  nullptr);
2248     EXPECT_GL_ERROR(GL_NO_ERROR);
2249 
2250     // Make a large number of superseding updates
2251     for (uint32_t width = kTexWidth / 2, height = kTexHeight / 2;
2252          width < kTexWidth && height < kTexHeight; width++, height++)
2253     {
2254         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
2255                         data.data());
2256     }
2257 
2258     // Upload different color to the whole texture thus superseding all prior updates.
2259     std::vector<GLubyte> supersedingData(kTexWidth * kTexHeight * kBpp, 128);
2260     constexpr GLColor kGray = GLColor(128u, 128u, 128u, 128u);
2261     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2262                     supersedingData.data());
2263 
2264     setUpProgram();
2265     glUseProgram(mProgram);
2266     glUniform1i(mTexture2DUniformLocation, 0);
2267     drawQuad(mProgram, "position", 0.5f);
2268     EXPECT_GL_NO_ERROR();
2269     EXPECT_PIXEL_COLOR_EQ(0, 0, kGray);
2270 }
2271 
TEST_P(Texture2DTest,DefineMultipleLevelsWithoutMipmapping)2272 TEST_P(Texture2DTest, DefineMultipleLevelsWithoutMipmapping)
2273 {
2274     setUpProgram();
2275 
2276     constexpr size_t kImageSize = 256;
2277     std::array<GLColor, kImageSize * kImageSize> kMipColors[2];
2278 
2279     std::fill(kMipColors[0].begin(), kMipColors[0].end(), GLColor::red);
2280     std::fill(kMipColors[1].begin(), kMipColors[1].end(), GLColor::green);
2281 
2282     glActiveTexture(GL_TEXTURE0);
2283     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2284     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2285     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2286 
2287     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2288                  kMipColors[0].data());
2289     EXPECT_GL_NO_ERROR();
2290 
2291     // Draw so the image is created.
2292     glUseProgram(mProgram);
2293     glUniform1i(mTexture2DUniformLocation, 0);
2294     drawQuad(mProgram, "position", 0.5f);
2295 
2296     // Define level 1 of the texture.
2297     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2298                  kMipColors[1].data());
2299     EXPECT_GL_NO_ERROR();
2300 
2301     // Draw again.
2302     drawQuad(mProgram, "position", 0.5f);
2303     EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0][0]);
2304 }
2305 
2306 // Test drawing with two texture types, to trigger an ANGLE bug in validation
TEST_P(TextureCubeTest,CubeMapBug)2307 TEST_P(TextureCubeTest, CubeMapBug)
2308 {
2309     glActiveTexture(GL_TEXTURE0);
2310     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2311     glActiveTexture(GL_TEXTURE1);
2312     glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2313     EXPECT_GL_ERROR(GL_NO_ERROR);
2314 
2315     glUseProgram(mProgram);
2316     glUniform1i(mTexture2DUniformLocation, 0);
2317     glUniform1i(mTextureCubeUniformLocation, 1);
2318     drawQuad(mProgram, "position", 0.5f);
2319     EXPECT_GL_NO_ERROR();
2320 }
2321 
2322 // Test drawing with two texture types accessed from the same shader and check that the result of
2323 // drawing is correct.
TEST_P(TextureCubeTest,CubeMapDraw)2324 TEST_P(TextureCubeTest, CubeMapDraw)
2325 {
2326     GLubyte texData[4];
2327     texData[0] = 0;
2328     texData[1] = 60;
2329     texData[2] = 0;
2330     texData[3] = 255;
2331 
2332     glActiveTexture(GL_TEXTURE0);
2333     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2334     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
2335 
2336     glActiveTexture(GL_TEXTURE1);
2337     glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2338     texData[1] = 120;
2339     glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2340                     texData);
2341     glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2342                     texData);
2343     glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2344                     texData);
2345     glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2346                     texData);
2347     glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2348                     texData);
2349     glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2350                     texData);
2351     EXPECT_GL_ERROR(GL_NO_ERROR);
2352 
2353     glUseProgram(mProgram);
2354     glUniform1i(mTexture2DUniformLocation, 0);
2355     glUniform1i(mTextureCubeUniformLocation, 1);
2356     drawQuad(mProgram, "position", 0.5f);
2357     EXPECT_GL_NO_ERROR();
2358 
2359     int px = getWindowWidth() - 1;
2360     int py = 0;
2361     EXPECT_PIXEL_NEAR(px, py, 0, 180, 0, 255, 2);
2362 }
2363 
TEST_P(Sampler2DAsFunctionParameterTest,Sampler2DAsFunctionParameter)2364 TEST_P(Sampler2DAsFunctionParameterTest, Sampler2DAsFunctionParameter)
2365 {
2366     glActiveTexture(GL_TEXTURE0);
2367     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2368     GLubyte texData[4];
2369     texData[0] = 0;
2370     texData[1] = 128;
2371     texData[2] = 0;
2372     texData[3] = 255;
2373     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
2374     glUseProgram(mProgram);
2375     glUniform1i(mTexture2DUniformLocation, 0);
2376     drawQuad(mProgram, "position", 0.5f);
2377     EXPECT_GL_NO_ERROR();
2378 
2379     EXPECT_PIXEL_NEAR(0, 0, 0, 128, 0, 255, 2);
2380 }
2381 
2382 // Test drawing with two textures passed to the shader in a sampler array.
TEST_P(SamplerArrayTest,SamplerArrayDraw)2383 TEST_P(SamplerArrayTest, SamplerArrayDraw)
2384 {
2385     testSamplerArrayDraw();
2386 }
2387 
2388 // Test drawing with two textures passed to the shader in a sampler array which is passed to a
2389 // user-defined function in the shader.
TEST_P(SamplerArrayAsFunctionParameterTest,SamplerArrayAsFunctionParameter)2390 TEST_P(SamplerArrayAsFunctionParameterTest, SamplerArrayAsFunctionParameter)
2391 {
2392     // TODO: Diagnose and fix. http://anglebug.com/2955
2393     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
2394 
2395     testSamplerArrayDraw();
2396 }
2397 
2398 // Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
TEST_P(Texture2DTestWithDrawScale,MipmapsTwice)2399 TEST_P(Texture2DTestWithDrawScale, MipmapsTwice)
2400 {
2401     int px = getWindowWidth() / 2;
2402     int py = getWindowHeight() / 2;
2403 
2404     glActiveTexture(GL_TEXTURE0);
2405     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2406 
2407     std::vector<GLColor> pixelsRed(16u * 16u, GLColor::red);
2408 
2409     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
2410     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
2411     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2412     glGenerateMipmap(GL_TEXTURE_2D);
2413 
2414     glUseProgram(mProgram);
2415     glUniform1i(mTexture2DUniformLocation, 0);
2416     glUniform2f(mDrawScaleUniformLocation, 0.0625f, 0.0625f);
2417     drawQuad(mProgram, "position", 0.5f);
2418     EXPECT_GL_NO_ERROR();
2419     EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
2420 
2421     std::vector<GLColor> pixelsBlue(16u * 16u, GLColor::blue);
2422 
2423     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2424                  pixelsBlue.data());
2425     glGenerateMipmap(GL_TEXTURE_2D);
2426 
2427     drawQuad(mProgram, "position", 0.5f);
2428 
2429     EXPECT_GL_NO_ERROR();
2430     EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::blue);
2431 
2432     std::vector<GLColor> pixelsGreen(16u * 16u, GLColor::green);
2433 
2434     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2435                  pixelsGreen.data());
2436     glGenerateMipmap(GL_TEXTURE_2D);
2437 
2438     drawQuad(mProgram, "position", 0.5f);
2439 
2440     EXPECT_GL_NO_ERROR();
2441     EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
2442 }
2443 
2444 // Test creating a FBO with a cube map render target, to test an ANGLE bug
2445 // https://code.google.com/p/angleproject/issues/detail?id=849
TEST_P(TextureCubeTest,CubeMapFBO)2446 TEST_P(TextureCubeTest, CubeMapFBO)
2447 {
2448     // http://anglebug.com/3145
2449     ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
2450 
2451     GLFramebuffer fbo;
2452     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2453 
2454     glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2455     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
2456                            mTextureCube, 0);
2457 
2458     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2459     EXPECT_GL_NO_ERROR();
2460 
2461     // Test clearing the six mip faces individually.
2462     std::array<GLColor, 6> faceColors = {{GLColor::red, GLColor::green, GLColor::blue,
2463                                           GLColor::yellow, GLColor::cyan, GLColor::magenta}};
2464 
2465     for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
2466     {
2467         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2468                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
2469 
2470         Vector4 clearColorF = faceColors[faceIndex].toNormalizedVector();
2471         glClearColor(clearColorF.x(), clearColorF.y(), clearColorF.z(), clearColorF.w());
2472         glClear(GL_COLOR_BUFFER_BIT);
2473 
2474         EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex]);
2475     }
2476 
2477     // Iterate the faces again to make sure the colors haven't changed.
2478     for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
2479     {
2480         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2481                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
2482         EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex])
2483             << "face color " << faceIndex << " shouldn't change";
2484     }
2485 }
2486 
2487 // Tests clearing a cube map with a scissor enabled.
TEST_P(TextureCubeTest,CubeMapFBOScissoredClear)2488 TEST_P(TextureCubeTest, CubeMapFBOScissoredClear)
2489 {
2490     // http://anglebug.com/3145
2491     ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
2492 
2493     constexpr size_t kSize = 16;
2494 
2495     GLFramebuffer fbo;
2496     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2497     glViewport(0, 0, kSize, kSize);
2498 
2499     GLTexture texcube;
2500     glBindTexture(GL_TEXTURE_CUBE_MAP, texcube);
2501     for (GLenum face = 0; face < 6; face++)
2502     {
2503         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
2504                      GL_UNSIGNED_BYTE, nullptr);
2505     }
2506     ASSERT_GL_NO_ERROR();
2507 
2508     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
2509                            texcube, 0);
2510 
2511     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2512     ASSERT_GL_NO_ERROR();
2513 
2514     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2515     glClear(GL_COLOR_BUFFER_BIT);
2516     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2517 
2518     glEnable(GL_SCISSOR_TEST);
2519     glScissor(kSize / 2, 0, kSize / 2, kSize);
2520     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2521     glClear(GL_COLOR_BUFFER_BIT);
2522 
2523     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2524     EXPECT_PIXEL_COLOR_EQ(kSize / 2 + 1, 0, GLColor::green);
2525 
2526     ASSERT_GL_NO_ERROR();
2527 }
2528 
2529 // Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
2530 // default color.
TEST_P(Texture2DTest,TexStorage)2531 TEST_P(Texture2DTest, TexStorage)
2532 {
2533     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
2534                        !IsGLExtensionEnabled("GL_EXT_texture_storage"));
2535 
2536     int width  = getWindowWidth();
2537     int height = getWindowHeight();
2538 
2539     GLTexture tex2D;
2540     glActiveTexture(GL_TEXTURE0);
2541     glBindTexture(GL_TEXTURE_2D, tex2D);
2542 
2543     // Fill with red
2544     std::vector<GLubyte> pixels(3 * 16 * 16);
2545     for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2546     {
2547         pixels[pixelId * 3 + 0] = 255;
2548         pixels[pixelId * 3 + 1] = 0;
2549         pixels[pixelId * 3 + 2] = 0;
2550     }
2551 
2552     // ANGLE internally uses RGBA as the DirectX format for RGB images
2553     // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent
2554     // alpha color. The data is kept in a CPU-side image and the image is marked as dirty.
2555     if (getClientMajorVersion() >= 3)
2556     {
2557         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2558     }
2559     else
2560     {
2561         glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2562     }
2563 
2564     // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2565     // glTexSubImage2D should take into account that the image is dirty.
2566     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
2567     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2568     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2569 
2570     setUpProgram();
2571 
2572     glUseProgram(mProgram);
2573     glUniform1i(mTexture2DUniformLocation, 0);
2574     drawQuad(mProgram, "position", 0.5f);
2575     EXPECT_GL_NO_ERROR();
2576     EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2577 
2578     // Validate that the region of the texture without data has an alpha of 1.0
2579     angle::GLColor pixel = ReadColor(3 * width / 4, 3 * height / 4);
2580     EXPECT_EQ(255, pixel.A);
2581 }
2582 
2583 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2584 // initialized the image with a default color.
TEST_P(Texture2DTest,TexStorageWithPBO)2585 TEST_P(Texture2DTest, TexStorageWithPBO)
2586 {
2587     if (getClientMajorVersion() < 3)
2588     {
2589         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2590         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2591     }
2592 
2593     const int width          = getWindowWidth();
2594     const int height         = getWindowHeight();
2595     const size_t pixelCount  = width * height;
2596     const int componentCount = 3;
2597 
2598     GLTexture tex2D;
2599     glActiveTexture(GL_TEXTURE0);
2600     glBindTexture(GL_TEXTURE_2D, tex2D);
2601 
2602     // Fill with red
2603     std::vector<GLubyte> pixels(componentCount * pixelCount);
2604     for (size_t pixelId = 0; pixelId < pixelCount; ++pixelId)
2605     {
2606         pixels[pixelId * componentCount + 0] = 255;
2607         pixels[pixelId * componentCount + 1] = 0;
2608         pixels[pixelId * componentCount + 2] = 0;
2609     }
2610 
2611     // Read 16x16 region from red backbuffer to PBO
2612     GLuint pbo;
2613     glGenBuffers(1, &pbo);
2614     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2615     glBufferData(GL_PIXEL_UNPACK_BUFFER, componentCount * pixelCount, pixels.data(),
2616                  GL_STATIC_DRAW);
2617 
2618     // ANGLE internally uses RGBA as the DirectX format for RGB images
2619     // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent
2620     // alpha color. The data is kept in a CPU-side image and the image is marked as dirty.
2621     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, width, height);
2622 
2623     // Initializes the color of the upper-left quadrant of pixels, leaves the other pixels
2624     // untouched. glTexSubImage2D should take into account that the image is dirty.
2625     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RGB, GL_UNSIGNED_BYTE,
2626                     nullptr);
2627     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2628     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2629 
2630     setUpProgram();
2631 
2632     glUseProgram(mProgram);
2633     glUniform1i(mTexture2DUniformLocation, 0);
2634     drawQuad(mProgram, "position", 0.5f);
2635     glDeleteBuffers(1, &pbo);
2636     EXPECT_GL_NO_ERROR();
2637     EXPECT_PIXEL_RECT_EQ(0, 0, width / 2, height / 2, GLColor(255, 0, 0, 255));
2638 }
2639 
2640 // Test that glTexSubImage2D combined with a PBO works properly after deleting the PBO
2641 // and drawing with the texture
2642 // Pseudo code for the follow test:
2643 // 1. Upload PBO to mTexture2D
2644 // 2. Delete PBO
2645 // 3. Draw with otherTexture (x5)
2646 // 4. Draw with mTexture2D
2647 // 5. Validate color output
TEST_P(Texture2DTest,PBOWithMultipleDraws)2648 TEST_P(Texture2DTest, PBOWithMultipleDraws)
2649 {
2650     if (getClientMajorVersion() < 3)
2651     {
2652         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2653         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2654     }
2655 
2656     const GLuint width            = getWindowWidth();
2657     const GLuint height           = getWindowHeight();
2658     const GLuint windowPixelCount = width * height;
2659     std::vector<GLColor> pixelsRed(windowPixelCount, GLColor::red);
2660     std::vector<GLColor> pixelsGreen(windowPixelCount, GLColor::green);
2661 
2662     // Create secondary draw that does not use mTexture
2663     const char *vertexShaderSource   = getVertexShaderSource();
2664     const char *fragmentShaderSource = getFragmentShaderSource();
2665     ANGLE_GL_PROGRAM(otherProgram, vertexShaderSource, fragmentShaderSource);
2666 
2667     GLint uniformLoc = glGetUniformLocation(otherProgram, getTextureUniformName());
2668     ASSERT_NE(-1, uniformLoc);
2669     glUseProgram(0);
2670 
2671     // Create secondary Texture to draw with
2672     GLTexture otherTexture;
2673     glActiveTexture(GL_TEXTURE0);
2674     glBindTexture(GL_TEXTURE_2D, otherTexture);
2675     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2676     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
2677                     pixelsRed.data());
2678     ASSERT_GL_NO_ERROR();
2679 
2680     // Setup primary Texture
2681     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2682     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2683     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2684     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2685     ASSERT_GL_NO_ERROR();
2686 
2687     // Setup PBO
2688     GLuint pbo = 0;
2689     glGenBuffers(1, &pbo);
2690     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2691     glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
2692                  GL_STATIC_DRAW);
2693     ASSERT_GL_NO_ERROR();
2694 
2695     // Write PBO to mTexture
2696     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2697     ASSERT_GL_NO_ERROR();
2698     // Delete PBO as ANGLE should be properly handling refcount of this buffer
2699     glDeleteBuffers(1, &pbo);
2700     pixelsGreen.clear();
2701 
2702     // Do 5 draws not involving primary texture that the PBO updated
2703     glUseProgram(otherProgram);
2704     glUniform1i(uniformLoc, 0);
2705     glBindTexture(GL_TEXTURE_2D, otherTexture);
2706     drawQuad(otherProgram, "position", 0.5f);
2707     glBindTexture(GL_TEXTURE_2D, 0);
2708     glUseProgram(0);
2709 
2710     glUseProgram(otherProgram);
2711     glUniform1i(uniformLoc, 0);
2712     glBindTexture(GL_TEXTURE_2D, otherTexture);
2713     drawQuad(otherProgram, "position", 0.5f);
2714     glBindTexture(GL_TEXTURE_2D, 0);
2715     glUseProgram(0);
2716 
2717     glUseProgram(otherProgram);
2718     glUniform1i(uniformLoc, 0);
2719     glBindTexture(GL_TEXTURE_2D, otherTexture);
2720     drawQuad(otherProgram, "position", 0.5f);
2721     glBindTexture(GL_TEXTURE_2D, 0);
2722     glUseProgram(0);
2723 
2724     glUseProgram(otherProgram);
2725     glUniform1i(uniformLoc, 0);
2726     glBindTexture(GL_TEXTURE_2D, otherTexture);
2727     drawQuad(otherProgram, "position", 0.5f);
2728     glBindTexture(GL_TEXTURE_2D, 0);
2729     glUseProgram(0);
2730     ASSERT_GL_NO_ERROR();
2731 
2732     std::vector<GLColor> output(windowPixelCount, GLColor::black);
2733     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2734                  output.data());
2735     EXPECT_EQ(pixelsRed, output);
2736 
2737     setUpProgram();
2738     // Draw using PBO updated texture
2739     glUseProgram(mProgram);
2740     glUniform1i(mTexture2DUniformLocation, 0);
2741     glBindTexture(GL_TEXTURE_2D, mTexture2D);
2742     drawQuad(mProgram, "position", 0.5f);
2743     ASSERT_GL_NO_ERROR();
2744 
2745     std::vector<GLColor> actual(windowPixelCount, GLColor::black);
2746     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2747                  actual.data());
2748     // Value should be green as it was updated during PBO transfer to mTexture
2749     std::vector<GLColor> expected(windowPixelCount, GLColor::green);
2750     EXPECT_EQ(expected, actual);
2751 }
2752 
2753 // Test that stencil texture uploads work.
TEST_P(Texture2DTestES3,TexImageWithStencilData)2754 TEST_P(Texture2DTestES3, TexImageWithStencilData)
2755 {
2756     constexpr GLsizei kSize = 4;
2757 
2758     const std::array<std::tuple<GLenum, GLenum, int, int>, 3> testConfigs = {
2759         std::make_tuple(GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, 4),
2760         std::make_tuple(GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, 4, 0),
2761         std::make_tuple(GL_STENCIL_INDEX8, GL_UNSIGNED_BYTE, 1, 0)};
2762 
2763     for (auto testConfig : testConfigs)
2764     {
2765         const GLenum format     = std::get<0>(testConfig);
2766         const GLenum type       = std::get<1>(testConfig);
2767         const GLenum typeLength = std::get<2>(testConfig);
2768         const GLenum typeOffset = std::get<3>(testConfig);
2769 
2770         ANGLE_SKIP_TEST_IF(format == GL_STENCIL_INDEX8 &&
2771                            !IsGLExtensionEnabled("GL_OES_texture_stencil8"));
2772 
2773         // Set up the framebuffer
2774         GLTexture colorTexture;
2775         glBindTexture(GL_TEXTURE_2D, colorTexture);
2776         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2777                      nullptr);
2778         ASSERT_GL_NO_ERROR();
2779 
2780         GLTexture depthStencilTexture;
2781         glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
2782 
2783         GLubyte pixels[kSize * kSize * 8] = {};
2784         for (size_t pixelId = 0; pixelId < kSize * kSize; ++pixelId)
2785         {
2786             pixels[pixelId * typeLength + typeOffset] = 0xD5;
2787         }
2788         glTexImage2D(GL_TEXTURE_2D, 0, format, kSize, kSize, 0,
2789                      format == GL_STENCIL_INDEX8 ? GL_STENCIL_INDEX : GL_DEPTH_STENCIL, type,
2790                      pixels);
2791         ASSERT_GL_NO_ERROR();
2792 
2793         GLFramebuffer fbo;
2794         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2795         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
2796                                0);
2797         glFramebufferTexture2D(
2798             GL_FRAMEBUFFER,
2799             format == GL_STENCIL_INDEX8 ? GL_STENCIL_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT,
2800             GL_TEXTURE_2D, depthStencilTexture, 0);
2801         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2802         ASSERT_GL_NO_ERROR();
2803 
2804         // Clear only color.
2805         glClearColor(0, 0, 0, 1);
2806         glClear(GL_COLOR_BUFFER_BIT);
2807         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
2808 
2809         // If stencil is not set to 0xD5, rendering would fail.
2810         glEnable(GL_STENCIL_TEST);
2811         glStencilFunc(GL_EQUAL, 0xD5, 0xFF);
2812         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2813         glStencilMask(0xFF);
2814 
2815         // Draw red
2816         ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2817         drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f);
2818         ASSERT_GL_NO_ERROR();
2819 
2820         EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
2821     }
2822 }
2823 
2824 // Test that glTexSubImage2D combined with a PBO works properly. PBO has all pixels as red
2825 // except the middle one being green.
TEST_P(Texture2DTest,TexStorageWithPBOMiddlePixelDifferent)2826 TEST_P(Texture2DTest, TexStorageWithPBOMiddlePixelDifferent)
2827 {
2828     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2829     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2830 
2831     int width  = getWindowWidth();
2832     int height = getWindowHeight();
2833 
2834     GLTexture tex2D;
2835     glActiveTexture(GL_TEXTURE0);
2836     glBindTexture(GL_TEXTURE_2D, tex2D);
2837 
2838     std::vector<GLubyte> pixels(3 * 16 * 16);
2839 
2840     // Initialize texture with default black color.
2841     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2842     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
2843 
2844     // Fill PBO's data with red, with middle one as green
2845     for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2846     {
2847         if (pixelId == 8 * 7 + 7)
2848         {
2849             pixels[pixelId * 3 + 0] = 0;
2850             pixels[pixelId * 3 + 1] = 255;
2851             pixels[pixelId * 3 + 2] = 0;
2852         }
2853         else
2854         {
2855             pixels[pixelId * 3 + 0] = 255;
2856             pixels[pixelId * 3 + 1] = 0;
2857             pixels[pixelId * 3 + 2] = 0;
2858         }
2859     }
2860 
2861     GLuint pbo;
2862     glGenBuffers(1, &pbo);
2863     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2864     glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
2865 
2866     // Update the color of the texture's upper-left 8x8 pixels, leaves the other pixels untouched.
2867     // glTexSubImage2D should take into account that the image is dirty.
2868     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
2869     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2870     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2871 
2872     setUpProgram();
2873 
2874     glUseProgram(mProgram);
2875     glUniform1i(mTexture2DUniformLocation, 0);
2876     drawQuad(mProgram, "position", 0.5f);
2877     glDeleteBuffers(1, &pbo);
2878     EXPECT_GL_NO_ERROR();
2879     EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
2880     EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2881     EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
2882 }
2883 
2884 // Test that glTexSubImage2D combined with a PBO works properly when glTexImage2D has
2885 // initialized the image with a luminance color
TEST_P(Texture2DTest,TexImageWithLuminancePBO)2886 TEST_P(Texture2DTest, TexImageWithLuminancePBO)
2887 {
2888     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2889 
2890     int width  = getWindowWidth();
2891     int height = getWindowHeight();
2892 
2893     GLTexture tex2D;
2894     glActiveTexture(GL_TEXTURE0);
2895     glBindTexture(GL_TEXTURE_2D, tex2D);
2896 
2897     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 16, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
2898                  nullptr);
2899 
2900     // Fill PBO with white, with middle one as grey
2901     std::vector<GLubyte> pixels(16 * 16);
2902     for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2903     {
2904         if (pixelId == 8 * 7 + 7)
2905         {
2906             pixels[pixelId] = 128;
2907         }
2908         else
2909         {
2910             pixels[pixelId] = 255;
2911         }
2912     }
2913 
2914     GLuint pbo;
2915     glGenBuffers(1, &pbo);
2916     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2917     glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16, pixels.data(), GL_STATIC_DRAW);
2918 
2919     // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2920     // glTexSubImage2D should take into account that the image is dirty.
2921     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
2922     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2923     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2924 
2925     setUpProgram();
2926 
2927     glUseProgram(mProgram);
2928     glUniform1i(mTexture2DUniformLocation, 0);
2929     drawQuad(mProgram, "position", 0.5f);
2930     glDeleteBuffers(1, &pbo);
2931     EXPECT_GL_NO_ERROR();
2932     EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 255, 255, 255);
2933     EXPECT_PIXEL_NEAR(width / 2 - 1, height / 2 - 1, 128, 128, 128, 255, 1);
2934 }
2935 
2936 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2937 // initialized the image with a RGB656 color
TEST_P(Texture2DTest,TexImageWithRGB565PBO)2938 TEST_P(Texture2DTest, TexImageWithRGB565PBO)
2939 {
2940     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2941     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2942 
2943     int width  = getWindowWidth();
2944     int height = getWindowHeight();
2945 
2946     GLTexture tex2D;
2947     glActiveTexture(GL_TEXTURE0);
2948     glBindTexture(GL_TEXTURE_2D, tex2D);
2949 
2950     // Fill PBO with red, with middle one as green
2951     std::vector<GLushort> pixels(16 * 16);
2952     for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2953     {
2954         if (pixelId == 8 * 7 + 8)
2955         {
2956             pixels[pixelId] = 0x7E0;
2957         }
2958         else
2959         {
2960             pixels[pixelId] = 0xF800;
2961         }
2962     }
2963 
2964     GLuint pbo;
2965     glGenBuffers(1, &pbo);
2966     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2967     glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
2968 
2969     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB565, 16, 16);
2970 
2971     // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2972     // glTexSubImage2D should take into account that the image is dirty.
2973     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
2974                     reinterpret_cast<void *>(2));
2975     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2976     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2977 
2978     setUpProgram();
2979 
2980     glUseProgram(mProgram);
2981     glUniform1i(mTexture2DUniformLocation, 0);
2982     drawQuad(mProgram, "position", 0.5f);
2983     glDeleteBuffers(1, &pbo);
2984     EXPECT_GL_NO_ERROR();
2985     EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2986     EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
2987 }
2988 
2989 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2990 // initialized the image with a RGBA4444 color
TEST_P(Texture2DTest,TexImageWithRGBA4444PBO)2991 TEST_P(Texture2DTest, TexImageWithRGBA4444PBO)
2992 {
2993     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2994     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2995 
2996     int width  = getWindowWidth();
2997     int height = getWindowHeight();
2998 
2999     GLTexture tex2D;
3000     glActiveTexture(GL_TEXTURE0);
3001     glBindTexture(GL_TEXTURE_2D, tex2D);
3002 
3003     // Fill PBO with red, with middle one as green
3004     std::vector<GLushort> pixels(16 * 16);
3005     for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
3006     {
3007         if (pixelId == 8 * 7 + 8)
3008         {
3009             pixels[pixelId] = 0xF0F;
3010         }
3011         else
3012         {
3013             pixels[pixelId] = 0xF00F;
3014         }
3015     }
3016 
3017     GLuint pbo;
3018     glGenBuffers(1, &pbo);
3019     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3020     glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
3021 
3022     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA4, 16, 16);
3023 
3024     // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
3025     // glTexSubImage2D should take into account that the image is dirty.
3026     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
3027                     reinterpret_cast<void *>(2));
3028     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3029     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3030 
3031     setUpProgram();
3032 
3033     glUseProgram(mProgram);
3034     glUniform1i(mTexture2DUniformLocation, 0);
3035     drawQuad(mProgram, "position", 0.5f);
3036     glDeleteBuffers(1, &pbo);
3037     EXPECT_GL_NO_ERROR();
3038     EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
3039     EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
3040 }
3041 
3042 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
3043 // initialized the image with a RGBA5551 color
TEST_P(Texture2DTest,TexImageWithRGBA5551PBO)3044 TEST_P(Texture2DTest, TexImageWithRGBA5551PBO)
3045 {
3046     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3047     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3048 
3049     int width  = getWindowWidth();
3050     int height = getWindowHeight();
3051 
3052     GLTexture tex2D;
3053     glActiveTexture(GL_TEXTURE0);
3054     glBindTexture(GL_TEXTURE_2D, tex2D);
3055 
3056     // Fill PBO with red, with middle one as green
3057     std::vector<GLushort> pixels(16 * 16);
3058     for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
3059     {
3060         if (pixelId == 8 * 7 + 7)
3061         {
3062             pixels[pixelId] = 0x7C1;
3063         }
3064         else
3065         {
3066             pixels[pixelId] = 0xF801;
3067         }
3068     }
3069 
3070     GLuint pbo;
3071     glGenBuffers(1, &pbo);
3072     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3073     glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
3074 
3075     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB5_A1, 16, 16);
3076 
3077     // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
3078     // glTexSubImage2D should take into account that the image is dirty.
3079     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, nullptr);
3080     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3081     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3082 
3083     setUpProgram();
3084 
3085     glUseProgram(mProgram);
3086     glUniform1i(mTexture2DUniformLocation, 0);
3087     drawQuad(mProgram, "position", 0.5f);
3088     glDeleteBuffers(1, &pbo);
3089     EXPECT_GL_NO_ERROR();
3090     EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
3091     EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
3092 }
3093 
3094 // Test that glTexSubImage2D from a PBO respects GL_UNPACK_ROW_LENGTH.
TEST_P(Texture2DTest,TexImageUnpackRowLengthPBO)3095 TEST_P(Texture2DTest, TexImageUnpackRowLengthPBO)
3096 {
3097     if (getClientMajorVersion() < 3)
3098     {
3099         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3100         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3101         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_unpack_subimage"));
3102     }
3103 
3104     const int width      = getWindowWidth() / 2;
3105     const int height     = getWindowHeight();
3106     const int rowLength  = getWindowWidth();
3107     const int bufferSize = rowLength * height;
3108 
3109     GLTexture tex2D;
3110     glActiveTexture(GL_TEXTURE0);
3111     glBindTexture(GL_TEXTURE_2D, tex2D);
3112 
3113     std::vector<GLColor> pixels(bufferSize);
3114     for (int y = 0; y < rowLength; ++y)
3115     {
3116         for (int x = 0; x < width; ++x)
3117         {
3118             pixels[y * rowLength + x] =
3119                 x < width ? (y < height / 2 ? GLColor::green : GLColor::blue) : GLColor::red;
3120         }
3121     }
3122 
3123     GLuint pbo;
3124     glGenBuffers(1, &pbo);
3125     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3126     glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize * sizeof(GLColor), pixels.data(),
3127                  GL_STATIC_DRAW);
3128 
3129     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
3130 
3131     // Initializes the texture from width x height of the PBO.
3132     glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength);
3133     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3134     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3135     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3136 
3137     setUpProgram();
3138 
3139     glUseProgram(mProgram);
3140     glUniform1i(mTexture2DUniformLocation, 0);
3141     drawQuad(mProgram, "position", 0.5f);
3142     glDeleteBuffers(1, &pbo);
3143     EXPECT_GL_NO_ERROR();
3144     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3145     EXPECT_PIXEL_COLOR_EQ(0, height - 1, GLColor::blue);
3146 }
3147 
3148 // Test if the KHR debug label is set and passed to D3D correctly using glCopyTexImage2D.
TEST_P(Texture2DTest,TextureKHRDebugLabelWithCopyTexImage2D)3149 TEST_P(Texture2DTest, TextureKHRDebugLabelWithCopyTexImage2D)
3150 {
3151     GLTexture texture2D;
3152     glBindTexture(GL_TEXTURE_2D, texture2D);
3153 
3154     // Create a texture and copy into, to initialize storage object.
3155     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 32, 32, 0);
3156 
3157     // Set KHR Debug Label.
3158     std::string label = "TestKHR.DebugLabel";
3159     glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3160 
3161     std::vector<char> labelBuf(label.length() + 1);
3162     GLsizei labelLengthBuf = 0;
3163 
3164     glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3165                         &labelLengthBuf, labelBuf.data());
3166 
3167     EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
3168     EXPECT_STREQ(label.c_str(), labelBuf.data());
3169 
3170     // Delete the texture.
3171     texture2D.reset();
3172     EXPECT_GL_NO_ERROR();
3173 
3174     glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3175     EXPECT_GL_ERROR(GL_INVALID_VALUE);
3176 
3177     glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3178                         &labelLengthBuf, labelBuf.data());
3179     EXPECT_GL_ERROR(GL_INVALID_VALUE);
3180 }
3181 
3182 // Test to call labeling API before the storage texture is created.
TEST_P(Texture2DTest,CallKHRDebugLabelBeforeTexStorageCreation)3183 TEST_P(Texture2DTest, CallKHRDebugLabelBeforeTexStorageCreation)
3184 {
3185     GLTexture texture2D;
3186     glBindTexture(GL_TEXTURE_2D, texture2D);
3187 
3188     // Set label before texture storage creation.
3189     std::string label = "TestKHR.DebugLabel";
3190     glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3191 
3192     // Create a texture and copy into, to initialize storage object.
3193     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 32, 32, 0);
3194 
3195     std::vector<char> labelBuf(label.length() + 1);
3196     GLsizei labelLengthBuf = 0;
3197 
3198     glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3199                         &labelLengthBuf, labelBuf.data());
3200 
3201     EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
3202     EXPECT_STREQ(label.c_str(), labelBuf.data());
3203 
3204     // Delete the texture.
3205     texture2D.reset();
3206     EXPECT_GL_NO_ERROR();
3207 
3208     glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3209     EXPECT_GL_ERROR(GL_INVALID_VALUE);
3210 
3211     glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3212                         &labelLengthBuf, labelBuf.data());
3213     EXPECT_GL_ERROR(GL_INVALID_VALUE);
3214 }
3215 
3216 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3217 // initialized the image with a depth-only format.
TEST_P(Texture2DTestES3,TexImageWithDepthPBO)3218 TEST_P(Texture2DTestES3, TexImageWithDepthPBO)
3219 {
3220     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3221     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3222 
3223     // http://anglebug.com/5315
3224     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3225 
3226     constexpr GLsizei kSize = 4;
3227 
3228     // Set up the framebuffer.
3229     GLTexture colorTexture;
3230     glBindTexture(GL_TEXTURE_2D, colorTexture);
3231     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3232     ASSERT_GL_NO_ERROR();
3233 
3234     GLTexture depthTexture;
3235     glBindTexture(GL_TEXTURE_2D, depthTexture);
3236     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, kSize, kSize);
3237     ASSERT_GL_NO_ERROR();
3238 
3239     GLFramebuffer fbo;
3240     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3241     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3242     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
3243     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3244     ASSERT_GL_NO_ERROR();
3245 
3246     // Clear depth to 0, ensuring the texture's image is allocated.
3247     glClearDepthf(0);
3248     glClearColor(0, 0, 0, 1);
3249     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3250     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3251 
3252     // Fill depth with 1.0f.
3253     std::vector<GLushort> pixels(kSize * kSize);
3254     for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3255     {
3256         pixels[pixelId] = 0xFFFF;
3257     }
3258 
3259     GLuint pbo;
3260     glGenBuffers(1, &pbo);
3261     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3262     glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3263                  GL_STATIC_DRAW);
3264     ASSERT_GL_NO_ERROR();
3265 
3266     // Upload PBO data.
3267     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
3268                     nullptr);
3269 
3270     // If depth is not set to 1, rendering would fail.
3271     glEnable(GL_DEPTH_TEST);
3272     glDepthFunc(GL_LESS);
3273 
3274     // Draw red
3275     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3276     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3277     ASSERT_GL_NO_ERROR();
3278 
3279     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3280 }
3281 
3282 // Test sampling modes with a DEPTH_COMPONENT16 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth16)3283 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth16)
3284 {
3285     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, false);
3286     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX, false);
3287 }
3288 
3289 // Test sampling modes with a swizzled DEPTH_COMPONENT16 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth16Swizzled)3290 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth16Swizzled)
3291 {
3292     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, true);
3293     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX, true);
3294 }
3295 
3296 // Test sampling modes with a DEPTH_COMPONENT24 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24)3297 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24)
3298 {
3299     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, false);
3300     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_STENCIL_INDEX, false);
3301 }
3302 
3303 // Test sampling modes with a swizzled DEPTH_COMPONENT24 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Swizzled)3304 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Swizzled)
3305 {
3306     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, true);
3307     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_STENCIL_INDEX, true);
3308 }
3309 
3310 // Test depth sampling with a DEPTH_COMPONENT32F texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32f)3311 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32f)
3312 {
3313     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, false);
3314     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_STENCIL_INDEX, false);
3315 }
3316 
3317 // Test depth sampling with a swizzled DEPTH_COMPONENT32F texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fSwizzled)3318 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fSwizzled)
3319 {
3320     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, true);
3321     TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_STENCIL_INDEX, true);
3322 }
3323 
3324 // Test sampling modes with a DEPTH24_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Stencil8)3325 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Stencil8)
3326 {
3327     TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT, false);
3328     TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX, false);
3329 }
3330 
3331 // Test sampling modes with a swizzled DEPTH24_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Stencil8Swizzled)3332 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Stencil8Swizzled)
3333 {
3334     TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT, true);
3335     TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX, true);
3336 }
3337 
3338 // Test sampling modes with a DEPTH32F_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fStencil8)3339 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fStencil8)
3340 {
3341     TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT, false);
3342     TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_STENCIL_INDEX, false);
3343 }
3344 
3345 // Test sampling modes with a swizzled DEPTH32F_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fStencil8Swizzled)3346 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fStencil8Swizzled)
3347 {
3348     TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT, true);
3349     TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_STENCIL_INDEX, true);
3350 }
3351 
3352 // Test sampling modes with a STENCIL_INDEX8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithStencil8)3353 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithStencil8)
3354 {
3355     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_stencil8"));
3356     TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_DEPTH_COMPONENT, false);
3357     TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, false);
3358 }
3359 
3360 // Test sampling modes with a swizzled STENCIL_INDEX8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithStencil8Swizzled)3361 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithStencil8Swizzled)
3362 {
3363     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_stencil8"));
3364     TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_DEPTH_COMPONENT, true);
3365     TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, true);
3366 }
3367 
3368 // Test that updating a texture format triggers depth/stencil mode resync.
TEST_P(Texture2DDepthStencilTestES3,Redefinition)3369 TEST_P(Texture2DDepthStencilTestES3, Redefinition)
3370 {
3371     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_stencil_texturing"));
3372 
3373     constexpr char kDepthFS[] =
3374         R"(#version 300 es
3375 precision mediump float;
3376 uniform highp sampler2D tex;
3377 out vec4 color;
3378 void main()
3379 {
3380     color = texture(tex, vec2(0, 0));
3381 })";
3382     ANGLE_GL_PROGRAM(programDepth, essl3_shaders::vs::Simple(), kDepthFS);
3383 
3384     constexpr char kStencilFS[] =
3385         R"(#version 300 es
3386 precision mediump float;
3387 uniform highp usampler2D tex;
3388 out vec4 color;
3389 void main()
3390 {
3391     color = vec4(texelFetch(tex, ivec2(0, 0), 0)) / 255.0;
3392 })";
3393     ANGLE_GL_PROGRAM(programStencil, essl3_shaders::vs::Simple(), kStencilFS);
3394 
3395     // Set up a D32F with stencil mode.
3396     GLTexture texture;
3397     glBindTexture(GL_TEXTURE_2D, texture);
3398     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3399     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3400     glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, GL_STENCIL_INDEX);
3401 
3402     const GLfloat d32f = 0.5f;
3403     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
3404                  &d32f);
3405     ASSERT_GL_NO_ERROR();
3406 
3407     drawQuad(programDepth, essl3_shaders::PositionAttrib(), 0.5f);
3408     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
3409 
3410     // Redefine the same texture as D24S8
3411     const GLuint d24s8 = 0xC0;
3412     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 1, 1, 0, GL_DEPTH_STENCIL,
3413                  GL_UNSIGNED_INT_24_8, &d24s8);
3414     ASSERT_GL_NO_ERROR();
3415 
3416     drawQuad(programStencil, essl3_shaders::PositionAttrib(), 0.5f);
3417     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(192, 0, 0, 1), 1);
3418 
3419     // Redefine the same texture as D16
3420     const GLushort d16 = 0x4000;
3421     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 1, 1, 0, GL_DEPTH_COMPONENT,
3422                  GL_UNSIGNED_SHORT, &d16);
3423     ASSERT_GL_NO_ERROR();
3424 
3425     drawQuad(programDepth, essl3_shaders::PositionAttrib(), 0.5f);
3426     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(64, 0, 0, 255), 1);
3427 }
3428 
3429 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3430 // initialized the image with a stencil-only format.
TEST_P(Texture2DTestES3,TexImageWithStencilPBO)3431 TEST_P(Texture2DTestES3, TexImageWithStencilPBO)
3432 {
3433     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3434     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3435 
3436     // http://anglebug.com/5315
3437     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3438 
3439     constexpr GLsizei kSize = 4;
3440 
3441     // Set up the framebuffer.
3442     GLTexture colorTexture;
3443     glBindTexture(GL_TEXTURE_2D, colorTexture);
3444     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3445     ASSERT_GL_NO_ERROR();
3446 
3447     GLTexture stencilTexture;
3448     glBindTexture(GL_TEXTURE_2D, stencilTexture);
3449     glTexStorage2D(GL_TEXTURE_2D, 1, GL_STENCIL_INDEX8, kSize, kSize);
3450     ASSERT_GL_NO_ERROR();
3451 
3452     GLFramebuffer fbo;
3453     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3454     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3455     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, stencilTexture, 0);
3456     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3457     ASSERT_GL_NO_ERROR();
3458 
3459     // Clear stencil to 0, ensuring the texture's image is allocated.
3460     glClearStencil(0);
3461     glClearColor(0, 0, 0, 1);
3462     glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3463     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3464 
3465     // Fill stencil with 0x4E
3466     std::vector<GLubyte> pixels(kSize * kSize);
3467     for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3468     {
3469         pixels[pixelId] = 0x4E;
3470     }
3471 
3472     GLuint pbo;
3473     glGenBuffers(1, &pbo);
3474     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3475     glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3476                  GL_STATIC_DRAW);
3477     ASSERT_GL_NO_ERROR();
3478 
3479     // Upload PBO data.
3480     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
3481                     nullptr);
3482     ASSERT_GL_NO_ERROR();
3483 
3484     // If stencil is not set to 0x4E, rendering would fail.
3485     glEnable(GL_STENCIL_TEST);
3486     glStencilFunc(GL_EQUAL, 0x4E, 0xFF);
3487     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3488     glStencilMask(0xFF);
3489 
3490     // Draw red
3491     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3492     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3493     ASSERT_GL_NO_ERROR();
3494 
3495     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3496 }
3497 
3498 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3499 // initialized the image with a depth/stencil format.
TEST_P(Texture2DTestES3,TexImageWithDepthStencilPBO)3500 TEST_P(Texture2DTestES3, TexImageWithDepthStencilPBO)
3501 {
3502     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3503     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3504 
3505     // http://anglebug.com/5315
3506     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3507 
3508     constexpr GLsizei kSize = 4;
3509 
3510     // Set up the framebuffer.
3511     GLTexture colorTexture;
3512     glBindTexture(GL_TEXTURE_2D, colorTexture);
3513     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3514     ASSERT_GL_NO_ERROR();
3515 
3516     GLTexture depthStencilTexture;
3517     glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
3518     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
3519     ASSERT_GL_NO_ERROR();
3520 
3521     GLFramebuffer fbo;
3522     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3523     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3524     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
3525                            depthStencilTexture, 0);
3526     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3527     ASSERT_GL_NO_ERROR();
3528 
3529     // Clear depth and stencil to 0, ensuring the texture's image is allocated.
3530     glClearDepthf(0);
3531     glClearStencil(0);
3532     glClearColor(0, 0, 0, 1);
3533     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3534     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3535 
3536     // Fill depth with 1.0f and stencil with 0xD5
3537     std::vector<GLuint> pixels(kSize * kSize);
3538     for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3539     {
3540         pixels[pixelId] = 0xFFFFFFD5;
3541     }
3542 
3543     GLuint pbo;
3544     glGenBuffers(1, &pbo);
3545     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3546     glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3547                  GL_STATIC_DRAW);
3548     ASSERT_GL_NO_ERROR();
3549 
3550     // Upload PBO data.
3551     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8,
3552                     nullptr);
3553 
3554     // If depth is not set to 1, rendering would fail.
3555     glEnable(GL_DEPTH_TEST);
3556     glDepthFunc(GL_LESS);
3557 
3558     // If stencil is not set to 0xD5, rendering would fail.
3559     glEnable(GL_STENCIL_TEST);
3560     glStencilFunc(GL_EQUAL, 0xD5, 0xFF);
3561     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3562     glStencilMask(0xFF);
3563 
3564     // Draw red
3565     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3566     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3567     ASSERT_GL_NO_ERROR();
3568 
3569     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3570 }
3571 
3572 // Test that the driver performs a flush when there is a large amount of image updates.
TEST_P(Texture2DMemoryTestES3,TextureDataInLoopUntilFlush)3573 TEST_P(Texture2DMemoryTestES3, TextureDataInLoopUntilFlush)
3574 {
3575     // Run this test for Vulkan only.
3576     ANGLE_SKIP_TEST_IF(!IsVulkan());
3577 
3578     // If VK_EXT_host_image_copy is used, uploads will all be done on the CPU and there would be no
3579     // submissions.
3580     ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::SupportsHostImageCopy));
3581 
3582     uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1;
3583 
3584     // Set up program
3585     const char *kFS = R"(#version 300 es
3586 precision highp float;
3587 uniform uni { vec4 color; };
3588 out vec4 fragColor;
3589 void main()
3590 {
3591     fragColor = color;
3592 })";
3593     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3594     ASSERT_NE(program, 0u);
3595 
3596     // Set up the uniform buffer and framebuffer
3597     GLint uniformBufferIndex;
3598     uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
3599     ASSERT_NE(uniformBufferIndex, -1);
3600 
3601     glClear(GL_COLOR_BUFFER_BIT);
3602     constexpr size_t kBufferSize = 4 * 1024 * 1024;
3603     std::vector<float> floatData;
3604     floatData.resize(kBufferSize / (sizeof(float)), 0.0f);
3605     floatData[0] = 0.5f;
3606     floatData[1] = 0.75f;
3607     floatData[2] = 0.25f;
3608     floatData[3] = 1.0f;
3609 
3610     GLBuffer uniformBuffer;
3611     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
3612     glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW);
3613     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
3614     glUniformBlockBinding(program, uniformBufferIndex, 0);
3615 
3616     GLFramebuffer fbo;
3617     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3618 
3619     // Create textures and draw
3620     constexpr uint32_t kTextureWidth  = 512;
3621     constexpr uint32_t kTextureHeight = 512;
3622     std::vector<GLColor> textureColor(kTextureWidth * kTextureHeight, GLColor::red);
3623     constexpr uint32_t kIterationCount = 4096;
3624     GLTexture textures[kIterationCount];
3625 
3626     for (auto &texture : textures)
3627     {
3628         glBindTexture(GL_TEXTURE_2D, texture);
3629         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureWidth, kTextureHeight);
3630         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RGBA,
3631                         GL_UNSIGNED_BYTE, textureColor.data());
3632 
3633         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3634         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3635         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3636 
3637         if (getPerfCounters().commandQueueSubmitCallsTotal == expectedSubmitCalls)
3638         {
3639             break;
3640         }
3641     }
3642     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls);
3643     ASSERT_GL_NO_ERROR();
3644     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
3645 }
3646 
3647 // Creating a texture and drawing with it in a loop without glFlush() should still work. Driver is
3648 // supposedly to issue flush if needed. There should be no fallbacks to allocate outside the device
3649 // memory.
TEST_P(Texture2DMemoryTestES3,TextureDataInLoopManyTimes)3650 TEST_P(Texture2DMemoryTestES3, TextureDataInLoopManyTimes)
3651 {
3652     // Run this test for Vulkan only.
3653     ANGLE_SKIP_TEST_IF(!IsVulkan());
3654     uint64_t expectedSubmitCalls           = getPerfCounters().commandQueueSubmitCallsTotal + 1;
3655     uint64_t expectedDeviceMemoryFallbacks = getPerfCounters().deviceMemoryImageAllocationFallbacks;
3656 
3657     // Set up program
3658     const char *kFS = R"(#version 300 es
3659 precision highp float;
3660 uniform uni { vec4 color; };
3661 out vec4 fragColor;
3662 void main()
3663 {
3664     fragColor = color;
3665 })";
3666     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3667     ASSERT_NE(program, 0u);
3668 
3669     // Set up the uniform buffer and framebuffer
3670     GLint uniformBufferIndex;
3671     uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
3672     ASSERT_NE(uniformBufferIndex, -1);
3673 
3674     glClear(GL_COLOR_BUFFER_BIT);
3675     constexpr size_t kBufferSize = 4 * 1024 * 1024;
3676     std::vector<float> floatData;
3677     floatData.resize(kBufferSize / (sizeof(float)), 0.0f);
3678     floatData[0] = 0.5f;
3679     floatData[1] = 0.75f;
3680     floatData[2] = 0.25f;
3681     floatData[3] = 1.0f;
3682 
3683     GLBuffer uniformBuffer;
3684     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
3685     glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW);
3686     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
3687     glUniformBlockBinding(program, uniformBufferIndex, 0);
3688 
3689     GLFramebuffer fbo;
3690     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3691 
3692     // Create textures and draw. We will use very small image updates to prevent flush before the
3693     // device runs out of memory.
3694     constexpr uint32_t kTextureWidth  = 4096;
3695     constexpr uint32_t kTextureHeight = 4096;
3696     std::vector<GLColor> textureColor(kTextureWidth * kTextureHeight, GLColor::red);
3697     constexpr uint32_t kIterationCount = 4096;
3698 
3699     for (uint32_t i = 0; i < kIterationCount; i++)
3700     {
3701         GLTexture texture;
3702         glBindTexture(GL_TEXTURE_2D, texture);
3703         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0, GL_RGBA,
3704                      GL_UNSIGNED_BYTE, nullptr);
3705         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
3706                         textureColor.data());
3707 
3708         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3709         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3710         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3711 
3712         if (getPerfCounters().commandQueueSubmitCallsTotal == expectedSubmitCalls)
3713         {
3714             break;
3715         }
3716     }
3717     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls);
3718     EXPECT_EQ(getPerfCounters().deviceMemoryImageAllocationFallbacks,
3719               expectedDeviceMemoryFallbacks);
3720     ASSERT_GL_NO_ERROR();
3721 }
3722 
3723 // Test functionality of GL_ANGLE_yuv_internal_format with min/mag filters
3724 // set to nearest and linear modes.
TEST_P(Texture2DTestES3YUV,TexStorage2DYuvFilterModes)3725 TEST_P(Texture2DTestES3YUV, TexStorage2DYuvFilterModes)
3726 {
3727     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3728 
3729     // Create YUV texture
3730     GLTexture yuvTexture;
3731     GLubyte yuvColor[]         = {40, 40, 40, 40, 40, 40, 40, 40, 240, 109, 240, 109};
3732     GLubyte expectedRgbColor[] = {0, 0, 255, 255};
3733     createImmutableTexture2D(yuvTexture, 2, 4, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3734                              GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3735 
3736     // Default is nearest filter mode
3737     verifyResults2D(yuvTexture, expectedRgbColor);
3738     ASSERT_GL_NO_ERROR();
3739 
3740     // Enable linear filter mode
3741     glBindTexture(GL_TEXTURE_2D, yuvTexture);
3742     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3743     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3744     verifyResults2D(yuvTexture, expectedRgbColor);
3745     ASSERT_GL_NO_ERROR();
3746 
3747     const int windowHeight = getWindowHeight();
3748     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::blue, 1);
3749     EXPECT_PIXEL_COLOR_NEAR(0, windowHeight - 1, GLColor::blue, 1);
3750     EXPECT_PIXEL_COLOR_NEAR(0, windowHeight / 2, GLColor::blue, 1);
3751 }
3752 
3753 // Test functionality of GL_ANGLE_yuv_internal_format while cycling through RGB and YUV sources
TEST_P(Texture2DTestES3,TexStorage2DCycleThroughYuvAndRgbSources)3754 TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvAndRgbSources)
3755 {
3756     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3757 
3758     // Create YUV texture
3759     GLTexture yuvTexture;
3760     GLubyte yuvColor[6]         = {40, 40, 40, 40, 240, 109};
3761     GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
3762     createImmutableTexture2D(yuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3763                              GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3764 
3765     // Create RGBA texture
3766     GLTexture rgbaTexture;
3767     GLubyte rgbaColor[4] = {0, 0, 255, 255};
3768     createImmutableTexture2D(rgbaTexture, 1, 1, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, 1, rgbaColor);
3769 
3770     // Cycle through source textures
3771     // RGBA source
3772     verifyResults2D(rgbaTexture, rgbaColor);
3773     ASSERT_GL_NO_ERROR();
3774 
3775     // YUV source
3776     verifyResults2D(yuvTexture, expectedRgbColor);
3777     ASSERT_GL_NO_ERROR();
3778 
3779     // RGBA source
3780     verifyResults2D(rgbaTexture, rgbaColor);
3781     ASSERT_GL_NO_ERROR();
3782 }
3783 
3784 // Test functionality of GL_ANGLE_yuv_internal_format with large number of YUV sources
TEST_P(Texture2DTestES3,TexStorage2DLargeYuvTextureCount)3785 TEST_P(Texture2DTestES3, TexStorage2DLargeYuvTextureCount)
3786 {
3787     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3788 
3789     constexpr uint32_t kTextureCount = 16;
3790 
3791     // Create YUV texture
3792     GLTexture yuvTexture[kTextureCount];
3793     for (uint32_t i = 0; i < kTextureCount; i++)
3794     {
3795         // Create 2 plane YCbCr 420 texture
3796         createImmutableTexture2D(yuvTexture[i], 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3797                                  GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3798     }
3799 
3800     // Cycle through YUV source textures
3801     glUseProgram(mProgram);
3802     glUniform1i(mTexture2DUniformLocation, 0);
3803 
3804     for (uint32_t i = 0; i < kTextureCount; i++)
3805     {
3806         glBindTexture(GL_TEXTURE_2D, yuvTexture[i]);
3807         drawQuad(mProgram, "position", 0.5f);
3808         ASSERT_GL_NO_ERROR();
3809     }
3810 }
3811 
3812 // Test functionality of GL_ANGLE_yuv_internal_format with simultaneous use of multiple YUV sources
TEST_P(Texture2DTestES3,TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData)3813 TEST_P(Texture2DTestES3, TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData)
3814 {
3815     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3816 
3817     // Create YUV texture
3818     // Create 2 plane YCbCr 420 texture
3819     GLTexture twoPlaneYuvTexture;
3820     createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3821                              GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3822 
3823     // Create 3 plane YCbCr 420 texture
3824     GLTexture threePlaneYuvTexture;
3825     createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
3826                              GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3827 
3828     // Cycle through YUV source textures
3829     // Create program with 2 samplers
3830     const char *vertexShaderSource   = getVertexShaderSource();
3831     const char *fragmentShaderSource = R"(#version 300 es
3832 precision highp float;
3833 uniform sampler2D tex0;
3834 uniform sampler2D tex1;
3835 in vec2 texcoord;
3836 out vec4 fragColor;
3837 
3838 void main()
3839 {
3840     vec4 color0 = texture(tex0, texcoord);
3841     vec4 color1 = texture(tex1, texcoord);
3842     fragColor = color0 + color1;
3843 })";
3844 
3845     ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
3846     glUseProgram(twoSamplersProgram);
3847     GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
3848     ASSERT_NE(-1, tex0Location);
3849     GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
3850     ASSERT_NE(-1, tex1Location);
3851 
3852     glUniform1i(tex0Location, 0);
3853     glUniform1i(tex1Location, 1);
3854 
3855     // Bind 2 plane YUV source
3856     glActiveTexture(GL_TEXTURE0);
3857     glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3858     ASSERT_GL_NO_ERROR();
3859 
3860     // Bind 3 plane YUV source
3861     glActiveTexture(GL_TEXTURE1);
3862     glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3863     ASSERT_GL_NO_ERROR();
3864 
3865     drawQuad(twoSamplersProgram, "position", 0.5f);
3866     ASSERT_GL_NO_ERROR();
3867 
3868     // Switch active texture index and draw again
3869     // Bind 2 plane YUV source
3870     glActiveTexture(GL_TEXTURE1);
3871     glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3872     ASSERT_GL_NO_ERROR();
3873 
3874     // Bind 3 plane YUV source
3875     glActiveTexture(GL_TEXTURE0);
3876     glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3877     ASSERT_GL_NO_ERROR();
3878 
3879     drawQuad(twoSamplersProgram, "position", 0.5f);
3880     ASSERT_GL_NO_ERROR();
3881 }
3882 
3883 // Test functional of GL_ANGLE_yuv_internal_format while cycling through YUV sources
TEST_P(Texture2DTestES3,TexStorage2DCycleThroughYuvSourcesNoData)3884 TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvSourcesNoData)
3885 {
3886     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3887 
3888     // Create YUV texture
3889     // Create 2 plane YCbCr 420 texture
3890     GLTexture twoPlaneYuvTexture;
3891     createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3892                              GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3893 
3894     // Create 3 plane YCbCr 420 texture
3895     GLTexture threePlaneYuvTexture;
3896     createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
3897                              GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3898 
3899     // Cycle through YUV source textures
3900     glUseProgram(mProgram);
3901     glUniform1i(mTexture2DUniformLocation, 0);
3902 
3903     // 2 plane YUV source
3904     glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3905     drawQuad(mProgram, "position", 0.5f);
3906     ASSERT_GL_NO_ERROR();
3907 
3908     // 3 plane YUV source
3909     glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3910     drawQuad(mProgram, "position", 0.5f);
3911     ASSERT_GL_NO_ERROR();
3912 
3913     // 2 plane YUV source
3914     glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3915     drawQuad(mProgram, "position", 0.5f);
3916     ASSERT_GL_NO_ERROR();
3917 }
3918 
3919 // Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while
3920 // switching sampler uniform values.
TEST_P(Texture2DTestES3,TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues)3921 TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues)
3922 {
3923     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3924 
3925     // Create YUV texture
3926     GLTexture yuvTexture;
3927     GLubyte yuvColor[6]         = {40, 40, 40, 40, 240, 109};
3928     GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
3929 
3930     // Create YUV texture
3931     // Create 2 plane YCbCr 420 texture
3932     GLTexture twoPlaneYuvTexture;
3933     createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3934                              GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3935     // Create 3 plane YCbCr 420 texture
3936     GLTexture threePlaneYuvTexture;
3937     createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
3938                              GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3939     // Create program with 2 samplers
3940     const char *vertexShaderSource   = getVertexShaderSource();
3941     const char *fragmentShaderSource = R"(#version 300 es
3942 precision highp float;
3943 uniform sampler2D tex0;
3944 uniform sampler2D tex1;
3945 uniform int texIndex;
3946 in vec2 texcoord;
3947 out vec4 fragColor;
3948 void main()
3949 {
3950     vec4 color0 = texture(tex0, texcoord);
3951     vec4 color1 = texture(tex1, texcoord);
3952     if (texIndex == 0)
3953     {
3954         fragColor = color0;
3955     }
3956     else
3957     {
3958         fragColor = color1;
3959     }
3960 })";
3961     ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
3962     glUseProgram(twoSamplersProgram);
3963     GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
3964     ASSERT_NE(-1, tex0Location);
3965     GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
3966     ASSERT_NE(-1, tex1Location);
3967     GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex");
3968     ASSERT_NE(-1, texIndexLocation);
3969     // Bind 2 plane YUV source
3970     glActiveTexture(GL_TEXTURE0);
3971     glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3972     ASSERT_GL_NO_ERROR();
3973     // Bind 3 plane YUV source
3974     glActiveTexture(GL_TEXTURE1);
3975     glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3976     ASSERT_GL_NO_ERROR();
3977 
3978     // Set sampler uniform values and draw
3979     glUniform1i(tex0Location, 0);
3980     glUniform1i(tex1Location, 1);
3981     // Set texture index selector to the 2 plane texture unit
3982     glUniform1i(texIndexLocation, 0);
3983     drawQuad(twoSamplersProgram, "position", 0.5f);
3984     ASSERT_GL_NO_ERROR();
3985     EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
3986                       expectedRgbColor[3], 1);
3987     ASSERT_GL_NO_ERROR();
3988 
3989     // Switch sampler uniform values and draw
3990     glUniform1i(tex0Location, 1);
3991     glUniform1i(tex1Location, 0);
3992     // Set texture index selector to the 2 plane texture unit
3993     glUniform1i(texIndexLocation, 1);
3994     drawQuad(twoSamplersProgram, "position", 0.5f);
3995     ASSERT_GL_NO_ERROR();
3996     EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
3997                       expectedRgbColor[3], 1);
3998     ASSERT_GL_NO_ERROR();
3999 
4000     // Switch back sampler uniform values and draw
4001     glUniform1i(tex0Location, 0);
4002     glUniform1i(tex1Location, 1);
4003     // Set texture index selector to the 2 plane texture unit
4004     glUniform1i(texIndexLocation, 0);
4005     drawQuad(twoSamplersProgram, "position", 0.5f);
4006     ASSERT_GL_NO_ERROR();
4007     EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4008                       expectedRgbColor[3], 1);
4009     ASSERT_GL_NO_ERROR();
4010 }
4011 
4012 // Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while
4013 // switching bound textures.
TEST_P(Texture2DTestES3,TexStorage2DMultipleYuvSamplersSwitchBoundTextures)4014 TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchBoundTextures)
4015 {
4016     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
4017 
4018     // Create YUV texture
4019     GLTexture yuvTexture;
4020     GLubyte yuvColor[6]         = {40, 40, 40, 40, 240, 109};
4021     GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
4022 
4023     // Create YUV texture
4024     // Create 2 plane YCbCr 420 texture
4025     GLTexture twoPlaneYuvTexture;
4026     createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
4027                              GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
4028     // Create 3 plane YCbCr 420 texture
4029     GLTexture threePlaneYuvTexture;
4030     createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
4031                              GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
4032     // Create program with 2 samplers
4033     const char *vertexShaderSource   = getVertexShaderSource();
4034     const char *fragmentShaderSource = R"(#version 300 es
4035 precision highp float;
4036 uniform sampler2D tex0;
4037 uniform sampler2D tex1;
4038 uniform int texIndex;
4039 in vec2 texcoord;
4040 out vec4 fragColor;
4041 void main()
4042 {
4043     vec4 color0 = texture(tex0, texcoord);
4044     vec4 color1 = texture(tex1, texcoord);
4045     if (texIndex == 0)
4046     {
4047         fragColor = color0;
4048     }
4049     else
4050     {
4051         fragColor = color1;
4052     }
4053 })";
4054     ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
4055     glUseProgram(twoSamplersProgram);
4056     GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
4057     ASSERT_NE(-1, tex0Location);
4058     GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
4059     ASSERT_NE(-1, tex1Location);
4060     GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex");
4061     ASSERT_NE(-1, texIndexLocation);
4062     // Set sampler uniform values
4063     glUniform1i(tex0Location, 0);
4064     glUniform1i(tex1Location, 1);
4065 
4066     // Bind 2 plane YUV source
4067     glActiveTexture(GL_TEXTURE0);
4068     glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4069     ASSERT_GL_NO_ERROR();
4070     // Bind 3 plane YUV source
4071     glActiveTexture(GL_TEXTURE1);
4072     glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4073     ASSERT_GL_NO_ERROR();
4074     // Set texture index selector to the 2 plane texture unit
4075     glUniform1i(texIndexLocation, 0);
4076     // Draw
4077     drawQuad(twoSamplersProgram, "position", 0.5f);
4078     ASSERT_GL_NO_ERROR();
4079     EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4080                       expectedRgbColor[3], 1);
4081     ASSERT_GL_NO_ERROR();
4082 
4083     // Bind 3 plane YUV source
4084     glActiveTexture(GL_TEXTURE0);
4085     glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4086     ASSERT_GL_NO_ERROR();
4087     // Bind 2 plane YUV source
4088     glActiveTexture(GL_TEXTURE1);
4089     glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4090     ASSERT_GL_NO_ERROR();
4091     // Set texture index selector to the 2 plane texture unit
4092     glUniform1i(texIndexLocation, 1);
4093     // Draw
4094     drawQuad(twoSamplersProgram, "position", 0.5f);
4095     ASSERT_GL_NO_ERROR();
4096     EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4097                       expectedRgbColor[3], 1);
4098     ASSERT_GL_NO_ERROR();
4099 }
4100 
4101 // Tests CopySubImage for float formats
TEST_P(Texture2DTest,CopySubImageFloat_R_R)4102 TEST_P(Texture2DTest, CopySubImageFloat_R_R)
4103 {
4104     testFloatCopySubImage(1, 1);
4105 }
4106 
TEST_P(Texture2DTest,CopySubImageFloat_RG_R)4107 TEST_P(Texture2DTest, CopySubImageFloat_RG_R)
4108 {
4109     testFloatCopySubImage(2, 1);
4110 }
4111 
TEST_P(Texture2DTest,CopySubImageFloat_RG_RG)4112 TEST_P(Texture2DTest, CopySubImageFloat_RG_RG)
4113 {
4114     testFloatCopySubImage(2, 2);
4115 }
4116 
TEST_P(Texture2DTest,CopySubImageFloat_RGB_R)4117 TEST_P(Texture2DTest, CopySubImageFloat_RGB_R)
4118 {
4119     testFloatCopySubImage(3, 1);
4120 }
4121 
TEST_P(Texture2DTest,CopySubImageFloat_RGB_RG)4122 TEST_P(Texture2DTest, CopySubImageFloat_RGB_RG)
4123 {
4124     testFloatCopySubImage(3, 2);
4125 }
4126 
TEST_P(Texture2DTest,CopySubImageFloat_RGB_RGB)4127 TEST_P(Texture2DTest, CopySubImageFloat_RGB_RGB)
4128 {
4129     // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/1346)
4130     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4131 
4132     testFloatCopySubImage(3, 3);
4133 }
4134 
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_R)4135 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_R)
4136 {
4137     testFloatCopySubImage(4, 1);
4138 }
4139 
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RG)4140 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RG)
4141 {
4142     testFloatCopySubImage(4, 2);
4143 }
4144 
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RGB)4145 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGB)
4146 {
4147     testFloatCopySubImage(4, 3);
4148 }
4149 
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RGBA)4150 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGBA)
4151 {
4152     testFloatCopySubImage(4, 4);
4153 }
4154 
4155 // Port of
4156 // https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html
4157 // Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly
4158 // handles GL_ALPHA
TEST_P(Texture2DTest,TextureNPOT_GL_ALPHA_UBYTE)4159 TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE)
4160 {
4161     const int npotTexSize = 5;
4162     const int potTexSize  = 4;  // Should be less than npotTexSize
4163     GLTexture tex2D;
4164 
4165     if (IsGLExtensionEnabled("GL_OES_texture_npot"))
4166     {
4167         // This test isn't applicable if texture_npot is enabled
4168         return;
4169     }
4170 
4171     setUpProgram();
4172 
4173     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4174 
4175     // Default unpack alignment is 4. The values of 'pixels' below needs it to be 1.
4176     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4177 
4178     glActiveTexture(GL_TEXTURE0);
4179     glBindTexture(GL_TEXTURE_2D, tex2D);
4180 
4181     const std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize, 64);
4182 
4183     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4184     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4185 
4186     // Check that an NPOT texture not on level 0 generates INVALID_VALUE
4187     glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA,
4188                  GL_UNSIGNED_BYTE, pixels.data());
4189     EXPECT_GL_ERROR(GL_INVALID_VALUE);
4190 
4191     // Check that an NPOT texture on level 0 succeeds
4192     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA,
4193                  GL_UNSIGNED_BYTE, pixels.data());
4194     EXPECT_GL_NO_ERROR();
4195 
4196     // Check that generateMipmap fails on NPOT
4197     glGenerateMipmap(GL_TEXTURE_2D);
4198     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4199 
4200     // Check that nothing is drawn if filtering is not correct for NPOT
4201     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4202     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4203     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
4204     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
4205     glClear(GL_COLOR_BUFFER_BIT);
4206     drawQuad(mProgram, "position", 1.0f);
4207     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
4208 
4209     // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
4210     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4211     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4212     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
4213     glClear(GL_COLOR_BUFFER_BIT);
4214     drawQuad(mProgram, "position", 1.0f);
4215     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
4216 
4217     // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw
4218     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4219     glClear(GL_COLOR_BUFFER_BIT);
4220     drawQuad(mProgram, "position", 1.0f);
4221     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
4222 
4223     // Check that glTexImage2D for POT texture succeeds
4224     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
4225                  pixels.data());
4226     EXPECT_GL_NO_ERROR();
4227 
4228     // Check that generateMipmap for an POT texture succeeds
4229     glGenerateMipmap(GL_TEXTURE_2D);
4230     EXPECT_GL_NO_ERROR();
4231 
4232     // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw
4233     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
4234     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4235     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
4236     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
4237     glClear(GL_COLOR_BUFFER_BIT);
4238     drawQuad(mProgram, "position", 1.0f);
4239     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
4240     EXPECT_GL_NO_ERROR();
4241 }
4242 
4243 // Test to ensure that glTexSubImage2D always accepts data for non-power-of-two subregions.
4244 // ANGLE previously rejected this if GL_OES_texture_npot wasn't active, which is incorrect.
TEST_P(Texture2DTest,NPOTSubImageParameters)4245 TEST_P(Texture2DTest, NPOTSubImageParameters)
4246 {
4247     glActiveTexture(GL_TEXTURE0);
4248     glBindTexture(GL_TEXTURE_2D, mTexture2D);
4249 
4250     // Create an 8x8 (i.e. power-of-two) texture.
4251     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4252     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4253     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4254     glGenerateMipmap(GL_TEXTURE_2D);
4255 
4256     // Supply a 3x3 (i.e. non-power-of-two) subimage to the texture.
4257     // This should always work, even if GL_OES_texture_npot isn't active.
4258     std::array<GLColor, 3 * 3> data;
4259     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
4260 
4261     EXPECT_GL_NO_ERROR();
4262 }
4263 
4264 // Regression test for https://crbug.com/1222516 to prevent integer overflow during validation.
TEST_P(Texture2DTest,SubImageValidationOverflow)4265 TEST_P(Texture2DTest, SubImageValidationOverflow)
4266 {
4267     glActiveTexture(GL_TEXTURE0);
4268     glBindTexture(GL_TEXTURE_2D, mTexture2D);
4269 
4270     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4271     EXPECT_GL_NO_ERROR();
4272 
4273     glTexSubImage2D(GL_TEXTURE_2D, 0, -4, 0, 2147483647, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4274     EXPECT_GL_ERROR(GL_INVALID_VALUE);
4275 
4276     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, -4, 1, 2147483647, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4277     EXPECT_GL_ERROR(GL_INVALID_VALUE);
4278 }
4279 
4280 // Test that when a mutable texture is deleted, its corresponding pointer in the Vulkan backend,
4281 // which is used for mutable texture flushing, is also deleted, and is not accessed by the new
4282 // mutable texture after it.
TEST_P(Texture2DTest,MutableUploadThenDeleteThenMutableUpload)4283 TEST_P(Texture2DTest, MutableUploadThenDeleteThenMutableUpload)
4284 {
4285     GLTexture texture1;
4286     glBindTexture(GL_TEXTURE_2D, texture1);
4287     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4288                  GLColor::red.data());
4289     texture1.reset();
4290     EXPECT_GL_NO_ERROR();
4291 
4292     GLTexture texture2;
4293     glBindTexture(GL_TEXTURE_2D, texture2);
4294     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4295                  GLColor::green.data());
4296     texture2.reset();
4297     EXPECT_GL_NO_ERROR();
4298 }
4299 
4300 // Test to ensure that glTexStorage3D accepts ASTC sliced 3D. https://crbug.com/1060012
TEST_P(Texture3DTestES3,ImmutableASTCSliced3D)4301 TEST_P(Texture3DTestES3, ImmutableASTCSliced3D)
4302 {
4303     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_texture_compression_astc_sliced_3d"));
4304 
4305     glBindTexture(GL_TEXTURE_3D, mTexture3D);
4306     glTexStorage3D(GL_TEXTURE_3D, 1, GL_COMPRESSED_RGBA_ASTC_4x4, 4, 4, 1);
4307     EXPECT_GL_NO_ERROR();
4308 }
4309 
FillLevel(GLint level,GLuint width,GLuint height,const GLColor & color,bool cubemap,bool subTex)4310 void FillLevel(GLint level,
4311                GLuint width,
4312                GLuint height,
4313                const GLColor &color,
4314                bool cubemap,
4315                bool subTex)
4316 {
4317     std::vector<GLColor> pixels(width * height, color);
4318     std::vector<GLenum> targets;
4319     if (cubemap)
4320     {
4321         targets = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
4322                    GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
4323                    GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
4324     }
4325     else
4326     {
4327         targets = {GL_TEXTURE_2D};
4328     }
4329 
4330     for (GLenum target : targets)
4331     {
4332         if (subTex)
4333         {
4334             glTexSubImage2D(target, level, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
4335                             pixels.data());
4336         }
4337         else
4338         {
4339             glTexImage2D(target, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4340                          pixels.data());
4341         }
4342     }
4343 }
4344 
4345 // This is part of tests that webgl_conformance_vulkan_passthrough_tests
4346 // conformance/textures/misc/texture-size.html does
testTextureSize(int testCaseIndex)4347 void Texture2DTest::testTextureSize(int testCaseIndex)
4348 {
4349     std::array<GLColor, 6> kNewMipColors = {
4350         GLColor::green,  GLColor::red,     GLColor::blue,
4351         GLColor::yellow, GLColor::magenta, GLColor::cyan,
4352     };
4353     GLuint colorCount = 0;
4354 
4355     setUpProgram();
4356 
4357     constexpr char kVS[] =
4358         R"(precision highp float;
4359 attribute vec4 position;
4360 varying vec3 texcoord;
4361 void main()
4362 {
4363     gl_Position = position;
4364     texcoord = (position.xyz * 0.5) + 0.5;
4365 }
4366 )";
4367     constexpr char kFS[] =
4368         R"(precision mediump float;
4369 uniform samplerCube tex;
4370 varying vec3 texcoord;
4371 void main()
4372 {
4373     gl_FragColor = textureCube(tex, texcoord);
4374 })";
4375     ANGLE_GL_PROGRAM(programCubeMap, kVS, kFS);
4376     GLint textureCubeUniformLocation = glGetUniformLocation(programCubeMap, "tex");
4377     ASSERT_NE(-1, textureCubeUniformLocation);
4378     ASSERT_GL_NO_ERROR();
4379 
4380     GLint max2DSize = 0;
4381     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize);
4382     GLint maxCubeMapSize = 0;
4383     glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapSize);
4384     // Assuming 2048x2048xRGBA (22 mb with mips) will run on all WebGL platforms
4385     GLint max2DSquareSize = std::min(max2DSize, 2048);
4386     // I'd prefer this to be 2048 but that's 16 mb x 6 faces or 128 mb (with mips)
4387     // 1024 is 33.5 mb (with mips)
4388     maxCubeMapSize = std::min(maxCubeMapSize, 1024);
4389     ASSERT_GL_NO_ERROR();
4390 
4391     for (GLint size = 1; size <= max2DSize; size *= 2)
4392     {
4393         bool cubeMap     = testCaseIndex == 3;
4394         GLenum texTarget = cubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
4395         GLuint program   = cubeMap ? programCubeMap : mProgram;
4396         GLint texWidth = 0, texHeight = 0;
4397 
4398         switch (testCaseIndex)
4399         {
4400             case 0:
4401                 texWidth  = size;
4402                 texHeight = 1;
4403                 break;
4404             case 1:
4405                 texWidth  = 1;
4406                 texHeight = size;
4407                 break;
4408             case 2:
4409             case 3:
4410                 texWidth  = size;
4411                 texHeight = size;
4412                 break;
4413         }
4414 
4415         if (texWidth == texHeight && size > max2DSquareSize)
4416         {
4417             return;
4418         }
4419 
4420         if (cubeMap && size > maxCubeMapSize)
4421         {
4422             return;
4423         }
4424 
4425         GLTexture texture;
4426         glActiveTexture(GL_TEXTURE0);
4427         glBindTexture(texTarget, texture);
4428         FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false);
4429         glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4430         glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4431         glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4432         glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4433         ASSERT_GL_NO_ERROR();
4434 
4435         glClear(GL_COLOR_BUFFER_BIT);
4436         ASSERT_GL_NO_ERROR();
4437 
4438         glUseProgram(program);
4439         if (cubeMap)
4440         {
4441             glUniform1i(textureCubeUniformLocation, 0);
4442         }
4443         else
4444         {
4445             glUniform1i(mTexture2DUniformLocation, 0);
4446         }
4447 
4448         drawQuad(program, "position", 1.0f);
4449         ASSERT_GL_NO_ERROR();
4450         EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
4451 
4452         colorCount = (colorCount + 1) % kNewMipColors.size();
4453         FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false);
4454         glGenerateMipmap(texTarget);
4455         ASSERT_GL_NO_ERROR();
4456 
4457         glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4458         glClear(GL_COLOR_BUFFER_BIT);
4459         drawQuad(program, "position", 1.0f);
4460         ASSERT_GL_NO_ERROR();
4461         EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
4462 
4463         colorCount = (colorCount + 1) % kNewMipColors.size();
4464         FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, true);
4465         glGenerateMipmap(texTarget);
4466 
4467         glClear(GL_COLOR_BUFFER_BIT);
4468         drawQuad(program, "position", 1.0f);
4469         ASSERT_GL_NO_ERROR();
4470         EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
4471     }
4472 }
4473 
testTextureSizeError()4474 void Texture2DTest::testTextureSizeError()
4475 {
4476     GLint max2DSize = 0;
4477     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize);
4478     glActiveTexture(GL_TEXTURE0);
4479     GLTexture texture;
4480     glBindTexture(GL_TEXTURE_2D, texture);
4481     FillLevel(0, max2DSize, max2DSize, GLColor::red, false, false);
4482     GLenum err  = glGetError();
4483     bool passed = (err == GL_NO_ERROR || err == GL_OUT_OF_MEMORY);
4484     ASSERT_TRUE(passed);
4485 }
4486 
4487 // Permutation 0 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase0)4488 TEST_P(Texture2DTest, TextureSizeCase0)
4489 {
4490     testTextureSize(0);
4491 }
4492 
4493 // Permutation 1 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase1)4494 TEST_P(Texture2DTest, TextureSizeCase1)
4495 {
4496     testTextureSize(1);
4497 }
4498 
4499 // Permutation 2 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase2)4500 TEST_P(Texture2DTest, TextureSizeCase2)
4501 {
4502     testTextureSize(2);
4503 }
4504 
4505 // Permutation 3 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase3)4506 TEST_P(Texture2DTest, TextureSizeCase3)
4507 {
4508     testTextureSize(3);
4509 }
4510 
4511 // Test allocating a very large texture
TEST_P(Texture2DTest,TextureMaxSize)4512 TEST_P(Texture2DTest, TextureMaxSize)
4513 {
4514     testTextureSizeError();
4515 }
4516 
4517 // Test that drawing works correctly RGBA 3D texture
TEST_P(Texture3DTestES2,RGBA)4518 TEST_P(Texture3DTestES2, RGBA)
4519 {
4520     ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4521 
4522     // http://anglebug.com/5728
4523     ANGLE_SKIP_TEST_IF(IsOzone());
4524 
4525     glActiveTexture(GL_TEXTURE0);
4526     glBindTexture(GL_TEXTURE_3D, mTexture3D);
4527     std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
4528     std::vector<GLColor> texDataRed(1u * 1u * 1u, GLColor::red);
4529     glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4530                     texDataGreen.data());
4531     glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4532                     texDataRed.data());
4533     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4534     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4535 
4536     EXPECT_GL_NO_ERROR();
4537 
4538     drawQuad(mProgram, "position", 0.5f);
4539 
4540     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4541 }
4542 
4543 // Test that drawing works correctly Luminance 3D texture
TEST_P(Texture3DTestES2,Luminance)4544 TEST_P(Texture3DTestES2, Luminance)
4545 {
4546     ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4547 
4548     // http://anglebug.com/5728
4549     ANGLE_SKIP_TEST_IF(IsOzone());
4550 
4551     glActiveTexture(GL_TEXTURE0);
4552     glBindTexture(GL_TEXTURE_3D, mTexture3D);
4553     std::vector<GLubyte> texData(2u * 2u * 2u, 125);
4554     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4555     glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4556                     texData.data());
4557     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4558     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4559 
4560     EXPECT_GL_NO_ERROR();
4561 
4562     drawQuad(mProgram, "position", 0.5f);
4563 
4564     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(125, 125, 125, 255));
4565 }
4566 
4567 // Test that drawing works correctly with glCopyTexSubImage3D
TEST_P(Texture3DTestES2,CopySubImageRGBA)4568 TEST_P(Texture3DTestES2, CopySubImageRGBA)
4569 {
4570     ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4571 
4572     // http://anglebug.com/5728
4573     ANGLE_SKIP_TEST_IF(IsOzone());
4574 
4575     glClearColor(0, 0, 1, 1);
4576     glClear(GL_COLOR_BUFFER_BIT);
4577 
4578     glActiveTexture(GL_TEXTURE0);
4579     glBindTexture(GL_TEXTURE_3D, mTexture3D);
4580     std::vector<GLColor> texDataRed(4u * 4u * 4u, GLColor::red);
4581     glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4582                     texDataRed.data());
4583     glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4584                     texDataRed.data());
4585     glTexImage3DOES(GL_TEXTURE_3D, 2, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4586                     texDataRed.data());
4587     glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4588     glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4589     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4590     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4591 
4592     EXPECT_GL_NO_ERROR();
4593 
4594     glClearColor(0, 1, 0, 1);
4595     glClear(GL_COLOR_BUFFER_BIT);
4596     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4597 
4598     glUseProgram(mProgram);
4599     glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4600     drawQuad(mProgram, "position", 0.5f);
4601 
4602     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4603 }
4604 
TEST_P(Texture3DTestES2,CopySubImageLuminance)4605 TEST_P(Texture3DTestES2, CopySubImageLuminance)
4606 {
4607     ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4608 
4609     // http://anglebug.com/5728
4610     ANGLE_SKIP_TEST_IF(IsOzone());
4611 
4612     glClearColor(1, 0, 0, 1);
4613     glClear(GL_COLOR_BUFFER_BIT);
4614 
4615     glActiveTexture(GL_TEXTURE0);
4616     glBindTexture(GL_TEXTURE_3D, mTexture3D);
4617     glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 4, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4618                     nullptr);
4619     glTexImage3DOES(GL_TEXTURE_3D, 1, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4620                     nullptr);
4621     glTexImage3DOES(GL_TEXTURE_3D, 2, GL_LUMINANCE, 1, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4622                     nullptr);
4623     glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4624     glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4625     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4626     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4627 
4628     EXPECT_GL_NO_ERROR();
4629 
4630     glClearColor(0, 1, 0, 1);
4631     glClear(GL_COLOR_BUFFER_BIT);
4632     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4633 
4634     glUseProgram(mProgram);
4635     glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4636     drawQuad(mProgram, "position", 0.5f);
4637 
4638     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
4639 }
4640 
TEST_P(Texture3DTestES2,CopySubImageAlpha)4641 TEST_P(Texture3DTestES2, CopySubImageAlpha)
4642 {
4643     ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4644 
4645     // http://anglebug.com/5728
4646     ANGLE_SKIP_TEST_IF(IsOzone());
4647 
4648     glClearColor(1, 0, 0, 0.5);
4649     glClear(GL_COLOR_BUFFER_BIT);
4650 
4651     glActiveTexture(GL_TEXTURE0);
4652     glBindTexture(GL_TEXTURE_3D, mTexture3D);
4653     glTexImage3DOES(GL_TEXTURE_3D, 0, GL_ALPHA, 4, 4, 4, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4654     glTexImage3DOES(GL_TEXTURE_3D, 1, GL_ALPHA, 2, 2, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4655     glTexImage3DOES(GL_TEXTURE_3D, 2, GL_ALPHA, 1, 1, 1, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4656     glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4657     glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4658     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4659     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4660 
4661     EXPECT_GL_NO_ERROR();
4662 
4663     glClearColor(0, 1, 0, 1);
4664     glClear(GL_COLOR_BUFFER_BIT);
4665     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4666 
4667     glUseProgram(mProgram);
4668     glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4669     drawQuad(mProgram, "position", 0.5f);
4670 
4671     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 128), 1.0);
4672 }
4673 
4674 // Test that defining a 2D texture array fails with Texture3DOES on ES2.
TEST_P(Texture3DTestES2,DefineTexture2DArrayShouldFail)4675 TEST_P(Texture3DTestES2, DefineTexture2DArrayShouldFail)
4676 {
4677     ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4678 
4679     // http://anglebug.com/5728
4680     ANGLE_SKIP_TEST_IF(IsOzone());
4681 
4682     glClearColor(1, 0, 0, 1);
4683     glClear(GL_COLOR_BUFFER_BIT);
4684 
4685     glActiveTexture(GL_TEXTURE0);
4686     glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
4687     EXPECT_GL_ERROR(GL_INVALID_ENUM);
4688 
4689     glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4690                     nullptr);
4691     glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4692                     nullptr);
4693     glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4694                     nullptr);
4695     EXPECT_GL_ERROR(GL_INVALID_ENUM);
4696 }
4697 
4698 // Verify shrinking a texture with glTexStorage2D works correctly
TEST_P(Texture2DTestES3,ChangeTexSizeWithTexStorage)4699 TEST_P(Texture2DTestES3, ChangeTexSizeWithTexStorage)
4700 {
4701     // TODO: http://anglebug.com/5256
4702     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL());
4703 
4704     constexpr uint32_t kSizeLarge = 128;
4705     constexpr uint32_t kSizeSmall = 64;
4706 
4707     glActiveTexture(GL_TEXTURE0);
4708     glBindTexture(GL_TEXTURE_2D, mTexture2D);
4709     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4710     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4711 
4712     // Create the texture with 'large' dimensions
4713     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4714                  nullptr);
4715     ASSERT_GL_NO_ERROR();
4716 
4717     GLFramebuffer destFbo;
4718     glBindFramebuffer(GL_FRAMEBUFFER, destFbo);
4719     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0);
4720     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4721 
4722     // Draw with the new texture so it's created in the back end
4723     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
4724     glUseProgram(blueProgram);
4725     drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
4726     ASSERT_GL_NO_ERROR();
4727     EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::blue);
4728 
4729     // Shrink the texture
4730     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall);
4731     ASSERT_GL_NO_ERROR();
4732 
4733     // Create a source texture/FBO to blit from
4734     GLTexture sourceTex;
4735     glBindTexture(GL_TEXTURE_2D, sourceTex);
4736     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall);
4737     ASSERT_GL_NO_ERROR();
4738     GLFramebuffer sourceFbo;
4739     glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo);
4740     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTex, 0);
4741     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4742     // Fill the source texture with green
4743     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4744     glUseProgram(greenProgram);
4745     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
4746     ASSERT_GL_NO_ERROR();
4747     EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::green);
4748 
4749     // Blit the source (green) to the destination
4750     glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo);
4751     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFbo);
4752     glBlitFramebuffer(0, 0, kSizeSmall, kSizeSmall, 0, 0, kSizeSmall, kSizeSmall,
4753                       GL_COLOR_BUFFER_BIT, GL_NEAREST);
4754     ASSERT_GL_NO_ERROR();
4755 
4756     // Render to the default framebuffer sampling from the blited texture and verify it's green
4757     glBindFramebuffer(GL_FRAMEBUFFER, 0);
4758     glBindTexture(GL_TEXTURE_2D, mTexture2D);
4759     ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
4760     glUseProgram(texProgram);
4761     drawQuad(texProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
4762     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4763 }
4764 
4765 // Regression test for http://crbug.com/949985 to make sure dirty bits are propagated up from
4766 // TextureImpl and the texture is synced before being used in a draw call.
TEST_P(Texture2DTestES3,TextureImplPropogatesDirtyBits)4767 TEST_P(Texture2DTestES3, TextureImplPropogatesDirtyBits)
4768 {
4769     ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
4770     // Flaky hangs on Win10 AMD RX 550 GL. http://anglebug.com/3371
4771     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4772     // D3D Debug device reports an error. http://anglebug.com/3501
4773     ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
4774     // Support copy from levels outside the image range. http://anglebug.com/4733
4775     ANGLE_SKIP_TEST_IF(IsVulkan());
4776 
4777     // The workaround in the GL backend required to trigger this bug generates driver warning
4778     // messages.
4779     ScopedIgnorePlatformMessages ignoreMessages;
4780 
4781     setUpProgram();
4782     glUseProgram(mProgram);
4783     glActiveTexture(GL_TEXTURE0 + mTexture2DUniformLocation);
4784 
4785     GLTexture dest;
4786     glBindTexture(GL_TEXTURE_2D, dest);
4787 
4788     GLTexture source;
4789     glBindTexture(GL_TEXTURE_2D, source);
4790 
4791     // Put data in mip 0 and 1
4792     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4793                  GLColor::red.data());
4794     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4795                  GLColor::green.data());
4796 
4797     // Disable mipmapping so source is complete
4798     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4799     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4800 
4801     // Force the dirty bits to be synchronized in source
4802     drawQuad(mProgram, "position", 1.0f);
4803 
4804     // Copy from mip 1 of the source.  In the GL backend this internally sets the base level to mip
4805     // 1 and sets a dirty bit.
4806     glCopyTextureCHROMIUM(source, 1, GL_TEXTURE_2D, dest, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_FALSE,
4807                           GL_FALSE, GL_FALSE);
4808 
4809     // Draw again, assertions are generated if the texture has internal dirty bits at draw time
4810     drawQuad(mProgram, "position", 1.0f);
4811 }
4812 
4813 // This test case changes the base level of a texture that's attached to a framebuffer, clears every
4814 // level to green, and then samples the texture when rendering. Test is taken from
4815 // https://www.khronos.org/registry/webgl/sdk/tests/conformance2/rendering/framebuffer-texture-changing-base-level.html
TEST_P(Texture2DTestES3,FramebufferTextureChangingBaselevel)4816 TEST_P(Texture2DTestES3, FramebufferTextureChangingBaselevel)
4817 {
4818     // TODO(cnorthrop): Failing on Vulkan/Windows/AMD. http://anglebug.com/3996
4819     ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
4820 
4821     setUpProgram();
4822 
4823     constexpr GLint width  = 8;
4824     constexpr GLint height = 4;
4825 
4826     GLTexture texture;
4827     glBindTexture(GL_TEXTURE_2D, texture);
4828     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
4829     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4830     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4831     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4832 
4833     // Create all mipmap levels for the texture from level 0 to the 1x1 pixel level.
4834     GLint level  = 0;
4835     GLint levelW = width;
4836     GLint levelH = height;
4837     glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4838                  nullptr);
4839     while (levelW > 1 || levelH > 1)
4840     {
4841         ++level;
4842         levelW = static_cast<GLint>(std::max(1.0, std::floor(width / std::pow(2, level))));
4843         levelH = static_cast<GLint>(std::max(1.0, std::floor(height / std::pow(2, level))));
4844         glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4845                      nullptr);
4846     }
4847 
4848     // Clear each level of the texture using an FBO. Change the base level to match the level used
4849     // for the FBO on each iteration.
4850     GLFramebuffer fbo;
4851     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4852     level  = 0;
4853     levelW = width;
4854     levelH = height;
4855     while (levelW > 1 || levelH > 1)
4856     {
4857         levelW = static_cast<GLint>(std::floor(width / std::pow(2, level)));
4858         levelH = static_cast<GLint>(std::floor(height / std::pow(2, level)));
4859 
4860         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
4861         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, level);
4862 
4863         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
4864         EXPECT_GL_NO_ERROR();
4865 
4866         glClearColor(0, 1, 0, 1);
4867         glClear(GL_COLOR_BUFFER_BIT);
4868 
4869         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4870 
4871         ++level;
4872     }
4873 
4874     glBindFramebuffer(GL_FRAMEBUFFER, 0);
4875     glViewport(0, 0, 16, 16);
4876     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
4877 
4878     drawQuad(mProgram, "position", 0.5f);
4879 
4880     EXPECT_GL_NO_ERROR();
4881     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4882 }
4883 
4884 // Test that changing the base level of a texture after redefining a level outside the mip-chain
4885 // preserves the other mips' data.
TEST_P(Texture2DBaseMaxTestES3,ExtendMipChainAfterRedefine)4886 TEST_P(Texture2DBaseMaxTestES3, ExtendMipChainAfterRedefine)
4887 {
4888     // http://anglebug.com/4699
4889     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
4890 
4891     // http://anglebug.com/5153
4892     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA() && IsMac());
4893 
4894     GLFramebuffer framebuffer;
4895     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4896 
4897     GLTexture texture;
4898     glBindTexture(GL_TEXTURE_2D, texture);
4899 
4900     std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
4901     fillMipData(mipData.data(), kMip0Size, kMipColors);
4902 
4903     for (size_t mip = 1; mip < kMipCount; ++mip)
4904     {
4905         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA,
4906                      GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip));
4907     }
4908 
4909     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
4910     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
4911     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4912 
4913     // Mip 1 is green.  Verify this.
4914     EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]);
4915 
4916     // http://anglebug.com/4709
4917     ANGLE_SKIP_TEST_IF(IsOpenGL() && (IsIntel() || IsAMD()) && IsWindows());
4918 
4919     // Add mip 0 and rebase the mip chain.
4920     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4921                  mipData.data() + getMipDataOffset(kMip0Size, 0));
4922     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
4923 
4924     // Mip 1 should still be green.
4925     EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]);
4926 
4927     // Verify the other mips too.
4928     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
4929     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4930     EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[2]);
4931 
4932     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
4933     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4934     EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[3]);
4935 
4936     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4937     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4938 
4939     EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]);
4940 }
4941 
4942 // Test that changing the base level of a texture multiple times preserves the data.
TEST_P(Texture2DBaseMaxTestES3,PingPongBaseLevel)4943 TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevel)
4944 {
4945     testPingPongBaseLevel(false);
4946 }
TEST_P(Texture2DBaseMaxTestES3,PingPongBaseLevelImmutable)4947 TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevelImmutable)
4948 {
4949     testPingPongBaseLevel(true);
4950 }
testPingPongBaseLevel(bool immutable)4951 void Texture2DBaseMaxTestES3::testPingPongBaseLevel(bool immutable)
4952 {
4953     // http://anglebug.com/4710
4954     ANGLE_SKIP_TEST_IF(IsD3D());
4955 
4956     // http://anglebug.com/4711
4957     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsWindows());
4958 
4959     // http://anglebug.com/4701
4960     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
4961 
4962     initTest(immutable);
4963 
4964     // Ping pong a few times.
4965     for (uint32_t tries = 0; tries < 2; ++tries)
4966     {
4967         // Rebase to different mips and verify mips.
4968         for (uint32_t base = 0; base < kMipCount; ++base)
4969         {
4970             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base);
4971             for (uint32_t lod = 0; lod < kMipCount - base; ++lod)
4972             {
4973                 setLodUniform(lod);
4974                 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4975                 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]);
4976             }
4977         }
4978 
4979         // Rebase backwards and verify mips.
4980         for (uint32_t base = kMipCount - 2; base > 0; --base)
4981         {
4982             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base);
4983             for (uint32_t lod = 0; lod < kMipCount - base; ++lod)
4984             {
4985                 setLodUniform(lod);
4986                 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4987                 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]);
4988             }
4989         }
4990     }
4991 }
4992 
4993 // Test that glTexSubImage2D after incompatibly redefining a mip level correctly applies the update
4994 // after the redefine data.
TEST_P(Texture2DBaseMaxTestES3,SubImageAfterRedefine)4995 TEST_P(Texture2DBaseMaxTestES3, SubImageAfterRedefine)
4996 {
4997     initTest(false);
4998 
4999     // Test that all mips have the expected data initially (this makes sure the texture image is
5000     // created already).
5001     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5002     {
5003         setLodUniform(lod);
5004         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5005         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5006     }
5007 
5008     // Redefine every level, followed by a glTexSubImage2D
5009     const GLColor kNewMipColors[kMipCount] = {
5010         GLColor::yellow,
5011         GLColor::cyan,
5012         GLColor(127, 0, 0, 255),
5013         GLColor(0, 127, 0, 255),
5014     };
5015     std::array<GLColor, getTotalMipDataSize(kMip0Size * 2)> newMipData;
5016     fillMipData(newMipData.data(), kMip0Size * 2, kNewMipColors);
5017 
5018     const GLColor kSubImageMipColors[kMipCount] = {
5019         GLColor(0, 0, 127, 255),
5020         GLColor(127, 127, 0, 255),
5021         GLColor(0, 127, 127, 255),
5022         GLColor(127, 0, 127, 255),
5023     };
5024     std::array<GLColor, getTotalMipDataSize(kMip0Size)> subImageMipData;
5025     fillMipData(subImageMipData.data(), kMip0Size, kSubImageMipColors);
5026 
5027     for (size_t mip = 0; mip < kMipCount; ++mip)
5028     {
5029         // Redefine the level.
5030         size_t newMipSize = (kMip0Size * 2) >> mip;
5031         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, newMipSize, newMipSize, 0, GL_RGBA,
5032                      GL_UNSIGNED_BYTE, newMipData.data() + getMipDataOffset(kMip0Size * 2, mip));
5033 
5034         // Immediately follow that with a subimage update.
5035         glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA,
5036                         GL_UNSIGNED_BYTE,
5037                         subImageMipData.data() + getMipDataOffset(kMip0Size, mip));
5038     }
5039     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1);
5040 
5041     // Test that the texture looks as expected.
5042     const int w = getWindowWidth() - 1;
5043     const int h = getWindowHeight() - 1;
5044     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5045     {
5046         setLodUniform(lod);
5047         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5048         EXPECT_PIXEL_COLOR_EQ(0, 0, kSubImageMipColors[lod]);
5049         EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColors[lod]);
5050         EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColors[lod]);
5051         EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColors[lod]);
5052     }
5053 }
5054 
5055 // Test that incompatibly redefining a level then redefining it back to its original size works.
TEST_P(Texture2DBaseMaxTestES3,IncompatiblyRedefineLevelThenRevert)5056 TEST_P(Texture2DBaseMaxTestES3, IncompatiblyRedefineLevelThenRevert)
5057 {
5058     initTest(false);
5059 
5060     // Test that all mips have the expected data initially (this makes sure the texture image is
5061     // created already).
5062     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5063     {
5064         setLodUniform(lod);
5065         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5066         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5067     }
5068 
5069     // Redefine Mip 1 to be larger.
5070     constexpr size_t kLargeMip1Size = getMipDataSize(kMip0Size * 2, 1);
5071     std::array<GLColor, kLargeMip1Size> interimMipData;
5072     std::fill(interimMipData.data(), interimMipData.data() + kLargeMip1Size, GLColor::yellow);
5073 
5074     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5075                  interimMipData.data());
5076 
5077     // Redefine Mip 1 back to its original size.
5078     constexpr size_t kNormalMip1Size = getMipDataSize(kMip0Size, 1);
5079     std::array<GLColor, kLargeMip1Size> newMipData;
5080     std::fill(newMipData.data(), newMipData.data() + kNormalMip1Size, GLColor::cyan);
5081 
5082     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size / 2, kMip0Size / 2, 0, GL_RGBA,
5083                  GL_UNSIGNED_BYTE, newMipData.data());
5084 
5085     // Verify texture colors.
5086     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5087     {
5088         setLodUniform(lod);
5089         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5090         EXPECT_PIXEL_COLOR_EQ(0, 0, lod == 1 ? GLColor::cyan : kMipColors[lod]);
5091     }
5092 }
5093 
5094 // Test that redefining every level of a texture to another format works.  The format uses more
5095 // bits per component, to ensure alignment requirements for the new format are taken into account.
TEST_P(Texture2DBaseMaxTestES3,RedefineEveryLevelToAnotherFormat)5096 TEST_P(Texture2DBaseMaxTestES3, RedefineEveryLevelToAnotherFormat)
5097 {
5098     initTest(false);
5099 
5100     // Test that all mips have the expected data initially (this makes sure the texture image is
5101     // created already).
5102     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5103     {
5104         setLodUniform(lod);
5105         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5106         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5107     }
5108 
5109     const GLColor32F kNewMipColors[kMipCount] = {
5110         GLColor32F(1.0, 1.0, 0.0, 1.0f),
5111         GLColor32F(1.0, 0.0, 1.0, 1.0f),
5112         GLColor32F(0.0, 1.0, 1.0, 1.0f),
5113         GLColor32F(1.0, 1.0, 1.0, 1.0f),
5114     };
5115 
5116     std::array<GLColor32F, getTotalMipDataSize(kMip0Size)> newMipData;
5117     fillMipData(newMipData.data(), kMip0Size, kNewMipColors);
5118 
5119     // Redefine every level with the new format.
5120     for (size_t mip = 0; mip < kMipCount; ++mip)
5121     {
5122         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA32F, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA,
5123                      GL_FLOAT, newMipData.data() + getMipDataOffset(kMip0Size, mip));
5124     }
5125 
5126     // Verify texture colors.
5127     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5128     {
5129         setLodUniform(lod);
5130         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5131 
5132         GLColor32F mipColor32F = kNewMipColors[lod];
5133         GLColor mipColor(static_cast<GLubyte>(std::roundf(mipColor32F.R * 255)),
5134                          static_cast<GLubyte>(std::roundf(mipColor32F.G * 255)),
5135                          static_cast<GLubyte>(std::roundf(mipColor32F.B * 255)),
5136                          static_cast<GLubyte>(std::roundf(mipColor32F.A * 255)));
5137 
5138         EXPECT_PIXEL_COLOR_EQ(0, 0, mipColor);
5139     }
5140 }
5141 
5142 // Test that generating mipmaps after change base level.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRebase)5143 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebase)
5144 {
5145     // http://anglebug.com/5880
5146     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
5147 
5148     testGenerateMipmapAfterRebase(false);
5149 }
5150 
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRebaseImmutable)5151 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebaseImmutable)
5152 {
5153     // http://anglebug.com/4710
5154     ANGLE_SKIP_TEST_IF(IsD3D());
5155     // http://anglebug.com/5798
5156     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
5157     // http://anglebug.com/5880
5158     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
5159 
5160     testGenerateMipmapAfterRebase(true);
5161 }
5162 
testGenerateMipmapAfterRebase(bool immutable)5163 void Texture2DBaseMaxTestES3::testGenerateMipmapAfterRebase(bool immutable)
5164 {
5165     initTest(immutable);
5166 
5167     // Test that all mips have the expected data initially (this makes sure the texture image is
5168     // created already).
5169     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5170     {
5171         setLodUniform(lod);
5172         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5173         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5174     }
5175 
5176     // Update level 1 (any level would do other than 0) with new data
5177     const GLColor kNewMipColor = GLColor::yellow;
5178     std::array<GLColor, getMipDataSize(kMip0Size >> 1, 0)> newMipData;
5179     std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5180 
5181     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kMip0Size >> 1, kMip0Size >> 1, GL_RGBA,
5182                     GL_UNSIGNED_BYTE, newMipData.data());
5183 
5184     // Change base level and max level and then generate mipmaps. This should redefine level 1 and 2
5185     // with kNewMipColor and leave levels 0 and 3 unchanged.
5186     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5187     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 2);
5188     glGenerateMipmap(GL_TEXTURE_2D);
5189     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5190     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1);
5191 
5192     // Test that the texture looks as expected.
5193     const int w = getWindowWidth() - 1;
5194     const int h = getWindowHeight() - 1;
5195     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5196     {
5197         setLodUniform(lod);
5198         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5199         if (lod == 0)
5200         {
5201             EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
5202             EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
5203             EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
5204             EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
5205         }
5206         else if (lod == kMipCount - 1)
5207         {
5208             EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
5209             EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
5210             EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
5211             EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
5212         }
5213         else
5214         {
5215             EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor) << "lod " << lod;
5216             EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor) << "lod " << lod;
5217             EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor) << "lod " << lod;
5218             EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor) << "lod " << lod;
5219         }
5220     }
5221 }
5222 
5223 // Test that generating mipmaps after incompatibly redefining a level works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefine)5224 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefine)
5225 {
5226     initTest(false);
5227 
5228     // Test that all mips have the expected data initially (this makes sure the texture image is
5229     // created already).
5230     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5231     {
5232         setLodUniform(lod);
5233         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5234         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5235     }
5236 
5237     // Redefine level 1 (any level would do other than 0) to an incompatible size, say the same size
5238     // as level 0.
5239     const GLColor kNewMipColor = GLColor::yellow;
5240     std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5241     std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5242 
5243     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5244                  newMipData.data());
5245 
5246     // Generate mipmaps.  This should redefine level 1 back to being compatible with level 0.
5247     glGenerateMipmap(GL_TEXTURE_2D);
5248 
5249     // Test that the texture looks as expected.
5250     const int w = getWindowWidth() - 1;
5251     const int h = getWindowHeight() - 1;
5252     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5253     {
5254         setLodUniform(lod);
5255         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5256         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]);
5257         EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]);
5258         EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]);
5259         EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]);
5260     }
5261 }
5262 
5263 // Test that generating mipmaps after incompatibly redefining a level while simultaneously changing
5264 // the base level works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefineAndRebase)5265 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefineAndRebase)
5266 {
5267     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
5268 
5269     // http://crbug.com/1100613
5270     ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
5271 
5272     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
5273     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
5274 
5275     initTest(false);
5276 
5277     // Test that all mips have the expected data initially (this makes sure the texture image is
5278     // created already).
5279     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5280     {
5281         setLodUniform(lod);
5282         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5283         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << lod;
5284     }
5285 
5286     // Redefine level 2 to an incompatible size, say the same size as level 0.
5287     const GLColor kNewMipColor = GLColor::yellow;
5288     std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5289     std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5290 
5291     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5292                  newMipData.data());
5293 
5294     // Set base level of the texture to 1 then generate mipmaps.  Level 2 that's redefined should
5295     // go back to being compatibly defined.
5296     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5297     glGenerateMipmap(GL_TEXTURE_2D);
5298 
5299     // Test that the texture looks as expected.
5300     const int w = getWindowWidth() - 1;
5301     const int h = getWindowHeight() - 1;
5302     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5303     {
5304         setLodUniform(lod);
5305         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5306         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]) << lod;
5307         EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[1]) << lod;
5308         EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[1]) << lod;
5309         EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[1]) << lod;
5310     }
5311 
5312     // Redefine level 1 (current base level) to an incompatible size.
5313     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5314                  newMipData.data());
5315 
5316     // Set base level of the texture back to 0 then generate mipmaps.  Level 1 should go back to
5317     // being compatibly defined.
5318     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5319     glGenerateMipmap(GL_TEXTURE_2D);
5320 
5321     // Test that the texture looks as expected.
5322     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5323     {
5324         setLodUniform(lod);
5325         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5326         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]) << lod;
5327         EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]) << lod;
5328         EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]) << lod;
5329         EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]) << lod;
5330     }
5331 }
5332 
5333 // Test that generating mipmaps after incompatibly redefining the base level of the texture works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefiningBase)5334 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBase)
5335 {
5336     initTest(false);
5337 
5338     // Test that all mips have the expected data initially (this makes sure the texture image is
5339     // created already).
5340     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5341     {
5342         setLodUniform(lod);
5343         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5344         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5345     }
5346 
5347     // Redefine level 0 to an incompatible size.
5348     const GLColor kNewMipColor = GLColor::yellow;
5349     std::array<GLColor, getMipDataSize(kMip0Size * 2, 0)> newMipData;
5350     std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5351 
5352     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA,
5353                  GL_UNSIGNED_BYTE, newMipData.data());
5354 
5355     // Generate mipmaps.
5356     glGenerateMipmap(GL_TEXTURE_2D);
5357 
5358     // Test that the texture looks as expected.
5359     const int w = getWindowWidth() - 1;
5360     const int h = getWindowHeight() - 1;
5361     for (uint32_t lod = 0; lod < kMipCount + 1; ++lod)
5362     {
5363         setLodUniform(lod);
5364         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5365         EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor);
5366         EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor);
5367         EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor);
5368         EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor);
5369     }
5370 }
5371 
5372 // Test that generating mipmaps after incompatibly redefining the base level while simultaneously
5373 // changing MAX_LEVEL works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefiningBaseAndChangingMax)5374 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBaseAndChangingMax)
5375 {
5376     initTest(false);
5377 
5378     // Test that all mips have the expected data initially (this makes sure the texture image is
5379     // created already).
5380     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5381     {
5382         setLodUniform(lod);
5383         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5384         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5385     }
5386 
5387     // Redefine level 0 to an incompatible size.
5388     const GLColor kNewMipColor = GLColor::yellow;
5389     std::array<GLColor, getMipDataSize(kMip0Size * 2, 0)> newMipData;
5390     std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5391 
5392     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA,
5393                  GL_UNSIGNED_BYTE, newMipData.data());
5394 
5395     // Set max level of the texture to 2 then generate mipmaps.
5396     constexpr uint32_t kMaxLevel = 2;
5397     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMaxLevel);
5398     glGenerateMipmap(GL_TEXTURE_2D);
5399 
5400     // Test that the texture looks as expected.
5401     const int w = getWindowWidth() - 1;
5402     const int h = getWindowHeight() - 1;
5403     for (uint32_t lod = 0; lod <= kMaxLevel; ++lod)
5404     {
5405         setLodUniform(lod);
5406         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5407         EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor);
5408         EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor);
5409         EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor);
5410         EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor);
5411     }
5412 }
5413 
5414 // Test that stage invalid texture levels work.
TEST_P(Texture2DBaseMaxTestES3,StageInvalidLevels)5415 TEST_P(Texture2DBaseMaxTestES3, StageInvalidLevels)
5416 {
5417     constexpr uint32_t kMaxLevel           = 2;
5418     const GLColor kMipColor[kMaxLevel + 1] = {GLColor::red, GLColor::green, GLColor::blue};
5419 
5420     initTest(false);
5421 
5422     GLTexture texture;
5423     glBindTexture(GL_TEXTURE_2D, texture);
5424 
5425     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5426     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5427     std::vector<GLColor> texDataCyan(2u * 2u, GLColor::cyan);
5428     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataCyan.data());
5429     setLodUniform(0);
5430     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5431     EXPECT_GL_NO_ERROR();
5432 
5433     std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
5434     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5435                  texDataGreen.data());
5436     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::blue);
5437     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5438     EXPECT_GL_NO_ERROR();
5439 
5440     std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5441     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5442     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5443     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5444 
5445     // Test that the texture looks as expected.
5446     const int w = getWindowWidth() - 1;
5447     const int h = getWindowHeight() - 1;
5448     for (uint32_t lod = 0; lod <= kMaxLevel; ++lod)
5449     {
5450         setLodUniform(lod);
5451         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5452         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColor[lod]);
5453         EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColor[lod]);
5454         EXPECT_PIXEL_COLOR_EQ(0, h, kMipColor[lod]);
5455         EXPECT_PIXEL_COLOR_EQ(w, h, kMipColor[lod]);
5456     }
5457 }
5458 
5459 // Test redefine a mutable texture into an immutable texture.
TEST_P(Texture2DBaseMaxTestES3,RedefineMutableToImmutable)5460 TEST_P(Texture2DBaseMaxTestES3, RedefineMutableToImmutable)
5461 {
5462     // http://anglebug.com/4710
5463     ANGLE_SKIP_TEST_IF(IsD3D());
5464 
5465     // http://anglebug.com/4701
5466     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
5467 
5468     constexpr uint32_t kBaseLevel          = 1;
5469     const GLColor kNewMipColors[kMipCount] = {
5470         GLColor::yellow,
5471         GLColor::cyan,
5472         GLColor::white,
5473         GLColor(127u, 127u, 127u, 255u),
5474     };
5475 
5476     initTest(false);
5477 
5478     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, kBaseLevel);
5479 
5480     // Test that all mips have the expected data
5481     for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
5482     {
5483         setLodUniform(lod - kBaseLevel);
5484         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5485         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5486     }
5487 
5488     glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size);
5489     std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
5490     fillMipData(mipData.data(), kMip0Size, kNewMipColors);
5491     for (size_t mip = 0; mip < kMipCount; ++mip)
5492     {
5493         glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA,
5494                         GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip));
5495     }
5496 
5497     // Test that all enabled mips have the expected data
5498     for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
5499     {
5500         setLodUniform(lod - kBaseLevel);
5501         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5502         EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
5503     }
5504 
5505     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5506     for (uint32_t lod = 0; lod < kBaseLevel; ++lod)
5507     {
5508         setLodUniform(lod);
5509         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5510         EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
5511     }
5512 }
5513 
5514 // Test that redefine a level with incompatible size beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,RedefineIncompatibleLevelBeyondMaxLevel)5515 TEST_P(Texture2DBaseMaxTestES3, RedefineIncompatibleLevelBeyondMaxLevel)
5516 {
5517     initTest(false);
5518 
5519     // Test that all mips have the expected data initially (this makes sure the texture image is
5520     // created already).
5521     for (uint32_t lod = 0; lod < kMipCount; ++lod)
5522     {
5523         setLodUniform(lod);
5524         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5525         EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5526     }
5527 
5528     uint32_t maxLevel = 1;
5529     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
5530 
5531     // Update level 0
5532     const GLColor kNewMipLevle0Color = GLColor::yellow;
5533     std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5534     std::fill(newMipData.begin(), newMipData.end(), kNewMipLevle0Color);
5535     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kMip0Size, kMip0Size, GL_RGBA, GL_UNSIGNED_BYTE,
5536                     newMipData.data());
5537 
5538     // Update level 2 with incompatible data
5539     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5540                  newMipData.data());
5541     EXPECT_GL_NO_ERROR();
5542 
5543     // Test that the texture looks as expected.
5544     const int w = getWindowWidth() - 1;
5545     const int h = getWindowHeight() - 1;
5546     for (uint32_t lod = 0; lod < maxLevel; ++lod)
5547     {
5548         setLodUniform(lod);
5549         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5550         if (lod == 0)
5551         {
5552             EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipLevle0Color);
5553             EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipLevle0Color);
5554             EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipLevle0Color);
5555             EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipLevle0Color);
5556         }
5557         else
5558         {
5559             EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5560             EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]);
5561             EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]);
5562             EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]);
5563         }
5564     }
5565 }
5566 
5567 // Port test from web_gl/conformance2/textures/misc/fuzz-545-immutable-tex-render-feedback.html.
5568 // What this tries to do is create a render feedback loop and ensure it is not crashing.
TEST_P(Texture2DBaseMaxTestES3,Fuzz545ImmutableTexRenderFeedback)5569 TEST_P(Texture2DBaseMaxTestES3, Fuzz545ImmutableTexRenderFeedback)
5570 {
5571     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5572 
5573     constexpr uint32_t MIPS = 2;
5574     constexpr uint32_t SIZE = 10;
5575 
5576     GLTexture immutTex;
5577     glBindTexture(GL_TEXTURE_2D, immutTex);
5578     glTexStorage2D(GL_TEXTURE_2D, MIPS, GL_RGBA8, SIZE, SIZE);
5579 
5580     GLTexture mutTex;
5581     glBindTexture(GL_TEXTURE_2D, mutTex);
5582     for (uint32_t mip = 0; mip < MIPS; mip++)
5583     {
5584         const uint32_t size = SIZE >> mip;
5585         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5586                      nullptr);
5587     }
5588 
5589     constexpr GLenum MAG_FILTERS[] = {GL_LINEAR, GL_NEAREST};
5590     constexpr GLenum MIN_FILTERS[] = {
5591         GL_LINEAR,  GL_LINEAR_MIPMAP_LINEAR,  GL_LINEAR_MIPMAP_NEAREST,
5592         GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST};
5593 
5594     GLFramebuffer fbo;
5595     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5596 
5597     const GLuint texs[] = {immutTex, mutTex};
5598     for (const GLuint tex : texs)
5599     {
5600         glBindTexture(GL_TEXTURE_2D, tex);
5601 
5602         for (GLuint level_prime_base = 0; level_prime_base < (MIPS + 1); level_prime_base++)
5603         {  // `level_base` in GLES
5604             // ES 3.0.6 p150
5605             GLuint _level_base = level_prime_base;
5606             if (tex == immutTex)
5607             {
5608                 _level_base = std::min(_level_base, MIPS - 1);
5609             }
5610             const GLuint level_base = _level_base;
5611 
5612             for (GLuint _level_prime_max = (level_prime_base - 1); _level_prime_max < (MIPS + 2);
5613                  _level_prime_max++)
5614             {  // `q` in GLES
5615                 if (_level_prime_max < 0)
5616                     continue;
5617                 if (_level_prime_max == (MIPS + 1))
5618                 {
5619                     _level_prime_max = 10000;  // This is the default, after all!
5620                 }
5621                 const GLuint level_prime_max = _level_prime_max;
5622 
5623                 // ES 3.0.6 p150
5624                 GLuint _level_max = level_prime_max;
5625                 if (tex == immutTex)
5626                 {
5627                     _level_max = std::min(std::max(level_base, level_prime_max), MIPS - 1);
5628                 }
5629                 const GLuint level_max = _level_max;
5630 
5631                 const GLuint p = std::floor((float)std::log2(SIZE)) + level_base;
5632                 const GLuint q = std::min(p, level_max);
5633 
5634                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level_prime_base);
5635                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level_prime_max);
5636 
5637                 const bool mipComplete = (q <= MIPS - 1);
5638 
5639                 for (const GLenum minFilter : MIN_FILTERS)
5640                 {
5641                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
5642 
5643                     for (const GLenum magFilter : MAG_FILTERS)
5644                     {
5645                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
5646 
5647                         for (GLuint dstMip = 0; dstMip < (MIPS + 1); dstMip++)
5648                         {
5649                             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5650                                                    GL_TEXTURE_2D, tex, dstMip);
5651 
5652                             // ES3.0 p213-214
5653                             bool fbComplete = true;
5654 
5655                             // * "The width and height of `image` are non-zero"
5656                             fbComplete &= (0 <= dstMip && dstMip <= MIPS - 1);
5657 
5658                             if (tex != immutTex)
5659                             {  // "...does not name an immutable-format texture..."
5660                                 // * "...the value of [level] must be in the range `[level_base,
5661                                 // q]`"
5662                                 fbComplete &= (level_base <= dstMip && dstMip <= q);
5663 
5664                                 // * "...the value of [level] is not `level_base`, then the texture
5665                                 // must be mipmap complete"
5666                                 if (dstMip != level_base)
5667                                 {
5668                                     fbComplete &= mipComplete;
5669                                 }
5670                             }
5671 
5672                             // -
5673                             GLenum expectError  = 0;
5674                             GLenum expectStatus = GL_FRAMEBUFFER_COMPLETE;
5675                             if (!fbComplete)
5676                             {
5677                                 expectStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
5678                                 expectError  = GL_INVALID_FRAMEBUFFER_OPERATION;
5679                             }
5680 
5681                             // -
5682                             EXPECT_GLENUM_EQ(expectStatus,
5683                                              glCheckFramebufferStatus(GL_FRAMEBUFFER));
5684 
5685                             drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
5686                             EXPECT_EQ(expectError, glGetError());
5687                         }
5688                     }
5689                 }
5690             }
5691         }
5692     }
5693 }
5694 
5695 // Test sampling from a texture of a (usually) not color-renderable
5696 // base format with a color-renderable level beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,NotColorRenderableWithColorRenderableBeyondMaxLevel)5697 TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableWithColorRenderableBeyondMaxLevel)
5698 {
5699     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5700 
5701     GLTexture texture;
5702     glBindTexture(GL_TEXTURE_2D, texture);
5703     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5704     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5705 
5706     const GLuint data[4] = {0xC0040200, 0xC0040200, 0xC0040200, 0xC0040200};
5707     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 2, 2, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data);
5708     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5709     ASSERT_GL_NO_ERROR();
5710 
5711     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5712     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5713     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5714 }
5715 
5716 // Test sampling from a texture of a depth-renderable base format
5717 // with a color-renderable level beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,DepthRenderableWithColorRenderableBeyondMaxLevel)5718 TEST_P(Texture2DBaseMaxTestES3, DepthRenderableWithColorRenderableBeyondMaxLevel)
5719 {
5720     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5721 
5722     GLTexture texture;
5723     glBindTexture(GL_TEXTURE_2D, texture);
5724     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5725     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5726 
5727     const GLfloat data[4] = {1.0f, 1.0f, 1.0f, 1.0f};
5728     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
5729                  data);
5730     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5731     ASSERT_GL_NO_ERROR();
5732 
5733     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5734     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5735     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5736 }
5737 
5738 // Test texture sampling while changing the base format from color-renderable
5739 // to (usually) not color-renderable by manipulating base and max levels.
TEST_P(Texture2DBaseMaxTestES3,NotColorRenderableAfterColorRenderableBelowBaseLevel)5740 TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableAfterColorRenderableBelowBaseLevel)
5741 {
5742     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5743 
5744     GLTexture texture;
5745     glBindTexture(GL_TEXTURE_2D, texture);
5746     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5747     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5748 
5749     std::array<GLColor, 4> data0;
5750     data0.fill(GLColor::green);
5751     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data());
5752 
5753     const GLuint data1[1] = {0xC0040200};
5754     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data1);
5755     ASSERT_GL_NO_ERROR();
5756 
5757     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5758     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5759     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5760 
5761     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5762     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5763     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5764     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5765 }
5766 
5767 // Test texture sampling while changing the base format from color-renderable
5768 // to depth-renderable by manipulating base and max levels.
TEST_P(Texture2DBaseMaxTestES3,DepthRenderableAfterColorRenderableBelowBaseLevel)5769 TEST_P(Texture2DBaseMaxTestES3, DepthRenderableAfterColorRenderableBelowBaseLevel)
5770 {
5771     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5772 
5773     GLTexture texture;
5774     glBindTexture(GL_TEXTURE_2D, texture);
5775     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5776     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5777 
5778     std::array<GLColor, 4> data0;
5779     data0.fill(GLColor::green);
5780     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data());
5781 
5782     const GLfloat data1[1] = {1.0f};
5783     glTexImage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
5784                  data1);
5785     ASSERT_GL_NO_ERROR();
5786 
5787     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5788     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5789     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5790 
5791     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5792     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5793     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5794     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5795 }
5796 
5797 // Test to check that texture completeness is determined correctly when the texture base level is
5798 // greater than 0, and also that level 0 is not sampled when base level is greater than 0.
TEST_P(Texture2DTestES3,DrawWithBaseLevel1)5799 TEST_P(Texture2DTestES3, DrawWithBaseLevel1)
5800 {
5801     glActiveTexture(GL_TEXTURE0);
5802     glBindTexture(GL_TEXTURE_2D, mTexture2D);
5803 
5804     std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5805     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5806     std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
5807     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5808                  texDataGreen.data());
5809     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5810                  texDataGreen.data());
5811     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5812     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5813     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5814 
5815     EXPECT_GL_NO_ERROR();
5816 
5817     drawQuad(mProgram, "position", 0.5f);
5818 
5819     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5820 }
5821 
testCopyImage(const APIExtensionVersion usedExtension)5822 void Texture2DTestES3::testCopyImage(const APIExtensionVersion usedExtension)
5823 {
5824     ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
5825 
5826     std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5827     GLTexture srcTexture;
5828     GLTexture destTexture;
5829 
5830     glActiveTexture(GL_TEXTURE0);
5831     glBindTexture(GL_TEXTURE_2D, destTexture);
5832     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5833     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5834     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5835     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5836     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5837 
5838     std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
5839     glBindTexture(GL_TEXTURE_2D, srcTexture);
5840     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5841     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5842     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5843     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5844     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5845                  texDataGreen.data());
5846 
5847     glBindTexture(GL_TEXTURE_2D, 0);
5848 
5849     // copy
5850     if (usedExtension == APIExtensionVersion::OES)
5851     {
5852         glCopyImageSubDataOES(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0,
5853                               2, 2, 0, 2, 2, 1);
5854     }
5855     else
5856     {
5857         glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0,
5858                               2, 2, 0, 2, 2, 1);
5859     }
5860     glBindTexture(GL_TEXTURE_2D, destTexture);
5861     EXPECT_GL_NO_ERROR();
5862 
5863     glViewport(0, 0, 4, 4);
5864     drawQuad(mProgram, "position", 0.5f);
5865     EXPECT_GL_NO_ERROR();
5866 
5867     EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green);
5868     EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red);
5869     EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red);
5870 }
5871 
5872 // Test basic GL_EXT_copy_image copy without any bound textures
TEST_P(Texture2DTestES3,CopyImageEXT)5873 TEST_P(Texture2DTestES3, CopyImageEXT)
5874 {
5875     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5876     testCopyImage(APIExtensionVersion::EXT);
5877 }
5878 
5879 // Test basic GL_OES_copy_image copy without any bound textures
TEST_P(Texture2DTestES3,CopyImageOES)5880 TEST_P(Texture2DTestES3, CopyImageOES)
5881 {
5882     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image"));
5883     testCopyImage(APIExtensionVersion::OES);
5884 }
5885 
testCopyImageDepthStencil(const APIExtensionVersion usedExtension)5886 void Texture2DTestES3::testCopyImageDepthStencil(const APIExtensionVersion usedExtension)
5887 {
5888     ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
5889 
5890     std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5891     GLTexture srcTexture;
5892     GLTexture destTexture;
5893 
5894     constexpr GLsizei kSize = 4;
5895 
5896     GLTexture src;
5897     glBindTexture(GL_TEXTURE_2D, src);
5898     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
5899 
5900     GLTexture dst;
5901     glBindTexture(GL_TEXTURE_2D, dst);
5902     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
5903 
5904     // A color image for testing depth/stencil
5905     GLTexture color;
5906     glBindTexture(GL_TEXTURE_2D, color);
5907     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
5908 
5909     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5910     glUseProgram(program);
5911     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
5912     ASSERT_NE(colorLoc, -1);
5913 
5914     // Initialize the src depth image
5915     GLFramebuffer fbo;
5916     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5917     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5918     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, src, 0);
5919     glClearDepthf(0.3f);
5920     glClearStencil(0x57);
5921     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
5922 
5923     glEnable(GL_DEPTH_TEST);
5924     glDepthMask(GL_FALSE);
5925     glEnable(GL_STENCIL_TEST);
5926     glStencilFunc(GL_EQUAL, 0x57, 0xFF);
5927     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
5928     glStencilMask(0xFF);
5929 
5930     glDepthFunc(GL_LESS);
5931     glUniform4f(colorLoc, 1, 0, 0, 1);
5932     drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f);
5933     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5934 
5935     glDepthFunc(GL_GREATER);
5936     glUniform4f(colorLoc, 0, 1, 0, 1);
5937     drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f);
5938     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5939     ASSERT_GL_NO_ERROR();
5940 
5941     // Now that the depth stencil image is definitely initialized, copy it into the destination
5942     if (usedExtension == APIExtensionVersion::OES)
5943     {
5944         glCopyImageSubDataOES(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
5945                               kSize, 1);
5946     }
5947     else
5948     {
5949         glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
5950                               kSize, 1);
5951     }
5952     ASSERT_GL_NO_ERROR();
5953 
5954     // Verify the dst texture has the right depth/stencil values
5955     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dst, 0);
5956 
5957     glDepthFunc(GL_LESS);
5958     glUniform4f(colorLoc, 0, 0, 1, 1);
5959     drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f);
5960     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5961 
5962     glDepthFunc(GL_GREATER);
5963     glUniform4f(colorLoc, 1, 1, 0, 1);
5964     drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f);
5965     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
5966     ASSERT_GL_NO_ERROR();
5967 }
5968 
5969 // Test basic GL_EXT_copy_image copy with a depth/stencil texture
TEST_P(Texture2DTestES3,CopyImageEXTDepthStencil)5970 TEST_P(Texture2DTestES3, CopyImageEXTDepthStencil)
5971 {
5972     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5973     testCopyImageDepthStencil(APIExtensionVersion::EXT);
5974 }
5975 
5976 // Test basic GL_OES_copy_image copy with a depth/stencil texture
TEST_P(Texture2DTestES3,CopyImageOESDepthStencil)5977 TEST_P(Texture2DTestES3, CopyImageOESDepthStencil)
5978 {
5979     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image"));
5980     testCopyImageDepthStencil(APIExtensionVersion::OES);
5981 }
5982 
5983 // Test GL_EXT_copy_image compressed texture copy with mipmaps smaller than the block size
TEST_P(Texture2DTestES3,CopyCompressedImageMipMaps)5984 TEST_P(Texture2DTestES3, CopyCompressedImageMipMaps)
5985 {
5986     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5987     // TODO(http://anglebug.com/5634): Fix calls to vkCmdCopyBufferToImage() with images smaller
5988     // than the compressed format block size.
5989     ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
5990 
5991     constexpr uint32_t kSize             = 4;
5992     constexpr size_t kNumLevels          = 3;
5993     const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0};
5994 
5995     GLTexture srcTexture;
5996     glBindTexture(GL_TEXTURE_2D, srcTexture);
5997     for (size_t level = 0; level < kNumLevels; ++level)
5998     {
5999         glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
6000                                kSize >> level, 0, 8, CompressedImageETC1);
6001         EXPECT_GL_NO_ERROR();
6002     }
6003 
6004     GLTexture destTexture;
6005     glBindTexture(GL_TEXTURE_2D, destTexture);
6006     for (size_t level = 0; level < kNumLevels; ++level)
6007     {
6008         glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
6009                                kSize >> level, 0, 8, nullptr);
6010         EXPECT_GL_NO_ERROR();
6011     }
6012 
6013     glBindTexture(GL_TEXTURE_2D, 0);
6014 
6015     // copy
6016     for (size_t level = 0; level < kNumLevels; ++level)
6017     {
6018         glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, level, 0, 0, 0, destTexture, GL_TEXTURE_2D,
6019                               level, 0, 0, 0, kSize >> level, kSize >> level, 1);
6020         EXPECT_GL_NO_ERROR();
6021     }
6022 }
6023 
6024 // Test GL_EXT_copy_image copy with a non-zero base level
TEST_P(Texture2DTestES3,CopyImageBaseLevel1)6025 TEST_P(Texture2DTestES3, CopyImageBaseLevel1)
6026 {
6027     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6028 
6029     std::vector<GLColor> texDataBlack(8u * 8u, GLColor::black);
6030     std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
6031     std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6032     std::vector<GLColor> texDataBlue(4u * 4u, GLColor::blue);
6033 
6034     GLTexture srcTexture;
6035     GLTexture destTexture;
6036 
6037     glActiveTexture(GL_TEXTURE0);
6038     glBindTexture(GL_TEXTURE_2D, destTexture);
6039     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6040     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6041     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6042                  texDataBlack.data());
6043     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6044     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6045                  texDataGreen.data());
6046     glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data());
6047     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6048     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6049 
6050     glBindTexture(GL_TEXTURE_2D, srcTexture);
6051     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6052     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6053     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6054                  texDataBlack.data());
6055     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6056                  texDataGreen.data());
6057     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data());
6058     glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6059     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6060     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6061 
6062     glBindTexture(GL_TEXTURE_2D, 0);
6063 
6064     // copy
6065     glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 1, 2, 2, 0, destTexture, GL_TEXTURE_2D, 1, 2,
6066                           2, 0, 2, 2, 1);
6067 
6068     glBindTexture(GL_TEXTURE_2D, destTexture);
6069 
6070     EXPECT_GL_NO_ERROR();
6071 
6072     glViewport(0, 0, 4, 4);
6073     drawQuad(mProgram, "position", 0.5f);
6074     EXPECT_GL_NO_ERROR();
6075 
6076     EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green);
6077     EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red);
6078     EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red);
6079 }
6080 
6081 // Test basic GL_EXT_copy_image copy without any draw calls by attaching the texture
6082 // to a framebuffer and reads from the framebuffer to validate the copy
TEST_P(Texture2DTestES3,CopyImageFB)6083 TEST_P(Texture2DTestES3, CopyImageFB)
6084 {
6085     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6086 
6087     glViewport(0, 0, 4, 4);
6088     std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
6089     GLTexture srcTexture;
6090     GLTexture destTexture;
6091 
6092     glActiveTexture(GL_TEXTURE0);
6093     glBindTexture(GL_TEXTURE_2D, destTexture);
6094     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6095     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6096     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6097     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6098     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6099 
6100     std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6101     glBindTexture(GL_TEXTURE_2D, srcTexture);
6102     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6103     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6104     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6105     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6106     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6107                  texDataGreen.data());
6108     glBindTexture(GL_TEXTURE_2D, 0);
6109 
6110     // copy
6111     glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, destTexture, GL_TEXTURE_2D, 0, 0,
6112                           1, 0, 3, 3, 1);
6113 
6114     EXPECT_GL_NO_ERROR();
6115 
6116     GLFramebuffer fb;
6117     glBindFramebuffer(GL_FRAMEBUFFER, fb);
6118     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0);
6119     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6120 
6121     EXPECT_PIXEL_RECT_EQ(0, 1, 3, 3, GLColor::green);
6122     EXPECT_PIXEL_RECT_EQ(3, 0, 1, 4, GLColor::red);
6123     EXPECT_PIXEL_RECT_EQ(0, 0, 4, 1, GLColor::red);
6124 
6125     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6126 }
6127 
6128 // Test GL_EXT_copy_image copy to a framebuffer attachment after
6129 // invalidation. Then draw with blending onto the framebuffer.
TEST_P(Texture2DTestES3,CopyImageFBInvalidateThenBlend)6130 TEST_P(Texture2DTestES3, CopyImageFBInvalidateThenBlend)
6131 {
6132     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6133 
6134     ANGLE_GL_PROGRAM(drawBlueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6135     ANGLE_GL_PROGRAM(drawRedProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6136 
6137     glViewport(0, 0, 4, 4);
6138     GLTexture srcTexture;
6139     GLTexture textureAttachment;
6140 
6141     std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6142     glBindTexture(GL_TEXTURE_2D, srcTexture);
6143     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6144     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6145     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6146                  texDataGreen.data());
6147     glBindTexture(GL_TEXTURE_2D, 0);
6148 
6149     glBindTexture(GL_TEXTURE_2D, textureAttachment);
6150     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6151     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6152     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6153     glBindTexture(GL_TEXTURE_2D, 0);
6154 
6155     GLFramebuffer fb;
6156     glBindFramebuffer(GL_FRAMEBUFFER, fb);
6157     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureAttachment,
6158                            0);
6159     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6160 
6161     // Draw something in the texture to make sure it's image is defined.
6162     drawQuad(drawRedProgram, essl1_shaders::PositionAttrib(), 0.0f);
6163 
6164     // Invalidate the framebuffer.
6165     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
6166     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
6167     ASSERT_GL_NO_ERROR();
6168 
6169     // Copy into the framebuffer attachment.
6170     glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, textureAttachment, GL_TEXTURE_2D,
6171                           0, 0, 0, 0, 4, 4, 1);
6172     EXPECT_GL_NO_ERROR();
6173 
6174     // Draw and blend, making sure both the copy and draw happen correctly.
6175     glEnable(GL_BLEND);
6176     glBlendFunc(GL_ONE, GL_ONE);
6177     drawQuad(drawBlueProgram, essl1_shaders::PositionAttrib(), 0.0f);
6178     ASSERT_GL_NO_ERROR();
6179 
6180     EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::cyan);
6181 
6182     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6183 }
6184 
6185 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
6186 // have images defined.
TEST_P(Texture2DTestES3,DrawWithLevelsOutsideRangeUndefined)6187 TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeUndefined)
6188 {
6189     // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
6190     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
6191 
6192     glActiveTexture(GL_TEXTURE0);
6193     glBindTexture(GL_TEXTURE_2D, mTexture2D);
6194     std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6195     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6196                  texDataGreen.data());
6197     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6198     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6199     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6200     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6201 
6202     EXPECT_GL_NO_ERROR();
6203 
6204     drawQuad(mProgram, "position", 0.5f);
6205 
6206     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6207 }
6208 
6209 // Test that drawing works correctly when level 0 is undefined and base level is 1.
TEST_P(Texture2DTestES3,DrawWithLevelZeroUndefined)6210 TEST_P(Texture2DTestES3, DrawWithLevelZeroUndefined)
6211 {
6212     // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
6213     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
6214 
6215     glActiveTexture(GL_TEXTURE0);
6216     glBindTexture(GL_TEXTURE_2D, mTexture2D);
6217     std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6218     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6219                  texDataGreen.data());
6220     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6221     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6222     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6223     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
6224 
6225     EXPECT_GL_NO_ERROR();
6226 
6227     // Texture is incomplete.
6228     drawQuad(mProgram, "position", 0.5f);
6229     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6230 
6231     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6232                  texDataGreen.data());
6233 
6234     // Texture is now complete.
6235     drawQuad(mProgram, "position", 0.5f);
6236     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6237 }
6238 
6239 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
6240 // dimensions that don't fit the images inside the range.
6241 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)6242 TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
6243 {
6244     glActiveTexture(GL_TEXTURE0);
6245     glBindTexture(GL_TEXTURE_2D, mTexture2D);
6246     std::vector<GLColor> texDataRed(8u * 8u, GLColor::red);
6247     std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6248     std::vector<GLColor> texDataCyan(2u * 2u, GLColor::cyan);
6249 
6250     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6251     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6252 
6253     // Two levels that are initially unused.
6254     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6255     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6256                  texDataCyan.data());
6257 
6258     // One level that is used - only this level should affect completeness.
6259     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6260                  texDataGreen.data());
6261 
6262     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6263     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6264 
6265     EXPECT_GL_NO_ERROR();
6266 
6267     drawQuad(mProgram, "position", 0.5f);
6268 
6269     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6270 
6271     ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6272 
6273     // Switch the level that is being used to the cyan level 2.
6274     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
6275     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
6276 
6277     EXPECT_GL_NO_ERROR();
6278 
6279     drawQuad(mProgram, "position", 0.5f);
6280 
6281     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6282 }
6283 
6284 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
6285 // have images defined.
TEST_P(Texture3DTestES3,DrawWithLevelsOutsideRangeUndefined)6286 TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeUndefined)
6287 {
6288     glActiveTexture(GL_TEXTURE0);
6289     glBindTexture(GL_TEXTURE_3D, mTexture3D);
6290     std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6291     glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6292                  texDataGreen.data());
6293     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6294     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6295     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
6296     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
6297 
6298     EXPECT_GL_NO_ERROR();
6299 
6300     drawQuad(mProgram, "position", 0.5f);
6301 
6302     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6303 }
6304 
6305 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
6306 // dimensions that don't fit the images inside the range.
6307 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture3DTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)6308 TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
6309 {
6310     glActiveTexture(GL_TEXTURE0);
6311     glBindTexture(GL_TEXTURE_3D, mTexture3D);
6312     std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
6313     std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6314     std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
6315 
6316     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6317     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6318 
6319     // Two levels that are initially unused.
6320     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6321                  texDataRed.data());
6322     glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6323                  texDataCyan.data());
6324 
6325     // One level that is used - only this level should affect completeness.
6326     glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6327                  texDataGreen.data());
6328 
6329     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
6330     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
6331 
6332     EXPECT_GL_NO_ERROR();
6333 
6334     drawQuad(mProgram, "position", 0.5f);
6335 
6336     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6337 
6338     ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6339 
6340     // Switch the level that is being used to the cyan level 2.
6341     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 2);
6342     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 2);
6343 
6344     EXPECT_GL_NO_ERROR();
6345 
6346     drawQuad(mProgram, "position", 0.5f);
6347 
6348     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6349 }
6350 
6351 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
6352 // have images defined.
TEST_P(Texture2DArrayTestES3,DrawWithLevelsOutsideRangeUndefined)6353 TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeUndefined)
6354 {
6355     glActiveTexture(GL_TEXTURE0);
6356     glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6357     std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6358     glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6359                  texDataGreen.data());
6360     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6361     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6362     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
6363     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
6364 
6365     EXPECT_GL_NO_ERROR();
6366 
6367     drawQuad(mProgram, "position", 0.5f);
6368 
6369     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6370 }
6371 
6372 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
6373 // dimensions that don't fit the images inside the range.
6374 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DArrayTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)6375 TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
6376 {
6377     // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
6378     ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
6379 
6380     glActiveTexture(GL_TEXTURE0);
6381     glBindTexture(GL_TEXTURE_3D, m2DArrayTexture);
6382     std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
6383     std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6384     std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
6385 
6386     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6387     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6388 
6389     // Two levels that are initially unused.
6390     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6391                  texDataRed.data());
6392     glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6393                  texDataCyan.data());
6394 
6395     // One level that is used - only this level should affect completeness.
6396     glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6397                  texDataGreen.data());
6398 
6399     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
6400     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
6401 
6402     EXPECT_GL_NO_ERROR();
6403 
6404     drawQuad(mProgram, "position", 0.5f);
6405 
6406     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6407 
6408     ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6409 
6410     // Switch the level that is being used to the cyan level 2.
6411     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 2);
6412     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 2);
6413 
6414     EXPECT_GL_NO_ERROR();
6415 
6416     drawQuad(mProgram, "position", 0.5f);
6417 
6418     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6419 }
6420 
6421 // Create a 2D array, then immediately redefine it to have fewer layers.  Regression test for a bug
6422 // in the Vulkan backend where the old higher-layer-count data upload was not removed.
TEST_P(Texture2DArrayTestES3,TextureArrayRedefineThenUse)6423 TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse)
6424 {
6425     int px = getWindowWidth() / 2;
6426     int py = getWindowHeight() / 2;
6427 
6428     glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6429 
6430     // Fill the whole texture with red, then redefine it and fill with green
6431     std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
6432     std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
6433     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6434                  pixelsRed.data());
6435     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6436                  pixelsGreen.data());
6437 
6438     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6439     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6440     EXPECT_GL_NO_ERROR();
6441 
6442     glUseProgram(mProgram);
6443     EXPECT_GL_NO_ERROR();
6444 
6445     // Draw the first slice
6446     glUniform1i(mTextureArraySliceUniformLocation, 0);
6447     drawQuad(mProgram, "position", 0.5f);
6448     EXPECT_GL_NO_ERROR();
6449     EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6450 
6451     // Draw the second slice
6452     glUniform1i(mTextureArraySliceUniformLocation, 1);
6453     drawQuad(mProgram, "position", 0.5f);
6454     EXPECT_GL_NO_ERROR();
6455     EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6456 }
6457 
6458 // Create a 2D array texture and update layers with data and test that pruning
6459 // of superseded updates works as expected.
TEST_P(Texture2DArrayTestES3,TextureArrayPruneSupersededUpdates)6460 TEST_P(Texture2DArrayTestES3, TextureArrayPruneSupersededUpdates)
6461 {
6462     constexpr uint32_t kTexWidth  = 256;
6463     constexpr uint32_t kTexHeight = 256;
6464     constexpr uint32_t kTexLayers = 3;
6465 
6466     glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6467     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6468     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6469     EXPECT_GL_NO_ERROR();
6470 
6471     // Initialize entire texture.
6472     constexpr GLColor kInitialExpectedColor = GLColor(201u, 201u, 201u, 201u);
6473     std::vector<GLColor> initialData(kTexWidth * kTexHeight * kTexLayers, kInitialExpectedColor);
6474     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kTexWidth, kTexHeight, kTexLayers, 0, GL_RGBA,
6475                  GL_UNSIGNED_BYTE, initialData.data());
6476 
6477     // Upate different layers with different colors, these together should supersed
6478     // the entire init update
6479     constexpr GLColor kExpectedColor[] = {GLColor(32u, 32u, 32u, 32u), GLColor(64u, 64u, 64u, 64u),
6480                                           GLColor(128u, 128u, 128u, 128u)};
6481     std::vector<GLColor> supersedingData[] = {
6482         std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[0]),
6483         std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[1]),
6484         std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[2])};
6485 
6486     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kTexWidth, kTexHeight, 1, GL_RGBA,
6487                     GL_UNSIGNED_BYTE, supersedingData[0].data());
6488     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, kTexWidth, kTexHeight, 1, GL_RGBA,
6489                     GL_UNSIGNED_BYTE, supersedingData[1].data());
6490     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, kTexWidth, kTexHeight, 1, GL_RGBA,
6491                     GL_UNSIGNED_BYTE, supersedingData[2].data());
6492 
6493     glUseProgram(mProgram);
6494     EXPECT_GL_NO_ERROR();
6495 
6496     // Draw layer 0
6497     glUniform1i(mTextureArraySliceUniformLocation, 0);
6498     drawQuad(mProgram, "position", 0.5f);
6499     EXPECT_GL_NO_ERROR();
6500     EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[0]);
6501 
6502     // Draw layer 1
6503     glUniform1i(mTextureArraySliceUniformLocation, 1);
6504     drawQuad(mProgram, "position", 0.5f);
6505     EXPECT_GL_NO_ERROR();
6506     EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[1]);
6507 
6508     // Draw layer 2
6509     glUniform1i(mTextureArraySliceUniformLocation, 2);
6510     drawQuad(mProgram, "position", 0.5f);
6511     EXPECT_GL_NO_ERROR();
6512     EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[2]);
6513 }
6514 
6515 // Create a 2D array, use it, then redefine it to have fewer layers.  Regression test for a bug in
6516 // the Vulkan backend where the old higher-layer-count data upload was not removed.
TEST_P(Texture2DArrayTestES3,TextureArrayUseThenRedefineThenUse)6517 TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse)
6518 {
6519     int px = getWindowWidth() / 2;
6520     int py = getWindowHeight() / 2;
6521 
6522     glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6523 
6524     // Fill the whole texture with red.
6525     std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
6526     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6527                  pixelsRed.data());
6528 
6529     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6530     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6531     EXPECT_GL_NO_ERROR();
6532 
6533     glUseProgram(mProgram);
6534     EXPECT_GL_NO_ERROR();
6535 
6536     // Draw the first slice
6537     glUniform1i(mTextureArraySliceUniformLocation, 0);
6538     drawQuad(mProgram, "position", 0.5f);
6539     EXPECT_GL_NO_ERROR();
6540     EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
6541 
6542     // Draw the fourth slice
6543     glUniform1i(mTextureArraySliceUniformLocation, 3);
6544     drawQuad(mProgram, "position", 0.5f);
6545     EXPECT_GL_NO_ERROR();
6546     EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
6547 
6548     // Redefine the image and fill with green
6549     std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
6550     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6551                  pixelsGreen.data());
6552 
6553     // Draw the first slice
6554     glUniform1i(mTextureArraySliceUniformLocation, 0);
6555     drawQuad(mProgram, "position", 0.5f);
6556     EXPECT_GL_NO_ERROR();
6557     EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6558 
6559     // Draw the second slice
6560     glUniform1i(mTextureArraySliceUniformLocation, 1);
6561     drawQuad(mProgram, "position", 0.5f);
6562     EXPECT_GL_NO_ERROR();
6563     EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6564 }
6565 
6566 // Create a 2D array texture, use it, then redefine one level without changing dimensions.
TEST_P(Texture2DArrayTestES3,RedefineLevelData)6567 TEST_P(Texture2DArrayTestES3, RedefineLevelData)
6568 {
6569     glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6570 
6571     // Fill both levels with red
6572     std::vector<GLColor> pixelsRed(2 * 2 * 1, GLColor::red);
6573     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6574                  pixelsRed.data());
6575     glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6576                  pixelsRed.data());
6577     ASSERT_GL_NO_ERROR();
6578 
6579     // Check that both levels are red
6580     GLFramebuffer fbo;
6581     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6582     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
6583     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6584     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0);
6585     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6586 
6587     // Redefine level 1 with green
6588     glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6589                  &GLColor::green);
6590     ASSERT_GL_NO_ERROR();
6591 
6592     // Check that level 0 is red and level 1 is green
6593     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
6594     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6595     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0);
6596     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6597 }
6598 
6599 // Create a 3D texture, use it, then redefine one level without changing dimensions.
TEST_P(Texture3DTestES3,RedefineLevelData)6600 TEST_P(Texture3DTestES3, RedefineLevelData)
6601 {
6602     glBindTexture(GL_TEXTURE_3D, mTexture3D);
6603 
6604     // Fill both levels with red
6605     std::vector<GLColor> pixelsRed(2 * 2 * 1, GLColor::red);
6606     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6607                  pixelsRed.data());
6608     glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6609                  pixelsRed.data());
6610     ASSERT_GL_NO_ERROR();
6611 
6612     // Check that both levels are red
6613     GLFramebuffer fbo;
6614     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6615     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0);
6616     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6617     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0);
6618     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6619 
6620     // Redefine level 1 with green
6621     glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6622                  &GLColor::green);
6623     ASSERT_GL_NO_ERROR();
6624 
6625     // Check that level 0 is red and level 1 is green
6626     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0);
6627     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6628     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0);
6629     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6630 }
6631 
6632 // Test that texture completeness is updated if texture max level changes.
6633 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureCompletenessChangesWithMaxLevel)6634 TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
6635 {
6636     glActiveTexture(GL_TEXTURE0);
6637     glBindTexture(GL_TEXTURE_2D, mTexture2D);
6638     std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
6639 
6640     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6641     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6642 
6643     // A level that is initially unused.
6644     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6645                  texDataGreen.data());
6646 
6647     // One level that is initially used - only this level should affect completeness.
6648     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6649                  texDataGreen.data());
6650 
6651     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6652     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6653 
6654     EXPECT_GL_NO_ERROR();
6655 
6656     drawQuad(mProgram, "position", 0.5f);
6657 
6658     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6659 
6660     // Switch the max level to level 1. The levels within the used range now have inconsistent
6661     // dimensions and the texture should be incomplete.
6662     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6663 
6664     EXPECT_GL_NO_ERROR();
6665 
6666     drawQuad(mProgram, "position", 0.5f);
6667 
6668     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6669 }
6670 
6671 // Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly
6672 // keep the staged clear. http://anglebug.com/345532371
TEST_P(Texture2DArrayTestES3,ClearThenTexSubImageWithOverlappingLayersThenRead)6673 TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenRead)
6674 {
6675     constexpr GLsizei kTexWidth  = 128;
6676     constexpr GLsizei kTexHeight = 128;
6677     constexpr GLsizei kTexDepth  = 6;
6678     // Create a single leveled texture with 6 layers
6679     GLTexture tex;
6680     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
6681     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth);
6682 
6683     // Stage clear to red on all layers
6684     GLFramebuffer drawFBO;
6685     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
6686     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
6687     for (GLsizei layer = 0; layer < kTexDepth; layer++)
6688     {
6689         glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
6690         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
6691         glClear(GL_COLOR_BUFFER_BIT);
6692     }
6693 
6694     // TexSubImage with green color on half of the image of layer 2,3,4
6695     std::vector<GLColor> updateData((kTexWidth / 2) * kTexHeight * 3, GLColor::green);
6696     GLsizei layerStart = 2;
6697     GLsizei layerCount = 3;
6698     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerStart, kTexWidth / 2, kTexHeight, layerCount,
6699                     GL_RGBA, GL_UNSIGNED_BYTE, updateData.data());
6700 
6701     // Now read out layer 2/3/4
6702     GLFramebuffer readFBO;
6703     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
6704     for (GLsizei layer = layerStart; layer < layerStart + layerCount; layer++)
6705     {
6706         glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
6707         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
6708         EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::green.R, GLColor::green.G,
6709                         GLColor::green.B, GLColor::green.A);
6710         EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::red.R, GLColor::red.G,
6711                         GLColor::red.B, GLColor::red.A);
6712     }
6713     ASSERT_GL_NO_ERROR();
6714 }
6715 
6716 // Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly
6717 // keep the staged clear. http://anglebug.com/345532371
TEST_P(Texture2DArrayTestES3,ClearThenTexSubImageWithOverlappingLayersThenDrawAndRead)6718 TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenDrawAndRead)
6719 {
6720     constexpr GLsizei kTexWidth  = 128;
6721     constexpr GLsizei kTexHeight = 128;
6722     constexpr GLsizei kTexDepth  = 6;
6723     // Create a single leveled texture with 6 layers
6724     GLTexture tex;
6725     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
6726     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth);
6727 
6728     // Stage clear to red on all layers
6729     GLFramebuffer drawFBO;
6730     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
6731     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
6732     for (GLsizei layer = 0; layer < kTexDepth; layer++)
6733     {
6734         glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
6735         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
6736         glClear(GL_COLOR_BUFFER_BIT);
6737     }
6738 
6739     // TexSubImage with green color on half of the image of layer 2,3,4
6740     std::vector<GLColor> updateData((kTexWidth / 2) * kTexHeight * 3, GLColor::green);
6741     GLsizei layerStart = 2;
6742     GLsizei layerCount = 3;
6743     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerStart, kTexWidth / 2, kTexHeight, layerCount,
6744                     GL_RGBA, GL_UNSIGNED_BYTE, updateData.data());
6745 
6746     // Now Draw to fbo on layerStart with blue color
6747     GLsizei blueQuadLayer = 2;
6748     glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, blueQuadLayer);
6749     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
6750     glEnable(GL_BLEND);
6751     glBlendFunc(GL_ONE, GL_ONE);
6752     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Blue());
6753     glUseProgram(blueProgram);
6754     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f);
6755 
6756     // Now read out layer 2/3/4
6757     GLFramebuffer readFBO;
6758     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
6759     for (GLsizei layer = layerStart; layer < layerStart + layerCount; layer++)
6760     {
6761         glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
6762         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
6763         if (layer == blueQuadLayer)
6764         {
6765             // green + blue = cyan
6766             EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::cyan.R, GLColor::cyan.G,
6767                             GLColor::cyan.B, GLColor::cyan.A);
6768             // red + blue = magenta
6769             EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::magenta.R,
6770                             GLColor::magenta.G, GLColor::magenta.B, GLColor::magenta.A);
6771         }
6772         else
6773         {
6774             EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::green.R, GLColor::green.G,
6775                             GLColor::green.B, GLColor::green.A);
6776             EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::red.R, GLColor::red.G,
6777                             GLColor::red.B, GLColor::red.A);
6778         }
6779     }
6780     ASSERT_GL_NO_ERROR();
6781 }
6782 
6783 // Test that compressed textures ignore the pixel unpack state.
6784 // (https://crbug.org/1267496)
TEST_P(Texture3DTestES3,PixelUnpackStateTexImage)6785 TEST_P(Texture3DTestES3, PixelUnpackStateTexImage)
6786 {
6787     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
6788                        !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
6789 
6790     glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
6791     glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
6792 
6793     uint8_t data[64] = {0};
6794     glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
6795                            data);
6796     EXPECT_GL_NO_ERROR();
6797 }
6798 
6799 // Test that compressed textures ignore the pixel unpack state.
6800 // (https://crbug.org/1267496)
TEST_P(Texture3DTestES3,PixelUnpackStateTexSubImage)6801 TEST_P(Texture3DTestES3, PixelUnpackStateTexSubImage)
6802 {
6803     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
6804                        !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
6805 
6806     glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
6807 
6808     uint8_t data[64] = {0};
6809     glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
6810                            data);
6811     EXPECT_GL_NO_ERROR();
6812 
6813     glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
6814 
6815     glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 4,
6816                               GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, data);
6817     EXPECT_GL_NO_ERROR();
6818 }
6819 
6820 // Test that 3D texture completeness is updated if texture max level changes.
6821 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture3DTestES3,Texture3DCompletenessChangesWithMaxLevel)6822 TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel)
6823 {
6824     glActiveTexture(GL_TEXTURE0);
6825     glBindTexture(GL_TEXTURE_3D, mTexture3D);
6826     std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6827 
6828     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6829     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6830 
6831     // A level that is initially unused.
6832     glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6833                  texDataGreen.data());
6834 
6835     // One level that is initially used - only this level should affect completeness.
6836     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6837                  texDataGreen.data());
6838 
6839     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
6840     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
6841 
6842     EXPECT_GL_NO_ERROR();
6843 
6844     drawQuad(mProgram, "position", 0.5f);
6845 
6846     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6847 
6848     // Switch the max level to level 1. The levels within the used range now have inconsistent
6849     // dimensions and the texture should be incomplete.
6850     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
6851 
6852     EXPECT_GL_NO_ERROR();
6853 
6854     drawQuad(mProgram, "position", 0.5f);
6855 
6856     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6857 }
6858 
6859 // Test that texture completeness is updated if texture base level changes.
6860 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureCompletenessChangesWithBaseLevel)6861 TEST_P(Texture2DTestES3, TextureCompletenessChangesWithBaseLevel)
6862 {
6863     glActiveTexture(GL_TEXTURE0);
6864     glBindTexture(GL_TEXTURE_2D, mTexture2D);
6865     std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
6866 
6867     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6868     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6869 
6870     // Two levels that are initially unused.
6871     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6872                  texDataGreen.data());
6873     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6874                  texDataGreen.data());
6875 
6876     // One level that is initially used - only this level should affect completeness.
6877     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6878                  texDataGreen.data());
6879 
6880     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
6881     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
6882 
6883     EXPECT_GL_NO_ERROR();
6884 
6885     drawQuad(mProgram, "position", 0.5f);
6886 
6887     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6888 
6889     // Switch the base level to level 1. The levels within the used range now have inconsistent
6890     // dimensions and the texture should be incomplete.
6891     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6892 
6893     EXPECT_GL_NO_ERROR();
6894 
6895     drawQuad(mProgram, "position", 0.5f);
6896 
6897     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6898 }
6899 
6900 // Test that texture is not complete if base level is greater than max level.
6901 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureBaseLevelGreaterThanMaxLevel)6902 TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMaxLevel)
6903 {
6904     glActiveTexture(GL_TEXTURE0);
6905     glBindTexture(GL_TEXTURE_2D, mTexture2D);
6906 
6907     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6908     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6909 
6910     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
6911 
6912     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
6913     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6914 
6915     EXPECT_GL_NO_ERROR();
6916 
6917     drawQuad(mProgram, "position", 0.5f);
6918 
6919     // Texture should be incomplete.
6920     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6921 }
6922 
6923 // Test that immutable texture base level and max level are clamped.
6924 // GLES 3.0.4 section 3.8.10 subsection Mipmapping
TEST_P(Texture2DTestES3,ImmutableTextureBaseLevelOutOfRange)6925 TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange)
6926 {
6927     glActiveTexture(GL_TEXTURE0);
6928     glBindTexture(GL_TEXTURE_2D, mTexture2D);
6929 
6930     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6931     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6932 
6933     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
6934 
6935     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
6936 
6937     // For immutable-format textures, base level should be clamped to [0, levels - 1], and max level
6938     // should be clamped to [base_level, levels - 1].
6939     // GLES 3.0.4 section 3.8.10 subsection Mipmapping
6940     // In the case of this test, those rules make the effective base level and max level 0.
6941     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
6942     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
6943 
6944     EXPECT_GL_NO_ERROR();
6945 
6946     drawQuad(mProgram, "position", 0.5f);
6947 
6948     // Texture should be complete.
6949     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6950 }
6951 
6952 // Test that changing base level works when it affects the format of the texture.
TEST_P(Texture2DTestES3,TextureFormatChangesWithBaseLevel)6953 TEST_P(Texture2DTestES3, TextureFormatChangesWithBaseLevel)
6954 {
6955     // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
6956     ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
6957 
6958     ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL());
6959 
6960     // Observed incorrect rendering on AMD OpenGL.
6961     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
6962 
6963     glActiveTexture(GL_TEXTURE0);
6964     glBindTexture(GL_TEXTURE_2D, mTexture2D);
6965     std::vector<GLColor> texDataCyan(4u * 4u, GLColor::cyan);
6966     std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6967 
6968     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6969     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6970 
6971     // RGBA8 level that's initially unused.
6972     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6973                  texDataCyan.data());
6974 
6975     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6976     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6977 
6978     // RG8 level that's initially used, with consistent dimensions with level 0 but a different
6979     // format. It reads green channel data from the green and alpha channels of texDataGreen
6980     // (this is a bit hacky but works).
6981     glTexImage2D(GL_TEXTURE_2D, 1, GL_RG8, 2, 2, 0, GL_RG, GL_UNSIGNED_BYTE, texDataGreen.data());
6982 
6983     EXPECT_GL_NO_ERROR();
6984 
6985     drawQuad(mProgram, "position", 0.5f);
6986 
6987     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6988 
6989     // Switch the texture to use the cyan level 0 with the RGBA format.
6990     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6991     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6992 
6993     EXPECT_GL_NO_ERROR();
6994 
6995     drawQuad(mProgram, "position", 0.5f);
6996 
6997     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6998 }
6999 
7000 // Test that setting a texture image works when base level is out of range.
TEST_P(Texture2DTestES3,SetImageWhenBaseLevelOutOfRange)7001 TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange)
7002 {
7003     glActiveTexture(GL_TEXTURE0);
7004     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7005 
7006     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7007     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7008 
7009     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
7010     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
7011 
7012     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
7013 
7014     EXPECT_GL_NO_ERROR();
7015 
7016     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7017 
7018     drawQuad(mProgram, "position", 0.5f);
7019 
7020     // Texture should be complete.
7021     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7022 }
7023 
7024 // In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG
7025 // RBA->RGBA8, with 1.0 in the alpha channel. This test covers a bug where redefining array textures
7026 // with these formats does not work as expected.
TEST_P(Texture2DArrayTestES3,RedefineInittableArray)7027 TEST_P(Texture2DArrayTestES3, RedefineInittableArray)
7028 {
7029     std::vector<GLubyte> pixelData;
7030     for (size_t count = 0; count < 5000; count++)
7031     {
7032         pixelData.push_back(0u);
7033         pixelData.push_back(255u);
7034         pixelData.push_back(0u);
7035     }
7036 
7037     glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
7038     glUseProgram(mProgram);
7039     glUniform1i(mTextureArrayLocation, 0);
7040 
7041     // The first draw worked correctly.
7042     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
7043                  &pixelData[0]);
7044 
7045     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7046     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7047     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
7048     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
7049     drawQuad(mProgram, "position", 1.0f);
7050     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7051 
7052     // The dimension of the respecification must match the original exactly to trigger the bug.
7053     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
7054                  &pixelData[0]);
7055     drawQuad(mProgram, "position", 1.0f);
7056     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7057 
7058     ASSERT_GL_NO_ERROR();
7059 }
7060 
7061 // Test shadow sampler and regular non-shadow sampler coexisting in the same shader.
7062 // This test is needed especially to confirm that sampler registers get assigned correctly on
7063 // the HLSL backend even when there's a mix of different HLSL sampler and texture types.
TEST_P(ShadowSamplerPlusSampler3DTestES3,ShadowSamplerPlusSampler3DDraw)7064 TEST_P(ShadowSamplerPlusSampler3DTestES3, ShadowSamplerPlusSampler3DDraw)
7065 {
7066     glActiveTexture(GL_TEXTURE0);
7067     glBindTexture(GL_TEXTURE_3D, mTexture3D);
7068     GLubyte texData[4];
7069     texData[0] = 0;
7070     texData[1] = 60;
7071     texData[2] = 0;
7072     texData[3] = 255;
7073     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7074 
7075     glActiveTexture(GL_TEXTURE1);
7076     glBindTexture(GL_TEXTURE_2D, mTextureShadow);
7077     GLfloat depthTexData[1];
7078     depthTexData[0] = 0.5f;
7079     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
7080                  depthTexData);
7081 
7082     glUseProgram(mProgram);
7083     glUniform1f(mDepthRefUniformLocation, 0.3f);
7084     glUniform1i(mTexture3DUniformLocation, 0);
7085     glUniform1i(mTextureShadowUniformLocation, 1);
7086 
7087     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
7088     drawQuad(mProgram, "position", 0.5f);
7089     EXPECT_GL_NO_ERROR();
7090     // The shader writes 0.5 * <comparison result (1.0)> + <texture color>
7091     EXPECT_PIXEL_NEAR(0, 0, 128, 188, 128, 255, 2);
7092 
7093     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);
7094     drawQuad(mProgram, "position", 0.5f);
7095     EXPECT_GL_NO_ERROR();
7096     // The shader writes 0.5 * <comparison result (0.0)> + <texture color>
7097     EXPECT_PIXEL_NEAR(0, 0, 0, 60, 0, 255, 2);
7098 }
7099 
7100 // Test multiple different sampler types in the same shader.
7101 // This test makes sure that even if sampler / texture registers get grouped together based on type
7102 // or otherwise get shuffled around in the HLSL backend of the shader translator, the D3D renderer
7103 // still has the right register index information for each ESSL sampler.
7104 // The tested ESSL samplers have the following types in D3D11 HLSL:
7105 // sampler2D:         Texture2D   + SamplerState
7106 // samplerCube:       TextureCube + SamplerState
7107 // sampler2DShadow:   Texture2D   + SamplerComparisonState
7108 // samplerCubeShadow: TextureCube + SamplerComparisonState
TEST_P(SamplerTypeMixTestES3,SamplerTypeMixDraw)7109 TEST_P(SamplerTypeMixTestES3, SamplerTypeMixDraw)
7110 {
7111     glActiveTexture(GL_TEXTURE0);
7112     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7113     GLubyte texData[4];
7114     texData[0] = 0;
7115     texData[1] = 0;
7116     texData[2] = 120;
7117     texData[3] = 255;
7118     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7119 
7120     glActiveTexture(GL_TEXTURE1);
7121     glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
7122     texData[0] = 0;
7123     texData[1] = 90;
7124     texData[2] = 0;
7125     texData[3] = 255;
7126     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
7127     glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
7128                     texData);
7129 
7130     glActiveTexture(GL_TEXTURE2);
7131     glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
7132     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
7133     GLfloat depthTexData[1];
7134     depthTexData[0] = 0.5f;
7135     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
7136                  depthTexData);
7137 
7138     glActiveTexture(GL_TEXTURE3);
7139     glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
7140     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
7141     depthTexData[0] = 0.2f;
7142     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT32F, 1, 1);
7143     glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT,
7144                     depthTexData);
7145 
7146     // http://anglebug.com/3949: TODO: Add a DS texture case
7147 
7148     EXPECT_GL_NO_ERROR();
7149 
7150     glUseProgram(mProgram);
7151     glUniform1f(mDepthRefUniformLocation, 0.3f);
7152     glUniform1i(mTexture2DUniformLocation, 0);
7153     glUniform1i(mTextureCubeUniformLocation, 1);
7154     glUniform1i(mTexture2DShadowUniformLocation, 2);
7155     glUniform1i(mTextureCubeShadowUniformLocation, 3);
7156 
7157     drawQuad(mProgram, "position", 0.5f);
7158     EXPECT_GL_NO_ERROR();
7159     // The shader writes:
7160     // <texture 2d color> +
7161     // <cube map color> +
7162     // 0.25 * <comparison result (1.0)> +
7163     // 0.125 * <comparison result (0.0)>
7164     EXPECT_PIXEL_NEAR(0, 0, 64, 154, 184, 255, 2);
7165 }
7166 
7167 // Test different base levels on textures accessed through the same sampler array.
7168 // Calling textureSize() on the samplers hits the D3D sampler metadata workaround.
TEST_P(TextureSizeTextureArrayTest,BaseLevelVariesInTextureArray)7169 TEST_P(TextureSizeTextureArrayTest, BaseLevelVariesInTextureArray)
7170 {
7171     ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D11());
7172 
7173     // http://anglebug.com/4391
7174     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsWindows() && IsD3D11());
7175 
7176     glActiveTexture(GL_TEXTURE0);
7177     glBindTexture(GL_TEXTURE_2D, mTexture2DA);
7178     GLsizei size = 64;
7179     for (GLint level = 0; level < 7; ++level)
7180     {
7181         ASSERT_LT(0, size);
7182         glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7183                      nullptr);
7184         size = size / 2;
7185     }
7186     ASSERT_EQ(0, size);
7187     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
7188 
7189     glActiveTexture(GL_TEXTURE1);
7190     glBindTexture(GL_TEXTURE_2D, mTexture2DB);
7191     size = 128;
7192     for (GLint level = 0; level < 8; ++level)
7193     {
7194         ASSERT_LT(0, size);
7195         glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7196                      nullptr);
7197         size = size / 2;
7198     }
7199     ASSERT_EQ(0, size);
7200     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 3);
7201     EXPECT_GL_NO_ERROR();
7202 
7203     glUseProgram(mProgram);
7204     glUniform1i(mTexture0Location, 0);
7205     glUniform1i(mTexture1Location, 1);
7206 
7207     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
7208     EXPECT_GL_NO_ERROR();
7209     // Red channel: width of level 1 of texture A: 32.
7210     // Green channel: width of level 3 of texture B: 16.
7211     EXPECT_PIXEL_NEAR(0, 0, 32, 16, 0, 255, 2);
7212 }
7213 
7214 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7215 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBImplicitAlpha1)7216 TEST_P(Texture2DTestES3, TextureRGBImplicitAlpha1)
7217 {
7218     glActiveTexture(GL_TEXTURE0);
7219     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7220     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
7221     EXPECT_GL_NO_ERROR();
7222 
7223     drawQuad(mProgram, "position", 0.5f);
7224 
7225     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7226 }
7227 
7228 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7229 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBXImplicitAlpha1)7230 TEST_P(Texture2DTestES3, TextureRGBXImplicitAlpha1)
7231 {
7232     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
7233 
7234     GLTexture texture2D;
7235     glBindTexture(GL_TEXTURE_2D, texture2D);
7236     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBX8_ANGLE, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
7237     glActiveTexture(GL_TEXTURE0);
7238     EXPECT_GL_NO_ERROR();
7239 
7240     drawQuad(mProgram, "position", 0.5f);
7241 
7242     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7243 }
7244 
7245 // Test that data upload to RGBX works.
TEST_P(Texture2DTestES3,TextureRGBXUpload)7246 TEST_P(Texture2DTestES3, TextureRGBXUpload)
7247 {
7248     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
7249 
7250     const size_t kWidth  = 32;
7251     const size_t kHeight = 32;
7252 
7253     GLTexture color;
7254     glBindTexture(GL_TEXTURE_2D, color);
7255     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
7256 
7257     GLFramebuffer fbo;
7258     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7259     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
7260     ASSERT_GL_NO_ERROR();
7261     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7262 
7263     // Upload data to an RGBX texture
7264     const GLColorRGB kColor(100, 200, 55);
7265     std::vector<GLColorRGB> data(kWidth * kHeight, kColor);
7266 
7267     GLTexture texture;
7268     glBindTexture(GL_TEXTURE_2D, texture);
7269     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight);
7270     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7271     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7272     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, data.data());
7273     ASSERT_GL_NO_ERROR();
7274 
7275     // Sample from the texture
7276     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7277     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
7278 
7279     const GLColor kExpect(kColor.R, kColor.G, kColor.B, 255);
7280     EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
7281     EXPECT_PIXEL_COLOR_NEAR(0, 1, kExpect, 1);
7282     EXPECT_PIXEL_COLOR_NEAR(1, 0, kExpect, 1);
7283     EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, kExpect, 1);
7284     EXPECT_PIXEL_COLOR_NEAR(0, kHeight - 1, kExpect, 1);
7285     EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, kExpect, 1);
7286     EXPECT_PIXEL_COLOR_NEAR(kWidth / 2, kHeight / 2, kExpect, 1);
7287     ASSERT_GL_NO_ERROR();
7288 }
7289 
7290 // Test that data download from RGBX works.
TEST_P(Texture2DTestES3,TextureRGBXDownload)7291 TEST_P(Texture2DTestES3, TextureRGBXDownload)
7292 {
7293     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
7294 
7295     const size_t kWidth  = 32;
7296     const size_t kHeight = 32;
7297 
7298     GLTexture color;
7299     glBindTexture(GL_TEXTURE_2D, color);
7300     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight);
7301 
7302     GLFramebuffer fbo;
7303     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7304     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
7305     ASSERT_GL_NO_ERROR();
7306     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7307 
7308     // Render to the RGBX texture
7309     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7310     glUseProgram(program);
7311     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7312     ASSERT_NE(colorLoc, -1);
7313 
7314     glUniform4f(colorLoc, 0.3f, 0.6f, 0.8f, 0.2f);
7315     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
7316     ASSERT_GL_NO_ERROR();
7317 
7318     // Readback as RGBX.
7319     std::vector<GLColor> readback(kWidth * kHeight);
7320     glReadPixels(0, 0, kWidth, kHeight, GL_RGBX8_ANGLE, GL_UNSIGNED_BYTE, readback.data());
7321     ASSERT_GL_NO_ERROR();
7322 
7323     const GLColor kExpect(76,   // 0.3f * 255
7324                           153,  // 0.6f * 255
7325                           204,  // 0.8f * 255
7326                           255);
7327 
7328     for (size_t y = 0; y < kHeight; y++)
7329     {
7330         for (size_t x = 0; x < kWidth; x++)
7331         {
7332             const GLColor actualColor = readback[y * kWidth + x];
7333 
7334             EXPECT_NEAR(actualColor.R, kExpect.R, 1) << x << "x" << y;
7335             EXPECT_NEAR(actualColor.G, kExpect.G, 1) << x << "x" << y;
7336             EXPECT_NEAR(actualColor.B, kExpect.B, 1) << x << "x" << y;
7337             EXPECT_EQ(actualColor.A, kExpect.A) << x << "x" << y;
7338         }
7339     }
7340     ASSERT_GL_NO_ERROR();
7341 }
7342 
7343 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7344 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminanceImplicitAlpha1)7345 TEST_P(Texture2DTest, TextureLuminanceImplicitAlpha1)
7346 {
7347     setUpProgram();
7348 
7349     glActiveTexture(GL_TEXTURE0);
7350     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7351     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
7352     EXPECT_GL_NO_ERROR();
7353 
7354     drawQuad(mProgram, "position", 0.5f);
7355 
7356     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7357 }
7358 
7359 // Validate that every component of the pixel will be equal to the luminance value we've set
7360 // and that the alpha channel will be 1 (or 255 to be exact).
TEST_P(Texture2DTest,TextureLuminanceRGBSame)7361 TEST_P(Texture2DTest, TextureLuminanceRGBSame)
7362 {
7363     setUpProgram();
7364 
7365     glActiveTexture(GL_TEXTURE0);
7366     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7367     uint8_t pixel = 50;
7368     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pixel);
7369     EXPECT_GL_NO_ERROR();
7370 
7371     drawQuad(mProgram, "position", 0.5f);
7372 
7373     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel, pixel, pixel, 255));
7374 }
7375 
7376 // Validate that every component of the pixel will be equal to the luminance value we've set
7377 // and that the alpha channel will be the second component.
TEST_P(Texture2DTest,TextureLuminanceAlphaRGBSame)7378 TEST_P(Texture2DTest, TextureLuminanceAlphaRGBSame)
7379 {
7380     setUpProgram();
7381 
7382     glActiveTexture(GL_TEXTURE0);
7383     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7384     uint8_t pixel[] = {50, 25};
7385     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 1, 1, 0, GL_LUMINANCE_ALPHA,
7386                  GL_UNSIGNED_BYTE, pixel);
7387     EXPECT_GL_NO_ERROR();
7388 
7389     drawQuad(mProgram, "position", 0.5f);
7390 
7391     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel[0], pixel[0], pixel[0], pixel[1]));
7392 }
7393 
7394 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7395 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminance32ImplicitAlpha1)7396 TEST_P(Texture2DTest, TextureLuminance32ImplicitAlpha1)
7397 {
7398     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
7399     ANGLE_SKIP_TEST_IF(IsD3D9());
7400     ANGLE_SKIP_TEST_IF(IsVulkan());
7401 
7402     setUpProgram();
7403 
7404     glActiveTexture(GL_TEXTURE0);
7405     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7406     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_FLOAT, nullptr);
7407     EXPECT_GL_NO_ERROR();
7408 
7409     drawQuad(mProgram, "position", 0.5f);
7410 
7411     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7412 }
7413 
7414 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7415 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminance16ImplicitAlpha1)7416 TEST_P(Texture2DTest, TextureLuminance16ImplicitAlpha1)
7417 {
7418     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
7419     ANGLE_SKIP_TEST_IF(IsD3D9());
7420     ANGLE_SKIP_TEST_IF(IsVulkan());
7421     // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1420 is fixed
7422     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
7423 
7424     setUpProgram();
7425 
7426     glActiveTexture(GL_TEXTURE0);
7427     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7428     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, nullptr);
7429     EXPECT_GL_NO_ERROR();
7430 
7431     drawQuad(mProgram, "position", 0.5f);
7432 
7433     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7434 }
7435 
7436 // Test that CopyTexImage2D does not trigger assertion after CompressedTexImage2D.
7437 // https://crbug.com/1216276
TEST_P(Texture2DTest,CopyAfterCompressed)7438 TEST_P(Texture2DTest, CopyAfterCompressed)
7439 {
7440     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
7441 
7442     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7443     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8, nullptr);
7444     EXPECT_GL_NO_ERROR();
7445 
7446     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 0, 0, 4, 4, 0);
7447     EXPECT_GL_NO_ERROR();
7448 }
7449 
7450 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7451 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB8UIImplicitAlpha1)7452 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB8UIImplicitAlpha1)
7453 {
7454     ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7455 
7456     glActiveTexture(GL_TEXTURE0);
7457     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7458     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, nullptr);
7459     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7460     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7461     EXPECT_GL_NO_ERROR();
7462 
7463     drawQuad(mProgram, "position", 0.5f);
7464 
7465     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7466 }
7467 
7468 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7469 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB8IImplicitAlpha1)7470 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB8IImplicitAlpha1)
7471 {
7472     ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7473 
7474     glActiveTexture(GL_TEXTURE0);
7475     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7476 
7477     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8I, 1, 1, 0, GL_RGB_INTEGER, GL_BYTE, nullptr);
7478     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7479     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7480     EXPECT_GL_NO_ERROR();
7481 
7482     drawQuad(mProgram, "position", 0.5f);
7483 
7484     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7485 }
7486 
7487 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7488 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB16UIImplicitAlpha1)7489 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB16UIImplicitAlpha1)
7490 {
7491     ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7492 
7493     glActiveTexture(GL_TEXTURE0);
7494     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7495     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, nullptr);
7496     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7497     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7498     EXPECT_GL_NO_ERROR();
7499 
7500     drawQuad(mProgram, "position", 0.5f);
7501 
7502     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7503 }
7504 
7505 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7506 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB16IImplicitAlpha1)7507 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB16IImplicitAlpha1)
7508 {
7509     ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7510 
7511     glActiveTexture(GL_TEXTURE0);
7512     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7513     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16I, 1, 1, 0, GL_RGB_INTEGER, GL_SHORT, nullptr);
7514     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7515     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7516     EXPECT_GL_NO_ERROR();
7517 
7518     drawQuad(mProgram, "position", 0.5f);
7519 
7520     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7521 }
7522 
7523 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7524 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB32UIImplicitAlpha1)7525 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB32UIImplicitAlpha1)
7526 {
7527     ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7528 
7529     glActiveTexture(GL_TEXTURE0);
7530     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7531     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, nullptr);
7532     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7533     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7534     EXPECT_GL_NO_ERROR();
7535 
7536     drawQuad(mProgram, "position", 0.5f);
7537 
7538     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7539 }
7540 
7541 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7542 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB32IImplicitAlpha1)7543 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB32IImplicitAlpha1)
7544 {
7545     ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7546 
7547     glActiveTexture(GL_TEXTURE0);
7548     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7549     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, nullptr);
7550     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7551     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7552     EXPECT_GL_NO_ERROR();
7553 
7554     drawQuad(mProgram, "position", 0.5f);
7555 
7556     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7557 }
7558 
7559 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7560 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBSNORMImplicitAlpha1)7561 TEST_P(Texture2DTestES3, TextureRGBSNORMImplicitAlpha1)
7562 {
7563     glActiveTexture(GL_TEXTURE0);
7564     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7565     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8_SNORM, 1, 1, 0, GL_RGB, GL_BYTE, nullptr);
7566     EXPECT_GL_NO_ERROR();
7567 
7568     drawQuad(mProgram, "position", 0.5f);
7569 
7570     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7571 }
7572 
7573 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7574 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGB9E5ImplicitAlpha1)7575 TEST_P(Texture2DTestES3, TextureRGB9E5ImplicitAlpha1)
7576 {
7577     glActiveTexture(GL_TEXTURE0);
7578     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7579     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV,
7580                  nullptr);
7581     EXPECT_GL_NO_ERROR();
7582 
7583     drawQuad(mProgram, "position", 0.5f);
7584 
7585     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7586 }
7587 
7588 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7589 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)7590 TEST_P(Texture2DTestES3, TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)
7591 {
7592     // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
7593     ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
7594 
7595     glActiveTexture(GL_TEXTURE0);
7596     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7597     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 1, 1, 0, 8, nullptr);
7598     EXPECT_GL_NO_ERROR();
7599 
7600     drawQuad(mProgram, "position", 0.5f);
7601 
7602     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7603 }
7604 
7605 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7606 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)7607 TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)
7608 {
7609     // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
7610     ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
7611 
7612     glActiveTexture(GL_TEXTURE0);
7613     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7614     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, 1, 1, 0, 8, nullptr);
7615     EXPECT_GL_NO_ERROR();
7616 
7617     drawQuad(mProgram, "position", 0.5f);
7618 
7619     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7620 }
7621 
7622 // ETC2 punchthrough alpha formats must be initialized to opaque black when emulated
7623 // http://anglebug.com/6936
TEST_P(Texture2DTestES3RobustInit,TextureCOMPRESSEDRGB8A1ETC2)7624 TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDRGB8A1ETC2)
7625 {
7626     glActiveTexture(GL_TEXTURE0);
7627     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7628     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0,
7629                            8, nullptr);
7630     EXPECT_GL_NO_ERROR();
7631 
7632     drawQuad(mProgram, "position", 0.5f);
7633 
7634     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7635 }
7636 
7637 // ETC2 punchthrough alpha formats must be initialized to opaque black when emulated
7638 // http://anglebug.com/6936
TEST_P(Texture2DTestES3RobustInit,TextureCOMPRESSEDSRGB8A1ETC2)7639 TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDSRGB8A1ETC2)
7640 {
7641     glActiveTexture(GL_TEXTURE0);
7642     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7643     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0,
7644                            8, nullptr);
7645     EXPECT_GL_NO_ERROR();
7646 
7647     drawQuad(mProgram, "position", 0.5f);
7648 
7649     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7650 }
7651 
7652 // Test that compressed textures ignore the pixel unpack state.
7653 // (https://crbug.org/1267496)
TEST_P(Texture2DTestES3,PixelUnpackStateTexImage)7654 TEST_P(Texture2DTestES3, PixelUnpackStateTexImage)
7655 {
7656     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
7657                        !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
7658 
7659     glPixelStorei(GL_UNPACK_ROW_LENGTH, 9);
7660     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7661 
7662     uint8_t data[64] = {0};
7663     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data);
7664     EXPECT_GL_NO_ERROR();
7665 }
7666 
7667 // Test that compressed textures ignore the pixel unpack state.
7668 // (https://crbug.org/1267496)
TEST_P(Texture2DTestES3,PixelUnpackStateTexSubImage)7669 TEST_P(Texture2DTestES3, PixelUnpackStateTexSubImage)
7670 {
7671     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
7672                        !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
7673 
7674     glBindTexture(GL_TEXTURE_2D, mTexture2D);
7675 
7676     uint8_t data[64] = {0};
7677     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data);
7678     EXPECT_GL_NO_ERROR();
7679 
7680     glPixelStorei(GL_UNPACK_ROW_LENGTH, 9);
7681 
7682     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64,
7683                               data);
7684     EXPECT_GL_NO_ERROR();
7685 }
7686 
7687 // Test for http://anglebug.com/6926.
TEST_P(Texture2DTestES3,TextureRGBUpdateWithPBO)7688 TEST_P(Texture2DTestES3, TextureRGBUpdateWithPBO)
7689 {
7690     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7691 
7692     glViewport(0, 0, 16, 16);
7693 
7694     GLTexture tex1;
7695     std::vector<GLColor> texDataRed(16u * 16u, GLColor::red);
7696     std::vector<GLColor> texDataGreen(16u * 16u, GLColor::green);
7697 
7698     glBindTexture(GL_TEXTURE_2D, tex1);
7699     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
7700     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, texDataRed.data());
7701     ASSERT_GL_NO_ERROR();
7702 
7703     GLBuffer pbo;
7704     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
7705     glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, texDataGreen.data(), GL_STATIC_DRAW);
7706     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
7707     ASSERT_GL_NO_ERROR();
7708 
7709     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
7710     ASSERT_GL_NO_ERROR();
7711 
7712     glBindTexture(GL_TEXTURE_2D, 0);
7713     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
7714     EXPECT_PIXEL_COLOR_EQ(4, 4, GLColor::green);
7715 }
7716 
7717 // Copied from Texture2DTest::TexStorage
7718 // Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
7719 // default color.
TEST_P(Texture2DTestES31PPO,TexStorage)7720 TEST_P(Texture2DTestES31PPO, TexStorage)
7721 {
7722     ANGLE_SKIP_TEST_IF(!IsVulkan());
7723     ANGLE_SKIP_TEST_IF((getClientMajorVersion() < 3 && getClientMinorVersion() < 1) &&
7724                        !IsGLExtensionEnabled("GL_EXT_texture_storage"));
7725 
7726     const char *vertexShaderSource   = getVertexShaderSource();
7727     const char *fragmentShaderSource = getFragmentShaderSource();
7728 
7729     bindProgramPipeline(vertexShaderSource, fragmentShaderSource);
7730     mTexture2DUniformLocation = glGetUniformLocation(mFragProg, getTextureUniformName());
7731 
7732     int width  = getWindowWidth();
7733     int height = getWindowHeight();
7734 
7735     GLTexture tex2D;
7736     glActiveTexture(GL_TEXTURE0);
7737     glBindTexture(GL_TEXTURE_2D, tex2D);
7738 
7739     // Fill with red
7740     std::vector<GLubyte> pixels(3 * 16 * 16);
7741     for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
7742     {
7743         pixels[pixelId * 3 + 0] = 255;
7744         pixels[pixelId * 3 + 1] = 0;
7745         pixels[pixelId * 3 + 2] = 0;
7746     }
7747 
7748     // ANGLE internally uses RGBA as the internal format for RGB images, therefore glTexStorage2DEXT
7749     // initializes the image to a default color to get a consistent alpha color. The data is kept in
7750     // a CPU-side image and the image is marked as dirty.
7751     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
7752 
7753     // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
7754     // glTexSubImage2D should take into account that the image is dirty.
7755     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
7756     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7757     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7758 
7759     glActiveShaderProgram(mPipeline, mFragProg);
7760     glUniform1i(mTexture2DUniformLocation, 0);
7761 
7762     std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
7763     ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7764 
7765     EXPECT_GL_NO_ERROR();
7766     EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
7767 
7768     // Validate that the region of the texture without data has an alpha of 1.0
7769     angle::GLColor pixel = ReadColor(3 * width / 4, 3 * height / 4);
7770     EXPECT_EQ(255, pixel.A);
7771 }
7772 
7773 // Copied from Texture2DTestES3::SingleTextureMultipleSamplers
7774 // Tests behaviour with a single texture and multiple sampler objects.
TEST_P(Texture2DTestES31PPO,SingleTextureMultipleSamplers)7775 TEST_P(Texture2DTestES31PPO, SingleTextureMultipleSamplers)
7776 {
7777     ANGLE_SKIP_TEST_IF(!IsVulkan());
7778 
7779     const char *vertexShaderSource   = getVertexShaderSource();
7780     const char *fragmentShaderSource = getFragmentShaderSource();
7781 
7782     bindProgramPipeline(vertexShaderSource, fragmentShaderSource);
7783     mTexture2DUniformLocation = glGetUniformLocation(mFragProg, getTextureUniformName());
7784 
7785     GLint maxTextureUnits = 0;
7786     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
7787     ANGLE_SKIP_TEST_IF(maxTextureUnits < 4);
7788 
7789     constexpr int kSize                 = 16;
7790     std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
7791 
7792     // Make a single-level texture, fill it with red.
7793     std::vector<GLColor> redColors(kSize * kSize, GLColor::red);
7794     GLTexture tex;
7795     glBindTexture(GL_TEXTURE_2D, tex);
7796     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7797                  redColors.data());
7798     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7799     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7800 
7801     // Simple confidence check.
7802     bind2DTexturedQuadProgramPipeline();
7803     ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7804     ASSERT_GL_NO_ERROR();
7805     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7806 
7807     // Bind texture to unit 1 with a sampler object making it incomplete.
7808     GLSampler sampler;
7809     glBindSampler(0, sampler);
7810     glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
7811     glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7812 
7813     // Make a mipmap texture, fill it with blue.
7814     std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
7815     GLTexture mipmapTex;
7816     glBindTexture(GL_TEXTURE_2D, mipmapTex);
7817     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7818                  blueColors.data());
7819     glGenerateMipmap(GL_TEXTURE_2D);
7820 
7821     // Draw with the sampler, expect blue.
7822     draw2DTexturedQuad(0.5f, 1.0f, true);
7823     ASSERT_GL_NO_ERROR();
7824     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
7825 
7826     // Simple multitexturing program.
7827     constexpr char kVS[] =
7828         "#version 310 es\n"
7829         "precision mediump float;\n"
7830         "in vec2 position;\n"
7831         "out vec2 texCoord;\n"
7832         "void main()\n"
7833         "{\n"
7834         "    gl_Position = vec4(position, 0, 1);\n"
7835         "    texCoord = position * 0.5 + vec2(0.5);\n"
7836         "}";
7837 
7838     constexpr char kFS[] =
7839         "#version 310 es\n"
7840         "precision mediump float;\n"
7841         "in vec2 texCoord;\n"
7842         "uniform sampler2D tex1;\n"
7843         "uniform sampler2D tex2;\n"
7844         "uniform sampler2D tex3;\n"
7845         "uniform sampler2D tex4;\n"
7846         "out vec4 color;\n"
7847         "void main()\n"
7848         "{\n"
7849         "    color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
7850         "          +  texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
7851         "}";
7852 
7853     bindProgramPipeline(kVS, kFS);
7854 
7855     std::array<GLint, 4> texLocations = {
7856         {glGetUniformLocation(mFragProg, "tex1"), glGetUniformLocation(mFragProg, "tex2"),
7857          glGetUniformLocation(mFragProg, "tex3"), glGetUniformLocation(mFragProg, "tex4")}};
7858     for (GLint location : texLocations)
7859     {
7860         ASSERT_NE(-1, location);
7861     }
7862 
7863     // Init the uniform data.
7864     glActiveShaderProgram(mPipeline, mFragProg);
7865     for (GLint location = 0; location < 4; ++location)
7866     {
7867         glUniform1i(texLocations[location], location);
7868     }
7869 
7870     // Initialize four samplers
7871     GLSampler samplers[4];
7872 
7873     // 0: non-mipped.
7874     glBindSampler(0, samplers[0]);
7875     glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7876     glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7877 
7878     // 1: mipped.
7879     glBindSampler(1, samplers[1]);
7880     glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
7881     glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7882 
7883     // 2: non-mipped.
7884     glBindSampler(2, samplers[2]);
7885     glSamplerParameteri(samplers[2], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7886     glSamplerParameteri(samplers[2], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7887 
7888     // 3: mipped.
7889     glBindSampler(3, samplers[3]);
7890     glSamplerParameteri(samplers[3], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
7891     glSamplerParameteri(samplers[3], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7892 
7893     // Bind two blue mipped textures and two single layer textures, should all draw.
7894     glActiveTexture(GL_TEXTURE0);
7895     glBindTexture(GL_TEXTURE_2D, tex);
7896 
7897     glActiveTexture(GL_TEXTURE1);
7898     glBindTexture(GL_TEXTURE_2D, mipmapTex);
7899 
7900     glActiveTexture(GL_TEXTURE2);
7901     glBindTexture(GL_TEXTURE_2D, tex);
7902 
7903     glActiveTexture(GL_TEXTURE3);
7904     glBindTexture(GL_TEXTURE_2D, mipmapTex);
7905 
7906     ASSERT_GL_NO_ERROR();
7907 
7908     ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7909     ASSERT_GL_NO_ERROR();
7910     EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 255, 2);
7911 
7912     // Bind four single layer textures, two should be incomplete.
7913     glActiveTexture(GL_TEXTURE1);
7914     glBindTexture(GL_TEXTURE_2D, tex);
7915 
7916     glActiveTexture(GL_TEXTURE3);
7917     glBindTexture(GL_TEXTURE_2D, tex);
7918 
7919     ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7920     ASSERT_GL_NO_ERROR();
7921     EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 2);
7922 }
7923 
7924 // Use a sampler in a uniform struct.
TEST_P(SamplerInStructTest,SamplerInStruct)7925 TEST_P(SamplerInStructTest, SamplerInStruct)
7926 {
7927     runSamplerInStructTest();
7928 }
7929 
7930 // Use a sampler in a uniform struct that's passed as a function parameter.
TEST_P(SamplerInStructAsFunctionParameterTest,SamplerInStructAsFunctionParameter)7931 TEST_P(SamplerInStructAsFunctionParameterTest, SamplerInStructAsFunctionParameter)
7932 {
7933     // Fails on Nexus 5X due to a driver bug. http://anglebug.com/1427
7934     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
7935 
7936     runSamplerInStructTest();
7937 }
7938 
7939 // Use a sampler in a uniform struct array with a struct from the array passed as a function
7940 // parameter.
TEST_P(SamplerInStructArrayAsFunctionParameterTest,SamplerInStructArrayAsFunctionParameter)7941 TEST_P(SamplerInStructArrayAsFunctionParameterTest, SamplerInStructArrayAsFunctionParameter)
7942 {
7943     // Fails on Nexus 5X due to a driver bug. http://anglebug.com/1427
7944     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
7945 
7946     runSamplerInStructTest();
7947 }
7948 
7949 // Use a sampler in a struct inside a uniform struct with the nested struct passed as a function
7950 // parameter.
TEST_P(SamplerInNestedStructAsFunctionParameterTest,SamplerInNestedStructAsFunctionParameter)7951 TEST_P(SamplerInNestedStructAsFunctionParameterTest, SamplerInNestedStructAsFunctionParameter)
7952 {
7953     // Fails on Nexus 5X due to a driver bug. http://anglebug.com/1427
7954     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
7955 
7956     runSamplerInStructTest();
7957 }
7958 
7959 // Make sure that there isn't a name conflict between sampler extracted from a struct and a
7960 // similarly named uniform.
TEST_P(SamplerInStructAndOtherVariableTest,SamplerInStructAndOtherVariable)7961 TEST_P(SamplerInStructAndOtherVariableTest, SamplerInStructAndOtherVariable)
7962 {
7963     runSamplerInStructTest();
7964 }
7965 
7966 // GL_EXT_texture_filter_anisotropic
7967 class TextureAnisotropyTest : public Texture2DTest
7968 {
7969   protected:
uploadTexture()7970     void uploadTexture()
7971     {
7972         glActiveTexture(GL_TEXTURE0);
7973         glBindTexture(GL_TEXTURE_2D, mTexture2D);
7974         GLColor texDataRed[1] = {GLColor::red};
7975         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed);
7976         EXPECT_GL_NO_ERROR();
7977     }
7978 };
7979 
7980 // Tests that setting anisotropic filtering doesn't cause failures at draw time.
TEST_P(TextureAnisotropyTest,AnisotropyFunctional)7981 TEST_P(TextureAnisotropyTest, AnisotropyFunctional)
7982 {
7983     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_filter_anisotropic"));
7984 
7985     setUpProgram();
7986 
7987     uploadTexture();
7988 
7989     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7990     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7991     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
7992     EXPECT_GL_NO_ERROR();
7993 
7994     drawQuad(mProgram, "position", 0.5f);
7995 
7996     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
7997     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7998     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
7999 }
8000 
8001 // GL_OES_texture_border_clamp
8002 class TextureBorderClampTest : public Texture2DTest
8003 {
8004   protected:
TextureBorderClampTest()8005     TextureBorderClampTest() : Texture2DTest() {}
8006 
getVertexShaderSource()8007     const char *getVertexShaderSource() override
8008     {
8009         return
8010             R"(precision highp float;
8011             attribute vec4 position;
8012             varying vec2 texcoord;
8013 
8014             void main()
8015             {
8016                 gl_Position = vec4(position.xy, 0.0, 1.0);
8017                 // texcoords in [-0.5, 1.5]
8018                 texcoord = (position.xy) + 0.5;
8019             })";
8020     }
8021 
uploadTexture()8022     void uploadTexture()
8023     {
8024         glActiveTexture(GL_TEXTURE0);
8025         glBindTexture(GL_TEXTURE_2D, mTexture2D);
8026         std::vector<GLColor> texDataRed(1, GLColor::red);
8027         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8028                      texDataRed.data());
8029         EXPECT_GL_NO_ERROR();
8030     }
8031 
testFormat(GLenum format,GLenum type,GLColor32F borderColor)8032     void testFormat(GLenum format, GLenum type, GLColor32F borderColor)
8033     {
8034         glBindTexture(GL_TEXTURE_2D, mTexture2D);
8035         glActiveTexture(GL_TEXTURE0);
8036         glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &borderColor.R);
8037         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8038         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8039         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8040         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8041         glTexImage2D(GL_TEXTURE_2D, 0, format, 2, 2, 0, format, type, nullptr);
8042         drawQuad(mProgram, "position", 0.5f);
8043     }
8044 
testCompressedFormat(GLenum format,GLsizei size,GLColor32F borderColor)8045     void testCompressedFormat(GLenum format, GLsizei size, GLColor32F borderColor)
8046     {
8047         setUpProgram();
8048         glBindTexture(GL_TEXTURE_2D, mTexture2D);
8049         glActiveTexture(GL_TEXTURE0);
8050         glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &borderColor.R);
8051         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8052         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8053         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8054         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8055         glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, 4, 4, 0, size, nullptr);
8056         drawQuad(mProgram, "position", 0.5f);
8057     }
8058 };
8059 
8060 // Test if the color set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the texture in
8061 // GL_CLAMP_TO_BORDER wrap mode (set with glTexParameter).
TEST_P(TextureBorderClampTest,TextureBorderClampFunctional)8062 TEST_P(TextureBorderClampTest, TextureBorderClampFunctional)
8063 {
8064     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8065 
8066     setUpProgram();
8067 
8068     uploadTexture();
8069 
8070     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8071     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8072     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8073     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8074     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8075     EXPECT_GL_NO_ERROR();
8076 
8077     drawQuad(mProgram, "position", 0.5f);
8078 
8079     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8080     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8081     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8082 }
8083 
8084 // Test reading back GL_TEXTURE_BORDER_COLOR by glGetTexParameter.
TEST_P(TextureBorderClampTest,TextureBorderClampFunctional2)8085 TEST_P(TextureBorderClampTest, TextureBorderClampFunctional2)
8086 {
8087     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8088 
8089     glActiveTexture(GL_TEXTURE0);
8090     glBindTexture(GL_TEXTURE_2D, mTexture2D);
8091 
8092     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8093 
8094     GLint colorFixedPoint[4] = {0};
8095     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorFixedPoint);
8096     constexpr GLint colorGreenFixedPoint[4] = {0, std::numeric_limits<GLint>::max(), 0,
8097                                                std::numeric_limits<GLint>::max()};
8098     EXPECT_EQ(colorFixedPoint[0], colorGreenFixedPoint[0]);
8099     EXPECT_EQ(colorFixedPoint[1], colorGreenFixedPoint[1]);
8100     EXPECT_EQ(colorFixedPoint[2], colorGreenFixedPoint[2]);
8101     EXPECT_EQ(colorFixedPoint[3], colorGreenFixedPoint[3]);
8102 
8103     constexpr GLint colorBlueFixedPoint[4] = {0, 0, std::numeric_limits<GLint>::max(),
8104                                               std::numeric_limits<GLint>::max()};
8105     glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorBlueFixedPoint);
8106 
8107     GLfloat color[4] = {0.0f};
8108     glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
8109     EXPECT_EQ(color[0], kFloatBlue.R);
8110     EXPECT_EQ(color[1], kFloatBlue.G);
8111     EXPECT_EQ(color[2], kFloatBlue.B);
8112     EXPECT_EQ(color[3], kFloatBlue.A);
8113 }
8114 
8115 // Test GL_TEXTURE_BORDER_COLOR parameter validation at glTexParameter.
TEST_P(TextureBorderClampTest,TextureBorderClampValidation)8116 TEST_P(TextureBorderClampTest, TextureBorderClampValidation)
8117 {
8118     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8119 
8120     glActiveTexture(GL_TEXTURE0);
8121     glBindTexture(GL_TEXTURE_2D, mTexture2D);
8122 
8123     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, 1.0f);
8124     EXPECT_GL_ERROR(GL_INVALID_ENUM);
8125 
8126     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::numeric_limits<GLint>::max());
8127     EXPECT_GL_ERROR(GL_INVALID_ENUM);
8128 
8129     glTexParameterfv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8130     EXPECT_GL_ERROR(GL_INVALID_ENUM);
8131 
8132     GLint colorInt[4] = {0};
8133     glTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_BORDER_COLOR, colorInt);
8134     EXPECT_GL_ERROR(GL_INVALID_ENUM);
8135 
8136     if (getClientMajorVersion() < 3)
8137     {
8138         glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
8139         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8140         glGetTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
8141         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8142 
8143         GLuint colorUInt[4] = {0};
8144         glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
8145         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8146         glGetTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
8147         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8148 
8149         GLSampler sampler;
8150         glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
8151         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8152         glGetSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
8153         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8154 
8155         glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
8156         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8157         glGetSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
8158         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8159     }
8160 }
8161 
8162 // Test GL_TEXTURE_BORDER_COLOR parameter with unorm formats.
TEST_P(TextureBorderClampTest,TextureBorderClampUnorm8)8163 TEST_P(TextureBorderClampTest, TextureBorderClampUnorm8)
8164 {
8165     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8166 
8167     GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8168 
8169     setUpProgram();
8170 
8171     testFormat(GL_ALPHA, GL_UNSIGNED_BYTE, kBorder);
8172     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8173 
8174     testFormat(GL_RGB, GL_UNSIGNED_BYTE, kBorder);
8175     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8176 
8177     testFormat(GL_RGBA, GL_UNSIGNED_BYTE, kBorder);
8178     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8179 
8180     testFormat(GL_LUMINANCE, GL_UNSIGNED_BYTE, kBorder);
8181     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
8182 
8183     testFormat(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, kBorder);
8184     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8185 }
8186 
8187 // Test GL_TEXTURE_BORDER_COLOR parameter with sRGB formats.
TEST_P(TextureBorderClampTest,TextureBorderClampSrgb)8188 TEST_P(TextureBorderClampTest, TextureBorderClampSrgb)
8189 {
8190     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8191     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB"));
8192 
8193     // AMD D3D9 drivers always sample sRGB formats with (0, 0, 0, 0) border color, won't fix.
8194     ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
8195 
8196     GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8197 
8198     setUpProgram();
8199 
8200     testFormat(GL_SRGB_EXT, GL_UNSIGNED_BYTE, kBorder);
8201     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8202 
8203     testFormat(GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, kBorder);
8204     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8205 }
8206 
8207 // Test GL_TEXTURE_BORDER_COLOR parameter with half-float formats.
TEST_P(TextureBorderClampTest,TextureBorderClampFloat16)8208 TEST_P(TextureBorderClampTest, TextureBorderClampFloat16)
8209 {
8210     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8211     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
8212 
8213     GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8214 
8215     setUpProgram();
8216 
8217     testFormat(GL_ALPHA, GL_HALF_FLOAT_OES, kBorder);
8218     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8219 
8220     testFormat(GL_RGB, GL_HALF_FLOAT_OES, kBorder);
8221     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8222 
8223     testFormat(GL_RGBA, GL_HALF_FLOAT_OES, kBorder);
8224     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8225 
8226     testFormat(GL_LUMINANCE, GL_HALF_FLOAT_OES, kBorder);
8227     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
8228 
8229     testFormat(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, kBorder);
8230     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8231 }
8232 
8233 // Test GL_TEXTURE_BORDER_COLOR parameter with float formats.
TEST_P(TextureBorderClampTest,TextureBorderClampFloat32)8234 TEST_P(TextureBorderClampTest, TextureBorderClampFloat32)
8235 {
8236     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8237     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
8238 
8239     GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8240 
8241     setUpProgram();
8242 
8243     testFormat(GL_ALPHA, GL_FLOAT, kBorder);
8244     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8245 
8246     testFormat(GL_RGB, GL_FLOAT, kBorder);
8247     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8248 
8249     testFormat(GL_RGBA, GL_FLOAT, kBorder);
8250     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8251 
8252     testFormat(GL_LUMINANCE, GL_FLOAT, kBorder);
8253     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
8254 
8255     testFormat(GL_LUMINANCE_ALPHA, GL_FLOAT, kBorder);
8256     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8257 }
8258 
8259 // Test GL_TEXTURE_BORDER_COLOR parameter with red and red-green formats.
TEST_P(TextureBorderClampTest,TextureBorderClampRG)8260 TEST_P(TextureBorderClampTest, TextureBorderClampRG)
8261 {
8262     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8263     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
8264 
8265     GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8266 
8267     setUpProgram();
8268 
8269     testFormat(GL_RED_EXT, GL_UNSIGNED_BYTE, kBorder);
8270     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
8271 
8272     testFormat(GL_RG_EXT, GL_UNSIGNED_BYTE, kBorder);
8273     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
8274 
8275     if (IsGLExtensionEnabled("GL_OES_texture_half_float"))
8276     {
8277         testFormat(GL_RED_EXT, GL_HALF_FLOAT_OES, kBorder);
8278         EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
8279 
8280         testFormat(GL_RG_EXT, GL_HALF_FLOAT_OES, kBorder);
8281         EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
8282     }
8283 
8284     if (IsGLExtensionEnabled("GL_OES_texture_float"))
8285     {
8286         testFormat(GL_RED_EXT, GL_FLOAT, kBorder);
8287         EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
8288 
8289         testFormat(GL_RG_EXT, GL_FLOAT, kBorder);
8290         EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
8291     }
8292 }
8293 
8294 // Test GL_TEXTURE_BORDER_COLOR parameter with DXT1 formats.
TEST_P(TextureBorderClampTest,TextureBorderClampDXT1)8295 TEST_P(TextureBorderClampTest, TextureBorderClampDXT1)
8296 {
8297     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8298     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
8299 
8300     GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8301 
8302     setUpProgram();
8303 
8304     testCompressedFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 8, kBorder);
8305     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8306 
8307     testCompressedFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, kBorder);
8308     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8309 }
8310 
8311 // Test GL_TEXTURE_BORDER_COLOR parameter with DXT1 sRGB formats.
TEST_P(TextureBorderClampTest,TextureBorderClampDXT1Srgb)8312 TEST_P(TextureBorderClampTest, TextureBorderClampDXT1Srgb)
8313 {
8314     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8315     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc_srgb"));
8316 
8317     // AMD D3D9 drivers always sample sRGB formats with (0, 0, 0, 0) border color, won't fix.
8318     ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
8319 
8320     GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8321 
8322     setUpProgram();
8323 
8324     testCompressedFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 8, kBorder);
8325     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8326 
8327     testCompressedFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 8, kBorder);
8328     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8329 }
8330 
8331 // Test GL_TEXTURE_BORDER_COLOR parameter with texture redefinition.
TEST_P(TextureBorderClampTest,Redefinition)8332 TEST_P(TextureBorderClampTest, Redefinition)
8333 {
8334     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8335 
8336     GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8337 
8338     setUpProgram();
8339 
8340     testFormat(GL_ALPHA, GL_UNSIGNED_BYTE, kBorder);
8341     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8342 
8343     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 2, 2, 0, GL_LUMINANCE_ALPHA,
8344                  GL_UNSIGNED_BYTE, nullptr);
8345     drawQuad(mProgram, "position", 0.5f);
8346     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8347 
8348     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
8349     drawQuad(mProgram, "position", 0.5f);
8350     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8351 }
8352 
8353 class TextureBorderClampTestES3 : public TextureBorderClampTest
8354 {
8355   protected:
TextureBorderClampTestES3()8356     TextureBorderClampTestES3() : TextureBorderClampTest() {}
8357 };
8358 
8359 // Test if the color set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the texture in
8360 // GL_CLAMP_TO_BORDER wrap mode (set with glSamplerParameter).
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Functional)8361 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Functional)
8362 {
8363     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8364 
8365     setUpProgram();
8366 
8367     uploadTexture();
8368 
8369     GLSampler sampler;
8370     glBindSampler(0, sampler);
8371     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8372     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8373     glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8374     glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8375     glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8376     EXPECT_GL_NO_ERROR();
8377 
8378     drawQuad(mProgram, "position", 0.5f);
8379 
8380     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8381     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8382     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8383 }
8384 
8385 // Test reading back GL_TEXTURE_BORDER_COLOR by glGetSamplerParameter.
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Functional2)8386 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Functional2)
8387 {
8388     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8389 
8390     glActiveTexture(GL_TEXTURE0);
8391 
8392     GLSampler sampler;
8393     glBindSampler(0, sampler);
8394 
8395     glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8396 
8397     GLint colorFixedPoint[4] = {0};
8398     glGetSamplerParameteriv(sampler, GL_TEXTURE_BORDER_COLOR, colorFixedPoint);
8399     constexpr GLint colorGreenFixedPoint[4] = {0, std::numeric_limits<GLint>::max(), 0,
8400                                                std::numeric_limits<GLint>::max()};
8401     EXPECT_EQ(colorFixedPoint[0], colorGreenFixedPoint[0]);
8402     EXPECT_EQ(colorFixedPoint[1], colorGreenFixedPoint[1]);
8403     EXPECT_EQ(colorFixedPoint[2], colorGreenFixedPoint[2]);
8404     EXPECT_EQ(colorFixedPoint[3], colorGreenFixedPoint[3]);
8405 
8406     constexpr GLint colorBlueFixedPoint[4] = {0, 0, std::numeric_limits<GLint>::max(),
8407                                               std::numeric_limits<GLint>::max()};
8408     glSamplerParameteriv(sampler, GL_TEXTURE_BORDER_COLOR, colorBlueFixedPoint);
8409 
8410     GLfloat color[4] = {0.0f};
8411     glGetSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, color);
8412     EXPECT_EQ(color[0], kFloatBlue.R);
8413     EXPECT_EQ(color[1], kFloatBlue.G);
8414     EXPECT_EQ(color[2], kFloatBlue.B);
8415     EXPECT_EQ(color[3], kFloatBlue.A);
8416 
8417     constexpr GLint colorSomewhatRedInt[4] = {500000, 0, 0, std::numeric_limits<GLint>::max()};
8418     glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorSomewhatRedInt);
8419     GLint colorInt[4] = {0};
8420     glGetSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
8421     EXPECT_EQ(colorInt[0], colorSomewhatRedInt[0]);
8422     EXPECT_EQ(colorInt[1], colorSomewhatRedInt[1]);
8423     EXPECT_EQ(colorInt[2], colorSomewhatRedInt[2]);
8424     EXPECT_EQ(colorInt[3], colorSomewhatRedInt[3]);
8425 
8426     constexpr GLuint colorSomewhatRedUInt[4] = {500000, 0, 0, std::numeric_limits<GLuint>::max()};
8427     glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorSomewhatRedUInt);
8428     GLuint colorUInt[4] = {0};
8429     glGetSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
8430     EXPECT_EQ(colorUInt[0], colorSomewhatRedUInt[0]);
8431     EXPECT_EQ(colorUInt[1], colorSomewhatRedUInt[1]);
8432     EXPECT_EQ(colorUInt[2], colorSomewhatRedUInt[2]);
8433     EXPECT_EQ(colorUInt[3], colorSomewhatRedUInt[3]);
8434 
8435     glBindTexture(GL_TEXTURE_2D, mTexture2D);
8436 
8437     constexpr GLint colorSomewhatGreenInt[4] = {0, 500000, 0, std::numeric_limits<GLint>::max()};
8438     glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorSomewhatGreenInt);
8439     glGetTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
8440     EXPECT_EQ(colorInt[0], colorSomewhatGreenInt[0]);
8441     EXPECT_EQ(colorInt[1], colorSomewhatGreenInt[1]);
8442     EXPECT_EQ(colorInt[2], colorSomewhatGreenInt[2]);
8443     EXPECT_EQ(colorInt[3], colorSomewhatGreenInt[3]);
8444 
8445     constexpr GLuint colorSomewhatGreenUInt[4] = {0, 500000, 0, std::numeric_limits<GLuint>::max()};
8446     glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorSomewhatGreenUInt);
8447     glGetTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
8448     EXPECT_EQ(colorUInt[0], colorSomewhatGreenUInt[0]);
8449     EXPECT_EQ(colorUInt[1], colorSomewhatGreenUInt[1]);
8450     EXPECT_EQ(colorUInt[2], colorSomewhatGreenUInt[2]);
8451     EXPECT_EQ(colorUInt[3], colorSomewhatGreenUInt[3]);
8452 }
8453 
8454 // Test GL_TEXTURE_BORDER_COLOR parameter validation at glSamplerParameter.
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Validation)8455 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Validation)
8456 {
8457     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8458 
8459     glActiveTexture(GL_TEXTURE0);
8460 
8461     GLSampler sampler;
8462     glBindSampler(0, sampler);
8463 
8464     glSamplerParameterf(sampler, GL_TEXTURE_BORDER_COLOR, 1.0f);
8465     EXPECT_GL_ERROR(GL_INVALID_ENUM);
8466 
8467     glSamplerParameteri(sampler, GL_TEXTURE_BORDER_COLOR, std::numeric_limits<GLint>::max());
8468     EXPECT_GL_ERROR(GL_INVALID_ENUM);
8469 }
8470 
8471 // Test that format-specific adjustments are applied
8472 // when the border color type does not match the texture type.
TEST_P(TextureBorderClampTestES3,TextureBorderTypeMismatch)8473 TEST_P(TextureBorderClampTestES3, TextureBorderTypeMismatch)
8474 {
8475     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8476 
8477     glBindTexture(GL_TEXTURE_2D, mTexture2D);
8478     glActiveTexture(GL_TEXTURE0);
8479     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8480     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8481     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8482     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8483 
8484     GLColor32UI kBorder = {1, 2, 3, 0};
8485     glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kBorder.R);
8486     ASSERT_GL_NO_ERROR();
8487 
8488     setUpProgram();
8489 
8490     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
8491     drawQuad(mProgram, "position", 0.5f);
8492     EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
8493 }
8494 
8495 class TextureBorderClampIntegerTestES3 : public Texture2DTest
8496 {
8497   protected:
TextureBorderClampIntegerTestES3()8498     TextureBorderClampIntegerTestES3() : Texture2DTest(), isUnsignedIntTest(false) {}
8499 
getVertexShaderSource()8500     const char *getVertexShaderSource() override
8501     {
8502         return
8503             R"(#version 300 es
8504             out vec2 texcoord;
8505             in vec4 position;
8506 
8507             void main()
8508             {
8509                 gl_Position = vec4(position.xy, 0.0, 1.0);
8510                 // texcoords in [-0.5, 1.5]
8511                 texcoord = (position.xy) + 0.5;
8512             })";
8513     }
8514 
getFragmentShaderSource()8515     const char *getFragmentShaderSource() override
8516     {
8517         if (isUnsignedIntTest)
8518         {
8519             return "#version 300 es\n"
8520                    "precision highp float;\n"
8521                    "uniform highp usampler2D tex;\n"
8522                    "in vec2 texcoord;\n"
8523                    "out vec4 fragColor;\n"
8524 
8525                    "void main()\n"
8526                    "{\n"
8527                    "vec4 red   = vec4(1.0, 0.0, 0.0, 1.0);\n"
8528                    "vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
8529                    "fragColor = (texture(tex, texcoord).r == 150u)"
8530                    "            ? green : red;\n"
8531                    "}\n";
8532         }
8533         else
8534         {
8535             return "#version 300 es\n"
8536                    "precision highp float;\n"
8537                    "uniform highp isampler2D tex;\n"
8538                    "in vec2 texcoord;\n"
8539                    "out vec4 fragColor;\n"
8540 
8541                    "void main()\n"
8542                    "{\n"
8543                    "vec4 red   = vec4(1.0, 0.0, 0.0, 1.0);\n"
8544                    "vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
8545                    "fragColor = (texture(tex, texcoord).r == -50)"
8546                    "            ? green : red;\n"
8547                    "}\n";
8548         }
8549     }
8550 
uploadTexture()8551     void uploadTexture()
8552     {
8553         glActiveTexture(GL_TEXTURE0);
8554         glBindTexture(GL_TEXTURE_2D, mTexture2D);
8555         if (isUnsignedIntTest)
8556         {
8557             std::vector<GLubyte> texData(4, 100);
8558             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
8559                          texData.data());
8560         }
8561         else
8562         {
8563             std::vector<GLbyte> texData(4, 100);
8564             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, 1, 1, 0, GL_RGBA_INTEGER, GL_BYTE,
8565                          texData.data());
8566         }
8567         EXPECT_GL_NO_ERROR();
8568     }
8569 
8570     bool isUnsignedIntTest;
8571 };
8572 
8573 // Test if the integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the
8574 // integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampInteger)8575 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampInteger)
8576 {
8577     // Fails on Win10 FYI x64 Release (AMD RX 550). http://anglebug.com/3760
8578     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
8579 
8580     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8581 
8582     setUpProgram();
8583 
8584     uploadTexture();
8585 
8586     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8587     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8588     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8589     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8590 
8591     constexpr GLint borderColor[4] = {-50, -50, -50, -50};
8592     glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
8593 
8594     EXPECT_GL_NO_ERROR();
8595 
8596     drawQuad(mProgram, "position", 0.5f);
8597 
8598     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8599     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8600     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8601 }
8602 
8603 // Test if the integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the
8604 // integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampInteger2)8605 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampInteger2)
8606 {
8607     // Fails on Win10 FYI x64 Release (AMD RX 550). http://anglebug.com/3760
8608     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
8609 
8610     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8611 
8612     setUpProgram();
8613 
8614     uploadTexture();
8615 
8616     GLSampler sampler;
8617     glBindSampler(0, sampler);
8618     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8619     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8620     glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8621     glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8622 
8623     constexpr GLint borderColor[4] = {-50, -50, -50, -50};
8624     glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, borderColor);
8625 
8626     EXPECT_GL_NO_ERROR();
8627 
8628     drawQuad(mProgram, "position", 0.5f);
8629 
8630     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8631     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8632     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8633 }
8634 
8635 // Test if the unsigned integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside
8636 // of the unsigned integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIuivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampIntegerUnsigned)8637 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampIntegerUnsigned)
8638 {
8639     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8640 
8641     isUnsignedIntTest = true;
8642 
8643     setUpProgram();
8644 
8645     uploadTexture();
8646 
8647     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8648     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8649     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8650     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8651 
8652     constexpr GLuint borderColor[4] = {150, 150, 150, 150};
8653     glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
8654 
8655     EXPECT_GL_NO_ERROR();
8656 
8657     drawQuad(mProgram, "position", 0.5f);
8658 
8659     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8660     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8661     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8662 }
8663 
8664 // Test if the unsigned integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside
8665 // of the unsigned integer texture in GL_CLAMP_TO_BORDER wrap mode (set with
8666 // glSamplerParameterIuivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampIntegerUnsigned2)8667 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampIntegerUnsigned2)
8668 {
8669     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8670 
8671     isUnsignedIntTest = true;
8672 
8673     setUpProgram();
8674 
8675     uploadTexture();
8676 
8677     GLSampler sampler;
8678     glBindSampler(0, sampler);
8679     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8680     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8681     glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8682     glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8683 
8684     constexpr GLuint borderColor[4] = {150, 150, 150, 150};
8685     glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, borderColor);
8686 
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 // ~GL_OES_texture_border_clamp
8697 
8698 // GL_EXT_texture_mirror_clamp_to_edge
8699 class TextureMirrorClampToEdgeTest : public Texture2DTest
8700 {
8701   protected:
TextureMirrorClampToEdgeTest()8702     TextureMirrorClampToEdgeTest() : Texture2DTest() {}
8703 
getVertexShaderSource()8704     const char *getVertexShaderSource() override
8705     {
8706         return R"(precision highp float;
8707 attribute vec4 position;
8708 varying vec2 texcoord;
8709 
8710 void main()
8711 {
8712     gl_Position = vec4(position.xy, 0.0, 1.0);
8713     texcoord = position.xy * 2.0;
8714 })";
8715     }
8716 
uploadTexture(bool isInteger,bool isSigned,GLuint sampler)8717     void uploadTexture(bool isInteger, bool isSigned, GLuint sampler)
8718     {
8719         glActiveTexture(GL_TEXTURE0);
8720         glBindTexture(GL_TEXTURE_2D, mTexture2D);
8721         if (isInteger && isSigned)
8722         {
8723             const int8_t data[] = {0, 0, 0, -1, -1, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, -1};
8724             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, 2, 2, 0, GL_RGBA_INTEGER, GL_BYTE, data);
8725         }
8726         else if (isInteger)
8727         {
8728             const uint8_t data[] = {0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1};
8729             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
8730                          data);
8731         }
8732         else
8733         {
8734             const uint8_t data[] = {0, 0, 0, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255};
8735             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
8736         }
8737 
8738         if (sampler != 0)
8739         {
8740             glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_MIRROR_CLAMP_TO_EDGE_EXT);
8741             glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_MIRROR_CLAMP_TO_EDGE_EXT);
8742             glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8743             glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8744         }
8745         else
8746         {
8747             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRROR_CLAMP_TO_EDGE_EXT);
8748             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRROR_CLAMP_TO_EDGE_EXT);
8749             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8750             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8751         }
8752         ASSERT_GL_NO_ERROR();
8753     }
8754 
checkTextureSampling()8755     void checkTextureSampling()
8756     {
8757         auto screenX = [&](float x) { return getWindowWidth() * (x * 0.25 + 0.5); };
8758         auto screenY = [&](float y) { return getWindowHeight() * (y * 0.25 + 0.5); };
8759 
8760         // +S, +T
8761         EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(0.25), GLColor::black);
8762         EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(0.25), GLColor::red);
8763         EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(0.25), GLColor::red);
8764         EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(0.75), GLColor::green);
8765         EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(1.50), GLColor::green);
8766         EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(0.75), GLColor::blue);
8767         EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(0.75), GLColor::blue);
8768         EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(1.50), GLColor::blue);
8769         EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(1.50), GLColor::blue);
8770 
8771         // -S, +T
8772         EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(0.25), GLColor::black);
8773         EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(0.25), GLColor::red);
8774         EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(0.25), GLColor::red);
8775         EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(0.75), GLColor::green);
8776         EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(1.50), GLColor::green);
8777         EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(0.75), GLColor::blue);
8778         EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(0.75), GLColor::blue);
8779         EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(1.50), GLColor::blue);
8780         EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(1.50), GLColor::blue);
8781 
8782         // +S, -T
8783         EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-0.25), GLColor::black);
8784         EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-0.25), GLColor::red);
8785         EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-0.25), GLColor::red);
8786         EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-0.75), GLColor::green);
8787         EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-1.50), GLColor::green);
8788         EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-0.75), GLColor::blue);
8789         EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-0.75), GLColor::blue);
8790         EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-1.50), GLColor::blue);
8791         EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-1.50), GLColor::blue);
8792 
8793         // -S, -T
8794         EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-0.25), GLColor::black);
8795         EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-0.25), GLColor::red);
8796         EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-0.25), GLColor::red);
8797         EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-0.75), GLColor::green);
8798         EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-1.50), GLColor::green);
8799         EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-0.75), GLColor::blue);
8800         EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-0.75), GLColor::blue);
8801         EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-1.50), GLColor::blue);
8802         EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-1.50), GLColor::blue);
8803     }
8804 };
8805 
8806 // Test that the texture is correctly mirrored in negative directions
8807 // and clamped to edge pixels outside of the normalized range.
TEST_P(TextureMirrorClampToEdgeTest,TexParameter)8808 TEST_P(TextureMirrorClampToEdgeTest, TexParameter)
8809 {
8810     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8811 
8812     setUpProgram();
8813     uploadTexture(false, false, 0);
8814     drawQuad(mProgram, "position", 0.5f);
8815     ASSERT_GL_NO_ERROR();
8816 
8817     checkTextureSampling();
8818 }
8819 
8820 class TextureMirrorClampToEdgeTestES3 : public TextureMirrorClampToEdgeTest
8821 {
8822   protected:
TextureMirrorClampToEdgeTestES3()8823     TextureMirrorClampToEdgeTestES3() : TextureMirrorClampToEdgeTest() {}
8824 };
8825 
8826 // Test that the texture is correctly mirrored in negative directions and clamped
8827 // to edge pixels outside of the normalized range with mode set via glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeTestES3,SamplerParameter)8828 TEST_P(TextureMirrorClampToEdgeTestES3, SamplerParameter)
8829 {
8830     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8831 
8832     GLSampler sampler;
8833     glBindSampler(0, sampler);
8834 
8835     setUpProgram();
8836     uploadTexture(false, false, sampler);
8837     drawQuad(mProgram, "position", 0.5f);
8838     ASSERT_GL_NO_ERROR();
8839 
8840     checkTextureSampling();
8841 }
8842 
8843 class TextureMirrorClampToEdgeIntegerTestES3 : public TextureMirrorClampToEdgeTestES3
8844 {
8845   protected:
TextureMirrorClampToEdgeIntegerTestES3()8846     TextureMirrorClampToEdgeIntegerTestES3() : TextureMirrorClampToEdgeTestES3() {}
8847 
getVertexShaderSource()8848     const char *getVertexShaderSource() override
8849     {
8850         return R"(#version 300 es
8851 precision highp float;
8852 in vec4 position;
8853 out vec2 texcoord;
8854 
8855 void main()
8856 {
8857     gl_Position = vec4(position.xy, 0.0, 1.0);
8858     texcoord = position.xy * 2.0;
8859 })";
8860     }
8861 
getFragmentShaderSource()8862     const char *getFragmentShaderSource() override
8863     {
8864         if (mIsSigned)
8865         {
8866             return R"(#version 300 es
8867 precision highp float;
8868 uniform highp isampler2D tex;
8869 in vec2 texcoord;
8870 out vec4 fragColor;
8871 void main() { fragColor = vec4(-texture(tex, texcoord)); })";
8872         }
8873         else
8874         {
8875             return R"(#version 300 es
8876 precision highp float;
8877 uniform highp usampler2D tex;
8878 in vec2 texcoord;
8879 out vec4 fragColor;
8880 void main() { fragColor = vec4(texture(tex, texcoord)); })";
8881         }
8882     }
8883 
8884     bool mIsSigned = false;
8885 };
8886 
8887 // Test that the texture is correctly mirrored in negative directions and clamped
8888 // to edge pixels outside of the normalized range with mode set with glTexParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,TexParameterSigned)8889 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, TexParameterSigned)
8890 {
8891     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8892 
8893     mIsSigned = true;
8894     setUpProgram();
8895     uploadTexture(true, true, 0);
8896     drawQuad(mProgram, "position", 0.5f);
8897     ASSERT_GL_NO_ERROR();
8898 
8899     checkTextureSampling();
8900 }
8901 
8902 // Test that the texture is correctly mirrored in negative directions and clamped
8903 // to edge pixels outside of the normalized range with mode set with glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,SamplerParameterSigned)8904 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, SamplerParameterSigned)
8905 {
8906     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8907 
8908     GLSampler sampler;
8909     glBindSampler(0, sampler);
8910 
8911     mIsSigned = true;
8912     setUpProgram();
8913     uploadTexture(true, true, sampler);
8914     drawQuad(mProgram, "position", 0.5f);
8915     ASSERT_GL_NO_ERROR();
8916 
8917     checkTextureSampling();
8918 }
8919 
8920 // Test that the unsigned integer texture is correctly mirrored in negative directions and clamped
8921 // to edge pixels outside of the normalized range with mode set with glTexParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,TexParameterUnsigned)8922 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, TexParameterUnsigned)
8923 {
8924     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8925 
8926     setUpProgram();
8927     uploadTexture(true, false, 0);
8928     drawQuad(mProgram, "position", 0.5f);
8929     ASSERT_GL_NO_ERROR();
8930 
8931     checkTextureSampling();
8932 }
8933 
8934 // Test that the unsigned integer texture is correctly mirrored in negative directions and clamped
8935 // to edge pixels outside of the normalized range with mode set with glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,SamplerParameterUnsigned)8936 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, SamplerParameterUnsigned)
8937 {
8938     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8939 
8940     GLSampler sampler;
8941     glBindSampler(0, sampler);
8942 
8943     setUpProgram();
8944     uploadTexture(true, false, sampler);
8945     drawQuad(mProgram, "position", 0.5f);
8946     ASSERT_GL_NO_ERROR();
8947 
8948     checkTextureSampling();
8949 }
8950 // ~GL_EXT_texture_mirror_clamp_to_edge
8951 
8952 class TextureLimitsTest : public ANGLETest<>
8953 {
8954   protected:
8955     struct RGBA8
8956     {
8957         uint8_t R, G, B, A;
8958     };
8959 
TextureLimitsTest()8960     TextureLimitsTest()
8961         : mProgram(0), mMaxVertexTextures(0), mMaxFragmentTextures(0), mMaxCombinedTextures(0)
8962     {
8963         setWindowWidth(128);
8964         setWindowHeight(128);
8965         setConfigRedBits(8);
8966         setConfigGreenBits(8);
8967         setConfigBlueBits(8);
8968         setConfigAlphaBits(8);
8969     }
8970 
testSetUp()8971     void testSetUp() override
8972     {
8973         glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mMaxVertexTextures);
8974         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mMaxFragmentTextures);
8975         glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxCombinedTextures);
8976 
8977         ASSERT_GL_NO_ERROR();
8978     }
8979 
testTearDown()8980     void testTearDown() override
8981     {
8982         if (mProgram != 0)
8983         {
8984             glDeleteProgram(mProgram);
8985             mProgram = 0;
8986 
8987             if (!mTextures.empty())
8988             {
8989                 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), &mTextures[0]);
8990             }
8991         }
8992     }
8993 
compileProgramWithTextureCounts(const std::string & vertexPrefix,GLint vertexTextureCount,GLint vertexActiveTextureCount,const std::string & fragPrefix,GLint fragmentTextureCount,GLint fragmentActiveTextureCount)8994     void compileProgramWithTextureCounts(const std::string &vertexPrefix,
8995                                          GLint vertexTextureCount,
8996                                          GLint vertexActiveTextureCount,
8997                                          const std::string &fragPrefix,
8998                                          GLint fragmentTextureCount,
8999                                          GLint fragmentActiveTextureCount)
9000     {
9001         std::stringstream vertexShaderStr;
9002         vertexShaderStr << "attribute vec2 position;\n"
9003                         << "varying vec4 color;\n"
9004                         << "varying vec2 texCoord;\n";
9005 
9006         for (GLint textureIndex = 0; textureIndex < vertexTextureCount; ++textureIndex)
9007         {
9008             vertexShaderStr << "uniform sampler2D " << vertexPrefix << textureIndex << ";\n";
9009         }
9010 
9011         vertexShaderStr << "void main() {\n"
9012                         << "  gl_Position = vec4(position, 0, 1);\n"
9013                         << "  texCoord = (position * 0.5) + 0.5;\n"
9014                         << "  color = vec4(0);\n";
9015 
9016         for (GLint textureIndex = 0; textureIndex < vertexActiveTextureCount; ++textureIndex)
9017         {
9018             vertexShaderStr << "  color += texture2D(" << vertexPrefix << textureIndex
9019                             << ", texCoord);\n";
9020         }
9021 
9022         vertexShaderStr << "}";
9023 
9024         std::stringstream fragmentShaderStr;
9025         fragmentShaderStr << "varying mediump vec4 color;\n" << "varying mediump vec2 texCoord;\n";
9026 
9027         for (GLint textureIndex = 0; textureIndex < fragmentTextureCount; ++textureIndex)
9028         {
9029             fragmentShaderStr << "uniform sampler2D " << fragPrefix << textureIndex << ";\n";
9030         }
9031 
9032         fragmentShaderStr << "void main() {\n" << "  gl_FragColor = color;\n";
9033 
9034         for (GLint textureIndex = 0; textureIndex < fragmentActiveTextureCount; ++textureIndex)
9035         {
9036             fragmentShaderStr << "  gl_FragColor += texture2D(" << fragPrefix << textureIndex
9037                               << ", texCoord);\n";
9038         }
9039 
9040         fragmentShaderStr << "}";
9041 
9042         const std::string &vertexShaderSource   = vertexShaderStr.str();
9043         const std::string &fragmentShaderSource = fragmentShaderStr.str();
9044 
9045         mProgram = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
9046     }
9047 
getPixel(GLint texIndex)9048     RGBA8 getPixel(GLint texIndex)
9049     {
9050         RGBA8 pixel = {static_cast<uint8_t>(texIndex & 0x7u), static_cast<uint8_t>(texIndex >> 3),
9051                        0, 255u};
9052         return pixel;
9053     }
9054 
initTextures(GLint tex2DCount,GLint texCubeCount)9055     void initTextures(GLint tex2DCount, GLint texCubeCount)
9056     {
9057         GLint totalCount = tex2DCount + texCubeCount;
9058         mTextures.assign(totalCount, 0);
9059         glGenTextures(totalCount, &mTextures[0]);
9060         ASSERT_GL_NO_ERROR();
9061 
9062         std::vector<RGBA8> texData(16 * 16);
9063 
9064         GLint texIndex = 0;
9065         for (; texIndex < tex2DCount; ++texIndex)
9066         {
9067             texData.assign(texData.size(), getPixel(texIndex));
9068             glActiveTexture(GL_TEXTURE0 + texIndex);
9069             glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
9070             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9071                          &texData[0]);
9072             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9073             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9074             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9075             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9076         }
9077 
9078         ASSERT_GL_NO_ERROR();
9079 
9080         for (; texIndex < texCubeCount; ++texIndex)
9081         {
9082             texData.assign(texData.size(), getPixel(texIndex));
9083             glActiveTexture(GL_TEXTURE0 + texIndex);
9084             glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[texIndex]);
9085             glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9086                          GL_UNSIGNED_BYTE, &texData[0]);
9087             glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9088                          GL_UNSIGNED_BYTE, &texData[0]);
9089             glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9090                          GL_UNSIGNED_BYTE, &texData[0]);
9091             glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9092                          GL_UNSIGNED_BYTE, &texData[0]);
9093             glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9094                          GL_UNSIGNED_BYTE, &texData[0]);
9095             glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9096                          GL_UNSIGNED_BYTE, &texData[0]);
9097             glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9098             glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9099             glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9100             glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9101         }
9102 
9103         ASSERT_GL_NO_ERROR();
9104     }
9105 
testWithTextures(GLint vertexTextureCount,const std::string & vertexTexturePrefix,GLint fragmentTextureCount,const std::string & fragmentTexturePrefix)9106     void testWithTextures(GLint vertexTextureCount,
9107                           const std::string &vertexTexturePrefix,
9108                           GLint fragmentTextureCount,
9109                           const std::string &fragmentTexturePrefix)
9110     {
9111         // Generate textures
9112         initTextures(vertexTextureCount + fragmentTextureCount, 0);
9113 
9114         glUseProgram(mProgram);
9115         RGBA8 expectedSum = {0};
9116         for (GLint texIndex = 0; texIndex < vertexTextureCount; ++texIndex)
9117         {
9118             std::stringstream uniformNameStr;
9119             uniformNameStr << vertexTexturePrefix << texIndex;
9120             const std::string &uniformName = uniformNameStr.str();
9121             GLint location                 = glGetUniformLocation(mProgram, uniformName.c_str());
9122             ASSERT_NE(-1, location);
9123 
9124             glUniform1i(location, texIndex);
9125             RGBA8 contribution = getPixel(texIndex);
9126             expectedSum.R += contribution.R;
9127             expectedSum.G += contribution.G;
9128         }
9129 
9130         for (GLint texIndex = 0; texIndex < fragmentTextureCount; ++texIndex)
9131         {
9132             std::stringstream uniformNameStr;
9133             uniformNameStr << fragmentTexturePrefix << texIndex;
9134             const std::string &uniformName = uniformNameStr.str();
9135             GLint location                 = glGetUniformLocation(mProgram, uniformName.c_str());
9136             ASSERT_NE(-1, location);
9137 
9138             glUniform1i(location, texIndex + vertexTextureCount);
9139             RGBA8 contribution = getPixel(texIndex + vertexTextureCount);
9140             expectedSum.R += contribution.R;
9141             expectedSum.G += contribution.G;
9142         }
9143 
9144         ASSERT_GE(256u, expectedSum.G);
9145 
9146         drawQuad(mProgram, "position", 0.5f);
9147         ASSERT_GL_NO_ERROR();
9148         EXPECT_PIXEL_NEAR(0, 0, expectedSum.R, expectedSum.G, 0, 255, 1);
9149     }
9150 
9151     GLuint mProgram;
9152     std::vector<GLuint> mTextures;
9153     GLint mMaxVertexTextures;
9154     GLint mMaxFragmentTextures;
9155     GLint mMaxCombinedTextures;
9156 };
9157 
9158 // Test rendering with the maximum vertex texture units.
TEST_P(TextureLimitsTest,MaxVertexTextures)9159 TEST_P(TextureLimitsTest, MaxVertexTextures)
9160 {
9161     compileProgramWithTextureCounts("tex", mMaxVertexTextures, mMaxVertexTextures, "tex", 0, 0);
9162     ASSERT_NE(0u, mProgram);
9163     ASSERT_GL_NO_ERROR();
9164 
9165     testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
9166 }
9167 
9168 // Test rendering with the maximum fragment texture units.
TEST_P(TextureLimitsTest,MaxFragmentTextures)9169 TEST_P(TextureLimitsTest, MaxFragmentTextures)
9170 {
9171     compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures, mMaxFragmentTextures);
9172     ASSERT_NE(0u, mProgram);
9173     ASSERT_GL_NO_ERROR();
9174 
9175     testWithTextures(mMaxFragmentTextures, "tex", 0, "tex");
9176 }
9177 
9178 // Test rendering with maximum combined texture units.
TEST_P(TextureLimitsTest,MaxCombinedTextures)9179 TEST_P(TextureLimitsTest, MaxCombinedTextures)
9180 {
9181     GLint vertexTextures = mMaxVertexTextures;
9182 
9183     if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
9184     {
9185         vertexTextures = mMaxCombinedTextures - mMaxFragmentTextures;
9186     }
9187 
9188     compileProgramWithTextureCounts("vtex", vertexTextures, vertexTextures, "ftex",
9189                                     mMaxFragmentTextures, mMaxFragmentTextures);
9190     ASSERT_NE(0u, mProgram);
9191     ASSERT_GL_NO_ERROR();
9192 
9193     testWithTextures(vertexTextures, "vtex", mMaxFragmentTextures, "ftex");
9194 }
9195 
9196 // Negative test for exceeding the number of vertex textures
TEST_P(TextureLimitsTest,ExcessiveVertexTextures)9197 TEST_P(TextureLimitsTest, ExcessiveVertexTextures)
9198 {
9199     compileProgramWithTextureCounts("tex", mMaxVertexTextures + 1, mMaxVertexTextures + 1, "tex", 0,
9200                                     0);
9201     ASSERT_EQ(0u, mProgram);
9202 }
9203 
9204 // Negative test for exceeding the number of fragment textures
TEST_P(TextureLimitsTest,ExcessiveFragmentTextures)9205 TEST_P(TextureLimitsTest, ExcessiveFragmentTextures)
9206 {
9207     compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 1,
9208                                     mMaxFragmentTextures + 1);
9209     ASSERT_EQ(0u, mProgram);
9210 }
9211 
9212 // Test active vertex textures under the limit, but excessive textures specified.
TEST_P(TextureLimitsTest,MaxActiveVertexTextures)9213 TEST_P(TextureLimitsTest, MaxActiveVertexTextures)
9214 {
9215     compileProgramWithTextureCounts("tex", mMaxVertexTextures + 4, mMaxVertexTextures, "tex", 0, 0);
9216     ASSERT_NE(0u, mProgram);
9217     ASSERT_GL_NO_ERROR();
9218 
9219     testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
9220 }
9221 
9222 // Test active fragment textures under the limit, but excessive textures specified.
TEST_P(TextureLimitsTest,MaxActiveFragmentTextures)9223 TEST_P(TextureLimitsTest, MaxActiveFragmentTextures)
9224 {
9225     compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 4,
9226                                     mMaxFragmentTextures);
9227     ASSERT_NE(0u, mProgram);
9228     ASSERT_GL_NO_ERROR();
9229 
9230     testWithTextures(0, "tex", mMaxFragmentTextures, "tex");
9231 }
9232 
9233 // Negative test for pointing two sampler uniforms of different types to the same texture.
9234 // GLES 2.0.25 section 2.10.4 page 39.
TEST_P(TextureLimitsTest,TextureTypeConflict)9235 TEST_P(TextureLimitsTest, TextureTypeConflict)
9236 {
9237     constexpr char kVS[] =
9238         "attribute vec2 position;\n"
9239         "varying float color;\n"
9240         "uniform sampler2D tex2D;\n"
9241         "uniform samplerCube texCube;\n"
9242         "void main() {\n"
9243         "  gl_Position = vec4(position, 0, 1);\n"
9244         "  vec2 texCoord = (position * 0.5) + 0.5;\n"
9245         "  color = texture2D(tex2D, texCoord).x;\n"
9246         "  color += textureCube(texCube, vec3(texCoord, 0)).x;\n"
9247         "}";
9248     constexpr char kFS[] =
9249         "varying mediump float color;\n"
9250         "void main() {\n"
9251         "  gl_FragColor = vec4(color, 0, 0, 1);\n"
9252         "}";
9253 
9254     mProgram = CompileProgram(kVS, kFS);
9255     ASSERT_NE(0u, mProgram);
9256 
9257     initTextures(1, 0);
9258 
9259     glUseProgram(mProgram);
9260     GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
9261     ASSERT_NE(-1, tex2DLocation);
9262     GLint texCubeLocation = glGetUniformLocation(mProgram, "texCube");
9263     ASSERT_NE(-1, texCubeLocation);
9264 
9265     glUniform1i(tex2DLocation, 0);
9266     glUniform1i(texCubeLocation, 0);
9267     ASSERT_GL_NO_ERROR();
9268 
9269     drawQuad(mProgram, "position", 0.5f);
9270     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
9271 }
9272 
9273 class Texture2DNorm16TestES3 : public Texture2DTestES3
9274 {
9275   protected:
Texture2DNorm16TestES3()9276     Texture2DNorm16TestES3() : Texture2DTestES3(), mTextures{0, 0, 0}, mFBO(0), mRenderbuffer(0) {}
9277 
testSetUp()9278     void testSetUp() override
9279     {
9280         Texture2DTestES3::testSetUp();
9281 
9282         glActiveTexture(GL_TEXTURE0);
9283         glGenTextures(3, mTextures);
9284         glGenFramebuffers(1, &mFBO);
9285         glGenRenderbuffers(1, &mRenderbuffer);
9286 
9287         for (size_t textureIndex = 0; textureIndex < 3; textureIndex++)
9288         {
9289             glBindTexture(GL_TEXTURE_2D, mTextures[textureIndex]);
9290             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9291             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9292         }
9293 
9294         glBindTexture(GL_TEXTURE_2D, 0);
9295 
9296         ASSERT_GL_NO_ERROR();
9297     }
9298 
testTearDown()9299     void testTearDown() override
9300     {
9301         glDeleteTextures(3, mTextures);
9302         glDeleteFramebuffers(1, &mFBO);
9303         glDeleteRenderbuffers(1, &mRenderbuffer);
9304 
9305         Texture2DTestES3::testTearDown();
9306     }
9307 
testNorm16Texture(GLint internalformat,GLenum format,GLenum type)9308     void testNorm16Texture(GLint internalformat, GLenum format, GLenum type)
9309     {
9310         // TODO(http://anglebug.com/4089) Fails on Win Intel OpenGL driver
9311         ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
9312         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
9313 
9314         GLushort pixelValue  = (type == GL_SHORT) ? 0x7FFF : 0x6A35;
9315         GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
9316 
9317         setUpProgram();
9318 
9319         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9320         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
9321                                0);
9322 
9323         for (int i = 0; i < 2; ++i)
9324         {
9325             bool isSubImage = i == 1;
9326             SCOPED_TRACE("is subimage:" + std::to_string(isSubImage));
9327             glBindTexture(GL_TEXTURE_2D, mTextures[0]);
9328             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16_EXT, 1, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT,
9329                          nullptr);
9330 
9331             glBindTexture(GL_TEXTURE_2D, mTextures[1]);
9332             if (isSubImage)
9333             {
9334                 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, nullptr);
9335                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, format, type, imageData);
9336             }
9337             else
9338             {
9339                 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
9340             }
9341             EXPECT_GL_NO_ERROR();
9342 
9343             drawQuad(mProgram, "position", 0.5f);
9344 
9345             GLubyte expectedValue =
9346                 (type == GL_SHORT) ? 0xFF : static_cast<GLubyte>(pixelValue >> 8);
9347 
9348             EXPECT_PIXEL_COLOR_EQ(0, 0,
9349                                   SliceFormatColor(format, GLColor(expectedValue, expectedValue,
9350                                                                    expectedValue, expectedValue)));
9351         }
9352         glBindFramebuffer(GL_FRAMEBUFFER, 0);
9353 
9354         ASSERT_GL_NO_ERROR();
9355     }
9356 
testReadPixelsRGBAWithRangeAndPixelStoreMode(GLuint x,GLuint y,GLuint width,GLuint height,GLint packRowLength,GLint packAlignment,GLint packSkipPixels,GLint packSkipRows,GLenum type,GLColor16UI color)9357     void testReadPixelsRGBAWithRangeAndPixelStoreMode(GLuint x,
9358                                                       GLuint y,
9359                                                       GLuint width,
9360                                                       GLuint height,
9361                                                       GLint packRowLength,
9362                                                       GLint packAlignment,
9363                                                       GLint packSkipPixels,
9364                                                       GLint packSkipRows,
9365                                                       GLenum type,
9366                                                       GLColor16UI color)
9367     {
9368         // PACK modes debugging
9369         GLint s = 2;  // single component size in bytes, UNSIGNED_SHORT -> 2 in our case
9370         GLint n = 4;  // 4 components per pixel, stands for GL_RGBA
9371 
9372         GLuint l       = packRowLength == 0 ? width : packRowLength;
9373         const GLint &a = packAlignment;
9374 
9375         // According to
9376         // https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml
9377         GLint k                    = (s >= a) ? n * l : a / s * (1 + (s * n * l - 1) / a);
9378         std::size_t componentCount = n * packSkipPixels + k * (packSkipRows + height);
9379         if (static_cast<GLuint>(packRowLength) < width)
9380         {
9381             componentCount += width * n * s - k;
9382         }
9383 
9384         // Populate the pixels array with random dirty value
9385         constexpr GLushort kDirtyValue = 0x1234;
9386         std::vector<GLushort> pixels(componentCount, kDirtyValue);
9387         glReadPixels(x, y, width, height, GL_RGBA, type, pixels.data());
9388 
9389         EXPECT_GL_NO_ERROR();
9390 
9391         GLushort *pixelRowStart = pixels.data();
9392         pixelRowStart += n * packSkipPixels + k * packSkipRows;
9393 
9394         std::vector<bool> modifiedPixels(componentCount, false);
9395 
9396         char errorInfo[200];
9397 
9398         for (GLuint row = 0; row < height; ++row)
9399         {
9400             GLushort *curPixel = pixelRowStart;
9401             for (GLuint col = 0, len = (row == height - 1) ? width : std::min(l, width); col < len;
9402                  ++col)
9403             {
9404                 snprintf(errorInfo, sizeof(errorInfo),
9405                          "extent: {%u, %u}, coord: (%u, %u), rowLength: %d, alignment: %d, "
9406                          "skipPixels: %d, skipRows: %d\n",
9407                          width, height, col, row, packRowLength, packAlignment, packSkipPixels,
9408                          packSkipRows);
9409                 EXPECT_EQ(color.R, curPixel[0]) << errorInfo;
9410                 EXPECT_EQ(color.G, curPixel[1]) << errorInfo;
9411                 EXPECT_EQ(color.B, curPixel[2]) << errorInfo;
9412                 EXPECT_EQ(color.A, curPixel[3]) << errorInfo;
9413 
9414                 std::ptrdiff_t diff      = curPixel - pixels.data();
9415                 modifiedPixels[diff + 0] = true;
9416                 modifiedPixels[diff + 1] = true;
9417                 modifiedPixels[diff + 2] = true;
9418                 modifiedPixels[diff + 3] = true;
9419 
9420                 curPixel += n;
9421             }
9422             pixelRowStart += k;
9423         }
9424 
9425         for (std::size_t i = 0; i < modifiedPixels.size(); ++i)
9426         {
9427             if (!modifiedPixels[i])
9428             {
9429                 EXPECT_EQ(pixels[i], kDirtyValue);
9430             }
9431         }
9432     }
9433 
testNorm16RenderAndReadPixels(GLint internalformat,GLenum format,GLenum type)9434     void testNorm16RenderAndReadPixels(GLint internalformat, GLenum format, GLenum type)
9435     {
9436         // TODO(http://anglebug.com/4089) Fails on Win Intel OpenGL driver
9437         ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
9438         // TODO(http://anglebug.com/4245) Fails on Win AMD OpenGL driver
9439         ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
9440         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
9441 
9442         GLushort pixelValue  = 0x6A35;
9443         GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
9444         GLColor16UI color    = SliceFormatColor16UI(
9445             format, GLColor16UI(pixelValue, pixelValue, pixelValue, pixelValue));
9446         // Size of drawing viewport
9447         constexpr GLint width = 8, height = 8;
9448 
9449         setUpProgram();
9450 
9451         glBindTexture(GL_TEXTURE_2D, mTextures[1]);
9452         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, type, nullptr);
9453 
9454         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9455         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
9456                                0);
9457 
9458         glBindTexture(GL_TEXTURE_2D, mTextures[2]);
9459         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
9460         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9461         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9462 
9463         EXPECT_GL_NO_ERROR();
9464 
9465         drawQuad(mProgram, "position", 0.5f);
9466 
9467         // ReadPixels against different width, height, pixel pack mode combinations to test
9468         // workaround of pixels rearrangement
9469 
9470         // {x, y, width, height}
9471         std::vector<std::array<GLint, 4>> areas = {
9472             {0, 0, 1, 1}, {0, 0, 1, 2}, {0, 0, 2, 1}, {0, 0, 2, 2},
9473             {0, 0, 3, 2}, {0, 0, 3, 3}, {0, 0, 4, 3}, {0, 0, 4, 4},
9474 
9475             {1, 3, 3, 2}, {1, 3, 3, 3}, {3, 2, 4, 3}, {3, 2, 4, 4},
9476 
9477             {0, 0, 5, 6}, {2, 1, 5, 6}, {0, 0, 6, 1}, {0, 0, 7, 1},
9478             {0, 0, 7, 3}, {0, 0, 7, 8}, {1, 0, 7, 8}, {0, 0, 8, 8},
9479         };
9480 
9481         // Put default settings at the last
9482         std::vector<GLint> paramsPackRowLength = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0};
9483         std::vector<GLint> paramsPackAlignment = {1, 2, 8, 4};
9484         std::vector<std::array<GLint, 2>> paramsPackSkipPixelsAndRows = {{1, 0}, {0, 1},   {1, 1},
9485                                                                          {3, 1}, {20, 20}, {0, 0}};
9486 
9487         // Restore pixel pack modes later
9488         GLint restorePackAlignment;
9489         glGetIntegerv(GL_PACK_ALIGNMENT, &restorePackAlignment);
9490         GLint restorePackRowLength;
9491         glGetIntegerv(GL_PACK_ROW_LENGTH, &restorePackRowLength);
9492         GLint restorePackSkipPixels;
9493         glGetIntegerv(GL_PACK_SKIP_PIXELS, &restorePackSkipPixels);
9494         GLint restorePackSkipRows;
9495         glGetIntegerv(GL_PACK_SKIP_ROWS, &restorePackSkipRows);
9496 
9497         // Variable symbols are based on:
9498         // https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml
9499         for (const auto &skipped : paramsPackSkipPixelsAndRows)
9500         {
9501             glPixelStorei(GL_PACK_SKIP_PIXELS, skipped[0]);
9502             glPixelStorei(GL_PACK_SKIP_ROWS, skipped[1]);
9503             for (GLint a : paramsPackAlignment)
9504             {
9505                 glPixelStorei(GL_PACK_ALIGNMENT, a);
9506                 for (GLint l : paramsPackRowLength)
9507                 {
9508                     glPixelStorei(GL_PACK_ROW_LENGTH, l);
9509 
9510                     for (const auto &area : areas)
9511                     {
9512                         ASSERT(area[0] + area[2] <= width);
9513                         ASSERT(area[1] + area[3] <= height);
9514                         testReadPixelsRGBAWithRangeAndPixelStoreMode(area[0], area[1], area[2],
9515                                                                      area[3], l, a, skipped[0],
9516                                                                      skipped[1], type, color);
9517                     }
9518                 }
9519             }
9520         }
9521 
9522         glPixelStorei(GL_PACK_ALIGNMENT, restorePackAlignment);
9523         glPixelStorei(GL_PACK_ROW_LENGTH, restorePackRowLength);
9524         glPixelStorei(GL_PACK_SKIP_PIXELS, restorePackSkipPixels);
9525         glPixelStorei(GL_PACK_SKIP_ROWS, restorePackSkipRows);
9526 
9527         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
9528         glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
9529         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
9530                                   mRenderbuffer);
9531         glBindRenderbuffer(GL_RENDERBUFFER, 0);
9532         EXPECT_GL_NO_ERROR();
9533 
9534         glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
9535         glClear(GL_COLOR_BUFFER_BIT);
9536 
9537         EXPECT_PIXEL_16UI_COLOR(
9538             0, 0, SliceFormatColor16UI(format, GLColor16UI(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)));
9539 
9540         glBindTexture(GL_TEXTURE_2D, mTextures[1]);
9541         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
9542 
9543         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
9544                                0);
9545         EXPECT_PIXEL_16UI_COLOR(
9546             0, 0, SliceFormatColor16UI(format, GLColor16UI(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)));
9547 
9548         ASSERT_GL_NO_ERROR();
9549 
9550         glBindFramebuffer(GL_FRAMEBUFFER, 0);
9551     }
9552 
9553     GLuint mTextures[3];
9554     GLuint mFBO;
9555     GLuint mRenderbuffer;
9556 };
9557 
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16TextureTest)9558 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16TextureTest)
9559 {
9560     testNorm16Texture(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
9561 }
9562 
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16SNORMTextureTest)9563 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16SNORMTextureTest)
9564 {
9565     testNorm16Texture(GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
9566 }
9567 
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16TextureTest)9568 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16TextureTest)
9569 {
9570     testNorm16Texture(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
9571 }
9572 
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16SNORMTextureTest)9573 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16SNORMTextureTest)
9574 {
9575     testNorm16Texture(GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
9576 }
9577 
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGB16TextureTest)9578 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGB16TextureTest)
9579 {
9580     // (http://anglebug.com/4215) Driver bug on some Qualcomm Adreno gpu
9581     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
9582 
9583     testNorm16Texture(GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
9584 }
9585 
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGB16SNORMTextureTest)9586 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGB16SNORMTextureTest)
9587 {
9588     // (http://anglebug.com/4215) Driver bug on some Qualcomm Adreno gpu
9589     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
9590 
9591     testNorm16Texture(GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
9592 }
9593 
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16TextureTest)9594 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16TextureTest)
9595 {
9596     testNorm16Texture(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
9597 }
9598 
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16SNORMTextureTest)9599 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16SNORMTextureTest)
9600 {
9601     testNorm16Texture(GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
9602 }
9603 
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16RenderTest)9604 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16RenderTest)
9605 {
9606     // http://anglebug.com/5153
9607     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
9608 
9609     testNorm16RenderAndReadPixels(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
9610 }
9611 
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16RenderTest)9612 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16RenderTest)
9613 {
9614     // http://anglebug.com/5153
9615     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
9616 
9617     testNorm16RenderAndReadPixels(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
9618 }
9619 
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16RenderTest)9620 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16RenderTest)
9621 {
9622     // http://anglebug.com/5153
9623     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
9624 
9625     testNorm16RenderAndReadPixels(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
9626 }
9627 
9628 class Texture2DRGTest : public Texture2DTest
9629 {
9630   protected:
Texture2DRGTest()9631     Texture2DRGTest()
9632         : Texture2DTest(), mRenderableTexture(0), mTestTexture(0), mFBO(0), mRenderbuffer(0)
9633     {}
9634 
testSetUp()9635     void testSetUp() override
9636     {
9637         Texture2DTest::testSetUp();
9638 
9639         glActiveTexture(GL_TEXTURE0);
9640         glGenTextures(1, &mRenderableTexture);
9641         glGenTextures(1, &mTestTexture);
9642         glGenFramebuffers(1, &mFBO);
9643         glGenRenderbuffers(1, &mRenderbuffer);
9644 
9645         glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
9646         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9647         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9648         glBindTexture(GL_TEXTURE_2D, mTestTexture);
9649         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9650         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9651 
9652         glBindTexture(GL_TEXTURE_2D, 0);
9653 
9654         setUpProgram();
9655         glUseProgram(mProgram);
9656         glUniform1i(mTexture2DUniformLocation, 0);
9657 
9658         ASSERT_GL_NO_ERROR();
9659     }
9660 
testTearDown()9661     void testTearDown() override
9662     {
9663         glDeleteTextures(1, &mRenderableTexture);
9664         glDeleteTextures(1, &mTestTexture);
9665         glDeleteFramebuffers(1, &mFBO);
9666         glDeleteRenderbuffers(1, &mRenderbuffer);
9667 
9668         Texture2DTest::testTearDown();
9669     }
9670 
setupFormatTextures(GLenum internalformat,GLenum format,GLenum type,GLvoid * imageData)9671     void setupFormatTextures(GLenum internalformat, GLenum format, GLenum type, GLvoid *imageData)
9672     {
9673         glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
9674         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9675 
9676         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9677         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
9678                                mRenderableTexture, 0);
9679 
9680         glBindTexture(GL_TEXTURE_2D, mTestTexture);
9681         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
9682 
9683         EXPECT_GL_NO_ERROR();
9684     }
9685 
testRGTexture(GLColor expectedColor)9686     void testRGTexture(GLColor expectedColor)
9687     {
9688         drawQuad(mProgram, "position", 0.5f);
9689 
9690         EXPECT_GL_NO_ERROR();
9691         EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, kPixelTolerance);
9692     }
9693 
testRGRender(GLenum internalformat,GLenum format)9694     void testRGRender(GLenum internalformat, GLenum format)
9695     {
9696         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
9697         glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
9698         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
9699                                   mRenderbuffer);
9700         glBindRenderbuffer(GL_RENDERBUFFER, 0);
9701         EXPECT_GL_NO_ERROR();
9702 
9703         glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
9704         glClear(GL_COLOR_BUFFER_BIT);
9705 
9706         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
9707 
9708         ASSERT_GL_NO_ERROR();
9709         EXPECT_PIXEL_COLOR_EQ(0, 0, SliceFormatColor(format, GLColor(255u, 255u, 255u, 255u)));
9710     }
9711 
9712     GLuint mRenderableTexture;
9713     GLuint mTestTexture;
9714     GLuint mFBO;
9715     GLuint mRenderbuffer;
9716 };
9717 
9718 // Test unorm texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGUNormTest)9719 TEST_P(Texture2DRGTest, TextureRGUNormTest)
9720 {
9721     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
9722     // This workaround causes a GL error on Windows AMD, which is likely a driver bug.
9723     // The workaround is not intended to be enabled in this configuration so skip it.
9724     ANGLE_SKIP_TEST_IF(
9725         getEGLWindow()->isFeatureEnabled(Feature::EmulateCopyTexImage2DFromRenderbuffers) &&
9726         IsWindows() && IsAMD());
9727 
9728     GLubyte pixelValue  = 0xab;
9729     GLubyte imageData[] = {pixelValue, pixelValue};
9730 
9731     setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_UNSIGNED_BYTE, imageData);
9732     testRGTexture(
9733         SliceFormatColor(GL_RED_EXT, GLColor(pixelValue, pixelValue, pixelValue, pixelValue)));
9734     testRGRender(GL_R8_EXT, GL_RED_EXT);
9735 
9736     setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_UNSIGNED_BYTE, imageData);
9737     testRGTexture(
9738         SliceFormatColor(GL_RG_EXT, GLColor(pixelValue, pixelValue, pixelValue, pixelValue)));
9739     testRGRender(GL_RG8_EXT, GL_RG_EXT);
9740 }
9741 
9742 // Test float texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGFloatTest)9743 TEST_P(Texture2DRGTest, TextureRGFloatTest)
9744 {
9745     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
9746     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
9747 
9748     GLfloat pixelValue  = 0.54321;
9749     GLfloat imageData[] = {pixelValue, pixelValue};
9750 
9751     GLubyte expectedValue = static_cast<GLubyte>(pixelValue * 255.0f);
9752     GLColor expectedColor = GLColor(expectedValue, expectedValue, expectedValue, expectedValue);
9753 
9754     setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_FLOAT, imageData);
9755     testRGTexture(SliceFormatColor(GL_RED_EXT, expectedColor));
9756 
9757     setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_FLOAT, imageData);
9758     testRGTexture(SliceFormatColor(GL_RG_EXT, expectedColor));
9759 }
9760 
9761 // Test half-float texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGHalfFloatTest)9762 TEST_P(Texture2DRGTest, TextureRGHalfFloatTest)
9763 {
9764     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
9765     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
9766 
9767     GLfloat pixelValueFloat = 0.543f;
9768     GLhalf pixelValue       = 0x3858;
9769     GLhalf imageData[]      = {pixelValue, pixelValue};
9770 
9771     GLubyte expectedValue = static_cast<GLubyte>(pixelValueFloat * 255.0f);
9772     GLColor expectedColor = GLColor(expectedValue, expectedValue, expectedValue, expectedValue);
9773 
9774     setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES, imageData);
9775     testRGTexture(SliceFormatColor(GL_RED_EXT, expectedColor));
9776 
9777     setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_HALF_FLOAT_OES, imageData);
9778     testRGTexture(SliceFormatColor(GL_RG_EXT, expectedColor));
9779 }
9780 
9781 class Texture2DFloatTest : public Texture2DTest
9782 {
9783   protected:
Texture2DFloatTest()9784     Texture2DFloatTest()
9785         : Texture2DTest(), mRenderableTexture(0), mTestTexture(0), mFBO(0), mRenderbuffer(0)
9786     {}
9787 
testSetUp()9788     void testSetUp() override
9789     {
9790         Texture2DTest::testSetUp();
9791 
9792         glActiveTexture(GL_TEXTURE0);
9793         glGenTextures(1, &mRenderableTexture);
9794         glGenTextures(1, &mTestTexture);
9795         glGenFramebuffers(1, &mFBO);
9796         glGenRenderbuffers(1, &mRenderbuffer);
9797 
9798         setUpProgram();
9799         glUseProgram(mProgram);
9800         glUniform1i(mTexture2DUniformLocation, 0);
9801 
9802         glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
9803         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9804 
9805         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9806         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
9807                                mRenderableTexture, 0);
9808 
9809         ASSERT_GL_NO_ERROR();
9810     }
9811 
testTearDown()9812     void testTearDown() override
9813     {
9814         glDeleteTextures(1, &mRenderableTexture);
9815         glDeleteTextures(1, &mTestTexture);
9816         glDeleteFramebuffers(1, &mFBO);
9817         glDeleteRenderbuffers(1, &mRenderbuffer);
9818 
9819         Texture2DTest::testTearDown();
9820     }
9821 
testFloatTextureSample(GLenum internalFormat,GLenum format,GLenum type)9822     void testFloatTextureSample(GLenum internalFormat, GLenum format, GLenum type)
9823     {
9824         constexpr GLfloat imageDataFloat[] = {
9825             0.2f,
9826             0.3f,
9827             0.4f,
9828             0.5f,
9829         };
9830         constexpr GLhalf imageDataHalf[] = {
9831             0x3266,
9832             0x34CD,
9833             0x3666,
9834             0x3800,
9835         };
9836         GLColor expectedValue;
9837         for (int i = 0; i < 4; i++)
9838         {
9839             expectedValue[i] = static_cast<GLubyte>(imageDataFloat[i] * 255.0f);
9840         }
9841 
9842         const GLvoid *imageData;
9843         switch (type)
9844         {
9845             case GL_FLOAT:
9846                 imageData = imageDataFloat;
9847                 break;
9848             case GL_HALF_FLOAT:
9849             case GL_HALF_FLOAT_OES:
9850                 imageData = imageDataHalf;
9851                 break;
9852             default:
9853                 imageData = nullptr;
9854         }
9855         ASSERT(imageData != nullptr);
9856 
9857         glBindTexture(GL_TEXTURE_2D, mTestTexture);
9858         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, imageData);
9859 
9860         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9861         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9862 
9863         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9864         drawQuad(mProgram, "position", 0.5f);
9865 
9866         EXPECT_GL_NO_ERROR();
9867         EXPECT_PIXEL_COLOR_NEAR(0, 0, SliceFormatColor(format, expectedValue), kPixelTolerance);
9868     }
9869 
testFloatTextureLinear(GLenum internalFormat,GLenum format,GLenum type)9870     void testFloatTextureLinear(GLenum internalFormat, GLenum format, GLenum type)
9871     {
9872         int numComponents;
9873         switch (format)
9874         {
9875             case GL_RGBA:
9876                 numComponents = 4;
9877                 break;
9878             case GL_RGB:
9879                 numComponents = 3;
9880                 break;
9881             case GL_LUMINANCE_ALPHA:
9882                 numComponents = 2;
9883                 break;
9884             case GL_LUMINANCE:
9885             case GL_ALPHA:
9886                 numComponents = 1;
9887                 break;
9888             default:
9889                 numComponents = 0;
9890         }
9891         ASSERT(numComponents > 0);
9892 
9893         constexpr GLfloat pixelIntensitiesFloat[] = {0.0f, 1.0f, 0.0f, 1.0f};
9894         constexpr GLhalf pixelIntensitiesHalf[]   = {0x0000, 0x3C00, 0x0000, 0x3C00};
9895 
9896         GLfloat imageDataFloat[16];
9897         GLhalf imageDataHalf[16];
9898         for (int i = 0; i < 4; i++)
9899         {
9900             for (int c = 0; c < numComponents; c++)
9901             {
9902                 imageDataFloat[i * numComponents + c] = pixelIntensitiesFloat[i];
9903                 imageDataHalf[i * numComponents + c]  = pixelIntensitiesHalf[i];
9904             }
9905         }
9906 
9907         const GLvoid *imageData;
9908         switch (type)
9909         {
9910             case GL_FLOAT:
9911                 imageData = imageDataFloat;
9912                 break;
9913             case GL_HALF_FLOAT:
9914             case GL_HALF_FLOAT_OES:
9915                 imageData = imageDataHalf;
9916                 break;
9917             default:
9918                 imageData = nullptr;
9919         }
9920         ASSERT(imageData != nullptr);
9921 
9922         glBindTexture(GL_TEXTURE_2D, mTestTexture);
9923         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 2, 2, 0, format, type, imageData);
9924 
9925         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9926         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9927 
9928         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9929         drawQuad(mProgram, "position", 0.5f);
9930 
9931         EXPECT_GL_NO_ERROR();
9932         // Source texture contains 2 black pixels and 2 white pixels, we sample in the center so we
9933         // should expect the final value to be gray (halfway in-between)
9934         EXPECT_PIXEL_COLOR_NEAR(0, 0, SliceFormatColor(format, GLColor(127u, 127u, 127u, 127u)),
9935                                 kPixelTolerance);
9936     }
9937 
performFloatTextureRender(GLenum internalFormat,GLenum renderBufferFormat,GLenum format,GLenum type)9938     bool performFloatTextureRender(GLenum internalFormat,
9939                                    GLenum renderBufferFormat,
9940                                    GLenum format,
9941                                    GLenum type)
9942     {
9943         glBindTexture(GL_TEXTURE_2D, mTestTexture);
9944         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, nullptr);
9945         glBindTexture(GL_TEXTURE_2D, 0);
9946 
9947         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
9948         glRenderbufferStorage(GL_RENDERBUFFER, renderBufferFormat, 1, 1);
9949         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
9950                                   mRenderbuffer);
9951         glBindRenderbuffer(GL_RENDERBUFFER, 0);
9952         EXPECT_GL_NO_ERROR();
9953 
9954         if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
9955         {
9956             return false;
9957         }
9958 
9959         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9960 
9961         glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
9962         glClear(GL_COLOR_BUFFER_BIT);
9963 
9964         EXPECT_GL_NO_ERROR();
9965         return true;
9966     }
9967 
9968     GLuint mRenderableTexture;
9969     GLuint mTestTexture;
9970     GLuint mFBO;
9971     GLuint mRenderbuffer;
9972 };
9973 
9974 class Texture2DFloatTestES3 : public Texture2DFloatTest
9975 {
9976   protected:
testFloatTextureRender(GLenum internalFormat,GLenum format,GLenum type)9977     void testFloatTextureRender(GLenum internalFormat, GLenum format, GLenum type)
9978     {
9979         bool framebufferComplete =
9980             performFloatTextureRender(internalFormat, internalFormat, format, type);
9981         EXPECT_TRUE(framebufferComplete);
9982         EXPECT_PIXEL_COLOR32F_NEAR(0, 0,
9983                                    SliceFormatColor32F(format, GLColor32F(1.0f, 1.0f, 1.0f, 1.0f)),
9984                                    kPixelTolerance32F);
9985     }
9986 };
9987 
9988 class Texture2DFloatTestES2 : public Texture2DFloatTest
9989 {
9990   protected:
checkFloatTextureRender(GLenum renderBufferFormat,GLenum format,GLenum type)9991     bool checkFloatTextureRender(GLenum renderBufferFormat, GLenum format, GLenum type)
9992     {
9993         bool framebufferComplete =
9994             performFloatTextureRender(format, renderBufferFormat, format, type);
9995 
9996         if (!framebufferComplete)
9997         {
9998             return false;
9999         }
10000 
10001         EXPECT_PIXEL_COLOR32F_NEAR(0, 0,
10002                                    SliceFormatColor32F(format, GLColor32F(1.0f, 1.0f, 1.0f, 1.0f)),
10003                                    kPixelTolerance32F);
10004         return true;
10005     }
10006 };
10007 
10008 // Test texture sampling for ES3 float texture formats
TEST_P(Texture2DFloatTestES3,TextureFloatSampleBasicTest)10009 TEST_P(Texture2DFloatTestES3, TextureFloatSampleBasicTest)
10010 {
10011     testFloatTextureSample(GL_RGBA32F, GL_RGBA, GL_FLOAT);
10012     testFloatTextureSample(GL_RGB32F, GL_RGB, GL_FLOAT);
10013 }
10014 
10015 // Test texture sampling for ES2 float texture formats
TEST_P(Texture2DFloatTestES2,TextureFloatSampleBasicTest)10016 TEST_P(Texture2DFloatTestES2, TextureFloatSampleBasicTest)
10017 {
10018     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10019     testFloatTextureSample(GL_RGBA, GL_RGBA, GL_FLOAT);
10020     testFloatTextureSample(GL_RGB, GL_RGB, GL_FLOAT);
10021 }
10022 
10023 // Test texture sampling for ES3 half float texture formats
TEST_P(Texture2DFloatTestES3,TextureHalfFloatSampleBasicTest)10024 TEST_P(Texture2DFloatTestES3, TextureHalfFloatSampleBasicTest)
10025 {
10026     testFloatTextureSample(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
10027     testFloatTextureSample(GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
10028 }
10029 
10030 // Test texture sampling for ES2 half float texture formats
TEST_P(Texture2DFloatTestES2,TextureHalfFloatSampleBasicTest)10031 TEST_P(Texture2DFloatTestES2, TextureHalfFloatSampleBasicTest)
10032 {
10033     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10034     testFloatTextureSample(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES);
10035     testFloatTextureSample(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES);
10036 }
10037 
10038 // Test texture sampling for legacy GLES 2.0 float texture formats in ES3
TEST_P(Texture2DFloatTestES3,TextureFloatSampleLegacyTest)10039 TEST_P(Texture2DFloatTestES3, TextureFloatSampleLegacyTest)
10040 {
10041     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10042 
10043     testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10044     testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10045     testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10046 
10047     if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10048     {
10049         testFloatTextureSample(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT);
10050         testFloatTextureSample(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT);
10051         testFloatTextureSample(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT);
10052     }
10053 }
10054 
10055 // Test texture sampling for legacy GLES 2.0 float texture formats in ES2
TEST_P(Texture2DFloatTestES2,TextureFloatSampleLegacyTest)10056 TEST_P(Texture2DFloatTestES2, TextureFloatSampleLegacyTest)
10057 {
10058     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10059 
10060     testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10061     testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10062     testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10063 }
10064 
10065 // Test texture sampling for legacy GLES 2.0 half float texture formats in ES3
TEST_P(Texture2DFloatTestES3,TextureHalfFloatSampleLegacyTest)10066 TEST_P(Texture2DFloatTestES3, TextureHalfFloatSampleLegacyTest)
10067 {
10068     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10069 
10070     testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10071     testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10072     testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10073 
10074     if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10075     {
10076         testFloatTextureSample(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT);
10077         testFloatTextureSample(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT);
10078         testFloatTextureSample(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT);
10079     }
10080 }
10081 // Test texture sampling for legacy GLES 2.0 half float texture formats in ES2
TEST_P(Texture2DFloatTestES2,TextureHalfFloatSampleLegacyTest)10082 TEST_P(Texture2DFloatTestES2, TextureHalfFloatSampleLegacyTest)
10083 {
10084     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10085 
10086     testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10087     testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10088     testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10089 }
10090 
10091 // Test linear sampling for ES3 32F formats
TEST_P(Texture2DFloatTestES3,TextureFloatLinearTest)10092 TEST_P(Texture2DFloatTestES3, TextureFloatLinearTest)
10093 {
10094     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
10095     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10096 
10097     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10098 
10099     testFloatTextureLinear(GL_RGBA32F, GL_RGBA, GL_FLOAT);
10100     testFloatTextureLinear(GL_RGB32F, GL_RGB, GL_FLOAT);
10101 }
10102 // Test linear sampling for ES2 32F formats
TEST_P(Texture2DFloatTestES2,TextureFloatLinearTest)10103 TEST_P(Texture2DFloatTestES2, TextureFloatLinearTest)
10104 {
10105     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
10106     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10107 
10108     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10109 
10110     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10111 
10112     testFloatTextureLinear(GL_RGBA, GL_RGBA, GL_FLOAT);
10113 }
10114 
10115 // Test linear sampling for ES3 16F formats
TEST_P(Texture2DFloatTestES3,TextureHalfFloatLinearTest)10116 TEST_P(Texture2DFloatTestES3, TextureHalfFloatLinearTest)
10117 {
10118     // Half float formats must be linearly filterable in GLES 3.0 core
10119     testFloatTextureLinear(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
10120     testFloatTextureLinear(GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
10121 }
10122 // Test linear sampling for ES2 16F formats
TEST_P(Texture2DFloatTestES2,TextureHalfFloatLinearTest)10123 TEST_P(Texture2DFloatTestES2, TextureHalfFloatLinearTest)
10124 {
10125     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
10126     testFloatTextureLinear(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES);
10127     testFloatTextureLinear(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES);
10128 }
10129 
10130 // Test linear sampling for legacy GLES 2.0 32F formats in ES3
TEST_P(Texture2DFloatTestES3,TextureFloatLinearLegacyTest)10131 TEST_P(Texture2DFloatTestES3, TextureFloatLinearLegacyTest)
10132 {
10133     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
10134     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10135 
10136     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10137     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10138 
10139     testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10140     testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10141     testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10142 
10143     if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10144     {
10145         testFloatTextureLinear(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT);
10146         testFloatTextureLinear(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT);
10147         testFloatTextureLinear(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT);
10148     }
10149 }
10150 // Test linear sampling for legacy GLES 2.0 32F formats in ES2
TEST_P(Texture2DFloatTestES2,TextureFloatLinearLegacyTest)10151 TEST_P(Texture2DFloatTestES2, TextureFloatLinearLegacyTest)
10152 {
10153     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
10154     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10155 
10156     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10157     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10158 
10159     testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10160     testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10161     testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10162 }
10163 
10164 // Test linear sampling for legacy GLES 2.0 16F formats in ES3
TEST_P(Texture2DFloatTestES3,TextureHalfFloatLinearLegacyTest)10165 TEST_P(Texture2DFloatTestES3, TextureHalfFloatLinearLegacyTest)
10166 {
10167     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10168     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
10169 
10170     testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10171     testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10172     testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10173 
10174     if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10175     {
10176         testFloatTextureLinear(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT);
10177         testFloatTextureLinear(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT);
10178         testFloatTextureLinear(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT);
10179     }
10180 }
10181 // Test linear sampling for legacy GLES 2.0 16F formats in ES2
TEST_P(Texture2DFloatTestES2,TextureHalfFloatLinearLegacyTest)10182 TEST_P(Texture2DFloatTestES2, TextureHalfFloatLinearLegacyTest)
10183 {
10184     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10185     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
10186 
10187     testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10188     testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10189     testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10190 }
10191 
10192 // Test color-renderability for ES3 float and half float textures
TEST_P(Texture2DFloatTestES3,TextureFloatRenderTest)10193 TEST_P(Texture2DFloatTestES3, TextureFloatRenderTest)
10194 {
10195     // http://anglebug.com/4092
10196     ANGLE_SKIP_TEST_IF(IsD3D9());
10197     // EXT_color_buffer_float covers float, half float, and 11-11-10 float formats
10198     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
10199 
10200     testFloatTextureRender(GL_R32F, GL_RED, GL_FLOAT);
10201     testFloatTextureRender(GL_RG32F, GL_RG, GL_FLOAT);
10202     testFloatTextureRender(GL_RGBA32F, GL_RGBA, GL_FLOAT);
10203 
10204     testFloatTextureRender(GL_R16F, GL_RED, GL_HALF_FLOAT);
10205     testFloatTextureRender(GL_RG16F, GL_RG, GL_HALF_FLOAT);
10206     testFloatTextureRender(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
10207 
10208     testFloatTextureRender(GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT);
10209 }
10210 
10211 // Test color-renderability for ES2 half float textures
TEST_P(Texture2DFloatTestES2,TextureFloatRenderTest)10212 TEST_P(Texture2DFloatTestES2, TextureFloatRenderTest)
10213 {
10214     // EXT_color_buffer_half_float requires at least one format to be renderable, but does not
10215     // require a specific one
10216     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
10217     // https://crbug.com/1003971
10218     ANGLE_SKIP_TEST_IF(IsOzone());
10219     // http://anglebug.com/4092
10220     ANGLE_SKIP_TEST_IF(IsD3D9());
10221 
10222     bool atLeastOneSupported = false;
10223 
10224     if (IsGLExtensionEnabled("GL_OES_texture_half_float") ||
10225         IsGLExtensionEnabled("GL_OES_texture_half_float"))
10226     {
10227         atLeastOneSupported |= checkFloatTextureRender(GL_R16F_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES);
10228         atLeastOneSupported |= checkFloatTextureRender(GL_RG16F_EXT, GL_RG_EXT, GL_HALF_FLOAT_OES);
10229     }
10230     if (IsGLExtensionEnabled("GL_OES_texture_half_float"))
10231     {
10232         atLeastOneSupported |= checkFloatTextureRender(GL_RGB16F_EXT, GL_RGB, GL_HALF_FLOAT_OES);
10233 
10234         // If OES_texture_half_float is supported, then RGBA half float textures must be renderable
10235         bool rgbaSupported = checkFloatTextureRender(GL_RGBA16F_EXT, GL_RGBA, GL_HALF_FLOAT_OES);
10236         EXPECT_TRUE(rgbaSupported);
10237         atLeastOneSupported |= rgbaSupported;
10238     }
10239 
10240     EXPECT_TRUE(atLeastOneSupported);
10241 }
10242 
10243 // Test that UNPACK_SKIP_IMAGES doesn't have an effect on 2D texture uploads.
10244 // GLES 3.0.4 section 3.8.3.
TEST_P(Texture2DTestES3,UnpackSkipImages2D)10245 TEST_P(Texture2DTestES3, UnpackSkipImages2D)
10246 {
10247     // Crashes on Nexus 5X due to a driver bug. http://anglebug.com/1429
10248     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
10249 
10250     glBindTexture(GL_TEXTURE_2D, mTexture2D);
10251     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10252     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10253     ASSERT_GL_NO_ERROR();
10254 
10255     // SKIP_IMAGES should not have an effect on uploading 2D textures
10256     glPixelStorei(GL_UNPACK_SKIP_IMAGES, 1000);
10257     ASSERT_GL_NO_ERROR();
10258 
10259     std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
10260 
10261     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10262                  pixelsGreen.data());
10263     ASSERT_GL_NO_ERROR();
10264 
10265     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE,
10266                     pixelsGreen.data());
10267     ASSERT_GL_NO_ERROR();
10268 
10269     glUseProgram(mProgram);
10270     drawQuad(mProgram, "position", 0.5f);
10271     ASSERT_GL_NO_ERROR();
10272 
10273     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10274 }
10275 
10276 // Test that skip defined in unpack parameters is taken into account when determining whether
10277 // unpacking source extends outside unpack buffer bounds.
TEST_P(Texture2DTestES3,UnpackSkipPixelsOutOfBounds)10278 TEST_P(Texture2DTestES3, UnpackSkipPixelsOutOfBounds)
10279 {
10280     glBindTexture(GL_TEXTURE_2D, mTexture2D);
10281     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10282     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10283     ASSERT_GL_NO_ERROR();
10284 
10285     GLBuffer buf;
10286     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
10287     std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
10288     glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
10289                  GL_DYNAMIC_COPY);
10290     ASSERT_GL_NO_ERROR();
10291 
10292     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10293     ASSERT_GL_NO_ERROR();
10294 
10295     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 1);
10296     ASSERT_GL_NO_ERROR();
10297 
10298     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10299     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
10300 
10301     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
10302     glPixelStorei(GL_UNPACK_SKIP_ROWS, 1);
10303     ASSERT_GL_NO_ERROR();
10304 
10305     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10306     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
10307 }
10308 
10309 // Test unpacking to texture from a buffer with a compatible format but different type.
10310 // Compatible formats can be found in "Table 8.2: Valid combinations of format, type, and sized
10311 // internal format." of the OpenGL ES 3.2 spec.
TEST_P(Texture2DTestES3,UnpackCompatibleFormatButDifferentType)10312 TEST_P(Texture2DTestES3, UnpackCompatibleFormatButDifferentType)
10313 {
10314     glBindTexture(GL_TEXTURE_2D, mTexture2D);
10315     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10316     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10317     ASSERT_GL_NO_ERROR();
10318 
10319     // Create texture with GL_RGBA4 format and fill with red
10320     std::vector<GLColor> pixelsRed(128u * 128u, GLColor::red);
10321     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10322                  pixelsRed.data());
10323     ASSERT_GL_NO_ERROR();
10324 
10325     // Call glTexSubImage2D with incompatible format and expect an error
10326     std::array<GLubyte, 2> rgColor = {255, 255};
10327     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RG, GL_UNSIGNED_BYTE, rgColor.data());
10328     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
10329 
10330     glUseProgram(mProgram);
10331     drawQuad(mProgram, "position", 0.5f);
10332     ASSERT_GL_NO_ERROR();
10333     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10334 
10335     // Create unpack buffer with GL_RGBA8
10336     GLBuffer buf;
10337     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
10338     std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
10339     glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
10340                  GL_DYNAMIC_COPY);
10341     ASSERT_GL_NO_ERROR();
10342 
10343     // Unpack GL_RGBA8 buffer data to GL_RGBA4 texture
10344     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10345     ASSERT_GL_NO_ERROR();
10346 
10347     // Validate that the data was unpacked correctly
10348     glUseProgram(mProgram);
10349     drawQuad(mProgram, "position", 0.5f);
10350     ASSERT_GL_NO_ERROR();
10351 
10352     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10353 }
10354 
10355 // Test that unpacking rows that overlap in a pixel unpack buffer works as expected.
TEST_P(Texture2DTestES3,UnpackOverlappingRowsFromUnpackBuffer)10356 TEST_P(Texture2DTestES3, UnpackOverlappingRowsFromUnpackBuffer)
10357 {
10358     ANGLE_SKIP_TEST_IF(IsD3D11());
10359 
10360     // Incorrect rendering results seen on OSX AMD.
10361     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac() && IsAMD());
10362 
10363     const GLuint width            = 8u;
10364     const GLuint height           = 8u;
10365     const GLuint unpackRowLength  = 5u;
10366     const GLuint unpackSkipPixels = 1u;
10367 
10368     setWindowWidth(width);
10369     setWindowHeight(height);
10370 
10371     glBindTexture(GL_TEXTURE_2D, mTexture2D);
10372     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10373     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10374     ASSERT_GL_NO_ERROR();
10375 
10376     GLBuffer buf;
10377     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
10378     std::vector<GLColor> pixelsGreen((height - 1u) * unpackRowLength + width + unpackSkipPixels,
10379                                      GLColor::green);
10380 
10381     for (GLuint skippedPixel = 0u; skippedPixel < unpackSkipPixels; ++skippedPixel)
10382     {
10383         pixelsGreen[skippedPixel] = GLColor(255, 0, 0, 255);
10384     }
10385 
10386     glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
10387                  GL_DYNAMIC_COPY);
10388     ASSERT_GL_NO_ERROR();
10389 
10390     glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackRowLength);
10391     glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels);
10392     ASSERT_GL_NO_ERROR();
10393 
10394     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10395     ASSERT_GL_NO_ERROR();
10396 
10397     glUseProgram(mProgram);
10398     drawQuad(mProgram, "position", 0.5f);
10399     ASSERT_GL_NO_ERROR();
10400 
10401     GLuint windowPixelCount = getWindowWidth() * getWindowHeight();
10402     std::vector<GLColor> actual(windowPixelCount, GLColor::black);
10403     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10404                  actual.data());
10405     std::vector<GLColor> expected(windowPixelCount, GLColor::green);
10406     EXPECT_EQ(expected, actual);
10407 }
10408 
10409 template <typename T>
UNorm(double value)10410 T UNorm(double value)
10411 {
10412     return static_cast<T>(value * static_cast<double>(std::numeric_limits<T>::max()));
10413 }
10414 
10415 // Test rendering a depth texture with mipmaps.
TEST_P(Texture2DTestES3,DepthTexturesWithMipmaps)10416 TEST_P(Texture2DTestES3, DepthTexturesWithMipmaps)
10417 {
10418     // TODO(cwallez) this is failing on Intel Win7 OpenGL.
10419     // TODO(zmo) this is faling on Win Intel HD 530 Debug.
10420     // http://anglebug.com/1706
10421     ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
10422 
10423     // Seems to fail on AMD D3D11. Possibly driver bug. http://anglebug.com/3342
10424     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsD3D11());
10425 
10426     // TODO(cnorthrop): Also failing on Vulkan/Windows/AMD. http://anglebug.com/3950
10427     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
10428 
10429     const int size = getWindowWidth();
10430 
10431     auto dim   = [size](int level) { return size >> level; };
10432     int levels = gl::log2(size);
10433 
10434     glActiveTexture(GL_TEXTURE0);
10435     glBindTexture(GL_TEXTURE_2D, mTexture2D);
10436     glTexStorage2D(GL_TEXTURE_2D, levels, GL_DEPTH_COMPONENT24, size, size);
10437     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10438     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10439     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
10440     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
10441     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10442     ASSERT_GL_NO_ERROR();
10443 
10444     glUseProgram(mProgram);
10445     glUniform1i(mTexture2DUniformLocation, 0);
10446 
10447     std::vector<unsigned char> expected;
10448 
10449     for (int level = 0; level < levels; ++level)
10450     {
10451         double value = (static_cast<double>(level) / static_cast<double>(levels - 1));
10452         expected.push_back(UNorm<unsigned char>(value));
10453 
10454         int levelDim = dim(level);
10455 
10456         ASSERT_GT(levelDim, 0);
10457 
10458         std::vector<unsigned int> initData(levelDim * levelDim, UNorm<unsigned int>(value));
10459         glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, levelDim, levelDim, GL_DEPTH_COMPONENT,
10460                         GL_UNSIGNED_INT, initData.data());
10461     }
10462     ASSERT_GL_NO_ERROR();
10463 
10464     for (int level = 0; level < levels; ++level)
10465     {
10466         glViewport(0, 0, dim(level), dim(level));
10467         drawQuad(mProgram, "position", 0.5f);
10468         GLColor actual = ReadColor(0, 0);
10469         EXPECT_NEAR(expected[level], actual.R, 10u);
10470     }
10471 
10472     ASSERT_GL_NO_ERROR();
10473 }
10474 
10475 class Texture2DDepthTest : public Texture2DTest
10476 {
10477   protected:
Texture2DDepthTest()10478     Texture2DDepthTest() : Texture2DTest() {}
10479 
getVertexShaderSource()10480     const char *getVertexShaderSource() override
10481     {
10482         return "attribute vec4 vPosition;\n"
10483                "void main() {\n"
10484                "  gl_Position = vPosition;\n"
10485                "}\n";
10486     }
10487 
getFragmentShaderSource()10488     const char *getFragmentShaderSource() override
10489     {
10490         return "precision mediump float;\n"
10491                "uniform sampler2D ShadowMap;"
10492                "void main() {\n"
10493                "  vec4 shadow_value = texture2D(ShadowMap, vec2(0.5, 0.5));"
10494                "  if (shadow_value.x == shadow_value.z && shadow_value.x != 0.0) {"
10495                "    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);"
10496                "  } else {"
10497                "    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
10498                "  }"
10499                "}\n";
10500     }
10501 
checkTexImageFormatSupport(GLenum format,GLenum internalformat,GLenum type)10502     bool checkTexImageFormatSupport(GLenum format, GLenum internalformat, GLenum type)
10503     {
10504         EXPECT_GL_NO_ERROR();
10505 
10506         GLTexture tex;
10507         glBindTexture(GL_TEXTURE_2D, tex);
10508         glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, type, nullptr);
10509 
10510         return (glGetError() == GL_NO_ERROR);
10511     }
10512 
testBehavior(bool useSizedComponent)10513     void testBehavior(bool useSizedComponent)
10514     {
10515         int w                 = getWindowWidth();
10516         int h                 = getWindowHeight();
10517         GLuint format         = GL_DEPTH_COMPONENT;
10518         GLuint internalFormat = GL_DEPTH_COMPONENT;
10519 
10520         if (useSizedComponent)
10521         {
10522             internalFormat = GL_DEPTH_COMPONENT24;
10523         }
10524 
10525         GLFramebuffer fbo;
10526         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10527         ASSERT_GL_NO_ERROR();
10528 
10529         GLTexture depthTexture;
10530         glBindTexture(GL_TEXTURE_2D, depthTexture);
10531         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10532         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10533         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
10534         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
10535 
10536         TexCoordDrawTest::setUpProgram();
10537         GLint shadowMapLocation = glGetUniformLocation(mProgram, "ShadowMap");
10538         ASSERT_NE(-1, shadowMapLocation);
10539 
10540         GLint positionLocation = glGetAttribLocation(mProgram, "vPosition");
10541         ASSERT_NE(-1, positionLocation);
10542 
10543         ANGLE_SKIP_TEST_IF(!checkTexImageFormatSupport(format, internalFormat, GL_UNSIGNED_INT));
10544         glBindTexture(GL_TEXTURE_2D, depthTexture);
10545         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_INT, nullptr);
10546         ASSERT_GL_NO_ERROR();
10547 
10548         // try adding a color buffer.
10549         GLTexture colorTex;
10550         glBindTexture(GL_TEXTURE_2D, colorTex);
10551         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
10552         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
10553         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10554         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10555         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10556         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
10557         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
10558         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10559         ASSERT_GL_NO_ERROR();
10560 
10561         glViewport(0, 0, w, h);
10562         // Fill depthTexture with 0.75
10563         glClearDepthf(0.75);
10564         glClear(GL_DEPTH_BUFFER_BIT);
10565 
10566         // Revert to normal framebuffer to test depth shader
10567         glBindFramebuffer(GL_FRAMEBUFFER, 0);
10568         glViewport(0, 0, w, h);
10569         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
10570         glClearDepthf(0.0f);
10571         ASSERT_GL_NO_ERROR();
10572 
10573         glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
10574         ASSERT_GL_NO_ERROR();
10575 
10576         glActiveTexture(GL_TEXTURE0);
10577         glBindTexture(GL_TEXTURE_2D, depthTexture);
10578 
10579         glUseProgram(mProgram);
10580         ASSERT_GL_NO_ERROR();
10581 
10582         glUniform1i(shadowMapLocation, 0);
10583 
10584         const GLfloat gTriangleVertices[] = {-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f};
10585 
10586         glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
10587         ASSERT_GL_NO_ERROR();
10588         glEnableVertexAttribArray(positionLocation);
10589         ASSERT_GL_NO_ERROR();
10590         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10591         ASSERT_GL_NO_ERROR();
10592 
10593         GLuint pixels[1];
10594         glReadPixels(w / 2, h / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
10595         ASSERT_GL_NO_ERROR();
10596 
10597         // The GLES 3.x spec says that the depth texture sample can be found in the RED component.
10598         // However, the OES_depth_texture indicates that the depth value is treated as luminance and
10599         // is in all the color components. Multiple implementations implement a workaround that
10600         // follows the OES_depth_texture behavior if the internalformat given at glTexImage2D was a
10601         // unsized format (e.g. DEPTH_COMPONENT) and the GLES 3.x behavior if it was a sized
10602         // internalformat such as GL_DEPTH_COMPONENT24. The shader will write out a different color
10603         // depending on if it sees the texture sample in only the RED component.
10604         if (useSizedComponent)
10605         {
10606             ASSERT_NE(pixels[0], 0xff0000ff);
10607         }
10608         else
10609         {
10610             ASSERT_EQ(pixels[0], 0xff0000ff);
10611         }
10612 
10613         glBindFramebuffer(GL_FRAMEBUFFER, 0);
10614         glDeleteProgram(mProgram);
10615     }
10616 };
10617 
10618 // Test depth texture compatibility with OES_depth_texture. Uses unsized internal format.
TEST_P(Texture2DDepthTest,DepthTextureES2Compatibility)10619 TEST_P(Texture2DDepthTest, DepthTextureES2Compatibility)
10620 {
10621     ANGLE_SKIP_TEST_IF(IsD3D11());
10622     ANGLE_SKIP_TEST_IF(IsIntel() && IsD3D9());
10623     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_depth_texture") &&
10624                        !IsGLExtensionEnabled("GL_OES_depth_texture"));
10625     // http://anglebug.com/4092
10626     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
10627     ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
10628 
10629     // When the depth texture is specified with unsized internalformat implementations follow
10630     // OES_depth_texture behavior. Otherwise they follow GLES 3.0 behavior.
10631     testBehavior(false);
10632 }
10633 
10634 // Test depth texture compatibility with GLES3 using sized internalformat.
TEST_P(Texture2DDepthTest,DepthTextureES3Compatibility)10635 TEST_P(Texture2DDepthTest, DepthTextureES3Compatibility)
10636 {
10637     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
10638 
10639     // http://anglebug.com/5243
10640     ANGLE_SKIP_TEST_IF(IsMetal() && !IsMetalTextureSwizzleAvailable());
10641 
10642     testBehavior(true);
10643 }
10644 
10645 // Tests unpacking into the unsized GL_ALPHA format.
TEST_P(Texture2DTestES3,UnsizedAlphaUnpackBuffer)10646 TEST_P(Texture2DTestES3, UnsizedAlphaUnpackBuffer)
10647 {
10648     // Initialize the texure.
10649     glBindTexture(GL_TEXTURE_2D, mTexture2D);
10650     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, getWindowWidth(), getWindowHeight(), 0, GL_ALPHA,
10651                  GL_UNSIGNED_BYTE, nullptr);
10652     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10653     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10654 
10655     std::vector<GLubyte> bufferData(getWindowWidth() * getWindowHeight(), 127);
10656 
10657     // Pull in the color data from the unpack buffer.
10658     GLBuffer unpackBuffer;
10659     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10660     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
10661     glBufferData(GL_PIXEL_UNPACK_BUFFER, getWindowWidth() * getWindowHeight(), bufferData.data(),
10662                  GL_STATIC_DRAW);
10663 
10664     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_ALPHA,
10665                     GL_UNSIGNED_BYTE, nullptr);
10666 
10667     // Clear to a weird color to make sure we're drawing something.
10668     glClearColor(0.5f, 0.8f, 1.0f, 0.2f);
10669     glClear(GL_COLOR_BUFFER_BIT);
10670 
10671     // Draw with the alpha texture and verify.
10672     drawQuad(mProgram, "position", 0.5f);
10673 
10674     ASSERT_GL_NO_ERROR();
10675     EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 127, 1);
10676 }
10677 
10678 // Ensure stale unpack data doesn't propagate in D3D11.
TEST_P(Texture2DTestES3,StaleUnpackData)10679 TEST_P(Texture2DTestES3, StaleUnpackData)
10680 {
10681     // Init unpack buffer.
10682     GLsizei pixelCount = getWindowWidth() * getWindowHeight() / 2;
10683     std::vector<GLColor> pixels(pixelCount, GLColor::red);
10684 
10685     GLBuffer unpackBuffer;
10686     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10687     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
10688     GLsizei bufferSize = pixelCount * sizeof(GLColor);
10689     glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize, pixels.data(), GL_STATIC_DRAW);
10690 
10691     // Create from unpack buffer.
10692     glBindTexture(GL_TEXTURE_2D, mTexture2D);
10693     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth() / 2, getWindowHeight() / 2, 0,
10694                  GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10695     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10696     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10697 
10698     drawQuad(mProgram, "position", 0.5f);
10699 
10700     ASSERT_GL_NO_ERROR();
10701     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10702 
10703     // Fill unpack with green, recreating buffer.
10704     pixels.assign(getWindowWidth() * getWindowHeight(), GLColor::green);
10705     GLsizei size2 = getWindowWidth() * getWindowHeight() * sizeof(GLColor);
10706     glBufferData(GL_PIXEL_UNPACK_BUFFER, size2, pixels.data(), GL_STATIC_DRAW);
10707 
10708     // Reinit texture with green.
10709     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
10710                     GL_UNSIGNED_BYTE, nullptr);
10711 
10712     drawQuad(mProgram, "position", 0.5f);
10713 
10714     ASSERT_GL_NO_ERROR();
10715     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10716 }
10717 
10718 // Ensure that texture parameters passed as floats that are converted to ints are rounded before
10719 // validating they are less than 0.
TEST_P(Texture2DTestES3,TextureBaseMaxLevelRoundingValidation)10720 TEST_P(Texture2DTestES3, TextureBaseMaxLevelRoundingValidation)
10721 {
10722     GLTexture texture;
10723     glBindTexture(GL_TEXTURE_2D, texture);
10724 
10725     // Use a negative number that will round to zero when converted to an integer
10726     // According to the spec(2.3.1 Data Conversion For State - Setting Commands):
10727     // "Validation of values performed by state-setting commands is performed after conversion,
10728     // unless specified otherwise for a specific command."
10729     GLfloat param = -7.30157126e-07f;
10730     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, param);
10731     EXPECT_GL_NO_ERROR();
10732 
10733     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, param);
10734     EXPECT_GL_NO_ERROR();
10735 }
10736 
10737 // This test covers a D3D format redefinition bug for 3D textures. The base level format was not
10738 // being properly checked, and the texture storage of the previous texture format was persisting.
10739 // This would result in an ASSERT in debug and incorrect rendering in release.
10740 // See http://anglebug.com/1609 and WebGL 2 test conformance2/misc/views-with-offsets.html.
TEST_P(Texture3DTestES3,FormatRedefinitionBug)10741 TEST_P(Texture3DTestES3, FormatRedefinitionBug)
10742 {
10743     GLTexture tex;
10744     glBindTexture(GL_TEXTURE_3D, tex);
10745     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10746 
10747     GLFramebuffer framebuffer;
10748     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
10749     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
10750 
10751     glCheckFramebufferStatus(GL_FRAMEBUFFER);
10752 
10753     std::vector<uint8_t> pixelData(100, 0);
10754 
10755     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB565, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, nullptr);
10756     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
10757                     pixelData.data());
10758 
10759     ASSERT_GL_NO_ERROR();
10760 }
10761 
10762 // Test glTexSubImage using PBO to 3D texture that expose the regression bug
10763 // https://issuetracker.google.com/170657065
TEST_P(Texture3DTestES3,TexSubImageWithPBO)10764 TEST_P(Texture3DTestES3, TexSubImageWithPBO)
10765 {
10766     GLTexture tex;
10767 
10768     GLuint pbo;
10769     glGenBuffers(1, &pbo);
10770     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
10771     std::vector<uint8_t> pixelData(128 * 128 * 8 * 4, 0x1f);
10772     glBufferData(GL_PIXEL_UNPACK_BUFFER, 128 * 128 * 8 * 4, pixelData.data(), GL_STATIC_DRAW);
10773 
10774     glBindTexture(GL_TEXTURE_3D, tex);
10775     glTexStorage3D(GL_TEXTURE_3D, 8, GL_RGBA8, 128, 128, 8);
10776     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
10777     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10778     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 128, 128, 8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10779     glTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 64, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10780     glTexSubImage3D(GL_TEXTURE_3D, 2, 0, 0, 0, 32, 32, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10781     glTexSubImage3D(GL_TEXTURE_3D, 3, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10782     glTexSubImage3D(GL_TEXTURE_3D, 4, 0, 0, 0, 8, 8, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10783     glTexSubImage3D(GL_TEXTURE_3D, 5, 0, 0, 0, 4, 4, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10784     glTexSubImage3D(GL_TEXTURE_3D, 6, 0, 0, 0, 2, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10785     glTexSubImage3D(GL_TEXTURE_3D, 7, 0, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10786 
10787     drawQuad(mProgram, "position", 0.5f);
10788     ASSERT_GL_NO_ERROR();
10789 
10790     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 128, 128, 8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10791     glTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 64, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10792     glTexSubImage3D(GL_TEXTURE_3D, 2, 0, 0, 0, 32, 32, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10793     ASSERT_GL_NO_ERROR();
10794 
10795     drawQuad(mProgram, "position", 0.5f);
10796     ASSERT_GL_NO_ERROR();
10797 }
10798 
10799 // Test basic pixel unpack buffer OOB checks when uploading to a 2D or 3D texture
TEST_P(Texture3DTestES3,BasicUnpackBufferOOB)10800 TEST_P(Texture3DTestES3, BasicUnpackBufferOOB)
10801 {
10802     // 2D tests
10803     {
10804         GLTexture tex;
10805         glBindTexture(GL_TEXTURE_2D, tex);
10806 
10807         GLBuffer pbo;
10808         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
10809 
10810         // Test OOB
10811         glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 - 1, nullptr, GL_STATIC_DRAW);
10812         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10813         ASSERT_GL_ERROR(GL_INVALID_OPERATION);
10814 
10815         // Test OOB
10816         glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2, nullptr, GL_STATIC_DRAW);
10817         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10818         ASSERT_GL_NO_ERROR();
10819     }
10820 
10821     // 3D tests
10822     {
10823         GLTexture tex;
10824         glBindTexture(GL_TEXTURE_3D, tex);
10825 
10826         GLBuffer pbo;
10827         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
10828 
10829         // Test OOB
10830         glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2 - 1, nullptr,
10831                      GL_STATIC_DRAW);
10832         glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10833         ASSERT_GL_ERROR(GL_INVALID_OPERATION);
10834 
10835         // Test OOB
10836         glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2, nullptr, GL_STATIC_DRAW);
10837         glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10838         ASSERT_GL_NO_ERROR();
10839     }
10840 }
10841 
10842 // Tests behaviour with a single texture and multiple sampler objects.
TEST_P(Texture2DTestES3,SingleTextureMultipleSamplers)10843 TEST_P(Texture2DTestES3, SingleTextureMultipleSamplers)
10844 {
10845     GLint maxTextureUnits = 0;
10846     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
10847     ANGLE_SKIP_TEST_IF(maxTextureUnits < 4);
10848 
10849     constexpr int kSize = 16;
10850 
10851     // Make a single-level texture, fill it with red.
10852     std::vector<GLColor> redColors(kSize * kSize, GLColor::red);
10853     GLTexture tex;
10854     glBindTexture(GL_TEXTURE_2D, tex);
10855     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10856                  redColors.data());
10857     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10858     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10859 
10860     // Simple confidence check.
10861     draw2DTexturedQuad(0.5f, 1.0f, true);
10862     ASSERT_GL_NO_ERROR();
10863     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10864 
10865     // Bind texture to unit 1 with a sampler object making it incomplete.
10866     GLSampler sampler;
10867     glBindSampler(0, sampler);
10868     glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10869     glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10870 
10871     // Make a mipmap texture, fill it with blue.
10872     std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
10873     GLTexture mipmapTex;
10874     glBindTexture(GL_TEXTURE_2D, mipmapTex);
10875     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10876                  blueColors.data());
10877     glGenerateMipmap(GL_TEXTURE_2D);
10878 
10879     // Draw with the sampler, expect blue.
10880     draw2DTexturedQuad(0.5f, 1.0f, true);
10881     ASSERT_GL_NO_ERROR();
10882     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10883 
10884     // Simple multitexturing program.
10885     constexpr char kVS[] =
10886         "#version 300 es\n"
10887         "in vec2 position;\n"
10888         "out vec2 texCoord;\n"
10889         "void main()\n"
10890         "{\n"
10891         "    gl_Position = vec4(position, 0, 1);\n"
10892         "    texCoord = position * 0.5 + vec2(0.5);\n"
10893         "}";
10894 
10895     constexpr char kFS[] =
10896         "#version 300 es\n"
10897         "precision mediump float;\n"
10898         "in vec2 texCoord;\n"
10899         "uniform sampler2D tex1;\n"
10900         "uniform sampler2D tex2;\n"
10901         "uniform sampler2D tex3;\n"
10902         "uniform sampler2D tex4;\n"
10903         "out vec4 color;\n"
10904         "void main()\n"
10905         "{\n"
10906         "    color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
10907         "          +  texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
10908         "}";
10909 
10910     ANGLE_GL_PROGRAM(program, kVS, kFS);
10911 
10912     std::array<GLint, 4> texLocations = {
10913         {glGetUniformLocation(program, "tex1"), glGetUniformLocation(program, "tex2"),
10914          glGetUniformLocation(program, "tex3"), glGetUniformLocation(program, "tex4")}};
10915     for (GLint location : texLocations)
10916     {
10917         ASSERT_NE(-1, location);
10918     }
10919 
10920     // Init the uniform data.
10921     glUseProgram(program);
10922     for (GLint location = 0; location < 4; ++location)
10923     {
10924         glUniform1i(texLocations[location], location);
10925     }
10926 
10927     // Initialize four samplers
10928     GLSampler samplers[4];
10929 
10930     // 0: non-mipped.
10931     glBindSampler(0, samplers[0]);
10932     glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10933     glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10934 
10935     // 1: mipped.
10936     glBindSampler(1, samplers[1]);
10937     glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10938     glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10939 
10940     // 2: non-mipped.
10941     glBindSampler(2, samplers[2]);
10942     glSamplerParameteri(samplers[2], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10943     glSamplerParameteri(samplers[2], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10944 
10945     // 3: mipped.
10946     glBindSampler(3, samplers[3]);
10947     glSamplerParameteri(samplers[3], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10948     glSamplerParameteri(samplers[3], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10949 
10950     // Bind two blue mipped textures and two single layer textures, should all draw.
10951     glActiveTexture(GL_TEXTURE0);
10952     glBindTexture(GL_TEXTURE_2D, tex);
10953 
10954     glActiveTexture(GL_TEXTURE1);
10955     glBindTexture(GL_TEXTURE_2D, mipmapTex);
10956 
10957     glActiveTexture(GL_TEXTURE2);
10958     glBindTexture(GL_TEXTURE_2D, tex);
10959 
10960     glActiveTexture(GL_TEXTURE3);
10961     glBindTexture(GL_TEXTURE_2D, mipmapTex);
10962 
10963     ASSERT_GL_NO_ERROR();
10964 
10965     drawQuad(program, "position", 0.5f);
10966     ASSERT_GL_NO_ERROR();
10967     EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 255, 2);
10968 
10969     // Bind four single layer textures, two should be incomplete.
10970     glActiveTexture(GL_TEXTURE1);
10971     glBindTexture(GL_TEXTURE_2D, tex);
10972 
10973     glActiveTexture(GL_TEXTURE3);
10974     glBindTexture(GL_TEXTURE_2D, tex);
10975 
10976     drawQuad(program, "position", 0.5f);
10977     ASSERT_GL_NO_ERROR();
10978     EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 2);
10979 }
10980 
10981 // The test is added to cover http://anglebug.com/2153. Cubemap completeness checks used to start
10982 // always at level 0 instead of the base level resulting in an incomplete texture if the faces at
10983 // level 0 are not created. The test creates a cubemap texture, specifies the images only for mip
10984 // level 1 filled with white color, updates the base level to be 1 and renders a quad. The program
10985 // samples the cubemap using a direction vector (1,1,1).
TEST_P(TextureCubeTestES3,SpecifyAndSampleFromBaseLevel1)10986 TEST_P(TextureCubeTestES3, SpecifyAndSampleFromBaseLevel1)
10987 {
10988     // Check http://anglebug.com/2155.
10989     ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
10990 
10991     constexpr char kVS[] =
10992         R"(#version 300 es
10993         precision mediump float;
10994         in vec3 pos;
10995         void main() {
10996             gl_Position = vec4(pos, 1.0);
10997         })";
10998 
10999     constexpr char kFS[] =
11000         R"(#version 300 es
11001         precision mediump float;
11002         out vec4 color;
11003         uniform samplerCube uTex;
11004         void main(){
11005             color = texture(uTex, vec3(1.0));
11006         })";
11007 
11008     ANGLE_GL_PROGRAM(program, kVS, kFS);
11009     glUseProgram(program);
11010 
11011     glUniform1i(glGetUniformLocation(program, "uTex"), 0);
11012     glActiveTexture(GL_TEXTURE0);
11013 
11014     GLTexture cubeTex;
11015     glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
11016 
11017     const int kFaceWidth  = 1;
11018     const int kFaceHeight = 1;
11019     std::vector<uint32_t> texData(kFaceWidth * kFaceHeight, 0xFFFFFFFF);
11020     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11021                  GL_UNSIGNED_BYTE, texData.data());
11022     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11023                  GL_UNSIGNED_BYTE, texData.data());
11024     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11025                  GL_UNSIGNED_BYTE, texData.data());
11026     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11027                  GL_UNSIGNED_BYTE, texData.data());
11028     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11029                  GL_UNSIGNED_BYTE, texData.data());
11030     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11031                  GL_UNSIGNED_BYTE, texData.data());
11032     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11033     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11034     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
11035     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
11036     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
11037     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 1);
11038 
11039     drawQuad(program, "pos", 0.5f, 1.0f, true);
11040     ASSERT_GL_NO_ERROR();
11041 
11042     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::white);
11043 }
11044 
11045 // Test GL_PIXEL_UNPACK_BUFFER with GL_TEXTURE_CUBE_MAP.
TEST_P(TextureCubeTestES3,CubeMapPixelUnpackBuffer)11046 TEST_P(TextureCubeTestES3, CubeMapPixelUnpackBuffer)
11047 {
11048     // Check http://anglebug.com/2155.
11049     ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
11050 
11051     constexpr char kVS[] =
11052         R"(#version 300 es
11053         precision mediump float;
11054         in vec3 pos;
11055         void main() {
11056             gl_Position = vec4(pos, 1.0);
11057         })";
11058 
11059     constexpr char kFS[] =
11060         R"(#version 300 es
11061         precision mediump float;
11062         out vec4 color;
11063         uniform samplerCube uTex;
11064         void main(){
11065             color = texture(uTex, vec3(1.0));
11066         })";
11067 
11068     ANGLE_GL_PROGRAM(program, kVS, kFS);
11069     glUseProgram(program);
11070 
11071     glUniform1i(glGetUniformLocation(program, "uTex"), 0);
11072     glActiveTexture(GL_TEXTURE0);
11073 
11074     GLTexture cubeTex;
11075     glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
11076 
11077     const int kFaceWidth  = 4;
11078     const int kFaceHeight = 4;
11079 
11080     uint16_t kHalfFloatOne  = 0x3C00;
11081     uint16_t kHalfFloatZero = 0;
11082 
11083     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA16F, kFaceWidth, kFaceHeight);
11084     struct RGBA16F
11085     {
11086         uint16_t R, G, B, A;
11087     };
11088     RGBA16F redColor = {kHalfFloatOne, kHalfFloatZero, kHalfFloatZero, kHalfFloatOne};
11089 
11090     std::vector<RGBA16F> pixels(kFaceWidth * kFaceHeight, redColor);
11091     GLBuffer buffer;
11092     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
11093     glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(RGBA16F), pixels.data(),
11094                  GL_DYNAMIC_DRAW);
11095     EXPECT_GL_NO_ERROR();
11096     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
11097 
11098     for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
11099     {
11100         glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, 0, 0, 0, kFaceWidth,
11101                         kFaceHeight, GL_RGBA, GL_HALF_FLOAT, 0);
11102         EXPECT_GL_NO_ERROR();
11103     }
11104     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
11105 
11106     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11107     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11108     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
11109     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
11110     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
11111 
11112     drawQuad(program, "pos", 0.5f, 1.0f, true);
11113     ASSERT_GL_NO_ERROR();
11114 
11115     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::red);
11116 }
11117 
11118 // Test creating a mutable cubemap, committing it, and then incomaptibly redefining one layer, while
11119 // compatibly redefining another layer.
TEST_P(TextureCubeTestES3,IncompatibleLayerAThenCompatibleLayerB)11120 TEST_P(TextureCubeTestES3, IncompatibleLayerAThenCompatibleLayerB)
11121 {
11122     GLTexture tex;
11123     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11124 
11125     std::vector<uint32_t> data(32 * 32 * 4, 0xC00FFC00);
11126 
11127     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11128                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11129     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11130                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11131     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11132                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11133     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11134                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11135     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11136                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11137     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11138                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11139     glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11140     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11141                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11142     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11143                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11144     EXPECT_GL_NO_ERROR();
11145 }
11146 
11147 // Test creating a mutable cubemap, committing it, and then comaptibly redefining one layer, while
11148 // incompatibly redefining another layer.
TEST_P(TextureCubeTestES3,CompatibleLayerAThenIncompatibleLayerB)11149 TEST_P(TextureCubeTestES3, CompatibleLayerAThenIncompatibleLayerB)
11150 {
11151     GLTexture tex;
11152     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11153 
11154     std::vector<uint32_t> data(32 * 32 * 4, 0xC00FFC00);
11155 
11156     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11157                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11158     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11159                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11160     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11161                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11162     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11163                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11164     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11165                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11166     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11167                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11168     glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11169     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11170                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11171     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11172                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11173     EXPECT_GL_NO_ERROR();
11174 }
11175 
11176 // Test creating a mutable cubemap, committing it, and then incomaptibly redefining two layers,
11177 // while compatibly redefining another layer.
TEST_P(TextureCubeTestES3,IncompatibleLayerABThenCompatibleLayerC)11178 TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerC)
11179 {
11180     GLTexture tex;
11181     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11182 
11183     std::vector<uint32_t> data(32 * 32 * 4, 0xC00FFC00);
11184 
11185     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11186                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11187     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11188                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11189     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11190                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11191     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11192                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11193     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11194                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11195     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11196                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11197     glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11198     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11199                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11200     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11201                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11202     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11203                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11204     EXPECT_GL_NO_ERROR();
11205 }
11206 
11207 // Test creating a mutable cubemap, committing it, and then incomaptibly redefining two layers and
11208 // compatibly redefining them again.
TEST_P(TextureCubeTestES3,IncompatibleLayerABThenCompatibleLayerAB)11209 TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerAB)
11210 {
11211     GLTexture tex;
11212     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11213 
11214     constexpr uint32_t kSize = 64;
11215 
11216     std::vector<uint32_t> data(kSize * kSize * 4 * 4, 0xC00FFC00);
11217     std::vector<uint32_t> data2(kSize * kSize * 4 * 4, 0xC00003FF);
11218 
11219     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11220                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11221     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11222                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11223     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11224                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11225     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11226                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11227     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11228                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11229     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11230                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11231     glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11232     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11233                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11234     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11235                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11236     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11237                  GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11238     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11239                  GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11240 
11241     glActiveTexture(GL_TEXTURE0);
11242     glBindTexture(GL_TEXTURE_2D, 0);
11243     glActiveTexture(GL_TEXTURE1);
11244     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11245 
11246     glUseProgram(mProgram);
11247     glUniform1i(mTexture2DUniformLocation, 0);
11248     glUniform1i(mTextureCubeUniformLocation, 1);
11249 
11250     const int w = getWindowWidth();
11251     const int h = getWindowHeight();
11252 
11253     for (uint32_t i = 0; i < 6; ++i)
11254     {
11255         glUniform1i(mTextureCubeFaceUniformLocation, i);
11256         glClear(GL_COLOR_BUFFER_BIT);
11257         drawQuad(mProgram, "position", 0.5f);
11258 
11259         const bool expectRed = i == 2 || i == 5;
11260         const GLColor expect = expectRed ? GLColor::red : GLColor::green;
11261         EXPECT_PIXEL_RECT_EQ(2, 2, w - 4, h - 4, expect);
11262         EXPECT_GL_NO_ERROR();
11263     }
11264 }
11265 
11266 // Similar to IncompatibleLayerABThenCompatibleLayerAB, but with a single-level texture
TEST_P(TextureCubeTestES3,IncompatibleLayerABThenCompatibleLayerABSingleLevel)11267 TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerABSingleLevel)
11268 {
11269     GLTexture tex;
11270     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11271 
11272     constexpr uint32_t kSize = 64;
11273 
11274     std::vector<uint32_t> data(kSize * kSize * 4 * 4, 0xC00FFC00);
11275     std::vector<uint32_t> data2(kSize * kSize * 4 * 4, 0xC00003FF);
11276 
11277     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11278                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11279     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11280                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11281     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11282                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11283     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11284                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11285     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11286                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11287     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11288                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11289 
11290     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11291     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11292 
11293     glActiveTexture(GL_TEXTURE0);
11294     glBindTexture(GL_TEXTURE_2D, 0);
11295     glActiveTexture(GL_TEXTURE1);
11296     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11297 
11298     glUseProgram(mProgram);
11299     glUniform1i(mTexture2DUniformLocation, 0);
11300     glUniform1i(mTextureCubeUniformLocation, 1);
11301 
11302     const int w = getWindowWidth();
11303     const int h = getWindowHeight();
11304 
11305     for (uint32_t i = 0; i < 6; ++i)
11306     {
11307         glUniform1i(mTextureCubeFaceUniformLocation, i);
11308         glClear(GL_COLOR_BUFFER_BIT);
11309         drawQuad(mProgram, "position", 0.5f);
11310 
11311         EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
11312         EXPECT_GL_NO_ERROR();
11313     }
11314 
11315     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11316                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11317     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11318                  GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11319     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11320                  GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11321     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11322                  GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11323 
11324     for (uint32_t i = 0; i < 6; ++i)
11325     {
11326         glUniform1i(mTextureCubeFaceUniformLocation, i);
11327         glClear(GL_COLOR_BUFFER_BIT);
11328         drawQuad(mProgram, "position", 0.5f);
11329 
11330         const bool expectRed = i == 2 || i == 5;
11331         const GLColor expect = expectRed ? GLColor::red : GLColor::green;
11332         EXPECT_PIXEL_RECT_EQ(2, 2, w - 4, h - 4, expect);
11333         EXPECT_GL_NO_ERROR();
11334     }
11335 }
11336 
11337 // Verify that using negative texture base level and max level generates GL_INVALID_VALUE.
TEST_P(Texture2DTestES3,NegativeTextureBaseLevelAndMaxLevel)11338 TEST_P(Texture2DTestES3, NegativeTextureBaseLevelAndMaxLevel)
11339 {
11340     GLuint texture = create2DTexture();
11341 
11342     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, -1);
11343     EXPECT_GL_ERROR(GL_INVALID_VALUE);
11344 
11345     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, -1);
11346     EXPECT_GL_ERROR(GL_INVALID_VALUE);
11347 
11348     glDeleteTextures(1, &texture);
11349     EXPECT_GL_NO_ERROR();
11350 }
11351 
11352 // Test setting base level after calling generateMipmap on a LUMA texture.
11353 // Covers http://anglebug.com/2498
TEST_P(Texture2DTestES3,GenerateMipmapAndBaseLevelLUMA)11354 TEST_P(Texture2DTestES3, GenerateMipmapAndBaseLevelLUMA)
11355 {
11356     glActiveTexture(GL_TEXTURE0);
11357     glBindTexture(GL_TEXTURE_2D, mTexture2D);
11358 
11359     constexpr const GLsizei kWidth  = 8;
11360     constexpr const GLsizei kHeight = 8;
11361     std::array<GLubyte, kWidth * kHeight * 2> whiteData;
11362     whiteData.fill(255u);
11363 
11364     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, kWidth, kHeight, 0, GL_LUMINANCE_ALPHA,
11365                  GL_UNSIGNED_BYTE, whiteData.data());
11366     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
11367     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11368     glGenerateMipmap(GL_TEXTURE_2D);
11369     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
11370     EXPECT_GL_NO_ERROR();
11371 
11372     drawQuad(mProgram, "position", 0.5f);
11373     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::white);
11374 }
11375 
11376 // Incompatible levels with non-mipmap filtering should work.
TEST_P(Texture2DTestES3,IncompatibleMipsButNoMipmapFiltering)11377 TEST_P(Texture2DTestES3, IncompatibleMipsButNoMipmapFiltering)
11378 {
11379     // http://anglebug.com/4782
11380     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && (IsAMD() || IsIntel()));
11381 
11382     // http://anglebug.com/4786
11383     ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIAShield());
11384 
11385     glActiveTexture(GL_TEXTURE0);
11386     glBindTexture(GL_TEXTURE_2D, mTexture2D);
11387 
11388     constexpr const GLsizei kSize = 8;
11389     const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
11390     const std::vector<GLColor> kLevel1Data(kSize * kSize, GLColor::red);
11391 
11392     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11393                  kLevel0Data.data());
11394     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11395                  kLevel1Data.data());
11396     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11397     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11398     EXPECT_GL_NO_ERROR();
11399 
11400     // Draw with base level 0.  The GL_LINEAR filtering ensures the texture's image is not created
11401     // with mipmap.
11402     drawQuad(mProgram, "position", 0.5f);
11403     EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
11404 
11405     // Verify draw with level 1.
11406     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
11407     drawQuad(mProgram, "position", 0.5f);
11408     EXPECT_GL_NO_ERROR();
11409     EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel1Data[0]);
11410 
11411     // Verify draw with level 0 again
11412     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
11413     drawQuad(mProgram, "position", 0.5f);
11414     EXPECT_GL_NO_ERROR();
11415     EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
11416 }
11417 
11418 // A collection of negative tests for QCOM foveated rendering extensions
TEST_P(Texture2DTestES3Foveation,NegativeTests)11419 TEST_P(Texture2DTestES3Foveation, NegativeTests)
11420 {
11421     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated") ||
11422                        !IsGLExtensionEnabled("GL_QCOM_texture_foveated"));
11423 
11424     // Switch to foveated framebuffer
11425     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11426 
11427     // QCOM framebuffer foveated tests
11428     GLuint providedFeatures = 0;
11429 
11430     // Test invalid numLayers
11431     glFramebufferFoveationConfigQCOM(mFramebuffer, std::numeric_limits<uint32_t>::max(), 1,
11432                                      GL_FOVEATION_ENABLE_BIT_QCOM, &providedFeatures);
11433     EXPECT_GL_ERROR(GL_INVALID_VALUE);
11434 
11435     // Test invalid focal points
11436     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, std::numeric_limits<uint32_t>::max(),
11437                                      GL_FOVEATION_ENABLE_BIT_QCOM, &providedFeatures);
11438     EXPECT_GL_ERROR(GL_INVALID_VALUE);
11439 
11440     // Test setting foveation parameters on a framebuffer that is not configured
11441     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11442     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11443 
11444     // Configure framebuffer correctly
11445     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11446                                      &providedFeatures);
11447     EXPECT_GL_NO_ERROR();
11448     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11449 
11450     // Try to configure it again
11451     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11452                                      &providedFeatures);
11453     EXPECT_GL_ERROR(GL_INVALID_VALUE);
11454 
11455     // Set foveation parameters
11456     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11457     EXPECT_GL_NO_ERROR();
11458 
11459     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11460 
11461     GLTexture texture;
11462     glActiveTexture(GL_TEXTURE0);
11463     glBindTexture(GL_TEXTURE_2D, texture);
11464     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
11465                  GL_UNSIGNED_BYTE, nullptr);
11466     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11467     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11468     EXPECT_GL_NO_ERROR();
11469 
11470     // Change attachments and try to perform a clear and draw
11471     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
11472     ASSERT_GL_NO_ERROR();
11473 
11474     glUseProgram(mProgram);
11475 
11476     // Clear
11477     glClearColor(0.5f, 0.8f, 1.0f, 0.2f);
11478     glClear(GL_COLOR_BUFFER_BIT);
11479     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11480 
11481     // Draw
11482     drawQuad(mProgram, "position", 0.5f);
11483     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11484 
11485     // QCOM texture foveated tests
11486     glBindTexture(GL_TEXTURE_2D, texture);
11487     // Test invalid feature bit
11488     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
11489                     GL_FOVEATION_SCALED_BIN_METHOD_BIT_QCOM);
11490     EXPECT_GL_ERROR(GL_INVALID_ENUM);
11491 
11492     // Test setting foveation parameters on a framebuffer that is not configured
11493     glTextureFoveationParametersQCOM(texture, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11494     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11495 
11496     // Configure texture
11497     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
11498                     GL_FOVEATION_ENABLE_BIT_QCOM);
11499     EXPECT_GL_NO_ERROR();
11500 
11501     // Test invalid focal points
11502     GLint supportedNumFocalPoints = 0;
11503     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM,
11504                         &supportedNumFocalPoints);
11505     EXPECT_GL_NO_ERROR();
11506 
11507     glTextureFoveationParametersQCOM(texture, 0, supportedNumFocalPoints + 1, 0.0f, 0.0f, 8.0f,
11508                                      8.0f, 0.0f);
11509     EXPECT_GL_ERROR(GL_INVALID_VALUE);
11510 
11511     // Attach foveated texture while framebuffer is also fovated and check framebuffer completeness
11512     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
11513     ASSERT_GL_NO_ERROR();
11514     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM,
11515                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
11516 
11517     // Attach multiple foveated textures to an un-foveated framebuffer and check completeness
11518     GLFramebuffer fbo;
11519     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
11520     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
11521     ASSERT_GL_NO_ERROR();
11522     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11523 
11524     glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
11525     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
11526                  GL_UNSIGNED_BYTE, nullptr);
11527     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11528     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11529     EXPECT_GL_NO_ERROR();
11530     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
11531                     GL_FOVEATION_ENABLE_BIT_QCOM);
11532     EXPECT_GL_NO_ERROR();
11533 
11534     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
11535                            mFramebufferColorTexture, 0);
11536     ASSERT_GL_NO_ERROR();
11537     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM,
11538                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
11539 }
11540 
11541 // QCOM framebuffer foveated rendering + clear
TEST_P(Texture2DTestES3Foveation,Clear)11542 TEST_P(Texture2DTestES3Foveation, Clear)
11543 {
11544     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11545 
11546     // Switch to foveated framebuffer
11547     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11548 
11549     // Just need 1 focal point
11550     GLuint providedFeatures = 0;
11551     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11552                                      &providedFeatures);
11553     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11554     // Set foveation parameters
11555     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11556     EXPECT_GL_NO_ERROR();
11557 
11558     // Clear
11559     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11560     glClear(GL_COLOR_BUFFER_BIT);
11561     EXPECT_GL_NO_ERROR();
11562 
11563     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11564 }
11565 
11566 // QCOM framebuffer foveated rendering + clear then draw
TEST_P(Texture2DTestES3Foveation,ClearThenDraw)11567 TEST_P(Texture2DTestES3Foveation, ClearThenDraw)
11568 {
11569     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11570 
11571     // Switch to foveated framebuffer
11572     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11573 
11574     // Just need 1 focal point
11575     GLuint providedFeatures = 0;
11576     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11577                                      &providedFeatures);
11578     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11579     // Set foveation parameters
11580     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11581     EXPECT_GL_NO_ERROR();
11582 
11583     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11584     glUseProgram(program);
11585 
11586     // Clear
11587     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11588     glClear(GL_COLOR_BUFFER_BIT);
11589     EXPECT_GL_NO_ERROR();
11590 
11591     // Draw
11592     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11593     EXPECT_GL_NO_ERROR();
11594 
11595     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11596 }
11597 
11598 // QCOM framebuffer foveated rendering with rendebuffer attachment + clear then draw
TEST_P(Texture2DTestES3Foveation,RenderbufferAttachmentClearThenDraw)11599 TEST_P(Texture2DTestES3Foveation, RenderbufferAttachmentClearThenDraw)
11600 {
11601     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11602 
11603     // Switch to foveated framebuffer and attach a renderbuffer
11604     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11605     GLRenderbuffer renderbuffer;
11606     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
11607     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight());
11608     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
11609     EXPECT_GL_NO_ERROR();
11610 
11611     // Just need 1 focal point
11612     GLuint providedFeatures = 0;
11613     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11614                                      &providedFeatures);
11615     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11616     // Set foveation parameters
11617     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11618     EXPECT_GL_NO_ERROR();
11619 
11620     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11621     glUseProgram(program);
11622 
11623     // Clear
11624     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11625     glClear(GL_COLOR_BUFFER_BIT);
11626     EXPECT_GL_NO_ERROR();
11627 
11628     // Draw
11629     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11630     EXPECT_GL_NO_ERROR();
11631 
11632     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11633 }
11634 
11635 // QCOM framebuffer foveated rendering + draw, clear then draw
TEST_P(Texture2DTestES3Foveation,DrawClearDraw)11636 TEST_P(Texture2DTestES3Foveation, DrawClearDraw)
11637 {
11638     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11639 
11640     // Switch to foveated framebuffer
11641     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11642 
11643     // Just need 1 focal point
11644     GLuint providedFeatures = 0;
11645     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11646                                      &providedFeatures);
11647     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11648     // Set foveation parameters
11649     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11650     EXPECT_GL_NO_ERROR();
11651 
11652     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11653     glUseProgram(greenProgram);
11654 
11655     // Draw
11656     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11657     EXPECT_GL_NO_ERROR();
11658 
11659     // Clear
11660     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
11661     glClear(GL_COLOR_BUFFER_BIT);
11662     EXPECT_GL_NO_ERROR();
11663 
11664     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
11665     glUseProgram(blueProgram);
11666 
11667     // Draw
11668     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
11669     EXPECT_GL_NO_ERROR();
11670 
11671     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11672 }
11673 
11674 // QCOM framebuffer foveated rendering - draw before and after enabling foveation
TEST_P(Texture2DTestES3Foveation,DrawThenEnableFoveationAndDraw)11675 TEST_P(Texture2DTestES3Foveation, DrawThenEnableFoveationAndDraw)
11676 {
11677     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11678 
11679     // Switch to foveated framebuffer
11680     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11681 
11682     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11683 
11684     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11685     glUseProgram(program);
11686 
11687     // Clear
11688     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11689     glClear(GL_COLOR_BUFFER_BIT);
11690     EXPECT_GL_NO_ERROR();
11691 
11692     // Draw
11693     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11694     EXPECT_GL_NO_ERROR();
11695 
11696     // Configure foveated rendering for framebuffer
11697     // Just need 1 focal point
11698     GLuint providedFeatures = 0;
11699     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11700                                      &providedFeatures);
11701     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11702     // Set foveation parameters
11703     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11704     EXPECT_GL_NO_ERROR();
11705 
11706     // Draw
11707     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11708     EXPECT_GL_NO_ERROR();
11709 
11710     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11711 }
11712 
11713 // QCOM framebuffer foveated rendering + draw, change foveation parameters and then draw
TEST_P(Texture2DTestES3Foveation,DrawChangeFoveationParametersThenDraw)11714 TEST_P(Texture2DTestES3Foveation, DrawChangeFoveationParametersThenDraw)
11715 {
11716     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11717 
11718     // Switch to foveated framebuffer
11719     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11720 
11721     // Just need 1 focal point
11722     GLuint providedFeatures = 0;
11723     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11724                                      &providedFeatures);
11725     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11726     // Set foveation parameters
11727     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11728     EXPECT_GL_NO_ERROR();
11729 
11730     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11731     glUseProgram(greenProgram);
11732 
11733     // Draw
11734     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11735     EXPECT_GL_NO_ERROR();
11736 
11737     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11738 
11739     // Change foveation parameters
11740     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.5f, 0.5f, 3.0f, 3.0f, 3.0f);
11741     EXPECT_GL_NO_ERROR();
11742 
11743     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
11744     glUseProgram(blueProgram);
11745 
11746     // Draw
11747     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
11748     EXPECT_GL_NO_ERROR();
11749 
11750     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11751 }
11752 
11753 // QCOM framebuffer foveated rendering + draw and use as blit source
TEST_P(Texture2DTestES3Foveation,DrawThenUseAsBlitSource)11754 TEST_P(Texture2DTestES3Foveation, DrawThenUseAsBlitSource)
11755 {
11756     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11757 
11758     // Switch to foveated framebuffer
11759     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11760 
11761     glActiveTexture(GL_TEXTURE0);
11762     glBindTexture(GL_TEXTURE_2D, mTexture2D);
11763 
11764     const GLsizei kSizeW = getWindowWidth();
11765     const GLsizei kSizeH = getWindowHeight();
11766     std::vector<GLColor> data(kSizeW * kSizeH, GLColor::blue);
11767     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSizeW, kSizeH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11768                  data.data());
11769     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11770     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11771     EXPECT_GL_NO_ERROR();
11772 
11773     // Just need 1 focal point
11774     GLuint providedFeatures = 0;
11775     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11776                                      &providedFeatures);
11777     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11778     // Set foveation parameters
11779     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11780     EXPECT_GL_NO_ERROR();
11781 
11782     glUseProgram(mProgram);
11783 
11784     // Verify
11785     drawQuad(mProgram, "position", 0.5f);
11786     EXPECT_GL_NO_ERROR();
11787 
11788     // Blit data from foveated framebuffer into default framebuffer
11789     glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
11790     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
11791     glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
11792                       getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
11793 
11794     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11795 }
11796 
11797 // QCOM framebuffer foveated rendering + draw and use as blit target
TEST_P(Texture2DTestES3Foveation,DrawThenUseAsBlitTarget)11798 TEST_P(Texture2DTestES3Foveation, DrawThenUseAsBlitTarget)
11799 {
11800     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11801 
11802     // Switch to foveated framebuffer
11803     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11804 
11805     // Just need 1 focal point
11806     GLuint providedFeatures = 0;
11807     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11808                                      &providedFeatures);
11809     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11810     // Set foveation parameters
11811     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11812     EXPECT_GL_NO_ERROR();
11813 
11814     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11815     glUseProgram(greenProgram);
11816 
11817     // Draw
11818     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11819     EXPECT_GL_NO_ERROR();
11820     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11821 
11822     // Switch to default framebuffer and clear to blue
11823     glBindFramebuffer(GL_FRAMEBUFFER, 0);
11824     EXPECT_GL_NO_ERROR();
11825     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11826     glClear(GL_COLOR_BUFFER_BIT);
11827     EXPECT_GL_NO_ERROR();
11828 
11829     // Blit data from default framebuffer into foveated framebuffer
11830     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
11831     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
11832     glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
11833                       getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
11834 
11835     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11836 }
11837 
11838 // QCOM framebuffer foveated rendering, reuse texture between 2 foveated framebuffers
TEST_P(Texture2DTestES3Foveation,ReuseTextureForFoveatedDraw)11839 TEST_P(Texture2DTestES3Foveation, ReuseTextureForFoveatedDraw)
11840 {
11841     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11842 
11843     // Switch to foveated framebuffer
11844     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11845 
11846     // Just need 1 focal point
11847     GLuint providedFeatures = 0;
11848     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11849                                      &providedFeatures);
11850     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11851     // Set foveation parameters
11852     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11853     EXPECT_GL_NO_ERROR();
11854 
11855     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11856     glUseProgram(greenProgram);
11857 
11858     // Draw
11859     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11860     EXPECT_GL_NO_ERROR();
11861 
11862     // Create another framebuffer
11863     GLFramebuffer framebuffer;
11864     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
11865 
11866     // Resuse texture from mFramebuffer
11867     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
11868                            mFramebufferColorTexture, 0);
11869 
11870     // Configure foveation parameters of the new framebuffer
11871     // Just need 1 focal point
11872     providedFeatures = 0;
11873     glFramebufferFoveationConfigQCOM(framebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11874                                      &providedFeatures);
11875     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11876     // Set foveation parameters
11877     glFramebufferFoveationParametersQCOM(framebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11878     EXPECT_GL_NO_ERROR();
11879 
11880     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
11881     glUseProgram(blueProgram);
11882 
11883     // Draw
11884     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
11885     EXPECT_GL_NO_ERROR();
11886 
11887     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11888 }
11889 
11890 // QCOM framebuffer foveated rendering with MSAA framebuffer
TEST_P(Texture2DTestES3Foveation,DrawWithMsaaFramebuffer)11891 TEST_P(Texture2DTestES3Foveation, DrawWithMsaaFramebuffer)
11892 {
11893     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11894     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
11895 
11896     // Create a new MSAA framebuffer
11897     GLFramebuffer msaaFramebuffer;
11898     glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebuffer);
11899     GLTexture texture;
11900     glActiveTexture(GL_TEXTURE0);
11901     glBindTexture(GL_TEXTURE_2D, texture);
11902     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
11903                  GL_UNSIGNED_BYTE, nullptr);
11904     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11905     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11906     EXPECT_GL_NO_ERROR();
11907 
11908     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
11909                                          texture, 0, 4);
11910     ASSERT_GL_NO_ERROR();
11911     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11912 
11913     // Just need 1 focal point
11914     GLuint providedFeatures = 0;
11915     glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11916                                      &providedFeatures);
11917     ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11918     // Set foveation parameters
11919     glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11920     EXPECT_GL_NO_ERROR();
11921 
11922     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11923     glUseProgram(program);
11924 
11925     // Clear
11926     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11927     glClear(GL_COLOR_BUFFER_BIT);
11928     EXPECT_GL_NO_ERROR();
11929 
11930     // Draw
11931     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11932     EXPECT_GL_NO_ERROR();
11933 
11934     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11935 }
11936 
11937 // QCOM texture foveated rendering, basic draw
TEST_P(Texture2DTestES3Foveation,FoveatedTextureDraw)11938 TEST_P(Texture2DTestES3Foveation, FoveatedTextureDraw)
11939 {
11940     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_texture_foveated"));
11941 
11942     // Create non-foveated framebuffer
11943     GLFramebuffer framebuffer;
11944     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
11945     glActiveTexture(GL_TEXTURE0);
11946     glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
11947     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
11948                            mFramebufferColorTexture, 0);
11949     ASSERT_GL_NO_ERROR();
11950     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11951 
11952     // Render before configuring foveation on the texture
11953     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11954     glUseProgram(greenProgram);
11955 
11956     // Clear
11957     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11958     glClear(GL_COLOR_BUFFER_BIT);
11959     EXPECT_GL_NO_ERROR();
11960 
11961     // Draw
11962     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11963     EXPECT_GL_NO_ERROR();
11964 
11965     // Configure foveation for the texture
11966     GLint supportedFoveationFeatures = 0;
11967     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_QUERY_QCOM,
11968                         &supportedFoveationFeatures);
11969     ASSERT_EQ(supportedFoveationFeatures & GL_FOVEATION_ENABLE_BIT_QCOM,
11970               GL_FOVEATION_ENABLE_BIT_QCOM);
11971     GLint supportedNumFocalPoints = 0;
11972     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM,
11973                         &supportedNumFocalPoints);
11974     ASSERT_GE(supportedNumFocalPoints, 1);
11975     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
11976                     GL_FOVEATION_ENABLE_BIT_QCOM);
11977     EXPECT_GL_NO_ERROR();
11978 
11979     // Set foveation parameters
11980     glTextureFoveationParametersQCOM(mFramebufferColorTexture, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11981     EXPECT_GL_NO_ERROR();
11982 
11983     // Render and verify after configuring foveation on the texture
11984     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
11985     glUseProgram(blueProgram);
11986 
11987     // Clear
11988     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
11989     glClear(GL_COLOR_BUFFER_BIT);
11990     EXPECT_GL_NO_ERROR();
11991 
11992     // Draw
11993     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
11994     EXPECT_GL_NO_ERROR();
11995 
11996     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11997 }
11998 
11999 // QCOM texture foveated rendering to MSAA texture followed by a blit
TEST_P(Texture2DTestES31Foveation,MsaaTextureDrawThenUseAsBlitSource)12000 TEST_P(Texture2DTestES31Foveation, MsaaTextureDrawThenUseAsBlitSource)
12001 {
12002     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_texture_foveated"));
12003 
12004     // Create a non-foveated framebuffer
12005     GLFramebuffer framebuffer;
12006     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
12007 
12008     // Create an msaa texture and bind to framebuffer
12009     GLTexture textureMS;
12010     glActiveTexture(GL_TEXTURE0);
12011     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureMS);
12012     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, getWindowWidth(),
12013                               getWindowHeight(), GL_TRUE);
12014     EXPECT_GL_NO_ERROR();
12015 
12016     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
12017                            textureMS, 0);
12018     ASSERT_GL_NO_ERROR();
12019     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12020 
12021     // Just need 1 focal point
12022     glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
12023                     GL_FOVEATION_ENABLE_BIT_QCOM);
12024     EXPECT_GL_NO_ERROR();
12025 
12026     // Set foveation parameters
12027     glTextureFoveationParametersQCOM(textureMS, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12028     EXPECT_GL_NO_ERROR();
12029 
12030     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12031     glUseProgram(program);
12032 
12033     // Clear
12034     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12035     glClear(GL_COLOR_BUFFER_BIT);
12036     EXPECT_GL_NO_ERROR();
12037 
12038     // Draw
12039     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
12040     EXPECT_GL_NO_ERROR();
12041 
12042     // Blit data from framebuffer with foveated texture into default framebuffer
12043     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
12044     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
12045     glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
12046                       getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
12047 
12048     glBindFramebuffer(GL_FRAMEBUFFER, 0);
12049     EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
12050 }
12051 
12052 // Enabling mipmap filtering after previously having used the texture without it should work.
TEST_P(Texture2DTestES3,NoMipmapDrawThenMipmapDraw)12053 TEST_P(Texture2DTestES3, NoMipmapDrawThenMipmapDraw)
12054 {
12055     glActiveTexture(GL_TEXTURE0);
12056     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12057 
12058     constexpr const GLsizei kSize = 8;
12059     const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
12060     const std::vector<GLColor> kLevelOtherData(kSize * kSize, GLColor::red);
12061 
12062     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12063                  kLevel0Data.data());
12064     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12065     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12066     EXPECT_GL_NO_ERROR();
12067 
12068     // Draw so the texture's image is allocated.
12069     drawQuad(mProgram, "position", 0.5f);
12070     EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
12071 
12072     // Specify the rest of the image
12073     for (GLint mip = 1; (kSize >> mip) >= 1; ++mip)
12074     {
12075         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12076                      GL_UNSIGNED_BYTE, kLevelOtherData.data());
12077     }
12078     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12079 
12080     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
12081     glUseProgram(program);
12082     GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
12083     GLint lodLoc     = glGetUniformLocation(program, essl3_shaders::LodUniform());
12084     ASSERT_NE(-1, textureLoc);
12085     ASSERT_NE(-1, lodLoc);
12086     glUniform1i(textureLoc, 0);
12087 
12088     // Verify the mips
12089     for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12090     {
12091         glUniform1f(lodLoc, mip);
12092         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12093         EXPECT_GL_NO_ERROR();
12094         EXPECT_PIXEL_COLOR_EQ(0, 0, (mip == 0 ? kLevel0Data[0] : kLevelOtherData[0]));
12095     }
12096 }
12097 
12098 // Disabling mipmap filtering after previously having used the texture with it should work.
TEST_P(Texture2DTestES3,MipmapDrawThenNoMipmapDraw)12099 TEST_P(Texture2DTestES3, MipmapDrawThenNoMipmapDraw)
12100 {
12101     glActiveTexture(GL_TEXTURE0);
12102     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12103 
12104     constexpr const GLsizei kSize = 8;
12105     const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
12106     const std::vector<GLColor> kLevelOtherData(kSize * kSize, GLColor::red);
12107 
12108     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12109                  kLevel0Data.data());
12110     for (GLint mip = 1; (kSize >> mip) >= 1; ++mip)
12111     {
12112         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12113                      GL_UNSIGNED_BYTE, kLevelOtherData.data());
12114     }
12115     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12116     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12117     EXPECT_GL_NO_ERROR();
12118 
12119     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
12120     glUseProgram(program);
12121     GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
12122     GLint lodLoc     = glGetUniformLocation(program, essl3_shaders::LodUniform());
12123     ASSERT_NE(-1, textureLoc);
12124     ASSERT_NE(-1, lodLoc);
12125     glUniform1i(textureLoc, 0);
12126 
12127     // Verify the mips.
12128     for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12129     {
12130         glUniform1f(lodLoc, mip);
12131         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12132         EXPECT_GL_NO_ERROR();
12133         EXPECT_PIXEL_COLOR_EQ(0, 0, (mip == 0 ? kLevel0Data[0] : kLevelOtherData[0]));
12134     }
12135 
12136     // Disable mipmapping and verify mips again.
12137     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12138 
12139     for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12140     {
12141         glUniform1f(lodLoc, mip);
12142         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12143         EXPECT_GL_NO_ERROR();
12144         EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
12145     }
12146 }
12147 
12148 // Respecify texture with more mips.
TEST_P(Texture2DTestES3,RespecifyWithMoreMips)12149 TEST_P(Texture2DTestES3, RespecifyWithMoreMips)
12150 {
12151     glActiveTexture(GL_TEXTURE0);
12152     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12153 
12154     constexpr const GLsizei kSize = 8;
12155     const std::vector<GLColor> kLevelEvenData(kSize * kSize, GLColor::blue);
12156     const std::vector<GLColor> kLevelOddData(kSize * kSize * 4, GLColor::red);
12157 
12158     auto getLevelData = [&](GLint mip) {
12159         return mip % 2 == 0 ? kLevelEvenData.data() : kLevelOddData.data();
12160     };
12161 
12162     for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12163     {
12164         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12165                      GL_UNSIGNED_BYTE, getLevelData(mip));
12166     }
12167     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12168     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12169     EXPECT_GL_NO_ERROR();
12170 
12171     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
12172     glUseProgram(program);
12173     GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
12174     GLint lodLoc     = glGetUniformLocation(program, essl3_shaders::LodUniform());
12175     ASSERT_NE(-1, textureLoc);
12176     ASSERT_NE(-1, lodLoc);
12177     glUniform1i(textureLoc, 0);
12178 
12179     // Verify the mips.
12180     for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12181     {
12182         glUniform1f(lodLoc, mip);
12183         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12184         EXPECT_GL_NO_ERROR();
12185         EXPECT_PIXEL_COLOR_EQ(0, 0, getLevelData(mip)[0]);
12186     }
12187 
12188     // Respecify the texture with more mips, without changing any parameters.
12189     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize * 2, kSize * 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12190                  kLevelOddData.data());
12191     for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12192     {
12193         glTexImage2D(GL_TEXTURE_2D, mip + 1, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12194                      GL_UNSIGNED_BYTE, getLevelData(mip));
12195     }
12196 
12197     // Verify the mips.
12198     for (GLint mip = 0; ((kSize * 2) >> mip) >= 1; ++mip)
12199     {
12200         glUniform1f(lodLoc, mip);
12201         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12202         EXPECT_GL_NO_ERROR();
12203         EXPECT_PIXEL_COLOR_EQ(0, 0, getLevelData(mip - 1)[0]);
12204     }
12205 }
12206 
12207 // Covers a bug in the D3D11 backend: http://anglebug.com/2772
12208 // When using a sampler the texture was created as if it has mipmaps,
12209 // regardless what you specified in GL_TEXTURE_MIN_FILTER via
12210 // glSamplerParameteri() -- mistakenly the default value
12211 // GL_NEAREST_MIPMAP_LINEAR or the value set via glTexParameteri() was
12212 // evaluated.
12213 // If you didn't provide mipmaps and didn't let the driver generate them
12214 // this led to not sampling your texture data when minification occurred.
TEST_P(Texture2DTestES3,MinificationWithSamplerNoMipmapping)12215 TEST_P(Texture2DTestES3, MinificationWithSamplerNoMipmapping)
12216 {
12217     constexpr char kVS[] =
12218         "#version 300 es\n"
12219         "out vec2 texcoord;\n"
12220         "in vec4 position;\n"
12221         "void main()\n"
12222         "{\n"
12223         "    gl_Position = vec4(position.xy * 0.1, 0.0, 1.0);\n"
12224         "    texcoord = (position.xy * 0.5) + 0.5;\n"
12225         "}\n";
12226 
12227     constexpr char kFS[] =
12228         "#version 300 es\n"
12229         "precision highp float;\n"
12230         "uniform highp sampler2D tex;\n"
12231         "in vec2 texcoord;\n"
12232         "out vec4 fragColor;\n"
12233         "void main()\n"
12234         "{\n"
12235         "    fragColor = texture(tex, texcoord);\n"
12236         "}\n";
12237 
12238     ANGLE_GL_PROGRAM(program, kVS, kFS);
12239 
12240     GLSampler sampler;
12241     glBindSampler(0, sampler);
12242     glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
12243     glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
12244 
12245     glActiveTexture(GL_TEXTURE0);
12246     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12247 
12248     const GLsizei texWidth  = getWindowWidth();
12249     const GLsizei texHeight = getWindowHeight();
12250     const std::vector<GLColor> whiteData(texWidth * texHeight, GLColor::white);
12251 
12252     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12253                  whiteData.data());
12254     EXPECT_GL_NO_ERROR();
12255 
12256     drawQuad(program, "position", 0.5f);
12257     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, angle::GLColor::white);
12258 }
12259 
testUploadThenUseInDifferentStages(const std::vector<UploadThenUseStageParam> & uses)12260 void Texture2DTest::testUploadThenUseInDifferentStages(
12261     const std::vector<UploadThenUseStageParam> &uses)
12262 {
12263     constexpr char kVSSampleVS[] = R"(attribute vec4 a_position;
12264 uniform sampler2D u_tex2D;
12265 varying vec4 v_color;
12266 
12267 void main()
12268 {
12269     gl_Position = vec4(a_position.xy, 0.0, 1.0);
12270     v_color = texture2D(u_tex2D, a_position.xy * 0.5 + vec2(0.5));
12271 })";
12272 
12273     constexpr char kVSSampleFS[] = R"(precision mediump float;
12274 varying vec4 v_color;
12275 
12276 void main()
12277 {
12278     gl_FragColor = v_color;
12279 })";
12280 
12281     ANGLE_GL_PROGRAM(sampleInVS, kVSSampleVS, kVSSampleFS);
12282     ANGLE_GL_PROGRAM(sampleInFS, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
12283 
12284     GLFramebuffer fbo[2];
12285     GLTexture color[2];
12286     for (uint32_t i = 0; i < 2; ++i)
12287     {
12288         glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
12289         glBindTexture(GL_TEXTURE_2D, color[i]);
12290         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
12291         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color[i], 0);
12292     }
12293 
12294     const GLColor kImageColor(63, 31, 0, 255);
12295 
12296     GLTexture tex;
12297     glBindTexture(GL_TEXTURE_2D, tex);
12298     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kImageColor);
12299     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12300     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12301     glActiveTexture(GL_TEXTURE0);
12302     ASSERT_GL_NO_ERROR();
12303 
12304     glEnable(GL_BLEND);
12305     glBlendFunc(GL_ONE, GL_ONE);
12306 
12307     glClearColor(0, 0, 0, 1);
12308 
12309     glBindFramebuffer(GL_FRAMEBUFFER, fbo[1]);
12310     glClear(GL_COLOR_BUFFER_BIT);
12311     glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
12312     glClear(GL_COLOR_BUFFER_BIT);
12313 
12314     uint32_t curFboIndex     = 0;
12315     uint32_t fboDrawCount[2] = {};
12316 
12317     for (const UploadThenUseStageParam &use : uses)
12318     {
12319         const GLProgram &program = use.useStage == GL_VERTEX_SHADER ? sampleInVS : sampleInFS;
12320         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
12321         ASSERT_GL_NO_ERROR();
12322 
12323         ++fboDrawCount[curFboIndex];
12324 
12325         if (use.closeRenderPassAfterUse)
12326         {
12327             // Close the render pass without accidentally incurring additional barriers.
12328             curFboIndex = 1 - curFboIndex;
12329             glBindFramebuffer(GL_FRAMEBUFFER, fbo[curFboIndex]);
12330         }
12331     }
12332 
12333     // Make sure the transfer operations below aren't reordered with the rendering above and thus
12334     // introduce additional synchronization.
12335     glFinish();
12336 
12337     for (uint32_t i = 0; i < 2; ++i)
12338     {
12339         const GLColor kExpectedColor(63 * std::min(4u, fboDrawCount[i]),
12340                                      31 * std::min(8u, fboDrawCount[i]), 0, 255);
12341 
12342         glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
12343         EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor);
12344     }
12345 }
12346 
12347 // Test synchronization when a texture is used in different shader stages after data upload.
12348 //
12349 // - Use in VS
12350 // - Use in FS
TEST_P(Texture2DTest,UploadThenVSThenFS)12351 TEST_P(Texture2DTest, UploadThenVSThenFS)
12352 {
12353     testUploadThenUseInDifferentStages({
12354         {GL_VERTEX_SHADER, false},
12355         {GL_FRAGMENT_SHADER, false},
12356     });
12357 }
12358 
12359 // Test synchronization when a texture is used in different shader stages after data upload.
12360 //
12361 // - Use in VS
12362 // - Break render pass
12363 // - Use in FS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFS)12364 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFS)
12365 {
12366     testUploadThenUseInDifferentStages({
12367         {GL_VERTEX_SHADER, true},
12368         {GL_FRAGMENT_SHADER, false},
12369     });
12370 }
12371 
12372 // Test synchronization when a texture is used in different shader stages after data upload.
12373 //
12374 // - Use in FS
12375 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenVS)12376 TEST_P(Texture2DTest, UploadThenFSThenVS)
12377 {
12378     testUploadThenUseInDifferentStages({
12379         {GL_FRAGMENT_SHADER, false},
12380         {GL_VERTEX_SHADER, false},
12381     });
12382 }
12383 
12384 // Test synchronization when a texture is used in different shader stages after data upload.
12385 //
12386 // - Use in FS
12387 // - Break render pass
12388 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenVS)12389 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenVS)
12390 {
12391     testUploadThenUseInDifferentStages({
12392         {GL_FRAGMENT_SHADER, true},
12393         {GL_VERTEX_SHADER, false},
12394     });
12395 }
12396 
12397 // Test synchronization when a texture is used in different shader stages after data upload.
12398 //
12399 // - Use in VS
12400 // - Use in FS
12401 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenFSThenVS)12402 TEST_P(Texture2DTest, UploadThenVSThenFSThenVS)
12403 {
12404     testUploadThenUseInDifferentStages({
12405         {GL_VERTEX_SHADER, false},
12406         {GL_FRAGMENT_SHADER, false},
12407         {GL_VERTEX_SHADER, false},
12408     });
12409 }
12410 
12411 // Test synchronization when a texture is used in different shader stages after data upload.
12412 //
12413 // - Use in VS
12414 // - Break render pass
12415 // - Use in FS
12416 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFSThenVS)12417 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFSThenVS)
12418 {
12419     testUploadThenUseInDifferentStages({
12420         {GL_VERTEX_SHADER, true},
12421         {GL_FRAGMENT_SHADER, false},
12422         {GL_VERTEX_SHADER, false},
12423     });
12424 }
12425 
12426 // Test synchronization when a texture is used in different shader stages after data upload.
12427 //
12428 // - Use in VS
12429 // - Break render pass
12430 // - Use in FS
12431 // - Break render pass
12432 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFSThenNewRPThenVS)12433 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFSThenNewRPThenVS)
12434 {
12435     testUploadThenUseInDifferentStages({
12436         {GL_VERTEX_SHADER, true},
12437         {GL_FRAGMENT_SHADER, true},
12438         {GL_VERTEX_SHADER, false},
12439     });
12440 }
12441 
12442 // Test synchronization when a texture is used in different shader stages after data upload.
12443 //
12444 // - Use in FS
12445 // - Use in VS
12446 // - Break render pass
12447 // - Use in FS
TEST_P(Texture2DTest,UploadThenFSThenVSThenNewRPThenFS)12448 TEST_P(Texture2DTest, UploadThenFSThenVSThenNewRPThenFS)
12449 {
12450     testUploadThenUseInDifferentStages({
12451         {GL_FRAGMENT_SHADER, false},
12452         {GL_VERTEX_SHADER, true},
12453         {GL_FRAGMENT_SHADER, false},
12454     });
12455 }
12456 
12457 // Test synchronization when a texture is used in different shader stages after data upload.
12458 //
12459 // - Use in FS
12460 // - Break render pass
12461 // - Use in VS
12462 // - Use in FS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenVSThenFS)12463 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenVSThenFS)
12464 {
12465     testUploadThenUseInDifferentStages({
12466         {GL_FRAGMENT_SHADER, true},
12467         {GL_VERTEX_SHADER, false},
12468         {GL_FRAGMENT_SHADER, false},
12469     });
12470 }
12471 
12472 // Test synchronization when a texture is used in different shader stages after data upload.
12473 //
12474 // - Use in FS
12475 // - Break render pass
12476 // - Use in FS
12477 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenFSThenVS)12478 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenFSThenVS)
12479 {
12480     testUploadThenUseInDifferentStages({
12481         {GL_FRAGMENT_SHADER, true},
12482         {GL_FRAGMENT_SHADER, false},
12483         {GL_VERTEX_SHADER, false},
12484     });
12485 }
12486 
12487 // Test that interleaved updates and draw calls many times work
TEST_P(Texture2DTest,DrawThenUpdateMultipleTimes)12488 TEST_P(Texture2DTest, DrawThenUpdateMultipleTimes)
12489 {
12490     constexpr uint32_t kTexWidth  = 16;
12491     constexpr uint32_t kTexHeight = 16;
12492     constexpr uint32_t kBpp       = 4;
12493 
12494     // Create the texture
12495     glActiveTexture(GL_TEXTURE0);
12496     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12497     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12498     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12499     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12500                  nullptr);
12501     EXPECT_GL_ERROR(GL_NO_ERROR);
12502 
12503     constexpr GLubyte kInitialColor = 16;
12504     GLubyte expectedFinalColorValue = kInitialColor;
12505     glEnable(GL_BLEND);
12506     glBlendFunc(GL_ONE, GL_ONE);
12507     glClearColor(0, 0, 0, 0);
12508     glClear(GL_COLOR_BUFFER_BIT);
12509 
12510     // First draw the screen with initial color
12511     {
12512         ANGLE_GL_PROGRAM(colorProgram, angle::essl1_shaders::vs::Simple(),
12513                          angle::essl1_shaders::fs::UniformColor());
12514         glUseProgram(colorProgram);
12515         GLint colorUniformLocation =
12516             glGetUniformLocation(colorProgram, angle::essl1_shaders::ColorUniform());
12517         ASSERT_NE(colorUniformLocation, -1);
12518         glUniform4f(colorUniformLocation, kInitialColor / 256.f, kInitialColor / 256.f,
12519                     kInitialColor / 256.f, kInitialColor / 256.f);
12520         drawQuad(colorProgram, angle::essl1_shaders::PositionAttrib(), 0.5f);
12521     }
12522 
12523     // Then update the texture then draw it multiple times
12524     constexpr GLubyte kColorsToUpdate[] = {16, 64, 64};
12525     setUpProgram();
12526     glUseProgram(mProgram);
12527     glUniform1i(mTexture2DUniformLocation, 0);
12528 
12529     for (auto color : kColorsToUpdate)
12530     {
12531         expectedFinalColorValue += color;
12532         std::vector<GLubyte> fullTextureData(kTexWidth * kTexHeight * kBpp, color);
12533         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
12534                         fullTextureData.data());
12535 
12536         drawQuad(mProgram, "position", 0.5f);
12537     }
12538 
12539     // The final color should be sum of all updated colors.
12540     const GLColor expectedFinalColor(expectedFinalColorValue, expectedFinalColorValue,
12541                                      expectedFinalColorValue, expectedFinalColorValue);
12542     EXPECT_GL_NO_ERROR();
12543     EXPECT_PIXEL_COLOR_EQ(1 * getWindowWidth() / 4, getWindowHeight() / 2, expectedFinalColor);
12544 }
12545 
12546 // Test that clears due to emulated formats are to the correct level given non-zero base level.
TEST_P(Texture2DTestES3,NonZeroBaseEmulatedClear)12547 TEST_P(Texture2DTestES3, NonZeroBaseEmulatedClear)
12548 {
12549     // Tests behavior of the Vulkan backend with emulated formats.
12550     ANGLE_SKIP_TEST_IF(!IsVulkan());
12551 
12552     // TODO(http://anglebug.com/8036): Skip when using VMA image suballocation on Linux/Intel.
12553     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() &&
12554                        getEGLWindow()->isFeatureEnabled(Feature::UseVmaForImageSuballocation));
12555 
12556     // This test assumes GL_RGB is always emulated, which overrides the
12557     // Feature::AllocateNonZeroMemory memory feature, clearing the memory to zero. However, if the
12558     // format is *not* emulated and the feature Feature::AllocateNonZeroMemory is enabled, the
12559     // texture memory will contain non-zero memory, which means the color is not black (causing the
12560     // test to fail).
12561     ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
12562 
12563     setUpProgram();
12564 
12565     glActiveTexture(GL_TEXTURE0);
12566     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12567     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12568     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12569     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 4, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12570     glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12571     glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12572     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
12573     EXPECT_GL_NO_ERROR();
12574 
12575     drawQuad(mProgram, "position", 0.5f);
12576 
12577     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
12578 }
12579 
12580 // Test that uploading data to buffer that's in use then using it as PBO to update a texture works.
TEST_P(Texture2DTestES3,UseAsUBOThenUpdateThenAsPBO)12581 TEST_P(Texture2DTestES3, UseAsUBOThenUpdateThenAsPBO)
12582 {
12583     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
12584                                                  GLColor::red};
12585     const std::array<GLColor, 4> kUpdateData  = {GLColor::blue, GLColor::blue, GLColor::blue,
12586                                                  GLColor::blue};
12587 
12588     GLBuffer buffer;
12589     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
12590     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_COPY);
12591     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
12592     EXPECT_GL_NO_ERROR();
12593 
12594     constexpr char kVerifyUBO[] = R"(#version 300 es
12595 precision mediump float;
12596 uniform block {
12597     uvec4 data;
12598 } ubo;
12599 out vec4 colorOut;
12600 void main()
12601 {
12602     if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
12603         colorOut = vec4(0, 1.0, 0, 1.0);
12604     else
12605         colorOut = vec4(1.0, 0, 0, 1.0);
12606 })";
12607 
12608     ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
12609     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
12610     EXPECT_GL_NO_ERROR();
12611 
12612     // Update buffer data
12613     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
12614     EXPECT_GL_NO_ERROR();
12615 
12616     // Bind as PBO
12617     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
12618     EXPECT_GL_NO_ERROR();
12619 
12620     // Upload from PBO to texture
12621     GLTexture tex;
12622     glBindTexture(GL_TEXTURE_2D, tex);
12623     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
12624     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
12625     EXPECT_GL_NO_ERROR();
12626 
12627     // Make sure uniform data is correct.
12628     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12629 
12630     // Make sure the texture data is correct.
12631     GLFramebuffer fbo;
12632     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12633     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
12634     EXPECT_GL_NO_ERROR();
12635     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12636 
12637     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
12638 }
12639 
12640 // Test if the RenderTargetCache is updated when the TextureStorage object is freed
TEST_P(Texture2DTestES3,UpdateRenderTargetCacheOnDestroyTexStorage)12641 TEST_P(Texture2DTestES3, UpdateRenderTargetCacheOnDestroyTexStorage)
12642 {
12643     ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
12644     const GLenum attachments[] = {GL_COLOR_ATTACHMENT0};
12645 
12646     GLTexture tex;
12647     GLFramebuffer fb;
12648     glBindTexture(GL_TEXTURE_2D, tex);
12649     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 100, 1);
12650     glBindFramebuffer(GL_FRAMEBUFFER, fb);
12651     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
12652     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments);
12653     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
12654     drawQuad(drawRed, essl3_shaders::PositionAttrib(), 1.0f);
12655     EXPECT_GL_NO_ERROR();
12656 
12657     EXPECT_PIXEL_RECT_EQ(0, 0, 100, 1, GLColor::red);
12658 }
12659 
12660 // Test that we can allocate at least 4096 images, which is the maximum allocation count on some
12661 // platforms. Image suballocation should enable us to allocate more than this limit.
TEST_P(Texture2DTestES3,AllocateMoreThan4096Textures)12662 TEST_P(Texture2DTestES3, AllocateMoreThan4096Textures)
12663 {
12664     ANGLE_SKIP_TEST_IF(!getEGLWindow()->isFeatureEnabled(Feature::UseVmaForImageSuballocation));
12665 
12666     // The test is skipped when AllocateNonZeroMemory is enabled due to risk of timeout.
12667     ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
12668 
12669     constexpr size_t kTextureCount = 8000;
12670     std::vector<GLTexture> textures(kTextureCount);
12671     for (auto &texture : textures)
12672     {
12673         glBindTexture(GL_TEXTURE_2D, texture);
12674         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
12675     }
12676     EXPECT_GL_NO_ERROR();
12677 }
12678 
12679 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
12680 // texture is output.
TEST_P(Texture2DIntegerTestES3,IntegerTextureNonZeroBaseLevel)12681 TEST_P(Texture2DIntegerTestES3, IntegerTextureNonZeroBaseLevel)
12682 {
12683     // http://anglebug.com/3478
12684     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
12685 
12686     glActiveTexture(GL_TEXTURE0);
12687     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12688     int width     = getWindowWidth();
12689     int height    = getWindowHeight();
12690     GLColor color = GLColor::green;
12691     std::vector<GLColor> pixels(width * height, color);
12692     GLint baseLevel = 1;
12693     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel);
12694     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12695     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12696     glTexImage2D(GL_TEXTURE_2D, baseLevel, GL_RGBA8UI, width, height, 0, GL_RGBA_INTEGER,
12697                  GL_UNSIGNED_BYTE, pixels.data());
12698 
12699     setUpProgram();
12700     glUseProgram(mProgram);
12701     glUniform1i(mTexture2DUniformLocation, 0);
12702     drawQuad(mProgram, "position", 0.5f);
12703 
12704     EXPECT_GL_NO_ERROR();
12705     EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12706     EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12707 }
12708 
12709 // Draw a quad with an integer cube texture with a non-zero base level, and test that the color of
12710 // the texture is output.
TEST_P(TextureCubeIntegerTestES3,IntegerCubeTextureNonZeroBaseLevel)12711 TEST_P(TextureCubeIntegerTestES3, IntegerCubeTextureNonZeroBaseLevel)
12712 {
12713     // All output checks returned black, rather than the texture color.
12714     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12715 
12716     glActiveTexture(GL_TEXTURE0);
12717 
12718     glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
12719     GLint baseLevel = 1;
12720     int width       = getWindowWidth();
12721     int height      = getWindowHeight();
12722     GLColor color   = GLColor::green;
12723     std::vector<GLColor> pixels(width * height, color);
12724     for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
12725     {
12726         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, baseLevel, GL_RGBA8UI, width,
12727                      height, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
12728         EXPECT_GL_NO_ERROR();
12729     }
12730     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, baseLevel);
12731     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12732     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12733 
12734     glUseProgram(mProgram);
12735     glUniform1i(mTextureCubeUniformLocation, 0);
12736     drawQuad(mProgram, "position", 0.5f);
12737 
12738     EXPECT_GL_NO_ERROR();
12739     EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12740     EXPECT_PIXEL_COLOR_EQ(width - 1, 0, color);
12741     EXPECT_PIXEL_COLOR_EQ(0, height - 1, color);
12742     EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12743 }
12744 
12745 // This test sets up a cube map with four distincly colored MIP levels.
12746 // The size of the texture and the geometry is chosen such that levels 1 or 2 should be chosen at
12747 // the corners of the screen.
TEST_P(TextureCubeIntegerEdgeTestES3,IntegerCubeTextureCorner)12748 TEST_P(TextureCubeIntegerEdgeTestES3, IntegerCubeTextureCorner)
12749 {
12750     glActiveTexture(GL_TEXTURE0);
12751 
12752     glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
12753     int width  = getWindowWidth();
12754     int height = getWindowHeight();
12755     ASSERT_EQ(width, height);
12756     GLColor color[4] = {GLColor::white, GLColor::green, GLColor::blue, GLColor::red};
12757     for (GLint level = 0; level < 4; level++)
12758     {
12759         for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
12760         {
12761             int levelWidth  = (2 * width) >> level;
12762             int levelHeight = (2 * height) >> level;
12763             std::vector<GLColor> pixels(levelWidth * levelHeight, color[level]);
12764             glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, GL_RGBA8UI, levelWidth,
12765                          levelHeight, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
12766             EXPECT_GL_NO_ERROR();
12767         }
12768     }
12769     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12770     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12771     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 3);
12772 
12773     glUseProgram(mProgram);
12774     glUniform1i(mTextureCubeUniformLocation, 0);
12775     drawQuad(mProgram, "position", 0.5f);
12776 
12777     ASSERT_GL_NO_ERROR();
12778     // Check that we do not read from levels 0 or 3. Levels 1 and 2 are both acceptable.
12779     EXPECT_EQ(ReadColor(0, 0).R, 0);
12780     EXPECT_EQ(ReadColor(width - 1, 0).R, 0);
12781     EXPECT_EQ(ReadColor(0, height - 1).R, 0);
12782     EXPECT_EQ(ReadColor(width - 1, height - 1).R, 0);
12783 }
12784 
12785 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
12786 // texture is output.
TEST_P(Texture2DIntegerProjectiveOffsetTestES3,NonZeroBaseLevel)12787 TEST_P(Texture2DIntegerProjectiveOffsetTestES3, NonZeroBaseLevel)
12788 {
12789     // Fails on AMD: http://crbug.com/967796
12790     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
12791 
12792     glActiveTexture(GL_TEXTURE0);
12793     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12794     int width     = getWindowWidth();
12795     int height    = getWindowHeight();
12796     GLColor color = GLColor::green;
12797     std::vector<GLColor> pixels(width * height, color);
12798     GLint baseLevel = 1;
12799     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel);
12800     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12801     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12802     glTexImage2D(GL_TEXTURE_2D, baseLevel, GL_RGBA8UI, width, height, 0, GL_RGBA_INTEGER,
12803                  GL_UNSIGNED_BYTE, pixels.data());
12804 
12805     setUpProgram();
12806     glUseProgram(mProgram);
12807     glUniform1i(mTexture2DUniformLocation, 0);
12808     drawQuad(mProgram, "position", 0.5f);
12809 
12810     EXPECT_GL_NO_ERROR();
12811     EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12812     EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12813 }
12814 
12815 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
12816 // texture is output.
TEST_P(Texture2DArrayIntegerTestES3,NonZeroBaseLevel)12817 TEST_P(Texture2DArrayIntegerTestES3, NonZeroBaseLevel)
12818 {
12819     // Test fail: http://anglebug.com/5959
12820     ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
12821 
12822     glActiveTexture(GL_TEXTURE0);
12823     glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
12824     int width     = getWindowWidth();
12825     int height    = getWindowHeight();
12826     int depth     = 2;
12827     GLColor color = GLColor::green;
12828     std::vector<GLColor> pixels(width * height * depth, color);
12829     GLint baseLevel = 1;
12830     glTexImage3D(GL_TEXTURE_2D_ARRAY, baseLevel, GL_RGBA8UI, width, height, depth, 0,
12831                  GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
12832     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, baseLevel);
12833     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12834     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12835 
12836     drawQuad(mProgram, "position", 0.5f);
12837 
12838     EXPECT_GL_NO_ERROR();
12839     EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12840     EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12841 }
12842 
12843 // Draw a quad with an integer 3D texture with a non-zero base level, and test that the color of the
12844 // texture is output.
TEST_P(Texture3DIntegerTestES3,NonZeroBaseLevel)12845 TEST_P(Texture3DIntegerTestES3, NonZeroBaseLevel)
12846 {
12847     glActiveTexture(GL_TEXTURE0);
12848     glBindTexture(GL_TEXTURE_3D, mTexture3D);
12849     int width     = getWindowWidth();
12850     int height    = getWindowHeight();
12851     int depth     = 2;
12852     GLColor color = GLColor::green;
12853     std::vector<GLColor> pixels(width * height * depth, color);
12854     GLint baseLevel = 1;
12855     glTexImage3D(GL_TEXTURE_3D, baseLevel, GL_RGBA8UI, width, height, depth, 0, GL_RGBA_INTEGER,
12856                  GL_UNSIGNED_BYTE, pixels.data());
12857     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, baseLevel);
12858     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12859     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12860 
12861     drawQuad(mProgram, "position", 0.5f);
12862 
12863     EXPECT_GL_NO_ERROR();
12864     EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12865     EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12866 }
12867 
runCompressedSubImage()12868 void PBOCompressedTextureTest::runCompressedSubImage()
12869 {
12870     // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
12871     ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
12872     // http://anglebug.com/4115
12873     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsDesktopOpenGL());
12874     ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL());
12875 
12876     if (getClientMajorVersion() < 3)
12877     {
12878         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
12879         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
12880         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_ETC2_RGB8_texture"));
12881     }
12882 
12883     const GLuint width  = 4u;
12884     const GLuint height = 4u;
12885 
12886     setWindowWidth(width);
12887     setWindowHeight(height);
12888 
12889     // Setup primary Texture
12890     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12891     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
12892     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
12893 
12894     if (getClientMajorVersion() < 3)
12895     {
12896         glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, width, height);
12897     }
12898     else
12899     {
12900         glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, width, height);
12901     }
12902     ASSERT_GL_NO_ERROR();
12903 
12904     // Setup PBO and fill it with a red
12905     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
12906     glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height / 2u, kCompressedImageETC2, GL_STATIC_DRAW);
12907     ASSERT_GL_NO_ERROR();
12908 
12909     // Write PBO to mTexture
12910     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_COMPRESSED_RGB8_ETC2,
12911                               width * height / 2u, nullptr);
12912     ASSERT_GL_NO_ERROR();
12913 
12914     setUpProgram();
12915     // Draw using PBO updated texture
12916     glUseProgram(mProgram);
12917     glUniform1i(mTexture2DUniformLocation, 0);
12918     glBindTexture(GL_TEXTURE_2D, mTexture2D);
12919     drawQuad(mProgram, "position", 0.5f);
12920     ASSERT_GL_NO_ERROR();
12921 
12922     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
12923     ASSERT_GL_NO_ERROR();
12924 }
12925 
12926 // Test that uses glCompressedTexSubImage2D combined with a PBO
TEST_P(PBOCompressedTextureTest,PBOCompressedSubImage)12927 TEST_P(PBOCompressedTextureTest, PBOCompressedSubImage)
12928 {
12929     runCompressedSubImage();
12930 }
12931 
12932 // Verify the row length state is ignored when using compressed tex image calls.
TEST_P(PBOCompressedTextureTest,PBOCompressedSubImageWithUnpackRowLength)12933 TEST_P(PBOCompressedTextureTest, PBOCompressedSubImageWithUnpackRowLength)
12934 {
12935     // ROW_LENGTH requires ES3 or an extension.
12936     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
12937                        !IsGLExtensionEnabled("GL_EXT_unpack_subimage"));
12938 
12939     glPixelStorei(GL_UNPACK_ROW_LENGTH, 1);
12940     runCompressedSubImage();
12941 }
12942 
12943 class PBOCompressedTexture3DTest : public ANGLETest<>
12944 {
12945   protected:
PBOCompressedTexture3DTest()12946     PBOCompressedTexture3DTest() {}
12947 };
12948 
12949 // Test that uses glCompressedTexSubImage3D combined with a PBO
12950 TEST_P(PBOCompressedTexture3DTest, 2DArray)
12951 {
12952     // We use GetTexImage to determine if the internal texture format is emulated
12953     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_get_image"));
12954 
12955     const GLuint width  = 4u;
12956     const GLuint height = 4u;
12957     const GLuint depth  = 1u;
12958 
12959     setWindowWidth(width);
12960     setWindowHeight(height);
12961 
12962     // Setup primary texture as a 2DArray holding ETC2 data
12963     GLTexture texture2DArray;
12964     glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
12965     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
12966     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
12967     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_COMPRESSED_RGB8_ETC2, width, height, depth);
12968 
12969     // If the format emulated, we can't transfer it from a PBO
12970     ANGLE_SKIP_TEST_IF(IsFormatEmulated(GL_TEXTURE_2D_ARRAY));
12971 
12972     // Set up a VS that simply passes through position and texcord
12973     const char kVS[] = R"(#version 300 es
12974 in vec4 position;
12975 out vec3 texCoord;
12976 
12977 void main()
12978 {
12979     gl_Position = vec4(position.xy, 0.0, 1.0);
12980     texCoord = vec3(position.xy * 0.5 + vec2(0.5), 0.0);
12981 })";
12982 
12983     // and FS that pulls from the 2DArray, writing out color
12984     const char kFS[] = R"(#version 300 es
12985 precision mediump float;
12986 uniform highp sampler2DArray tex2DArray;
12987 in vec3 texCoord;
12988 out vec4 fragColor;
12989 
12990 void main()
12991 {
12992     fragColor = texture(tex2DArray, texCoord);
12993 })";
12994 
12995     // Compile the shaders and create the program
12996     ANGLE_GL_PROGRAM(program, kVS, kFS);
12997     ASSERT_GL_NO_ERROR();
12998 
12999     // Setup PBO and fill it with a red
13000     GLBuffer pbo;
13001     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
13002     glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * depth / 2u, kCompressedImageETC2,
13003                  GL_STATIC_DRAW);
13004     ASSERT_GL_NO_ERROR();
13005 
13006     // Write PBO to texture2DArray
13007     glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, depth,
13008                               GL_COMPRESSED_RGB8_ETC2, width * height * depth / 2u, nullptr);
13009 
13010     ASSERT_GL_NO_ERROR();
13011 
13012     // Draw using PBO updated texture
13013     glUseProgram(program);
13014     glUniform1i(glGetUniformLocation(program, "tex2DArray"), 0);
13015     glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
13016     drawQuad(program, "position", 0.5f);
13017     ASSERT_GL_NO_ERROR();
13018 
13019     // Verify the texture now contains data from the PBO
13020     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13021     ASSERT_GL_NO_ERROR();
13022 }
13023 
13024 // Test using ETC1_RGB8 with subimage updates
TEST_P(ETC1CompressedTextureTest,ETC1CompressedSubImage)13025 TEST_P(ETC1CompressedTextureTest, ETC1CompressedSubImage)
13026 {
13027     // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
13028     ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13029 
13030     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
13031                        !IsGLExtensionEnabled("GL_EXT_texture_storage"));
13032     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13033 
13034     const GLuint width  = 4u;
13035     const GLuint height = 4u;
13036 
13037     setWindowWidth(width);
13038     setWindowHeight(height);
13039 
13040     // Setup primary Texture
13041     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
13042     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13043 
13044     if (getClientMajorVersion() < 3)
13045     {
13046         glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
13047     }
13048     else
13049     {
13050         glTexStorage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
13051     }
13052     ASSERT_GL_NO_ERROR();
13053 
13054     // Populate a subimage of the texture
13055     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ETC1_RGB8_OES,
13056                               width * height / 2u, kCompressedImageETC2);
13057     ASSERT_GL_NO_ERROR();
13058 
13059     // Render and ensure we get red
13060     glUseProgram(mProgram);
13061     drawQuad(mProgram, "position", 0.5f);
13062     ASSERT_GL_NO_ERROR();
13063 
13064     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13065     ASSERT_GL_NO_ERROR();
13066 }
13067 
13068 // Fully-define a NPOT compressed texture and draw; set MAX_LEVEL and draw; then increase
13069 // MAX_LEVEL and draw.  This used to cause Vulkan validation errors.
TEST_P(ETC1CompressedTextureTest,ETC1CompressedImageNPOT)13070 TEST_P(ETC1CompressedTextureTest, ETC1CompressedImageNPOT)
13071 {
13072     // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
13073     ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13074 
13075     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
13076     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13077 
13078     const GLuint width  = 5u;
13079     const GLuint height = 5u;
13080     // round up to the nearest block size
13081     const GLsizei imageSize = 8 * 8 / 2;
13082     // smallest block size
13083     const GLsizei minImageSize = 4 * 4 / 2;
13084 
13085     uint8_t data[imageSize] = {0};
13086 
13087     setWindowWidth(width);
13088     setWindowHeight(height);
13089 
13090     // Setup primary Texture
13091     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
13092     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
13093     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13094     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13095 
13096     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, width, height, 0, imageSize, data);
13097     ASSERT_GL_NO_ERROR();
13098 
13099     glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width / 2, height / 2, 0,
13100                            minImageSize, data);
13101     ASSERT_GL_NO_ERROR();
13102 
13103     glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_ETC1_RGB8_OES, width / 4, height / 4, 0,
13104                            minImageSize, data);
13105     ASSERT_GL_NO_ERROR();
13106 
13107     glUseProgram(mProgram);
13108     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13109     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13110     drawQuad(mProgram, "position", 0.5f);
13111     ASSERT_GL_NO_ERROR();
13112 
13113     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
13114     drawQuad(mProgram, "position", 0.5f);
13115     ASSERT_GL_NO_ERROR();
13116 }
13117 
13118 // Define two NPOT compressed textures, set MAX_LEVEL, draw, and swap buffers
13119 // with the two textures. This used to cause release of staging buffers
13120 // that have not been flushed.
TEST_P(ETC1CompressedTextureTest,ETC1CompressedImageDraws)13121 TEST_P(ETC1CompressedTextureTest, ETC1CompressedImageDraws)
13122 {
13123     // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
13124     ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13125 
13126     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
13127     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13128 
13129     const GLuint width  = 384u;
13130     const GLuint height = 384u;
13131     // round up to the nearest block size
13132     const GLsizei imageSize = width * height / 2;
13133 
13134     uint8_t data[imageSize] = {0};
13135 
13136     setWindowWidth(width);
13137     setWindowHeight(height);
13138 
13139     const GLuint smallerWidth  = 384u;
13140     const GLuint smallerHeight = 320u;
13141     // round up to the nearest block size
13142     const GLsizei smallerImageSize = smallerWidth * smallerHeight / 2;
13143 
13144     // Setup primary Texture
13145     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
13146     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
13147     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13148     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13149 
13150     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, smallerWidth, smallerHeight, 0,
13151                            smallerImageSize, data);
13152     ASSERT_GL_NO_ERROR();
13153 
13154     glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 192, 160, 0, 15360, data);
13155     ASSERT_GL_NO_ERROR();
13156 
13157     GLTexture largerTexture;
13158     glBindTexture(GL_TEXTURE_2D, largerTexture);
13159 
13160     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, width, height, 0, imageSize, data);
13161     ASSERT_GL_NO_ERROR();
13162 
13163     glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 192, 192, 0, 18432, data);
13164     ASSERT_GL_NO_ERROR();
13165 
13166     glBindTexture(GL_TEXTURE_2D, mTexture2D);
13167 
13168     glUseProgram(mProgram);
13169     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13170     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13171     drawQuad(mProgram, "position", 0.5f);
13172     ASSERT_GL_NO_ERROR();
13173     swapBuffers();
13174     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
13175     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
13176     drawQuad(mProgram, "position", 0.5f);
13177     ASSERT_GL_NO_ERROR();
13178     swapBuffers();
13179 
13180     glBindTexture(GL_TEXTURE_2D, largerTexture);
13181 
13182     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13183     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13184     drawQuad(mProgram, "position", 0.5f);
13185     ASSERT_GL_NO_ERROR();
13186     swapBuffers();
13187 
13188     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
13189     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
13190     drawQuad(mProgram, "position", 0.5f);
13191     ASSERT_GL_NO_ERROR();
13192     swapBuffers();
13193 
13194     glBindTexture(GL_TEXTURE_2D, mTexture2D);
13195 
13196     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13197     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13198     drawQuad(mProgram, "position", 0.5f);
13199     swapBuffers();
13200     ASSERT_GL_NO_ERROR();
13201 }
13202 
13203 // Fully-define a compressed texture and draw; then decrease MAX_LEVEL and draw; then increase
13204 // MAX_LEVEL and draw.  This used to cause Vulkan validation errors.
TEST_P(ETC1CompressedTextureTest,ETC1ShrinkThenGrowMaxLevels)13205 TEST_P(ETC1CompressedTextureTest, ETC1ShrinkThenGrowMaxLevels)
13206 {
13207     // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
13208     ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13209 
13210     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
13211     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13212 
13213     const GLuint width  = 4u;
13214     const GLuint height = 4u;
13215 
13216     setWindowWidth(width);
13217     setWindowHeight(height);
13218 
13219     // Setup primary Texture
13220     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
13221     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13222 
13223     if (getClientMajorVersion() < 3)
13224     {
13225         glTexStorage2DEXT(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, width, height);
13226     }
13227     else
13228     {
13229         glTexStorage2D(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, width, height);
13230     }
13231     ASSERT_GL_NO_ERROR();
13232 
13233     // Populate a subimage of the texture
13234     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ETC1_RGB8_OES,
13235                               width * height / 2u, kCompressedImageETC2);
13236     glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, width / 2, height / 2, GL_ETC1_RGB8_OES,
13237                               width * height / 2u, kCompressedImageETC2);
13238     glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, width / 4, height / 4, GL_ETC1_RGB8_OES,
13239                               width * height / 2u, kCompressedImageETC2);
13240     ASSERT_GL_NO_ERROR();
13241 
13242     // Set MAX_LEVEL to 2 (the highest level)
13243     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
13244 
13245     // Render and ensure we get red
13246     glUseProgram(mProgram);
13247     drawQuad(mProgram, "position", 0.5f);
13248     ASSERT_GL_NO_ERROR();
13249     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13250     ASSERT_GL_NO_ERROR();
13251 
13252     // Decrease MAX_LEVEL to 0, render, and ensure we still get red
13253     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13254     drawQuad(mProgram, "position", 0.5f);
13255     ASSERT_GL_NO_ERROR();
13256     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13257     ASSERT_GL_NO_ERROR();
13258 
13259     // Increase MAX_LEVEL back to 2, render, and ensure we still get red
13260     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
13261     drawQuad(mProgram, "position", 0.5f);
13262     ASSERT_GL_NO_ERROR();
13263     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13264     ASSERT_GL_NO_ERROR();
13265 }
13266 
13267 class TextureBufferTestES31 : public ANGLETest<>
13268 {
13269   protected:
TextureBufferTestES31()13270     TextureBufferTestES31() {}
13271 
13272     void drawWithIncompleteOrZeroTexture(bool useCompleteTexture, bool useNonZeroTexture);
13273 };
13274 
drawWithIncompleteOrZeroTexture(bool useCompleteTexture,bool useNonZeroTexture)13275 void TextureBufferTestES31::drawWithIncompleteOrZeroTexture(bool useCompleteTexture,
13276                                                             bool useNonZeroTexture)
13277 {
13278     constexpr char kSamplerBuffer[] = R"(#version 310 es
13279         #extension GL_OES_texture_buffer : require
13280         precision mediump float;
13281         uniform highp samplerBuffer s;
13282         out vec4 colorOut;
13283         void main()
13284         {
13285             colorOut = texelFetch(s, 0);
13286         })";
13287 
13288     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kSamplerBuffer);
13289     glUseProgram(program);
13290     EXPECT_GL_NO_ERROR();
13291 
13292     // Bind as texture buffer
13293     GLTexture texture;
13294     glActiveTexture(GL_TEXTURE0);
13295     glBindTexture(GL_TEXTURE_BUFFER, useNonZeroTexture ? texture.get() : 0u);
13296     EXPECT_GL_NO_ERROR();
13297 
13298     if (useCompleteTexture)
13299     {
13300         const std::array<GLColor, 4> kData = {GLColor::blue, GLColor::blue, GLColor::blue,
13301                                               GLColor::blue};
13302 
13303         // Create buffer and initialize with data
13304         GLBuffer buffer;
13305         glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13306         glBufferData(GL_TEXTURE_BUFFER, sizeof(kData), kData.data(), GL_DYNAMIC_DRAW);
13307         glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13308         EXPECT_GL_NO_ERROR();
13309     }
13310 
13311     // Draw texture buffer
13312     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
13313     EXPECT_GL_NO_ERROR();
13314 
13315     if (useCompleteTexture)
13316     {
13317         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13318     }
13319 }
13320 
13321 // Test that mutating a buffer attached to a texture returns correct results in query.
TEST_P(TextureBufferTestES31,QueryWidthAfterBufferResize)13322 TEST_P(TextureBufferTestES31, QueryWidthAfterBufferResize)
13323 {
13324     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
13325 
13326     constexpr GLint kInitialSize                  = 128;
13327     constexpr std::array<GLint, 4> kModifiedSizes = {96, 192, 32, 256};
13328 
13329     GLTexture texture;
13330     glBindTexture(GL_TEXTURE_BUFFER, texture);
13331 
13332     GLBuffer buffer;
13333     glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13334     glBufferData(GL_TEXTURE_BUFFER, kInitialSize, nullptr, GL_STATIC_DRAW);
13335 
13336     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13337     ASSERT_GL_NO_ERROR();
13338 
13339     GLint queryResult = 0;
13340     glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
13341     ASSERT_GL_NO_ERROR();
13342     EXPECT_EQ(queryResult, kInitialSize / 4);
13343 
13344     for (GLint modifiedSize : kModifiedSizes)
13345     {
13346         glBufferData(GL_TEXTURE_BUFFER, modifiedSize, nullptr, GL_STATIC_DRAW);
13347         glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
13348         ASSERT_GL_NO_ERROR();
13349         EXPECT_EQ(queryResult, modifiedSize / 4);
13350     }
13351 }
13352 
13353 // Test that glTexBufferEXT can be used in two draw calls.
13354 // Covers a bug where TextureVk::setBuffer releases buffer views and doesn't init them.
TEST_P(TextureBufferTestES31,TexBufferDrawTwice)13355 TEST_P(TextureBufferTestES31, TexBufferDrawTwice)
13356 {
13357     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13358 
13359     // TODO(http://anglebug.com/5832): Claims to support GL_OES_texture_buffer, but fails
13360     // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported".
13361     ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
13362 
13363     const std::array<GLColor, 1> kTexData = {GLColor::red};
13364 
13365     GLBuffer buffer;
13366     glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13367     glBufferData(GL_TEXTURE_BUFFER, sizeof(kTexData), kTexData.data(), GL_DYNAMIC_DRAW);
13368     EXPECT_GL_NO_ERROR();
13369 
13370     constexpr char kSamplerBuffer[] = R"(#version 310 es
13371 #extension GL_OES_texture_buffer : require
13372 precision mediump float;
13373 uniform highp samplerBuffer s;
13374 out vec4 colorOut;
13375 void main()
13376 {
13377     colorOut = texelFetch(s, 0);
13378 })";
13379 
13380     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kSamplerBuffer);
13381 
13382     // Draw once
13383     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13384     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
13385     EXPECT_GL_NO_ERROR();
13386 
13387     // Draw twice
13388     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13389     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
13390     EXPECT_GL_NO_ERROR();
13391 
13392     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
13393 }
13394 
13395 // Test that uploading data to buffer that's in use then using it as texture buffer works.
TEST_P(TextureBufferTestES31,UseAsUBOThenUpdateThenAsTextureBuffer)13396 TEST_P(TextureBufferTestES31, UseAsUBOThenUpdateThenAsTextureBuffer)
13397 {
13398     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13399 
13400     // Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension
13401     // 'GL_OES_texture_buffer' is not supported".  http://anglebug.com/5832
13402     ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
13403 
13404     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
13405                                                  GLColor::red};
13406     const std::array<GLColor, 4> kUpdateData  = {GLColor::blue, GLColor::blue, GLColor::blue,
13407                                                  GLColor::blue};
13408 
13409     GLBuffer buffer;
13410     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
13411     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
13412     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
13413     EXPECT_GL_NO_ERROR();
13414 
13415     constexpr char kVerifyUBO[] = R"(#version 310 es
13416 precision mediump float;
13417 layout(binding = 0) uniform block {
13418     uvec4 data;
13419 } ubo;
13420 out vec4 colorOut;
13421 void main()
13422 {
13423     if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
13424         colorOut = vec4(0, 1.0, 0, 1.0);
13425     else
13426         colorOut = vec4(1.0, 0, 0, 1.0);
13427 })";
13428 
13429     ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
13430     drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
13431     EXPECT_GL_NO_ERROR();
13432 
13433     // Update buffer data
13434     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
13435     EXPECT_GL_NO_ERROR();
13436 
13437     // Bind as texture buffer
13438     GLTexture texture;
13439     glBindTexture(GL_TEXTURE_BUFFER, texture);
13440     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13441     EXPECT_GL_NO_ERROR();
13442 
13443     constexpr char kVerifySamplerBuffer[] = R"(#version 310 es
13444 #extension GL_OES_texture_buffer : require
13445 precision mediump float;
13446 uniform highp samplerBuffer s;
13447 out vec4 colorOut;
13448 void main()
13449 {
13450     colorOut = texelFetch(s, 0);
13451 })";
13452 
13453     ANGLE_GL_PROGRAM(verifySamplerBuffer, essl31_shaders::vs::Simple(), kVerifySamplerBuffer);
13454 
13455     glEnable(GL_BLEND);
13456     glBlendFunc(GL_ONE, GL_ONE);
13457     drawQuad(verifySamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13458     EXPECT_GL_NO_ERROR();
13459 
13460     // Make sure both draw calls succeed
13461     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
13462 }
13463 
13464 // Test that mapping a texture buffer with GL_MAP_INVALIDATE_BUFFER_BIT and writing to it works
13465 // correctly.
TEST_P(TextureBufferTestES31,MapTextureBufferInvalidateThenWrite)13466 TEST_P(TextureBufferTestES31, MapTextureBufferInvalidateThenWrite)
13467 {
13468     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13469 
13470     // TODO(http://anglebug.com/5832): Claims to support GL_OES_texture_buffer, but fails
13471     // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported".
13472     ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
13473     // TODO(http://anglebug.com/6396): The OpenGL backend doesn't correctly handle texture buffers
13474     // being invalidated when mapped.
13475     ANGLE_SKIP_TEST_IF(IsOpenGL());
13476 
13477     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
13478                                                  GLColor::red};
13479     const std::array<GLColor, 4> kUpdateData  = {GLColor::blue, GLColor::blue, GLColor::blue,
13480                                                  GLColor::blue};
13481 
13482     GLBuffer buffer;
13483     glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13484     glBufferData(GL_TEXTURE_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
13485     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
13486     EXPECT_GL_NO_ERROR();
13487 
13488     // Bind as texture buffer
13489     GLTexture texture;
13490     glBindTexture(GL_TEXTURE_BUFFER, texture);
13491     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13492     EXPECT_GL_NO_ERROR();
13493 
13494     constexpr char kSamplerBuffer[] = R"(#version 310 es
13495 #extension GL_OES_texture_buffer : require
13496 precision mediump float;
13497 uniform highp samplerBuffer s;
13498 out vec4 colorOut;
13499 void main()
13500 {
13501     colorOut = texelFetch(s, 0);
13502 })";
13503 
13504     ANGLE_GL_PROGRAM(initialSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
13505     drawQuad(initialSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13506     EXPECT_GL_NO_ERROR();
13507 
13508     // Don't read back, so we don't break the render pass.
13509 
13510     // Map the buffer and update it.
13511     void *mappedBuffer = glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(kInitialData),
13512                                           GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
13513     memcpy(mappedBuffer, kUpdateData.data(), sizeof(kInitialData));
13514 
13515     glUnmapBuffer(GL_TEXTURE_BUFFER);
13516 
13517     // Draw with the updated buffer data.
13518     ANGLE_GL_PROGRAM(updateSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
13519     drawQuad(updateSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13520     EXPECT_GL_NO_ERROR();
13521 
13522     // Make sure both draw calls succeed
13523     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13524 }
13525 
13526 // Test that calling glBufferData on a buffer that is used as texture buffer still works correctly.
TEST_P(TextureBufferTestES31,TextureBufferThenBufferData)13527 TEST_P(TextureBufferTestES31, TextureBufferThenBufferData)
13528 {
13529     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13530 
13531     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
13532                                                  GLColor::red};
13533     const std::array<GLColor, 4> kUpdateData  = {GLColor::blue, GLColor::blue, GLColor::blue,
13534                                                  GLColor::blue};
13535     // Create buffer and initialize with data
13536     GLBuffer buffer;
13537     glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13538     glBufferData(GL_TEXTURE_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
13539 
13540     // Bind as texture buffer
13541     GLTexture texture;
13542     glBindTexture(GL_TEXTURE_BUFFER, texture);
13543     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13544     EXPECT_GL_NO_ERROR();
13545 
13546     constexpr char kSamplerBuffer[] = R"(#version 310 es
13547 #extension GL_OES_texture_buffer : require
13548 precision mediump float;
13549 uniform highp samplerBuffer s;
13550 out vec4 colorOut;
13551 void main()
13552 {
13553     colorOut = texelFetch(s, 0);
13554 })";
13555 
13556     ANGLE_GL_PROGRAM(initialSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
13557     drawQuad(initialSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13558 
13559     // Don't read back, so we keep the original buffer busy. Issue a glBufferData call with same
13560     // size and nullptr so that the old buffer storage gets orphaned.
13561     glBufferData(GL_TEXTURE_BUFFER, sizeof(kUpdateData), nullptr, GL_DYNAMIC_DRAW);
13562     glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(kUpdateData), kUpdateData.data());
13563 
13564     // Draw with the updated buffer data.
13565     ANGLE_GL_PROGRAM(updateSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
13566     drawQuad(updateSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13567     EXPECT_GL_NO_ERROR();
13568     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13569 }
13570 
13571 // Test workaround in Vulkan backend for mismatched texture buffer and sampler formats
TEST_P(TextureBufferTestES31,TexBufferFormatMismatch)13572 TEST_P(TextureBufferTestES31, TexBufferFormatMismatch)
13573 {
13574     ANGLE_SKIP_TEST_IF(!IsVulkan());
13575     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
13576 
13577     auto runTestCase = [&](auto texData, GLenum format, const char *samplerType) {
13578         std::stringstream fsStream;
13579         fsStream << R"(#version 310 es
13580     #extension GL_EXT_texture_buffer : require
13581     precision mediump float;
13582     uniform highp )"
13583                  << samplerType << R"( s;
13584     out vec4 colorOut;
13585     void main()
13586     {
13587         colorOut = vec4(texelFetch(s, 0).r, 0, 0, 1);
13588     })";
13589         ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fsStream.str().c_str());
13590 
13591         GLBuffer buffer;
13592         glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13593 
13594         glBufferData(GL_TEXTURE_BUFFER, sizeof(texData), texData.data(), GL_DYNAMIC_DRAW);
13595         glTexBufferEXT(GL_TEXTURE_BUFFER, format, buffer);
13596 
13597         drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
13598         EXPECT_GL_NO_ERROR();
13599         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
13600     };
13601 
13602     const std::array<uint8_t, 4> kTexData8n{255};  // 8-bit normalized {1,0,0,0}
13603     const std::array<uint8_t, 4> kTexData8i{1};    // 8-bit (u)int {1,0,0,0}
13604 
13605     // Test all 8-bit formats from EXT_texture_buffer.txt Table texbo.1
13606     for (auto format :
13607          {GL_R8, GL_R8I, GL_R8UI, GL_RG8, GL_RG8I, GL_RG8UI, GL_RGBA8, GL_RGBA8I, GL_RGBA8UI})
13608     {
13609         // float sampler
13610         runTestCase(kTexData8n, format, "samplerBuffer");
13611         // integer samplers
13612         runTestCase(kTexData8i, format, "isamplerBuffer");
13613         runTestCase(kTexData8i, format, "usamplerBuffer");
13614     }
13615 
13616     const uint16_t kHalfFloatOne = 0x3C00;
13617     const std::array<uint16_t, 4> kTexData16f{kHalfFloatOne};  // 16-bit float {1,0,0,0}
13618     const std::array<uint16_t, 4> kTexData16i{1};              // 16-bit (u)int {1,0,0,0}
13619 
13620     // Test all 16-bit formats from EXT_texture_buffer.txt Table texbo.1
13621     for (auto format : {GL_R16F, GL_R16I, GL_R16UI, GL_RG16F, GL_RG16I, GL_RG16UI, GL_RGBA16F,
13622                         GL_RGBA16I, GL_RGBA16UI})
13623     {
13624         // float sampler
13625         runTestCase(kTexData16f, format, "samplerBuffer");
13626         // integer samplers
13627         runTestCase(kTexData16i, format, "isamplerBuffer");
13628         runTestCase(kTexData16i, format, "usamplerBuffer");
13629     }
13630 
13631     const std::array<GLfloat, 4> kTexData32f{1.0f};  // 32-bit float {1,0,0,0}
13632     const std::array<uint32_t, 4> kTexData32i{1};    // 32-bit (u)int {1,0,0,0}
13633 
13634     // Test all 32-bit formats from EXT_texture_buffer.txt Table texbo.1
13635     for (auto format : {GL_R32F, GL_R32I, GL_R32UI, GL_RG32F, GL_RG32I, GL_RG32UI, GL_RGB32F,
13636                         GL_RGB32I, GL_RGB32UI, GL_RGBA32F, GL_RGBA32I, GL_RGBA32UI})
13637     {
13638         // float sampler
13639         runTestCase(kTexData32f, format, "samplerBuffer");
13640         // integer samplers
13641         runTestCase(kTexData32i, format, "isamplerBuffer");
13642         runTestCase(kTexData32i, format, "usamplerBuffer");
13643     }
13644 }
13645 
13646 // Create an integer format texture but specify a FLOAT sampler. OpenGL
13647 // tolerates this but it causes a Vulkan validation error.
TEST_P(Texture2DTestES3,TexImageFormatMismatch)13648 TEST_P(Texture2DTestES3, TexImageFormatMismatch)
13649 {
13650     GLint textureUnit = 2;
13651     GLuint genericBuffer;
13652     GLubyte genericBufferMemory[1024];
13653     GLuint texture;
13654     GLuint sampler;
13655     GLuint vertexArray;
13656 
13657     glGenBuffers(1, &genericBuffer);
13658     glBindBuffer(GL_ARRAY_BUFFER, genericBuffer);
13659     glBufferData(GL_ARRAY_BUFFER, 1024, &genericBufferMemory, GL_STATIC_DRAW);
13660 
13661     glGenTextures(1, &texture);
13662     glBindTexture(GL_TEXTURE_2D, texture);
13663     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13664     glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, 8, 8, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT,
13665                  &genericBufferMemory);
13666 
13667     const char *vertexShaderSource   = getVertexShaderSource();
13668     const char *fragmentShaderSource = getFragmentShaderSource();
13669     ANGLE_GL_PROGRAM(testProgram, vertexShaderSource, fragmentShaderSource);
13670 
13671     GLint texLocation = glGetUniformLocation(testProgram, "tex");
13672     glUseProgram(testProgram);
13673 
13674     glUniform1iv(texLocation, 1, &textureUnit);
13675 
13676     glGenSamplers(1, &sampler);
13677     glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13678     glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13679 
13680     glBindBuffer(GL_UNIFORM_BUFFER, genericBuffer);
13681 
13682     glActiveTexture(GL_TEXTURE0 + textureUnit);
13683     glBindTexture(GL_TEXTURE_2D, texture);
13684     glBindSampler(textureUnit, sampler);
13685 
13686     glGenVertexArrays(1, &vertexArray);
13687     glBindVertexArray(vertexArray);
13688     glBindBuffer(GL_ARRAY_BUFFER, genericBuffer);
13689 
13690     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, genericBuffer);
13691     glBindVertexArray(vertexArray);
13692     glDrawElementsInstanced(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, 0, 1);
13693 }
13694 
13695 // Checks that drawing incomplete zero texture buffer does not crash.
TEST_P(TextureBufferTestES31,DrawIncompleteZeroTexture)13696 TEST_P(TextureBufferTestES31, DrawIncompleteZeroTexture)
13697 {
13698     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13699 
13700     drawWithIncompleteOrZeroTexture(false, false);
13701 }
13702 
13703 // Checks that drawing incomplete non-zero texture buffer does not crash.
TEST_P(TextureBufferTestES31,DrawIncompleteNonZeroTexture)13704 TEST_P(TextureBufferTestES31, DrawIncompleteNonZeroTexture)
13705 {
13706     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13707 
13708     drawWithIncompleteOrZeroTexture(false, true);
13709 }
13710 
13711 // Checks that drawing complete zero texture buffer produces expected results.
TEST_P(TextureBufferTestES31,DrawCompleteZeroTexture)13712 TEST_P(TextureBufferTestES31, DrawCompleteZeroTexture)
13713 {
13714     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13715 
13716     drawWithIncompleteOrZeroTexture(true, false);
13717 }
13718 
13719 // Checks that drawing complete non-zero texture buffer produces expected results.
TEST_P(TextureBufferTestES31,DrawCompleteNonZeroTexture)13720 TEST_P(TextureBufferTestES31, DrawCompleteNonZeroTexture)
13721 {
13722     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13723 
13724     drawWithIncompleteOrZeroTexture(true, true);
13725 }
13726 
13727 // Test that the correct error is generated if texture buffer support used anyway when not enabled.
TEST_P(TextureBufferTestES31,TestErrorWhenNotEnabled)13728 TEST_P(TextureBufferTestES31, TestErrorWhenNotEnabled)
13729 {
13730     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_texture_buffer"));
13731 
13732     GLTexture texture;
13733     glBindTexture(GL_TEXTURE_BUFFER, texture);
13734     ASSERT_GL_ERROR(GL_INVALID_ENUM);
13735 }
13736 
13737 class CopyImageTestES31 : public ANGLETest<>
13738 {
13739   protected:
CopyImageTestES31()13740     CopyImageTestES31() {}
13741 };
13742 
13743 // Test that copies between RGB formats doesn't affect the emulated alpha channel, if any.
TEST_P(CopyImageTestES31,PreserveEmulatedAlpha)13744 TEST_P(CopyImageTestES31, PreserveEmulatedAlpha)
13745 {
13746     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
13747 
13748     constexpr GLsizei kSize = 1;
13749 
13750     GLTexture src, dst;
13751 
13752     // Set up the textures
13753     glBindTexture(GL_TEXTURE_2D, src);
13754     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, kSize, kSize);
13755 
13756     const GLColor kInitColor(50, 100, 150, 200);
13757     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGB, GL_UNSIGNED_BYTE, &kInitColor);
13758 
13759     glBindTexture(GL_TEXTURE_2D, dst);
13760     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8UI, kSize, kSize);
13761     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13762     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13763 
13764     // Copy from src to dst
13765     glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
13766                           kSize, 1);
13767 
13768     // Bind dst as image
13769     glBindImageTexture(0, dst, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
13770 
13771     // Create a buffer for output
13772     constexpr GLsizei kBufferSize = kSize * kSize * sizeof(uint32_t) * 4;
13773     GLBuffer buffer;
13774     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
13775     glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
13776     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer);
13777 
13778     constexpr char kCS[] = R"(#version 310 es
13779 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
13780 layout(rgba8ui, binding = 0) readonly uniform highp uimage2D imageIn;
13781  layout(std140, binding = 1) buffer dataOut {
13782      uvec4 data[];
13783  };
13784 void main()
13785 {
13786     uvec4 color = imageLoad(imageIn, ivec2(0));
13787     data[0] = color;
13788 })";
13789 
13790     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13791     glUseProgram(program);
13792     glDispatchCompute(1, 1, 1);
13793     EXPECT_GL_NO_ERROR();
13794 
13795     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13796 
13797     const uint32_t *ptr = reinterpret_cast<uint32_t *>(
13798         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
13799 
13800     EXPECT_EQ(ptr[0], kInitColor.R);
13801     EXPECT_EQ(ptr[1], kInitColor.G);
13802     EXPECT_EQ(ptr[2], kInitColor.B);
13803 
13804     // Expect alpha to be 1, even if the RGB format is emulated with RGBA.
13805     EXPECT_EQ(ptr[3], 1u);
13806 
13807     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13808 }
13809 
13810 // Verify a common pattern used by the Unreal Engine that trips up the tracer
TEST_P(CopyImageTestES31,CubeMapCopyImageSubData)13811 TEST_P(CopyImageTestES31, CubeMapCopyImageSubData)
13812 {
13813     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
13814 
13815     constexpr char kVS[] =
13816         R"(#version 300 es
13817         precision mediump float;
13818         in vec3 pos;
13819         void main() {
13820             gl_Position = vec4(pos, 1.0);
13821         })";
13822 
13823     constexpr char kFS[] =
13824         R"(#version 300 es
13825         precision mediump float;
13826         out vec4 color;
13827         uniform samplerCube uTex;
13828         void main(){
13829             // sample from lod 1.0
13830             color = textureLod(uTex, vec3(1.0), 1.0);
13831         })";
13832 
13833     ANGLE_GL_PROGRAM(program, kVS, kFS);
13834     glUseProgram(program);
13835 
13836     // Set up two cube maps, then verify we can copy between them
13837     constexpr size_t kSize = 2;
13838     constexpr int levels   = 2;
13839     std::vector<GLColor> pixelsGreen(kSize * kSize, GLColor::green);
13840     std::vector<GLColor> pixelsRed(kSize * kSize, GLColor::red);
13841 
13842     // Initialize src to green
13843     GLTexture texCubeSrc;
13844     glBindTexture(GL_TEXTURE_CUBE_MAP, texCubeSrc);
13845     for (int i = 0; i < levels; i++)
13846     {
13847         for (GLenum face = 0; face < 6; face++)
13848         {
13849             glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, GL_RGBA, kSize >> i, kSize >> i,
13850                          0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsGreen.data());
13851         }
13852     }
13853     ASSERT_GL_NO_ERROR();
13854 
13855     // Initialize dst to red
13856     GLTexture texCubeDst;
13857     glBindTexture(GL_TEXTURE_CUBE_MAP, texCubeDst);
13858     for (int i = 0; i < levels; i++)
13859     {
13860         for (GLenum face = 0; face < 6; face++)
13861         {
13862             glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, GL_RGBA, kSize >> i, kSize >> i,
13863                          0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
13864         }
13865     }
13866     ASSERT_GL_NO_ERROR();
13867 
13868     // Clear to blue
13869     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
13870     glClear(GL_COLOR_BUFFER_BIT);
13871     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13872 
13873     // Sample from the dst texture to ensure it has the right color
13874     GLint textureLoc = glGetUniformLocation(program, "uTex");
13875     ASSERT_NE(-1, textureLoc);
13876     glUniform1i(textureLoc, 0);
13877 
13878     // Draw once and sample from level 1, which is red
13879     drawQuad(program, "pos", 0.5f);
13880     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
13881 
13882     // Swap to trigger MEC
13883     swapBuffers();
13884 
13885     // Copy level 1 from src to dst
13886     glCopyImageSubDataEXT(texCubeSrc, GL_TEXTURE_CUBE_MAP, 1, 0, 0, 0, texCubeDst,
13887                           GL_TEXTURE_CUBE_MAP, 1, 0, 0, 0, kSize >> 1, kSize >> 1, 6);
13888     ASSERT_GL_NO_ERROR();
13889 
13890     // Draw again and verify we get green
13891     drawQuad(program, "pos", 0.5f);
13892     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
13893 
13894     // Swap again to end the capture
13895     swapBuffers();
13896 
13897     ASSERT_GL_NO_ERROR();
13898 }
13899 
13900 // Verify that copies between texture layers works, including when there is a read after write in a
13901 // level/layer.
TEST_P(CopyImageTestES31,ArraySelfCopyImageSubDataWithReadAfterWrite)13902 TEST_P(CopyImageTestES31, ArraySelfCopyImageSubDataWithReadAfterWrite)
13903 {
13904     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
13905 
13906     // Set up a texture with multiple layers, then verify we can copy between them
13907     constexpr uint32_t kWidth  = 13;
13908     constexpr uint32_t kHeight = 57;
13909     constexpr uint32_t kLayers = 5;
13910     constexpr uint32_t kLevels = 2;
13911     std::vector<GLColor> pixelsRed(kWidth * kHeight, GLColor::red);
13912     std::vector<GLColor> pixelsGreen(kWidth * kHeight, GLColor::green);
13913     std::vector<GLColor> pixelsBlue(kWidth * kHeight, GLColor::blue);
13914 
13915     const GLColor *colors[3] = {
13916         pixelsRed.data(),
13917         pixelsGreen.data(),
13918         pixelsBlue.data(),
13919     };
13920 
13921     GLTexture tex;
13922     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
13923     glTexStorage3D(GL_TEXTURE_2D_ARRAY, kLevels, GL_RGBA8, kWidth, kHeight, kLayers);
13924     for (uint32_t level = 0; level < kLevels; ++level)
13925     {
13926         for (uint32_t layer = 0; layer < kLayers; ++layer)
13927         {
13928             glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, layer, kWidth >> level,
13929                             kHeight >> level, 1, GL_RGBA, GL_UNSIGNED_BYTE,
13930                             colors[(level + layer) % 3]);
13931         }
13932     }
13933     ASSERT_GL_NO_ERROR();
13934 
13935     // The texture has the following colors:
13936     //              Layer 0   Layer 1   Layer 2   Layer 3   Layer 4
13937     // Level  0      Red       Green     Blue      Red       Green
13938     // Level  1      Green     Blue      Red       Green     Blue
13939 
13940     // Copy level 0, layer 0 to level 0, layer 2
13941     glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
13942                           2, kWidth, kHeight, 1);
13943 
13944     // Copy level 1, layers 3, 4 to level 1, layers 1, 2
13945     glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 1, 0, 0, 3, tex, GL_TEXTURE_2D_ARRAY, 1, 0, 0,
13946                           1, kWidth >> 1, kHeight >> 1, 2);
13947 
13948     // Partially copy level 1, layer 1 to level 0, layer 3
13949     // Level 1/layer 1 will be read from after being written to
13950     glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 1, kWidth / 8, kHeight / 8, 1, tex,
13951                           GL_TEXTURE_2D_ARRAY, 0, kWidth / 4, kHeight / 4, 3, kWidth / 4,
13952                           kHeight / 4, 1);
13953     ASSERT_GL_NO_ERROR();
13954 
13955     // Verify colors
13956     GLFramebuffer FBO;
13957     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
13958     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
13959     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
13960 
13961     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
13962     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
13963 
13964     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
13965     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
13966 
13967     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 3);
13968     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight / 4, GLColor::red);
13969     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 4, kHeight, GLColor::red);
13970     EXPECT_PIXEL_RECT_EQ(0, kHeight / 4 + kHeight / 4, kWidth,
13971                          kHeight - (kHeight / 4 + kHeight / 4), GLColor::red);
13972     EXPECT_PIXEL_RECT_EQ(kWidth / 4 + kWidth / 4, 0, kWidth - (kWidth / 4 + kWidth / 4), kHeight,
13973                          GLColor::red);
13974     EXPECT_PIXEL_RECT_EQ(kWidth / 4, kHeight / 4, kWidth / 4, kHeight / 4, GLColor::green);
13975 
13976     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 4);
13977     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
13978 
13979     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 0);
13980     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
13981 
13982     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 1);
13983     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
13984 
13985     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 2);
13986     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
13987 
13988     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 3);
13989     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
13990 
13991     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 4);
13992     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
13993     ASSERT_GL_NO_ERROR();
13994 }
13995 
13996 // Verify that copies between texture layers works, including when there is a write after read in a
13997 // level/layer.
TEST_P(CopyImageTestES31,ArraySelfCopyImageSubDataWithWriteAfterRead)13998 TEST_P(CopyImageTestES31, ArraySelfCopyImageSubDataWithWriteAfterRead)
13999 {
14000     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
14001 
14002     // Set up a texture with multiple layers, then verify we can copy between them
14003     constexpr uint32_t kWidth  = 13;
14004     constexpr uint32_t kHeight = 57;
14005     constexpr uint32_t kLayers = 5;
14006     constexpr uint32_t kLevels = 2;
14007     std::vector<GLColor> pixelsRed(kWidth * kHeight, GLColor::red);
14008     std::vector<GLColor> pixelsGreen(kWidth * kHeight, GLColor::green);
14009     std::vector<GLColor> pixelsBlue(kWidth * kHeight, GLColor::blue);
14010 
14011     const GLColor *colors[3] = {
14012         pixelsRed.data(),
14013         pixelsGreen.data(),
14014         pixelsBlue.data(),
14015     };
14016 
14017     GLTexture tex;
14018     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
14019     glTexStorage3D(GL_TEXTURE_2D_ARRAY, kLevels, GL_RGBA8, kWidth, kHeight, kLayers);
14020     for (uint32_t level = 0; level < kLevels; ++level)
14021     {
14022         for (uint32_t layer = 0; layer < kLayers; ++layer)
14023         {
14024             glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, layer, kWidth >> level,
14025                             kHeight >> level, 1, GL_RGBA, GL_UNSIGNED_BYTE,
14026                             colors[(level + layer) % 3]);
14027         }
14028     }
14029     ASSERT_GL_NO_ERROR();
14030 
14031     // The texture has the following colors:
14032     //              Layer 0   Layer 1   Layer 2   Layer 3   Layer 4
14033     // Level  0      Red       Green     Blue      Red       Green
14034     // Level  1      Green     Blue      Red       Green     Blue
14035 
14036     // Copy level 0, layer 0 to level 0, layer 2
14037     glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14038                           2, kWidth, kHeight, 1);
14039     ASSERT_GL_NO_ERROR();
14040 
14041     // Copy level 0, layer 1 to level 0, layer 3
14042     glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14043                           3, kWidth, kHeight, 1);
14044     ASSERT_GL_NO_ERROR();
14045 
14046     // Copy level 0, layer 0 to level 0, layer 1
14047     // Level 0/layer 1 will be written to from after being read from
14048     glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14049                           1, kWidth, kHeight, 1);
14050     ASSERT_GL_NO_ERROR();
14051 
14052     // Verify colors
14053     GLFramebuffer FBO;
14054     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
14055     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
14056     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14057 
14058     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
14059     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14060 
14061     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
14062     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14063 
14064     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 3);
14065     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14066 
14067     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 4);
14068     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14069 
14070     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 0);
14071     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
14072 
14073     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 1);
14074     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14075 
14076     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 2);
14077     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::red);
14078 
14079     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 3);
14080     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
14081 
14082     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 4);
14083     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14084     ASSERT_GL_NO_ERROR();
14085 }
14086 
14087 // Verify that copies between 3D texture slices work
TEST_P(CopyImageTestES31,Texture3DSelfCopyImageSubData)14088 TEST_P(CopyImageTestES31, Texture3DSelfCopyImageSubData)
14089 {
14090     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
14091 
14092     // Set up a texture with multiple layers, then verify we can copy between them
14093     constexpr uint32_t kWidth  = 23;
14094     constexpr uint32_t kHeight = 47;
14095     constexpr uint32_t kDepth  = 5;
14096     constexpr uint32_t kLevels = 2;
14097     std::vector<GLColor> pixelsRed(kWidth * kHeight, GLColor::red);
14098     std::vector<GLColor> pixelsGreen(kWidth * kHeight, GLColor::green);
14099     std::vector<GLColor> pixelsBlue(kWidth * kHeight, GLColor::blue);
14100 
14101     const GLColor *colors[3] = {
14102         pixelsRed.data(),
14103         pixelsGreen.data(),
14104         pixelsBlue.data(),
14105     };
14106 
14107     GLTexture tex;
14108     glBindTexture(GL_TEXTURE_3D, tex);
14109     glTexStorage3D(GL_TEXTURE_3D, kLevels, GL_RGBA8, kWidth, kHeight, kDepth);
14110     for (uint32_t level = 0; level < kLevels; ++level)
14111     {
14112         for (uint32_t depth = 0; depth < kDepth >> level; ++depth)
14113         {
14114             glTexSubImage3D(GL_TEXTURE_3D, level, 0, 0, depth, kWidth >> level, kHeight >> level, 1,
14115                             GL_RGBA, GL_UNSIGNED_BYTE, colors[(level + depth) % 3]);
14116         }
14117     }
14118     ASSERT_GL_NO_ERROR();
14119 
14120     // The texture has the following colors:
14121     //              Slice 0   Slice 1   Slice 2   Slice 3   Slice 4
14122     // Level  0      Red       Green     Blue      Red       Green
14123     // Level  1      Green     Blue
14124 
14125     // Copy level 1, slice 1 to level 1, slice 0
14126     glCopyImageSubDataEXT(tex, GL_TEXTURE_3D, 1, 0, 0, 1, tex, GL_TEXTURE_3D, 1, 0, 0, 0,
14127                           kWidth >> 1, kHeight >> 1, 1);
14128     ASSERT_GL_NO_ERROR();
14129 
14130     // Copy level 0, slice 3, 4 to level 0, slice 1, 2
14131     glCopyImageSubDataEXT(tex, GL_TEXTURE_3D, 0, 0, 0, 3, tex, GL_TEXTURE_3D, 0, 0, 0, 1, kWidth,
14132                           kHeight, 2);
14133     ASSERT_GL_NO_ERROR();
14134 
14135     // Partially copy level 1, slice 1 to level 0, slice 3
14136     glCopyImageSubDataEXT(tex, GL_TEXTURE_3D, 1, kWidth / 8, kHeight / 8, 1, tex, GL_TEXTURE_3D, 0,
14137                           kWidth / 4, kHeight / 4, 3, kWidth / 4, kHeight / 4, 1);
14138     ASSERT_GL_NO_ERROR();
14139 
14140     // Verify colors
14141     GLFramebuffer FBO;
14142     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
14143     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
14144     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14145 
14146     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
14147     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14148 
14149     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
14150     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14151 
14152     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 3);
14153     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight / 4, GLColor::red);
14154     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 4, kHeight, GLColor::red);
14155     EXPECT_PIXEL_RECT_EQ(0, kHeight / 4 + kHeight / 4, kWidth,
14156                          kHeight - (kHeight / 4 + kHeight / 4), GLColor::red);
14157     EXPECT_PIXEL_RECT_EQ(kWidth / 4 + kWidth / 4, 0, kWidth - (kWidth / 4 + kWidth / 4), kHeight,
14158                          GLColor::red);
14159     EXPECT_PIXEL_RECT_EQ(kWidth / 4, kHeight / 4, kWidth / 4, kHeight / 4, GLColor::blue);
14160 
14161     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 4);
14162     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14163 
14164     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 0);
14165     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14166 
14167     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 1);
14168     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14169     ASSERT_GL_NO_ERROR();
14170 }
14171 
14172 class TextureChangeStorageUploadTest : public ANGLETest<>
14173 {
14174   protected:
TextureChangeStorageUploadTest()14175     TextureChangeStorageUploadTest()
14176     {
14177         setWindowWidth(256);
14178         setWindowHeight(256);
14179         setConfigRedBits(8);
14180         setConfigGreenBits(8);
14181         setConfigBlueBits(8);
14182         setConfigAlphaBits(8);
14183     }
14184 
testSetUp()14185     void testSetUp() override
14186     {
14187         mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
14188         if (mProgram == 0)
14189         {
14190             FAIL() << "shader compilation failed.";
14191         }
14192 
14193         glUseProgram(mProgram);
14194 
14195         glClearColor(0, 0, 0, 0);
14196         glClearDepthf(0.0);
14197         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
14198 
14199         glEnable(GL_BLEND);
14200         glDisable(GL_DEPTH_TEST);
14201 
14202         glGenTextures(1, &mTexture);
14203         ASSERT_GL_NO_ERROR();
14204     }
14205 
testTearDown()14206     void testTearDown() override
14207     {
14208         glDeleteTextures(1, &mTexture);
14209         glDeleteProgram(mProgram);
14210     }
14211 
14212     GLuint mProgram;
14213     GLint mColorLocation;
14214     GLuint mTexture;
14215 };
14216 
14217 // Verify that respecifying storage and re-uploading doesn't crash.
TEST_P(TextureChangeStorageUploadTest,Basic)14218 TEST_P(TextureChangeStorageUploadTest, Basic)
14219 {
14220     constexpr int kImageSize        = 8;  // 4 doesn't trip ASAN
14221     constexpr int kSmallerImageSize = kImageSize / 2;
14222     EXPECT_GT(kImageSize, kSmallerImageSize);
14223     EXPECT_GT(kSmallerImageSize / 2, 0);
14224 
14225     std::array<GLColor, kImageSize * kImageSize> kColor;
14226 
14227     glBindTexture(GL_TEXTURE_2D, mTexture);
14228     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
14229                  kColor.data());
14230     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSmallerImageSize, kSmallerImageSize);
14231     // need partial update to sidestep optimizations that remove the full upload
14232     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSmallerImageSize / 2, kSmallerImageSize / 2, GL_RGBA,
14233                     GL_UNSIGNED_BYTE, kColor.data());
14234     EXPECT_GL_NO_ERROR();
14235 }
14236 
14237 class ExtraSamplerCubeShadowUseTest : public ANGLETest<>
14238 {
14239   protected:
ExtraSamplerCubeShadowUseTest()14240     ExtraSamplerCubeShadowUseTest() : ANGLETest() {}
14241 
getVertexShaderSource()14242     const char *getVertexShaderSource() { return "#version 300 es\nvoid main() {}"; }
14243 
getFragmentShaderSource()14244     const char *getFragmentShaderSource()
14245     {
14246         return R"(#version 300 es
14247 precision mediump float;
14248 
14249 uniform mediump samplerCube var_0002; // this has to be there
14250 uniform highp samplerCubeShadow var_0004; // this has to be a cube shadow sampler
14251 out vec4 color;
14252 void main() {
14253 
14254     vec4 var_0031 = texture(var_0002, vec3(1,1,1));
14255     ivec2 size = textureSize(var_0004, 0) ;
14256     var_0031.x += float(size.y);
14257 
14258     color = var_0031;
14259 })";
14260     }
14261 
testSetUp()14262     void testSetUp() override
14263     {
14264         mProgram = CompileProgram(getVertexShaderSource(), getFragmentShaderSource());
14265         if (mProgram == 0)
14266         {
14267             FAIL() << "shader compilation failed.";
14268         }
14269         glUseProgram(mProgram);
14270         ASSERT_GL_NO_ERROR();
14271     }
14272 
testTearDown()14273     void testTearDown() override { glDeleteProgram(mProgram); }
14274 
14275     GLuint mProgram;
14276 };
14277 
TEST_P(ExtraSamplerCubeShadowUseTest,Basic)14278 TEST_P(ExtraSamplerCubeShadowUseTest, Basic)
14279 {
14280     glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
14281     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
14282 }
14283 
14284 // Tests covering RBG->RGBA emulation path
14285 class RGBTextureBufferTestES31 : public ANGLETest<>
14286 {
14287   protected:
RGBTextureBufferTestES31()14288     RGBTextureBufferTestES31()
14289     {
14290         setWindowWidth(128);
14291         setWindowHeight(128);
14292         setConfigRedBits(8);
14293         setConfigGreenBits(8);
14294         setConfigBlueBits(8);
14295         setConfigAlphaBits(8);
14296     }
14297     void TestInt(GLuint format);
14298 };
14299 
SetupTextureBufferDrawProgram(GLProgram & program,GLuint format)14300 void SetupTextureBufferDrawProgram(GLProgram &program, GLuint format)
14301 {
14302     constexpr char kVS[] = R"(#version 310 es
14303     precision highp float;
14304     in vec4 inputAttribute;
14305 
14306     void main()
14307     {
14308         gl_Position = inputAttribute;
14309     })";
14310 
14311     if (format == GL_RGB32UI)
14312     {
14313         constexpr char kFS[] = R"(#version 310 es
14314         #extension GL_EXT_texture_buffer : require
14315         precision mediump float;
14316         uniform highp usamplerBuffer tex;
14317         layout(location = 0) out mediump vec4 color;
14318 
14319         void main()
14320         {
14321             uvec4 v = texelFetch(tex, 1);
14322             color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
14323         })";
14324         program.makeRaster(kVS, kFS);
14325     }
14326     if (format == GL_RGB32I)
14327     {
14328         constexpr char kFS[] = R"(#version 310 es
14329         #extension GL_EXT_texture_buffer : require
14330         precision mediump float;
14331         uniform highp isamplerBuffer tex;
14332         layout(location = 0) out mediump vec4 color;
14333 
14334         void main()
14335         {
14336             ivec4 v = texelFetch(tex, 1);
14337             color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
14338         })";
14339         program.makeRaster(kVS, kFS);
14340     }
14341     if (format == GL_RGB32F)
14342     {
14343         constexpr char kFS[] = R"(#version 310 es
14344         #extension GL_EXT_texture_buffer : require
14345         precision mediump float;
14346         uniform highp samplerBuffer tex;
14347         layout(location = 0) out mediump vec4 color;
14348 
14349         void main()
14350         {
14351             vec4 v = texelFetch(tex, 1);
14352             color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
14353         })";
14354         program.makeRaster(kVS, kFS);
14355     }
14356     ASSERT_TRUE(program.valid());
14357 }
14358 
TestInt(GLuint format)14359 void RGBTextureBufferTestES31::TestInt(GLuint format)
14360 {
14361     const GLint pixelSize = sizeof(GLuint) * 3;
14362 
14363     // Offset must be aligned to GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT (16, 64, ...)
14364     GLint offsetAlignment = 0;
14365     glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment);
14366     ASSERT(offsetAlignment % sizeof(GLuint) == 0);
14367     GLint byteOffset = ((pixelSize * 2) / offsetAlignment + 1) * offsetAlignment;
14368 
14369     GLint intOffset = byteOffset / sizeof(GLuint);
14370 
14371     std::vector<GLuint> texData(intOffset + 3 * 2);
14372 
14373     // first texel(1) col
14374     GLColor col = MakeGLColor(11, 22, 33, 255);
14375     texData[3]  = col.R;
14376     texData[4]  = col.G;
14377     texData[5]  = col.B;
14378 
14379     // second texel(1) col2
14380     GLColor col2           = MakeGLColor(44, 55, 66, 255);
14381     texData[intOffset + 3] = col2.R;
14382     texData[intOffset + 4] = col2.G;
14383     texData[intOffset + 5] = col2.B;
14384 
14385     GLTexture texture;
14386     glBindTexture(GL_TEXTURE_BUFFER, texture);
14387 
14388     GLBuffer buffer;
14389     glBindBuffer(GL_TEXTURE_BUFFER, buffer);
14390     glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * texData.size(), texData.data(),
14391                  GL_STATIC_DRAW);
14392     ASSERT_GL_NO_ERROR();
14393 
14394     GLProgram program;
14395     SetupTextureBufferDrawProgram(program, format);
14396 
14397     glTexBufferEXT(GL_TEXTURE_BUFFER, format, buffer);
14398 
14399     drawQuad(program, "inputAttribute", 0.5f);
14400     ASSERT_GL_NO_ERROR();
14401     EXPECT_PIXEL_COLOR_NEAR(0, 0, col, 1);
14402 
14403     glTexBufferRangeEXT(GL_TEXTURE_BUFFER, format, buffer, byteOffset, pixelSize * 2);
14404     ASSERT_GL_NO_ERROR();
14405     drawQuad(program, "inputAttribute", 0.5f);
14406     EXPECT_PIXEL_COLOR_NEAR(0, 0, col2, 1);
14407 
14408     // Now update the buffer to check the converted data also gets updated.
14409     GLColor colUpd      = MakeGLColor(77, 88, 99, 255);
14410     GLuint texDataUpd[] = {0, 0, 0, colUpd.R, colUpd.G, colUpd.B};  // second texel(1) colUpd
14411     glBufferSubData(GL_TEXTURE_BUFFER, byteOffset, sizeof(texDataUpd), texDataUpd);
14412     ASSERT_GL_NO_ERROR();
14413     drawQuad(program, "inputAttribute", 0.5f);
14414     EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd, 1);
14415 
14416     // Update with glMapBuffer (hits a different code path...)
14417     GLColor colUpd2      = MakeGLColor(111, 122, 133, 255);
14418     GLuint texDataUpd2[] = {0, 0, 0, colUpd2.R, colUpd2.G, colUpd2.B};  // second texel(1) colUpd2
14419     void *mappedBuffer =
14420         glMapBufferRange(GL_TEXTURE_BUFFER, byteOffset, sizeof(texDataUpd2), GL_MAP_WRITE_BIT);
14421     memcpy(mappedBuffer, texDataUpd2, sizeof(texDataUpd2));
14422     glUnmapBuffer(GL_TEXTURE_BUFFER);
14423     ASSERT_GL_NO_ERROR();
14424     drawQuad(program, "inputAttribute", 0.5f);
14425     EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd2, 1);
14426 }
14427 
14428 // Tests GL_RGB32UI texture buffer
TEST_P(RGBTextureBufferTestES31,Uint)14429 TEST_P(RGBTextureBufferTestES31, Uint)
14430 {
14431     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
14432 
14433     TestInt(GL_RGB32UI);
14434 }
14435 
14436 // Tests GL_RGB32I texture buffer
TEST_P(RGBTextureBufferTestES31,Sint)14437 TEST_P(RGBTextureBufferTestES31, Sint)
14438 {
14439     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
14440 
14441     TestInt(GL_RGB32I);
14442 }
14443 
14444 // Tests GL_RGB32F texture buffer
TEST_P(RGBTextureBufferTestES31,Float)14445 TEST_P(RGBTextureBufferTestES31, Float)
14446 {
14447     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
14448 
14449     // first texel(1) col
14450     GLColor col = MakeGLColor(11, 22, 33, 255);
14451     GLfloat texData[6]{};
14452     texData[3] = col.R;
14453     texData[4] = col.G;
14454     texData[5] = col.B;
14455 
14456     GLTexture texture;
14457     glBindTexture(GL_TEXTURE_BUFFER, texture);
14458 
14459     GLBuffer buffer;
14460     glBindBuffer(GL_TEXTURE_BUFFER, buffer);
14461     glBufferData(GL_TEXTURE_BUFFER, sizeof(texData), texData, GL_STATIC_DRAW);
14462     ASSERT_GL_NO_ERROR();
14463 
14464     GLProgram program;
14465     SetupTextureBufferDrawProgram(program, GL_RGB32F);
14466 
14467     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGB32F, buffer);
14468 
14469     drawQuad(program, "inputAttribute", 0.5f);
14470     ASSERT_GL_NO_ERROR();
14471     EXPECT_PIXEL_COLOR_NEAR(0, 0, col, 1);
14472 
14473     // Now update the buffer to check the converted data also gets updated.
14474     GLColor colUpd = MakeGLColor(77, 88, 99, 255);
14475     GLfloat texDataUpd[6]{};
14476     texDataUpd[3] = colUpd.R;
14477     texDataUpd[4] = colUpd.G;
14478     texDataUpd[5] = colUpd.B;
14479     glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(texDataUpd), texDataUpd);
14480     ASSERT_GL_NO_ERROR();
14481     drawQuad(program, "inputAttribute", 0.5f);
14482     EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd, 1);
14483 
14484     // Update with glMapBuffer (hits a different code path...)
14485     GLColor colUpd2 = MakeGLColor(111, 122, 133, 255);
14486     GLfloat texDataUpd2[6]{};
14487     texDataUpd2[3] = colUpd2.R;
14488     texDataUpd2[4] = colUpd2.G;
14489     texDataUpd2[5] = colUpd2.B;
14490     void *mappedBuffer =
14491         glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(texDataUpd2), GL_MAP_WRITE_BIT);
14492     memcpy(mappedBuffer, texDataUpd2, sizeof(texDataUpd2));
14493     glUnmapBuffer(GL_TEXTURE_BUFFER);
14494     ASSERT_GL_NO_ERROR();
14495     drawQuad(program, "inputAttribute", 0.5f);
14496     EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd2, 1);
14497 }
14498 
SetupSSBOProgram(GLProgram & program)14499 void SetupSSBOProgram(GLProgram &program)
14500 {
14501     constexpr char kVS[] = R"(#version 310 es
14502     precision highp float;
14503     in vec4 inputAttribute;
14504 
14505     void main()
14506     {
14507         gl_Position = inputAttribute;
14508     })";
14509 
14510     constexpr char kFS[] = R"(#version 310 es
14511     layout(location = 0) out mediump vec4 color;
14512     layout(std140, binding = 0) buffer outBlock {
14513         uvec4 data[2];  // uvec4 to avoid padding
14514     };
14515     void main (void)
14516     {
14517         data[0] = uvec4(11u, 22u, 33u, 44u);
14518         data[1] = uvec4(55u, 66u, 0u, 0u);
14519         color = vec4(0);
14520     })";
14521 
14522     program.makeRaster(kVS, kFS);
14523     ASSERT_TRUE(program.valid());
14524 }
14525 
14526 // Tests RGB32 texture buffer with a SSBO write
TEST_P(RGBTextureBufferTestES31,SSBOWrite)14527 TEST_P(RGBTextureBufferTestES31, SSBOWrite)
14528 {
14529     GLProgram programSSBO;
14530     SetupSSBOProgram(programSSBO);
14531 
14532     GLProgram programBufferDraw;
14533     SetupTextureBufferDrawProgram(programBufferDraw, GL_RGB32UI);
14534 
14535     constexpr GLint kBufferSize = 2 * 4 * sizeof(GLuint);
14536     GLBuffer buffer;
14537     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
14538     glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
14539     glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize);
14540 
14541     drawQuad(programSSBO, "inputAttribute", 0.5f);
14542     ASSERT_GL_NO_ERROR();
14543 
14544     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
14545 
14546     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGB32UI, buffer);
14547     drawQuad(programBufferDraw, "inputAttribute", 0.5f);
14548     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(44, 55, 66, 255), 1);
14549 }
14550 
14551 class TextureTestES31 : public ANGLETest<>
14552 {
14553   protected:
TextureTestES31()14554     TextureTestES31()
14555     {
14556         setWindowWidth(128);
14557         setWindowHeight(128);
14558         setConfigRedBits(8);
14559         setConfigGreenBits(8);
14560         setConfigBlueBits(8);
14561         setConfigAlphaBits(8);
14562     }
14563 };
14564 
14565 // Verify that image uniforms can link in separable programs
TEST_P(TextureTestES31,LinkedImageUniforms)14566 TEST_P(TextureTestES31, LinkedImageUniforms)
14567 {
14568     ANGLE_SKIP_TEST_IF(!IsVulkan());
14569 
14570     GLint maxVertexImageUniforms;
14571     glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
14572     ANGLE_SKIP_TEST_IF(maxVertexImageUniforms == 0);
14573 
14574     constexpr char kVS[] = R"(#version 310 es
14575 precision highp float;
14576 precision highp image2D;
14577 layout(binding = 0, r32f) uniform image2D img;
14578 
14579 void main()
14580 {
14581     vec2 position = -imageLoad(img, ivec2(0, 0)).rr;
14582     if (gl_VertexID == 1)
14583         position = vec2(3, -1);
14584     else if (gl_VertexID == 2)
14585         position = vec2(-1, 3);
14586 
14587     gl_Position = vec4(position, 0, 1);
14588 })";
14589 
14590     constexpr char kFS[] = R"(#version 310 es
14591 precision highp float;
14592 precision highp image2D;
14593 layout(binding = 0, r32f) uniform image2D img;
14594 layout(location = 0) out vec4 color;
14595 
14596 void main()
14597 {
14598     color = imageLoad(img, ivec2(0, 0));
14599 })";
14600 
14601     ANGLE_GL_PROGRAM(program, kVS, kFS);
14602 
14603     GLTexture texture;
14604     GLfloat value = 1.0;
14605 
14606     glBindTexture(GL_TEXTURE_2D, texture);
14607     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
14608     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &value);
14609     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14610     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14611 
14612     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
14613 
14614     glUseProgram(program);
14615     glDrawArrays(GL_TRIANGLES, 0, 3);
14616 
14617     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
14618     ASSERT_GL_NO_ERROR();
14619 }
14620 
14621 // Test that layer-related parameters are ignored when binding a 2D texture
TEST_P(TextureTestES31,Texture2DLayered)14622 TEST_P(TextureTestES31, Texture2DLayered)
14623 {
14624     constexpr char kFS[] = R"(#version 310 es
14625 precision highp float;
14626 precision highp image2D;
14627 layout(binding = 0, r32f) uniform image2D img;
14628 layout(location = 0) out vec4 color;
14629 
14630 void main()
14631 {
14632     color = imageLoad(img, ivec2(0, 0));
14633 })";
14634 
14635     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
14636 
14637     GLTexture texture;
14638     GLfloat value = 1.0;
14639 
14640     glBindTexture(GL_TEXTURE_2D, texture);
14641     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
14642     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &value);
14643     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14644     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14645 
14646     glClearColor(0.0, 1.0, 0.0, 1.0);
14647     for (const bool layered : {true, false})
14648     {
14649         for (const GLint layer : {0, 1})
14650         {
14651             glClear(GL_COLOR_BUFFER_BIT);
14652             glBindImageTexture(0, texture, 0, layered, layer, GL_READ_ONLY, GL_R32F);
14653             ASSERT_GL_NO_ERROR();
14654 
14655             drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14656             EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red)
14657                 << "Layered: " << (layered ? "true" : "false") << ", Layer: " << layer;
14658         }
14659     }
14660 }
14661 
14662 // Test that rebinding the shader image level without changing the program works
TEST_P(TextureTestES31,Texture2DChangeLevel)14663 TEST_P(TextureTestES31, Texture2DChangeLevel)
14664 {
14665     constexpr char kFS[] = R"(#version 310 es
14666 precision highp float;
14667 precision highp image2D;
14668 layout(binding = 0, r32f) uniform image2D img;
14669 layout(location = 0) out vec4 color;
14670 
14671 void main()
14672 {
14673     color = imageLoad(img, ivec2(0, 0));
14674 })";
14675     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
14676 
14677     // Must be active before calling drawQuad to avoid program switches
14678     glUseProgram(program);
14679 
14680     GLTexture texture;
14681     const GLfloat level0[4] = {0.5, 0.5, 0.5, 0.5};
14682     const GLfloat level1[1] = {1.0};
14683 
14684     glBindTexture(GL_TEXTURE_2D, texture);
14685     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32F, 2, 2);
14686     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RED, GL_FLOAT, level0);
14687     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 1, 1, GL_RED, GL_FLOAT, level1);
14688     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14689     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14690 
14691     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14692     ASSERT_GL_NO_ERROR();
14693     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14694     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
14695 
14696     glBindImageTexture(0, texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14697     ASSERT_GL_NO_ERROR();
14698     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14699     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
14700 }
14701 
14702 // Test that rebinding the shader image layer/level without changing the program works
TEST_P(TextureTestES31,Texture2DArrayChangeLayerLevel)14703 TEST_P(TextureTestES31, Texture2DArrayChangeLayerLevel)
14704 {
14705     constexpr char kFS[] = R"(#version 310 es
14706 precision highp float;
14707 precision highp image2D;
14708 layout(binding = 0, r32f) uniform image2D img;
14709 layout(location = 0) out vec4 color;
14710 
14711 void main()
14712 {
14713     color = imageLoad(img, ivec2(0, 0));
14714 })";
14715     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
14716 
14717     // Must be active before calling drawQuad to avoid program switches
14718     glUseProgram(program);
14719 
14720     GLTexture texture;
14721     const GLfloat level0layer0[4] = {0.25, 0.25, 0.25, 0.25};
14722     const GLfloat level0layer1[4] = {0.50, 0.50, 0.50, 0.50};
14723     const GLfloat level1layer0[1] = {0.75};
14724     const GLfloat level1layer1[1] = {1.00};
14725 
14726     glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
14727     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 2, 2, 2);
14728     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 2, 2, 1, GL_RED, GL_FLOAT, level0layer0);
14729     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 2, 2, 1, GL_RED, GL_FLOAT, level0layer1);
14730     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, 1, 1, 1, GL_RED, GL_FLOAT, level1layer0);
14731     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 1, 1, 1, 1, GL_RED, GL_FLOAT, level1layer1);
14732     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14733     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14734 
14735     // Level 0, layer 0
14736     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14737     ASSERT_GL_NO_ERROR();
14738     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14739     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 0, 0, 255), 1);
14740 
14741     // Level 0, layer 1
14742     glBindImageTexture(0, texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
14743     ASSERT_GL_NO_ERROR();
14744     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14745     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
14746 
14747     // Level 1, layer 0
14748     glBindImageTexture(0, texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14749     ASSERT_GL_NO_ERROR();
14750     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14751     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(191, 0, 0, 255), 1);
14752 
14753     // Level 1, layer 1
14754     glBindImageTexture(0, texture, 1, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
14755     ASSERT_GL_NO_ERROR();
14756     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14757     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 0, 0, 255), 1);
14758 }
14759 
14760 // Test that switching between a 2D texture and a layer of a 2D array texture works
TEST_P(TextureTestES31,Texture2DTo2DArraySwitch)14761 TEST_P(TextureTestES31, Texture2DTo2DArraySwitch)
14762 {
14763     constexpr char kFS[] = R"(#version 310 es
14764 precision highp float;
14765 precision highp image2D;
14766 layout(binding = 0, r32f) uniform image2D img;
14767 layout(location = 0) out vec4 color;
14768 
14769 void main()
14770 {
14771     color = imageLoad(img, ivec2(0, 0));
14772 })";
14773     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
14774 
14775     // Must be active before calling drawQuad to avoid program switches
14776     glUseProgram(program);
14777 
14778     GLTexture texture2D;
14779     GLTexture texture2DArray;
14780     const GLfloat data2D[1]       = {0.50};
14781     const GLfloat data2DArray0[1] = {0.25};
14782     const GLfloat data2DArray1[1] = {0.75};
14783 
14784     glBindTexture(GL_TEXTURE_2D, texture2D);
14785     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
14786     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, data2D);
14787     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14788     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14789 
14790     glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
14791     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 1, 1, 2);
14792     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 1, 1, 1, GL_RED, GL_FLOAT, data2DArray0);
14793     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 1, 1, 1, GL_RED, GL_FLOAT, data2DArray1);
14794     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14795     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14796 
14797     // Texture2D
14798     glBindImageTexture(0, texture2D, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14799     ASSERT_GL_NO_ERROR();
14800     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14801     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
14802 
14803     // Texture2D array, layer 0
14804     glBindImageTexture(0, texture2DArray, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14805     ASSERT_GL_NO_ERROR();
14806     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14807     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 0, 0, 255), 1);
14808 
14809     // Texture2D again
14810     glBindImageTexture(0, texture2D, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14811     ASSERT_GL_NO_ERROR();
14812     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14813     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
14814 
14815     // Texture2D array, layer 1
14816     glBindImageTexture(0, texture2DArray, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
14817     ASSERT_GL_NO_ERROR();
14818     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14819     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(191, 0, 0, 255), 1);
14820 }
14821 
14822 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
14823 // tests should be run against.
14824 #define ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB()             \
14825     ES2_OPENGL().enable(Feature::EmulateCopyTexImage2D), \
14826         ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2D)
14827 #define ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB()             \
14828     ES3_OPENGL().enable(Feature::EmulateCopyTexImage2D), \
14829         ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2D)
14830 #define ES2_EMULATE_COPY_TEX_IMAGE()                                      \
14831     ES2_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers), \
14832         ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers)
14833 #define ES3_EMULATE_COPY_TEX_IMAGE()                                      \
14834     ES3_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers), \
14835         ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers)
14836 ANGLE_INSTANTIATE_TEST(Texture2DTest,
14837                        ANGLE_ALL_TEST_PLATFORMS_ES2,
14838                        ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
14839                        ES2_EMULATE_COPY_TEX_IMAGE(),
14840                        ES2_WEBGPU());
14841 ANGLE_INSTANTIATE_TEST_ES2(TextureCubeTest);
14842 ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale);
14843 ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest);
14844 ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayTest);
14845 ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayAsFunctionParameterTest);
14846 
14847 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3);
14848 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3,
14849                                ES3_VULKAN().enable(Feature::AllocateNonZeroMemory),
14850                                ES3_VULKAN().enable(Feature::ForceFallbackFormat));
14851 
14852 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DMemoryTestES3);
14853 ANGLE_INSTANTIATE_TEST_ES3(Texture2DMemoryTestES3);
14854 
14855 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3YUV);
14856 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3YUV,
14857                                ES3_VULKAN().enable(Feature::PreferLinearFilterForYUV),
14858                                ES3_VULKAN().enable(Feature::DisableProgramCaching));
14859 
14860 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3RobustInit);
14861 ANGLE_INSTANTIATE_TEST_ES3(Texture2DTestES3RobustInit);
14862 
14863 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3Foveation);
14864 ANGLE_INSTANTIATE_TEST_ES3(Texture2DTestES3Foveation);
14865 
14866 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES31Foveation);
14867 ANGLE_INSTANTIATE_TEST_ES31(Texture2DTestES31Foveation);
14868 
14869 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES31PPO);
14870 ANGLE_INSTANTIATE_TEST_ES31(Texture2DTestES31PPO);
14871 
14872 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DBaseMaxTestES3);
14873 ANGLE_INSTANTIATE_TEST_ES3(Texture2DBaseMaxTestES3);
14874 
14875 ANGLE_INSTANTIATE_TEST_ES2(Texture3DTestES2);
14876 
14877 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DTestES3);
14878 ANGLE_INSTANTIATE_TEST_ES3(Texture3DTestES3);
14879 
14880 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerAlpha1TestES3);
14881 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerAlpha1TestES3);
14882 
14883 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DUnsignedIntegerAlpha1TestES3);
14884 ANGLE_INSTANTIATE_TEST_ES3(Texture2DUnsignedIntegerAlpha1TestES3);
14885 
14886 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShadowSamplerPlusSampler3DTestES3);
14887 ANGLE_INSTANTIATE_TEST_ES3(ShadowSamplerPlusSampler3DTestES3);
14888 
14889 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SamplerTypeMixTestES3);
14890 ANGLE_INSTANTIATE_TEST_ES3(SamplerTypeMixTestES3);
14891 
14892 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayTestES3);
14893 ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayTestES3);
14894 
14895 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSizeTextureArrayTest);
14896 ANGLE_INSTANTIATE_TEST_ES3(TextureSizeTextureArrayTest);
14897 
14898 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructTest);
14899 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAsFunctionParameterTest);
14900 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructArrayAsFunctionParameterTest);
14901 ANGLE_INSTANTIATE_TEST_ES2(SamplerInNestedStructAsFunctionParameterTest);
14902 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAndOtherVariableTest);
14903 ANGLE_INSTANTIATE_TEST_ES2(TextureAnisotropyTest);
14904 ANGLE_INSTANTIATE_TEST_ES2(TextureBorderClampTest);
14905 
14906 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampTestES3);
14907 ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampTestES3);
14908 
14909 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampIntegerTestES3);
14910 ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampIntegerTestES3);
14911 
14912 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(TextureMirrorClampToEdgeTest);
14913 
14914 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMirrorClampToEdgeTestES3);
14915 ANGLE_INSTANTIATE_TEST_ES3(TextureMirrorClampToEdgeTestES3);
14916 
14917 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMirrorClampToEdgeIntegerTestES3);
14918 ANGLE_INSTANTIATE_TEST_ES3(TextureMirrorClampToEdgeIntegerTestES3);
14919 
14920 ANGLE_INSTANTIATE_TEST_ES2(TextureLimitsTest);
14921 
14922 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DNorm16TestES3);
14923 ANGLE_INSTANTIATE_TEST_ES3(Texture2DNorm16TestES3);
14924 
14925 ANGLE_INSTANTIATE_TEST(Texture2DRGTest,
14926                        ANGLE_ALL_TEST_PLATFORMS_ES2,
14927                        ANGLE_ALL_TEST_PLATFORMS_ES3,
14928                        ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
14929                        ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
14930                        ES2_EMULATE_COPY_TEX_IMAGE(),
14931                        ES3_EMULATE_COPY_TEX_IMAGE());
14932 
14933 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DFloatTestES3);
14934 ANGLE_INSTANTIATE_TEST_ES3(Texture2DFloatTestES3);
14935 
14936 ANGLE_INSTANTIATE_TEST_ES2(Texture2DFloatTestES2);
14937 
14938 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeTestES3);
14939 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeTestES3);
14940 
14941 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerTestES3);
14942 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerTestES3);
14943 
14944 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerTestES3);
14945 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerTestES3);
14946 
14947 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerEdgeTestES3);
14948 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerEdgeTestES3);
14949 
14950 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerProjectiveOffsetTestES3);
14951 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerProjectiveOffsetTestES3);
14952 
14953 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayIntegerTestES3);
14954 ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayIntegerTestES3);
14955 
14956 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DIntegerTestES3);
14957 ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3);
14958 
14959 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest);
14960 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest);
14961 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest);
14962 ANGLE_INSTANTIATE_TEST_ES3(PBOCompressedTexture3DTest);
14963 
14964 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBufferTestES31);
14965 ANGLE_INSTANTIATE_TEST_ES31(TextureBufferTestES31);
14966 
14967 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureTestES31);
14968 ANGLE_INSTANTIATE_TEST_ES31(TextureTestES31);
14969 
14970 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyImageTestES31);
14971 ANGLE_INSTANTIATE_TEST_ES31(CopyImageTestES31);
14972 
14973 ANGLE_INSTANTIATE_TEST_ES3(TextureChangeStorageUploadTest);
14974 
14975 ANGLE_INSTANTIATE_TEST_ES3(ExtraSamplerCubeShadowUseTest);
14976 
14977 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DDepthStencilTestES3);
14978 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DDepthStencilTestES3,
14979                                ES3_VULKAN().enable(Feature::ForceFallbackFormat));
14980 
14981 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RGBTextureBufferTestES31);
14982 ANGLE_INSTANTIATE_TEST_ES31(RGBTextureBufferTestES31);
14983 
14984 }  // anonymous namespace
14985