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