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 = IsD3D11() || IsD3D11_FL93() || IsD3D9() || IsOpenGL() ||
316                              IsOpenGLES() || IsVulkan() || IsMetal();
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         GLTexture texture;
336         glBindTexture(GL_TEXTURE_2D, texture);
337         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
338 
339         // Can't verify the init state after glTexImage2D, the implementation is free to initialize
340         // any time before the resource is read.
341 
342         {
343             // Force to uninitialized
344             glTexParameteri(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, GL_FALSE);
345 
346             GLint initState = 0;
347             glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
348             EXPECT_GL_FALSE(initState);
349         }
350         {
351             // Force to initialized
352             glTexParameteri(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, GL_TRUE);
353 
354             GLint initState = 0;
355             glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
356             EXPECT_GL_TRUE(initState);
357         }
358     }
359     else
360     {
361         // Querying robust resource init should return INVALID_ENUM.
362         GLboolean enabled = 0;
363         glGetBooleanv(GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
364         EXPECT_GL_ERROR(GL_INVALID_ENUM);
365     }
366 }
367 
368 // Tests that buffers start zero-filled if the data pointer is null.
TEST_P(RobustResourceInitTest,BufferData)369 TEST_P(RobustResourceInitTest, BufferData)
370 {
371     ANGLE_SKIP_TEST_IF(!hasGLExtension());
372 
373     GLBuffer buffer;
374     glBindBuffer(GL_ARRAY_BUFFER, buffer);
375     glBufferData(GL_ARRAY_BUFFER, getWindowWidth() * getWindowHeight() * sizeof(GLfloat), nullptr,
376                  GL_STATIC_DRAW);
377 
378     constexpr char kVS[] =
379         "attribute vec2 position;\n"
380         "attribute float testValue;\n"
381         "varying vec4 colorOut;\n"
382         "void main() {\n"
383         "    gl_Position = vec4(position, 0, 1);\n"
384         "    colorOut = testValue == 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
385         "}";
386     constexpr char kFS[] =
387         "varying mediump vec4 colorOut;\n"
388         "void main() {\n"
389         "    gl_FragColor = colorOut;\n"
390         "}";
391 
392     ANGLE_GL_PROGRAM(program, kVS, kFS);
393 
394     GLint testValueLoc = glGetAttribLocation(program.get(), "testValue");
395     ASSERT_NE(-1, testValueLoc);
396 
397     glBindBuffer(GL_ARRAY_BUFFER, buffer);
398     glVertexAttribPointer(testValueLoc, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
399     glEnableVertexAttribArray(testValueLoc);
400     glBindBuffer(GL_ARRAY_BUFFER, 0);
401 
402     drawQuad(program.get(), "position", 0.5f);
403 
404     ASSERT_GL_NO_ERROR();
405 
406     std::vector<GLColor> expected(getWindowWidth() * getWindowHeight(), GLColor::green);
407     std::vector<GLColor> actual(getWindowWidth() * getWindowHeight());
408     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
409                  actual.data());
410     EXPECT_EQ(expected, actual);
411 
412     GLint initState = 0;
413     glBindBuffer(GL_ARRAY_BUFFER, buffer);
414     glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
415     EXPECT_GL_TRUE(initState);
416 }
417 
418 // Regression test for passing a zero size init buffer with the extension.
TEST_P(RobustResourceInitTest,BufferDataZeroSize)419 TEST_P(RobustResourceInitTest, BufferDataZeroSize)
420 {
421     ANGLE_SKIP_TEST_IF(!hasGLExtension());
422 
423     GLBuffer buffer;
424     glBindBuffer(GL_ARRAY_BUFFER, buffer);
425     glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_STATIC_DRAW);
426 }
427 
428 // The following test code translated from WebGL 1 test:
429 // https://www.khronos.org/registry/webgl/sdk/tests/conformance/misc/uninitialized-test.html
setupTexture(GLTexture * tex)430 void RobustResourceInitTest::setupTexture(GLTexture *tex)
431 {
432     GLuint tempTexture;
433     glGenTextures(1, &tempTexture);
434     glBindTexture(GL_TEXTURE_2D, tempTexture);
435     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
436 
437     // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits
438     // into tex then delete texture then re-create one with same characteristics (driver will likely
439     // reuse mem) with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15%
440     // of the time.
441 
442     std::array<uint8_t, kWidth * kHeight * 4> badData;
443     for (size_t i = 0; i < badData.size(); ++i)
444     {
445         badData[i] = static_cast<uint8_t>(i % 255);
446     }
447 
448     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
449                     badData.data());
450     glDeleteTextures(1, &tempTexture);
451 
452     // This will create the GLTexture.
453     glBindTexture(GL_TEXTURE_2D, *tex);
454 }
455 
setup3DTexture(GLTexture * tex)456 void RobustResourceInitTest::setup3DTexture(GLTexture *tex)
457 {
458     GLuint tempTexture;
459     glGenTextures(1, &tempTexture);
460     glBindTexture(GL_TEXTURE_3D, tempTexture);
461     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, kWidth, kHeight, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
462                  nullptr);
463 
464     // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits
465     // into tex then delete texture then re-create one with same characteristics (driver will likely
466     // reuse mem) with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15%
467     // of the time.
468 
469     std::array<uint8_t, kWidth * kHeight * 2 * 4> badData;
470     for (size_t i = 0; i < badData.size(); ++i)
471     {
472         badData[i] = static_cast<uint8_t>(i % 255);
473     }
474 
475     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, 2, GL_RGBA, GL_UNSIGNED_BYTE,
476                     badData.data());
477     glDeleteTextures(1, &tempTexture);
478 
479     // This will create the GLTexture.
480     glBindTexture(GL_TEXTURE_3D, *tex);
481 }
482 
checkNonZeroPixels(GLTexture * texture,int skipX,int skipY,int skipWidth,int skipHeight,const GLColor & skip)483 void RobustResourceInitTest::checkNonZeroPixels(GLTexture *texture,
484                                                 int skipX,
485                                                 int skipY,
486                                                 int skipWidth,
487                                                 int skipHeight,
488                                                 const GLColor &skip)
489 {
490     glBindTexture(GL_TEXTURE_2D, 0);
491     GLFramebuffer fb;
492     glBindFramebuffer(GL_FRAMEBUFFER, fb);
493     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->get(), 0);
494     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
495 
496     checkFramebufferNonZeroPixels(skipX, skipY, skipWidth, skipHeight, skip);
497 }
498 
checkNonZeroPixels3D(GLTexture * texture,int skipX,int skipY,int skipWidth,int skipHeight,int textureLayer,const GLColor & skip)499 void RobustResourceInitTest::checkNonZeroPixels3D(GLTexture *texture,
500                                                   int skipX,
501                                                   int skipY,
502                                                   int skipWidth,
503                                                   int skipHeight,
504                                                   int textureLayer,
505                                                   const GLColor &skip)
506 {
507     glBindTexture(GL_TEXTURE_3D, 0);
508     GLFramebuffer fb;
509     glBindFramebuffer(GL_FRAMEBUFFER, fb);
510     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture->get(), 0,
511                               textureLayer);
512     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
513 
514     checkFramebufferNonZeroPixels(skipX, skipY, skipWidth, skipHeight, skip);
515 }
516 
checkFramebufferNonZeroPixels(int skipX,int skipY,int skipWidth,int skipHeight,const GLColor & skip)517 void RobustResourceInitTest::checkFramebufferNonZeroPixels(int skipX,
518                                                            int skipY,
519                                                            int skipWidth,
520                                                            int skipHeight,
521                                                            const GLColor &skip)
522 {
523     checkCustomFramebufferNonZeroPixels(kWidth, kHeight, skipX, skipY, skipWidth, skipHeight, skip);
524 }
525 
checkCustomFramebufferNonZeroPixels(int fboWidth,int fboHeight,int skipX,int skipY,int skipWidth,int skipHeight,const GLColor & skip)526 void RobustResourceInitTest::checkCustomFramebufferNonZeroPixels(int fboWidth,
527                                                                  int fboHeight,
528                                                                  int skipX,
529                                                                  int skipY,
530                                                                  int skipWidth,
531                                                                  int skipHeight,
532                                                                  const GLColor &skip)
533 {
534     std::vector<GLColor> data(fboWidth * fboHeight);
535     glReadPixels(0, 0, fboWidth, fboHeight, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
536 
537     int k = 0;
538     for (int y = 0; y < fboHeight; ++y)
539     {
540         for (int x = 0; x < fboWidth; ++x)
541         {
542             int index = (y * fboWidth + x);
543             if (x >= skipX && x < skipX + skipWidth && y >= skipY && y < skipY + skipHeight)
544             {
545                 ASSERT_EQ(skip, data[index]) << " at pixel " << x << ", " << y;
546             }
547             else
548             {
549                 k += (data[index] != GLColor::transparentBlack) ? 1 : 0;
550             }
551         }
552     }
553 
554     EXPECT_EQ(0, k);
555 }
556 
557 // Reading an uninitialized texture (texImage2D) should succeed with all bytes set to 0.
TEST_P(RobustResourceInitTest,ReadingUninitializedTexture)558 TEST_P(RobustResourceInitTest, ReadingUninitializedTexture)
559 {
560     ANGLE_SKIP_TEST_IF(!hasGLExtension());
561 
562     GLTexture tex;
563     setupTexture(&tex);
564     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
565     checkNonZeroPixels(&tex, 0, 0, 0, 0, GLColor::transparentBlack);
566     EXPECT_GL_NO_ERROR();
567 }
568 
569 // Test that calling glTexImage2D multiple times with the same size and no data resets all texture
570 // data
TEST_P(RobustResourceInitTest,ReuploadingClearsTexture)571 TEST_P(RobustResourceInitTest, ReuploadingClearsTexture)
572 {
573     ANGLE_SKIP_TEST_IF(!hasGLExtension());
574 
575     // crbug.com/826576
576     ANGLE_SKIP_TEST_IF(IsOSX() && IsNVIDIA() && IsDesktopOpenGL());
577 
578     // Put some data into the texture
579     std::array<GLColor, kWidth * kHeight> data;
580     data.fill(GLColor::white);
581 
582     GLTexture tex;
583     glBindTexture(GL_TEXTURE_2D, tex);
584     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
585                  data.data());
586 
587     // Reset the texture
588     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
589     checkNonZeroPixels(&tex, 0, 0, 0, 0, GLColor::transparentBlack);
590     EXPECT_GL_NO_ERROR();
591 }
592 
593 // Cover the case where null pixel data is uploaded to a texture and then sub image is used to
594 // upload partial data
TEST_P(RobustResourceInitTest,TexImageThenSubImage)595 TEST_P(RobustResourceInitTest, TexImageThenSubImage)
596 {
597     ANGLE_SKIP_TEST_IF(!hasGLExtension());
598 
599     // http://anglebug.com/2407, but only fails on Nexus devices
600     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
601 
602     // Put some data into the texture
603     GLTexture tex;
604     glBindTexture(GL_TEXTURE_2D, tex);
605     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
606 
607     // Force the D3D texture to create a storage
608     checkNonZeroPixels(&tex, 0, 0, 0, 0, GLColor::transparentBlack);
609 
610     glBindTexture(GL_TEXTURE_2D, tex);
611     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
612 
613     std::array<GLColor, kWidth * kHeight> data;
614     data.fill(GLColor::white);
615 
616     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth / 2, kHeight / 2, GL_RGBA, GL_UNSIGNED_BYTE,
617                     data.data());
618     checkNonZeroPixels(&tex, 0, 0, kWidth / 2, kHeight / 2, GLColor::white);
619     EXPECT_GL_NO_ERROR();
620 }
621 
622 // Reading an uninitialized texture (texImage3D) should succeed with all bytes set to 0.
TEST_P(RobustResourceInitTestES3,ReadingUninitialized3DTexture)623 TEST_P(RobustResourceInitTestES3, ReadingUninitialized3DTexture)
624 {
625     ANGLE_SKIP_TEST_IF(!hasGLExtension());
626 
627     GLTexture tex;
628     setup3DTexture(&tex);
629     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, kWidth, kHeight, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
630                  nullptr);
631     checkNonZeroPixels3D(&tex, 0, 0, 0, 0, 0, GLColor::transparentBlack);
632     EXPECT_GL_NO_ERROR();
633 }
634 
635 // Copy of the copytexsubimage3d_texture_wrongly_initialized test that is part of the WebGL2
636 // conformance suite: copy-texture-image-webgl-specific.html
TEST_P(RobustResourceInitTestES3,CopyTexSubImage3DTextureWronglyInitialized)637 TEST_P(RobustResourceInitTestES3, CopyTexSubImage3DTextureWronglyInitialized)
638 {
639     ANGLE_SKIP_TEST_IF(!hasGLExtension());
640 
641     constexpr GLint kTextureLayer     = 0;
642     constexpr GLint kTextureWidth     = 2;
643     constexpr GLint kTextureHeight    = 2;
644     constexpr GLint kTextureDepth     = 2;
645     constexpr size_t kTextureDataSize = kTextureWidth * kTextureHeight * 4;
646 
647     GLTexture texture2D;
648     glBindTexture(GL_TEXTURE_2D, texture2D);
649     constexpr std::array<uint8_t, kTextureDataSize> data = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
650                                                              0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
651                                                              0x0D, 0x0E, 0x0F, 0x10}};
652     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0, GL_RGBA,
653                  GL_UNSIGNED_BYTE, data.data());
654 
655     GLFramebuffer fbo;
656     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
657     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2D, 0);
658     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
659 
660     GLTexture texture3D;
661     glBindTexture(GL_TEXTURE_3D, texture3D);
662     glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA8, kTextureWidth, kTextureHeight, kTextureDepth);
663     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, kTextureLayer, 0, 0, kTextureWidth, kTextureHeight);
664 
665     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0, kTextureLayer);
666     std::array<uint8_t, kTextureDataSize> pixels;
667     glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
668     ASSERT_GL_NO_ERROR();
669     EXPECT_EQ(data, pixels);
670 }
671 
672 // Test that binding an EGL surface to a texture does not cause it to be cleared.
TEST_P(RobustResourceInitTestES3,BindTexImage)673 TEST_P(RobustResourceInitTestES3, BindTexImage)
674 {
675     ANGLE_SKIP_TEST_IF(!hasGLExtension());
676 
677     EGLWindow *window  = getEGLWindow();
678     EGLSurface surface = window->getSurface();
679     EGLDisplay display = window->getDisplay();
680     EGLConfig config   = window->getConfig();
681     EGLContext context = window->getContext();
682 
683     EGLint surfaceType = 0;
684     eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
685     // Test skipped because EGL config cannot be used to create pbuffers.
686     ANGLE_SKIP_TEST_IF((surfaceType & EGL_PBUFFER_BIT) == 0);
687 
688     EGLint bindToSurfaceRGBA = 0;
689     eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_RGBA, &bindToSurfaceRGBA);
690     // Test skipped because EGL config cannot be used to create pbuffers.
691     ANGLE_SKIP_TEST_IF(bindToSurfaceRGBA == EGL_FALSE);
692 
693     EGLint attribs[] = {
694         EGL_WIDTH,          32,
695         EGL_HEIGHT,         32,
696         EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
697         EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
698         EGL_NONE,
699     };
700 
701     EGLSurface pbuffer = eglCreatePbufferSurface(display, config, attribs);
702     ASSERT_NE(EGL_NO_SURFACE, pbuffer);
703 
704     // Clear the pbuffer
705     eglMakeCurrent(display, pbuffer, pbuffer, context);
706     GLColor clearColor = GLColor::magenta;
707     glClearColor(clearColor.R, clearColor.G, clearColor.B, clearColor.A);
708     glClear(GL_COLOR_BUFFER_BIT);
709     EXPECT_PIXEL_COLOR_EQ(0, 0, clearColor);
710 
711     // Bind the pbuffer to a texture and read its color
712     eglMakeCurrent(display, surface, surface, context);
713 
714     GLTexture texture;
715     glBindTexture(GL_TEXTURE_2D, texture);
716     eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
717 
718     GLFramebuffer fbo;
719     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
720     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
721     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
722     {
723         EXPECT_PIXEL_COLOR_EQ(0, 0, clearColor);
724     }
725     else
726     {
727         std::cout << "Read pixels check skipped because framebuffer was not complete." << std::endl;
728     }
729 
730     eglDestroySurface(display, pbuffer);
731 }
732 
733 // Tests that drawing with an uninitialized Texture works as expected.
TEST_P(RobustResourceInitTest,DrawWithTexture)734 TEST_P(RobustResourceInitTest, DrawWithTexture)
735 {
736     ANGLE_SKIP_TEST_IF(!hasGLExtension());
737 
738     GLTexture texture;
739     glBindTexture(GL_TEXTURE_2D, texture);
740     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
741     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
742     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
743 
744     constexpr char kVS[] =
745         "attribute vec2 position;\n"
746         "varying vec2 texCoord;\n"
747         "void main() {\n"
748         "    gl_Position = vec4(position, 0, 1);\n"
749         "    texCoord = (position * 0.5) + 0.5;\n"
750         "}";
751     constexpr char kFS[] =
752         "precision mediump float;\n"
753         "varying vec2 texCoord;\n"
754         "uniform sampler2D tex;\n"
755         "void main() {\n"
756         "    gl_FragColor = texture2D(tex, texCoord);\n"
757         "}";
758 
759     ANGLE_GL_PROGRAM(program, kVS, kFS);
760     drawQuad(program, "position", 0.5f);
761 
762     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
763 }
764 
765 // Tests that drawing with an uninitialized mipped texture works as expected.
TEST_P(RobustResourceInitTestES3,DrawWithMippedTexture)766 TEST_P(RobustResourceInitTestES3, DrawWithMippedTexture)
767 {
768     ANGLE_SKIP_TEST_IF(!hasGLExtension());
769 
770     GLTexture texture;
771     glBindTexture(GL_TEXTURE_2D, texture);
772     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
773     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kWidth / 2, kHeight / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
774                  nullptr);
775     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, kWidth / 4, kHeight / 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
776                  nullptr);
777     glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, kWidth / 8, kHeight / 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
778                  nullptr);
779     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
780     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
781     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
782     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
783 
784     EXPECT_GL_NO_ERROR();
785 
786     constexpr char kVS[] =
787         "attribute vec2 position;\n"
788         "varying vec2 texCoord;\n"
789         "void main() {\n"
790         "    gl_Position = vec4(position, 0, 1);\n"
791         "    texCoord = (position * 0.5) + 0.5;\n"
792         "}";
793     constexpr char kFS[] =
794         "precision mediump float;\n"
795         "varying vec2 texCoord;\n"
796         "uniform sampler2D tex;\n"
797         "void main() {\n"
798         "    gl_FragColor = texture2D(tex, texCoord);\n"
799         "}";
800 
801     ANGLE_GL_PROGRAM(program, kVS, kFS);
802     drawQuad(program, "position", 0.5f);
803 
804     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
805 }
806 
807 // Reading a partially initialized texture (texImage2D) should succeed with all uninitialized bytes
808 // set to 0 and initialized bytes untouched.
TEST_P(RobustResourceInitTest,ReadingPartiallyInitializedTexture)809 TEST_P(RobustResourceInitTest, ReadingPartiallyInitializedTexture)
810 {
811     ANGLE_SKIP_TEST_IF(!hasGLExtension());
812 
813     // http://anglebug.com/2407, but only fails on Nexus devices
814     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
815 
816     GLTexture tex;
817     setupTexture(&tex);
818     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
819     GLColor data(108, 72, 36, 9);
820     glTexSubImage2D(GL_TEXTURE_2D, 0, kWidth / 2, kHeight / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
821                     &data.R);
822     checkNonZeroPixels(&tex, kWidth / 2, kHeight / 2, 1, 1, data);
823     EXPECT_GL_NO_ERROR();
824 }
825 
826 // Uninitialized parts of textures initialized via copyTexImage2D should have all bytes set to 0.
TEST_P(RobustResourceInitTest,UninitializedPartsOfCopied2DTexturesAreBlack)827 TEST_P(RobustResourceInitTest, UninitializedPartsOfCopied2DTexturesAreBlack)
828 {
829     ANGLE_SKIP_TEST_IF(!hasGLExtension());
830 
831     GLTexture tex;
832     setupTexture(&tex);
833     GLFramebuffer fbo;
834     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
835     GLRenderbuffer rbo;
836     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
837     constexpr int fboWidth  = 16;
838     constexpr int fboHeight = 16;
839     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboWidth, fboHeight);
840     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
841     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
842     glClearColor(1.0, 0.0, 0.0, 1.0);
843     glClear(GL_COLOR_BUFFER_BIT);
844     EXPECT_GL_NO_ERROR();
845     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kWidth, kHeight, 0);
846     checkNonZeroPixels(&tex, 0, 0, fboWidth, fboHeight, GLColor::red);
847     EXPECT_GL_NO_ERROR();
848 }
849 
850 // Reading an uninitialized portion of a texture (copyTexImage2D with negative x and y) should
851 // succeed with all bytes set to 0. Regression test for a bug where the zeroing out of the
852 // texture was done via the same code path as glTexImage2D, causing the PIXEL_UNPACK_BUFFER
853 // to be used.
TEST_P(RobustResourceInitTestES3,ReadingOutOfBoundsCopiedTextureWithUnpackBuffer)854 TEST_P(RobustResourceInitTestES3, ReadingOutOfBoundsCopiedTextureWithUnpackBuffer)
855 {
856     ANGLE_SKIP_TEST_IF(!hasGLExtension());
857     // TODO(geofflang@chromium.org): CopyTexImage from GL_RGBA4444 to GL_ALPHA fails when looking
858     // up which resulting format the texture should have.
859     ANGLE_SKIP_TEST_IF(IsOpenGL());
860 
861     // GL_ALPHA texture can't be read with glReadPixels, for convenience this test uses
862     // glCopyTextureCHROMIUM to copy GL_ALPHA into GL_RGBA
863     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_copy_texture"));
864 
865     GLFramebuffer fbo;
866     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
867     GLRenderbuffer rbo;
868     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
869     constexpr int fboWidth  = 16;
870     constexpr int fboHeight = 16;
871     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboWidth, fboHeight);
872     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
873     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
874     glClearColor(1.0, 0.0, 0.0, 1.0);
875     glClear(GL_COLOR_BUFFER_BIT);
876     EXPECT_GL_NO_ERROR();
877     constexpr int x = -8;
878     constexpr int y = -8;
879 
880     GLBuffer buffer;
881     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
882     std::vector<GLColor> bunchOfGreen(fboWidth * fboHeight, GLColor::green);
883     glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(bunchOfGreen), bunchOfGreen.data(), GL_STATIC_DRAW);
884     EXPECT_GL_NO_ERROR();
885 
886     // Use non-multiple-of-4 dimensions to make sure unpack alignment is set in the backends
887     // (http://crbug.com/836131)
888     constexpr int kTextureWidth  = 127;
889     constexpr int kTextureHeight = 127;
890 
891     // Use GL_ALPHA to force a CPU readback in the D3D11 backend
892     GLTexture texAlpha;
893     glBindTexture(GL_TEXTURE_2D, texAlpha);
894     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, x, y, kTextureWidth, kTextureHeight, 0);
895     EXPECT_GL_NO_ERROR();
896 
897     // GL_ALPHA cannot be glReadPixels, so copy into a GL_RGBA texture
898     GLTexture texRGBA;
899     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
900     setupTexture(&texRGBA);
901     glCopyTextureCHROMIUM(texAlpha, 0, GL_TEXTURE_2D, texRGBA, 0, GL_RGBA, GL_UNSIGNED_BYTE,
902                           GL_FALSE, GL_FALSE, GL_FALSE);
903     EXPECT_GL_NO_ERROR();
904 
905     checkNonZeroPixels(&texRGBA, -x, -y, fboWidth, fboHeight, GLColor(0, 0, 0, 255));
906     EXPECT_GL_NO_ERROR();
907 }
908 
909 // Reading an uninitialized portion of a texture (copyTexImage2D with negative x and y) should
910 // succeed with all bytes set to 0.
TEST_P(RobustResourceInitTest,ReadingOutOfBoundsCopiedTexture)911 TEST_P(RobustResourceInitTest, ReadingOutOfBoundsCopiedTexture)
912 {
913     ANGLE_SKIP_TEST_IF(!hasGLExtension());
914 
915     GLTexture tex;
916     setupTexture(&tex);
917     GLFramebuffer fbo;
918     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
919     GLRenderbuffer rbo;
920     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
921     constexpr int fboWidth  = 16;
922     constexpr int fboHeight = 16;
923     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboWidth, fboHeight);
924     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
925     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
926     glClearColor(1.0, 0.0, 0.0, 1.0);
927     glClear(GL_COLOR_BUFFER_BIT);
928     EXPECT_GL_NO_ERROR();
929     constexpr int x = -8;
930     constexpr int y = -8;
931     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, kWidth, kHeight, 0);
932     checkNonZeroPixels(&tex, -x, -y, fboWidth, fboHeight, GLColor::red);
933     EXPECT_GL_NO_ERROR();
934 }
935 
936 // Tests resources are initialized properly with multisample resolve.
TEST_P(RobustResourceInitTestES3,MultisampledDepthInitializedCorrectly)937 TEST_P(RobustResourceInitTestES3, MultisampledDepthInitializedCorrectly)
938 {
939     ANGLE_SKIP_TEST_IF(!hasGLExtension());
940 
941     // http://anglebug.com/2407
942     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
943 
944     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
945 
946     // Make the destination non-multisampled depth FBO.
947     GLTexture color;
948     glBindTexture(GL_TEXTURE_2D, color);
949     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
950 
951     GLRenderbuffer depth;
952     glBindRenderbuffer(GL_RENDERBUFFER, depth);
953     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kWidth, kHeight);
954 
955     GLFramebuffer fbo;
956     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
957     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
958     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
959     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
960 
961     glClearColor(0, 1, 0, 1);
962     glClearDepthf(0);
963     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
964     ASSERT_GL_NO_ERROR();
965     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
966 
967     // Make the multisampled depth FBO.
968     GLRenderbuffer msDepth;
969     glBindRenderbuffer(GL_RENDERBUFFER, msDepth);
970     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, kWidth, kHeight);
971 
972     GLFramebuffer msFBO;
973     glBindFramebuffer(GL_READ_FRAMEBUFFER, msFBO);
974     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msDepth);
975     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
976 
977     // Multisample resolve.
978     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
979                       GL_NEAREST);
980     ASSERT_GL_NO_ERROR();
981 
982     // Test drawing with the resolved depth buffer.
983     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
984     glDepthMask(GL_FALSE);
985     glEnable(GL_DEPTH_TEST);
986     glDepthFunc(GL_EQUAL);
987     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
988     ASSERT_GL_NO_ERROR();
989     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
990 }
991 
992 // Basic test that textures are initialized correctly.
TEST_P(RobustResourceInitTest,Texture)993 TEST_P(RobustResourceInitTest, Texture)
994 {
995     ANGLE_SKIP_TEST_IF(!hasGLExtension());
996 
997     GLTexture texture;
998     glBindTexture(GL_TEXTURE_2D, texture);
999     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1000 
1001     GLFramebuffer framebuffer;
1002     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1003     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1004     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
1005 
1006     GLint initState = 0;
1007     glBindTexture(GL_TEXTURE_2D, texture);
1008     glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
1009     EXPECT_GL_TRUE(initState);
1010 }
1011 
1012 // Test that uploading texture data with an unpack state set correctly initializes the texture and
1013 // the data is uploaded correctly.
TEST_P(RobustResourceInitTest,TextureWithUnpackState)1014 TEST_P(RobustResourceInitTest, TextureWithUnpackState)
1015 {
1016     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1017 
1018     // GL_UNPACK_ROW_LENGTH requires ES 3.0 or GL_EXT_unpack_subimage
1019     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
1020                        !EnsureGLExtensionEnabled("GL_EXT_unpack_subimage"));
1021 
1022     GLTexture texture;
1023     glBindTexture(GL_TEXTURE_2D, texture);
1024     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1025 
1026     // Upload a 2x2 rect using GL_UNPACK_ROW_LENGTH=4
1027     GLColor colorData[8] = {
1028         GLColor::green, GLColor::green, GLColor::red, GLColor::red,
1029         GLColor::green, GLColor::green, GLColor::red, GLColor::red,
1030     };
1031     glPixelStorei(GL_UNPACK_ROW_LENGTH, 4);
1032     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorData);
1033 
1034     GLFramebuffer framebuffer;
1035     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1036     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1037 
1038     checkFramebufferNonZeroPixels(0, 0, 2, 2, GLColor::green);
1039 }
1040 
1041 template <typename PixelT>
testIntegerTextureInit(const char * samplerType,GLenum internalFormatRGBA,GLenum internalFormatRGB,GLenum type)1042 void RobustResourceInitTestES3::testIntegerTextureInit(const char *samplerType,
1043                                                        GLenum internalFormatRGBA,
1044                                                        GLenum internalFormatRGB,
1045                                                        GLenum type)
1046 {
1047     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1048 
1049     std::string fs = GetSimpleTextureFragmentShader(samplerType);
1050 
1051     ANGLE_GL_PROGRAM(program, kSimpleTextureVertexShader, fs.c_str());
1052 
1053     // Make an RGBA framebuffer.
1054     GLTexture framebufferTexture;
1055     glBindTexture(GL_TEXTURE_2D, framebufferTexture);
1056     glTexImage2D(GL_TEXTURE_2D, 0, internalFormatRGBA, kWidth, kHeight, 0, GL_RGBA_INTEGER, type,
1057                  nullptr);
1058     ASSERT_GL_NO_ERROR();
1059 
1060     GLFramebuffer framebuffer;
1061     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1062     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferTexture,
1063                            0);
1064 
1065     // Make an RGB texture.
1066     GLTexture texture;
1067     glBindTexture(GL_TEXTURE_2D, texture);
1068     glTexImage2D(GL_TEXTURE_2D, 0, internalFormatRGB, kWidth, kHeight, 0, GL_RGB_INTEGER, type,
1069                  nullptr);
1070     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1071     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1072     ASSERT_GL_NO_ERROR();
1073 
1074     // Blit from the texture to the framebuffer.
1075     drawQuad(program, "position", 0.5f);
1076 
1077     // Verify both textures have been initialized
1078     {
1079         GLint initState = 0;
1080         glBindTexture(GL_TEXTURE_2D, framebufferTexture);
1081         glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
1082         EXPECT_GL_TRUE(initState);
1083     }
1084     {
1085         GLint initState = 0;
1086         glBindTexture(GL_TEXTURE_2D, texture);
1087         glGetTexParameteriv(GL_TEXTURE_2D, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
1088         EXPECT_GL_TRUE(initState);
1089     }
1090 
1091     std::array<PixelT, kWidth * kHeight * 4> data;
1092     glReadPixels(0, 0, kWidth, kHeight, GL_RGBA_INTEGER, type, data.data());
1093 
1094     // Check the color channels are zero and the alpha channel is 1.
1095     int incorrectPixels = 0;
1096     for (int y = 0; y < kHeight; ++y)
1097     {
1098         for (int x = 0; x < kWidth; ++x)
1099         {
1100             int index    = (y * kWidth + x) * 4;
1101             bool correct = (data[index] == 0 && data[index + 1] == 0 && data[index + 2] == 0 &&
1102                             data[index + 3] == 1);
1103             incorrectPixels += (!correct ? 1 : 0);
1104         }
1105     }
1106 
1107     ASSERT_GL_NO_ERROR();
1108     EXPECT_EQ(0, incorrectPixels);
1109 }
1110 
1111 // Simple tests for integer formats that ANGLE must emulate on D3D11.
TEST_P(RobustResourceInitTestES3,TextureInit_UIntRGB8)1112 TEST_P(RobustResourceInitTestES3, TextureInit_UIntRGB8)
1113 {
1114     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1115     testIntegerTextureInit<uint8_t>("u", GL_RGBA8UI, GL_RGB8UI, GL_UNSIGNED_BYTE);
1116 }
1117 
TEST_P(RobustResourceInitTestES3,TextureInit_UIntRGB32)1118 TEST_P(RobustResourceInitTestES3, TextureInit_UIntRGB32)
1119 {
1120     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1121     testIntegerTextureInit<uint32_t>("u", GL_RGBA32UI, GL_RGB32UI, GL_UNSIGNED_INT);
1122 }
1123 
TEST_P(RobustResourceInitTestES3,TextureInit_IntRGB8)1124 TEST_P(RobustResourceInitTestES3, TextureInit_IntRGB8)
1125 {
1126     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1127     testIntegerTextureInit<int8_t>("i", GL_RGBA8I, GL_RGB8I, GL_BYTE);
1128 }
1129 
TEST_P(RobustResourceInitTestES3,TextureInit_IntRGB32)1130 TEST_P(RobustResourceInitTestES3, TextureInit_IntRGB32)
1131 {
1132     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1133     testIntegerTextureInit<int32_t>("i", GL_RGBA32I, GL_RGB32I, GL_INT);
1134 }
1135 
1136 // Test that uninitialized image texture works well.
TEST_P(RobustResourceInitTestES31,ImageTextureInit_R32UI)1137 TEST_P(RobustResourceInitTestES31, ImageTextureInit_R32UI)
1138 {
1139     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1140     constexpr char kCS[] =
1141         R"(#version 310 es
1142         layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1143         layout(r32ui, binding = 1) writeonly uniform highp uimage2D writeImage;
1144         void main()
1145         {
1146             imageStore(writeImage, ivec2(gl_LocalInvocationID.xy), uvec4(200u));
1147         })";
1148 
1149     GLTexture texture;
1150     // Don't upload data to texture.
1151     glBindTexture(GL_TEXTURE_2D, texture);
1152     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1153     EXPECT_GL_NO_ERROR();
1154 
1155     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1156     glUseProgram(program.get());
1157 
1158     glBindImageTexture(1, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1159 
1160     glDispatchCompute(1, 1, 1);
1161     EXPECT_GL_NO_ERROR();
1162 
1163     GLFramebuffer framebuffer;
1164     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1165     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1166 
1167     GLuint outputValue;
1168     glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
1169     EXPECT_GL_NO_ERROR();
1170 
1171     EXPECT_EQ(200u, outputValue);
1172 
1173     outputValue = 0u;
1174     // Write to another uninitialized texture.
1175     GLTexture texture2;
1176     glBindTexture(GL_TEXTURE_2D, texture2);
1177     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1178     EXPECT_GL_NO_ERROR();
1179     glBindImageTexture(1, texture2, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1180     glDispatchCompute(1, 1, 1);
1181     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
1182     glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
1183     EXPECT_EQ(200u, outputValue);
1184 }
1185 
1186 // Basic test that renderbuffers are initialized correctly.
TEST_P(RobustResourceInitTest,Renderbuffer)1187 TEST_P(RobustResourceInitTest, Renderbuffer)
1188 {
1189     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1190 
1191     GLRenderbuffer renderbuffer;
1192     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1193     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
1194 
1195     GLFramebuffer framebuffer;
1196     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1197     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
1198 
1199     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
1200 }
1201 
1202 // Tests creating mipmaps with robust resource init.
TEST_P(RobustResourceInitTestES3,GenerateMipmap)1203 TEST_P(RobustResourceInitTestES3, GenerateMipmap)
1204 {
1205     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1206 
1207     constexpr GLint kTextureSize = 16;
1208 
1209     // Initialize a 16x16 RGBA8 texture with no data.
1210     GLTexture tex;
1211     glBindTexture(GL_TEXTURE_2D, tex);
1212     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA,
1213                  GL_UNSIGNED_BYTE, nullptr);
1214     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1215     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1216 
1217     std::string shader = GetSimpleTextureFragmentShader("");
1218     ANGLE_GL_PROGRAM(program, kSimpleTextureVertexShader, shader.c_str());
1219 
1220     // Generate mipmaps and verify all the mips.
1221     glGenerateMipmap(GL_TEXTURE_2D);
1222     ASSERT_GL_NO_ERROR();
1223 
1224     // Validate a small texture.
1225     glClearColor(1, 0, 0, 1);
1226     glClear(GL_COLOR_BUFFER_BIT);
1227     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1228 
1229     // Set viewport to resize the texture and draw.
1230     glViewport(0, 0, 2, 2);
1231     drawQuad(program, "position", 0.5f);
1232     ASSERT_GL_NO_ERROR();
1233     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1234 }
1235 
1236 // Tests creating mipmaps with robust resource init multiple times.
TEST_P(RobustResourceInitTestES3,GenerateMipmapAfterRedefine)1237 TEST_P(RobustResourceInitTestES3, GenerateMipmapAfterRedefine)
1238 {
1239     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1240 
1241     constexpr GLint kTextureSize = 16;
1242     const std::vector<GLColor> kInitData(kTextureSize * kTextureSize, GLColor::blue);
1243 
1244     // Initialize a 16x16 RGBA8 texture with blue.
1245     GLTexture tex;
1246     glBindTexture(GL_TEXTURE_2D, tex);
1247     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA,
1248                  GL_UNSIGNED_BYTE, kInitData.data());
1249     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1250     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1251 
1252     std::string shader = GetSimpleTextureFragmentShader("");
1253     ANGLE_GL_PROGRAM(program, kSimpleTextureVertexShader, shader.c_str());
1254 
1255     // Generate mipmaps.
1256     glGenerateMipmap(GL_TEXTURE_2D);
1257     ASSERT_GL_NO_ERROR();
1258 
1259     // Validate a small mip.
1260     glClearColor(1, 0, 0, 1);
1261     glClear(GL_COLOR_BUFFER_BIT);
1262     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1263 
1264     // Set viewport to resize the texture and draw.
1265     glViewport(0, 0, 2, 2);
1266     drawQuad(program, "position", 0.5f);
1267     ASSERT_GL_NO_ERROR();
1268     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1269 
1270     // Redefine mip 0 with no data.
1271     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA,
1272                  GL_UNSIGNED_BYTE, nullptr);
1273 
1274     // Generate mipmaps again.  Mip 0 must be cleared before the mipmaps are regenerated.
1275     glGenerateMipmap(GL_TEXTURE_2D);
1276     EXPECT_GL_NO_ERROR();
1277 
1278     // Validate a small mip.
1279     glClearColor(1, 0, 0, 1);
1280     glClear(GL_COLOR_BUFFER_BIT);
1281     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1282 
1283     glViewport(0, 0, 2, 2);
1284     drawQuad(program, "position", 0.5f);
1285     ASSERT_GL_NO_ERROR();
1286     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1287 }
1288 
1289 // Tests creating mipmaps for cube maps with robust resource init.
TEST_P(RobustResourceInitTestES3,GenerateMipmapCubeMap)1290 TEST_P(RobustResourceInitTestES3, GenerateMipmapCubeMap)
1291 {
1292     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1293 
1294     constexpr GLint kTextureSize   = 16;
1295     constexpr GLint kTextureLevels = 5;
1296 
1297     // Initialize a 16x16 RGBA8 texture with no data.
1298     GLTexture tex;
1299     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1300     for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1301          ++target)
1302     {
1303         glTexImage2D(target, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1304                      nullptr);
1305     }
1306     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1307     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1308 
1309     // Generate mipmaps and verify all the mips.
1310     glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
1311     ASSERT_GL_NO_ERROR();
1312 
1313     GLFramebuffer fbo;
1314     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1315     for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1316          ++target)
1317     {
1318         for (GLint level = 0; level < kTextureLevels; ++level)
1319         {
1320             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, tex, level);
1321             EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1322         }
1323     }
1324 }
1325 
1326 // Test blitting a framebuffer out-of-bounds. Multiple iterations.
TEST_P(RobustResourceInitTestES3,BlitFramebufferOutOfBounds)1327 TEST_P(RobustResourceInitTestES3, BlitFramebufferOutOfBounds)
1328 {
1329     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1330 
1331     // http://anglebug.com/2408
1332     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD());
1333 
1334     // Initiate data to read framebuffer
1335     constexpr int size                = 8;
1336     constexpr GLenum readbufferFormat = GL_RGBA8;
1337     constexpr GLenum drawbufferFormat = GL_RGBA8;
1338     constexpr GLenum filter           = GL_NEAREST;
1339 
1340     std::vector<GLColor> readColors(size * size, GLColor::yellow);
1341 
1342     // Create read framebuffer and feed data to read buffer
1343     // Read buffer may have srgb image
1344     GLTexture tex_read;
1345     glBindTexture(GL_TEXTURE_2D, tex_read);
1346     glTexImage2D(GL_TEXTURE_2D, 0, readbufferFormat, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1347                  readColors.data());
1348 
1349     GLFramebuffer fbo_read;
1350     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read);
1351     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_read, 0);
1352 
1353     // Create draw framebuffer. Color in draw buffer is initialized to 0.
1354     // Draw buffer may have srgb image
1355     GLTexture tex_draw;
1356     glBindTexture(GL_TEXTURE_2D, tex_draw);
1357     glTexImage2D(GL_TEXTURE_2D, 0, drawbufferFormat, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1358                  nullptr);
1359 
1360     GLFramebuffer fbo_draw;
1361     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_draw);
1362     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_draw, 0);
1363 
1364     ASSERT_GL_NO_ERROR();
1365     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
1366 
1367     using Region = std::array<int, 4>;
1368 
1369     struct Test
1370     {
1371         constexpr Test(const Region &read, const Region &draw, const Region &real)
1372             : readRegion(read), drawRegion(draw), realRegion(real)
1373         {}
1374 
1375         Region readRegion;
1376         Region drawRegion;
1377         Region realRegion;
1378     };
1379 
1380     constexpr std::array<Test, 2> tests = {{
1381         // only src region is out-of-bounds, dst region has different width/height as src region.
1382         {{{-2, -2, 4, 4}}, {{1, 1, 4, 4}}, {{2, 2, 4, 4}}},
1383         // only src region is out-of-bounds, dst region has the same width/height as src region.
1384         {{{-2, -2, 4, 4}}, {{1, 1, 7, 7}}, {{3, 3, 7, 7}}},
1385     }};
1386 
1387     // Blit read framebuffer to the image in draw framebuffer.
1388     for (const auto &test : tests)
1389     {
1390         // both the read framebuffer and draw framebuffer bounds are [0, 0, 8, 8]
1391         // blitting from src region to dst region
1392         glBindTexture(GL_TEXTURE_2D, tex_draw);
1393         glTexImage2D(GL_TEXTURE_2D, 0, drawbufferFormat, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1394                      nullptr);
1395 
1396         const auto &read = test.readRegion;
1397         const auto &draw = test.drawRegion;
1398         const auto &real = test.realRegion;
1399 
1400         glBlitFramebuffer(read[0], read[1], read[2], read[3], draw[0], draw[1], draw[2], draw[3],
1401                           GL_COLOR_BUFFER_BIT, filter);
1402 
1403         // Read pixels and check the correctness.
1404         std::vector<GLColor> pixels(size * size);
1405         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_draw);
1406         glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1407         glReadPixels(0, 0, size, size, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
1408         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read);
1409         ASSERT_GL_NO_ERROR();
1410 
1411         for (int ii = 0; ii < size; ++ii)
1412         {
1413             for (int jj = 0; jj < size; ++jj)
1414             {
1415                 GLColor expectedColor = GLColor::transparentBlack;
1416                 if (ii >= real[0] && ii < real[2] && jj >= real[1] && jj < real[3])
1417                 {
1418                     expectedColor = GLColor::yellow;
1419                 }
1420 
1421                 int loc = ii * size + jj;
1422                 EXPECT_EQ(expectedColor, pixels[loc]) << " at [" << jj << ", " << ii << "]";
1423             }
1424         }
1425     }
1426 }
1427 
1428 template <typename ClearFunc>
maskedDepthClear(ClearFunc clearFunc)1429 void RobustResourceInitTest::maskedDepthClear(ClearFunc clearFunc)
1430 {
1431     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1432 
1433     constexpr int kSize = 16;
1434 
1435     // Initialize a FBO with depth and simple color.
1436     GLRenderbuffer depthbuffer;
1437     glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
1438     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kSize, kSize);
1439 
1440     GLTexture colorbuffer;
1441     glBindTexture(GL_TEXTURE_2D, colorbuffer);
1442     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1443 
1444     GLFramebuffer framebuffer;
1445     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1446     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1447     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer);
1448 
1449     ASSERT_GL_NO_ERROR();
1450     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1451 
1452     // Disable depth writes and trigger a clear.
1453     glDepthMask(GL_FALSE);
1454 
1455     clearFunc(0.5f);
1456     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1457 
1458     // Draw red with a depth function that checks for the clear value.
1459     glEnable(GL_DEPTH_TEST);
1460     glDepthFunc(GL_EQUAL);
1461 
1462     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1463 
1464     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1465     ASSERT_GL_NO_ERROR();
1466     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black) << "depth should not be 0.5f";
1467 
1468     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
1469     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "depth should be initialized to 1.0f";
1470 }
1471 
1472 // Test that clearing a masked depth buffer doesn't mark it clean.
TEST_P(RobustResourceInitTest,MaskedDepthClear)1473 TEST_P(RobustResourceInitTest, MaskedDepthClear)
1474 {
1475     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1476 
1477     // http://anglebug.com/2407
1478     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1479 
1480     auto clearFunc = [](float depth) {
1481         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1482         glClearDepthf(depth);
1483         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1484     };
1485 
1486     maskedDepthClear(clearFunc);
1487 }
1488 
1489 // Tests the same as MaskedDepthClear, but using ClearBuffer calls.
TEST_P(RobustResourceInitTestES3,MaskedDepthClearBuffer)1490 TEST_P(RobustResourceInitTestES3, MaskedDepthClearBuffer)
1491 {
1492     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1493 
1494     // http://anglebug.com/2407
1495     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1496 
1497     auto clearFunc = [](float depth) {
1498         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1499         glClear(GL_COLOR_BUFFER_BIT);
1500         glClearBufferfv(GL_DEPTH, 0, &depth);
1501     };
1502 
1503     maskedDepthClear(clearFunc);
1504 }
1505 
1506 template <typename ClearFunc>
maskedStencilClear(ClearFunc clearFunc)1507 void RobustResourceInitTest::maskedStencilClear(ClearFunc clearFunc)
1508 {
1509     constexpr int kSize = 16;
1510 
1511     // Initialize a FBO with stencil and simple color.
1512     GLRenderbuffer stencilbuffer;
1513     glBindRenderbuffer(GL_RENDERBUFFER, stencilbuffer);
1514     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, kSize, kSize);
1515 
1516     GLTexture colorbuffer;
1517     glBindTexture(GL_TEXTURE_2D, colorbuffer);
1518     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1519 
1520     GLFramebuffer framebuffer;
1521     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1522     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1523     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1524                               stencilbuffer);
1525 
1526     ASSERT_GL_NO_ERROR();
1527     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1528 
1529     // Disable stencil writes and trigger a clear. Use a tricky mask that does not overlap the
1530     // clear.
1531     glStencilMask(0xF0);
1532     clearFunc(0x0F);
1533     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1534 
1535     // Draw red with a stencil function that checks for stencil == 0
1536     glEnable(GL_STENCIL_TEST);
1537     glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1538     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1539 
1540     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1541 
1542     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1543     ASSERT_GL_NO_ERROR();
1544     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "stencil should be equal to zero";
1545 }
1546 
1547 // Test that clearing a masked stencil buffer doesn't mark it clean.
TEST_P(RobustResourceInitTest,MaskedStencilClear)1548 TEST_P(RobustResourceInitTest, MaskedStencilClear)
1549 {
1550     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1551     ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
1552 
1553     // http://anglebug.com/2407, but only fails on Nexus devices
1554     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
1555 
1556     auto clearFunc = [](GLint clearValue) {
1557         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1558         glClearStencil(clearValue);
1559         glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1560     };
1561 
1562     maskedStencilClear(clearFunc);
1563 }
1564 
1565 // Test that clearing a masked stencil buffer doesn't mark it clean, with ClearBufferi.
TEST_P(RobustResourceInitTestES3,MaskedStencilClearBuffer)1566 TEST_P(RobustResourceInitTestES3, MaskedStencilClearBuffer)
1567 {
1568     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1569 
1570     // http://anglebug.com/2408
1571     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsNVIDIA()));
1572 
1573     ANGLE_SKIP_TEST_IF(IsLinux() && IsOpenGL());
1574 
1575     // http://anglebug.com/2407, but only fails on Nexus devices
1576     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
1577 
1578     auto clearFunc = [](GLint clearValue) {
1579         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1580         glClear(GL_COLOR_BUFFER_BIT);
1581         glClearBufferiv(GL_STENCIL, 0, &clearValue);
1582     };
1583 
1584     maskedStencilClear(clearFunc);
1585 }
1586 
1587 template <int Size, typename InitializedTest>
VerifyRGBA8PixelRect(InitializedTest inInitialized)1588 void VerifyRGBA8PixelRect(InitializedTest inInitialized)
1589 {
1590     std::array<std::array<GLColor, Size>, Size> actualPixels;
1591     glReadPixels(0, 0, Size, Size, GL_RGBA, GL_UNSIGNED_BYTE, actualPixels.data());
1592     ASSERT_GL_NO_ERROR();
1593 
1594     for (int y = 0; y < Size; ++y)
1595     {
1596         for (int x = 0; x < Size; ++x)
1597         {
1598             if (inInitialized(x, y))
1599             {
1600                 EXPECT_EQ(actualPixels[y][x], GLColor::red) << " at " << x << ", " << y;
1601             }
1602             else
1603             {
1604                 EXPECT_EQ(actualPixels[y][x], GLColor::transparentBlack)
1605                     << " at " << x << ", " << y;
1606             }
1607         }
1608     }
1609 }
1610 
1611 // Tests that calling CopyTexSubImage2D will initialize the source & destination.
TEST_P(RobustResourceInitTest,CopyTexSubImage2D)1612 TEST_P(RobustResourceInitTest, CopyTexSubImage2D)
1613 {
1614     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1615     ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
1616 
1617     static constexpr int kDestSize = 4;
1618     constexpr int kSrcSize         = kDestSize / 2;
1619     static constexpr int kOffset   = kSrcSize / 2;
1620 
1621     std::vector<GLColor> redColors(kDestSize * kDestSize, GLColor::red);
1622 
1623     // Initialize source texture with red.
1624     GLTexture srcTexture;
1625     glBindTexture(GL_TEXTURE_2D, srcTexture);
1626     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSrcSize, kSrcSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1627                  redColors.data());
1628 
1629     GLFramebuffer framebuffer;
1630     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1631     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexture, 0);
1632 
1633     ASSERT_GL_NO_ERROR();
1634     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1635 
1636     // Create uninitialized destination texture.
1637     GLTexture destTexture;
1638     glBindTexture(GL_TEXTURE_2D, destTexture);
1639     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kDestSize, kDestSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1640                  nullptr);
1641 
1642     // Trigger the copy from initialized source into uninitialized dest.
1643     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kOffset, kOffset, 0, 0, kSrcSize, kSrcSize);
1644 
1645     // Verify the pixel rectangle.
1646     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0);
1647     ASSERT_GL_NO_ERROR();
1648 
1649     auto srcInitTest = [](int x, int y) {
1650         return (x >= kOffset) && x < (kDestSize - kOffset) && (y >= kOffset) &&
1651                y < (kDestSize - kOffset);
1652     };
1653 
1654     VerifyRGBA8PixelRect<kDestSize>(srcInitTest);
1655 
1656     // Make source texture uninitialized. Force a release by redefining a new size.
1657     glBindTexture(GL_TEXTURE_2D, srcTexture);
1658     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSrcSize, kSrcSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1659                  nullptr);
1660     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexture, 0);
1661 
1662     // Fill destination texture with red.
1663     glBindTexture(GL_TEXTURE_2D, destTexture);
1664     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kDestSize, kDestSize, GL_RGBA, GL_UNSIGNED_BYTE,
1665                     redColors.data());
1666 
1667     // Trigger a copy from uninitialized source into initialized dest.
1668     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kOffset, kOffset, 0, 0, kSrcSize, kSrcSize);
1669 
1670     // Verify the pixel rectangle.
1671     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0);
1672     ASSERT_GL_NO_ERROR();
1673 
1674     auto destInitTest = [srcInitTest](int x, int y) { return !srcInitTest(x, y); };
1675 
1676     VerifyRGBA8PixelRect<kDestSize>(destInitTest);
1677 }
1678 
copyTexSubImage2DCustomFBOTest(int offsetX,int offsetY)1679 void RobustResourceInitTest::copyTexSubImage2DCustomFBOTest(int offsetX, int offsetY)
1680 {
1681     const int texSize = 512;
1682     const int fboSize = 16;
1683 
1684     GLTexture texture;
1685     glBindTexture(GL_TEXTURE_2D, texture.get());
1686     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texSize, texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1687                  nullptr);
1688     ASSERT_GL_NO_ERROR();
1689 
1690     GLRenderbuffer renderbuffer;
1691     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
1692     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboSize, fboSize);
1693     ASSERT_GL_NO_ERROR();
1694 
1695     GLFramebuffer framebuffer;
1696     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1697     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1698                               renderbuffer.get());
1699     ASSERT_GL_NO_ERROR();
1700     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1701 
1702     glClearColor(1.0, 0.0, 0.0, 1.0);
1703     glClear(GL_COLOR_BUFFER_BIT);
1704     ASSERT_GL_NO_ERROR();
1705 
1706     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, offsetX, offsetY, texSize, texSize);
1707     ASSERT_GL_NO_ERROR();
1708 
1709     GLFramebuffer readbackFBO;
1710     glBindFramebuffer(GL_FRAMEBUFFER, readbackFBO.get());
1711     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1712     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1713     checkCustomFramebufferNonZeroPixels(texSize, texSize, -offsetX, -offsetY, fboSize, fboSize,
1714                                         GLColor::red);
1715 }
1716 
1717 // Test CopyTexSubImage2D clipped to size of custom FBO, zero x/y source offset.
TEST_P(RobustResourceInitTest,CopyTexSubImage2DCustomFBOZeroOffsets)1718 TEST_P(RobustResourceInitTest, CopyTexSubImage2DCustomFBOZeroOffsets)
1719 {
1720     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1721     copyTexSubImage2DCustomFBOTest(0, 0);
1722 }
1723 
1724 // Test CopyTexSubImage2D clipped to size of custom FBO, negative x/y source offset.
TEST_P(RobustResourceInitTest,CopyTexSubImage2DCustomFBONegativeOffsets)1725 TEST_P(RobustResourceInitTest, CopyTexSubImage2DCustomFBONegativeOffsets)
1726 {
1727     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1728     copyTexSubImage2DCustomFBOTest(-8, -8);
1729 }
1730 
1731 // Tests that calling CopyTexSubImage3D will initialize the source & destination.
TEST_P(RobustResourceInitTestES3,CopyTexSubImage3D)1732 TEST_P(RobustResourceInitTestES3, CopyTexSubImage3D)
1733 {
1734     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1735 
1736     static constexpr int kDestSize = 4;
1737     constexpr int kSrcSize         = kDestSize / 2;
1738     static constexpr int kOffset   = kSrcSize / 2;
1739 
1740     std::vector<GLColor> redColors(kDestSize * kDestSize * kDestSize, GLColor::red);
1741 
1742     GLTexture srcTexture;
1743     GLFramebuffer framebuffer;
1744     GLTexture destTexture;
1745     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1746 
1747     // Initialize source texture with red.
1748     glBindTexture(GL_TEXTURE_3D, srcTexture);
1749     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kSrcSize, kSrcSize, kSrcSize, 0, GL_RGBA,
1750                  GL_UNSIGNED_BYTE, redColors.data());
1751 
1752     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTexture, 0, 0);
1753 
1754     ASSERT_GL_NO_ERROR();
1755     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1756 
1757     // Create uninitialized destination texture.
1758     glBindTexture(GL_TEXTURE_3D, destTexture);
1759     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kDestSize, kDestSize, kDestSize, 0, GL_RGBA,
1760                  GL_UNSIGNED_BYTE, nullptr);
1761 
1762     // Trigger the copy from initialized source into uninitialized dest.
1763     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, kOffset, kOffset, 0, 0, 0, kSrcSize, kSrcSize);
1764 
1765     // Verify the pixel rectangle.
1766     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destTexture, 0, 0);
1767     ASSERT_GL_NO_ERROR();
1768 
1769     auto srcInitTest = [](int x, int y) {
1770         return (x >= kOffset) && x < (kDestSize - kOffset) && (y >= kOffset) &&
1771                y < (kDestSize - kOffset);
1772     };
1773 
1774     VerifyRGBA8PixelRect<kDestSize>(srcInitTest);
1775 
1776     // Make source texture uninitialized.
1777     glBindTexture(GL_TEXTURE_3D, srcTexture);
1778     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kSrcSize, kSrcSize, kSrcSize, 0, GL_RGBA,
1779                  GL_UNSIGNED_BYTE, nullptr);
1780     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTexture, 0, 0);
1781 
1782     ASSERT_GL_NO_ERROR();
1783     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1784 
1785     // Fill destination texture with red.
1786     glBindTexture(GL_TEXTURE_3D, destTexture);
1787     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kDestSize, kDestSize, kDestSize, 0, GL_RGBA,
1788                  GL_UNSIGNED_BYTE, redColors.data());
1789 
1790     // Trigger a copy from uninitialized source into initialized dest.
1791     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, kOffset, kOffset, 0, 0, 0, kSrcSize, kSrcSize);
1792 
1793     // Verify the pixel rectangle.
1794     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destTexture, 0, 0);
1795     ASSERT_GL_NO_ERROR();
1796 
1797     auto destInitTest = [srcInitTest](int x, int y) { return !srcInitTest(x, y); };
1798 
1799     VerifyRGBA8PixelRect<kDestSize>(destInitTest);
1800 }
1801 
1802 // Test basic robustness with 2D array textures.
TEST_P(RobustResourceInitTestES3,Texture2DArray)1803 TEST_P(RobustResourceInitTestES3, Texture2DArray)
1804 {
1805     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1806 
1807     constexpr int kSize   = 1024;
1808     constexpr int kLayers = 8;
1809 
1810     GLTexture texture;
1811     glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
1812     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kSize, kSize, kLayers, 0, GL_RGBA,
1813                  GL_UNSIGNED_BYTE, nullptr);
1814 
1815     GLFramebuffer framebuffer;
1816     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1817 
1818     for (int layer = 0; layer < kLayers; ++layer)
1819     {
1820         checkNonZeroPixels3D(&texture, 0, 0, 0, 0, layer, GLColor::transparentBlack);
1821     }
1822 }
1823 
1824 // Test that using TexStorage2D followed by CompressedSubImage works with robust init.
1825 // Taken from WebGL test conformance/extensions/webgl-compressed-texture-s3tc.
TEST_P(RobustResourceInitTestES3,CompressedSubImage)1826 TEST_P(RobustResourceInitTestES3, CompressedSubImage)
1827 {
1828     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1829     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
1830 
1831     // http://anglebug.com/4929
1832     // Metal doesn't support robust resource init with compressed textures yet.
1833     ANGLE_SKIP_TEST_IF(IsMetal());
1834 
1835     constexpr int width     = 8;
1836     constexpr int height    = 8;
1837     constexpr int subX0     = 0;
1838     constexpr int subY0     = 0;
1839     constexpr int subWidth  = 4;
1840     constexpr int subHeight = 4;
1841     constexpr GLenum format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1842 
1843     static constexpr uint8_t img_8x8_rgb_dxt1[] = {
1844         0xe0, 0x07, 0x00, 0xf8, 0x11, 0x10, 0x15, 0x00, 0x1f, 0x00, 0xe0,
1845         0xff, 0x11, 0x10, 0x15, 0x00, 0xe0, 0x07, 0x1f, 0xf8, 0x44, 0x45,
1846         0x40, 0x55, 0x1f, 0x00, 0xff, 0x07, 0x44, 0x45, 0x40, 0x55,
1847     };
1848 
1849     static constexpr uint8_t img_4x4_rgb_dxt1[] = {
1850         0xe0, 0x07, 0x00, 0xf8, 0x11, 0x10, 0x15, 0x00,
1851     };
1852 
1853     std::vector<uint8_t> data(img_8x8_rgb_dxt1, img_8x8_rgb_dxt1 + ArraySize(img_8x8_rgb_dxt1));
1854     std::vector<uint8_t> subData(img_4x4_rgb_dxt1, img_4x4_rgb_dxt1 + ArraySize(img_4x4_rgb_dxt1));
1855 
1856     GLTexture colorbuffer;
1857     glBindTexture(GL_TEXTURE_2D, colorbuffer);
1858     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1859 
1860     GLFramebuffer framebuffer;
1861     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1862     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1863     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1864 
1865     glViewport(0, 0, width, height);
1866 
1867     // testing format width-x-height via texStorage2D
1868     const auto &expectedData = UncompressDXTIntoSubRegion(width, height, subX0, subY0, subWidth,
1869                                                           subHeight, subData, format);
1870 
1871     GLTexture tex;
1872     glBindTexture(GL_TEXTURE_2D, tex);
1873     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1874     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1875     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1876     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1877 
1878     glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
1879     ASSERT_GL_NO_ERROR();
1880     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, subX0, subY0, subWidth, subHeight, format,
1881                               static_cast<GLsizei>(subData.size()), subData.data());
1882     ASSERT_GL_NO_ERROR();
1883 
1884     draw2DTexturedQuad(0.5f, 1.0f, true);
1885     ASSERT_GL_NO_ERROR();
1886 
1887     std::vector<GLColor> actualData(width * height);
1888     glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
1889     ASSERT_GL_NO_ERROR();
1890 
1891     for (int y = 0; y < height; ++y)
1892     {
1893         for (int x = 0; x < width; ++x)
1894         {
1895             int offset                  = x + y * width;
1896             const GLColor expectedColor = expectedData[offset];
1897             const GLColor actualColor   = actualData[offset];
1898 
1899             // Allow for some minor variation because the format is compressed.
1900             EXPECT_NEAR(expectedColor.R, actualColor.R, 1) << " at (" << x << ", " << y << ")";
1901             EXPECT_NEAR(expectedColor.G, actualColor.G, 1) << " at (" << x << ", " << y << ")";
1902             EXPECT_NEAR(expectedColor.B, actualColor.B, 1) << " at (" << x << ", " << y << ")";
1903         }
1904     }
1905 }
1906 
1907 // Tests that a partial scissor still initializes contents as expected.
TEST_P(RobustResourceInitTest,ClearWithScissor)1908 TEST_P(RobustResourceInitTest, ClearWithScissor)
1909 {
1910     ANGLE_SKIP_TEST_IF(!hasGLExtension());
1911 
1912     constexpr int kSize = 16;
1913 
1914     GLRenderbuffer colorbuffer;
1915     glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
1916     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
1917 
1918     GLFramebuffer framebuffer;
1919     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1920     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
1921 
1922     ASSERT_GL_NO_ERROR();
1923     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1924 
1925     // Scissor to half the width.
1926     glEnable(GL_SCISSOR_TEST);
1927     glScissor(0, 0, kSize / 2, kSize);
1928 
1929     // Clear. Half the texture should be black, and half red.
1930     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1931     glClear(GL_COLOR_BUFFER_BIT);
1932 
1933     EXPECT_GL_NO_ERROR();
1934     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1935     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::transparentBlack);
1936 
1937     GLint initState = 0;
1938     glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RESOURCE_INITIALIZED_ANGLE, &initState);
1939     EXPECT_GL_TRUE(initState);
1940 }
1941 
1942 // Tests that surfaces are initialized when they are created
TEST_P(RobustResourceInitTest,SurfaceInitialized)1943 TEST_P(RobustResourceInitTest, SurfaceInitialized)
1944 {
1945     ANGLE_SKIP_TEST_IF(!hasRobustSurfaceInit());
1946 
1947     checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
1948 }
1949 
1950 // Tests that surfaces are initialized after swapping if they are not preserved
TEST_P(RobustResourceInitTest,SurfaceInitializedAfterSwap)1951 TEST_P(RobustResourceInitTest, SurfaceInitializedAfterSwap)
1952 {
1953     ANGLE_SKIP_TEST_IF(!hasRobustSurfaceInit());
1954 
1955     EGLint swapBehaviour = 0;
1956     ASSERT_TRUE(eglQuerySurface(getEGLWindow()->getDisplay(), getEGLWindow()->getSurface(),
1957                                 EGL_SWAP_BEHAVIOR, &swapBehaviour));
1958 
1959     const std::array<GLColor, 4> clearColors = {{
1960         GLColor::blue,
1961         GLColor::cyan,
1962         GLColor::red,
1963         GLColor::yellow,
1964     }};
1965 
1966     if (swapBehaviour != EGL_BUFFER_PRESERVED)
1967     {
1968         checkFramebufferNonZeroPixels(0, 0, 0, 0, GLColor::black);
1969     }
1970 
1971     glEnable(GL_SCISSOR_TEST);
1972     glScissor(0, 0, 1, 1);
1973 
1974     for (size_t i = 0; i < clearColors.size(); i++)
1975     {
1976         if (swapBehaviour == EGL_BUFFER_PRESERVED && i > 0)
1977         {
1978             EXPECT_PIXEL_COLOR_EQ(0, 0, clearColors[i - 1]);
1979         }
1980 
1981         angle::Vector4 clearColor = clearColors[i].toNormalizedVector();
1982         glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
1983         glClear(GL_COLOR_BUFFER_BIT);
1984         EXPECT_GL_NO_ERROR();
1985 
1986         if (swapBehaviour != EGL_BUFFER_PRESERVED)
1987         {
1988             // Only scissored area (0, 0, 1, 1) has clear color.
1989             // The rest should be robust initialized.
1990             checkFramebufferNonZeroPixels(0, 0, 1, 1, clearColors[i]);
1991         }
1992 
1993         swapBuffers();
1994     }
1995 }
1996 
1997 // Test that multisampled 2D textures are initialized.
TEST_P(RobustResourceInitTestES31,Multisample2DTexture)1998 TEST_P(RobustResourceInitTestES31, Multisample2DTexture)
1999 {
2000     ANGLE_SKIP_TEST_IF(!hasGLExtension());
2001 
2002     GLTexture texture;
2003     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
2004     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, kWidth, kHeight, false);
2005 
2006     GLFramebuffer framebuffer;
2007     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2008     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2009                            texture, 0);
2010 
2011     GLTexture resolveTexture;
2012     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2013     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
2014 
2015     GLFramebuffer resolveFramebuffer;
2016     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
2017     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
2018                            0);
2019     ASSERT_GL_NO_ERROR();
2020 
2021     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
2022                       GL_NEAREST);
2023     ASSERT_GL_NO_ERROR();
2024 
2025     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFramebuffer);
2026     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::transparentBlack);
2027 }
2028 
2029 // Test that multisampled 2D texture arrays from OES_texture_storage_multisample_2d_array are
2030 // initialized.
TEST_P(RobustResourceInitTestES31,Multisample2DTextureArray)2031 TEST_P(RobustResourceInitTestES31, Multisample2DTextureArray)
2032 {
2033     ANGLE_SKIP_TEST_IF(!hasGLExtension());
2034 
2035     if (IsGLExtensionRequestable("GL_OES_texture_storage_multisample_2d_array"))
2036     {
2037         glRequestExtensionANGLE("GL_OES_texture_storage_multisample_2d_array");
2038     }
2039     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"));
2040 
2041     const GLsizei kLayers = 4;
2042 
2043     GLTexture texture;
2044     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, texture);
2045     glTexStorage3DMultisampleOES(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, GL_RGBA8, kWidth, kHeight,
2046                                  kLayers, false);
2047 
2048     GLTexture resolveTexture;
2049     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2050     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
2051 
2052     GLFramebuffer resolveFramebuffer;
2053     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
2054     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
2055                            0);
2056     ASSERT_GL_NO_ERROR();
2057 
2058     for (GLsizei layerIndex = 0; layerIndex < kLayers; ++layerIndex)
2059     {
2060         GLFramebuffer framebuffer;
2061         glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2062         glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0,
2063                                   layerIndex);
2064 
2065         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
2066                           GL_NEAREST);
2067         ASSERT_GL_NO_ERROR();
2068 
2069         glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFramebuffer);
2070         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::transparentBlack);
2071     }
2072 }
2073 
2074 // Tests that using an out of bounds draw offset with a dynamic array succeeds.
TEST_P(RobustResourceInitTest,DynamicVertexArrayOffsetOutOfBounds)2075 TEST_P(RobustResourceInitTest, DynamicVertexArrayOffsetOutOfBounds)
2076 {
2077     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2078     glUseProgram(program);
2079 
2080     GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2081     ASSERT_NE(-1, posLoc);
2082 
2083     glEnableVertexAttribArray(posLoc);
2084     GLBuffer buf;
2085     glBindBuffer(GL_ARRAY_BUFFER, buf);
2086     glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const void *>(500));
2087     glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_DYNAMIC_DRAW);
2088     glDrawArrays(GL_TRIANGLES, 0, 3);
2089 
2090     // Either no error or invalid operation is okay.
2091 }
2092 
2093 // Test to cover a bug that the multisampled depth attachment of a framebuffer are not successfully
2094 // initialized before it is used as the read framebuffer in blitFramebuffer.
2095 // Referenced from the following WebGL CTS:
2096 // conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html
TEST_P(RobustResourceInitTestES3,InitializeMultisampledDepthRenderbufferAfterCopyTextureCHROMIUM)2097 TEST_P(RobustResourceInitTestES3, InitializeMultisampledDepthRenderbufferAfterCopyTextureCHROMIUM)
2098 {
2099     ANGLE_SKIP_TEST_IF(!hasGLExtension());
2100     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_copy_texture"));
2101 
2102     // Call glCopyTextureCHROMIUM to set destTexture as the color attachment of the internal
2103     // framebuffer mScratchFBO.
2104     GLTexture sourceTexture;
2105     glBindTexture(GL_TEXTURE_2D, sourceTexture);
2106     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2107     GLTexture destTexture;
2108     glBindTexture(GL_TEXTURE_2D, destTexture);
2109     glCopyTextureCHROMIUM(sourceTexture, 0, GL_TEXTURE_2D, destTexture, 0, GL_RGBA,
2110                           GL_UNSIGNED_BYTE, GL_FALSE, GL_FALSE, GL_FALSE);
2111     ASSERT_GL_NO_ERROR();
2112 
2113     GLFramebuffer drawFbo;
2114     glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
2115 
2116     GLTexture colorTex;
2117     glBindTexture(GL_TEXTURE_2D, colorTex);
2118     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2119     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
2120     GLRenderbuffer drawDepthRbo;
2121     glBindRenderbuffer(GL_RENDERBUFFER, drawDepthRbo);
2122     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kWidth, kHeight);
2123     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, drawDepthRbo);
2124 
2125     // Clear drawDepthRbo to 0.0f
2126     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2127     glClearDepthf(0.0f);
2128     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2129 
2130     constexpr uint32_t kReadDepthRboSampleCount = 4;
2131     GLFramebuffer readFbo;
2132     glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
2133     GLRenderbuffer readDepthRbo;
2134     glBindRenderbuffer(GL_RENDERBUFFER, readDepthRbo);
2135     glRenderbufferStorageMultisample(GL_RENDERBUFFER, kReadDepthRboSampleCount,
2136                                      GL_DEPTH_COMPONENT16, kWidth, kHeight);
2137     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, readDepthRbo);
2138 
2139     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2140     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
2141 
2142     // Blit from readDepthRbo to drawDepthRbo. When robust resource init is enabled, readDepthRbo
2143     // should be initialized to 1.0f by default, so the data in drawDepthRbo should also be 1.0f.
2144     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
2145                       GL_NEAREST);
2146     ASSERT_GL_NO_ERROR();
2147 
2148     glDepthFunc(GL_LESS);
2149     glEnable(GL_DEPTH_TEST);
2150 
2151     glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
2152     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2153 
2154     // If drawDepthRbo is correctly set to 1.0f, the depth test can always pass, so the result
2155     // should be green.
2156     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2157     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2158 }
2159 
2160 // Corner case for robust resource init: CopyTexImage to a cube map.
TEST_P(RobustResourceInitTest,CopyTexImageToOffsetCubeMap)2161 TEST_P(RobustResourceInitTest, CopyTexImageToOffsetCubeMap)
2162 {
2163     ANGLE_SKIP_TEST_IF(!hasGLExtension());
2164 
2165     constexpr GLuint kSize = 2;
2166 
2167     std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
2168 
2169     GLTexture srcTex;
2170     glBindTexture(GL_TEXTURE_2D, srcTex);
2171     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2172                  redPixels.data());
2173 
2174     GLFramebuffer fbo;
2175     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2176     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTex, 0);
2177 
2178     ASSERT_GL_NO_ERROR();
2179     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2180     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2181 
2182     GLTexture dstTex;
2183     glBindTexture(GL_TEXTURE_CUBE_MAP, dstTex);
2184     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, kSize, kSize, 0);
2185     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, -1, -1, kSize, kSize, 0);
2186     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 2, 2, kSize, kSize, 0);
2187     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, -2, -2, kSize, kSize, 0);
2188     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2189     glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
2190 
2191     ASSERT_GL_NO_ERROR();
2192 
2193     // Verify the offset attachments.
2194     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
2195                            dstTex, 0);
2196     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2197     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2198     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::transparentBlack);
2199     EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::transparentBlack);
2200     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::transparentBlack);
2201 
2202     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
2203                            dstTex, 0);
2204     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2205     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2206     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::transparentBlack);
2207     EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::transparentBlack);
2208     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
2209 }
2210 
2211 // Test that blit between two depth/stencil buffers after glClearBufferfi works.  The blit is done
2212 // once expecting robust resource init value, then clear is called with the same value as the robust
2213 // init, and blit is done again.  This triggers an optimization in the Vulkan backend where the
2214 // second clear is no-oped.
TEST_P(RobustResourceInitTestES3,BlitDepthStencilAfterClearBuffer)2215 TEST_P(RobustResourceInitTestES3, BlitDepthStencilAfterClearBuffer)
2216 {
2217     // http://anglebug.com/5301
2218     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2219 
2220     // http://anglebug.com/5300
2221     ANGLE_SKIP_TEST_IF(IsD3D11());
2222 
2223     // http://anglebug.com/4919
2224     ANGLE_SKIP_TEST_IF(IsIntel() && IsMetal());
2225 
2226     constexpr GLsizei kSize = 16;
2227 
2228     GLFramebuffer readFbo, drawFbo;
2229     GLRenderbuffer readDepthStencil, drawDepthStencil;
2230 
2231     // Create destination framebuffer.
2232     glBindRenderbuffer(GL_RENDERBUFFER, drawDepthStencil);
2233     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
2234     glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
2235     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2236                               drawDepthStencil);
2237     ASSERT_GL_NO_ERROR();
2238 
2239     // Create source framebuffer
2240     glBindRenderbuffer(GL_RENDERBUFFER, readDepthStencil);
2241     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
2242     glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
2243     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2244                               readDepthStencil);
2245     ASSERT_GL_NO_ERROR();
2246 
2247     // Blit once with the robust resource init clear.
2248     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
2249     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize,
2250                       GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
2251     ASSERT_GL_NO_ERROR();
2252 
2253     // Verify that the blit was successful.
2254     GLRenderbuffer color;
2255     glBindRenderbuffer(GL_RENDERBUFFER, color);
2256     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
2257     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
2258     ASSERT_GL_NO_ERROR();
2259 
2260     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2261 
2262     glEnable(GL_DEPTH_TEST);
2263     glDepthFunc(GL_LESS);
2264 
2265     glEnable(GL_STENCIL_TEST);
2266     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2267     glStencilFunc(GL_EQUAL, 0, 0xFF);
2268 
2269     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f, 1.0f, true);
2270     ASSERT_GL_NO_ERROR();
2271 
2272     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
2273     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2274     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
2275     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
2276     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
2277 
2278     // Clear to the same value as robust init, and blit again.
2279     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, readFbo);
2280     glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
2281     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2282     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
2283     glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.5f, 0x3C);
2284     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize,
2285                       GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
2286     ASSERT_GL_NO_ERROR();
2287 
2288     // Verify that the blit was successful.
2289     ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2290     drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.95f, 1.0f, true);
2291     ASSERT_GL_NO_ERROR();
2292 
2293     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
2294     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2295     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
2296     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
2297     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
2298 }
2299 
2300 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(RobustResourceInitTest,
2301                                        WithAllocateNonZeroMemory(ES2_VULKAN()));
2302 
2303 ANGLE_INSTANTIATE_TEST_ES3_AND(RobustResourceInitTestES3, WithAllocateNonZeroMemory(ES3_VULKAN()));
2304 
2305 ANGLE_INSTANTIATE_TEST_ES31_AND(RobustResourceInitTestES31,
2306                                 WithAllocateNonZeroMemory(ES31_VULKAN()));
2307 
2308 }  // namespace angle
2309