• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 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 // RobustResourceInitTest: Tests for GL_ANGLE_robust_resource_initialization.
7 
8 #include "test_utils/ANGLETest.h"
9 
10 #include "test_utils/gl_raii.h"
11 #include "util/EGLWindow.h"
12 
13 namespace angle
14 {
15 constexpr char kSimpleTextureVertexShader[] =
16     "#version 300 es\n"
17     "in vec4 position;\n"
18     "out vec2 texcoord;\n"
19     "void main()\n"
20     "{\n"
21     "    gl_Position = position;\n"
22     "    texcoord = vec2(position.xy * 0.5 - 0.5);\n"
23     "}";
24 
25 // TODO(jmadill): Would be useful in a shared place in a utils folder.
UncompressDXTBlock(int destX,int destY,int destWidth,const std::vector<uint8_t> & src,int srcOffset,GLenum format,std::vector<GLColor> * colorsOut)26 void UncompressDXTBlock(int destX,
27                         int destY,
28                         int destWidth,
29                         const std::vector<uint8_t> &src,
30                         int srcOffset,
31                         GLenum format,
32                         std::vector<GLColor> *colorsOut)
33 {
34     auto make565 = [src](int offset) {
35         return static_cast<int>(src[offset + 0]) + static_cast<int>(src[offset + 1]) * 256;
36     };
37     auto make8888From565 = [](int c) {
38         return GLColor(
39             static_cast<GLubyte>(floor(static_cast<float>((c >> 11) & 0x1F) * (255.0f / 31.0f))),
40             static_cast<GLubyte>(floor(static_cast<float>((c >> 5) & 0x3F) * (255.0f / 63.0f))),
41             static_cast<GLubyte>(floor(static_cast<float>((c >> 0) & 0x1F) * (255.0f / 31.0f))),
42             255);
43     };
44     auto mix = [](int mult, GLColor c0, GLColor c1, float div) {
45         GLColor r = GLColor::transparentBlack;
46         for (int ii = 0; ii < 4; ++ii)
47         {
48             r[ii] = static_cast<GLubyte>(floor(static_cast<float>(c0[ii] * mult + c1[ii]) / div));
49         }
50         return r;
51     };
52     bool isDXT1 =
53         (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) || (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
54     int colorOffset               = srcOffset + (isDXT1 ? 0 : 8);
55     int color0                    = make565(colorOffset + 0);
56     int color1                    = make565(colorOffset + 2);
57     bool c0gtc1                   = color0 > color1 || !isDXT1;
58     GLColor rgba0                 = make8888From565(color0);
59     GLColor rgba1                 = make8888From565(color1);
60     std::array<GLColor, 4> colors = {{rgba0, rgba1,
61                                       c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
62                                       c0gtc1 ? mix(2, rgba1, rgba0, 3) : GLColor::black}};
63 
64     // Original comment preserved below for posterity:
65     // "yea I know there is a lot of math in this inner loop. so sue me."
66     for (int yy = 0; yy < 4; ++yy)
67     {
68         uint8_t pixels = src[colorOffset + 4 + yy];
69         for (int xx = 0; xx < 4; ++xx)
70         {
71             uint8_t code     = (pixels >> (xx * 2)) & 0x3;
72             GLColor srcColor = colors[code];
73             uint8_t alpha    = 0;
74             switch (format)
75             {
76                 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
77                     alpha = 255;
78                     break;
79                 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
80                     alpha = (code == 3 && !c0gtc1) ? 0 : 255;
81                     break;
82                 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
83                 {
84                     uint8_t alpha0 = src[srcOffset + yy * 2 + (xx >> 1)];
85                     uint8_t alpha1 = (alpha0 >> ((xx % 2) * 4)) & 0xF;
86                     alpha          = alpha1 | (alpha1 << 4);
87                 }
88                 break;
89                 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
90                 {
91                     uint8_t alpha0 = src[srcOffset + 0];
92                     uint8_t alpha1 = src[srcOffset + 1];
93                     int alphaOff   = (yy >> 1) * 3 + 2;
94                     uint32_t alphaBits =
95                         static_cast<uint32_t>(src[srcOffset + alphaOff + 0]) +
96                         static_cast<uint32_t>(src[srcOffset + alphaOff + 1]) * 256 +
97                         static_cast<uint32_t>(src[srcOffset + alphaOff + 2]) * 65536;
98                     int alphaShift    = (yy % 2) * 12 + xx * 3;
99                     uint8_t alphaCode = static_cast<uint8_t>((alphaBits >> alphaShift) & 0x7);
100                     if (alpha0 > alpha1)
101                     {
102                         switch (alphaCode)
103                         {
104                             case 0:
105                                 alpha = alpha0;
106                                 break;
107                             case 1:
108                                 alpha = alpha1;
109                                 break;
110                             default:
111                                 // TODO(jmadill): fix rounding
112                                 alpha = ((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7;
113                                 break;
114                         }
115                     }
116                     else
117                     {
118                         switch (alphaCode)
119                         {
120                             case 0:
121                                 alpha = alpha0;
122                                 break;
123                             case 1:
124                                 alpha = alpha1;
125                                 break;
126                             case 6:
127                                 alpha = 0;
128                                 break;
129                             case 7:
130                                 alpha = 255;
131                                 break;
132                             default:
133                                 // TODO(jmadill): fix rounding
134                                 alpha = ((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5;
135                                 break;
136                         }
137                     }
138                 }
139                 break;
140                 default:
141                     ASSERT_FALSE(true);
142                     break;
143             }
144             int dstOff           = ((destY + yy) * destWidth + destX + xx);
145             (*colorsOut)[dstOff] = GLColor(srcColor[0], srcColor[1], srcColor[2], alpha);
146         }
147     }
148 }
149 
GetBlockSize(GLenum format)150 int GetBlockSize(GLenum format)
151 {
152     bool isDXT1 =
153         format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
154     return isDXT1 ? 8 : 16;
155 }
156 
UncompressDXTIntoSubRegion(int width,int height,int subX0,int subY0,int subWidth,int subHeight,const std::vector<uint8_t> & data,GLenum format)157 std::vector<GLColor> UncompressDXTIntoSubRegion(int width,
158                                                 int height,
159                                                 int subX0,
160                                                 int subY0,
161                                                 int subWidth,
162                                                 int subHeight,
163                                                 const std::vector<uint8_t> &data,
164                                                 GLenum format)
165 {
166     std::vector<GLColor> dest(width * height, GLColor::transparentBlack);
167 
168     if ((width % 4) != 0 || (height % 4) != 0 || (subX0 % 4) != 0 || (subY0 % 4) != 0 ||
169         (subWidth % 4) != 0 || (subHeight % 4) != 0)
170     {
171         std::cout << "Implementation error in UncompressDXTIntoSubRegion.";
172         return dest;
173     }
174 
175     int blocksAcross = subWidth / 4;
176     int blocksDown   = subHeight / 4;
177     int blockSize    = GetBlockSize(format);
178     for (int yy = 0; yy < blocksDown; ++yy)
179     {
180         for (int xx = 0; xx < blocksAcross; ++xx)
181         {
182             UncompressDXTBlock(subX0 + xx * 4, subY0 + yy * 4, width, data,
183                                (yy * blocksAcross + xx) * blockSize, format, &dest);
184         }
185     }
186     return dest;
187 }
188 
189 class RobustResourceInitTest : public ANGLETest
190 {
191   protected:
192     constexpr static int kWidth  = 128;
193     constexpr static int kHeight = 128;
194 
RobustResourceInitTest()195     RobustResourceInitTest()
196     {
197         setWindowWidth(kWidth);
198         setWindowHeight(kHeight);
199         setConfigRedBits(8);
200         setConfigGreenBits(8);
201         setConfigBlueBits(8);
202         setConfigAlphaBits(8);
203         setConfigDepthBits(24);
204         setConfigStencilBits(8);
205 
206         setRobustResourceInit(true);
207 
208         // Test flakiness was noticed when reusing displays.
209         forceNewDisplay();
210     }
211 
hasGLExtension()212     bool hasGLExtension()
213     {
214         return IsGLExtensionEnabled("GL_ANGLE_robust_resource_initialization");
215     }
216 
hasEGLExtension()217     bool hasEGLExtension()
218     {
219         return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
220                                             "EGL_ANGLE_robust_resource_initialization");
221     }
222 
hasRobustSurfaceInit()223     bool hasRobustSurfaceInit()
224     {
225         if (!hasEGLExtension())
226         {
227             return false;
228         }
229 
230         EGLint robustSurfaceInit = EGL_FALSE;
231         eglQuerySurface(getEGLWindow()->getDisplay(), getEGLWindow()->getSurface(),
232                         EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &robustSurfaceInit);
233         return robustSurfaceInit;
234     }
235 
236     void setupTexture(GLTexture *tex);
237     void setup3DTexture(GLTexture *tex);
238 
239     // Checks for uninitialized (non-zero pixels) in a Texture.
240     void checkNonZeroPixels(GLTexture *texture,
241                             int skipX,
242                             int skipY,
243                             int skipWidth,
244                             int skipHeight,
245                             const GLColor &skip);
246     void checkNonZeroPixels3D(GLTexture *texture,
247                               int skipX,
248                               int skipY,
249                               int skipWidth,
250                               int skipHeight,
251                               int textureLayer,
252                               const GLColor &skip);
253     void checkFramebufferNonZeroPixels(int skipX,
254                                        int skipY,
255                                        int skipWidth,
256                                        int skipHeight,
257                                        const GLColor &skip);
258 
259     void checkCustomFramebufferNonZeroPixels(int fboWidth,
260                                              int fboHeight,
261                                              int skipX,
262                                              int skipY,
263                                              int skipWidth,
264                                              int skipHeight,
265                                              const GLColor &skip);
266 
GetSimpleTextureFragmentShader(const char * samplerType)267     static std::string GetSimpleTextureFragmentShader(const char *samplerType)
268     {
269         std::stringstream fragmentStream;
270         fragmentStream << "#version 300 es\n"
271                           "precision mediump "
272                        << samplerType
273                        << "sampler2D;\n"
274                           "precision mediump float;\n"
275                           "out "
276                        << samplerType
277                        << "vec4 color;\n"
278                           "in vec2 texcoord;\n"
279                           "uniform "
280                        << samplerType
281                        << "sampler2D tex;\n"
282                           "void main()\n"
283                           "{\n"
284                           "    color = texture(tex, texcoord);\n"
285                           "}";
286         return fragmentStream.str();
287     }
288 
289     template <typename ClearFunc>
290     void maskedDepthClear(ClearFunc clearFunc);
291 
292     template <typename ClearFunc>
293     void maskedStencilClear(ClearFunc clearFunc);
294 
295     void copyTexSubImage2DCustomFBOTest(int offsetX, int offsetY);
296 };
297 
298 class RobustResourceInitTestES3 : public RobustResourceInitTest
299 {
300   protected:
301     template <typename PixelT>
302     void testIntegerTextureInit(const char *samplerType,
303                                 GLenum internalFormatRGBA,
304                                 GLenum internalFormatRGB,
305                                 GLenum type);
306 };
307 
308 class RobustResourceInitTestES31 : public RobustResourceInitTest
309 {};
310 
311 // Robust resource initialization is not based on hardware support or native extensions, check that
312 // it only works on the implemented renderers
TEST_P(RobustResourceInitTest,ExpectedRendererSupport)313 TEST_P(RobustResourceInitTest, ExpectedRendererSupport)
314 {
315     bool shouldHaveSupport =
316         IsD3D11() || IsD3D11_FL93() || IsD3D9() || IsOpenGL() || IsOpenGLES() || IsVulkan();
317     EXPECT_EQ(shouldHaveSupport, hasGLExtension());
318     EXPECT_EQ(shouldHaveSupport, hasEGLExtension());
319     EXPECT_EQ(shouldHaveSupport, hasRobustSurfaceInit());
320 }
321 
322 // Tests of the GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE query.
TEST_P(RobustResourceInitTest,Queries)323 TEST_P(RobustResourceInitTest, Queries)
324 {
325     // If context extension string exposed, check queries.
326     if (IsGLExtensionEnabled("GL_ANGLE_robust_resource_initialization"))
327     {
328         GLboolean enabled = 0;
329         glGetBooleanv(GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
330         EXPECT_GL_TRUE(enabled);
331 
332         EXPECT_GL_TRUE(glIsEnabled(GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE));
333         EXPECT_GL_NO_ERROR();
334     }
335     else
336     {
337         // Querying robust resource init should return INVALID_ENUM.
338         GLboolean enabled = 0;
339         glGetBooleanv(GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
340         EXPECT_GL_ERROR(GL_INVALID_ENUM);
341     }
342 }
343 
344 // Tests that buffers start zero-filled if the data pointer is null.
TEST_P(RobustResourceInitTest,BufferData)345 TEST_P(RobustResourceInitTest, BufferData)
346 {
347     ANGLE_SKIP_TEST_IF(!hasGLExtension());
348 
349     GLBuffer buffer;
350     glBindBuffer(GL_ARRAY_BUFFER, buffer);
351     glBufferData(GL_ARRAY_BUFFER, getWindowWidth() * getWindowHeight() * sizeof(GLfloat), nullptr,
352                  GL_STATIC_DRAW);
353 
354     constexpr char kVS[] =
355         "attribute vec2 position;\n"
356         "attribute float testValue;\n"
357         "varying vec4 colorOut;\n"
358         "void main() {\n"
359         "    gl_Position = vec4(position, 0, 1);\n"
360         "    colorOut = testValue == 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
361         "}";
362     constexpr char kFS[] =
363         "varying mediump vec4 colorOut;\n"
364         "void main() {\n"
365         "    gl_FragColor = colorOut;\n"
366         "}";
367 
368     ANGLE_GL_PROGRAM(program, kVS, kFS);
369 
370     GLint testValueLoc = glGetAttribLocation(program.get(), "testValue");
371     ASSERT_NE(-1, testValueLoc);
372 
373     glBindBuffer(GL_ARRAY_BUFFER, buffer);
374     glVertexAttribPointer(testValueLoc, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
375     glEnableVertexAttribArray(testValueLoc);
376     glBindBuffer(GL_ARRAY_BUFFER, 0);
377 
378     drawQuad(program.get(), "position", 0.5f);
379 
380     ASSERT_GL_NO_ERROR();
381 
382     std::vector<GLColor> expected(getWindowWidth() * getWindowHeight(), GLColor::green);
383     std::vector<GLColor> actual(getWindowWidth() * getWindowHeight());
384     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
385                  actual.data());
386     EXPECT_EQ(expected, actual);
387 }
388 
389 // Regression test for passing a zero size init buffer with the extension.
TEST_P(RobustResourceInitTest,BufferDataZeroSize)390 TEST_P(RobustResourceInitTest, BufferDataZeroSize)
391 {
392     ANGLE_SKIP_TEST_IF(!hasGLExtension());
393 
394     GLBuffer buffer;
395     glBindBuffer(GL_ARRAY_BUFFER, buffer);
396     glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_STATIC_DRAW);
397 }
398 
399 // The following test code translated from WebGL 1 test:
400 // https://www.khronos.org/registry/webgl/sdk/tests/conformance/misc/uninitialized-test.html
setupTexture(GLTexture * tex)401 void RobustResourceInitTest::setupTexture(GLTexture *tex)
402 {
403     GLuint tempTexture;
404     glGenTextures(1, &tempTexture);
405     glBindTexture(GL_TEXTURE_2D, tempTexture);
406     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
407 
408     // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits
409     // into tex then delete texture then re-create one with same characteristics (driver will likely
410     // reuse mem) with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15%
411     // of the time.
412 
413     std::array<uint8_t, kWidth * kHeight * 4> badData;
414     for (size_t i = 0; i < badData.size(); ++i)
415     {
416         badData[i] = static_cast<uint8_t>(i % 255);
417     }
418 
419     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
420                     badData.data());
421     glDeleteTextures(1, &tempTexture);
422 
423     // This will create the GLTexture.
424     glBindTexture(GL_TEXTURE_2D, *tex);
425 }
426 
setup3DTexture(GLTexture * tex)427 void RobustResourceInitTest::setup3DTexture(GLTexture *tex)
428 {
429     GLuint tempTexture;
430     glGenTextures(1, &tempTexture);
431     glBindTexture(GL_TEXTURE_3D, tempTexture);
432     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, kWidth, kHeight, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
433                  nullptr);
434 
435     // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits
436     // into tex then delete texture then re-create one with same characteristics (driver will likely
437     // reuse mem) with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15%
438     // of the time.
439 
440     std::array<uint8_t, kWidth * kHeight * 2 * 4> badData;
441     for (size_t i = 0; i < badData.size(); ++i)
442     {
443         badData[i] = static_cast<uint8_t>(i % 255);
444     }
445 
446     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, 2, GL_RGBA, GL_UNSIGNED_BYTE,
447                     badData.data());
448     glDeleteTextures(1, &tempTexture);
449 
450     // This will create the GLTexture.
451     glBindTexture(GL_TEXTURE_3D, *tex);
452 }
453 
checkNonZeroPixels(GLTexture * texture,int skipX,int skipY,int skipWidth,int skipHeight,const GLColor & skip)454 void RobustResourceInitTest::checkNonZeroPixels(GLTexture *texture,
455                                                 int skipX,
456                                                 int skipY,
457                                                 int skipWidth,
458                                                 int skipHeight,
459                                                 const GLColor &skip)
460 {
461     glBindTexture(GL_TEXTURE_2D, 0);
462     GLFramebuffer fb;
463     glBindFramebuffer(GL_FRAMEBUFFER, fb);
464     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->get(), 0);
465     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
466 
467     checkFramebufferNonZeroPixels(skipX, skipY, skipWidth, skipHeight, skip);
468 }
469 
checkNonZeroPixels3D(GLTexture * texture,int skipX,int skipY,int skipWidth,int skipHeight,int textureLayer,const GLColor & skip)470 void RobustResourceInitTest::checkNonZeroPixels3D(GLTexture *texture,
471                                                   int skipX,
472                                                   int skipY,
473                                                   int skipWidth,
474                                                   int skipHeight,
475                                                   int textureLayer,
476                                                   const GLColor &skip)
477 {
478     glBindTexture(GL_TEXTURE_3D, 0);
479     GLFramebuffer fb;
480     glBindFramebuffer(GL_FRAMEBUFFER, fb);
481     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture->get(), 0,
482                               textureLayer);
483     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
484 
485     checkFramebufferNonZeroPixels(skipX, skipY, skipWidth, skipHeight, skip);
486 }
487 
checkFramebufferNonZeroPixels(int skipX,int skipY,int skipWidth,int skipHeight,const GLColor & skip)488 void RobustResourceInitTest::checkFramebufferNonZeroPixels(int skipX,
489                                                            int skipY,
490                                                            int skipWidth,
491                                                            int skipHeight,
492                                                            const GLColor &skip)
493 {
494     checkCustomFramebufferNonZeroPixels(kWidth, kHeight, skipX, skipY, skipWidth, skipHeight, skip);
495 }
496 
checkCustomFramebufferNonZeroPixels(int fboWidth,int fboHeight,int skipX,int skipY,int skipWidth,int skipHeight,const GLColor & skip)497 void RobustResourceInitTest::checkCustomFramebufferNonZeroPixels(int fboWidth,
498                                                                  int fboHeight,
499                                                                  int skipX,
500                                                                  int skipY,
501                                                                  int skipWidth,
502                                                                  int skipHeight,
503                                                                  const GLColor &skip)
504 {
505     std::vector<GLColor> data(fboWidth * fboHeight);
506     glReadPixels(0, 0, fboWidth, fboHeight, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
507 
508     int k = 0;
509     for (int y = 0; y < fboHeight; ++y)
510     {
511         for (int x = 0; x < fboWidth; ++x)
512         {
513             int index = (y * fboWidth + x);
514             if (x >= skipX && x < skipX + skipWidth && y >= skipY && y < skipY + skipHeight)
515             {
516                 ASSERT_EQ(skip, data[index]) << " at pixel " << x << ", " << y;
517             }
518             else
519             {
520                 k += (data[index] != GLColor::transparentBlack) ? 1 : 0;
521             }
522         }
523     }
524 
525     EXPECT_EQ(0, k);
526 }
527 
528 // Reading an uninitialized texture (texImage2D) should succeed with all bytes set to 0.
TEST_P(RobustResourceInitTest,ReadingUninitializedTexture)529 TEST_P(RobustResourceInitTest, ReadingUninitializedTexture)
530 {
531     ANGLE_SKIP_TEST_IF(!hasGLExtension());
532 
533     GLTexture tex;
534     setupTexture(&tex);
535     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
536     checkNonZeroPixels(&tex, 0, 0, 0, 0, GLColor::transparentBlack);
537     EXPECT_GL_NO_ERROR();
538 }
539 
540 // Test that calling glTexImage2D multiple times with the same size and no data resets all texture
541 // data
TEST_P(RobustResourceInitTest,ReuploadingClearsTexture)542 TEST_P(RobustResourceInitTest, ReuploadingClearsTexture)
543 {
544     ANGLE_SKIP_TEST_IF(!hasGLExtension());
545 
546     // crbug.com/826576
547     ANGLE_SKIP_TEST_IF(IsOSX() && IsNVIDIA() && IsDesktopOpenGL());
548 
549     // Put some data into the texture
550     std::array<GLColor, kWidth * kHeight> data;
551     data.fill(GLColor::white);
552 
553     GLTexture tex;
554     glBindTexture(GL_TEXTURE_2D, tex);
555     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
556                  data.data());
557 
558     // Reset the texture
559     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
560     checkNonZeroPixels(&tex, 0, 0, 0, 0, GLColor::transparentBlack);
561     EXPECT_GL_NO_ERROR();
562 }
563 
564 // Cover the case where null pixel data is uploaded to a texture and then sub image is used to
565 // upload partial data
TEST_P(RobustResourceInitTest,TexImageThenSubImage)566 TEST_P(RobustResourceInitTest, TexImageThenSubImage)
567 {
568     ANGLE_SKIP_TEST_IF(!hasGLExtension());
569 
570     // http://anglebug.com/2407, but only fails on Nexus devices
571     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
572 
573     // Put some data into the texture
574     GLTexture tex;
575     glBindTexture(GL_TEXTURE_2D, tex);
576     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
577 
578     // Force the D3D texture to create a storage
579     checkNonZeroPixels(&tex, 0, 0, 0, 0, GLColor::transparentBlack);
580 
581     glBindTexture(GL_TEXTURE_2D, tex);
582     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
583 
584     std::array<GLColor, kWidth * kHeight> data;
585     data.fill(GLColor::white);
586 
587     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth / 2, kHeight / 2, GL_RGBA, GL_UNSIGNED_BYTE,
588                     data.data());
589     checkNonZeroPixels(&tex, 0, 0, kWidth / 2, kHeight / 2, GLColor::white);
590     EXPECT_GL_NO_ERROR();
591 }
592 
593 // Reading an uninitialized texture (texImage3D) should succeed with all bytes set to 0.
TEST_P(RobustResourceInitTestES3,ReadingUninitialized3DTexture)594 TEST_P(RobustResourceInitTestES3, ReadingUninitialized3DTexture)
595 {
596     ANGLE_SKIP_TEST_IF(!hasGLExtension());
597 
598     GLTexture tex;
599     setup3DTexture(&tex);
600     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, kWidth, kHeight, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
601                  nullptr);
602     checkNonZeroPixels3D(&tex, 0, 0, 0, 0, 0, GLColor::transparentBlack);
603     EXPECT_GL_NO_ERROR();
604 }
605 
606 // Copy of the copytexsubimage3d_texture_wrongly_initialized test that is part of the WebGL2
607 // conformance suite: copy-texture-image-webgl-specific.html
TEST_P(RobustResourceInitTestES3,CopyTexSubImage3DTextureWronglyInitialized)608 TEST_P(RobustResourceInitTestES3, CopyTexSubImage3DTextureWronglyInitialized)
609 {
610     ANGLE_SKIP_TEST_IF(!hasGLExtension());
611 
612     constexpr GLint kTextureLayer     = 0;
613     constexpr GLint kTextureWidth     = 2;
614     constexpr GLint kTextureHeight    = 2;
615     constexpr GLint kTextureDepth     = 2;
616     constexpr size_t kTextureDataSize = kTextureWidth * kTextureHeight * 4;
617 
618     GLTexture texture2D;
619     glBindTexture(GL_TEXTURE_2D, texture2D);
620     constexpr std::array<uint8_t, kTextureDataSize> data = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
621                                                              0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
622                                                              0x0D, 0x0E, 0x0F, 0x10}};
623     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0, GL_RGBA,
624                  GL_UNSIGNED_BYTE, data.data());
625 
626     GLFramebuffer fbo;
627     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
628     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2D, 0);
629     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
630 
631     GLTexture texture3D;
632     glBindTexture(GL_TEXTURE_3D, texture3D);
633     glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA8, kTextureWidth, kTextureHeight, kTextureDepth);
634     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, kTextureLayer, 0, 0, kTextureWidth, kTextureHeight);
635 
636     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0, kTextureLayer);
637     std::array<uint8_t, kTextureDataSize> pixels;
638     glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
639     ASSERT_GL_NO_ERROR();
640     EXPECT_EQ(data, pixels);
641 }
642 
643 // Test that binding an EGL surface to a texture does not cause it to be cleared.
TEST_P(RobustResourceInitTestES3,BindTexImage)644 TEST_P(RobustResourceInitTestES3, BindTexImage)
645 {
646     ANGLE_SKIP_TEST_IF(!hasGLExtension());
647 
648     EGLWindow *window  = getEGLWindow();
649     EGLSurface surface = window->getSurface();
650     EGLDisplay display = window->getDisplay();
651     EGLConfig config   = window->getConfig();
652     EGLContext context = window->getContext();
653 
654     EGLint surfaceType = 0;
655     eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
656     // Test skipped because EGL config cannot be used to create pbuffers.
657     ANGLE_SKIP_TEST_IF((surfaceType & EGL_PBUFFER_BIT) == 0);
658 
659     EGLint bindToSurfaceRGBA = 0;
660     eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_RGBA, &bindToSurfaceRGBA);
661     // Test skipped because EGL config cannot be used to create pbuffers.
662     ANGLE_SKIP_TEST_IF(bindToSurfaceRGBA == EGL_FALSE);
663 
664     EGLint attribs[] = {
665         EGL_WIDTH,          32,
666         EGL_HEIGHT,         32,
667         EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
668         EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
669         EGL_NONE,
670     };
671 
672     EGLSurface pbuffer = eglCreatePbufferSurface(display, config, attribs);
673     ASSERT_NE(EGL_NO_SURFACE, pbuffer);
674 
675     // Clear the pbuffer
676     eglMakeCurrent(display, pbuffer, pbuffer, context);
677     GLColor clearColor = GLColor::magenta;
678     glClearColor(clearColor.R, clearColor.G, clearColor.B, clearColor.A);
679     glClear(GL_COLOR_BUFFER_BIT);
680     EXPECT_PIXEL_COLOR_EQ(0, 0, clearColor);
681 
682     // Bind the pbuffer to a texture and read its color
683     eglMakeCurrent(display, surface, surface, context);
684 
685     GLTexture texture;
686     glBindTexture(GL_TEXTURE_2D, texture);
687     eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
688 
689     GLFramebuffer fbo;
690     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
691     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
692     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
693     {
694         EXPECT_PIXEL_COLOR_EQ(0, 0, clearColor);
695     }
696     else
697     {
698         std::cout << "Read pixels check skipped because framebuffer was not complete." << std::endl;
699     }
700 
701     eglDestroySurface(display, pbuffer);
702 }
703 
704 // Tests that drawing with an uninitialized Texture works as expected.
TEST_P(RobustResourceInitTest,DrawWithTexture)705 TEST_P(RobustResourceInitTest, DrawWithTexture)
706 {
707     ANGLE_SKIP_TEST_IF(!hasGLExtension());
708 
709     GLTexture texture;
710     glBindTexture(GL_TEXTURE_2D, texture);
711     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
712     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
713     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
714 
715     constexpr char kVS[] =
716         "attribute vec2 position;\n"
717         "varying vec2 texCoord;\n"
718         "void main() {\n"
719         "    gl_Position = vec4(position, 0, 1);\n"
720         "    texCoord = (position * 0.5) + 0.5;\n"
721         "}";
722     constexpr char kFS[] =
723         "precision mediump float;\n"
724         "varying vec2 texCoord;\n"
725         "uniform sampler2D tex;\n"
726         "void main() {\n"
727         "    gl_FragColor = texture2D(tex, texCoord);\n"
728         "}";
729 
730     ANGLE_GL_PROGRAM(program, kVS, kFS);
731     drawQuad(program, "position", 0.5f);
732 
733     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
734 }
735 
736 // Tests that drawing with an uninitialized mipped texture works as expected.
TEST_P(RobustResourceInitTestES3,DrawWithMippedTexture)737 TEST_P(RobustResourceInitTestES3, DrawWithMippedTexture)
738 {
739     ANGLE_SKIP_TEST_IF(!hasGLExtension());
740 
741     GLTexture texture;
742     glBindTexture(GL_TEXTURE_2D, texture);
743     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
744     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kWidth / 2, kHeight / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
745                  nullptr);
746     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, kWidth / 4, kHeight / 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
747                  nullptr);
748     glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, kWidth / 8, kHeight / 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
749                  nullptr);
750     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
751     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
752     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
753     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
754 
755     EXPECT_GL_NO_ERROR();
756 
757     constexpr char kVS[] =
758         "attribute vec2 position;\n"
759         "varying vec2 texCoord;\n"
760         "void main() {\n"
761         "    gl_Position = vec4(position, 0, 1);\n"
762         "    texCoord = (position * 0.5) + 0.5;\n"
763         "}";
764     constexpr char kFS[] =
765         "precision mediump float;\n"
766         "varying vec2 texCoord;\n"
767         "uniform sampler2D tex;\n"
768         "void main() {\n"
769         "    gl_FragColor = texture2D(tex, texCoord);\n"
770         "}";
771 
772     ANGLE_GL_PROGRAM(program, kVS, kFS);
773     drawQuad(program, "position", 0.5f);
774 
775     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
776 }
777 
778 // Reading a partially initialized texture (texImage2D) should succeed with all uninitialized bytes
779 // set to 0 and initialized bytes untouched.
TEST_P(RobustResourceInitTest,ReadingPartiallyInitializedTexture)780 TEST_P(RobustResourceInitTest, ReadingPartiallyInitializedTexture)
781 {
782     ANGLE_SKIP_TEST_IF(!hasGLExtension());
783 
784     // http://anglebug.com/2407, but only fails on Nexus devices
785     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
786 
787     GLTexture tex;
788     setupTexture(&tex);
789     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
790     GLColor data(108, 72, 36, 9);
791     glTexSubImage2D(GL_TEXTURE_2D, 0, kWidth / 2, kHeight / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
792                     &data.R);
793     checkNonZeroPixels(&tex, kWidth / 2, kHeight / 2, 1, 1, data);
794     EXPECT_GL_NO_ERROR();
795 }
796 
797 // Uninitialized parts of textures initialized via copyTexImage2D should have all bytes set to 0.
TEST_P(RobustResourceInitTest,UninitializedPartsOfCopied2DTexturesAreBlack)798 TEST_P(RobustResourceInitTest, UninitializedPartsOfCopied2DTexturesAreBlack)
799 {
800     ANGLE_SKIP_TEST_IF(!hasGLExtension());
801 
802     GLTexture tex;
803     setupTexture(&tex);
804     GLFramebuffer fbo;
805     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
806     GLRenderbuffer rbo;
807     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
808     constexpr int fboWidth  = 16;
809     constexpr int fboHeight = 16;
810     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboWidth, fboHeight);
811     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
812     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
813     glClearColor(1.0, 0.0, 0.0, 1.0);
814     glClear(GL_COLOR_BUFFER_BIT);
815     EXPECT_GL_NO_ERROR();
816     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kWidth, kHeight, 0);
817     checkNonZeroPixels(&tex, 0, 0, fboWidth, fboHeight, GLColor::red);
818     EXPECT_GL_NO_ERROR();
819 }
820 
821 // Reading an uninitialized portion of a texture (copyTexImage2D with negative x and y) should
822 // succeed with all bytes set to 0. Regression test for a bug where the zeroing out of the
823 // texture was done via the same code path as glTexImage2D, causing the PIXEL_UNPACK_BUFFER
824 // to be used.
TEST_P(RobustResourceInitTestES3,ReadingOutOfBoundsCopiedTextureWithUnpackBuffer)825 TEST_P(RobustResourceInitTestES3, ReadingOutOfBoundsCopiedTextureWithUnpackBuffer)
826 {
827     ANGLE_SKIP_TEST_IF(!hasGLExtension());
828     // TODO(geofflang@chromium.org): CopyTexImage from GL_RGBA4444 to GL_ALPHA fails when looking
829     // up which resulting format the texture should have.
830     ANGLE_SKIP_TEST_IF(IsOpenGL());
831 
832     // GL_ALPHA texture can't be read with glReadPixels, for convenience this test uses
833     // glCopyTextureCHROMIUM to copy GL_ALPHA into GL_RGBA
834     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_copy_texture"));
835 
836     GLFramebuffer fbo;
837     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
838     GLRenderbuffer rbo;
839     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
840     constexpr int fboWidth  = 16;
841     constexpr int fboHeight = 16;
842     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboWidth, fboHeight);
843     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
844     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
845     glClearColor(1.0, 0.0, 0.0, 1.0);
846     glClear(GL_COLOR_BUFFER_BIT);
847     EXPECT_GL_NO_ERROR();
848     constexpr int x = -8;
849     constexpr int y = -8;
850 
851     GLBuffer buffer;
852     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
853     std::vector<GLColor> bunchOfGreen(fboWidth * fboHeight, GLColor::green);
854     glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(bunchOfGreen), bunchOfGreen.data(), GL_STATIC_DRAW);
855     EXPECT_GL_NO_ERROR();
856 
857     // Use non-multiple-of-4 dimensions to make sure unpack alignment is set in the backends
858     // (http://crbug.com/836131)
859     constexpr int kTextureWidth  = 127;
860     constexpr int kTextureHeight = 127;
861 
862     // Use GL_ALPHA to force a CPU readback in the D3D11 backend
863     GLTexture texAlpha;
864     glBindTexture(GL_TEXTURE_2D, texAlpha);
865     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, x, y, kTextureWidth, kTextureHeight, 0);
866     EXPECT_GL_NO_ERROR();
867 
868     // GL_ALPHA cannot be glReadPixels, so copy into a GL_RGBA texture
869     GLTexture texRGBA;
870     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
871     setupTexture(&texRGBA);
872     glCopyTextureCHROMIUM(texAlpha, 0, GL_TEXTURE_2D, texRGBA, 0, GL_RGBA, GL_UNSIGNED_BYTE,
873                           GL_FALSE, GL_FALSE, GL_FALSE);
874     EXPECT_GL_NO_ERROR();
875 
876     checkNonZeroPixels(&texRGBA, -x, -y, fboWidth, fboHeight, GLColor(0, 0, 0, 255));
877     EXPECT_GL_NO_ERROR();
878 }
879 
880 // Reading an uninitialized portion of a texture (copyTexImage2D with negative x and y) should
881 // succeed with all bytes set to 0.
TEST_P(RobustResourceInitTest,ReadingOutOfBoundsCopiedTexture)882 TEST_P(RobustResourceInitTest, ReadingOutOfBoundsCopiedTexture)
883 {
884     ANGLE_SKIP_TEST_IF(!hasGLExtension());
885 
886     GLTexture tex;
887     setupTexture(&tex);
888     GLFramebuffer fbo;
889     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
890     GLRenderbuffer rbo;
891     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
892     constexpr int fboWidth  = 16;
893     constexpr int fboHeight = 16;
894     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboWidth, fboHeight);
895     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
896     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
897     glClearColor(1.0, 0.0, 0.0, 1.0);
898     glClear(GL_COLOR_BUFFER_BIT);
899     EXPECT_GL_NO_ERROR();
900     constexpr int x = -8;
901     constexpr int y = -8;
902     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, kWidth, kHeight, 0);
903     checkNonZeroPixels(&tex, -x, -y, fboWidth, fboHeight, GLColor::red);
904     EXPECT_GL_NO_ERROR();
905 }
906 
907 // Tests resources are initialized properly with multisample resolve.
TEST_P(RobustResourceInitTestES3,MultisampledDepthInitializedCorrectly)908 TEST_P(RobustResourceInitTestES3, MultisampledDepthInitializedCorrectly)
909 {
910     ANGLE_SKIP_TEST_IF(!hasGLExtension());
911 
912     // http://anglebug.com/2407
913     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
914 
915     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
916 
917     // Make the destination non-multisampled depth FBO.
918     GLTexture color;
919     glBindTexture(GL_TEXTURE_2D, color);
920     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
921 
922     GLRenderbuffer depth;
923     glBindRenderbuffer(GL_RENDERBUFFER, depth);
924     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kWidth, kHeight);
925 
926     GLFramebuffer fbo;
927     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
928     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
929     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
930     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
931 
932     glClearColor(0, 1, 0, 1);
933     glClearDepthf(0);
934     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
935     ASSERT_GL_NO_ERROR();
936     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
937 
938     // Make the multisampled depth FBO.
939     GLRenderbuffer msDepth;
940     glBindRenderbuffer(GL_RENDERBUFFER, msDepth);
941     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, kWidth, kHeight);
942 
943     GLFramebuffer msFBO;
944     glBindFramebuffer(GL_READ_FRAMEBUFFER, msFBO);
945     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msDepth);
946     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
947 
948     // Multisample resolve.
949     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
950                       GL_NEAREST);
951     ASSERT_GL_NO_ERROR();
952 
953     // Test drawing with the resolved depth buffer.
954     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
955     glDepthMask(GL_FALSE);
956     glEnable(GL_DEPTH_TEST);
957     glDepthFunc(GL_EQUAL);
958     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
959     ASSERT_GL_NO_ERROR();
960     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
961 }
962 
963 // Basic test that textures are initialized correctly.
TEST_P(RobustResourceInitTest,Texture)964 TEST_P(RobustResourceInitTest, Texture)
965 {
966     ANGLE_SKIP_TEST_IF(!hasGLExtension());
967 
968     GLTexture texture;
969     glBindTexture(GL_TEXTURE_2D, texture);
970     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
971 
972     GLFramebuffer framebuffer;
973     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
974     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
975     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
976 }
977 
978 // Test that uploading texture data with an unpack state set correctly initializes the texture and
979 // the data is uploaded correctly.
TEST_P(RobustResourceInitTest,TextureWithUnpackState)980 TEST_P(RobustResourceInitTest, TextureWithUnpackState)
981 {
982     ANGLE_SKIP_TEST_IF(!hasGLExtension());
983 
984     // GL_UNPACK_ROW_LENGTH requires ES 3.0 or GL_EXT_unpack_subimage
985     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
986                        !EnsureGLExtensionEnabled("GL_EXT_unpack_subimage"));
987 
988     GLTexture texture;
989     glBindTexture(GL_TEXTURE_2D, texture);
990     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
991 
992     // Upload a 2x2 rect using GL_UNPACK_ROW_LENGTH=4
993     GLColor colorData[8] = {
994         GLColor::green, GLColor::green, GLColor::red, GLColor::red,
995         GLColor::green, GLColor::green, GLColor::red, GLColor::red,
996     };
997     glPixelStorei(GL_UNPACK_ROW_LENGTH, 4);
998     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorData);
999 
1000     GLFramebuffer framebuffer;
1001     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1002     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1003 
1004     checkFramebufferNonZeroPixels(0, 0, 2, 2, GLColor::green);
1005 }
1006 
1007 template <typename PixelT>
testIntegerTextureInit(const char * samplerType,GLenum internalFormatRGBA,GLenum internalFormatRGB,GLenum type)1008 void RobustResourceInitTestES3::testIntegerTextureInit(const char *samplerType,
1009                                                        GLenum internalFormatRGBA,
1010                                                        GLenum internalFormatRGB,
1011                                                        GLenum type)
1012 {
1013     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1014 
1015     std::string fs = GetSimpleTextureFragmentShader(samplerType);
1016 
1017     ANGLE_GL_PROGRAM(program, kSimpleTextureVertexShader, fs.c_str());
1018 
1019     // Make an RGBA framebuffer.
1020     GLTexture framebufferTexture;
1021     glBindTexture(GL_TEXTURE_2D, framebufferTexture);
1022     glTexImage2D(GL_TEXTURE_2D, 0, internalFormatRGBA, kWidth, kHeight, 0, GL_RGBA_INTEGER, type,
1023                  nullptr);
1024     ASSERT_GL_NO_ERROR();
1025 
1026     GLFramebuffer framebuffer;
1027     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1028     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferTexture,
1029                            0);
1030 
1031     // Make an RGB texture.
1032     GLTexture texture;
1033     glBindTexture(GL_TEXTURE_2D, texture);
1034     glTexImage2D(GL_TEXTURE_2D, 0, internalFormatRGB, kWidth, kHeight, 0, GL_RGB_INTEGER, type,
1035                  nullptr);
1036     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1037     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1038     ASSERT_GL_NO_ERROR();
1039 
1040     // Blit from the texture to the framebuffer.
1041     drawQuad(program, "position", 0.5f);
1042 
1043     std::array<PixelT, kWidth * kHeight * 4> data;
1044     glReadPixels(0, 0, kWidth, kHeight, GL_RGBA_INTEGER, type, data.data());
1045 
1046     // Check the color channels are zero and the alpha channel is 1.
1047     int incorrectPixels = 0;
1048     for (int y = 0; y < kHeight; ++y)
1049     {
1050         for (int x = 0; x < kWidth; ++x)
1051         {
1052             int index    = (y * kWidth + x) * 4;
1053             bool correct = (data[index] == 0 && data[index + 1] == 0 && data[index + 2] == 0 &&
1054                             data[index + 3] == 1);
1055             incorrectPixels += (!correct ? 1 : 0);
1056         }
1057     }
1058 
1059     ASSERT_GL_NO_ERROR();
1060     EXPECT_EQ(0, incorrectPixels);
1061 }
1062 
1063 // Simple tests for integer formats that ANGLE must emulate on D3D11.
TEST_P(RobustResourceInitTestES3,TextureInit_UIntRGB8)1064 TEST_P(RobustResourceInitTestES3, TextureInit_UIntRGB8)
1065 {
1066     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1067     testIntegerTextureInit<uint8_t>("u", GL_RGBA8UI, GL_RGB8UI, GL_UNSIGNED_BYTE);
1068 }
1069 
TEST_P(RobustResourceInitTestES3,TextureInit_UIntRGB32)1070 TEST_P(RobustResourceInitTestES3, TextureInit_UIntRGB32)
1071 {
1072     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1073     testIntegerTextureInit<uint32_t>("u", GL_RGBA32UI, GL_RGB32UI, GL_UNSIGNED_INT);
1074 }
1075 
TEST_P(RobustResourceInitTestES3,TextureInit_IntRGB8)1076 TEST_P(RobustResourceInitTestES3, TextureInit_IntRGB8)
1077 {
1078     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1079     testIntegerTextureInit<int8_t>("i", GL_RGBA8I, GL_RGB8I, GL_BYTE);
1080 }
1081 
TEST_P(RobustResourceInitTestES3,TextureInit_IntRGB32)1082 TEST_P(RobustResourceInitTestES3, TextureInit_IntRGB32)
1083 {
1084     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1085     testIntegerTextureInit<int32_t>("i", GL_RGBA32I, GL_RGB32I, GL_INT);
1086 }
1087 
1088 // Test that uninitialized image texture works well.
TEST_P(RobustResourceInitTestES31,ImageTextureInit_R32UI)1089 TEST_P(RobustResourceInitTestES31, ImageTextureInit_R32UI)
1090 {
1091     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1092     constexpr char kCS[] =
1093         R"(#version 310 es
1094         layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1095         layout(r32ui, binding = 1) writeonly uniform highp uimage2D writeImage;
1096         void main()
1097         {
1098             imageStore(writeImage, ivec2(gl_LocalInvocationID.xy), uvec4(200u));
1099         })";
1100 
1101     GLTexture texture;
1102     // Don't upload data to texture.
1103     glBindTexture(GL_TEXTURE_2D, texture);
1104     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1105     EXPECT_GL_NO_ERROR();
1106 
1107     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1108     glUseProgram(program.get());
1109 
1110     glBindImageTexture(1, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1111 
1112     glDispatchCompute(1, 1, 1);
1113     EXPECT_GL_NO_ERROR();
1114 
1115     GLFramebuffer framebuffer;
1116     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1117     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1118 
1119     GLuint outputValue;
1120     glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
1121     EXPECT_GL_NO_ERROR();
1122 
1123     EXPECT_EQ(200u, outputValue);
1124 
1125     outputValue = 0u;
1126     // Write to another uninitialized texture.
1127     GLTexture texture2;
1128     glBindTexture(GL_TEXTURE_2D, texture2);
1129     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1130     EXPECT_GL_NO_ERROR();
1131     glBindImageTexture(1, texture2, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1132     glDispatchCompute(1, 1, 1);
1133     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
1134     glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
1135     EXPECT_EQ(200u, outputValue);
1136 }
1137 
1138 // Basic test that renderbuffers are initialized correctly.
TEST_P(RobustResourceInitTest,Renderbuffer)1139 TEST_P(RobustResourceInitTest, Renderbuffer)
1140 {
1141     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1142 
1143     GLRenderbuffer renderbuffer;
1144     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1145     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
1146 
1147     GLFramebuffer framebuffer;
1148     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1149     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
1150 
1151     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
1152 }
1153 
1154 // Tests creating mipmaps with robust resource init.
TEST_P(RobustResourceInitTestES3,GenerateMipmap)1155 TEST_P(RobustResourceInitTestES3, GenerateMipmap)
1156 {
1157     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1158 
1159     constexpr GLint kTextureSize = 16;
1160 
1161     // Initialize a 16x16 RGBA8 texture with no data.
1162     GLTexture tex;
1163     glBindTexture(GL_TEXTURE_2D, tex);
1164     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA,
1165                  GL_UNSIGNED_BYTE, nullptr);
1166     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1167     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1168 
1169     std::string shader = GetSimpleTextureFragmentShader("");
1170     ANGLE_GL_PROGRAM(program, kSimpleTextureVertexShader, shader.c_str());
1171 
1172     // Generate mipmaps and verify all the mips.
1173     glGenerateMipmap(GL_TEXTURE_2D);
1174     ASSERT_GL_NO_ERROR();
1175 
1176     // Validate a small texture.
1177     glClearColor(1, 0, 0, 1);
1178     glClear(GL_COLOR_BUFFER_BIT);
1179     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1180 
1181     // Set viewport to resize the texture and draw.
1182     glViewport(0, 0, 2, 2);
1183     drawQuad(program, "position", 0.5f);
1184     ASSERT_GL_NO_ERROR();
1185     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1186 }
1187 
1188 // Tests creating mipmaps for cube maps with robust resource init.
TEST_P(RobustResourceInitTestES3,GenerateMipmapCubeMap)1189 TEST_P(RobustResourceInitTestES3, GenerateMipmapCubeMap)
1190 {
1191     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1192 
1193     constexpr GLint kTextureSize   = 16;
1194     constexpr GLint kTextureLevels = 5;
1195 
1196     // Initialize a 16x16 RGBA8 texture with no data.
1197     GLTexture tex;
1198     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1199     for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1200          ++target)
1201     {
1202         glTexImage2D(target, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1203                      nullptr);
1204     }
1205     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1206     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1207 
1208     // Generate mipmaps and verify all the mips.
1209     glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
1210     ASSERT_GL_NO_ERROR();
1211 
1212     GLFramebuffer fbo;
1213     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1214     for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1215          ++target)
1216     {
1217         for (GLint level = 0; level < kTextureLevels; ++level)
1218         {
1219             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, tex, level);
1220             EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1221         }
1222     }
1223 }
1224 
1225 // Test blitting a framebuffer out-of-bounds. Multiple iterations.
TEST_P(RobustResourceInitTestES3,BlitFramebufferOutOfBounds)1226 TEST_P(RobustResourceInitTestES3, BlitFramebufferOutOfBounds)
1227 {
1228     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1229 
1230     // http://anglebug.com/2408
1231     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD());
1232 
1233     // Initiate data to read framebuffer
1234     constexpr int size                = 8;
1235     constexpr GLenum readbufferFormat = GL_RGBA8;
1236     constexpr GLenum drawbufferFormat = GL_RGBA8;
1237     constexpr GLenum filter           = GL_NEAREST;
1238 
1239     std::vector<GLColor> readColors(size * size, GLColor::yellow);
1240 
1241     // Create read framebuffer and feed data to read buffer
1242     // Read buffer may have srgb image
1243     GLTexture tex_read;
1244     glBindTexture(GL_TEXTURE_2D, tex_read);
1245     glTexImage2D(GL_TEXTURE_2D, 0, readbufferFormat, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1246                  readColors.data());
1247 
1248     GLFramebuffer fbo_read;
1249     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read);
1250     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_read, 0);
1251 
1252     // Create draw framebuffer. Color in draw buffer is initialized to 0.
1253     // Draw buffer may have srgb image
1254     GLTexture tex_draw;
1255     glBindTexture(GL_TEXTURE_2D, tex_draw);
1256     glTexImage2D(GL_TEXTURE_2D, 0, drawbufferFormat, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1257                  nullptr);
1258 
1259     GLFramebuffer fbo_draw;
1260     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_draw);
1261     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_draw, 0);
1262 
1263     ASSERT_GL_NO_ERROR();
1264     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
1265 
1266     using Region = std::array<int, 4>;
1267 
1268     struct Test
1269     {
1270         constexpr Test(const Region &read, const Region &draw, const Region &real)
1271             : readRegion(read), drawRegion(draw), realRegion(real)
1272         {}
1273 
1274         Region readRegion;
1275         Region drawRegion;
1276         Region realRegion;
1277     };
1278 
1279     constexpr std::array<Test, 2> tests = {{
1280         // only src region is out-of-bounds, dst region has different width/height as src region.
1281         {{{-2, -2, 4, 4}}, {{1, 1, 4, 4}}, {{2, 2, 4, 4}}},
1282         // only src region is out-of-bounds, dst region has the same width/height as src region.
1283         {{{-2, -2, 4, 4}}, {{1, 1, 7, 7}}, {{3, 3, 7, 7}}},
1284     }};
1285 
1286     // Blit read framebuffer to the image in draw framebuffer.
1287     for (const auto &test : tests)
1288     {
1289         // both the read framebuffer and draw framebuffer bounds are [0, 0, 8, 8]
1290         // blitting from src region to dst region
1291         glBindTexture(GL_TEXTURE_2D, tex_draw);
1292         glTexImage2D(GL_TEXTURE_2D, 0, drawbufferFormat, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1293                      nullptr);
1294 
1295         const auto &read = test.readRegion;
1296         const auto &draw = test.drawRegion;
1297         const auto &real = test.realRegion;
1298 
1299         glBlitFramebuffer(read[0], read[1], read[2], read[3], draw[0], draw[1], draw[2], draw[3],
1300                           GL_COLOR_BUFFER_BIT, filter);
1301 
1302         // Read pixels and check the correctness.
1303         std::vector<GLColor> pixels(size * size);
1304         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_draw);
1305         glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1306         glReadPixels(0, 0, size, size, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
1307         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read);
1308         ASSERT_GL_NO_ERROR();
1309 
1310         for (int ii = 0; ii < size; ++ii)
1311         {
1312             for (int jj = 0; jj < size; ++jj)
1313             {
1314                 GLColor expectedColor = GLColor::transparentBlack;
1315                 if (ii >= real[0] && ii < real[2] && jj >= real[1] && jj < real[3])
1316                 {
1317                     expectedColor = GLColor::yellow;
1318                 }
1319 
1320                 int loc = ii * size + jj;
1321                 EXPECT_EQ(expectedColor, pixels[loc]) << " at [" << jj << ", " << ii << "]";
1322             }
1323         }
1324     }
1325 }
1326 
1327 template <typename ClearFunc>
maskedDepthClear(ClearFunc clearFunc)1328 void RobustResourceInitTest::maskedDepthClear(ClearFunc clearFunc)
1329 {
1330     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1331 
1332     constexpr int kSize = 16;
1333 
1334     // Initialize a FBO with depth and simple color.
1335     GLRenderbuffer depthbuffer;
1336     glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
1337     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kSize, kSize);
1338 
1339     GLTexture colorbuffer;
1340     glBindTexture(GL_TEXTURE_2D, colorbuffer);
1341     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1342 
1343     GLFramebuffer framebuffer;
1344     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1345     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1346     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer);
1347 
1348     ASSERT_GL_NO_ERROR();
1349     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1350 
1351     // Disable depth writes and trigger a clear.
1352     glDepthMask(GL_FALSE);
1353 
1354     clearFunc(0.5f);
1355     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1356 
1357     // Draw red with a depth function that checks for the clear value.
1358     glEnable(GL_DEPTH_TEST);
1359     glDepthFunc(GL_EQUAL);
1360 
1361     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1362 
1363     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1364     ASSERT_GL_NO_ERROR();
1365     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black) << "depth should not be 0.5f";
1366 
1367     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
1368     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "depth should be initialized to 1.0f";
1369 }
1370 
1371 // Test that clearing a masked depth buffer doesn't mark it clean.
TEST_P(RobustResourceInitTest,MaskedDepthClear)1372 TEST_P(RobustResourceInitTest, MaskedDepthClear)
1373 {
1374     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1375 
1376     // http://anglebug.com/2407
1377     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1378 
1379     auto clearFunc = [](float depth) {
1380         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1381         glClearDepthf(depth);
1382         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1383     };
1384 
1385     maskedDepthClear(clearFunc);
1386 }
1387 
1388 // Tests the same as MaskedDepthClear, but using ClearBuffer calls.
TEST_P(RobustResourceInitTestES3,MaskedDepthClearBuffer)1389 TEST_P(RobustResourceInitTestES3, MaskedDepthClearBuffer)
1390 {
1391     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1392 
1393     // http://anglebug.com/2407
1394     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1395 
1396     auto clearFunc = [](float depth) {
1397         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1398         glClear(GL_COLOR_BUFFER_BIT);
1399         glClearBufferfv(GL_DEPTH, 0, &depth);
1400     };
1401 
1402     maskedDepthClear(clearFunc);
1403 }
1404 
1405 template <typename ClearFunc>
maskedStencilClear(ClearFunc clearFunc)1406 void RobustResourceInitTest::maskedStencilClear(ClearFunc clearFunc)
1407 {
1408     constexpr int kSize = 16;
1409 
1410     // Initialize a FBO with stencil and simple color.
1411     GLRenderbuffer stencilbuffer;
1412     glBindRenderbuffer(GL_RENDERBUFFER, stencilbuffer);
1413     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, kSize, kSize);
1414 
1415     GLTexture colorbuffer;
1416     glBindTexture(GL_TEXTURE_2D, colorbuffer);
1417     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1418 
1419     GLFramebuffer framebuffer;
1420     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1421     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1422     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1423                               stencilbuffer);
1424 
1425     ASSERT_GL_NO_ERROR();
1426     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1427 
1428     // Disable stencil writes and trigger a clear. Use a tricky mask that does not overlap the
1429     // clear.
1430     glStencilMask(0xF0);
1431     clearFunc(0x0F);
1432     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1433 
1434     // Draw red with a stencil function that checks for stencil == 0
1435     glEnable(GL_STENCIL_TEST);
1436     glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1437     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1438 
1439     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1440 
1441     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1442     ASSERT_GL_NO_ERROR();
1443     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "stencil should be equal to zero";
1444 }
1445 
1446 // Test that clearing a masked stencil buffer doesn't mark it clean.
TEST_P(RobustResourceInitTest,MaskedStencilClear)1447 TEST_P(RobustResourceInitTest, MaskedStencilClear)
1448 {
1449     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1450     ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
1451 
1452     // http://anglebug.com/2407, but only fails on Nexus devices
1453     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
1454 
1455     auto clearFunc = [](GLint clearValue) {
1456         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1457         glClearStencil(clearValue);
1458         glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1459     };
1460 
1461     maskedStencilClear(clearFunc);
1462 }
1463 
1464 // Test that clearing a masked stencil buffer doesn't mark it clean, with ClearBufferi.
TEST_P(RobustResourceInitTestES3,MaskedStencilClearBuffer)1465 TEST_P(RobustResourceInitTestES3, MaskedStencilClearBuffer)
1466 {
1467     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1468 
1469     // http://anglebug.com/2408
1470     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsNVIDIA()));
1471 
1472     ANGLE_SKIP_TEST_IF(IsLinux() && IsOpenGL());
1473 
1474     // http://anglebug.com/2407, but only fails on Nexus devices
1475     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
1476 
1477     auto clearFunc = [](GLint clearValue) {
1478         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1479         glClear(GL_COLOR_BUFFER_BIT);
1480         glClearBufferiv(GL_STENCIL, 0, &clearValue);
1481     };
1482 
1483     maskedStencilClear(clearFunc);
1484 }
1485 
1486 template <int Size, typename InitializedTest>
VerifyRGBA8PixelRect(InitializedTest inInitialized)1487 void VerifyRGBA8PixelRect(InitializedTest inInitialized)
1488 {
1489     std::array<std::array<GLColor, Size>, Size> actualPixels;
1490     glReadPixels(0, 0, Size, Size, GL_RGBA, GL_UNSIGNED_BYTE, actualPixels.data());
1491     ASSERT_GL_NO_ERROR();
1492 
1493     for (int y = 0; y < Size; ++y)
1494     {
1495         for (int x = 0; x < Size; ++x)
1496         {
1497             if (inInitialized(x, y))
1498             {
1499                 EXPECT_EQ(actualPixels[y][x], GLColor::red) << " at " << x << ", " << y;
1500             }
1501             else
1502             {
1503                 EXPECT_EQ(actualPixels[y][x], GLColor::transparentBlack)
1504                     << " at " << x << ", " << y;
1505             }
1506         }
1507     }
1508 }
1509 
1510 // Tests that calling CopyTexSubImage2D will initialize the source & destination.
TEST_P(RobustResourceInitTest,CopyTexSubImage2D)1511 TEST_P(RobustResourceInitTest, CopyTexSubImage2D)
1512 {
1513     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1514     ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
1515 
1516     static constexpr int kDestSize = 4;
1517     constexpr int kSrcSize         = kDestSize / 2;
1518     static constexpr int kOffset   = kSrcSize / 2;
1519 
1520     std::vector<GLColor> redColors(kDestSize * kDestSize, GLColor::red);
1521 
1522     // Initialize source texture with red.
1523     GLTexture srcTexture;
1524     glBindTexture(GL_TEXTURE_2D, srcTexture);
1525     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSrcSize, kSrcSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1526                  redColors.data());
1527 
1528     GLFramebuffer framebuffer;
1529     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1530     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexture, 0);
1531 
1532     ASSERT_GL_NO_ERROR();
1533     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1534 
1535     // Create uninitialized destination texture.
1536     GLTexture destTexture;
1537     glBindTexture(GL_TEXTURE_2D, destTexture);
1538     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kDestSize, kDestSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1539                  nullptr);
1540 
1541     // Trigger the copy from initialized source into uninitialized dest.
1542     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kOffset, kOffset, 0, 0, kSrcSize, kSrcSize);
1543 
1544     // Verify the pixel rectangle.
1545     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0);
1546     ASSERT_GL_NO_ERROR();
1547 
1548     auto srcInitTest = [](int x, int y) {
1549         return (x >= kOffset) && x < (kDestSize - kOffset) && (y >= kOffset) &&
1550                y < (kDestSize - kOffset);
1551     };
1552 
1553     VerifyRGBA8PixelRect<kDestSize>(srcInitTest);
1554 
1555     // Make source texture uninitialized. Force a release by redefining a new size.
1556     glBindTexture(GL_TEXTURE_2D, srcTexture);
1557     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSrcSize, kSrcSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1558                  nullptr);
1559     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexture, 0);
1560 
1561     // Fill destination texture with red.
1562     glBindTexture(GL_TEXTURE_2D, destTexture);
1563     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kDestSize, kDestSize, GL_RGBA, GL_UNSIGNED_BYTE,
1564                     redColors.data());
1565 
1566     // Trigger a copy from uninitialized source into initialized dest.
1567     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kOffset, kOffset, 0, 0, kSrcSize, kSrcSize);
1568 
1569     // Verify the pixel rectangle.
1570     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0);
1571     ASSERT_GL_NO_ERROR();
1572 
1573     auto destInitTest = [srcInitTest](int x, int y) { return !srcInitTest(x, y); };
1574 
1575     VerifyRGBA8PixelRect<kDestSize>(destInitTest);
1576 }
1577 
copyTexSubImage2DCustomFBOTest(int offsetX,int offsetY)1578 void RobustResourceInitTest::copyTexSubImage2DCustomFBOTest(int offsetX, int offsetY)
1579 {
1580     const int texSize = 512;
1581     const int fboSize = 16;
1582 
1583     GLTexture texture;
1584     glBindTexture(GL_TEXTURE_2D, texture.get());
1585     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texSize, texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1586                  nullptr);
1587     ASSERT_GL_NO_ERROR();
1588 
1589     GLRenderbuffer renderbuffer;
1590     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
1591     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboSize, fboSize);
1592     ASSERT_GL_NO_ERROR();
1593 
1594     GLFramebuffer framebuffer;
1595     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1596     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1597                               renderbuffer.get());
1598     ASSERT_GL_NO_ERROR();
1599     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1600 
1601     glClearColor(1.0, 0.0, 0.0, 1.0);
1602     glClear(GL_COLOR_BUFFER_BIT);
1603     ASSERT_GL_NO_ERROR();
1604 
1605     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, offsetX, offsetY, texSize, texSize);
1606     ASSERT_GL_NO_ERROR();
1607 
1608     GLFramebuffer readbackFBO;
1609     glBindFramebuffer(GL_FRAMEBUFFER, readbackFBO.get());
1610     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1611     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1612     checkCustomFramebufferNonZeroPixels(texSize, texSize, -offsetX, -offsetY, fboSize, fboSize,
1613                                         GLColor::red);
1614 }
1615 
1616 // Test CopyTexSubImage2D clipped to size of custom FBO, zero x/y source offset.
TEST_P(RobustResourceInitTest,CopyTexSubImage2DCustomFBOZeroOffsets)1617 TEST_P(RobustResourceInitTest, CopyTexSubImage2DCustomFBOZeroOffsets)
1618 {
1619     // TODO(anglebug.com/4507): pass this test on the Metal backend.
1620     ANGLE_SKIP_TEST_IF(IsMetal());
1621     copyTexSubImage2DCustomFBOTest(0, 0);
1622 }
1623 
1624 // Test CopyTexSubImage2D clipped to size of custom FBO, negative x/y source offset.
TEST_P(RobustResourceInitTest,CopyTexSubImage2DCustomFBONegativeOffsets)1625 TEST_P(RobustResourceInitTest, CopyTexSubImage2DCustomFBONegativeOffsets)
1626 {
1627     // TODO(anglebug.com/4507): pass this test on the Metal backend.
1628     ANGLE_SKIP_TEST_IF(IsMetal());
1629     copyTexSubImage2DCustomFBOTest(-8, -8);
1630 }
1631 
1632 // Tests that calling CopyTexSubImage3D will initialize the source & destination.
TEST_P(RobustResourceInitTestES3,CopyTexSubImage3D)1633 TEST_P(RobustResourceInitTestES3, CopyTexSubImage3D)
1634 {
1635     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1636 
1637     static constexpr int kDestSize = 4;
1638     constexpr int kSrcSize         = kDestSize / 2;
1639     static constexpr int kOffset   = kSrcSize / 2;
1640 
1641     std::vector<GLColor> redColors(kDestSize * kDestSize * kDestSize, GLColor::red);
1642 
1643     GLTexture srcTexture;
1644     GLFramebuffer framebuffer;
1645     GLTexture destTexture;
1646     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1647 
1648     // Initialize source texture with red.
1649     glBindTexture(GL_TEXTURE_3D, srcTexture);
1650     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kSrcSize, kSrcSize, kSrcSize, 0, GL_RGBA,
1651                  GL_UNSIGNED_BYTE, redColors.data());
1652 
1653     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTexture, 0, 0);
1654 
1655     ASSERT_GL_NO_ERROR();
1656     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1657 
1658     // Create uninitialized destination texture.
1659     glBindTexture(GL_TEXTURE_3D, destTexture);
1660     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kDestSize, kDestSize, kDestSize, 0, GL_RGBA,
1661                  GL_UNSIGNED_BYTE, nullptr);
1662 
1663     // Trigger the copy from initialized source into uninitialized dest.
1664     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, kOffset, kOffset, 0, 0, 0, kSrcSize, kSrcSize);
1665 
1666     // Verify the pixel rectangle.
1667     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destTexture, 0, 0);
1668     ASSERT_GL_NO_ERROR();
1669 
1670     auto srcInitTest = [](int x, int y) {
1671         return (x >= kOffset) && x < (kDestSize - kOffset) && (y >= kOffset) &&
1672                y < (kDestSize - kOffset);
1673     };
1674 
1675     VerifyRGBA8PixelRect<kDestSize>(srcInitTest);
1676 
1677     // Make source texture uninitialized.
1678     glBindTexture(GL_TEXTURE_3D, srcTexture);
1679     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kSrcSize, kSrcSize, kSrcSize, 0, GL_RGBA,
1680                  GL_UNSIGNED_BYTE, nullptr);
1681     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTexture, 0, 0);
1682 
1683     ASSERT_GL_NO_ERROR();
1684     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1685 
1686     // Fill destination texture with red.
1687     glBindTexture(GL_TEXTURE_3D, destTexture);
1688     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kDestSize, kDestSize, kDestSize, 0, GL_RGBA,
1689                  GL_UNSIGNED_BYTE, redColors.data());
1690 
1691     // Trigger a copy from uninitialized source into initialized dest.
1692     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, kOffset, kOffset, 0, 0, 0, kSrcSize, kSrcSize);
1693 
1694     // Verify the pixel rectangle.
1695     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destTexture, 0, 0);
1696     ASSERT_GL_NO_ERROR();
1697 
1698     auto destInitTest = [srcInitTest](int x, int y) { return !srcInitTest(x, y); };
1699 
1700     VerifyRGBA8PixelRect<kDestSize>(destInitTest);
1701 }
1702 
1703 // Test basic robustness with 2D array textures.
TEST_P(RobustResourceInitTestES3,Texture2DArray)1704 TEST_P(RobustResourceInitTestES3, Texture2DArray)
1705 {
1706     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1707 
1708     constexpr int kSize   = 1024;
1709     constexpr int kLayers = 8;
1710 
1711     GLTexture texture;
1712     glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
1713     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kSize, kSize, kLayers, 0, GL_RGBA,
1714                  GL_UNSIGNED_BYTE, nullptr);
1715 
1716     GLFramebuffer framebuffer;
1717     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1718 
1719     for (int layer = 0; layer < kLayers; ++layer)
1720     {
1721         checkNonZeroPixels3D(&texture, 0, 0, 0, 0, layer, GLColor::transparentBlack);
1722     }
1723 }
1724 
1725 // Test that using TexStorage2D followed by CompressedSubImage works with robust init.
1726 // Taken from WebGL test conformance/extensions/webgl-compressed-texture-s3tc.
TEST_P(RobustResourceInitTestES3,CompressedSubImage)1727 TEST_P(RobustResourceInitTestES3, CompressedSubImage)
1728 {
1729     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1730     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
1731 
1732     constexpr int width     = 8;
1733     constexpr int height    = 8;
1734     constexpr int subX0     = 0;
1735     constexpr int subY0     = 0;
1736     constexpr int subWidth  = 4;
1737     constexpr int subHeight = 4;
1738     constexpr GLenum format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1739 
1740     static constexpr uint8_t img_8x8_rgb_dxt1[] = {
1741         0xe0, 0x07, 0x00, 0xf8, 0x11, 0x10, 0x15, 0x00, 0x1f, 0x00, 0xe0,
1742         0xff, 0x11, 0x10, 0x15, 0x00, 0xe0, 0x07, 0x1f, 0xf8, 0x44, 0x45,
1743         0x40, 0x55, 0x1f, 0x00, 0xff, 0x07, 0x44, 0x45, 0x40, 0x55,
1744     };
1745 
1746     static constexpr uint8_t img_4x4_rgb_dxt1[] = {
1747         0xe0, 0x07, 0x00, 0xf8, 0x11, 0x10, 0x15, 0x00,
1748     };
1749 
1750     std::vector<uint8_t> data(img_8x8_rgb_dxt1, img_8x8_rgb_dxt1 + ArraySize(img_8x8_rgb_dxt1));
1751     std::vector<uint8_t> subData(img_4x4_rgb_dxt1, img_4x4_rgb_dxt1 + ArraySize(img_4x4_rgb_dxt1));
1752 
1753     GLTexture colorbuffer;
1754     glBindTexture(GL_TEXTURE_2D, colorbuffer);
1755     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1756 
1757     GLFramebuffer framebuffer;
1758     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1759     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1760     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1761 
1762     glViewport(0, 0, width, height);
1763 
1764     // testing format width-x-height via texStorage2D
1765     const auto &expectedData = UncompressDXTIntoSubRegion(width, height, subX0, subY0, subWidth,
1766                                                           subHeight, subData, format);
1767 
1768     GLTexture tex;
1769     glBindTexture(GL_TEXTURE_2D, tex);
1770     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1771     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1772     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1773     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1774 
1775     glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
1776     ASSERT_GL_NO_ERROR();
1777     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, subX0, subY0, subWidth, subHeight, format,
1778                               static_cast<GLsizei>(subData.size()), subData.data());
1779     ASSERT_GL_NO_ERROR();
1780 
1781     draw2DTexturedQuad(0.5f, 1.0f, true);
1782     ASSERT_GL_NO_ERROR();
1783 
1784     std::vector<GLColor> actualData(width * height);
1785     glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
1786     ASSERT_GL_NO_ERROR();
1787 
1788     for (int y = 0; y < height; ++y)
1789     {
1790         for (int x = 0; x < width; ++x)
1791         {
1792             int offset                  = x + y * width;
1793             const GLColor expectedColor = expectedData[offset];
1794             const GLColor actualColor   = actualData[offset];
1795 
1796             // Allow for some minor variation because the format is compressed.
1797             EXPECT_NEAR(expectedColor.R, actualColor.R, 1) << " at (" << x << ", " << y << ")";
1798             EXPECT_NEAR(expectedColor.G, actualColor.G, 1) << " at (" << x << ", " << y << ")";
1799             EXPECT_NEAR(expectedColor.B, actualColor.B, 1) << " at (" << x << ", " << y << ")";
1800         }
1801     }
1802 }
1803 
1804 // Tests that a partial scissor still initializes contents as expected.
TEST_P(RobustResourceInitTest,ClearWithScissor)1805 TEST_P(RobustResourceInitTest, ClearWithScissor)
1806 {
1807     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1808 
1809     constexpr int kSize = 16;
1810 
1811     GLRenderbuffer colorbuffer;
1812     glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
1813     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
1814 
1815     GLFramebuffer framebuffer;
1816     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1817     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
1818 
1819     ASSERT_GL_NO_ERROR();
1820     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1821 
1822     // Scissor to half the width.
1823     glEnable(GL_SCISSOR_TEST);
1824     glScissor(0, 0, kSize / 2, kSize);
1825 
1826     // Clear. Half the texture should be black, and half red.
1827     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1828     glClear(GL_COLOR_BUFFER_BIT);
1829 
1830     EXPECT_GL_NO_ERROR();
1831     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1832     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::transparentBlack);
1833 }
1834 
1835 // Tests that surfaces are initialized when they are created
TEST_P(RobustResourceInitTest,SurfaceInitialized)1836 TEST_P(RobustResourceInitTest, SurfaceInitialized)
1837 {
1838     ANGLE_SKIP_TEST_IF(!hasRobustSurfaceInit());
1839 
1840     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
1841 }
1842 
1843 // Tests that surfaces are initialized after swapping if they are not preserved
TEST_P(RobustResourceInitTest,SurfaceInitializedAfterSwap)1844 TEST_P(RobustResourceInitTest, SurfaceInitializedAfterSwap)
1845 {
1846     ANGLE_SKIP_TEST_IF(!hasRobustSurfaceInit());
1847 
1848     EGLint swapBehaviour = 0;
1849     ASSERT_TRUE(eglQuerySurface(getEGLWindow()->getDisplay(), getEGLWindow()->getSurface(),
1850                                 EGL_SWAP_BEHAVIOR, &swapBehaviour));
1851 
1852     const std::array<GLColor, 4> clearColors = {{
1853         GLColor::blue,
1854         GLColor::cyan,
1855         GLColor::red,
1856         GLColor::yellow,
1857     }};
1858     for (size_t i = 0; i < clearColors.size(); i++)
1859     {
1860         if (swapBehaviour == EGL_BUFFER_PRESERVED && i > 0)
1861         {
1862             EXPECT_PIXEL_COLOR_EQ(0, 0, clearColors[i - 1]);
1863         }
1864         else
1865         {
1866             checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
1867         }
1868 
1869         angle::Vector4 clearColor = clearColors[i].toNormalizedVector();
1870         glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
1871         glClear(GL_COLOR_BUFFER_BIT);
1872         EXPECT_GL_NO_ERROR();
1873 
1874         swapBuffers();
1875     }
1876 }
1877 
1878 // Test that multisampled 2D textures are initialized.
TEST_P(RobustResourceInitTestES31,Multisample2DTexture)1879 TEST_P(RobustResourceInitTestES31, Multisample2DTexture)
1880 {
1881     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1882     // http://anglebug.com/4092
1883     ANGLE_SKIP_TEST_IF(IsVulkan());
1884 
1885     GLTexture texture;
1886     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
1887     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, kWidth, kHeight, false);
1888 
1889     GLFramebuffer framebuffer;
1890     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1891     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1892                            texture, 0);
1893 
1894     GLTexture resolveTexture;
1895     glBindTexture(GL_TEXTURE_2D, resolveTexture);
1896     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
1897 
1898     GLFramebuffer resolveFramebuffer;
1899     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
1900     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
1901                            0);
1902     ASSERT_GL_NO_ERROR();
1903 
1904     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1905                       GL_NEAREST);
1906     ASSERT_GL_NO_ERROR();
1907 
1908     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFramebuffer);
1909     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::transparentBlack);
1910 }
1911 
1912 // Test that multisampled 2D texture arrays from OES_texture_storage_multisample_2d_array are
1913 // initialized.
TEST_P(RobustResourceInitTestES31,Multisample2DTextureArray)1914 TEST_P(RobustResourceInitTestES31, Multisample2DTextureArray)
1915 {
1916     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1917 
1918     if (IsGLExtensionRequestable("GL_OES_texture_storage_multisample_2d_array"))
1919     {
1920         glRequestExtensionANGLE("GL_OES_texture_storage_multisample_2d_array");
1921     }
1922     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"));
1923 
1924     const GLsizei kLayers = 4;
1925 
1926     GLTexture texture;
1927     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, texture);
1928     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, kWidth, kHeight,
1929                                  kLayers, false);
1930 
1931     GLTexture resolveTexture;
1932     glBindTexture(GL_TEXTURE_2D, resolveTexture);
1933     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
1934 
1935     GLFramebuffer resolveFramebuffer;
1936     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
1937     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
1938                            0);
1939     ASSERT_GL_NO_ERROR();
1940 
1941     for (GLsizei layerIndex = 0; layerIndex < kLayers; ++layerIndex)
1942     {
1943         GLFramebuffer framebuffer;
1944         glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1945         glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0,
1946                                   layerIndex);
1947 
1948         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1949                           GL_NEAREST);
1950         ASSERT_GL_NO_ERROR();
1951 
1952         glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFramebuffer);
1953         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::transparentBlack);
1954     }
1955 }
1956 
1957 // Tests that using an out of bounds draw offset with a dynamic array succeeds.
TEST_P(RobustResourceInitTest,DynamicVertexArrayOffsetOutOfBounds)1958 TEST_P(RobustResourceInitTest, DynamicVertexArrayOffsetOutOfBounds)
1959 {
1960     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1961     glUseProgram(program);
1962 
1963     GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1964     ASSERT_NE(-1, posLoc);
1965 
1966     glEnableVertexAttribArray(posLoc);
1967     GLBuffer buf;
1968     glBindBuffer(GL_ARRAY_BUFFER, buf);
1969     glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const void *>(500));
1970     glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_DYNAMIC_DRAW);
1971     glDrawArrays(GL_TRIANGLES, 0, 3);
1972 
1973     // Either no error or invalid operation is okay.
1974 }
1975 
1976 // Test to cover a bug that the multisampled depth attachment of a framebuffer are not successfully
1977 // initialized before it is used as the read framebuffer in blitFramebuffer.
1978 // Referenced from the following WebGL CTS:
1979 // conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html
TEST_P(RobustResourceInitTestES3,InitializeMultisampledDepthRenderbufferAfterCopyTextureCHROMIUM)1980 TEST_P(RobustResourceInitTestES3, InitializeMultisampledDepthRenderbufferAfterCopyTextureCHROMIUM)
1981 {
1982     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1983     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_copy_texture"));
1984 
1985     // Call glCopyTextureCHROMIUM to set destTexture as the color attachment of the internal
1986     // framebuffer mScratchFBO.
1987     GLTexture sourceTexture;
1988     glBindTexture(GL_TEXTURE_2D, sourceTexture);
1989     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1990     GLTexture destTexture;
1991     glBindTexture(GL_TEXTURE_2D, destTexture);
1992     glCopyTextureCHROMIUM(sourceTexture, 0, GL_TEXTURE_2D, destTexture, 0, GL_RGBA,
1993                           GL_UNSIGNED_BYTE, GL_FALSE, GL_FALSE, GL_FALSE);
1994     ASSERT_GL_NO_ERROR();
1995 
1996     GLFramebuffer drawFbo;
1997     glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
1998 
1999     GLTexture colorTex;
2000     glBindTexture(GL_TEXTURE_2D, colorTex);
2001     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2002     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
2003     GLRenderbuffer drawDepthRbo;
2004     glBindRenderbuffer(GL_RENDERBUFFER, drawDepthRbo);
2005     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kWidth, kHeight);
2006     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, drawDepthRbo);
2007 
2008     // Clear drawDepthRbo to 0.0f
2009     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2010     glClearDepthf(0.0f);
2011     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2012 
2013     constexpr uint32_t kReadDepthRboSampleCount = 4;
2014     GLFramebuffer readFbo;
2015     glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
2016     GLRenderbuffer readDepthRbo;
2017     glBindRenderbuffer(GL_RENDERBUFFER, readDepthRbo);
2018     glRenderbufferStorageMultisample(GL_RENDERBUFFER, kReadDepthRboSampleCount,
2019                                      GL_DEPTH_COMPONENT16, kWidth, kHeight);
2020     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, readDepthRbo);
2021 
2022     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2023     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
2024 
2025     // Blit from readDepthRbo to drawDepthRbo. When robust resource init is enabled, readDepthRbo
2026     // should be initialized to 1.0f by default, so the data in drawDepthRbo should also be 1.0f.
2027     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
2028                       GL_NEAREST);
2029     ASSERT_GL_NO_ERROR();
2030 
2031     glDepthFunc(GL_LESS);
2032     glEnable(GL_DEPTH_TEST);
2033 
2034     glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
2035     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2036 
2037     // If drawDepthRbo is correctly set to 1.0f, the depth test can always pass, so the result
2038     // should be green.
2039     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2040     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2041 }
2042 
2043 // Corner case for robust resource init: CopyTexImage to a cube map.
TEST_P(RobustResourceInitTest,CopyTexImageToOffsetCubeMap)2044 TEST_P(RobustResourceInitTest, CopyTexImageToOffsetCubeMap)
2045 {
2046     // http://anglebug.com/4549
2047     ANGLE_SKIP_TEST_IF(IsMetal());
2048 
2049     constexpr GLuint kSize = 2;
2050 
2051     std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
2052 
2053     GLTexture srcTex;
2054     glBindTexture(GL_TEXTURE_2D, srcTex);
2055     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2056                  redPixels.data());
2057 
2058     GLFramebuffer fbo;
2059     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2060     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTex, 0);
2061 
2062     ASSERT_GL_NO_ERROR();
2063     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2064     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2065 
2066     GLTexture dstTex;
2067     glBindTexture(GL_TEXTURE_CUBE_MAP, dstTex);
2068     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, kSize, kSize, 0);
2069     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, -1, -1, kSize, kSize, 0);
2070     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 2, 2, kSize, kSize, 0);
2071     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, -2, -2, kSize, kSize, 0);
2072     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2073     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2074 
2075     ASSERT_GL_NO_ERROR();
2076 
2077     // Verify the offset attachments.
2078     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
2079                            dstTex, 0);
2080     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2081     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2082     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::transparentBlack);
2083     EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::transparentBlack);
2084     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::transparentBlack);
2085 
2086     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
2087                            dstTex, 0);
2088     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2089     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2090     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::transparentBlack);
2091     EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::transparentBlack);
2092     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
2093 }
2094 
2095 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(RobustResourceInitTest,
2096                                        WithAllocateNonZeroMemory(ES2_VULKAN()));
2097 
2098 ANGLE_INSTANTIATE_TEST_ES3_AND(RobustResourceInitTestES3, WithAllocateNonZeroMemory(ES3_VULKAN()));
2099 
2100 ANGLE_INSTANTIATE_TEST_ES31_AND(RobustResourceInitTestES31,
2101                                 WithAllocateNonZeroMemory(ES31_VULKAN()));
2102 
2103 }  // namespace angle
2104