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