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