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