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