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