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