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