1 //
2 // Copyright 2015 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 // Framebuffer tests:
7 // Various tests related for Frambuffers.
8 //
9
10 #include "common/mathutil.h"
11 #include "platform/autogen/FeaturesD3D_autogen.h"
12 #include "test_utils/ANGLETest.h"
13 #include "test_utils/gl_raii.h"
14 #include "util/OSWindow.h"
15
16 using namespace angle;
17
18 namespace
19 {
20
ExpectFramebufferCompleteOrUnsupported(GLenum binding)21 void ExpectFramebufferCompleteOrUnsupported(GLenum binding)
22 {
23 GLenum status = glCheckFramebufferStatus(binding);
24 EXPECT_TRUE(status == GL_FRAMEBUFFER_COMPLETE || status == GL_FRAMEBUFFER_UNSUPPORTED);
25 }
26
27 } // anonymous namespace
28
29 class FramebufferFormatsTest : public ANGLETest<>
30 {
31 protected:
FramebufferFormatsTest()32 FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
33 {
34 setWindowWidth(128);
35 setWindowHeight(128);
36 setConfigRedBits(8);
37 setConfigGreenBits(8);
38 setConfigBlueBits(8);
39 setConfigAlphaBits(8);
40 }
41
checkBitCount(GLuint fbo,GLenum channel,GLint minBits)42 void checkBitCount(GLuint fbo, GLenum channel, GLint minBits)
43 {
44 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
45
46 GLint bits = 0;
47 glGetIntegerv(channel, &bits);
48
49 if (minBits == 0)
50 {
51 EXPECT_EQ(minBits, bits);
52 }
53 else
54 {
55 EXPECT_GE(bits, minBits);
56 }
57 }
58
testBitCounts(GLuint fbo,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits,GLint minDepthBits,GLint minStencilBits)59 void testBitCounts(GLuint fbo,
60 GLint minRedBits,
61 GLint minGreenBits,
62 GLint minBlueBits,
63 GLint minAlphaBits,
64 GLint minDepthBits,
65 GLint minStencilBits)
66 {
67 checkBitCount(fbo, GL_RED_BITS, minRedBits);
68 checkBitCount(fbo, GL_GREEN_BITS, minGreenBits);
69 checkBitCount(fbo, GL_BLUE_BITS, minBlueBits);
70 checkBitCount(fbo, GL_ALPHA_BITS, minAlphaBits);
71 checkBitCount(fbo, GL_DEPTH_BITS, minDepthBits);
72 checkBitCount(fbo, GL_STENCIL_BITS, minStencilBits);
73 }
74
testTextureFormat(GLenum internalFormat,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits)75 void testTextureFormat(GLenum internalFormat,
76 GLint minRedBits,
77 GLint minGreenBits,
78 GLint minBlueBits,
79 GLint minAlphaBits)
80 {
81 glGenTextures(1, &mTexture);
82 glBindTexture(GL_TEXTURE_2D, mTexture);
83
84 if (getClientMajorVersion() >= 3)
85 {
86 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
87 }
88 else
89 {
90 glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
91 }
92
93 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
94
95 testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
96 }
97
testRenderbufferMultisampleFormat(int minESVersion,GLenum attachmentType,GLenum internalFormat)98 void testRenderbufferMultisampleFormat(int minESVersion,
99 GLenum attachmentType,
100 GLenum internalFormat)
101 {
102 int clientVersion = getClientMajorVersion();
103 if (clientVersion < minESVersion)
104 {
105 return;
106 }
107
108 // Check that multisample is supported with at least two samples (minimum required is 1)
109 bool supports2Samples = false;
110
111 if (clientVersion == 2)
112 {
113 if (IsGLExtensionEnabled("ANGLE_framebuffer_multisample"))
114 {
115 int maxSamples;
116 glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples);
117 supports2Samples = maxSamples >= 2;
118 }
119 }
120 else
121 {
122 assert(clientVersion >= 3);
123 int maxSamples;
124 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
125 supports2Samples = maxSamples >= 2;
126 }
127
128 if (!supports2Samples)
129 {
130 return;
131 }
132
133 glGenRenderbuffers(1, &mRenderbuffer);
134 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
135
136 EXPECT_GL_NO_ERROR();
137 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
138 EXPECT_GL_NO_ERROR();
139 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
140 EXPECT_GL_NO_ERROR();
141 }
142
testZeroHeightRenderbuffer()143 void testZeroHeightRenderbuffer()
144 {
145 glGenRenderbuffers(1, &mRenderbuffer);
146 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
147 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 0);
148 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
149 mRenderbuffer);
150 EXPECT_GL_NO_ERROR();
151 }
152
testSetUp()153 void testSetUp() override
154 {
155 glGenFramebuffers(1, &mFramebuffer);
156 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
157 }
158
testTearDown()159 void testTearDown() override
160 {
161 if (mTexture != 0)
162 {
163 glDeleteTextures(1, &mTexture);
164 mTexture = 0;
165 }
166
167 if (mRenderbuffer != 0)
168 {
169 glDeleteRenderbuffers(1, &mRenderbuffer);
170 mRenderbuffer = 0;
171 }
172
173 if (mFramebuffer != 0)
174 {
175 glDeleteFramebuffers(1, &mFramebuffer);
176 mFramebuffer = 0;
177 }
178
179 if (mProgram != 0)
180 {
181 glDeleteProgram(mProgram);
182 mProgram = 0;
183 }
184 }
185
186 GLuint mFramebuffer;
187 GLuint mTexture;
188 GLuint mRenderbuffer;
189 GLuint mProgram;
190 };
191
TEST_P(FramebufferFormatsTest,RGBA4)192 TEST_P(FramebufferFormatsTest, RGBA4)
193 {
194 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
195 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
196
197 testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
198 }
199
TEST_P(FramebufferFormatsTest,RGB565)200 TEST_P(FramebufferFormatsTest, RGB565)
201 {
202 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
203 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
204
205 testTextureFormat(GL_RGB565, 5, 6, 5, 0);
206 }
207
TEST_P(FramebufferFormatsTest,RGB8)208 TEST_P(FramebufferFormatsTest, RGB8)
209 {
210 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
211 (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
212 !IsGLExtensionEnabled("GL_EXT_texture_storage")));
213
214 testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
215 }
216
TEST_P(FramebufferFormatsTest,BGRA8)217 TEST_P(FramebufferFormatsTest, BGRA8)
218 {
219 ANGLE_SKIP_TEST_IF(
220 !IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888") ||
221 (getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_texture_storage")));
222
223 testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
224 }
225
TEST_P(FramebufferFormatsTest,RGBA8)226 TEST_P(FramebufferFormatsTest, RGBA8)
227 {
228 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
229 (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
230 !IsGLExtensionEnabled("GL_EXT_texture_storage")));
231
232 testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
233 }
234
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH16)235 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
236 {
237 testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
238 }
239
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24)240 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
241 {
242 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
243 }
244
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F)245 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
246 {
247 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
248
249 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
250 }
251
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24_STENCIL8)252 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
253 {
254 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
255 }
256
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F_STENCIL8)257 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
258 {
259 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
260
261 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
262 }
263
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_STENCIL_INDEX8)264 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
265 {
266 // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
267 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
268
269 testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
270 }
271
272 // Test that binding an incomplete cube map is rejected by ANGLE.
TEST_P(FramebufferFormatsTest,IncompleteCubeMap)273 TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
274 {
275 // http://anglebug.com/3145
276 ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
277
278 // First make a complete CubeMap.
279 glGenTextures(1, &mTexture);
280 glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
281 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
282 nullptr);
283 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
284 nullptr);
285 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
286 nullptr);
287 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
288 nullptr);
289 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
290 nullptr);
291 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
292 nullptr);
293 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
294 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
295
296 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
297 mTexture, 0);
298
299 // Verify the framebuffer is complete.
300 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
301
302 // Make the CubeMap cube-incomplete.
303 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
304 nullptr);
305
306 // Verify the framebuffer is incomplete.
307 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
308 glCheckFramebufferStatus(GL_FRAMEBUFFER));
309
310 ASSERT_GL_NO_ERROR();
311
312 // Verify drawing with the incomplete framebuffer produces a GL error
313 mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
314 ASSERT_NE(0u, mProgram);
315 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
316 ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
317 }
318
319 // Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts.
TEST_P(FramebufferFormatsTest,ZeroHeightRenderbuffer)320 TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
321 {
322 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
323
324 testZeroHeightRenderbuffer();
325 }
326
327 // Test to cover a bug where the read framebuffer affects the completeness of the draw framebuffer.
TEST_P(FramebufferFormatsTest,ReadDrawCompleteness)328 TEST_P(FramebufferFormatsTest, ReadDrawCompleteness)
329 {
330 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
331
332 GLTexture incompleteTexture;
333 glBindTexture(GL_TEXTURE_2D, incompleteTexture);
334
335 GLFramebuffer incompleteFBO;
336 glBindFramebuffer(GL_FRAMEBUFFER, incompleteFBO);
337 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, incompleteTexture,
338 0);
339 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
340 glCheckFramebufferStatus(GL_FRAMEBUFFER));
341
342 GLTexture completeTexture;
343 glBindTexture(GL_TEXTURE_2D, completeTexture);
344 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
345
346 GLFramebuffer completeFBO;
347 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, completeFBO);
348 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
349 completeTexture, 0);
350
351 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
352 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
353 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
354
355 ASSERT_GL_NO_ERROR();
356
357 // Simple draw program.
358 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
359
360 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
361 EXPECT_GL_NO_ERROR();
362
363 glBindFramebuffer(GL_READ_FRAMEBUFFER, completeFBO);
364 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
365 }
366
367 // Test that a renderbuffer with RGB565 format works as expected. This test is intended for some
368 // back-end having no support for native RGB565 renderbuffer and thus having to emulate using RGBA
369 // format.
TEST_P(FramebufferFormatsTest,RGB565Renderbuffer)370 TEST_P(FramebufferFormatsTest, RGB565Renderbuffer)
371 {
372 GLRenderbuffer rbo;
373 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
374 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, 1, 1);
375
376 GLFramebuffer completeFBO;
377 glBindFramebuffer(GL_FRAMEBUFFER, completeFBO);
378 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
379
380 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
381
382 ASSERT_GL_NO_ERROR();
383
384 glClearColor(1, 0, 0, 0.5f);
385 glClear(GL_COLOR_BUFFER_BIT);
386 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
387 }
388
389 class FramebufferTest_ES3 : public ANGLETest<>
390 {
391 protected:
FramebufferTest_ES3()392 FramebufferTest_ES3()
393 {
394 setWindowWidth(kWidth);
395 setWindowHeight(kHeight);
396 setConfigRedBits(8);
397 setConfigGreenBits(8);
398 setConfigBlueBits(8);
399 setConfigAlphaBits(8);
400 setConfigDepthBits(24);
401 setConfigStencilBits(8);
402 }
403
404 static constexpr GLsizei kWidth = 64;
405 static constexpr GLsizei kHeight = 256;
406 };
407
408 // Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3,InvalidateIncomplete)409 TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
410 {
411 GLFramebuffer framebuffer;
412 GLRenderbuffer renderbuffer;
413
414 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
415 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
416 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
417 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
418 glCheckFramebufferStatus(GL_FRAMEBUFFER));
419
420 std::vector<GLenum> attachments;
421 attachments.push_back(GL_COLOR_ATTACHMENT0);
422
423 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
424 EXPECT_GL_NO_ERROR();
425 }
426
427 // Covers sub-invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3,SubInvalidateIncomplete)428 TEST_P(FramebufferTest_ES3, SubInvalidateIncomplete)
429 {
430 GLFramebuffer framebuffer;
431 GLRenderbuffer renderbuffer;
432
433 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
434 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
435 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
436 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
437 glCheckFramebufferStatus(GL_FRAMEBUFFER));
438
439 std::vector<GLenum> attachments;
440 attachments.push_back(GL_COLOR_ATTACHMENT0);
441
442 glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 1, attachments.data(), 5, 5, 10, 10);
443 EXPECT_GL_NO_ERROR();
444 }
445
446 enum class DisableDitherVsClear
447 {
448 Before,
449 After
450 };
451
testDitherDisabledProperlyOnRGB565(GLColor gradientColor,DisableDitherVsClear disableDitherVsClear)452 void testDitherDisabledProperlyOnRGB565(GLColor gradientColor,
453 DisableDitherVsClear disableDitherVsClear)
454 {
455 GLFramebuffer framebuffer;
456
457 constexpr GLsizei kFramebufferWidth = 4;
458 constexpr GLsizei kFramebufferHeight = 4;
459 GLTexture texture;
460 glBindTexture(GL_TEXTURE_2D, texture);
461 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB565, kFramebufferWidth, kFramebufferHeight);
462
463 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
464 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
465
466 constexpr char kVS[] = {
467 R"(#version 300 es
468 in highp vec4 a_position;
469 in mediump vec4 a_color;
470 out mediump vec4 v_color;
471 void main()
472 {
473 gl_Position = a_position;
474 v_color = a_color;
475 })",
476 };
477
478 constexpr char kFS[] = {
479 R"(#version 300 es
480 in mediump vec4 v_color;
481 layout(location = 0) out mediump vec4 o_color;
482 void main()
483 {
484 o_color = v_color;
485 })",
486 };
487
488 ANGLE_GL_PROGRAM(program, kVS, kFS);
489
490 glUseProgram(program);
491
492 // setup quad data
493 // black ----> gradientColor
494 // **********
495 // * *
496 // * *
497 // **********
498 const std::vector<float> positions = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
499 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
500
501 const std::vector<float> color0 = {0.0f,
502 0.0f,
503 0.0f,
504 0.0f,
505 0.0f,
506 0.0f,
507 0.0f,
508 0.0f,
509 gradientColor.R * 1.0f / 255.0f,
510 gradientColor.G * 1.0f / 255.0f,
511 gradientColor.B * 1.0f / 255.0f,
512 gradientColor.A * 1.0f / 255.0f,
513 gradientColor.R * 1.0f / 255.0f,
514 gradientColor.G * 1.0f / 255.0f,
515 gradientColor.B * 1.0f / 255.0f,
516 gradientColor.A * 1.0f / 255.0f};
517
518 GLBuffer vertexBuffer;
519 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
520 glBufferData(GL_ARRAY_BUFFER, sizeof(positions[0]) * positions.size(), positions.data(),
521 GL_STATIC_DRAW);
522
523 GLBuffer colorBuffer;
524 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
525 glBufferData(GL_ARRAY_BUFFER, sizeof(color0[0]) * color0.size(), color0.data(), GL_STATIC_DRAW);
526
527 GLint vertexPosLocation = glGetAttribLocation(program, "a_position");
528 ASSERT_NE(vertexPosLocation, -1);
529 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
530 glEnableVertexAttribArray(vertexPosLocation);
531 glVertexAttribPointer(vertexPosLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
532
533 GLint vertexColorLocation = glGetAttribLocation(program, "a_color");
534 ASSERT_NE(vertexColorLocation, -1);
535 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
536 glEnableVertexAttribArray(vertexColorLocation);
537 glVertexAttribPointer(vertexColorLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
538
539 const std::vector<uint8_t> indices = {0, 2, 1, 1, 2, 3};
540
541 GLBuffer indexBuffer;
542 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
543 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(),
544 GL_STATIC_DRAW);
545 ASSERT_GL_NO_ERROR();
546
547 switch (disableDitherVsClear)
548 {
549 case DisableDitherVsClear::Before:
550 glDisable(GL_DITHER);
551 glClearColor(0.125, 0.25, 0.5, 1);
552 glClear(GL_COLOR_BUFFER_BIT);
553 break;
554
555 case DisableDitherVsClear::After:
556 glClearColor(0.125, 0.25, 0.5, 1);
557 glClear(GL_COLOR_BUFFER_BIT);
558 glDisable(GL_DITHER);
559 break;
560 }
561
562 // draw quad
563 glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_BYTE, 0);
564 glBindBuffer(GL_ARRAY_BUFFER, 0);
565 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
566
567 // validate that when disabling dithering, the color selection must be coordinate-independent
568 std::vector<GLColor> pixelData(kFramebufferWidth * kFramebufferHeight);
569 glReadPixels(0, 0, kFramebufferWidth, kFramebufferHeight, GL_RGBA, GL_UNSIGNED_BYTE,
570 pixelData.data());
571
572 const int increasingDirectionSize = kFramebufferWidth;
573 const int constantDirectionSize = kFramebufferHeight;
574
575 for (int incrPos = 0; incrPos < increasingDirectionSize; incrPos++)
576 {
577 bool colorHasChanged = false;
578
579 GLColor prevConstantDirectionPixel;
580
581 for (int constPos = 0; constPos < constantDirectionSize; constPos++)
582 {
583 const int x = incrPos;
584 const int y = constPos;
585
586 const int currentPixelLoc = y * kFramebufferWidth + x;
587 const GLColor currentPixel = pixelData[currentPixelLoc];
588
589 if (constPos > 0 && currentPixel != prevConstantDirectionPixel)
590 {
591 if (colorHasChanged)
592 {
593 ASSERT(false);
594 }
595 else
596 {
597 colorHasChanged = true;
598 }
599 }
600
601 prevConstantDirectionPixel = currentPixel;
602 }
603 }
604 }
605
606 // repro dEQP-GLES3.functional.dither.disabled.gradient_red failure
TEST_P(FramebufferTest_ES3,RGB565DisableDitheringGradientRedTest)607 TEST_P(FramebufferTest_ES3, RGB565DisableDitheringGradientRedTest)
608 {
609 testDitherDisabledProperlyOnRGB565(GLColor::red, DisableDitherVsClear::Before);
610 testDitherDisabledProperlyOnRGB565(GLColor::red, DisableDitherVsClear::After);
611 }
612
613 // repro dEQP-GLES3.functional.dither.disabled.gradient_green failure
TEST_P(FramebufferTest_ES3,RGB565DisableDitheringGradientGreenTest)614 TEST_P(FramebufferTest_ES3, RGB565DisableDitheringGradientGreenTest)
615 {
616 testDitherDisabledProperlyOnRGB565(GLColor::green, DisableDitherVsClear::Before);
617 testDitherDisabledProperlyOnRGB565(GLColor::green, DisableDitherVsClear::After);
618 }
619
620 // repro dEQP-GLES3.functional.dither.disabled.gradient_blue failure
TEST_P(FramebufferTest_ES3,RGB565DisableDitheringGradientBlueTest)621 TEST_P(FramebufferTest_ES3, RGB565DisableDitheringGradientBlueTest)
622 {
623 testDitherDisabledProperlyOnRGB565(GLColor::blue, DisableDitherVsClear::Before);
624 testDitherDisabledProperlyOnRGB565(GLColor::blue, DisableDitherVsClear::After);
625 }
626
627 // repro dEQP-GLES3.functional.dither.disabled.gradient_white failure
TEST_P(FramebufferTest_ES3,RGB565DisableDitheringGradientWhiteTest)628 TEST_P(FramebufferTest_ES3, RGB565DisableDitheringGradientWhiteTest)
629 {
630 testDitherDisabledProperlyOnRGB565(GLColor::white, DisableDitherVsClear::Before);
631 testDitherDisabledProperlyOnRGB565(GLColor::white, DisableDitherVsClear::After);
632 }
633
634 // Test that subinvalidate with no prior command works. Regression test for the Vulkan backend that
635 // assumed a render pass is started when sub invalidate is called.
TEST_P(FramebufferTest_ES3,SubInvalidateFirst)636 TEST_P(FramebufferTest_ES3, SubInvalidateFirst)
637 {
638 glBindFramebuffer(GL_FRAMEBUFFER, 0);
639
640 // Invalidate half of the framebuffer using swapped dimensions.
641 std::array<GLenum, 1> attachments = {GL_COLOR};
642 glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, attachments.data(), 0, 0, kHeight, kWidth);
643 EXPECT_GL_NO_ERROR();
644 }
645
646 // Test that subinvalidate doesn't discard data outside area. Uses swapped width/height for
647 // invalidate which results in a partial invalidate, but also prevents bugs with Vulkan
648 // pre-rotation.
TEST_P(FramebufferTest_ES3,SubInvalidatePartial)649 TEST_P(FramebufferTest_ES3, SubInvalidatePartial)
650 {
651 glBindFramebuffer(GL_FRAMEBUFFER, 0);
652
653 // Clear the attachment.
654 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
655 glClear(GL_COLOR_BUFFER_BIT);
656 EXPECT_GL_NO_ERROR();
657
658 // Invalidate half of the framebuffer using swapped dimensions.
659 std::array<GLenum, 1> attachments = {GL_COLOR};
660 glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, attachments.data(), 0, 0, kHeight, kWidth);
661 EXPECT_GL_NO_ERROR();
662
663 // Make sure the other half is correct.
664 EXPECT_PIXEL_COLOR_EQ(0, kWidth, GLColor::red);
665 EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kWidth, GLColor::red);
666 EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
667 EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::red);
668 }
669
670 // Test that invalidating depth/stencil of the default framebuffer doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateDefaultFramebufferDepthStencil)671 TEST_P(FramebufferTest_ES3, InvalidateDefaultFramebufferDepthStencil)
672 {
673 glBindFramebuffer(GL_FRAMEBUFFER, 0);
674
675 std::array<GLenum, 2> attachments = {GL_DEPTH, GL_STENCIL};
676
677 // Invalidate default framebuffer depth/stencil attachments
678 glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments.data());
679 EXPECT_GL_NO_ERROR();
680 }
681
682 // Test that invalidating color of the default framebuffer doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateDefaultFramebufferColor)683 TEST_P(FramebufferTest_ES3, InvalidateDefaultFramebufferColor)
684 {
685 glBindFramebuffer(GL_FRAMEBUFFER, 0);
686
687 std::array<GLenum, 1> attachments = {GL_COLOR};
688
689 // Invalidate default framebuffer color attachment.
690 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
691 EXPECT_GL_NO_ERROR();
692 }
693
694 // Test that invalidating all attachments on the default framebuffer doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateDefaultFramebuffer)695 TEST_P(FramebufferTest_ES3, InvalidateDefaultFramebuffer)
696 {
697 glBindFramebuffer(GL_FRAMEBUFFER, 0);
698
699 std::array<GLenum, 3> attachments = {GL_COLOR, GL_DEPTH, GL_STENCIL};
700
701 // Invalidate all default framebuffer attachments.
702 glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments.data());
703 EXPECT_GL_NO_ERROR();
704 }
705
706 // Test that invalidating combined depth/stencil attachment doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateDepthStencil)707 TEST_P(FramebufferTest_ES3, InvalidateDepthStencil)
708 {
709 // Create the framebuffer that will be invalidated
710 GLRenderbuffer depthStencil;
711 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
712 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 2, 2);
713
714 GLFramebuffer fbo;
715 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
716 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencil);
717 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
718
719 EXPECT_GL_NO_ERROR();
720
721 std::array<GLenum, 2> attachments = {GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT};
722
723 // Invalidate both depth and stencil.
724 glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments.data());
725 EXPECT_GL_NO_ERROR();
726 }
727
728 // Test that invalidating an FB with a stencil attachment, which
729 // generates Validation errors, will not fail
TEST_P(FramebufferTest_ES3,InvalidateStencilAttachmentOnly)730 TEST_P(FramebufferTest_ES3, InvalidateStencilAttachmentOnly)
731 {
732 constexpr GLsizei kBufferSize = 4096;
733 std::vector<uint8_t> abdata(kBufferSize);
734 GLBuffer arrayBuffer;
735 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
736 glBufferData(GL_ARRAY_BUFFER, kBufferSize, abdata.data(), GL_STATIC_DRAW);
737
738 std::vector<uint8_t> eabdata(kBufferSize);
739 GLBuffer elementArrayBuffer;
740 glBindBuffer(GL_ARRAY_BUFFER, elementArrayBuffer);
741 glBufferData(GL_ARRAY_BUFFER, kBufferSize, eabdata.data(), GL_STATIC_DRAW);
742
743 GLTexture stencilTexture;
744 glBindTexture(GL_TEXTURE_2D, stencilTexture);
745 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, 32, 32);
746
747 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
748 glUseProgram(program);
749
750 glEnableVertexAttribArray(0);
751 glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
752 glVertexAttribPointer(0, 4, GL_SHORT, GL_TRUE, 8, nullptr);
753 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
754
755 GLFramebuffer framebuffer;
756 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
757 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, stencilTexture, 0);
758 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
759
760 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
761 GLVertexArray vertexArray;
762 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
763 glDrawElements(GL_TRIANGLE_STRIP, 26, GL_UNSIGNED_INT, nullptr);
764 EXPECT_GL_NO_ERROR();
765
766 std::array<GLenum, 1> attachments = {GL_STENCIL_ATTACHMENT};
767 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
768 EXPECT_GL_NO_ERROR();
769 }
770
771 // Test that invalidating stencil-only attachment doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateStencilOnly)772 TEST_P(FramebufferTest_ES3, InvalidateStencilOnly)
773 {
774 // Create the framebuffer that will be invalidated
775 GLRenderbuffer stencil;
776 glBindRenderbuffer(GL_RENDERBUFFER, stencil);
777 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 2, 2);
778
779 GLFramebuffer fbo;
780 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
781 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencil);
782 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
783
784 EXPECT_GL_NO_ERROR();
785
786 std::array<GLenum, 1> attachments = {GL_STENCIL_ATTACHMENT};
787
788 // Invalidate both depth and stencil.
789 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
790 EXPECT_GL_NO_ERROR();
791 }
792
793 // Test that invalidating stencil of a depth-only attachment doesn't crash.
TEST_P(FramebufferTest_ES3,DepthOnlyAttachmentInvalidateStencil)794 TEST_P(FramebufferTest_ES3, DepthOnlyAttachmentInvalidateStencil)
795 {
796 // Create the framebuffer that will be invalidated
797 GLRenderbuffer depth;
798 glBindRenderbuffer(GL_RENDERBUFFER, depth);
799 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 2, 2);
800
801 GLFramebuffer fbo;
802 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
803 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
804 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
805
806 EXPECT_GL_NO_ERROR();
807
808 // Invalidate stencil only.
809 std::array<GLenum, 2> attachments = {GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT};
810 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
811 EXPECT_GL_NO_ERROR();
812
813 // Invalidate both depth and stencil.
814 glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments.data());
815 EXPECT_GL_NO_ERROR();
816 }
817
818 // Test that invalidating depth of a stencil-only attachment doesn't crash.
TEST_P(FramebufferTest_ES3,StencilOnlyAttachmentInvalidateDepth)819 TEST_P(FramebufferTest_ES3, StencilOnlyAttachmentInvalidateDepth)
820 {
821 // Create the framebuffer that will be invalidated
822 GLRenderbuffer depth;
823 glBindRenderbuffer(GL_RENDERBUFFER, depth);
824 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 2, 2);
825
826 GLFramebuffer fbo;
827 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
828 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depth);
829 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
830
831 EXPECT_GL_NO_ERROR();
832
833 // Invalidate depth only.
834 std::array<GLenum, 2> attachments = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
835 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
836 EXPECT_GL_NO_ERROR();
837
838 // Invalidate both depth and stencil.
839 glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments.data());
840 EXPECT_GL_NO_ERROR();
841 }
842
843 // Test that a scissored draw followed by subinvalidate followed by a non-scissored draw retains the
844 // part that is not invalidated. Uses swapped width/height for invalidate which results in a
845 // partial invalidate, but also prevents bugs with Vulkan pre-rotation.
TEST_P(FramebufferTest_ES3,ScissoredDrawSubInvalidateThenNonScissoredDraw)846 TEST_P(FramebufferTest_ES3, ScissoredDrawSubInvalidateThenNonScissoredDraw)
847 {
848 glBindFramebuffer(GL_FRAMEBUFFER, 0);
849
850 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
851 glUseProgram(drawColor);
852 GLint colorUniformLocation =
853 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
854 ASSERT_NE(colorUniformLocation, -1);
855
856 // Clear color to red and the depth/stencil buffer to 1.0 and 0x55
857 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
858 glClearDepthf(1);
859 glClearStencil(0x55);
860 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
861 EXPECT_GL_NO_ERROR();
862
863 // Break rendering so the following draw call starts rendering with a scissored area.
864 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
865
866 // Issue a scissored draw call that changes depth to 0.5 and stencil 0x3C
867 glScissor(0, 0, kHeight, kWidth);
868 glEnable(GL_SCISSOR_TEST);
869
870 glEnable(GL_DEPTH_TEST);
871 glDepthFunc(GL_ALWAYS);
872
873 glEnable(GL_STENCIL_TEST);
874 glStencilFunc(GL_ALWAYS, 0x3C, 0xFF);
875 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
876 glStencilMask(0xFF);
877
878 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
879 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0);
880
881 // Invalidate the draw region (half of the framebuffer using swapped dimensions).
882 std::array<GLenum, 3> attachments = {GL_COLOR, GL_DEPTH, GL_STENCIL};
883 glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 3, attachments.data(), 0, 0, kHeight, kWidth);
884 EXPECT_GL_NO_ERROR();
885
886 // Match the scissor to the framebuffer size and issue a draw call that blends blue, and expects
887 // depth to be 1 and stencil to be 0x55. This is only valid for the half that was not
888 // invalidated.
889 glScissor(0, 0, kWidth, kHeight);
890 glDepthFunc(GL_LESS);
891 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
892 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
893
894 glEnable(GL_BLEND);
895 glBlendFunc(GL_ONE, GL_ONE);
896 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
897 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
898 ASSERT_GL_NO_ERROR();
899
900 // Make sure the half that was not invalidated is correct.
901 EXPECT_PIXEL_COLOR_EQ(0, kWidth, GLColor::magenta);
902 EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kWidth, GLColor::magenta);
903 EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
904 EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
905 }
906
907 // Test that the framebuffer state tracking robustly handles a depth-only attachment being set
908 // as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
TEST_P(FramebufferTest_ES3,DepthOnlyAsDepthStencil)909 TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
910 {
911 GLFramebuffer framebuffer;
912 GLRenderbuffer renderbuffer;
913
914 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
915 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
916 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
917
918 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
919 renderbuffer);
920 EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
921 }
922
923 // Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
924 // are bound
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevels)925 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
926 {
927 GLFramebuffer framebuffer;
928 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
929
930 GLTexture texture;
931 glBindTexture(GL_TEXTURE_2D, texture);
932
933 // Create a complete mip chain in mips 1 to 3
934 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
935 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
936 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
937
938 // Create another complete mip chain in mips 4 to 5
939 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
940 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
941
942 // Create a non-complete mip chain in mip 6
943 glTexImage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
944
945 // Incomplete, mipLevel != baseLevel and texture is not mip complete
946 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
947 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
948 glCheckFramebufferStatus(GL_FRAMEBUFFER));
949
950 // Complete, mipLevel == baseLevel
951 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
952 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
953
954 // Complete, mipLevel != baseLevel but texture is now mip complete
955 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
956 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
957 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
958 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
959
960 // Incomplete, attached level below the base level
961 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
962 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
963 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
964 glCheckFramebufferStatus(GL_FRAMEBUFFER));
965
966 // Incomplete, attached level is beyond effective max level
967 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 4);
968 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
969 glCheckFramebufferStatus(GL_FRAMEBUFFER));
970
971 // Complete, mipLevel == baseLevel
972 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
973 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
974
975 // Complete, mipLevel != baseLevel but texture is now mip complete
976 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 5);
977 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
978
979 // Complete, mipLevel == baseLevel
980 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 6);
981 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 6);
982 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
983 }
984
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevelsReadBack)985 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBack)
986 {
987 GLFramebuffer framebuffer;
988 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
989
990 GLTexture texture;
991 glBindTexture(GL_TEXTURE_2D, texture);
992
993 const std::array<GLColor, 4 * 4> mip0Data = {
994 GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
995 GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
996 GLColor::red, GLColor::red, GLColor::red, GLColor::red};
997 const std::array<GLColor, 2 * 2> mip1Data = {GLColor::green, GLColor::green, GLColor::green,
998 GLColor::green};
999
1000 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
1001 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
1002
1003 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1004 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
1005 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1006
1007 glClearColor(0, 0, 1.0f, 1.0f);
1008 glClear(GL_COLOR_BUFFER_BIT);
1009 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1010 }
1011
1012 // TextureAttachmentMipLevelsReadBackWithDraw is a copy of TextureAttachmentMipLevelsReadBack except
1013 // for adding a draw after the last clear. The draw forces ANGLE's Vulkan backend to use the
1014 // framebuffer that is level 1 of the texture which will trigger the mismatch use of the GL level
1015 // and Vulkan level in referring to that rendertarget.
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevelsReadBackWithDraw)1016 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBackWithDraw)
1017 {
1018 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1019
1020 GLFramebuffer framebuffer;
1021 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1022
1023 GLTexture texture;
1024 glBindTexture(GL_TEXTURE_2D, texture);
1025
1026 const std::array<GLColor, 4 * 4> mip0Data = {
1027 GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
1028 GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
1029 GLColor::red, GLColor::red, GLColor::red, GLColor::red};
1030 const std::array<GLColor, 2 * 2> mip1Data = {GLColor::green, GLColor::green, GLColor::green,
1031 GLColor::green};
1032
1033 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
1034 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
1035
1036 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1037 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
1038 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1039
1040 glClearColor(0, 0, 1.0f, 1.0f);
1041 glClear(GL_COLOR_BUFFER_BIT);
1042
1043 // This draw triggers the use of the framebuffer
1044 glUseProgram(greenProgram);
1045 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1046 ASSERT_GL_NO_ERROR();
1047 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1048 }
1049
1050 // Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
1051 // generates an INVALID_OPERATION.
1052 // OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
1053 // 208
TEST_P(FramebufferTest_ES3,ColorAttachmentIndexOutOfBounds)1054 TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
1055 {
1056 GLFramebuffer framebuffer;
1057 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1058
1059 GLint maxColorAttachments = 0;
1060 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
1061 GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
1062
1063 GLTexture texture;
1064 glBindTexture(GL_TEXTURE_2D, texture);
1065 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
1066 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture, 0);
1067 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1068 }
1069
1070 // Check that depth-only attachments report the correct number of samples.
TEST_P(FramebufferTest_ES3,MultisampleDepthOnly)1071 TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
1072 {
1073 GLRenderbuffer renderbuffer;
1074 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1075 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
1076
1077 GLFramebuffer framebuffer;
1078 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1079 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
1080 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1081 EXPECT_GL_NO_ERROR();
1082
1083 GLint samples = 0;
1084 glGetIntegerv(GL_SAMPLES, &samples);
1085 EXPECT_GL_NO_ERROR();
1086 EXPECT_GE(samples, 2);
1087 }
1088
1089 // Check that we only compare width and height of attachments, not depth.
TEST_P(FramebufferTest_ES3,AttachmentWith3DLayers)1090 TEST_P(FramebufferTest_ES3, AttachmentWith3DLayers)
1091 {
1092 GLTexture texA;
1093 glBindTexture(GL_TEXTURE_2D, texA);
1094 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1095
1096 GLTexture texB;
1097 glBindTexture(GL_TEXTURE_3D, texB);
1098 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 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, texA, 0);
1103 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texB, 0, 0);
1104 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1105 EXPECT_GL_NO_ERROR();
1106 }
1107
1108 // Check that invalid layer is detected in framebuffer completeness check.
1109 TEST_P(FramebufferTest_ES3, 3DAttachmentInvalidLayer)
1110 {
1111 GLTexture tex;
1112 glBindTexture(GL_TEXTURE_3D, tex);
1113 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1114
1115 GLFramebuffer framebuffer;
1116 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1117 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
1118 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1119 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1120
1121 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
1122 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1123 EXPECT_GL_NO_ERROR();
1124 }
1125
1126 // Check that invalid layer is detected in framebuffer completeness check.
1127 TEST_P(FramebufferTest_ES3, 2DArrayInvalidLayer)
1128 {
1129 GLTexture tex;
1130 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
1131 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1132
1133 GLFramebuffer framebuffer;
1134 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1135 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
1136 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1137 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1138
1139 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
1140 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1141 EXPECT_GL_NO_ERROR();
1142 }
1143
1144 // Test that clearing the stencil buffer when the framebuffer only has a color attachment does not
1145 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentStencil)1146 TEST_P(FramebufferTest_ES3, ClearNonexistentStencil)
1147 {
1148 GLRenderbuffer rbo;
1149 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1150 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1151
1152 GLFramebuffer fbo;
1153 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1154 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1155
1156 GLint clearValue = 0;
1157 glClearBufferiv(GL_STENCIL, 0, &clearValue);
1158
1159 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
1160 EXPECT_GL_NO_ERROR();
1161 }
1162
1163 // Test that clearing the depth buffer when the framebuffer only has a color attachment does not
1164 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepth)1165 TEST_P(FramebufferTest_ES3, ClearNonexistentDepth)
1166 {
1167 GLRenderbuffer rbo;
1168 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1169 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1170
1171 GLFramebuffer fbo;
1172 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1173 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1174
1175 GLfloat clearValue = 0.0f;
1176 glClearBufferfv(GL_DEPTH, 0, &clearValue);
1177
1178 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
1179 EXPECT_GL_NO_ERROR();
1180 }
1181
1182 // Test that clearing a nonexistent color attachment does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentColor)1183 TEST_P(FramebufferTest_ES3, ClearNonexistentColor)
1184 {
1185 GLRenderbuffer rbo;
1186 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1187 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1188
1189 GLFramebuffer fbo;
1190 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1191 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1192
1193 std::vector<GLfloat> clearValue = {{0.0f, 1.0f, 0.0f, 1.0f}};
1194 glClearBufferfv(GL_COLOR, 1, clearValue.data());
1195
1196 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
1197 EXPECT_GL_NO_ERROR();
1198 }
1199
1200 // Test that clearing the depth and stencil buffers when the framebuffer only has a color attachment
1201 // does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepthStencil)1202 TEST_P(FramebufferTest_ES3, ClearNonexistentDepthStencil)
1203 {
1204 GLRenderbuffer rbo;
1205 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1206 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1207
1208 GLFramebuffer fbo;
1209 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1210 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1211
1212 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1213
1214 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
1215 EXPECT_GL_NO_ERROR();
1216 }
1217
1218 // Test that clearing a color attachment that has been deleted doesn't crash.
TEST_P(FramebufferTest_ES3,ClearDeletedAttachment)1219 TEST_P(FramebufferTest_ES3, ClearDeletedAttachment)
1220 {
1221 // An INVALID_FRAMEBUFFER_OPERATION error was seen in this test on Mac, not sure where it might
1222 // be originating from. http://anglebug.com/2834
1223 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
1224
1225 GLFramebuffer fbo;
1226 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1227
1228 // There used to be a bug where some draw buffer state used to remain set even after the
1229 // attachment was detached via deletion. That's why we create, attach and delete this RBO here.
1230 GLuint rbo = 0u;
1231 glGenRenderbuffers(1, &rbo);
1232 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1233 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1234 glDeleteRenderbuffers(1, &rbo);
1235
1236 // There needs to be at least one color attachment to prevent early out from the clear calls.
1237 GLRenderbuffer rbo2;
1238 glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
1239 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1240 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo2);
1241
1242 ASSERT_GL_NO_ERROR();
1243
1244 // There's no error specified for clearing nonexistent buffers, it's simply a no-op, so we
1245 // expect no GL errors below.
1246 std::array<GLfloat, 4> floatClearValue = {0.0f, 0.0f, 0.0f, 0.0f};
1247 glClearBufferfv(GL_COLOR, 0, floatClearValue.data());
1248 EXPECT_GL_NO_ERROR();
1249 std::array<GLuint, 4> uintClearValue = {0u, 0u, 0u, 0u};
1250 glClearBufferuiv(GL_COLOR, 0, uintClearValue.data());
1251 EXPECT_GL_NO_ERROR();
1252 std::array<GLint, 4> intClearValue = {0, 0, 0, 0};
1253 glClearBufferiv(GL_COLOR, 0, intClearValue.data());
1254 EXPECT_GL_NO_ERROR();
1255 }
1256
1257 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentSmallToLarge)1258 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
1259 {
1260 GLFramebuffer fbo;
1261 GLTexture smallTexture;
1262 GLTexture largeTexture;
1263
1264 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1265 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1266
1267 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1268
1269 // Bind the small texture
1270 glBindTexture(GL_TEXTURE_2D, smallTexture);
1271 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1272 GL_UNSIGNED_BYTE, nullptr);
1273 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1275 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
1276 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1277
1278 // Draw to FBO backed by the small texture
1279 glUseProgram(greenProgram);
1280 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1281 ASSERT_GL_NO_ERROR();
1282 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1283 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
1284
1285 // Change the attachment to the larger texture that fills the window
1286 glBindTexture(GL_TEXTURE_2D, largeTexture);
1287 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1288 GL_UNSIGNED_BYTE, nullptr);
1289 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1290 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1291 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
1292 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1293
1294 // Draw to FBO backed by the large texture
1295 glUseProgram(blueProgram);
1296 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1297 ASSERT_GL_NO_ERROR();
1298 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1299 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
1300 }
1301
1302 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentLargeToSmall)1303 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
1304 {
1305 GLFramebuffer fbo;
1306 GLTexture smallTexture;
1307 GLTexture largeTexture;
1308
1309 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1310 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1311
1312 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1313
1314 // Bind the large texture
1315 glBindTexture(GL_TEXTURE_2D, largeTexture);
1316 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1317 GL_UNSIGNED_BYTE, nullptr);
1318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1320 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
1321 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1322
1323 // Draw to FBO backed by the large texture
1324 glUseProgram(blueProgram);
1325 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1326 ASSERT_GL_NO_ERROR();
1327 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1328 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
1329
1330 // Change the attachment to the smaller texture
1331 glBindTexture(GL_TEXTURE_2D, smallTexture);
1332 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1333 GL_UNSIGNED_BYTE, nullptr);
1334 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1336 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
1337 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1338
1339 // Draw to FBO backed by the small texture
1340 glUseProgram(greenProgram);
1341 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1342 ASSERT_GL_NO_ERROR();
1343 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1344 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
1345 }
1346
1347 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureLargeToSmall)1348 TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
1349 {
1350 GLFramebuffer fbo;
1351 GLTexture texture;
1352
1353 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1354 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1355
1356 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1357
1358 // Allocate a large texture
1359 glBindTexture(GL_TEXTURE_2D, texture);
1360 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1361 GL_UNSIGNED_BYTE, nullptr);
1362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1364 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1365 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1366
1367 // Draw to FBO backed by the large texture
1368 glUseProgram(blueProgram);
1369 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1370 ASSERT_GL_NO_ERROR();
1371 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1372 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
1373
1374 // Shrink the texture
1375 glBindTexture(GL_TEXTURE_2D, texture);
1376 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1377 GL_UNSIGNED_BYTE, nullptr);
1378 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1380 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1381 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1382
1383 // Draw to FBO backed by the small texture
1384 glUseProgram(greenProgram);
1385 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1386 ASSERT_GL_NO_ERROR();
1387 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1388 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
1389 }
1390
1391 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureSmallToLarge)1392 TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
1393 {
1394 GLFramebuffer fbo;
1395 GLTexture texture;
1396
1397 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1398 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1399
1400 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1401
1402 // Allocate a small texture
1403 glBindTexture(GL_TEXTURE_2D, texture);
1404 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1405 GL_UNSIGNED_BYTE, nullptr);
1406 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1407 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1408 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1409 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1410
1411 // Draw to FBO backed by the large texture
1412 glUseProgram(blueProgram);
1413 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1414 ASSERT_GL_NO_ERROR();
1415 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1416 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
1417
1418 // Grow the texture
1419 glBindTexture(GL_TEXTURE_2D, texture);
1420 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1421 GL_UNSIGNED_BYTE, nullptr);
1422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1424 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1425 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1426
1427 // Draw to FBO backed by the small texture
1428 glUseProgram(greenProgram);
1429 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1430 ASSERT_GL_NO_ERROR();
1431 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1432 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
1433 }
1434
1435 // Test that fewer outputs than framebuffer attachments doesn't crash. This causes a Vulkan
1436 // validation warning, but should not be fatal.
TEST_P(FramebufferTest_ES3,FewerShaderOutputsThanAttachments)1437 TEST_P(FramebufferTest_ES3, FewerShaderOutputsThanAttachments)
1438 {
1439 constexpr char kFS[] = R"(#version 300 es
1440 precision highp float;
1441
1442 layout(location = 0) out vec4 color0;
1443 layout(location = 1) out vec4 color1;
1444 layout(location = 2) out vec4 color2;
1445
1446 void main()
1447 {
1448 color0 = vec4(1.0, 0.0, 0.0, 1.0);
1449 color1 = vec4(0.0, 1.0, 0.0, 1.0);
1450 color2 = vec4(0.0, 0.0, 1.0, 1.0);
1451 }
1452 )";
1453
1454 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1455
1456 constexpr GLint kDrawBufferCount = 4;
1457
1458 GLint maxDrawBuffers;
1459 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1460 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
1461
1462 GLTexture textures[kDrawBufferCount];
1463
1464 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
1465 {
1466 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
1467 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1468 GL_UNSIGNED_BYTE, nullptr);
1469 }
1470
1471 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
1472 GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
1473
1474 GLFramebuffer fbo;
1475 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1476
1477 // Enable all draw buffers.
1478 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
1479 {
1480 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
1481 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
1482 textures[texIndex], 0);
1483 }
1484 glDrawBuffers(kDrawBufferCount, allBufs);
1485
1486 // Draw with simple program.
1487 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1488 ASSERT_GL_NO_ERROR();
1489 }
1490
1491 // Test that GL_RGB9_E5 is renderable with the extension.
TEST_P(FramebufferTest_ES3,RenderSharedExponent)1492 TEST_P(FramebufferTest_ES3, RenderSharedExponent)
1493 {
1494 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_render_shared_exponent"));
1495
1496 GLTexture tex;
1497 glBindTexture(GL_TEXTURE_2D, tex);
1498 const uint32_t data = 0x80000100; // Red
1499 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, &data);
1500 ASSERT_GL_NO_ERROR();
1501
1502 GLFramebuffer readFbo;
1503 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1504 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1505 ASSERT_GL_NO_ERROR();
1506
1507 EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatRed);
1508
1509 GLRenderbuffer rbo;
1510 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1511 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB9_E5, 1, 1);
1512 ASSERT_GL_NO_ERROR();
1513
1514 GLFramebuffer drawFbo;
1515 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
1516 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1517 ASSERT_GL_NO_ERROR();
1518
1519 glClearColor(0.0, 1.0, 0.0, 1.0);
1520 glClear(GL_COLOR_BUFFER_BIT);
1521 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
1522 EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatGreen);
1523
1524 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1525 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1526 ASSERT_GL_NO_ERROR();
1527
1528 glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
1529 EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatRed);
1530 }
1531
1532 // Test color write masks with GL_RGB9_E5 color buffers.
TEST_P(FramebufferTest_ES3,RenderSharedExponentWithMask)1533 TEST_P(FramebufferTest_ES3, RenderSharedExponentWithMask)
1534 {
1535 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_render_shared_exponent"));
1536
1537 constexpr char kFS[] = R"(#version 300 es
1538 precision highp float;
1539 layout(location = 0) out vec4 color0;
1540 layout(location = 1) out vec4 color1;
1541 void main()
1542 {
1543 color0 = vec4(1.0, 0.0, 0.0, 1.0);
1544 color1 = vec4(0.0, 1.0, 0.0, 1.0);
1545 })";
1546
1547 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1548
1549 GLFramebuffer fbo;
1550 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1551
1552 GLRenderbuffer rb0;
1553 glBindRenderbuffer(GL_RENDERBUFFER, rb0);
1554 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB9_E5, 4, 4);
1555 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
1556
1557 GLRenderbuffer rb1;
1558 glBindRenderbuffer(GL_RENDERBUFFER, rb1);
1559 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 4, 4);
1560 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rb1);
1561
1562 ASSERT_GL_NO_ERROR();
1563 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1564
1565 for (int mask = 0; mask < 16; mask++)
1566 {
1567 glColorMask(mask & 1, mask & 2, mask & 4, mask & 8);
1568 for (const bool enableSharedExponentAttachment : {false, true})
1569 {
1570 GLenum bufs[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
1571 bufs[0] = enableSharedExponentAttachment ? GL_COLOR_ATTACHMENT0 : GL_NONE;
1572 glDrawBuffers(2, bufs);
1573
1574 auto expectError = [](bool enabled, int mask) {
1575 if (!enabled || mask == 0 || mask == 8 || mask == 7 || mask == 15)
1576 {
1577 EXPECT_GL_NO_ERROR();
1578 }
1579 else
1580 {
1581 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1582 }
1583 };
1584
1585 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
1586 expectError(enableSharedExponentAttachment, mask);
1587
1588 glClear(GL_COLOR_BUFFER_BIT);
1589 expectError(enableSharedExponentAttachment, mask);
1590
1591 GLfloat clearValuef[4] = {};
1592 glClearBufferfv(GL_COLOR, 0, clearValuef);
1593 expectError(enableSharedExponentAttachment, mask);
1594 glClearBufferfv(GL_COLOR, 1, clearValuef);
1595 EXPECT_GL_NO_ERROR();
1596 }
1597 }
1598 }
1599
1600 // Test that R8_SNORM, RG8_SNORM, and RGBA8_SNORM are renderable with the extension.
TEST_P(FramebufferTest_ES3,RenderSnorm8)1601 TEST_P(FramebufferTest_ES3, RenderSnorm8)
1602 {
1603 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_render_snorm"));
1604
1605 auto test = [&](GLenum format) {
1606 GLRenderbuffer rbo;
1607 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1608 glRenderbufferStorage(GL_RENDERBUFFER, format, 4, 4);
1609 ASSERT_GL_NO_ERROR();
1610
1611 GLFramebuffer fbo;
1612 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1613 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1614 ASSERT_GL_NO_ERROR();
1615
1616 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1617
1618 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1619 glUseProgram(program);
1620 GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1621 glUniform4f(colorLocation, -1.0f, -0.5f, -0.25f, -0.125f);
1622 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
1623 ASSERT_GL_NO_ERROR();
1624
1625 if (format == GL_R8_SNORM)
1626 {
1627 EXPECT_PIXEL_8S_NEAR(0, 0, -127, 0, 0, 127, 2);
1628 }
1629 else if (format == GL_RG8_SNORM)
1630 {
1631 EXPECT_PIXEL_8S_NEAR(0, 0, -127, -64, 0, 127, 2);
1632 }
1633 else if (format == GL_RGBA8_SNORM)
1634 {
1635 EXPECT_PIXEL_8S_NEAR(0, 0, -127, -64, -32, -16, 2);
1636 }
1637 };
1638
1639 test(GL_R8_SNORM);
1640 test(GL_RG8_SNORM);
1641 test(GL_RGBA8_SNORM);
1642 }
1643
1644 // Test that non-trivial, e.g., reversed, blits are supported for signed normalized formats.
TEST_P(FramebufferTest_ES3,BlitReversedSnorm8)1645 TEST_P(FramebufferTest_ES3, BlitReversedSnorm8)
1646 {
1647 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_render_snorm"));
1648
1649 auto test = [&](GLenum format) {
1650 GLRenderbuffer rbo1;
1651 glBindRenderbuffer(GL_RENDERBUFFER, rbo1);
1652 glRenderbufferStorage(GL_RENDERBUFFER, format, 4, 4);
1653 ASSERT_GL_NO_ERROR();
1654
1655 GLFramebuffer fbo1;
1656 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo1);
1657 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo1);
1658 ASSERT_GL_NO_ERROR();
1659
1660 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1661
1662 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1663 glUseProgram(program);
1664 GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1665 glUniform4f(colorLocation, -1.0f, -0.5f, -0.25f, -0.125f);
1666 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
1667 ASSERT_GL_NO_ERROR();
1668
1669 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo1);
1670
1671 GLRenderbuffer rbo2;
1672 glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
1673 glRenderbufferStorage(GL_RENDERBUFFER, format, 4, 4);
1674 ASSERT_GL_NO_ERROR();
1675
1676 GLFramebuffer fbo2;
1677 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo2);
1678 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo2);
1679 ASSERT_GL_NO_ERROR();
1680
1681 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1682
1683 glBlitFramebuffer(0, 0, 4, 4, 4, 4, 0, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1684 ASSERT_GL_NO_ERROR();
1685
1686 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo2);
1687
1688 if (format == GL_R8_SNORM)
1689 {
1690 EXPECT_PIXEL_8S_NEAR(0, 0, -127, 0, 0, 127, 2);
1691 }
1692 else if (format == GL_RG8_SNORM)
1693 {
1694 EXPECT_PIXEL_8S_NEAR(0, 0, -127, -64, 0, 127, 2);
1695 }
1696 else if (format == GL_RGBA8_SNORM)
1697 {
1698 EXPECT_PIXEL_8S_NEAR(0, 0, -127, -64, -32, -16, 2);
1699 }
1700 };
1701
1702 test(GL_R8_SNORM);
1703 test(GL_RG8_SNORM);
1704 test(GL_RGBA8_SNORM);
1705 }
1706
1707 // Test that R16_SNORM, RG16_SNORM, and RGBA16_SNORM are renderable with the extension.
TEST_P(FramebufferTest_ES3,RenderSnorm16)1708 TEST_P(FramebufferTest_ES3, RenderSnorm16)
1709 {
1710 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_render_snorm"));
1711 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
1712
1713 auto test = [&](GLenum format) {
1714 GLRenderbuffer rbo;
1715 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1716 glRenderbufferStorage(GL_RENDERBUFFER, format, 4, 4);
1717 ASSERT_GL_NO_ERROR();
1718
1719 GLFramebuffer fbo;
1720 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1721 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1722 ASSERT_GL_NO_ERROR();
1723
1724 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1725
1726 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1727 glUseProgram(program);
1728 GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1729 glUniform4f(colorLocation, -1.0f, -0.5f, -0.25f, -0.125f);
1730 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
1731 ASSERT_GL_NO_ERROR();
1732
1733 if (format == GL_R16_SNORM_EXT)
1734 {
1735 EXPECT_PIXEL_16S_NEAR(0, 0, -32767, 0, 0, 32767, 2);
1736 }
1737 else if (format == GL_RG16_SNORM_EXT)
1738 {
1739 EXPECT_PIXEL_16S_NEAR(0, 0, -32767, -16383, 0, 32767, 2);
1740 }
1741 else if (format == GL_RGBA16_SNORM_EXT)
1742 {
1743 EXPECT_PIXEL_16S_NEAR(0, 0, -32767, -16383, -8191, -4095, 2);
1744 }
1745 };
1746
1747 test(GL_R16_SNORM_EXT);
1748 test(GL_RG16_SNORM_EXT);
1749 test(GL_RGBA16_SNORM_EXT);
1750 }
1751
1752 class FramebufferTest_ES3Metal : public FramebufferTest_ES3
1753 {};
1754
1755 // Metal, iOS has a limit of the number of bits that can be output
1756 // to color attachments. Test we're enforcing that limit.
TEST_P(FramebufferTest_ES3Metal,TooManyBitsGeneratesFramebufferUnsupported)1757 TEST_P(FramebufferTest_ES3Metal, TooManyBitsGeneratesFramebufferUnsupported)
1758 {
1759 ANGLE_SKIP_TEST_IF(
1760 !getEGLWindow()->isFeatureEnabled(Feature::LimitMaxColorTargetBitsForTesting));
1761
1762 GLint maxDrawBuffers;
1763 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1764
1765 GLFramebuffer framebuffer;
1766
1767 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1768
1769 // Test maxDrawBuffers * RGBA8UI works.
1770 {
1771 std::vector<GLTexture> textures(maxDrawBuffers);
1772 for (GLint i = 0; i < maxDrawBuffers; ++i)
1773 {
1774 glBindTexture(GL_TEXTURE_2D, textures[i]);
1775 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 1, 1);
1776 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1777 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1778 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
1779 textures[i], 0);
1780 }
1781 EXPECT_GL_NO_ERROR();
1782 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1783 }
1784
1785 // Test maxDrawBuffers * RGBA32UI does not work.
1786 {
1787 std::vector<GLTexture> textures(maxDrawBuffers);
1788 for (GLint i = 0; i < maxDrawBuffers; ++i)
1789 {
1790 glBindTexture(GL_TEXTURE_2D, textures[i]);
1791 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 1, 1);
1792 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1793 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1794 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
1795 textures[i], 0);
1796 }
1797 EXPECT_GL_NO_ERROR();
1798 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_UNSUPPORTED, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1799 }
1800 }
1801
1802 // Metal, iOS has a limit of the number of bits that can be output
1803 // to color attachments. Test we're enforcing that limit.
1804 // This test is separate from the one above as it's possible
1805 // glCheckFramebufferStatus might cache some calculation so we
1806 // don't call here to ensure we get INVALID_FRAMEBUFFER_OPERATION
1807 // when drawing.
TEST_P(FramebufferTest_ES3Metal,TooManyBitsGeneratesInvalidFramebufferOperation)1808 TEST_P(FramebufferTest_ES3Metal, TooManyBitsGeneratesInvalidFramebufferOperation)
1809 {
1810 ANGLE_SKIP_TEST_IF(
1811 !getEGLWindow()->isFeatureEnabled(Feature::LimitMaxColorTargetBitsForTesting));
1812
1813 GLint maxDrawBuffers;
1814 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1815
1816 GLFramebuffer framebuffer;
1817 std::vector<GLTexture> textures(maxDrawBuffers);
1818 std::vector<GLenum> drawBuffers(maxDrawBuffers, GL_NONE);
1819
1820 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1821
1822 std::stringstream fs;
1823
1824 fs << R"(#version 300 es
1825 precision highp float;
1826 out uvec4 fragColor[)"
1827 << maxDrawBuffers << R"(];
1828 void main() {
1829 )";
1830
1831 for (GLint i = 0; i < maxDrawBuffers; ++i)
1832 {
1833 fs << " fragColor[" << i << "] = uvec4(" << i << ", " << i * 2 << ", " << i * 4 << ", "
1834 << i * 8 << ");\n";
1835 drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
1836 glBindTexture(GL_TEXTURE_2D, textures[i]);
1837 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
1838 nullptr);
1839 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1840 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1841 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i],
1842 0);
1843 }
1844 EXPECT_GL_NO_ERROR();
1845
1846 fs << "}";
1847
1848 constexpr const char vs[] = R"(#version 300 es
1849 void main() {
1850 gl_Position = vec4(0, 0, 0, 1);
1851 gl_PointSize = 1.0;
1852 }
1853 )";
1854
1855 GLProgram program;
1856 program.makeRaster(vs, fs.str().c_str());
1857 glUseProgram(program);
1858 EXPECT_GL_NO_ERROR();
1859
1860 // Validate we can draw to maxDrawBuffers attachments
1861 glDrawBuffers(maxDrawBuffers, drawBuffers.data());
1862 glDrawArrays(GL_POINTS, 0, 1);
1863 EXPECT_GL_NO_ERROR();
1864
1865 for (GLint i = 0; i < maxDrawBuffers; ++i)
1866 {
1867 glBindTexture(GL_TEXTURE_2D, textures[i]);
1868 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
1869 nullptr);
1870 }
1871 EXPECT_GL_NO_ERROR();
1872
1873 glDrawArrays(GL_POINTS, 0, 1);
1874 EXPECT_GLENUM_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, glGetError());
1875 }
1876
1877 class FramebufferTestWithFormatFallback : public ANGLETest<>
1878 {
1879 protected:
FramebufferTestWithFormatFallback()1880 FramebufferTestWithFormatFallback()
1881 {
1882 setWindowWidth(16);
1883 setWindowHeight(16);
1884 setConfigRedBits(8);
1885 setConfigGreenBits(8);
1886 setConfigBlueBits(8);
1887 setConfigAlphaBits(8);
1888 setConfigDepthBits(24);
1889 setConfigStencilBits(8);
1890 }
1891
1892 void texImageFollowedByFBORead(GLenum internalFormat, GLenum type);
1893 void blitCopyFollowedByFBORead(GLenum internalFormat, GLenum type);
1894 void copyTexImageFollowedBySampling(GLenum internalFormat, GLenum type);
1895 void cubeTexImageFollowedByFBORead(GLenum internalFormat, GLenum type);
1896 GLushort convertGLColorToUShort(GLenum internalFormat, const GLColor &color);
1897 static constexpr GLsizei kTexWidth = 16;
1898 static constexpr GLsizei kTexHeight = 16;
1899 static constexpr GLsizei kMaxLevel = 4;
1900 };
1901
convertGLColorToUShort(GLenum internalFormat,const GLColor & color)1902 GLushort FramebufferTestWithFormatFallback::convertGLColorToUShort(GLenum internalFormat,
1903 const GLColor &color)
1904 {
1905 GLushort r, g, b, a;
1906 switch (internalFormat)
1907 {
1908 case GL_RGB5_A1:
1909 r = (color.R >> 3) << 11;
1910 g = (color.G >> 3) << 6;
1911 b = (color.B >> 3) << 1;
1912 a = color.A >> 7;
1913 break;
1914 case GL_RGBA4:
1915 r = (color.R >> 4) << 12;
1916 g = (color.G >> 4) << 8;
1917 b = (color.B >> 4) << 4;
1918 a = color.A >> 4;
1919 break;
1920 default:
1921 UNREACHABLE();
1922 r = 0;
1923 g = 0;
1924 b = 0;
1925 a = 0;
1926 break;
1927 }
1928 return r | g | b | a;
1929 }
1930
1931 // Test texture format fallback while it has staged updates.
texImageFollowedByFBORead(GLenum internalFormat,GLenum type)1932 void FramebufferTestWithFormatFallback::texImageFollowedByFBORead(GLenum internalFormat,
1933 GLenum type)
1934 {
1935 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1936 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1937 ASSERT_NE(-1, textureLocation);
1938 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1939 ASSERT_NE(-1, lodLocation);
1940
1941 const GLColor kColor = GLColor::blue;
1942
1943 for (int loop = 0; loop < 4; loop++)
1944 {
1945 GLTexture texture;
1946 glBindTexture(GL_TEXTURE_2D, texture);
1947 const GLushort u16Color = convertGLColorToUShort(internalFormat, kColor);
1948 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1949 if (loop == 0 || loop == 2)
1950 {
1951 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1952 pixels.data());
1953 }
1954 else
1955 {
1956 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kTexWidth, kTexHeight);
1957 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, type,
1958 pixels.data());
1959 }
1960 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1961 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1962
1963 if (loop >= 2)
1964 {
1965 // Draw quad using texture
1966 glUseProgram(program);
1967 glActiveTexture(GL_TEXTURE0);
1968 glBindTexture(GL_TEXTURE_2D, texture);
1969 glClearColor(0, 0, 0, 1);
1970 glClear(GL_COLOR_BUFFER_BIT);
1971 glUniform1f(lodLocation, 0);
1972 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1973 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
1974 ASSERT_GL_NO_ERROR();
1975 }
1976
1977 // attach blue texture to FBO
1978 GLFramebuffer fbo;
1979 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1980 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1981 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1982 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, kColor.R, kColor.G, kColor.B, kColor.A);
1983 ASSERT_GL_NO_ERROR();
1984 }
1985 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_TexImage)1986 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_TexImage)
1987 {
1988 texImageFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1989 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_TexImage)1990 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_TexImage)
1991 {
1992 texImageFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1993 }
1994
1995 // Test texture format fallback while it has staged updates and then do copyTexImage2D and followed
1996 // by sampling.
copyTexImageFollowedBySampling(GLenum internalFormat,GLenum type)1997 void FramebufferTestWithFormatFallback::copyTexImageFollowedBySampling(GLenum internalFormat,
1998 GLenum type)
1999 {
2000 const GLColor kColor = GLColor::blue;
2001 // Create blue texture
2002 GLTexture blueTex2D;
2003 glBindTexture(GL_TEXTURE_2D, blueTex2D);
2004 const GLushort u16Color = convertGLColorToUShort(internalFormat, kColor);
2005 std::vector<GLushort> bluePixels(kTexWidth * kTexHeight, u16Color);
2006 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2007 bluePixels.data());
2008 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2009 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2010
2011 // attach blue texture to FBO and read back to verify. This should trigger format conversion
2012 GLFramebuffer blueFbo;
2013 glBindFramebuffer(GL_FRAMEBUFFER, blueFbo);
2014 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blueTex2D, 0);
2015 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2016 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 0, 0, 255, 255);
2017 ASSERT_GL_NO_ERROR();
2018
2019 // Create red texture
2020 GLTexture copyTex2D;
2021 glBindTexture(GL_TEXTURE_2D, copyTex2D);
2022 std::vector<GLushort> redPixels(kTexWidth * kTexHeight, 0xF801);
2023 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2024 redPixels.data());
2025 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2026 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2027
2028 // CopyTexImage from blue to red
2029 glCopyTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 0, 0, kTexWidth, kTexHeight, 0);
2030 ASSERT_GL_NO_ERROR();
2031
2032 // Draw with copyTex2D
2033 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2034 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
2035 glUseProgram(program);
2036 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2037 ASSERT_NE(-1, textureLocation);
2038 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2039 ASSERT_NE(-1, lodLocation);
2040 glActiveTexture(GL_TEXTURE0);
2041 glBindTexture(GL_TEXTURE_2D, copyTex2D);
2042 glClearColor(0, 1, 0, 1);
2043 glClear(GL_COLOR_BUFFER_BIT);
2044 glUniform1f(lodLocation, 0);
2045 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2046 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, kColor.R, kColor.G, kColor.B,
2047 kColor.A);
2048 ASSERT_GL_NO_ERROR();
2049 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_CopyTexImage)2050 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_CopyTexImage)
2051 {
2052 copyTexImageFollowedBySampling(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
2053 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_CopyTexImage)2054 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_CopyTexImage)
2055 {
2056 copyTexImageFollowedBySampling(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
2057 }
2058
2059 // Test texture format fallback while it has staged updates and then do FBO blit and followed by
2060 // copyTexImage2D.
blitCopyFollowedByFBORead(GLenum internalFormat,GLenum type)2061 void FramebufferTestWithFormatFallback::blitCopyFollowedByFBORead(GLenum internalFormat,
2062 GLenum type)
2063 {
2064 for (int loop = 0; loop < 2; loop++)
2065 {
2066 // Create blue texture
2067 GLTexture blueTex2D;
2068 glBindTexture(GL_TEXTURE_2D, blueTex2D);
2069 GLushort u16Color = convertGLColorToUShort(internalFormat, GLColor::blue);
2070 std::vector<GLushort> bluePixels(kTexWidth * kTexHeight, u16Color);
2071 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2072 bluePixels.data());
2073 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2074 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2075
2076 // attach blue texture to FBO
2077 GLFramebuffer readFbo;
2078 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2079 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blueTex2D,
2080 0);
2081 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2082
2083 GLTexture redTex2D;
2084 GLRenderbuffer renderBuffer;
2085 GLFramebuffer drawFbo;
2086 if (loop == 0)
2087 {
2088 glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
2089 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, kTexWidth, kTexHeight);
2090
2091 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
2092 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2093 renderBuffer);
2094 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2095 glClearColor(1.0, 0.0, 0.0, 1.0);
2096 glClear(GL_COLOR_BUFFER_BIT);
2097 }
2098 else
2099 {
2100 glBindTexture(GL_TEXTURE_2D, redTex2D);
2101 u16Color = convertGLColorToUShort(internalFormat, GLColor::red);
2102 std::vector<GLushort> redPixels(kTexWidth * kTexHeight, u16Color);
2103 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2104 redPixels.data());
2105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2107
2108 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
2109 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2110 redTex2D, 0);
2111 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2112 }
2113
2114 // Blit
2115 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2116 glBlitFramebuffer(0, 0, kTexWidth, kTexHeight, 0, 0, kTexWidth, kTexHeight,
2117 GL_COLOR_BUFFER_BIT, GL_NEAREST);
2118 ASSERT_GL_NO_ERROR();
2119
2120 GLFramebuffer readFbo2;
2121 if (loop == 0)
2122 {
2123 // CopyTexImage from renderBuffer to copyTex2D
2124 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo2);
2125 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2126 renderBuffer);
2127 }
2128 else
2129 {
2130
2131 // CopyTexImage from redTex2D to copyTex2D
2132 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo2);
2133 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2134 redTex2D, 0);
2135 }
2136 GLTexture copyTex2D;
2137 glBindTexture(GL_TEXTURE_2D, copyTex2D);
2138 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kTexWidth, kTexHeight, 0);
2139 ASSERT_GL_NO_ERROR();
2140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2141 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2142 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2143 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2144 glBindTexture(GL_TEXTURE_2D, 0);
2145
2146 // Read out red texture
2147 GLFramebuffer readFbo3;
2148 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo3);
2149 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex2D,
2150 0);
2151 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2152 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 0, 0, 255, 255);
2153 ASSERT_GL_NO_ERROR();
2154 }
2155 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_BlitCopyTexImage)2156 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_BlitCopyTexImage)
2157 {
2158 blitCopyFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
2159 }
TEST_P(FramebufferTestWithFormatFallback,RGBA4444_BlitCopyTexImage)2160 TEST_P(FramebufferTestWithFormatFallback, RGBA4444_BlitCopyTexImage)
2161 {
2162 blitCopyFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
2163 }
2164
2165 // Test texture format fallback while it has staged updates, specially for cubemap target.
cubeTexImageFollowedByFBORead(GLenum internalFormat,GLenum type)2166 void FramebufferTestWithFormatFallback::cubeTexImageFollowedByFBORead(GLenum internalFormat,
2167 GLenum type)
2168 {
2169 const GLColor kColors[6] = {GLColor::red, GLColor::green, GLColor::blue,
2170 GLColor::cyan, GLColor::yellow, GLColor::magenta};
2171 GLTexture cubeTex2D;
2172 glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex2D);
2173 for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2174 target++)
2175 {
2176 int j = target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2177 const GLushort u16Color = convertGLColorToUShort(internalFormat, kColors[j]);
2178 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2179 glTexImage2D(target, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2180 pixels.data());
2181 }
2182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2184
2185 // attach blue texture to FBO
2186 GLFramebuffer fbo;
2187 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2188 for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2189 target++)
2190 {
2191 GLint j = target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2192 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, cubeTex2D, 0);
2193 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2194 EXPECT_PIXEL_COLOR_EQ(kTexWidth / 2, kTexHeight / 2, kColors[j]) << "face " << j;
2195 }
2196 ASSERT_GL_NO_ERROR();
2197 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_CubeTexImage)2198 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_CubeTexImage)
2199 {
2200 cubeTexImageFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
2201 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_CubeTexImage)2202 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_CubeTexImage)
2203 {
2204 cubeTexImageFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
2205 }
2206
2207 // Tests that the out-of-range staged update is reformatted when mipmapping is enabled, but not
2208 // before it.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_OutOfRangeStagedUpdateReformated)2209 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_OutOfRangeStagedUpdateReformated)
2210 {
2211 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
2212 glUseProgram(program);
2213 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2214 ASSERT_NE(-1, textureLocation);
2215 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2216 ASSERT_NE(-1, lodLocation);
2217
2218 GLTexture texture;
2219 glBindTexture(GL_TEXTURE_2D, texture);
2220 GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
2221 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2222 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2223 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2224 u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::green);
2225 pixels.assign(kTexWidth * kTexHeight, u16Color);
2226 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
2227 GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
2228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2229 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2230
2231 // Draw quad
2232 glActiveTexture(GL_TEXTURE0);
2233 glBindTexture(GL_TEXTURE_2D, texture);
2234 glUniform1f(lodLocation, 0);
2235 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2236 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2237
2238 // Now trigger format conversion
2239 GLFramebuffer readFbo;
2240 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2241 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2242 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2243 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowWidth() / 2, 255, 0, 0, 255);
2244
2245 // update level0 with compatible data and enable mipmap
2246 u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::blue);
2247 pixels.assign(kTexWidth * kTexHeight, u16Color);
2248 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2249 GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
2250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
2251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
2253
2254 // Draw quad with lod0 and lod1 and verify color
2255 glUniform1f(lodLocation, 0);
2256 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2257 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
2258 glUniform1f(lodLocation, 1);
2259 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2260 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
2261 ASSERT_GL_NO_ERROR();
2262 }
2263
2264 // Tests that the texture is reformatted when the clear is done through the draw path.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_MaskedClear)2265 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_MaskedClear)
2266 {
2267 for (int loop = 0; loop < 2; loop++)
2268 {
2269 GLTexture texture;
2270 glBindTexture(GL_TEXTURE_2D, texture);
2271 GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
2272 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2273 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2274 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2277
2278 if (loop == 0)
2279 {
2280 // Draw quad
2281 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(),
2282 essl3_shaders::fs::Texture2DLod());
2283 glUseProgram(program);
2284 GLint textureLocation =
2285 glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2286 ASSERT_NE(-1, textureLocation);
2287 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2288 ASSERT_NE(-1, lodLocation);
2289 glActiveTexture(GL_TEXTURE0);
2290 glBindTexture(GL_TEXTURE_2D, texture);
2291 glClearColor(0, 0, 0, 1);
2292 glClear(GL_COLOR_BUFFER_BIT);
2293 glUniform1f(lodLocation, 0);
2294 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2295 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2296 ASSERT_GL_NO_ERROR();
2297 }
2298
2299 // Now trigger format conversion with masked clear
2300 GLFramebuffer fbo;
2301 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2302 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2303 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2304 glClearColor(0, 1, 1, 1);
2305 glColorMask(false, true, false, false);
2306 glClear(GL_COLOR_BUFFER_BIT);
2307 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 255, 255, 0, 255);
2308 ASSERT_GL_NO_ERROR();
2309 }
2310 }
2311
2312 // Tests that glGenerateMipmap works when the format is converted to renderable..
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_GenerateMipmap)2313 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_GenerateMipmap)
2314 {
2315 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
2316 glUseProgram(program);
2317 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2318 ASSERT_NE(-1, textureLocation);
2319 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2320 ASSERT_NE(-1, lodLocation);
2321
2322 for (int loop = 0; loop < 4; loop++)
2323 {
2324 GLTexture texture;
2325 glBindTexture(GL_TEXTURE_2D, texture);
2326 GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
2327 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2328 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2329 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2330 u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::green);
2331 pixels.assign(kTexWidth * kTexHeight, u16Color);
2332 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
2333 GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
2334 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2336
2337 if (loop == 0 || loop == 2)
2338 {
2339 // Draw quad
2340 glUniform1f(lodLocation, 0);
2341 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2342 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2343 ASSERT_GL_NO_ERROR();
2344 }
2345
2346 if (loop > 2)
2347 {
2348 // Now trigger format conversion
2349 GLFramebuffer readFbo;
2350 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2351 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2352 texture, 0);
2353 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2354 }
2355
2356 // GenerateMipmap
2357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
2358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2359 glGenerateMipmap(GL_TEXTURE_2D);
2360
2361 // Verify each lod
2362 for (int lod = 0; lod <= kMaxLevel; lod++)
2363 {
2364 glUniform1f(lodLocation, lod);
2365 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2366 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2367 }
2368 ASSERT_GL_NO_ERROR();
2369 }
2370 }
2371
2372 // Tests that when reformatting the image, incompatible updates don't cause a problem.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_InCompatibleFormat)2373 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_InCompatibleFormat)
2374 {
2375 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
2376 glUseProgram(program);
2377 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2378 ASSERT_NE(-1, textureLocation);
2379 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2380 ASSERT_NE(-1, lodLocation);
2381
2382 for (int loop = 0; loop < 4; loop++)
2383 {
2384 GLTexture texture;
2385 glBindTexture(GL_TEXTURE_2D, texture);
2386 // Define a texture with lod0 and lod1 with two different effective internal formats or size
2387 GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
2388 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2389 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2390 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2391 if (loop < 2)
2392 {
2393 u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::green);
2394 pixels.assign(kTexWidth * kTexHeight, u16Color);
2395 // bad effective internal format
2396 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
2397 GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
2398 }
2399 else
2400 {
2401 u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::green);
2402 pixels.assign(kTexWidth * kTexHeight, u16Color);
2403 // bad size
2404 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2405 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2406 }
2407 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
2408 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2409
2410 // Now trigger format conversion and verify lod0
2411 GLFramebuffer readFbo;
2412 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2413 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,
2414 0);
2415 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2416 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 255, 0, 0, 255);
2417
2418 if (loop == 1 || loop == 3)
2419 {
2420 // Disable mipmap and sample from lod0 and verify
2421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2423 glUniform1f(lodLocation, 0);
2424 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2425 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2426 }
2427 }
2428 }
2429
2430 class FramebufferTest_ES31 : public ANGLETest<>
2431 {
2432 protected:
validateSamplePass(GLQuery & query,GLint width,GLint height)2433 void validateSamplePass(GLQuery &query, GLint width, GLint height)
2434 {
2435 GLuint passedCount;
2436
2437 glUniform2i(0, width - 1, height - 1);
2438 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
2439 glDrawArrays(GL_TRIANGLES, 0, 6);
2440 glEndQuery(GL_ANY_SAMPLES_PASSED);
2441 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
2442 EXPECT_GT(static_cast<GLint>(passedCount), 0);
2443
2444 glUniform2i(0, width - 1, height);
2445 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
2446 glDrawArrays(GL_TRIANGLES, 0, 6);
2447 glEndQuery(GL_ANY_SAMPLES_PASSED);
2448 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
2449 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
2450
2451 glUniform2i(0, width, height - 1);
2452 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
2453 glDrawArrays(GL_TRIANGLES, 0, 6);
2454 glEndQuery(GL_ANY_SAMPLES_PASSED);
2455 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
2456 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
2457 }
2458
verifyDepth(GLuint framebuffer,int width,int height,float depthValue)2459 void verifyDepth(GLuint framebuffer, int width, int height, float depthValue)
2460 {
2461 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
2462
2463 GLint colorAttachment = GL_NONE;
2464 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2465 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
2466 &colorAttachment);
2467
2468 // If no color attachment add a temp one for verification.
2469 GLTexture tempColor;
2470 if (colorAttachment == GL_NONE)
2471 {
2472 glBindTexture(GL_TEXTURE_2D, tempColor);
2473 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2474 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempColor,
2475 0);
2476 }
2477
2478 // Use a small shader to verify depth.
2479 ANGLE_GL_PROGRAM(depthTestProgram, essl1_shaders::vs::Passthrough(),
2480 essl1_shaders::fs::Blue());
2481 ANGLE_GL_PROGRAM(depthTestProgramFail, essl1_shaders::vs::Passthrough(),
2482 essl1_shaders::fs::Red());
2483
2484 GLboolean hasDepthTest = GL_FALSE;
2485 GLboolean hasDepthWrite = GL_TRUE;
2486 GLint prevDepthFunc = GL_ALWAYS;
2487 GLboolean hasStencilTest = GL_FALSE;
2488
2489 glGetBooleanv(GL_DEPTH_TEST, &hasDepthTest);
2490 glGetBooleanv(GL_DEPTH_WRITEMASK, &hasDepthWrite);
2491 glGetIntegerv(GL_DEPTH_FUNC, &prevDepthFunc);
2492 glGetBooleanv(GL_STENCIL_TEST, &hasStencilTest);
2493
2494 if (!hasDepthTest)
2495 {
2496 glEnable(GL_DEPTH_TEST);
2497 }
2498 if (hasDepthWrite)
2499 {
2500 glDepthMask(GL_FALSE);
2501 }
2502 if (hasStencilTest)
2503 {
2504 glDisable(GL_STENCIL_TEST);
2505 }
2506 glDepthFunc(GL_LESS);
2507 drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), depthValue - 0.01f);
2508 drawQuad(depthTestProgramFail, essl1_shaders::PositionAttrib(), depthValue + 0.01f);
2509 if (!hasDepthTest)
2510 {
2511 glDisable(GL_DEPTH_TEST);
2512 }
2513 if (hasDepthWrite)
2514 {
2515 glDepthMask(GL_TRUE);
2516 }
2517 glDepthFunc(prevDepthFunc);
2518 if (hasStencilTest)
2519 {
2520 glEnable(GL_STENCIL_TEST);
2521 }
2522 ASSERT_GL_NO_ERROR();
2523
2524 EXPECT_PIXEL_RECT_EQ(0, 0, width, height, GLColor::blue);
2525
2526 if (colorAttachment == GL_NONE)
2527 {
2528 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
2529 }
2530 }
2531
verifyStencil(GLuint framebuffer,int width,int height,uint32_t stencilValue)2532 void verifyStencil(GLuint framebuffer, int width, int height, uint32_t stencilValue)
2533 {
2534 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
2535
2536 GLint colorAttachment = GL_NONE;
2537 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2538 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
2539 &colorAttachment);
2540
2541 // If no color attachment add a temp one for verification.
2542 GLTexture tempColor;
2543 if (colorAttachment == GL_NONE)
2544 {
2545 glBindTexture(GL_TEXTURE_2D, tempColor);
2546 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2547 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempColor,
2548 0);
2549 }
2550
2551 // Use another small shader to verify stencil.
2552 ANGLE_GL_PROGRAM(stencilTestProgram, essl1_shaders::vs::Passthrough(),
2553 essl1_shaders::fs::Green());
2554 GLboolean hasStencilTest = GL_FALSE;
2555 GLint prevStencilFunc = GL_ALWAYS;
2556 GLint prevStencilValue = 0xFF;
2557 GLint prevStencilRef = 0xFF;
2558 GLint prevStencilFail = GL_KEEP;
2559 GLint prevStencilDepthFail = GL_KEEP;
2560 GLint prevStencilDepthPass = GL_KEEP;
2561 GLboolean hasDepthTest = GL_FALSE;
2562
2563 glGetBooleanv(GL_STENCIL_TEST, &hasStencilTest);
2564 glGetIntegerv(GL_STENCIL_FUNC, &prevStencilFunc);
2565 glGetIntegerv(GL_STENCIL_VALUE_MASK, &prevStencilValue);
2566 glGetIntegerv(GL_STENCIL_REF, &prevStencilRef);
2567 glGetIntegerv(GL_STENCIL_FAIL, &prevStencilFail);
2568 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &prevStencilDepthFail);
2569 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &prevStencilDepthPass);
2570 glGetBooleanv(GL_DEPTH_TEST, &hasDepthTest);
2571
2572 if (!hasStencilTest)
2573 {
2574 glEnable(GL_STENCIL_TEST);
2575 }
2576 glStencilFunc(GL_EQUAL, stencilValue, 0xFF);
2577 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2578 if (hasDepthTest)
2579 {
2580 glDisable(GL_DEPTH_TEST);
2581 }
2582 drawQuad(stencilTestProgram, essl1_shaders::PositionAttrib(), 0.0f);
2583 if (!hasStencilTest)
2584 {
2585 glDisable(GL_STENCIL_TEST);
2586 }
2587 glStencilFunc(prevStencilFunc, prevStencilValue, prevStencilRef);
2588 glStencilOp(prevStencilFail, prevStencilDepthFail, prevStencilDepthPass);
2589 if (hasDepthTest)
2590 {
2591 glEnable(GL_DEPTH_TEST);
2592 }
2593 ASSERT_GL_NO_ERROR();
2594
2595 EXPECT_PIXEL_RECT_EQ(0, 0, width, height, GLColor::green);
2596
2597 if (colorAttachment == GL_NONE)
2598 {
2599 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
2600 }
2601 }
2602
2603 static constexpr char kFSWriteRedGreen[] = R"(#extension GL_EXT_draw_buffers : enable
2604 precision highp float;
2605 void main()
2606 {
2607 gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0); // attachment 0: red
2608 gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0); // attachment 1: green
2609 })";
2610 };
2611
2612 // Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
2613 // FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
TEST_P(FramebufferTest_ES31,IncompleteMissingAttachmentDefaultParam)2614 TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
2615 {
2616 GLFramebuffer mFramebuffer;
2617 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2618
2619 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
2620 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
2621 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2622
2623 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
2624 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
2625 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
2626 glCheckFramebufferStatus(GL_FRAMEBUFFER));
2627
2628 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
2629 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
2630 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
2631 glCheckFramebufferStatus(GL_FRAMEBUFFER));
2632
2633 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
2634 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
2635 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
2636 glCheckFramebufferStatus(GL_FRAMEBUFFER));
2637
2638 ASSERT_GL_NO_ERROR();
2639 }
2640
2641 // Test that the sample count of a mix of texture and renderbuffer should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountMix)2642 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
2643 {
2644 GLFramebuffer mFramebuffer;
2645 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2646
2647 // Lookup the supported number of sample counts (rely on fact that ANGLE uses the same set of
2648 // sample counts for textures and renderbuffers)
2649 GLint numSampleCounts = 0;
2650 std::vector<GLint> sampleCounts;
2651 GLsizei queryBufferSize = 1;
2652 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
2653 queryBufferSize, &numSampleCounts);
2654 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
2655 sampleCounts.resize(numSampleCounts);
2656 queryBufferSize = numSampleCounts;
2657 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
2658 sampleCounts.data());
2659
2660 GLTexture mTexture;
2661 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
2662 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
2663
2664 GLRenderbuffer mRenderbuffer;
2665 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
2666 glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[1], GL_RGBA8, 1, 1);
2667 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2668 mTexture, 0);
2669 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, mRenderbuffer);
2670 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
2671 glCheckFramebufferStatus(GL_FRAMEBUFFER));
2672
2673 ASSERT_GL_NO_ERROR();
2674 }
2675
2676 // Test that the sample count of texture attachments should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountTex)2677 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
2678 {
2679 GLFramebuffer mFramebuffer;
2680 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2681
2682 // Lookup the supported number of sample counts
2683 GLint numSampleCounts = 0;
2684 std::vector<GLint> sampleCounts;
2685 GLsizei queryBufferSize = 1;
2686 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
2687 queryBufferSize, &numSampleCounts);
2688 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
2689 sampleCounts.resize(numSampleCounts);
2690 queryBufferSize = numSampleCounts;
2691 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
2692 sampleCounts.data());
2693
2694 GLTexture mTextures[2];
2695 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0]);
2696 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
2697 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1]);
2698 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[1], GL_RGBA8, 1, 1, true);
2699 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2700 mTextures[0], 0);
2701 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2702 mTextures[1], 0);
2703 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
2704 glCheckFramebufferStatus(GL_FRAMEBUFFER));
2705
2706 ASSERT_GL_NO_ERROR();
2707 }
2708
2709 // Test that if the attached images are a mix of renderbuffers and textures, the value of
2710 // TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsMix)2711 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
2712 {
2713 GLFramebuffer mFramebuffer;
2714 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2715
2716 GLTexture mTexture;
2717 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
2718 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
2719
2720 GLRenderbuffer mRenderbuffer;
2721 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
2722 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
2723 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2724 mTexture, 0);
2725 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, mRenderbuffer);
2726 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
2727 glCheckFramebufferStatus(GL_FRAMEBUFFER));
2728
2729 ASSERT_GL_NO_ERROR();
2730 }
2731
2732 // Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsTex)2733 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
2734 {
2735 GLFramebuffer mFramebuffer;
2736 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2737
2738 GLTexture mTextures[2];
2739 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0]);
2740 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
2741 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2742 mTextures[0], 0);
2743 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1]);
2744 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
2745 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2746 mTextures[1], 0);
2747 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
2748 glCheckFramebufferStatus(GL_FRAMEBUFFER));
2749
2750 ASSERT_GL_NO_ERROR();
2751 }
2752
2753 // Tests that draw to Y-flipped FBO results in correct pixels.
TEST_P(FramebufferTest_ES31,BasicDrawToYFlippedFBO)2754 TEST_P(FramebufferTest_ES31, BasicDrawToYFlippedFBO)
2755 {
2756 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
2757
2758 constexpr int kSize = 16;
2759 glViewport(0, 0, kSize, kSize);
2760
2761 GLFramebuffer fbo;
2762 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2763
2764 glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
2765
2766 GLTexture texture;
2767 glBindTexture(GL_TEXTURE_2D, texture);
2768 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
2769 ASSERT_GL_NO_ERROR();
2770 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2771 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2772
2773 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2774 essl31_shaders::fs::RedGreenGradient());
2775 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2776 ASSERT_GL_NO_ERROR();
2777
2778 // Remove the flag so that glReadPixels do not implicitly use that.
2779 glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
2780
2781 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2782 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2783 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255,
2784 1.0);
2785 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2786 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255,
2787 1.0);
2788 }
2789
2790 // Test resolving a multisampled texture with blit
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlit)2791 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlit)
2792 {
2793 constexpr int kSize = 16;
2794 glViewport(0, 0, kSize, kSize);
2795
2796 GLFramebuffer msaaFBO;
2797 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
2798
2799 GLTexture texture;
2800 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
2801 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2802 ASSERT_GL_NO_ERROR();
2803 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
2804 0);
2805 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2806
2807 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2808 essl31_shaders::fs::RedGreenGradient());
2809 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2810 ASSERT_GL_NO_ERROR();
2811
2812 // Create another FBO to resolve the multisample buffer into.
2813 GLTexture resolveTexture;
2814 GLFramebuffer resolveFBO;
2815 glBindTexture(GL_TEXTURE_2D, resolveTexture);
2816 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2817 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2818 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2819 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2820
2821 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2822 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2823 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2824 ASSERT_GL_NO_ERROR();
2825
2826 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2827 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2828 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2829 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2830 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2831 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2832 255, 1.0);
2833 }
2834
2835 // Test resolving a multisampled texture with blit to a different format
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitDifferentFormats)2836 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitDifferentFormats)
2837 {
2838 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888"));
2839
2840 constexpr int kSize = 16;
2841 glViewport(0, 0, kSize, kSize);
2842
2843 GLFramebuffer msaaFBO;
2844 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
2845
2846 GLTexture texture;
2847 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
2848 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2849 ASSERT_GL_NO_ERROR();
2850 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
2851 0);
2852 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2853
2854 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2855 essl31_shaders::fs::RedGreenGradient());
2856 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2857 ASSERT_GL_NO_ERROR();
2858
2859 // Create another FBO to resolve the multisample buffer into.
2860 GLTexture resolveTexture;
2861 GLFramebuffer resolveFBO;
2862 glBindTexture(GL_TEXTURE_2D, resolveTexture);
2863 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA8_EXT, kSize, kSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
2864 nullptr);
2865 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2866 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2867
2868 // Another attachment of the same format as the blit source
2869 // to ensure that it does not confuse the backend.
2870 GLTexture resolveTexture2;
2871 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2872 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2873 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, resolveTexture2, 0);
2874
2875 GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
2876 glDrawBuffers(2, drawBuffers);
2877
2878 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2879
2880 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2881 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2882 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2883 ASSERT_GL_NO_ERROR();
2884
2885 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2886 for (const GLenum buffer : {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1})
2887 {
2888 glReadBuffer(buffer);
2889 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2890 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2891 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2892 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2893 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient,
2894 0, 255, 1.0);
2895 }
2896 }
2897
2898 // Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitMultipleFBOs)2899 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleFBOs)
2900 {
2901 // FBO 1 -> multisample draw (red)
2902 // FBO 2 -> multisample draw (green)
2903 // Bind FBO 1 as read
2904 // Bind FBO 3 as draw
2905 // Resolve
2906
2907 constexpr int kSize = 16;
2908 glViewport(0, 0, kSize, kSize);
2909
2910 GLFramebuffer msaaFBORed;
2911 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed);
2912
2913 GLTexture textureRed;
2914 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed);
2915 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2916 ASSERT_GL_NO_ERROR();
2917 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2918 textureRed, 0);
2919 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2920
2921 ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
2922 drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2923 ASSERT_GL_NO_ERROR();
2924
2925 GLFramebuffer msaaFBOGreen;
2926 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBOGreen);
2927
2928 GLTexture textureGreen;
2929 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureGreen);
2930 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2931 ASSERT_GL_NO_ERROR();
2932 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2933 textureGreen, 0);
2934 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2935
2936 ANGLE_GL_PROGRAM(greenProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Green());
2937 drawQuad(greenProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2938 ASSERT_GL_NO_ERROR();
2939
2940 // Create another FBO to resolve the multisample buffer into.
2941 GLTexture resolveTexture;
2942 GLFramebuffer resolveFBO;
2943 glBindTexture(GL_TEXTURE_2D, resolveTexture);
2944 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2945 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2946 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2947 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2948
2949 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2950 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2951 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2952 ASSERT_GL_NO_ERROR();
2953
2954 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2955 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2956 }
2957
2958 // Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitMultipleResolves)2959 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleResolves)
2960 {
2961 // Draw multisampled in FBO 1
2962 // Bind FBO 1 as read
2963 // Bind FBO 2 as draw
2964 // Resolve
2965 // Bind FBO 3 as draw
2966 // Resolve
2967
2968 constexpr int kSize = 16;
2969 glViewport(0, 0, kSize, kSize);
2970
2971 GLFramebuffer msaaFBORed;
2972 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed);
2973
2974 GLTexture textureRed;
2975 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed);
2976 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2977 ASSERT_GL_NO_ERROR();
2978 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2979 textureRed, 0);
2980 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2981
2982 ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
2983 drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2984 ASSERT_GL_NO_ERROR();
2985
2986 // Create another FBO to resolve the multisample buffer into.
2987 GLTexture resolveTexture1;
2988 GLFramebuffer resolveFBO1;
2989 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2990 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2991 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2992 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2993 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2994
2995 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2996 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2997 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2998 ASSERT_GL_NO_ERROR();
2999
3000 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3001 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3002
3003 // Create another FBO to resolve the multisample buffer into.
3004 GLTexture resolveTexture2;
3005 GLFramebuffer resolveFBO2;
3006 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
3007 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3008 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
3009 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
3010 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3011
3012 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
3013 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
3014 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3015 ASSERT_GL_NO_ERROR();
3016
3017 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
3018 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3019 }
3020
3021 // Test resolving a multisampled texture with blit into an FBO with different read and draw
3022 // attachments.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitDifferentReadDrawBuffers)3023 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitDifferentReadDrawBuffers)
3024 {
3025 constexpr int kSize = 16;
3026 glViewport(0, 0, kSize, kSize);
3027
3028 GLFramebuffer msaaFBO;
3029 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3030
3031 GLTexture texture;
3032 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3033 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3034 ASSERT_GL_NO_ERROR();
3035 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3036 0);
3037 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3038
3039 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3040 essl31_shaders::fs::RedGreenGradient());
3041 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3042 ASSERT_GL_NO_ERROR();
3043
3044 // Create another FBO to resolve the multisample buffer into.
3045 GLFramebuffer resolveFBO;
3046 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3047
3048 // Bind both read and draw textures as separate attachments.
3049 const std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
3050 GLTexture resolveReadTexture;
3051 glBindTexture(GL_TEXTURE_2D, resolveReadTexture);
3052 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3053 blueColors.data());
3054 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveReadTexture,
3055 0);
3056 glReadBuffer(GL_COLOR_ATTACHMENT0);
3057 ASSERT_GL_NO_ERROR();
3058
3059 GLTexture resolveDrawTexture;
3060 glBindTexture(GL_TEXTURE_2D, resolveDrawTexture);
3061 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3062 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, resolveDrawTexture,
3063 0);
3064 // Only enable color attachment 1 to be drawn to, since the Vulkan back end (currently) only
3065 // supports using resolve attachments when there is a single draw attachment enabled. This
3066 // ensures that the read and draw images are treated separately, including their layouts.
3067 GLenum drawBuffers[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
3068 glDrawBuffers(2, drawBuffers);
3069 ASSERT_GL_NO_ERROR();
3070 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3071
3072 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3073 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3074 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3075 ASSERT_GL_NO_ERROR();
3076
3077 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3078 glReadBuffer(GL_COLOR_ATTACHMENT1);
3079 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3080 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3081 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3082 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3083 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3084 255, 1.0);
3085 }
3086
3087 // Test resolving a multisampled texture into a mipmaped texture with blit
TEST_P(FramebufferTest_ES31,MultisampleResolveIntoMipMapWithBlit)3088 TEST_P(FramebufferTest_ES31, MultisampleResolveIntoMipMapWithBlit)
3089 {
3090 // FBO 1 is attached to a 64x64 texture
3091 // FBO 2 attached to level 1 of a 128x128 texture
3092
3093 constexpr int kSize = 64;
3094 glViewport(0, 0, kSize, kSize);
3095
3096 // Create the textures early and call glGenerateMipmap() so it doesn't break the render pass
3097 // between the drawQuad() and glBlitFramebuffer(), so we can test the resolve with subpass path
3098 // in the Vulkan back end.
3099 GLTexture texture;
3100 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3101 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3102 ASSERT_GL_NO_ERROR();
3103
3104 GLTexture resolveTexture;
3105 glBindTexture(GL_TEXTURE_2D, resolveTexture);
3106 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
3108 ASSERT_GL_NO_ERROR();
3109
3110 GLFramebuffer msaaFBO;
3111 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3112 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3113 0);
3114 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3115
3116 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3117 essl31_shaders::fs::RedGreenGradient());
3118 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3119 ASSERT_GL_NO_ERROR();
3120
3121 // Create another FBO to resolve the multisample buffer into.
3122 GLFramebuffer resolveFBO;
3123 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3124 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
3125 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3126
3127 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3128 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3129 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3130 ASSERT_GL_NO_ERROR();
3131
3132 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3133 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3134 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3135 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3136 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3137 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3138 255, 1.0);
3139 }
3140
3141 // Test resolving a multisampled texture with blit after drawing to multiple FBOs.
TEST_P(FramebufferTest_ES31,MultipleTextureMultisampleResolveWithBlitMultipleResolves)3142 TEST_P(FramebufferTest_ES31, MultipleTextureMultisampleResolveWithBlitMultipleResolves)
3143 {
3144 // Attach two MSAA textures to FBO1
3145 // Set read buffer 0
3146 // Resolve into FBO2
3147 // Set read buffer 1
3148 // Resolve into FBO3
3149
3150 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3151
3152 constexpr int kSize = 16;
3153 glViewport(0, 0, kSize, kSize);
3154
3155 GLFramebuffer msaaFBO;
3156 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3157
3158 GLTexture msaaTextureRed;
3159 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed);
3160 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3161 ASSERT_GL_NO_ERROR();
3162 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
3163 msaaTextureRed, 0);
3164 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3165
3166 GLTexture msaaTextureGreen;
3167 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen);
3168 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3169 ASSERT_GL_NO_ERROR();
3170 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
3171 msaaTextureGreen, 0);
3172 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3173
3174 // Setup program to render red into attachment 0 and green into attachment 1.
3175 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
3176 glUseProgram(program);
3177 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
3178 glDrawBuffers(2, kDrawBuffers);
3179
3180 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3181 ASSERT_GL_NO_ERROR();
3182
3183 // Create another FBO to resolve the multisample buffer into.
3184 GLTexture resolveTexture1;
3185 GLFramebuffer resolveFBO1;
3186 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
3187 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3188 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
3189 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
3190 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3191
3192 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3193 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
3194 glReadBuffer(GL_COLOR_ATTACHMENT0); // Red
3195 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3196 ASSERT_GL_NO_ERROR();
3197
3198 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3199 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3200
3201 // Create another FBO to resolve the multisample buffer into.
3202 GLTexture resolveTexture2;
3203 GLFramebuffer resolveFBO2;
3204 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
3205 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3206 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
3207 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
3208 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3209
3210 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3211 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
3212 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
3213 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3214 ASSERT_GL_NO_ERROR();
3215
3216 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
3217 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3218 }
3219
3220 // Test resolving a multisampled texture with blit after drawing to multiple FBOs, with color
3221 // attachment 1 resolved first.
TEST_P(FramebufferTest_ES31,MultipleTextureMultisampleResolveWithBlitMultipleResolvesAttachment1First)3222 TEST_P(FramebufferTest_ES31,
3223 MultipleTextureMultisampleResolveWithBlitMultipleResolvesAttachment1First)
3224 {
3225 // Attach two MSAA textures to FBO1
3226 // Set read buffer 1
3227 // Resolve into FBO2
3228 // Set read buffer 0
3229 // Resolve into FBO3
3230
3231 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3232
3233 constexpr int kSize = 16;
3234 glViewport(0, 0, kSize, kSize);
3235
3236 GLFramebuffer msaaFBO;
3237 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3238
3239 GLTexture msaaTextureRed;
3240 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed);
3241 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3242 ASSERT_GL_NO_ERROR();
3243 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
3244 msaaTextureRed, 0);
3245 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3246
3247 GLTexture msaaTextureGreen;
3248 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen);
3249 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3250 ASSERT_GL_NO_ERROR();
3251 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
3252 msaaTextureGreen, 0);
3253 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3254
3255 // Setup program to render red into attachment 0 and green into attachment 1.
3256 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
3257 glUseProgram(program);
3258 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
3259 glDrawBuffers(2, kDrawBuffers);
3260
3261 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3262 ASSERT_GL_NO_ERROR();
3263
3264 // Create another FBO to resolve the multisample buffer into.
3265 GLTexture resolveTexture1;
3266 GLFramebuffer resolveFBO1;
3267 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
3268 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3269 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
3270 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
3271 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3272
3273 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3274 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
3275 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
3276 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3277 ASSERT_GL_NO_ERROR();
3278
3279 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3280 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3281
3282 // Create another FBO to resolve the multisample buffer into.
3283 GLTexture resolveTexture2;
3284 GLFramebuffer resolveFBO2;
3285 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
3286 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3287 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
3288 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
3289 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3290
3291 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3292 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
3293 glReadBuffer(GL_COLOR_ATTACHMENT0); // Red
3294 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3295 ASSERT_GL_NO_ERROR();
3296
3297 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
3298 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3299 }
3300
3301 // Test resolving a multisampled texture with blit, then drawing multisampled again. The latter
3302 // should not get re-resolved automatically.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDraw)3303 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDraw)
3304 {
3305 constexpr int kSize = 16;
3306 glViewport(0, 0, kSize, kSize);
3307
3308 GLFramebuffer msaaFBO;
3309 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3310
3311 GLTexture texture;
3312 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3313 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3314 ASSERT_GL_NO_ERROR();
3315 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3316 0);
3317 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3318
3319 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3320 essl31_shaders::fs::RedGreenGradient());
3321 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3322 ASSERT_GL_NO_ERROR();
3323
3324 // Create another FBO to resolve the multisample buffer into.
3325 GLTexture resolveTexture;
3326 GLFramebuffer resolveFBO;
3327 glBindTexture(GL_TEXTURE_2D, resolveTexture);
3328 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3329 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3330 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
3331 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3332
3333 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3334 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3335 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3336 ASSERT_GL_NO_ERROR();
3337
3338 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3339 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3340 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3341 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3342 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3343 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3344 255, 1.0);
3345
3346 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
3347 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
3348 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3349 ASSERT_GL_NO_ERROR();
3350
3351 // The resolved FBO should be unaffected by the last draw call.
3352 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3353 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3354 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3355 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3356 255, 1.0);
3357 }
3358
3359 // Test resolving a multisampled texture with blit, then drawing multisampled again. The latter
3360 // should not get re-resolved automatically. Resoloves color attachment 1.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawAttachment1)3361 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawAttachment1)
3362 {
3363 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3364
3365 constexpr int kSize = 16;
3366 glViewport(0, 0, kSize, kSize);
3367
3368 GLFramebuffer msaaFBO;
3369 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3370
3371 GLTexture msaaTextureRed;
3372 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed);
3373 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3374 ASSERT_GL_NO_ERROR();
3375 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
3376 msaaTextureRed, 0);
3377 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3378
3379 GLTexture msaaTextureGreen;
3380 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen);
3381 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3382 ASSERT_GL_NO_ERROR();
3383 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
3384 msaaTextureGreen, 0);
3385 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3386
3387 // Setup program to render red into attachment 0 and green into attachment 1.
3388 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
3389 glUseProgram(program);
3390 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
3391 glDrawBuffers(2, kDrawBuffers);
3392
3393 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3394 ASSERT_GL_NO_ERROR();
3395
3396 // Create another FBO to resolve the multisample buffer into.
3397 GLTexture resolveTexture;
3398 GLFramebuffer resolveFBO;
3399 glBindTexture(GL_TEXTURE_2D, resolveTexture);
3400 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3401 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3402 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
3403 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3404
3405 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3406 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3407 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
3408 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3409 ASSERT_GL_NO_ERROR();
3410
3411 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3412 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3413 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
3414 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
3415 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
3416
3417 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
3418 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
3419 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3420 ASSERT_GL_NO_ERROR();
3421
3422 // The resolved FBO should be unaffected by the last draw call.
3423 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3424 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
3425 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
3426 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
3427 }
3428
3429 // Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
3430 // same framebuffer.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawThenResolveAgain)3431 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgain)
3432 {
3433 constexpr int kSize = 16;
3434 glViewport(0, 0, kSize, kSize);
3435
3436 GLFramebuffer msaaFBO;
3437 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3438
3439 GLTexture texture;
3440 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3441 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3442 ASSERT_GL_NO_ERROR();
3443 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3444 0);
3445 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3446
3447 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3448 essl31_shaders::fs::RedGreenGradient());
3449 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3450 ASSERT_GL_NO_ERROR();
3451
3452 // Create another FBO to resolve the multisample buffer into.
3453 GLTexture resolveTexture;
3454 GLFramebuffer resolveFBO;
3455 glBindTexture(GL_TEXTURE_2D, resolveTexture);
3456 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3457 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3458 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
3459 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3460
3461 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3462 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3463 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3464 ASSERT_GL_NO_ERROR();
3465
3466 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3467 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3468 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3469 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3470 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3471 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3472 255, 1.0);
3473
3474 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
3475 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
3476 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3477 ASSERT_GL_NO_ERROR();
3478
3479 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3480 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3481 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3482 ASSERT_GL_NO_ERROR();
3483
3484 // Verify that the resolve happened correctly
3485 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3486 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3487 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
3488 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
3489 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
3490 }
3491
3492 // Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
3493 // another framebuffer.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawThenResolveAgainToDifferentFBO)3494 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgainToDifferentFBO)
3495 {
3496 constexpr int kSize = 16;
3497 glViewport(0, 0, kSize, kSize);
3498
3499 GLFramebuffer msaaFBO;
3500 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3501
3502 GLTexture texture;
3503 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3504 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3505 ASSERT_GL_NO_ERROR();
3506 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3507 0);
3508 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3509
3510 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3511 essl31_shaders::fs::RedGreenGradient());
3512 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3513 ASSERT_GL_NO_ERROR();
3514
3515 // Create another FBO to resolve the multisample buffer into.
3516 GLTexture resolveTexture1;
3517 GLFramebuffer resolveFBO1;
3518 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
3519 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3520 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
3521 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
3522 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3523
3524 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3525 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
3526 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3527 ASSERT_GL_NO_ERROR();
3528
3529 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3530 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3531 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3532 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3533 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3534 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3535 255, 1.0);
3536
3537 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
3538 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
3539 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3540 ASSERT_GL_NO_ERROR();
3541
3542 // Create another FBO to resolve the multisample buffer into.
3543 GLTexture resolveTexture2;
3544 GLFramebuffer resolveFBO2;
3545 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
3546 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3547 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
3548 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
3549 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3550
3551 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3552 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
3553 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3554 ASSERT_GL_NO_ERROR();
3555
3556 // Verify that the resolve happened to the correct FBO
3557 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
3558 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3559 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
3560 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
3561 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
3562
3563 // The first resolve FBO should be untouched.
3564 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3565 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3566 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3567 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3568 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3569 255, 1.0);
3570 }
3571
3572 // Test resolving a multisampled texture with blit to a non-zero level.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitNonZeroLevel)3573 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitNonZeroLevel)
3574 {
3575 constexpr int kWidth = 16;
3576 constexpr int kHeight = 20;
3577 glViewport(0, 0, kWidth, kHeight);
3578
3579 GLFramebuffer msaaFBO;
3580 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3581
3582 GLTexture texture;
3583 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3584 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
3585 ASSERT_GL_NO_ERROR();
3586 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3587 0);
3588 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3589
3590 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3591 essl31_shaders::fs::RedGreenGradient());
3592 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3593 ASSERT_GL_NO_ERROR();
3594
3595 // Create a resolve FBO and texture. The multisample buffer will be resolved into level 1 of the
3596 // bound texture, which has the same dimensions as the multisampled texture.
3597 GLTexture resolveTexture;
3598 glBindTexture(GL_TEXTURE_2D, resolveTexture);
3599 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 2, kHeight * 2);
3600
3601 GLFramebuffer resolveFBO;
3602 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3603 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
3604 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3605
3606 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3607 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3608 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
3609 GL_NEAREST);
3610 ASSERT_GL_NO_ERROR();
3611
3612 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3613 constexpr uint8_t kWidthHalfPixelGradient = 256 / kWidth / 2;
3614 constexpr uint8_t kHeightHalfPixelGradient = 256 / kHeight / 2;
3615 EXPECT_PIXEL_NEAR(0, 0, kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0, 255, 1.0);
3616 EXPECT_PIXEL_NEAR(kWidth - 1, 0, 255 - kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0,
3617 255, 1.0);
3618 EXPECT_PIXEL_NEAR(0, kHeight - 1, kWidthHalfPixelGradient, 255 - kHeightHalfPixelGradient, 0,
3619 255, 1.0);
3620 EXPECT_PIXEL_NEAR(kWidth - 1, kHeight - 1, 255 - kWidthHalfPixelGradient,
3621 255 - kHeightHalfPixelGradient, 0, 255, 1.0);
3622 }
3623
3624 // If there are no attachments, rendering will be limited to a rectangle having a lower left of
3625 // (0, 0) and an upper right of(width, height), where width and height are the framebuffer
3626 // object's default width and height.
TEST_P(FramebufferTest_ES31,RenderingLimitToDefaultFBOSizeWithNoAttachments)3627 TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttachments)
3628 {
3629 // anglebug.com/2253
3630 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
3631
3632 constexpr char kVS1[] = R"(#version 310 es
3633 in layout(location = 0) highp vec2 a_position;
3634 void main()
3635 {
3636 gl_Position = vec4(a_position, 0.0, 1.0);
3637 })";
3638
3639 constexpr char kFS1[] = R"(#version 310 es
3640 uniform layout(location = 0) highp ivec2 u_expectedSize;
3641 out layout(location = 3) mediump vec4 f_color;
3642 void main()
3643 {
3644 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3645 f_color = vec4(1.0, 0.5, 0.25, 1.0);
3646 })";
3647
3648 constexpr char kVS2[] = R"(#version 310 es
3649 in layout(location = 0) highp vec2 a_position;
3650 void main()
3651 {
3652 gl_Position = vec4(a_position, 0.0, 1.0);
3653 })";
3654
3655 constexpr char kFS2[] = R"(#version 310 es
3656 uniform layout(location = 0) highp ivec2 u_expectedSize;
3657 out layout(location = 2) mediump vec4 f_color;
3658 void main()
3659 {
3660 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3661 f_color = vec4(1.0, 0.5, 0.25, 1.0);
3662 })";
3663
3664 ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
3665 ANGLE_GL_PROGRAM(program2, kVS2, kFS2);
3666
3667 glUseProgram(program1);
3668
3669 GLFramebuffer mFramebuffer;
3670 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
3671 GLuint defaultWidth = 1;
3672 GLuint defaultHeight = 1;
3673
3674 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3675 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3676 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3677
3678 const float data[] = {
3679 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
3680 };
3681
3682 GLQuery query;
3683
3684 GLVertexArray vertexArray;
3685 glBindVertexArray(vertexArray);
3686
3687 GLBuffer vertexBuffer;
3688 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3689 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3690
3691 glEnableVertexAttribArray(0);
3692 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
3693 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3694
3695 validateSamplePass(query, defaultWidth, defaultHeight);
3696
3697 glUseProgram(program2);
3698 validateSamplePass(query, defaultWidth, defaultHeight);
3699
3700 glUseProgram(program1);
3701 // If fbo has attachments, the rendering size should be the same as its attachment.
3702 GLTexture mTexture;
3703 GLuint width = 2;
3704 GLuint height = 2;
3705 glBindTexture(GL_TEXTURE_2D, mTexture);
3706 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
3707
3708 const GLenum bufs[] = {GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
3709
3710 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTexture, 0);
3711 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3712 glDrawBuffers(4, bufs);
3713
3714 validateSamplePass(query, width, height);
3715
3716 // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
3717 // default size.
3718 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, 0, 0);
3719 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3720
3721 validateSamplePass(query, defaultWidth, defaultHeight);
3722 ASSERT_GL_NO_ERROR();
3723 }
3724
3725 // Creating two attachmentless framebuffers should work without vvl error.
TEST_P(FramebufferTest_ES31,CreateNoAttachmentFBOWithDifferentSize)3726 TEST_P(FramebufferTest_ES31, CreateNoAttachmentFBOWithDifferentSize)
3727 {
3728 constexpr char kVS1[] = R"(#version 310 es
3729 in layout(location = 0) highp vec2 a_position;
3730 void main()
3731 {
3732 gl_Position = vec4(a_position, 0.0, 1.0);
3733 })";
3734
3735 constexpr char kFS1[] = R"(#version 310 es
3736 uniform layout(location = 0) highp ivec2 u_expectedSize;
3737 out layout(location = 3) mediump vec4 f_color;
3738 void main()
3739 {
3740 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3741 f_color = vec4(1.0, 0.5, 0.25, 1.0);
3742 })";
3743 ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
3744 glUseProgram(program1);
3745
3746 GLBuffer vertexBuffer;
3747 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3748 const float data[] = {
3749 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
3750 };
3751 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3752 glEnableVertexAttribArray(0);
3753 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
3754
3755 GLQuery query;
3756
3757 // Test that:
3758 // 1. create 1st no-attachment framebuffer with size 1*1, draw, delete framebuffer
3759 // 2. create 2nd no-attachment framebuffer with size 2*2, draw, delete framebuffer
3760 // works properly
3761 for (int loop = 0; loop < 2; loop++)
3762 {
3763 GLFramebuffer framebuffer;
3764 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
3765 GLuint defaultWidth = 1 << loop;
3766 GLuint defaultHeight = 1 << loop;
3767 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3768 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3769 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3770
3771 // Draw and check the FBO size
3772 validateSamplePass(query, defaultWidth, defaultHeight);
3773 }
3774
3775 ASSERT_GL_NO_ERROR();
3776
3777 // Test that:
3778 // 1. create 1st no-attachment framebuffer with size 2*2, draw, delete framebuffer
3779 // 2. create 2nd no-attachment framebuffer with size 1*1, draw, delete framebuffer
3780 // works properly
3781 for (int loop = 1; loop >= 0; loop--)
3782 {
3783 GLFramebuffer framebuffer;
3784 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
3785 GLuint defaultWidth = 1 << loop;
3786 GLuint defaultHeight = 1 << loop;
3787 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3788 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3789 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3790
3791 // Draw and check the FBO size
3792 validateSamplePass(query, defaultWidth, defaultHeight);
3793 }
3794
3795 ASSERT_GL_NO_ERROR();
3796 }
3797
3798 // Altering the default width and height of attachmentless framebuffer should work fine
TEST_P(FramebufferTest_ES31,ChangeFBOSizeWithNoAttachments)3799 TEST_P(FramebufferTest_ES31, ChangeFBOSizeWithNoAttachments)
3800 {
3801 constexpr char kVS1[] = R"(#version 310 es
3802 in layout(location = 0) highp vec2 a_position;
3803 void main()
3804 {
3805 gl_Position = vec4(a_position, 0.0, 1.0);
3806 })";
3807
3808 constexpr char kFS1[] = R"(#version 310 es
3809 uniform layout(location = 0) highp ivec2 u_expectedSize;
3810 out layout(location = 3) mediump vec4 f_color;
3811 void main()
3812 {
3813 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3814 f_color = vec4(1.0, 0.5, 0.25, 1.0);
3815 })";
3816 ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
3817 glUseProgram(program1);
3818
3819 GLBuffer vertexBuffer;
3820 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3821 const float data[] = {
3822 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
3823 };
3824 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3825 glEnableVertexAttribArray(0);
3826 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
3827
3828 GLQuery query;
3829
3830 // Test that:
3831 // 1. create a no-attachment framebuffer with size 1*1, draw
3832 // 2. change the no-attachment framebuffer size to 2*2, draw
3833 // works properly
3834 GLFramebuffer framebufferWithVariousSizeGrow;
3835 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeGrow);
3836 for (int loop = 0; loop < 2; loop++)
3837 {
3838 GLuint defaultWidth = 1 << loop;
3839 GLuint defaultHeight = 1 << loop;
3840 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3841 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3842 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3843
3844 // Draw and check the FBO size
3845 validateSamplePass(query, defaultWidth, defaultHeight);
3846 }
3847
3848 ASSERT_GL_NO_ERROR();
3849
3850 // Test that:
3851 // 1. create a no-attachment framebuffer with size 2*2, draw
3852 // 2. change the no-attachment framebuffer size to 1*1, draw
3853 // works properly
3854 GLFramebuffer framebufferWithVariousSizeShrink;
3855 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeShrink);
3856 for (int loop = 1; loop >= 0; loop--)
3857 {
3858 GLuint defaultWidth = 1 << loop;
3859 GLuint defaultHeight = 1 << loop;
3860 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3861 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3862 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3863
3864 // Draw and check the FBO size
3865 validateSamplePass(query, defaultWidth, defaultHeight);
3866 }
3867
3868 ASSERT_GL_NO_ERROR();
3869 }
3870
3871 // Test that changing framebuffer attachment count and its' default width and height work properly
TEST_P(FramebufferTest_ES31,ChangeFBOSizeAndAttachmentsCount)3872 TEST_P(FramebufferTest_ES31, ChangeFBOSizeAndAttachmentsCount)
3873 {
3874 constexpr char kVS1[] = R"(#version 310 es
3875 in layout(location = 0) highp vec2 a_position;
3876 void main()
3877 {
3878 gl_Position = vec4(a_position, 0.0, 1.0);
3879 })";
3880
3881 constexpr char kFS1[] = R"(#version 310 es
3882 uniform layout(location = 0) highp ivec2 u_expectedSize;
3883 out layout(location = 3) mediump vec4 f_color;
3884 void main()
3885 {
3886 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3887 f_color = vec4(1.0, 0.5, 0.25, 1.0);
3888 })";
3889 ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
3890 glUseProgram(program1);
3891
3892 GLBuffer vertexBuffer;
3893 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3894 const float data[] = {
3895 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
3896 };
3897 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3898 glEnableVertexAttribArray(0);
3899 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
3900
3901 GLQuery query;
3902
3903 // 1. create a no-attachment framebuffer with default size 1*1, draw
3904 // 2. give the fbo with 1 color attachment with size 2*2, draw
3905 // 3. change the fbo default size to 3*3, draw
3906 // 4. remove the fbo attachment, draw
3907 // works properly
3908 GLFramebuffer framebufferWithVariousSizeAndAttachmentGrow;
3909 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeAndAttachmentGrow);
3910 GLuint defaultWidth = 1;
3911 GLuint defaultHeight = 1;
3912 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3913 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3914 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3915 validateSamplePass(query, defaultWidth, defaultHeight);
3916
3917 GLTexture mTexture;
3918 glBindTexture(GL_TEXTURE_2D, mTexture);
3919 GLuint attachmentWidth = 2;
3920 GLuint attachmentHeight = 2;
3921 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, attachmentWidth, attachmentHeight);
3922 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
3923 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3924 validateSamplePass(query, attachmentWidth, attachmentWidth);
3925
3926 defaultWidth = 3;
3927 defaultHeight = 3;
3928 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3929 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3930 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3931 validateSamplePass(query, attachmentWidth, attachmentHeight);
3932
3933 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0);
3934 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3935 validateSamplePass(query, defaultWidth, defaultHeight);
3936
3937 ASSERT_GL_NO_ERROR();
3938
3939 // 1. create a no-attachment framebuffer with default size 3*3, draw
3940 // 2. give the fbo with 1 color attachment with size 2*2, draw
3941 // 3. change the fbo default size to 1*1, draw
3942 // 4. remove the fbo attachment, draw
3943 // works properly
3944 GLFramebuffer framebufferWithVariousSizeAndAttachmentShrink;
3945 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeAndAttachmentShrink);
3946 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3947 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3948 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3949 validateSamplePass(query, defaultWidth, defaultHeight);
3950
3951 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
3952 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3953 validateSamplePass(query, attachmentWidth, attachmentHeight);
3954
3955 defaultWidth = 1;
3956 defaultHeight = 1;
3957 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3958 glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3959 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3960 validateSamplePass(query, attachmentWidth, attachmentHeight);
3961
3962 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0);
3963 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3964 validateSamplePass(query, defaultWidth, defaultHeight);
3965
3966 ASSERT_GL_NO_ERROR();
3967 }
3968
3969 // Test binding two textures with different widths to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentWidthsToFBOAndDraw)3970 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentWidthsToFBOAndDraw)
3971 {
3972 constexpr GLuint kSize = 2;
3973
3974 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
3975
3976 GLTexture colorTexture;
3977 glBindTexture(GL_TEXTURE_2D, colorTexture);
3978 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3979
3980 GLFramebuffer fbo;
3981 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3982 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3983 ASSERT_GL_NO_ERROR();
3984 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3985
3986 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3987 ASSERT_GL_NO_ERROR();
3988 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
3989
3990 // The second texture is defined with double the width as the first.
3991 GLTexture colorTexture2;
3992 glBindTexture(GL_TEXTURE_2D, colorTexture2);
3993 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize * 2, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3994 nullptr);
3995
3996 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3997 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
3998 ASSERT_GL_NO_ERROR();
3999 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4000
4001 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4002 ASSERT_GL_NO_ERROR();
4003 EXPECT_PIXEL_RECT_EQ(0, 0, kSize * 2, kSize, GLColor::green);
4004 }
4005
4006 // Test binding two textures with different heights to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentHeightsToFBOAndDraw)4007 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentHeightsToFBOAndDraw)
4008 {
4009 constexpr GLuint kSize = 2;
4010
4011 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4012
4013 GLTexture colorTexture;
4014 glBindTexture(GL_TEXTURE_2D, colorTexture);
4015 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4016
4017 GLFramebuffer fbo;
4018 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4019 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4020 ASSERT_GL_NO_ERROR();
4021 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4022
4023 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4024 ASSERT_GL_NO_ERROR();
4025 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4026
4027 // The second texture is defined with double the height as the first.
4028 GLTexture colorTexture2;
4029 glBindTexture(GL_TEXTURE_2D, colorTexture2);
4030 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize * 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4031 nullptr);
4032
4033 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4034 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
4035 ASSERT_GL_NO_ERROR();
4036 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4037
4038 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4039 ASSERT_GL_NO_ERROR();
4040 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize * 2, GLColor::green);
4041 }
4042
4043 // Test binding two textures with different formats to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentFormatsToFBOAndDraw)4044 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentFormatsToFBOAndDraw)
4045 {
4046 constexpr GLuint kSize = 2;
4047
4048 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4049
4050 GLTexture colorTexture;
4051 glBindTexture(GL_TEXTURE_2D, colorTexture);
4052 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4053
4054 GLFramebuffer fbo;
4055 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4056 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4057 ASSERT_GL_NO_ERROR();
4058 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4059
4060 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4061 ASSERT_GL_NO_ERROR();
4062 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
4063
4064 // The second texture is defined with R8 as its format.
4065 GLTexture colorTexture2;
4066 glBindTexture(GL_TEXTURE_2D, colorTexture2);
4067 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, kSize, kSize, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
4068
4069 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4070 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
4071 ASSERT_GL_NO_ERROR();
4072 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4073
4074 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4075 ASSERT_GL_NO_ERROR();
4076 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
4077 }
4078
4079 // Test binding two textures with different attachments to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentAttachmentsToFBOAndDraw)4080 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentAttachmentsToFBOAndDraw)
4081 {
4082 constexpr GLuint kSize = 2;
4083
4084 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4085
4086 GLTexture colorTexture;
4087 glBindTexture(GL_TEXTURE_2D, colorTexture);
4088 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4089
4090 GLFramebuffer fbo;
4091 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4092 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4093 ASSERT_GL_NO_ERROR();
4094 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4095
4096 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4097 ASSERT_GL_NO_ERROR();
4098 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4099
4100 // The second texture has an additional depth attachment.
4101 GLTexture colorTexture2;
4102 glBindTexture(GL_TEXTURE_2D, colorTexture2);
4103 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4104 ASSERT_GL_NO_ERROR();
4105
4106 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4107 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
4108
4109 GLRenderbuffer depthBuffer;
4110 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
4111 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
4112 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
4113
4114 ASSERT_GL_NO_ERROR();
4115 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4116
4117 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4118 ASSERT_GL_NO_ERROR();
4119 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4120 }
4121
4122 // Test binding two textures with different create flags to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentCreateFlagsToFBOAndDraw)4123 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentCreateFlagsToFBOAndDraw)
4124 {
4125 constexpr GLuint kSize = 2;
4126
4127 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4128
4129 GLTexture colorTexture;
4130 glBindTexture(GL_TEXTURE_2D, colorTexture);
4131 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4132
4133 GLFramebuffer fbo;
4134 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4135 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4136 ASSERT_GL_NO_ERROR();
4137 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4138
4139 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4140 ASSERT_GL_NO_ERROR();
4141 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4142
4143 // The second texture is defined as a cubemap, changing its create flags.
4144 GLTexture colorTexture2;
4145 glBindTexture(GL_TEXTURE_CUBE_MAP, colorTexture2);
4146
4147 for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
4148 {
4149 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, 0, GL_RGBA8, kSize, kSize, 0,
4150 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4151 }
4152 ASSERT_GL_NO_ERROR();
4153
4154 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4155 for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
4156 {
4157 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4158 GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, colorTexture2, 0);
4159 }
4160 ASSERT_GL_NO_ERROR();
4161
4162 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4163
4164 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4165 ASSERT_GL_NO_ERROR();
4166 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4167 }
4168
4169 // Test binding two textures with different usage flags to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentUsageFlagsToFBOAndDraw)4170 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentUsageFlagsToFBOAndDraw)
4171 {
4172 constexpr GLuint kSize = 2;
4173
4174 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4175
4176 GLTexture colorTexture;
4177 glBindTexture(GL_TEXTURE_2D, colorTexture);
4178 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4179
4180 GLFramebuffer fbo;
4181 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4182 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4183 ASSERT_GL_NO_ERROR();
4184 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4185
4186 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4187 ASSERT_GL_NO_ERROR();
4188 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4189
4190 // The second texture is used in a compute shader before the original shader, adding the storage
4191 // bit to its usage bits.
4192 GLTexture colorTexture2;
4193 glBindTexture(GL_TEXTURE_2D, colorTexture2);
4194 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4195 ASSERT_GL_NO_ERROR();
4196
4197 constexpr char kCS[] = R"(#version 310 es
4198 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4199 uniform vec4 data;
4200 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
4201
4202 void main()
4203 {
4204 imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
4205 })";
4206
4207 GLuint computeProgram = CompileComputeProgram(kCS);
4208 ASSERT_NE(computeProgram, 0u);
4209 glUseProgram(computeProgram);
4210
4211 glBindImageTexture(0, colorTexture2, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4212
4213 GLint uniformLoc = glGetUniformLocation(computeProgram, "data");
4214 ASSERT_NE(uniformLoc, -1);
4215 glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
4216
4217 glDispatchCompute(1, 1, 1);
4218 EXPECT_GL_NO_ERROR();
4219
4220 glUseProgram(program);
4221 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4222 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
4223 ASSERT_GL_NO_ERROR();
4224 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4225
4226 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4227 ASSERT_GL_NO_ERROR();
4228 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4229 }
4230
4231 // Test that clear with color masks on framebuffer texture with internal format GL_RGB5_A1 works
4232 // This is a simplified version of below two deqp tests:
4233 // KHR-GLES31.core.draw_buffers_indexed.color_masks
4234 // KHR-GLES32.core.draw_buffers_indexed.color_masks
TEST_P(FramebufferTest_ES31,ClearWithColorMasksRGB5A1)4235 TEST_P(FramebufferTest_ES31, ClearWithColorMasksRGB5A1)
4236 {
4237 constexpr int kSize = 4;
4238 GLint maxDrawBuffers = 0;
4239 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
4240 GLFramebuffer fbo;
4241 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4242
4243 std::vector<GLenum> bufs(maxDrawBuffers);
4244 for (int i = 0; i < maxDrawBuffers; ++i)
4245 {
4246 bufs[i] = GL_COLOR_ATTACHMENT0 + i;
4247 }
4248
4249 // Specifies a list of color buffers to be drawn into
4250 glDrawBuffers(maxDrawBuffers, &bufs[0]);
4251
4252 glDisable(GL_DITHER);
4253
4254 // Attach textures with internal format GL_RGB5_A1 to each framebuffer color attachment
4255 GLTexture textures[maxDrawBuffers];
4256 std::vector<unsigned char> pixelData(kSize * kSize * 4, 255);
4257 for (int i = 0; i < maxDrawBuffers; ++i)
4258 {
4259 glBindTexture(GL_TEXTURE_2D, textures[i]);
4260 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4261 pixelData.data());
4262 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i],
4263 0);
4264 }
4265
4266 ASSERT_GL_NO_ERROR();
4267 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4268
4269 // Clear all buffers with clear color (0.15f, 0.3f, 0.45f, 0.6f)
4270 angle::Vector4 clearColor(0.15f, 0.3f, 0.45f, 0.6f);
4271 for (int i = 0; i < maxDrawBuffers; ++i)
4272 {
4273 glClearBufferfv(GL_COLOR, i, clearColor.data());
4274 }
4275
4276 ASSERT_GL_NO_ERROR();
4277
4278 // Set color masks
4279 for (int i = 0; i < maxDrawBuffers; ++i)
4280 {
4281 if (i % 4 == 0)
4282 {
4283 glColorMaski(i, GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
4284 }
4285
4286 if (i % 4 == 1)
4287 {
4288 glColorMaski(i, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
4289 }
4290
4291 if (i % 4 == 2)
4292 {
4293 glColorMaski(i, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
4294 }
4295
4296 if (i % 4 == 3)
4297 {
4298 glColorMaski(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
4299 }
4300 }
4301
4302 ASSERT_GL_NO_ERROR();
4303
4304 // Clear buffers again with a new clear color (0.85f, 0.85f, 0.85f, 0.85f)
4305 // Only the channel with color mask set to GL_TRUE is cleared with the new color.
4306 clearColor = {0.85f, 0.85f, 0.85f, 0.85f};
4307 for (int i = 0; i < maxDrawBuffers; ++i)
4308 {
4309 glClearBufferfv(GL_COLOR, i, &clearColor[0]);
4310 }
4311
4312 ASSERT_GL_NO_ERROR();
4313
4314 // Read and Verify
4315 // calculate the comparison epsilon based on the number of bits
4316 std::vector<int> bits = {0, 0, 0, 0};
4317 std::vector<uint8_t> epsilon = {0, 0, 0, 0};
4318 for (int i = 0; i < 4; ++i)
4319 {
4320 glGetIntegerv(GL_RED_BITS + i, bits.data() + i);
4321 epsilon[i] =
4322 std::min(255u, static_cast<unsigned int>(
4323 ceil(1.0 + 255.0 * (1.0 / pow(2.0, static_cast<double>(bits[i]))))));
4324
4325 ASSERT(epsilon[i] >= 0 && epsilon[i] <= 255u);
4326 }
4327
4328 std::vector<GLColor> rendered(kSize * kSize, GLColor::green);
4329
4330 for (int i = 0; i < maxDrawBuffers; ++i)
4331 {
4332 std::vector<uint8_t> expected = {
4333 static_cast<uint8_t>(0.15f * 255), static_cast<uint8_t>(0.30f * 255),
4334 static_cast<uint8_t>(0.45f * 255), static_cast<uint8_t>(0.60f * 255)};
4335 expected[i % 4] = static_cast<uint8_t>(0.85f * 255);
4336
4337 glReadBuffer(GL_COLOR_ATTACHMENT0 + i);
4338 glReadPixels(0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, rendered.data());
4339
4340 for (int y = 0; y < kSize; ++y)
4341 {
4342 for (int x = 0; x < kSize; ++x)
4343 {
4344 GLColor readBackData = rendered[y * kSize + x];
4345
4346 bool exactMatch = readBackData.R == expected[0] && readBackData.G == expected[1] &&
4347 readBackData.B == expected[2] && readBackData.A == expected[3];
4348
4349 bool matchWithinEpsilon =
4350 abs(static_cast<int>(readBackData.R) - static_cast<int>(expected[0])) <=
4351 static_cast<int>(epsilon[0]) &&
4352 abs(static_cast<int>(readBackData.G) - static_cast<int>(expected[1])) <=
4353 static_cast<int>(epsilon[1]) &&
4354 abs(static_cast<int>(readBackData.B) - static_cast<int>(expected[2])) <=
4355 static_cast<int>(epsilon[2]) &&
4356 abs(static_cast<int>(readBackData.A) - static_cast<int>(expected[3])) <=
4357 static_cast<int>(epsilon[3]);
4358
4359 ASSERT(exactMatch || matchWithinEpsilon);
4360 }
4361 }
4362 }
4363
4364 // Set the framebuffer color mask back to default values
4365 for (int i = 0; i < maxDrawBuffers; ++i)
4366 {
4367 glColorMaski(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4368 }
4369
4370 ASSERT_GL_NO_ERROR();
4371 }
4372
clearColorMorePrecisionThanFBOFormatNoDithering(const GLint & fboInternalFormat)4373 void clearColorMorePrecisionThanFBOFormatNoDithering(const GLint &fboInternalFormat)
4374 {
4375 constexpr int kSize = 4;
4376 GLFramebuffer fbo;
4377 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4378
4379 glDisable(GL_DITHER);
4380
4381 // Attach texture with internal format GL_RGB5_A1 to each framebuffer color attachment
4382 std::vector<unsigned char> pixelData(kSize * kSize * 4, 255);
4383 GLTexture texture;
4384 glBindTexture(GL_TEXTURE_2D, texture);
4385 glTexImage2D(GL_TEXTURE_2D, 0, fboInternalFormat, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4386 pixelData.data());
4387 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4388 ASSERT_GL_NO_ERROR();
4389 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4390
4391 // Clear FBO color attachment with clear color (0.15f, 0.3f, 0.45f, 0.6f)
4392 glClearColor(0.15f, 0.3f, 0.45f, 0.6f);
4393 glClear(GL_COLOR_BUFFER_BIT);
4394 ASSERT_GL_NO_ERROR();
4395
4396 // Read and Verify
4397 // calculate the comparison epsilon based on the number of bits
4398 std::vector<int> bits = {0, 0, 0, 0};
4399 std::vector<uint8_t> epsilon = {0, 0, 0, 0};
4400 for (int i = 0; i < 4; ++i)
4401 {
4402 glGetIntegerv(GL_RED_BITS + i, bits.data() + i);
4403 epsilon[i] =
4404 std::min(255u, static_cast<unsigned int>(
4405 ceil(1.0 + 255.0 * (1.0 / pow(2.0, static_cast<double>(bits[i]))))));
4406
4407 ASSERT(epsilon[i] >= 0 && epsilon[i] <= 255u);
4408 }
4409
4410 std::vector<GLColor> rendered(kSize * kSize, GLColor::green);
4411
4412 std::vector<uint8_t> expected = {
4413 static_cast<uint8_t>(0.15f * 255), static_cast<uint8_t>(0.30f * 255),
4414 static_cast<uint8_t>(0.45f * 255), static_cast<uint8_t>(0.60f * 255)};
4415
4416 glReadPixels(0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, rendered.data());
4417 ASSERT_GL_NO_ERROR();
4418
4419 // Every pixel should have the same rendered result color. No dithering should be applied.
4420 GLColor clearedResultAtFirstPixel = rendered[0];
4421
4422 for (int y = 0; y < kSize; ++y)
4423 {
4424 for (int x = 0; x < kSize; ++x)
4425 {
4426 GLColor readBackData = rendered[y * kSize + x];
4427
4428 // Firstly check the rendered result is rational
4429 bool exactMatch = readBackData.R == expected[0] && readBackData.G == expected[1] &&
4430 readBackData.B == expected[2] && readBackData.A == expected[3];
4431
4432 bool matchWithinEpsilon =
4433 abs(static_cast<int>(readBackData.R) - static_cast<int>(expected[0])) <=
4434 static_cast<int>(epsilon[0]) &&
4435 abs(static_cast<int>(readBackData.G) - static_cast<int>(expected[1])) <=
4436 static_cast<int>(epsilon[1]) &&
4437 abs(static_cast<int>(readBackData.B) - static_cast<int>(expected[2])) <=
4438 static_cast<int>(epsilon[2]) &&
4439 abs(static_cast<int>(readBackData.A) - static_cast<int>(expected[3])) <=
4440 static_cast<int>(epsilon[3]);
4441
4442 ASSERT(exactMatch || matchWithinEpsilon);
4443
4444 // Secondly check no dithering is applied
4445 bool sameClearResultAsFirstPixel = readBackData.R == clearedResultAtFirstPixel.R &&
4446 readBackData.G == clearedResultAtFirstPixel.G &&
4447 readBackData.B == clearedResultAtFirstPixel.B &&
4448 readBackData.A == clearedResultAtFirstPixel.A;
4449 ASSERT(sameClearResultAsFirstPixel);
4450 }
4451 }
4452 }
4453
4454 // Verify that when clear color has more precision than FBO color attachment format can hold,
4455 // dithering is not automatically applied.
4456 // https://issuetracker.google.com/292282210
TEST_P(FramebufferTest_ES31,ClearColorMorePrecisionThanFBOFormatShouldNotApplyDithering)4457 TEST_P(FramebufferTest_ES31, ClearColorMorePrecisionThanFBOFormatShouldNotApplyDithering)
4458 {
4459 clearColorMorePrecisionThanFBOFormatNoDithering(GL_RGB5_A1);
4460 }
4461
4462 // Validates both MESA and standard functions can be used on OpenGL ES >=3.1
TEST_P(FramebufferTest_ES31,ValidateFramebufferFlipYMesaExtension)4463 TEST_P(FramebufferTest_ES31, ValidateFramebufferFlipYMesaExtension)
4464 {
4465 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
4466
4467 GLFramebuffer mFramebuffer;
4468 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
4469
4470 glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
4471 ASSERT_GL_NO_ERROR();
4472
4473 GLint flip_y = -1;
4474
4475 glGetFramebufferParameterivMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
4476 ASSERT_GL_NO_ERROR();
4477 EXPECT_EQ(flip_y, 1);
4478
4479 glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
4480 ASSERT_GL_NO_ERROR();
4481
4482 flip_y = -1;
4483 glGetFramebufferParameterivMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
4484 ASSERT_GL_NO_ERROR();
4485 EXPECT_EQ(flip_y, 0);
4486
4487 // Also using non-MESA functions should work.
4488 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
4489 ASSERT_GL_NO_ERROR();
4490
4491 flip_y = -1;
4492 glGetFramebufferParameteriv(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
4493 ASSERT_GL_NO_ERROR();
4494 EXPECT_EQ(flip_y, 1);
4495
4496 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
4497 ASSERT_GL_NO_ERROR();
4498
4499 flip_y = -1;
4500 glGetFramebufferParameteriv(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
4501 ASSERT_GL_NO_ERROR();
4502 EXPECT_EQ(flip_y, 0);
4503 }
4504
4505 class AddMockTextureNoRenderTargetTest : public ANGLETest<>
4506 {
4507 public:
AddMockTextureNoRenderTargetTest()4508 AddMockTextureNoRenderTargetTest()
4509 {
4510 setWindowWidth(512);
4511 setWindowHeight(512);
4512 setConfigRedBits(8);
4513 setConfigGreenBits(8);
4514 setConfigBlueBits(8);
4515 setConfigAlphaBits(8);
4516 }
4517 };
4518
4519 // Test to verify workaround succeeds when no program outputs exist http://anglebug.com/2283
TEST_P(AddMockTextureNoRenderTargetTest,NoProgramOutputWorkaround)4520 TEST_P(AddMockTextureNoRenderTargetTest, NoProgramOutputWorkaround)
4521 {
4522 constexpr char kVS[] = "void main() {}";
4523 constexpr char kFS[] = "void main() {}";
4524
4525 ANGLE_GL_PROGRAM(drawProgram, kVS, kFS);
4526
4527 glUseProgram(drawProgram);
4528
4529 glDrawArrays(GL_TRIANGLES, 0, 6);
4530
4531 ASSERT_GL_NO_ERROR();
4532 }
4533
4534 // Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
4535 // calls to DrawBuffers.
TEST_P(FramebufferTest_ES3,AttachmentStateChange)4536 TEST_P(FramebufferTest_ES3, AttachmentStateChange)
4537 {
4538 constexpr GLuint kSize = 2;
4539
4540 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4541
4542 GLTexture colorTexture;
4543 glBindTexture(GL_TEXTURE_2D, colorTexture);
4544 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4545
4546 GLFramebuffer fbo;
4547 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4548 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4549
4550 ASSERT_GL_NO_ERROR();
4551 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4552
4553 // First draw without a depth buffer.
4554 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4555
4556 GLRenderbuffer depthBuffer;
4557 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
4558 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
4559
4560 // Bind just a renderbuffer and draw.
4561 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
4562
4563 ASSERT_GL_NO_ERROR();
4564 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4565
4566 glDrawBuffers(0, nullptr);
4567 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4568
4569 // Re-enable color buffer and draw one final time. This previously triggered a crash.
4570 GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
4571 glDrawBuffers(1, &drawBuffs);
4572
4573 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4574 ASSERT_GL_NO_ERROR();
4575 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4576 }
4577
4578 // Tests that we can support a color texture also attached to the color attachment but
4579 // with different LOD. From GLES3.0 spec section 4.4.3.2, if min_filter is GL_NEAREST_MIPMAP_NEAREST
4580 // and the lod is within the [base_level, max_level] range, and it is possible to sample from a LOD
4581 // that is rendering to then it does form a feedback loop. But if it is using textureLOD to
4582 // explicitly fetching texture on different LOD, there is no loop and should still work. Aztec_ruins
4583 // (https://issuetracker.google.com/175584609) is doing exactly this.
TEST_P(FramebufferTest_ES3,SampleFromAttachedTextureWithDifferentLOD)4584 TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLOD)
4585 {
4586 // TODO: https://anglebug.com/5760
4587 ANGLE_SKIP_TEST_IF(IsD3D());
4588
4589 constexpr GLuint kLevel0Size = 4;
4590 constexpr GLuint kLevel1Size = kLevel0Size / 2;
4591 constexpr GLuint kLevel2Size = kLevel1Size / 2;
4592 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4593
4594 GLTexture colorTexture;
4595 glBindTexture(GL_TEXTURE_2D, colorTexture);
4596 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4598 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
4599 gData.fill(GLColor::red);
4600 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
4601 gData.data());
4602 gData.fill(GLColor::green);
4603 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
4604 gData.data());
4605 gData.fill(GLColor::blue);
4606 glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, kLevel2Size, kLevel2Size, GL_RGBA, GL_UNSIGNED_BYTE,
4607 gData.data());
4608
4609 // Attach level 1 to a FBO
4610 GLFramebuffer framebuffer;
4611 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4612 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4613 ASSERT_GL_NO_ERROR();
4614 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4615
4616 // Render to FBO with color texture level 1 and textureLod from level 0.
4617 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
4618 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
4619 glViewport(0, 0, kLevel1Size, kLevel1Size);
4620 glScissor(0, 0, kLevel1Size, kLevel1Size);
4621 glEnable(GL_CULL_FACE);
4622 glCullFace(GL_BACK);
4623 glDisable(GL_BLEND);
4624 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4625 glActiveTexture(GL_TEXTURE0);
4626 glBindTexture(GL_TEXTURE_2D, colorTexture);
4627
4628 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
4629 glUseProgram(program);
4630 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
4631 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
4632 ASSERT_NE(-1, textureLoc);
4633 ASSERT_NE(-1, lodLoc);
4634 glUniform1i(textureLoc, 0); // texture unit 0
4635 glUniform1f(lodLoc, 0); // with Lod=0
4636 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4637
4638 glDisable(GL_CULL_FACE);
4639 glDisable(GL_DEPTH_TEST);
4640 glDisable(GL_BLEND);
4641 glDisable(GL_SCISSOR_TEST);
4642 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4643
4644 ASSERT_GL_NO_ERROR();
4645 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4646 }
4647
4648 // This extends the test SampleFromAttachedTextureWithDifferentLOD by creating two renderpasses
4649 // without changing texture binding. This is to make sure that sample/render to the same texture
4650 // still function properly when transition from one renderpass to another without texture binding
4651 // change.
TEST_P(FramebufferTest_ES3,SampleFromAttachedTextureWithDifferentLODAndFBOSwitch)4652 TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLODAndFBOSwitch)
4653 {
4654 // TODO: https://anglebug.com/5760
4655 ANGLE_SKIP_TEST_IF(IsD3D());
4656
4657 constexpr GLuint kLevel0Size = 4;
4658 constexpr GLuint kLevel1Size = kLevel0Size / 2;
4659 constexpr GLuint kLevel2Size = kLevel1Size / 2;
4660 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4661
4662 GLTexture colorTexture;
4663 glBindTexture(GL_TEXTURE_2D, colorTexture);
4664 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4665 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4666 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
4667 gData.fill(GLColor::red);
4668 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
4669 gData.data());
4670 gData.fill(GLColor::green);
4671 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
4672 gData.data());
4673 gData.fill(GLColor::blue);
4674 glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, kLevel2Size, kLevel2Size, GL_RGBA, GL_UNSIGNED_BYTE,
4675 gData.data());
4676
4677 // Attach level 1 to two FBOs
4678 GLFramebuffer framebuffer1;
4679 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
4680 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4681 ASSERT_GL_NO_ERROR();
4682 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4683 GLFramebuffer framebuffer2;
4684 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4685 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4686 ASSERT_GL_NO_ERROR();
4687 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4688
4689 // Render to left half of FBO1 and textureLod from level 0.
4690 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
4691 glViewport(0, 0, kLevel1Size / 2, kLevel1Size);
4692 glScissor(0, 0, kLevel1Size / 2, kLevel1Size);
4693 glActiveTexture(GL_TEXTURE0);
4694 glBindTexture(GL_TEXTURE_2D, colorTexture);
4695 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
4696 glUseProgram(program);
4697 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
4698 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
4699 ASSERT_NE(-1, textureLoc);
4700 ASSERT_NE(-1, lodLoc);
4701 glUniform1i(textureLoc, 0); // texture unit 0
4702 glUniform1f(lodLoc, 0); // with Lod=0
4703 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4704 ASSERT_GL_NO_ERROR();
4705
4706 // Render to right half of FBO2 and textureLod from level 0 without trigger texture binding
4707 // change.
4708 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4709 glViewport(kLevel1Size / 2, 0, kLevel1Size / 2, kLevel1Size);
4710 glScissor(kLevel1Size / 2, 0, kLevel1Size / 2, kLevel1Size);
4711 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4712 ASSERT_GL_NO_ERROR();
4713 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4714 EXPECT_PIXEL_COLOR_EQ(kLevel1Size - 1, 0, GLColor::red);
4715 }
4716
4717 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
4718 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
4719 // texture itself has not been initialized with any data before rendering (TexSubImage call may
4720 // initialize a VkImage object).
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithBeyondMaxLevel)4721 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBeyondMaxLevel)
4722 {
4723 constexpr GLuint kLevel0Size = 4;
4724 constexpr GLuint kLevel1Size = kLevel0Size / 2;
4725
4726 GLTexture colorTexture;
4727 glBindTexture(GL_TEXTURE_2D, colorTexture);
4728 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4729 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4730 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
4731 // set max_level to 0
4732 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
4733
4734 // Attach level 1 to a FBO
4735 GLFramebuffer framebuffer;
4736 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4737 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4738 ASSERT_GL_NO_ERROR();
4739 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4740
4741 // Render to FBO
4742 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4743 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
4744 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
4745 glViewport(0, 0, kLevel1Size, kLevel1Size);
4746 glScissor(0, 0, kLevel1Size, kLevel1Size);
4747 glEnable(GL_CULL_FACE);
4748 glCullFace(GL_BACK);
4749 glDisable(GL_BLEND);
4750 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4751 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
4752 glUseProgram(program);
4753 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4754
4755 glDisable(GL_CULL_FACE);
4756 glDisable(GL_DEPTH_TEST);
4757 glDisable(GL_BLEND);
4758 glDisable(GL_SCISSOR_TEST);
4759 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4760
4761 ASSERT_GL_NO_ERROR();
4762 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4763 }
4764
4765 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
4766 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
4767 // texture itself has been initialized with data before rendering.
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithSubImageWithBeyondMaxLevel)4768 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithSubImageWithBeyondMaxLevel)
4769 {
4770 constexpr GLuint kLevel0Size = 4;
4771 constexpr GLuint kLevel1Size = kLevel0Size / 2;
4772 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4773
4774 GLTexture colorTexture;
4775 glBindTexture(GL_TEXTURE_2D, colorTexture);
4776 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4777 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4778 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
4779 // set max_level to 0
4780 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
4781 // Initialize with TexSubImage call
4782 gData.fill(GLColor::blue);
4783 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
4784 gData.data());
4785
4786 // Attach level 1 to a FBO
4787 GLFramebuffer framebuffer;
4788 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4789 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4790 ASSERT_GL_NO_ERROR();
4791 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4792
4793 // Render to FBO
4794 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4795 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
4796 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
4797 glViewport(0, 0, kLevel1Size, kLevel1Size);
4798 glScissor(0, 0, kLevel1Size, kLevel1Size);
4799 glEnable(GL_CULL_FACE);
4800 glCullFace(GL_BACK);
4801 glDisable(GL_BLEND);
4802 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4803 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
4804 glUseProgram(program);
4805 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4806
4807 glDisable(GL_CULL_FACE);
4808 glDisable(GL_DEPTH_TEST);
4809 glDisable(GL_BLEND);
4810 glDisable(GL_SCISSOR_TEST);
4811 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4812
4813 ASSERT_GL_NO_ERROR();
4814 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4815 }
4816
4817 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
4818 // renders to an immutable texture at the level that is smaller than GL_TEXTURE_BASE_LEVEL. The
4819 // texture itself has been initialized with data before rendering. Filament is using it this way
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithBellowBaseLevelLOD)4820 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBellowBaseLevelLOD)
4821 {
4822 constexpr GLuint kLevel0Size = 4;
4823 constexpr GLuint kLevel1Size = kLevel0Size / 2;
4824 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4825
4826 GLTexture colorTexture;
4827 glBindTexture(GL_TEXTURE_2D, colorTexture);
4828 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4829 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4830 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
4831 // set base_level to 1
4832 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
4833 gData.fill(GLColor::blue);
4834 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
4835 gData.data());
4836
4837 // Attach level 0 to a FBO
4838 GLFramebuffer framebuffer;
4839 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4840 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4841 ASSERT_GL_NO_ERROR();
4842 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4843
4844 // Render to FBO
4845 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4846 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
4847 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
4848 glViewport(0, 0, kLevel0Size, kLevel0Size);
4849 glScissor(0, 0, kLevel0Size, kLevel0Size);
4850 glEnable(GL_CULL_FACE);
4851 glCullFace(GL_BACK);
4852 glDisable(GL_BLEND);
4853 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4854 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
4855 glUseProgram(program);
4856 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4857
4858 glDisable(GL_CULL_FACE);
4859 glDisable(GL_DEPTH_TEST);
4860 glDisable(GL_BLEND);
4861 glDisable(GL_SCISSOR_TEST);
4862 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4863
4864 ASSERT_GL_NO_ERROR();
4865 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4866 }
4867
4868 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
4869 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
4870 // texture level that we render to has been initialized with data before rendering. This test if
4871 // render to that level will get flush the level update even though it is outside [base, max]
4872 // levels.
TEST_P(FramebufferTest_ES3,RenderImmutableTextureWithSubImageWithBeyondMaxLevel)4873 TEST_P(FramebufferTest_ES3, RenderImmutableTextureWithSubImageWithBeyondMaxLevel)
4874 {
4875 // Set up program to sample from specific lod level.
4876 GLProgram textureLodProgram;
4877 textureLodProgram.makeRaster(essl3_shaders::vs::Texture2DLod(),
4878 essl3_shaders::fs::Texture2DLod());
4879 ASSERT(textureLodProgram.valid());
4880 glUseProgram(textureLodProgram);
4881
4882 GLint textureLocation =
4883 glGetUniformLocation(textureLodProgram, essl3_shaders::Texture2DUniform());
4884 ASSERT_NE(-1, textureLocation);
4885 GLint lodLocation = glGetUniformLocation(textureLodProgram, essl3_shaders::LodUniform());
4886 ASSERT_NE(-1, lodLocation);
4887
4888 constexpr GLuint kLevel0Size = 4;
4889 constexpr GLuint kLevel1Size = kLevel0Size / 2;
4890 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4891
4892 GLTexture colorTexture;
4893 glBindTexture(GL_TEXTURE_2D, colorTexture);
4894 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4895 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4896 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
4897 // Initialize level 0 with blue
4898 gData.fill(GLColor::blue);
4899 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
4900 gData.data());
4901 // set max_level to 0
4902 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
4903 // Draw with level 0
4904 glUniform1f(lodLocation, 0);
4905 drawQuad(textureLodProgram, essl3_shaders::PositionAttrib(), 0.5f);
4906 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4907
4908 // Initalize level 1 with green
4909 gData.fill(GLColor::green);
4910 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
4911 gData.data());
4912 // Attach level 1 to a FBO
4913 GLFramebuffer framebuffer;
4914 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4915 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4916 ASSERT_GL_NO_ERROR();
4917 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4918 // Render to FBO (i.e. level 1) with Red and blend with existing texture level data
4919 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4920 glViewport(0, 0, kLevel1Size, kLevel1Size);
4921 glScissor(0, 0, kLevel1Size, kLevel1Size);
4922 glEnable(GL_CULL_FACE);
4923 glCullFace(GL_BACK);
4924 glEnable(GL_BLEND);
4925 glBlendFunc(GL_ONE, GL_ONE);
4926 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4927 ANGLE_GL_PROGRAM(redProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
4928 glUseProgram(redProgram);
4929 drawQuad(redProgram, essl3_shaders::PositionAttrib(), 0.5f);
4930
4931 glDisable(GL_CULL_FACE);
4932 glDisable(GL_DEPTH_TEST);
4933 glDisable(GL_BLEND);
4934 glDisable(GL_SCISSOR_TEST);
4935 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4936
4937 ASSERT_GL_NO_ERROR();
4938 // Expect to see Red + Green, which is Yellow
4939 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4940 }
4941
4942 // Similar to the other RenderImmutableTexture*** tests, but test on depth attachment instead of
4943 // color attachment. This tests render to a depth texture level that is less than
4944 // GL_TEXTURE_BASE_LEVEL and sample from it at the same time.
TEST_P(FramebufferTest_ES3,RenderSampleDepthTextureWithExcludedLevel)4945 TEST_P(FramebufferTest_ES3, RenderSampleDepthTextureWithExcludedLevel)
4946 {
4947 // Set up program to copy depth texture's value to color.red.
4948 constexpr char kVS[] = R"(precision mediump float;
4949 attribute vec4 a_position;
4950 varying vec2 v_texCoord;
4951 void main()
4952 {
4953 gl_Position = a_position;
4954 v_texCoord = a_position.xy * 0.5 + vec2(0.5);
4955 })";
4956 constexpr char kFS[] = R"(precision mediump float;
4957 varying vec2 v_texCoord;
4958 uniform sampler2D depth;
4959 void main()
4960 {
4961 gl_FragColor = vec4(texture2D(depth, v_texCoord).x, 1, 0, 1);
4962 })";
4963 ANGLE_GL_PROGRAM(program, kVS, kFS);
4964
4965 constexpr GLuint kLevel0Size = 4;
4966 constexpr GLuint kLevel1Size = kLevel0Size / 2;
4967
4968 GLTexture colorTexture;
4969 glBindTexture(GL_TEXTURE_2D, colorTexture);
4970 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4971 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4972 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
4973
4974 GLTexture depthTexture;
4975 glBindTexture(GL_TEXTURE_2D, depthTexture);
4976 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4977 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4978 glTexStorage2D(GL_TEXTURE_2D, 3, GL_DEPTH_COMPONENT32F, kLevel0Size, kLevel0Size);
4979 // Initialize level 1 with known depth value
4980 std::array<GLfloat, kLevel1Size * kLevel1Size> gData = {0.2, 0.4, 0.6, 0.8};
4981 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_DEPTH_COMPONENT, GL_FLOAT,
4982 gData.data());
4983 // set base_level and max_level to 1, exclude level 0
4984 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
4985 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
4986
4987 // Attach level 0 to a FBO
4988 GLFramebuffer framebuffer;
4989 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4990 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4991 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
4992 ASSERT_GL_NO_ERROR();
4993 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4994
4995 // Render to FBO (LOD 0) with depth texture LOD 1
4996 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4997 glViewport(0, 0, kLevel0Size, kLevel0Size);
4998 glScissor(0, 0, kLevel0Size, kLevel0Size);
4999 glDepthMask(GL_TRUE);
5000 glEnable(GL_DEPTH_TEST);
5001 glDepthFunc(GL_ALWAYS);
5002 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5003 ASSERT_GL_NO_ERROR();
5004 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51u, 255u, 0, 255u), 1);
5005 EXPECT_PIXEL_COLOR_NEAR(kLevel0Size - 1, 0, GLColor(102u, 255u, 0, 255u), 1);
5006 EXPECT_PIXEL_COLOR_NEAR(0, kLevel0Size - 1, GLColor(153u, 255u, 0, 255u), 1);
5007 EXPECT_PIXEL_COLOR_NEAR(kLevel0Size - 1, kLevel0Size - 1, GLColor(204u, 255u, 0, 255u), 1);
5008
5009 // Now check depth value is 0.5
5010 glDepthFunc(GL_LESS);
5011 glDepthMask(GL_FALSE);
5012 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
5013 glUseProgram(blueProgram);
5014 // should fail depth test
5015 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.51f);
5016 ASSERT_GL_NO_ERROR();
5017 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51u, 255u, 0, 255u), 1);
5018 // should pass depth test
5019 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.49f);
5020 ASSERT_GL_NO_ERROR();
5021 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5022 }
5023
5024 // Covers a bug in ANGLE's Vulkan back-end. Our VkFramebuffer cache would in some cases forget to
5025 // check the draw states when computing a cache key.
TEST_P(FramebufferTest_ES3,DisabledAttachmentRedefinition)5026 TEST_P(FramebufferTest_ES3, DisabledAttachmentRedefinition)
5027 {
5028 constexpr GLuint kSize = 2;
5029
5030 // Make a Framebuffer with two attachments with one enabled and one disabled.
5031 GLTexture texA, texB;
5032 glBindTexture(GL_TEXTURE_2D, texA);
5033 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5034 glBindTexture(GL_TEXTURE_2D, texB);
5035 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5036
5037 GLFramebuffer fbo;
5038 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5039 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
5040 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
5041
5042 // Mask out the second texture.
5043 constexpr GLenum kOneDrawBuf = GL_COLOR_ATTACHMENT0;
5044 glDrawBuffers(1, &kOneDrawBuf);
5045
5046 ASSERT_GL_NO_ERROR();
5047 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5048
5049 // Set up a very simple shader.
5050 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
5051 glViewport(0, 0, kSize, kSize);
5052
5053 // Draw
5054 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5055 ASSERT_GL_NO_ERROR();
5056 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5057
5058 // Update the masked out attachment and draw again.
5059 std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
5060 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
5061 redPixels.data());
5062
5063 // Draw
5064 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5065 ASSERT_GL_NO_ERROR();
5066 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5067
5068 glReadBuffer(GL_COLOR_ATTACHMENT1);
5069 ASSERT_GL_NO_ERROR();
5070 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5071 }
5072
5073 // Test that changing the attachment of a framebuffer then sync'ing both READ and DRAW framebuffer
5074 // (currently possible with glInvalidateFramebuffer) updates the scissor correctly.
TEST_P(FramebufferTest_ES3,ChangeAttachmentThenInvalidateAndDraw)5075 TEST_P(FramebufferTest_ES3, ChangeAttachmentThenInvalidateAndDraw)
5076 {
5077 constexpr GLsizei kSizeLarge = 32;
5078 constexpr GLsizei kSizeSmall = 16;
5079
5080 GLTexture color1;
5081 glBindTexture(GL_TEXTURE_2D, color1);
5082 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeSmall, kSizeSmall, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5083 nullptr);
5084
5085 GLTexture color2;
5086 glBindTexture(GL_TEXTURE_2D, color2);
5087 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5088 nullptr);
5089
5090 GLFramebuffer fbo;
5091 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5092 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
5093
5094 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5095 glUseProgram(drawColor);
5096 GLint colorUniformLocation =
5097 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5098 ASSERT_NE(colorUniformLocation, -1);
5099
5100 glViewport(0, 0, kSizeLarge, kSizeLarge);
5101
5102 // Draw red into the framebuffer.
5103 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
5104 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5105 ASSERT_GL_NO_ERROR();
5106
5107 // Change the attachment, invalidate it and draw green.
5108 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color2, 0);
5109 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5110
5111 std::array<GLenum, 1> attachments = {GL_COLOR_ATTACHMENT0};
5112 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
5113 ASSERT_GL_NO_ERROR();
5114
5115 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
5116 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5117 ASSERT_GL_NO_ERROR();
5118
5119 // Validate the result.
5120 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::green);
5121
5122 // Do the same, but changing from the large to small attachment.
5123
5124 // Draw red into the framebuffer.
5125 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
5126 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5127 ASSERT_GL_NO_ERROR();
5128
5129 // Change the attachment, invalidate it and draw blue.
5130 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
5131 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5132 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
5133
5134 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
5135 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5136 ASSERT_GL_NO_ERROR();
5137
5138 // Validate the result.
5139 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::blue);
5140 }
5141
5142 // Test Framebuffer object with two attachments that have unequal size. In OpenGLES3.0, this is
5143 // a supported config. The common intersection area should be correctly rendered. The contents
5144 // outside common intersection area are undefined.
TEST_P(FramebufferTest_ES3,AttachmentsWithUnequalDimensions)5145 TEST_P(FramebufferTest_ES3, AttachmentsWithUnequalDimensions)
5146 {
5147 ANGLE_SKIP_TEST_IF(IsD3D());
5148
5149 constexpr GLsizei kSizeLarge = 32;
5150 constexpr GLsizei kSizeSmall = 16;
5151
5152 GLTexture colorTexture;
5153 glBindTexture(GL_TEXTURE_2D, colorTexture);
5154 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeSmall, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5155 nullptr);
5156
5157 GLRenderbuffer color;
5158 glBindRenderbuffer(GL_RENDERBUFFER, color);
5159 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSizeSmall, kSizeLarge);
5160
5161 GLRenderbuffer depth;
5162 glBindRenderbuffer(GL_RENDERBUFFER, depth);
5163 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kSizeSmall, kSizeLarge);
5164
5165 GLRenderbuffer stencil;
5166 glBindRenderbuffer(GL_RENDERBUFFER, stencil);
5167 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSizeSmall, kSizeLarge);
5168
5169 struct
5170 {
5171 GLenum attachment;
5172 GLuint renderbuffer;
5173 } attachment2[4] = {{GL_COLOR_ATTACHMENT1, 0},
5174 {GL_COLOR_ATTACHMENT1, color},
5175 {GL_DEPTH_ATTACHMENT, depth},
5176 {GL_STENCIL_ATTACHMENT, stencil}};
5177 for (int i = 0; i < 4; i++)
5178 {
5179 GLFramebuffer fbo;
5180 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5181 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
5182 0);
5183 if (attachment2[i].renderbuffer)
5184 {
5185 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment2[i].attachment, GL_RENDERBUFFER,
5186 attachment2[i].renderbuffer);
5187 }
5188 ASSERT_GL_NO_ERROR();
5189 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5190
5191 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5192 glUseProgram(drawColor);
5193 GLint colorUniformLocation =
5194 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5195 ASSERT_NE(colorUniformLocation, -1);
5196
5197 glViewport(0, 0, kSizeLarge, kSizeLarge);
5198 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
5199 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
5200
5201 // Draw red into the framebuffer.
5202 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
5203 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5204 ASSERT_GL_NO_ERROR();
5205
5206 // Validate the result. The intersected common area should be red now
5207 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::red);
5208 }
5209 }
5210
5211 // Validates only MESA functions can be used on OpenGL ES <3.1
TEST_P(FramebufferTest_ES3,ValidateFramebufferFlipYMesaExtension)5212 TEST_P(FramebufferTest_ES3, ValidateFramebufferFlipYMesaExtension)
5213 {
5214 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
5215
5216 GLFramebuffer mFramebuffer;
5217 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
5218
5219 glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
5220 ASSERT_GL_NO_ERROR();
5221
5222 GLint flip_y = -1;
5223
5224 glGetFramebufferParameterivMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
5225 ASSERT_GL_NO_ERROR();
5226 EXPECT_EQ(flip_y, 1);
5227
5228 glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
5229 ASSERT_GL_NO_ERROR();
5230
5231 flip_y = -1;
5232 glGetFramebufferParameterivMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
5233 ASSERT_GL_NO_ERROR();
5234 EXPECT_EQ(flip_y, 0);
5235
5236 // Using non-MESA function should fail.
5237 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
5238 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
5239
5240 glGetFramebufferParameteriv(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
5241 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
5242 }
5243
TEST_P(FramebufferTest_ES3,FramebufferFlipYMesaExtensionIncorrectPname)5244 TEST_P(FramebufferTest_ES3, FramebufferFlipYMesaExtensionIncorrectPname)
5245 {
5246 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
5247
5248 GLFramebuffer mFramebuffer;
5249 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
5250
5251 glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
5252 ASSERT_GL_ERROR(GL_INVALID_ENUM);
5253 }
5254
5255 class FramebufferTest : public ANGLETest<>
5256 {};
5257
5258 template <typename T>
FillTexture2D(GLuint texture,GLsizei width,GLsizei height,const T & onePixelData,GLint level,GLint internalFormat,GLenum format,GLenum type)5259 void FillTexture2D(GLuint texture,
5260 GLsizei width,
5261 GLsizei height,
5262 const T &onePixelData,
5263 GLint level,
5264 GLint internalFormat,
5265 GLenum format,
5266 GLenum type)
5267 {
5268 std::vector<T> allPixelsData(width * height, onePixelData);
5269
5270 glBindTexture(GL_TEXTURE_2D, texture);
5271 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
5272 allPixelsData.data());
5273 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5277 }
5278
5279 // Multi-context uses of textures should not cause rendering feedback loops.
TEST_P(FramebufferTest,MultiContextNoRenderingFeedbackLoops)5280 TEST_P(FramebufferTest, MultiContextNoRenderingFeedbackLoops)
5281 {
5282 constexpr char kTextureVS[] =
5283 R"(attribute vec4 a_position;
5284 varying vec2 v_texCoord;
5285 void main() {
5286 gl_Position = a_position;
5287 v_texCoord = (a_position.xy * 0.5) + 0.5;
5288 })";
5289
5290 constexpr char kTextureFS[] =
5291 R"(precision mediump float;
5292 varying vec2 v_texCoord;
5293 uniform sampler2D u_texture;
5294 void main() {
5295 gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
5296 })";
5297
5298 ANGLE_GL_PROGRAM(textureProgram, kTextureVS, kTextureFS);
5299
5300 glUseProgram(textureProgram);
5301 GLint uniformLoc = glGetUniformLocation(textureProgram, "u_texture");
5302 ASSERT_NE(-1, uniformLoc);
5303 glUniform1i(uniformLoc, 0);
5304
5305 GLTexture texture;
5306 FillTexture2D(texture, 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
5307 glBindTexture(GL_TEXTURE_2D, texture);
5308 // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
5309
5310 EGLWindow *window = getEGLWindow();
5311 EGLDisplay display = window->getDisplay();
5312 EGLConfig config = window->getConfig();
5313 EGLSurface surface = window->getSurface();
5314 EGLint contextAttributes[] = {
5315 EGL_CONTEXT_MAJOR_VERSION_KHR,
5316 GetParam().majorVersion,
5317 EGL_CONTEXT_MINOR_VERSION_KHR,
5318 GetParam().minorVersion,
5319 EGL_NONE,
5320 };
5321 EGLContext context1 = eglGetCurrentContext();
5322 // Create context2, sharing resources with context1.
5323 EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
5324 ASSERT_NE(context2, EGL_NO_CONTEXT);
5325 eglMakeCurrent(display, surface, surface, context2);
5326
5327 constexpr char kVS[] =
5328 R"(attribute vec4 a_position;
5329 void main() {
5330 gl_Position = a_position;
5331 })";
5332
5333 constexpr char kFS[] =
5334 R"(precision mediump float;
5335 void main() {
5336 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
5337 })";
5338
5339 ANGLE_GL_PROGRAM(program, kVS, kFS);
5340 glUseProgram(program);
5341
5342 ASSERT_GL_NO_ERROR();
5343
5344 // Render to the texture in context2.
5345 GLFramebuffer framebuffer;
5346 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5347 // Texture is still a valid name in context2.
5348 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
5349 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5350 // There is no rendering feedback loop at this point.
5351
5352 glDisable(GL_BLEND);
5353 glDisable(GL_DEPTH_TEST);
5354 ASSERT_GL_NO_ERROR();
5355
5356 // If draw is no-op'ed, texture will not be filled appropriately.
5357 drawQuad(program, "a_position", 0.5f, 1.0f, true);
5358 ASSERT_GL_NO_ERROR();
5359 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5360
5361 // Make context1 current again.
5362 eglMakeCurrent(display, surface, surface, context1);
5363
5364 // Render texture to screen.
5365 drawQuad(textureProgram, "a_position", 0.5f, 1.0f, true);
5366 ASSERT_GL_NO_ERROR();
5367 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5368
5369 eglDestroyContext(display, context2);
5370 }
5371
5372 // Ensure cube-incomplete attachments cause incomplete Framebuffers.
TEST_P(FramebufferTest,IncompleteCubeMap)5373 TEST_P(FramebufferTest, IncompleteCubeMap)
5374 {
5375 constexpr GLuint kSize = 2;
5376
5377 GLTexture srcTex;
5378 glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex);
5379 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
5380 GL_UNSIGNED_BYTE, nullptr);
5381
5382 GLFramebuffer fbo;
5383 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5384 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
5385 srcTex, 0);
5386
5387 ASSERT_GL_NO_ERROR();
5388 ASSERT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
5389 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
5390 }
5391
5392 // Test FBOs with different sizes are drawn correctly
TEST_P(FramebufferTest,BindAndDrawDifferentSizedFBOs)5393 TEST_P(FramebufferTest, BindAndDrawDifferentSizedFBOs)
5394 {
5395 // 1. Create FBO 1 with dimensions 16x16
5396 // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
5397 // 3. Create FBO 2 with dimensions 8x8
5398 // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
5399 // 5. Bind FBO 1 (note, it's not dirty)
5400 // 6. Draw blue into FBO 1
5401 // 7. Verify FBO 1 is entirely blue
5402
5403 GLFramebuffer smallFbo;
5404 GLFramebuffer largeFbo;
5405 GLTexture smallTexture;
5406 GLTexture largeTexture;
5407 constexpr GLsizei kLargeWidth = 16;
5408 constexpr GLsizei kLargeHeight = 16;
5409 constexpr GLsizei kSmallWidth = 8;
5410 constexpr GLsizei kSmallHeight = 8;
5411
5412 ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
5413 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
5414 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
5415
5416 // 1. Create FBO 1 with dimensions 16x16
5417 glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
5418 glBindTexture(GL_TEXTURE_2D, largeTexture);
5419 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kLargeWidth, kLargeHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5420 nullptr);
5421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5423 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
5424 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5425
5426 // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
5427 glUseProgram(redProgram);
5428 drawQuad(redProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
5429 ASSERT_GL_NO_ERROR();
5430
5431 // 3. Create FBO 2 with dimensions 8x8
5432 glBindFramebuffer(GL_FRAMEBUFFER, smallFbo);
5433 glBindTexture(GL_TEXTURE_2D, smallTexture);
5434 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallWidth, kSmallHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5435 nullptr);
5436 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5438 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
5439 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5440
5441 // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
5442 glUseProgram(greenProgram);
5443 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
5444 ASSERT_GL_NO_ERROR();
5445
5446 // 5. Bind FBO 1 (note, it's not dirty)
5447 glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
5448
5449 // 6. Draw blue into FBO 1
5450 glUseProgram(blueProgram);
5451 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
5452 ASSERT_GL_NO_ERROR();
5453
5454 // 7. Verify FBO 1 is entirely blue
5455 EXPECT_PIXEL_RECT_EQ(0, 0, kLargeWidth, kLargeHeight, GLColor::blue);
5456 }
5457
5458 // Test FBOs with same attachments. Destroy one framebuffer should not affect the other framebuffer
5459 // (chromium:1351170).
TEST_P(FramebufferTest_ES3,TwoFramebuffersWithSameAttachments)5460 TEST_P(FramebufferTest_ES3, TwoFramebuffersWithSameAttachments)
5461 {
5462 ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
5463 glUseProgram(redProgram);
5464
5465 GLRenderbuffer rb;
5466 glBindRenderbuffer(GL_RENDERBUFFER, rb);
5467 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
5468
5469 GLuint fbs[2];
5470 glGenFramebuffers(2, fbs);
5471 // Create fbos[0]
5472 glBindFramebuffer(GL_FRAMEBUFFER, fbs[0]);
5473 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
5474 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5475 const GLenum colorAttachment0 = {GL_COLOR_ATTACHMENT0};
5476 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &colorAttachment0);
5477 // Create fbos[1] with same attachment as fbos[0]
5478 glBindFramebuffer(GL_FRAMEBUFFER, fbs[1]);
5479 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
5480 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5481 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &colorAttachment0);
5482 // Destroy fbos[0]
5483 glDeleteFramebuffers(1, &fbs[0]);
5484 // fbos[1] should still work, not crash.
5485 GLuint data;
5486 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &data);
5487 drawQuad(redProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
5488 ASSERT_GL_NO_ERROR();
5489 }
5490
5491 // Regression test based on a fuzzer failure. A crash was encountered in the following situation:
5492 //
5493 // - Texture bound as sampler with MAX_LEVEL 0
5494 // - Framebuffer bound to level 0
5495 // - Draw
5496 // - Texture MAX_LEVEL changed to 1
5497 // - Framebuffer bound to level 1
5498 // - Draw
5499 //
5500 // Notes: Removing the first half removed the crash. MIN_FILTERING of LINEAR vs
5501 // LINEAR_MIPMAP_LINEAR did not make any changes.
TEST_P(FramebufferTest_ES3,FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash)5502 TEST_P(FramebufferTest_ES3, FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash)
5503 {
5504 constexpr char kFS[] = R"(precision mediump float;
5505 uniform sampler2D u_tex0;
5506 void main() {
5507 gl_FragColor = texture2D(u_tex0, vec2(0));
5508 })";
5509
5510 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), kFS);
5511 glUseProgram(program);
5512
5513 GLTexture mutTex;
5514 glBindTexture(GL_TEXTURE_2D, mutTex);
5515 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5516 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5517
5518 GLFramebuffer fb;
5519 glBindFramebuffer(GL_FRAMEBUFFER, fb);
5520
5521 // Attempt a draw with level 0 (feedback loop)
5522 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5523 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5524
5525 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutTex, 0);
5526 glDrawArrays(GL_POINTS, 0, 1);
5527
5528 // Attempt another draw with level 1.
5529 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5530
5531 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutTex, 1);
5532
5533 // This shouldn't crash.
5534 glDrawArrays(GL_POINTS, 0, 1);
5535 ASSERT_GL_NO_ERROR();
5536 }
5537
5538 // Modify renderbuffer attachment samples after bind
TEST_P(FramebufferTest_ES3,BindRenderbufferThenModifySamples)5539 TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySamples)
5540 {
5541 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5542 glUseProgram(program);
5543 GLint colorUniformLocation =
5544 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
5545 ASSERT_NE(colorUniformLocation, -1);
5546
5547 GLFramebuffer fbo;
5548 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5549
5550 GLsizei size = 16;
5551 glViewport(0, 0, size, size);
5552
5553 GLRenderbuffer color;
5554 glBindRenderbuffer(GL_RENDERBUFFER, color);
5555
5556 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, size, size);
5557 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
5558 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
5559
5560 glUniform4f(colorUniformLocation, 1, 0, 0, 1);
5561 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5562
5563 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5564 ASSERT_GL_NO_ERROR();
5565 }
5566
5567 // Modify renderbuffer attachment size after bind
TEST_P(FramebufferTest_ES3,BindRenderbufferThenModifySize)5568 TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySize)
5569 {
5570 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5571 glUseProgram(program);
5572 GLint colorUniformLocation =
5573 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
5574 ASSERT_NE(colorUniformLocation, -1);
5575
5576 GLFramebuffer fbo;
5577 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5578
5579 GLsizei size = 16;
5580 glViewport(0, 0, size, size);
5581
5582 GLRenderbuffer color;
5583 glBindRenderbuffer(GL_RENDERBUFFER, color);
5584
5585 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
5586 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
5587 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size / 2, size * 2);
5588
5589 glUniform4f(colorUniformLocation, 1, 0, 0, 1);
5590 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5591
5592 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5593 ASSERT_GL_NO_ERROR();
5594 }
5595
5596 // Tests redefining a layered framebuffer attachment.
TEST_P(FramebufferTest_ES3,RedefineLayerAttachment)5597 TEST_P(FramebufferTest_ES3, RedefineLayerAttachment)
5598 {
5599 GLTexture texture;
5600 glBindTexture(GL_TEXTURE_3D, texture);
5601 std::vector<uint8_t> imgData(20480, 0);
5602 glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, 8, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, imgData.data());
5603
5604 GLFramebuffer fbo;
5605 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5606 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 8);
5607 glGenerateMipmap(GL_TEXTURE_3D);
5608
5609 glTexImage3D(GL_TEXTURE_3D, 0, GL_R8UI, 16, 16, 16, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
5610 imgData.data());
5611 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, 2, 15, 16, 16);
5612 ASSERT_GL_NO_ERROR();
5613 }
5614
5615 // Covers a bug when changing a base level of a texture bound to a FBO.
TEST_P(FramebufferTest_ES3,ReattachToInvalidBaseLevel)5616 TEST_P(FramebufferTest_ES3, ReattachToInvalidBaseLevel)
5617 {
5618 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5619 glUseProgram(testProgram);
5620
5621 GLTexture tex;
5622 glBindTexture(GL_TEXTURE_2D, tex);
5623 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5624
5625 for (int mip = 0; mip <= 2; ++mip)
5626 {
5627 int size = 10 >> mip;
5628 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5629 nullptr);
5630 }
5631
5632 GLFramebuffer fb;
5633 glBindFramebuffer(GL_FRAMEBUFFER, fb);
5634 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 1);
5635 EXPECT_GL_NO_ERROR();
5636
5637 // Set base level 1 and draw.
5638 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5639 glDrawArrays(GL_POINTS, 0, 1);
5640 EXPECT_GL_NO_ERROR();
5641 // Set base level 0. The FBO is incomplete because the FBO attachment binds to level 1.
5642 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5643 glDrawArrays(GL_POINTS, 0, 1);
5644 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
5645 }
5646
5647 // Ensure that clear color is correctly applied after invalidate
TEST_P(FramebufferTest_ES3,InvalidateClearDraw)5648 TEST_P(FramebufferTest_ES3, InvalidateClearDraw)
5649 {
5650 constexpr GLsizei kSize = 2;
5651
5652 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
5653
5654 GLTexture tex;
5655 glBindTexture(GL_TEXTURE_2D, tex);
5656 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5657
5658 GLFramebuffer fbo;
5659 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5660 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5661
5662 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5663
5664 // Clear the image, and make sure the clear is flushed outside the render pass.
5665 glClearColor(1, 0, 0, 1);
5666 glClear(GL_COLOR_BUFFER_BIT);
5667 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5668
5669 // Invalidate it such that the contents are marked as undefined. Note that
5670 // regardless of the marking, the image is cleared nevertheless.
5671 const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
5672 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
5673
5674 // Clear it again to the same color, and make sure the clear is flushed outside the render pass,
5675 // which may be optimized out.
5676 glClear(GL_COLOR_BUFFER_BIT);
5677 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5678
5679 // Draw with blend. If the second clear is dropped and the image continues to be marked as
5680 // invalidated, loadOp=DONT_CARE would be used instead of loadOp=LOAD.
5681 glEnable(GL_BLEND);
5682 glBlendFunc(GL_ONE, GL_ONE);
5683
5684 drawQuad(program, essl1_shaders::PositionAttrib(), 0);
5685 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
5686 }
5687
5688 // Produces VUID-VkImageMemoryBarrier-oldLayout-01197 VVL error with a "Render pass closed due to
5689 // framebuffer change" command buffer label. As seen in Black Desert Mobile.
5690 // The application draws 2 passes to produce the issue. First pass draws to a depth only frame
5691 // buffer, the second one to a different color+depth frame buffer. The second pass samples the first
5692 // passes frame buffer in two draw calls. First draw call samples it in the fragment stage, second
5693 // in the the vertex stage.
TEST_P(FramebufferTest_ES3,FramebufferChangeTest)5694 TEST_P(FramebufferTest_ES3, FramebufferChangeTest)
5695 {
5696 // Init depth frame buffer
5697 GLFramebuffer depthFramebuffer;
5698 glBindFramebuffer(GL_FRAMEBUFFER, depthFramebuffer);
5699
5700 GLTexture depthAttachment;
5701 glBindTexture(GL_TEXTURE_2D, depthAttachment);
5702 // When using a color attachment instead, the issue does not occur.
5703 // The issue seems to occur for all GL_DEPTH_COMPONENT formats.
5704 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, kWidth, kHeight, 0, GL_DEPTH_COMPONENT,
5705 GL_UNSIGNED_INT, nullptr);
5706
5707 // If filtering the depth attachment to GL_NEAREST is not set, the issue does not occur.
5708 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5709 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5710
5711 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthAttachment, 0);
5712
5713 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5714 ASSERT_GL_NO_ERROR();
5715
5716 // Depth only pass
5717 {
5718 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
5719 glUseProgram(program);
5720
5721 glClear(GL_DEPTH_BUFFER_BIT);
5722
5723 glDrawArrays(GL_TRIANGLES, 0, 6);
5724 ASSERT_GL_NO_ERROR();
5725 }
5726
5727 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5728
5729 // Color pass
5730 // The depth texture from the first pass is sampled from in both draw calls.
5731 // Skipping any of the two depth texture binds makes the issue not occur.
5732 // Changing the order of the draw calls makes the issue not occur.
5733 // This pass does not need to draw into a frame buffer.
5734
5735 // Draw 1
5736 // The depth texture from the first pass is sampled from in the frament stage.
5737 {
5738 constexpr char kFS[] = {
5739 R"(#version 300 es
5740 precision mediump float;
5741
5742 uniform mediump sampler2D samp;
5743
5744 layout(location = 0) out highp vec4 color;
5745
5746 void main()
5747 {
5748 color = texture(samp, vec2(0));
5749 })",
5750 };
5751 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5752 glUseProgram(program);
5753
5754 GLint textureLoc = glGetUniformLocation(program, "samp");
5755 glUniform1i(textureLoc, 1);
5756
5757 // Skipping this bind makes the issue not occur
5758 glActiveTexture(GL_TEXTURE1);
5759 glBindTexture(GL_TEXTURE_2D, depthAttachment);
5760
5761 glDrawArrays(GL_TRIANGLES, 0, 6);
5762 ASSERT_GL_NO_ERROR();
5763 }
5764
5765 // Draw 2
5766 // Here the depth attachment from the first pass is used in the vertex stage. The VVL error
5767 // occurs in this draw. The sampler has to be attached to the vertex stage, otherwise the issue
5768 // does not occur.
5769 {
5770 constexpr char kVS[] = {
5771 R"(#version 300 es
5772
5773 uniform mediump sampler2D samp;
5774
5775 layout(location = 0) in mediump vec4 pos;
5776
5777 void main()
5778 {
5779 gl_Position = pos + texture(samp, vec2(0));
5780 })",
5781 };
5782
5783 ANGLE_GL_PROGRAM(program, kVS, essl3_shaders::fs::Red());
5784 glUseProgram(program);
5785
5786 GLint textureLoc = glGetUniformLocation(program, "samp");
5787 glUniform1i(textureLoc, 2);
5788
5789 // Skipping this bind makes the issue not occur
5790 glActiveTexture(GL_TEXTURE2);
5791 glBindTexture(GL_TEXTURE_2D, depthAttachment);
5792
5793 glDrawArrays(GL_TRIANGLES, 0, 6);
5794 ASSERT_GL_NO_ERROR();
5795 }
5796 }
5797
5798 // Regression test for a bug in the Vulkan backend where the application produces a conditional
5799 // framebuffer feedback loop which results in VUID-VkDescriptorImageInfo-imageLayout-00344 and
5800 // VUID-vkCmdDraw-None-02699 (or VUID-vkCmdDrawIndexed-None-02699 when a different draw call is
5801 // used). The application samples from the frame buffer it renders to depending on a uniform
5802 // condition.
TEST_P(FramebufferTest_ES3,FramebufferConditionalFeedbackLoop)5803 TEST_P(FramebufferTest_ES3, FramebufferConditionalFeedbackLoop)
5804 {
5805 GLTexture colorAttachment;
5806 glBindTexture(GL_TEXTURE_2D, colorAttachment);
5807 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
5808
5809 glActiveTexture(GL_TEXTURE13);
5810 glBindTexture(GL_TEXTURE_2D, colorAttachment);
5811
5812 ASSERT_GL_NO_ERROR();
5813
5814 GLFramebuffer framebuffer;
5815 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5816 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorAttachment, 0);
5817
5818 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5819
5820 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5821
5822 constexpr char kFS[] = {
5823 R"(#version 300 es
5824 precision mediump float;
5825
5826 uniform mediump sampler2D samp;
5827 uniform vec4 sampleCondition;
5828 out vec4 color;
5829
5830 void main()
5831 {
5832 if (sampleCondition.x > 0.0)
5833 {
5834 color = texture(samp, vec2(0.0));
5835 }
5836 })",
5837 };
5838
5839 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5840 glUseProgram(program);
5841
5842 GLint textureLoc = glGetUniformLocation(program, "samp");
5843 glUniform1i(textureLoc, 13);
5844
5845 // This draw is required for the issue to occur. The application does multiple draws to
5846 // different framebuffers at this point, but drawing without a framebuffer bound also does
5847 // reproduce it.
5848 glDrawArrays(GL_TRIANGLES, 0, 6);
5849 ASSERT_GL_NO_ERROR();
5850
5851 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5852
5853 // This draw triggers the issue.
5854 glDrawArrays(GL_TRIANGLES, 0, 6);
5855 ASSERT_GL_NO_ERROR();
5856 }
5857
5858 // Regression test for a bug in the Vulkan backend where sampling from a
5859 // texture previously involved in a framebuffer feedback loop would produce
5860 // VUID-VkDescriptorImageInfo-imageLayout-00344 and VUID-vkCmdDraw-None-02699
5861 // because of an incorrect cached descriptor set.
TEST_P(FramebufferTest_ES3,FeedbackLoopTextureBindings)5862 TEST_P(FramebufferTest_ES3, FeedbackLoopTextureBindings)
5863 {
5864 constexpr char kVS[] = R"(#version 300 es
5865 precision highp float;
5866 out vec2 texCoord;
5867 const vec2 kVertices[4] = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));
5868 void main()
5869 {
5870 gl_Position = vec4(kVertices[gl_VertexID], 0.0, 1.0);
5871 texCoord = (kVertices[gl_VertexID] * 0.5) + 0.5;
5872 })";
5873
5874 constexpr char kFS[] = R"(#version 300 es
5875 precision highp float;
5876 uniform sampler2D sampler;
5877 uniform int sampleCondition;
5878 in vec2 texCoord;
5879 out vec4 colorOut;
5880 const vec4 kGreen = vec4(0, 1, 0, 1);
5881 void main()
5882 {
5883 if (sampleCondition == 0) {
5884 colorOut = kGreen;
5885 } else {
5886 colorOut = texture(sampler, texCoord);
5887 }
5888 })";
5889
5890 ANGLE_GL_PROGRAM(program, kVS, kFS);
5891 GLint sampleCondition = glGetUniformLocation(program, "sampleCondition");
5892 glUseProgram(program);
5893
5894 GLTexture tex;
5895 glActiveTexture(GL_TEXTURE0);
5896 glBindTexture(GL_TEXTURE_2D, tex);
5897 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
5898 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
5899
5900 // Render to tex with tex bound but not sampled
5901 GLFramebuffer framebuffer;
5902 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5903 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5904 const GLenum buffers[]{GL_COLOR_ATTACHMENT0};
5905 glDrawBuffers(1, buffers);
5906 glUniform1i(sampleCondition, 0);
5907 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5908 ASSERT_GL_NO_ERROR();
5909
5910 // Render to default framebuffer with tex bound and sampled
5911 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5912 glUniform1i(sampleCondition, 1);
5913 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5914 ASSERT_GL_NO_ERROR();
5915 }
5916
5917 // Tests change of framebuffer dimensions vs gl_FragCoord.
TEST_P(FramebufferTest_ES3,FramebufferDimensionsChangeAndFragCoord)5918 TEST_P(FramebufferTest_ES3, FramebufferDimensionsChangeAndFragCoord)
5919 {
5920 constexpr char kVS[] = R"(#version 300 es
5921 precision highp float;
5922 uniform float height;
5923 void main()
5924 {
5925 // gl_VertexID x y
5926 // 0 -1 -1
5927 // 1 1 -1
5928 // 2 -1 1
5929 // 3 1 1
5930 int bit0 = gl_VertexID & 1;
5931 int bit1 = gl_VertexID >> 1;
5932 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
5933 })";
5934
5935 constexpr char kFS[] = R"(#version 300 es
5936 precision mediump float;
5937 out vec4 colorOut;
5938 void main()
5939 {
5940 float red = gl_FragCoord.x < 10. ? 1.0 : 0.0;
5941 float green = gl_FragCoord.y < 25. ? 1.0 : 0.0;
5942 colorOut = vec4(red, green, 0, 1);
5943 })";
5944
5945 ANGLE_GL_PROGRAM(program, kVS, kFS);
5946
5947 constexpr GLuint kWidth1 = 99;
5948 constexpr GLuint kHeight1 = 142;
5949 constexpr GLuint kWidth2 = 75;
5950 constexpr GLuint kHeight2 = 167;
5951 constexpr GLuint kRenderSplitX = 10;
5952 constexpr GLuint kRenderSplitY = 25;
5953
5954 glViewport(0, 0, std::max(kWidth1, kWidth2), std::max(kHeight1, kHeight2));
5955
5956 GLTexture tex1, tex2;
5957 glBindTexture(GL_TEXTURE_2D, tex1);
5958 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth1, kHeight1);
5959 glBindTexture(GL_TEXTURE_2D, tex2);
5960 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth2, kHeight2);
5961
5962 GLFramebuffer fbo;
5963 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5964
5965 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0);
5966 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5967
5968 glUseProgram(program);
5969 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5970
5971 // Verify results
5972 EXPECT_PIXEL_RECT_EQ(0, 0, kRenderSplitX, kRenderSplitY, GLColor::yellow);
5973 EXPECT_PIXEL_RECT_EQ(0, kRenderSplitY, kRenderSplitX, kHeight1 - kRenderSplitY, GLColor::red);
5974 EXPECT_PIXEL_RECT_EQ(kRenderSplitX, 0, kWidth1 - kRenderSplitX, kRenderSplitY, GLColor::green);
5975 EXPECT_PIXEL_RECT_EQ(kRenderSplitX, kRenderSplitY, kWidth1 - kRenderSplitX,
5976 kHeight1 - kRenderSplitY, GLColor::black);
5977
5978 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0);
5979 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5980
5981 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5982
5983 // Verify results
5984 EXPECT_PIXEL_RECT_EQ(0, 0, kRenderSplitX, kRenderSplitY, GLColor::yellow);
5985 EXPECT_PIXEL_RECT_EQ(0, kRenderSplitY, kRenderSplitX, kHeight2 - kRenderSplitY, GLColor::red);
5986 EXPECT_PIXEL_RECT_EQ(kRenderSplitX, 0, kWidth2 - kRenderSplitX, kRenderSplitY, GLColor::green);
5987 EXPECT_PIXEL_RECT_EQ(kRenderSplitX, kRenderSplitY, kWidth2 - kRenderSplitX,
5988 kHeight2 - kRenderSplitY, GLColor::black);
5989
5990 ASSERT_GL_NO_ERROR();
5991 }
5992
5993 // Tests change of surface dimensions vs gl_FragCoord.
TEST_P(FramebufferTest_ES3,SurfaceDimensionsChangeAndFragCoord)5994 TEST_P(FramebufferTest_ES3, SurfaceDimensionsChangeAndFragCoord)
5995 {
5996 constexpr char kVS[] = R"(#version 300 es
5997 precision highp float;
5998 uniform float height;
5999 void main()
6000 {
6001 // gl_VertexID x y
6002 // 0 -1 -1
6003 // 1 1 -1
6004 // 2 -1 1
6005 // 3 1 1
6006 int bit0 = gl_VertexID & 1;
6007 int bit1 = gl_VertexID >> 1;
6008 gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
6009 })";
6010
6011 constexpr char kFS[] = R"(#version 300 es
6012 precision mediump float;
6013 out vec4 colorOut;
6014 void main()
6015 {
6016 float red = gl_FragCoord.x < 10. ? 1.0 : 0.0;
6017 float green = gl_FragCoord.y < 25. ? 1.0 : 0.0;
6018 colorOut = vec4(red, green, 0, 1);
6019 })";
6020
6021 ANGLE_GL_PROGRAM(program, kVS, kFS);
6022
6023 constexpr GLuint kWidth1 = 99;
6024 constexpr GLuint kHeight1 = 142;
6025 constexpr GLuint kWidth2 = 75;
6026 constexpr GLuint kHeight2 = 167;
6027 constexpr GLuint kRenderSplitX = 10;
6028 constexpr GLuint kRenderSplitY = 25;
6029
6030 glViewport(0, 0, std::max(kWidth1, kWidth2), std::max(kHeight1, kHeight2));
6031
6032 const bool isSwappedDimensions =
6033 getEGLWindow()->isFeatureEnabled(Feature::EmulatedPrerotation90) ||
6034 getEGLWindow()->isFeatureEnabled(Feature::EmulatedPrerotation270);
6035
6036 auto resizeWindow = [this, isSwappedDimensions](GLuint width, GLuint height) {
6037 if (isSwappedDimensions)
6038 {
6039 getOSWindow()->resize(height, width);
6040 }
6041 else
6042 {
6043 getOSWindow()->resize(width, height);
6044 }
6045 swapBuffers();
6046 };
6047
6048 resizeWindow(kWidth1, kHeight1);
6049 glUseProgram(program);
6050 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6051
6052 // Verify results
6053 EXPECT_PIXEL_RECT_EQ(0, 0, kRenderSplitX, kRenderSplitY, GLColor::yellow);
6054 EXPECT_PIXEL_RECT_EQ(0, kRenderSplitY, kRenderSplitX, kHeight1 - kRenderSplitY, GLColor::red);
6055 EXPECT_PIXEL_RECT_EQ(kRenderSplitX, 0, kWidth1 - kRenderSplitX, kRenderSplitY, GLColor::green);
6056 EXPECT_PIXEL_RECT_EQ(kRenderSplitX, kRenderSplitY, kWidth1 - kRenderSplitX,
6057 kHeight1 - kRenderSplitY, GLColor::black);
6058
6059 resizeWindow(kWidth2, kHeight2);
6060 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6061
6062 // Verify results
6063 EXPECT_PIXEL_RECT_EQ(0, 0, kRenderSplitX, kRenderSplitY, GLColor::yellow);
6064 EXPECT_PIXEL_RECT_EQ(0, kRenderSplitY, kRenderSplitX, kHeight2 - kRenderSplitY, GLColor::red);
6065 EXPECT_PIXEL_RECT_EQ(kRenderSplitX, 0, kWidth2 - kRenderSplitX, kRenderSplitY, GLColor::green);
6066 EXPECT_PIXEL_RECT_EQ(kRenderSplitX, kRenderSplitY, kWidth2 - kRenderSplitX,
6067 kHeight2 - kRenderSplitY, GLColor::black);
6068
6069 // Reset window to original dimensions
6070 resizeWindow(kWidth, kHeight);
6071
6072 ASSERT_GL_NO_ERROR();
6073 }
6074
6075 // Tests blits between draw and read surfaces with different pre-rotation values.
TEST_P(FramebufferTest_ES3,BlitWithDifferentPreRotations)6076 TEST_P(FramebufferTest_ES3, BlitWithDifferentPreRotations)
6077 {
6078 // TODO(anglebug.com/7594): Untriaged bot failures with non-Vulkan backends
6079 ANGLE_SKIP_TEST_IF(!IsVulkan());
6080
6081 EGLWindow *window = getEGLWindow();
6082 ASSERT(window);
6083 EGLConfig config = window->getConfig();
6084 EGLContext context = window->getContext();
6085 EGLDisplay dpy = window->getDisplay();
6086 EGLint surfaceType = 0;
6087
6088 // Skip if pbuffer surface is not supported
6089 eglGetConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType);
6090 ANGLE_SKIP_TEST_IF((surfaceType & EGL_PBUFFER_BIT) == 0);
6091
6092 const EGLint surfaceWidth = static_cast<EGLint>(getWindowWidth());
6093 const EGLint surfaceHeight = static_cast<EGLint>(getWindowHeight());
6094 const EGLint pBufferAttributes[] = {
6095 EGL_WIDTH, surfaceWidth, EGL_HEIGHT, surfaceHeight, EGL_NONE,
6096 };
6097
6098 // Create Pbuffer surface
6099 EGLSurface pbufferSurface = eglCreatePbufferSurface(dpy, config, pBufferAttributes);
6100 ASSERT_NE(pbufferSurface, EGL_NO_SURFACE);
6101 ASSERT_EGL_SUCCESS();
6102
6103 EGLSurface windowSurface = window->getSurface();
6104 ASSERT_NE(windowSurface, EGL_NO_SURFACE);
6105
6106 // Clear window surface with red color
6107 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6108 ASSERT_EGL_SUCCESS();
6109 glClearColor(1, 0, 0, 1);
6110 glClear(GL_COLOR_BUFFER_BIT);
6111 EXPECT_PIXEL_RECT_EQ(0, 0, surfaceWidth, surfaceHeight, GLColor::red);
6112
6113 // Blit from window surface to pbuffer surface and expect red color
6114 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, pbufferSurface, windowSurface, context));
6115 ASSERT_EGL_SUCCESS();
6116
6117 glBlitFramebuffer(0, 0, surfaceWidth, surfaceHeight, 0, 0, surfaceWidth, surfaceHeight,
6118 GL_COLOR_BUFFER_BIT, GL_NEAREST);
6119 ASSERT_GL_NO_ERROR();
6120 EXPECT_PIXEL_RECT_EQ(0, 0, surfaceWidth, surfaceHeight, GLColor::red);
6121
6122 // Clear pbuffer surface with blue color
6123 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, pbufferSurface, pbufferSurface, context));
6124 ASSERT_EGL_SUCCESS();
6125 glClearColor(0, 0, 1, 1);
6126 glClear(GL_COLOR_BUFFER_BIT);
6127 EXPECT_PIXEL_RECT_EQ(0, 0, surfaceWidth, surfaceHeight, GLColor::blue);
6128
6129 // Blit from pbuffer surface to window surface and expect blue color
6130 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, pbufferSurface, context));
6131 ASSERT_EGL_SUCCESS();
6132
6133 glBlitFramebuffer(0, 0, surfaceWidth, surfaceHeight, 0, 0, surfaceWidth, surfaceHeight,
6134 GL_COLOR_BUFFER_BIT, GL_NEAREST);
6135 ASSERT_GL_NO_ERROR();
6136 EXPECT_PIXEL_RECT_EQ(0, 0, surfaceWidth, surfaceHeight, GLColor::blue);
6137
6138 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6139 ASSERT_EGL_SUCCESS();
6140
6141 EXPECT_EGL_TRUE(eglDestroySurface(dpy, pbufferSurface));
6142 ASSERT_EGL_SUCCESS();
6143 }
6144
6145 // Tests draw to surfaces with different pre-rotation values.
TEST_P(FramebufferTest_ES3,DrawWithDifferentPreRotations)6146 TEST_P(FramebufferTest_ES3, DrawWithDifferentPreRotations)
6147 {
6148 EGLWindow *window = getEGLWindow();
6149 ASSERT(window);
6150 EGLConfig config = window->getConfig();
6151 EGLContext context = window->getContext();
6152 EGLDisplay dpy = window->getDisplay();
6153 EGLint surfaceType = 0;
6154
6155 // Skip if pbuffer surface is not supported
6156 eglGetConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType);
6157 ANGLE_SKIP_TEST_IF((surfaceType & EGL_PBUFFER_BIT) == 0);
6158
6159 const EGLint surfaceWidth = static_cast<EGLint>(getWindowWidth());
6160 const EGLint surfaceHeight = static_cast<EGLint>(getWindowHeight());
6161 const EGLint pBufferAttributes[] = {
6162 EGL_WIDTH, surfaceWidth, EGL_HEIGHT, surfaceHeight, EGL_NONE,
6163 };
6164
6165 // Create Pbuffer surface
6166 EGLSurface pbufferSurface = eglCreatePbufferSurface(dpy, config, pBufferAttributes);
6167 ASSERT_NE(pbufferSurface, EGL_NO_SURFACE);
6168 ASSERT_EGL_SUCCESS();
6169
6170 EGLSurface windowSurface = window->getSurface();
6171 ASSERT_NE(windowSurface, EGL_NO_SURFACE);
6172
6173 constexpr char kCheckered2FS[] = R"(precision highp float;
6174 varying vec4 v_position;
6175
6176 void main()
6177 {
6178 bool isLeft = v_position.x < 0.0;
6179 bool isTop = v_position.y < 0.0;
6180 if (isLeft)
6181 {
6182 if (isTop)
6183 {
6184 gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
6185 }
6186 else
6187 {
6188 gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);
6189 }
6190 }
6191 else
6192 {
6193 if (isTop)
6194 {
6195 gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
6196 }
6197 else
6198 {
6199 gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
6200 }
6201 }
6202 })";
6203
6204 ANGLE_GL_PROGRAM(checkerProgram, essl1_shaders::vs::Passthrough(),
6205 essl1_shaders::fs::Checkered());
6206 ANGLE_GL_PROGRAM(checkerProgram2, essl1_shaders::vs::Passthrough(), kCheckered2FS);
6207
6208 // The test does the following:
6209 //
6210 // 1. draw checkered to window (rotated)
6211 // 2. draw checkered to pbuffer (not rotated)
6212 // 3. verify rendering to window, draw checkered2, verify again
6213 // 4. verify rendering to pbuffer, draw checkered2, verify again
6214 //
6215 // Step 2 ensures that the correct state is used after a change to the bound surface (from
6216 // rotated to not). Step 3 ensures the same from not rotated to rotated. Step 4 is a redundant
6217 // check.
6218
6219 // Step 1
6220 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6221 ASSERT_EGL_SUCCESS();
6222
6223 drawQuad(checkerProgram, essl1_shaders::PositionAttrib(), 0);
6224
6225 // Step 2
6226 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, pbufferSurface, windowSurface, context));
6227 ASSERT_EGL_SUCCESS();
6228
6229 drawQuad(checkerProgram, essl1_shaders::PositionAttrib(), 0);
6230
6231 // Step 3
6232 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6233 ASSERT_EGL_SUCCESS();
6234
6235 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6236 EXPECT_PIXEL_COLOR_EQ(0, surfaceHeight - 1, GLColor::green);
6237 EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, 0, GLColor::blue);
6238 EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, surfaceHeight - 1, GLColor::yellow);
6239
6240 drawQuad(checkerProgram2, essl1_shaders::PositionAttrib(), 0);
6241
6242 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
6243 EXPECT_PIXEL_COLOR_EQ(0, surfaceHeight - 1, GLColor::cyan);
6244 EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, 0, GLColor::magenta);
6245 EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, surfaceHeight - 1, GLColor::white);
6246
6247 // Step 4
6248 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, pbufferSurface, pbufferSurface, context));
6249 ASSERT_EGL_SUCCESS();
6250
6251 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6252 EXPECT_PIXEL_COLOR_EQ(0, surfaceHeight - 1, GLColor::green);
6253 EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, 0, GLColor::blue);
6254 EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, surfaceHeight - 1, GLColor::yellow);
6255
6256 drawQuad(checkerProgram2, essl1_shaders::PositionAttrib(), 0);
6257
6258 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
6259 EXPECT_PIXEL_COLOR_EQ(0, surfaceHeight - 1, GLColor::cyan);
6260 EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, 0, GLColor::magenta);
6261 EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, surfaceHeight - 1, GLColor::white);
6262
6263 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6264 ASSERT_EGL_SUCCESS();
6265
6266 EXPECT_EGL_TRUE(eglDestroySurface(dpy, pbufferSurface));
6267 ASSERT_EGL_SUCCESS();
6268 }
6269
6270 class FramebufferExtensionsTest : public FramebufferTest
6271 {
6272 protected:
FramebufferExtensionsTest()6273 FramebufferExtensionsTest() { setExtensionsEnabled(false); }
6274
checkParameter(GLenum expectedComponentType)6275 void checkParameter(GLenum expectedComponentType)
6276 {
6277 GLint componentType = 0;
6278 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6279 GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT,
6280 &componentType);
6281 EXPECT_EQ(componentType, static_cast<GLint>(expectedComponentType));
6282 if (expectedComponentType)
6283 {
6284 EXPECT_GL_NO_ERROR();
6285 }
6286 else
6287 {
6288 EXPECT_GL_ERROR(GL_INVALID_ENUM);
6289 }
6290 }
6291
checkTexture(GLenum format,GLenum type,GLenum expectedComponentType)6292 void checkTexture(GLenum format, GLenum type, GLenum expectedComponentType)
6293 {
6294 GLTexture texture;
6295 glBindTexture(GL_TEXTURE_2D, texture);
6296 glTexImage2D(GL_TEXTURE_2D, 0, format, 8, 8, 0, format, type, nullptr);
6297 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6298 ASSERT_GL_NO_ERROR();
6299 checkParameter(expectedComponentType);
6300 }
6301
checkRenderbuffer(GLenum format,GLenum expectedComponentType)6302 void checkRenderbuffer(GLenum format, GLenum expectedComponentType)
6303 {
6304 GLRenderbuffer renderbuffer;
6305 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
6306 glRenderbufferStorage(GL_RENDERBUFFER, format, 8, 8);
6307 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
6308 renderbuffer);
6309 ASSERT_GL_NO_ERROR();
6310 checkParameter(expectedComponentType);
6311 }
6312
test(const char * extensionName,GLenum format,bool supportsRenderbuffer)6313 void test(const char *extensionName, GLenum format, bool supportsRenderbuffer)
6314 {
6315 GLFramebuffer fbo;
6316 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6317 checkTexture(GL_RGBA, GL_UNSIGNED_BYTE, 0);
6318 checkRenderbuffer(GL_RGB565, 0);
6319
6320 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled(extensionName));
6321
6322 checkTexture(GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED_EXT);
6323 checkRenderbuffer(GL_RGB565, GL_UNSIGNED_NORMALIZED_EXT);
6324
6325 if (supportsRenderbuffer)
6326 checkRenderbuffer(format, GL_FLOAT);
6327 }
6328 };
6329
6330 // Tests that GL_EXT_color_buffer_half_float enables component type state queries on
6331 // framebuffer attachments.
TEST_P(FramebufferExtensionsTest,ColorBufferHalfFloat)6332 TEST_P(FramebufferExtensionsTest, ColorBufferHalfFloat)
6333 {
6334 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_half_float"));
6335 test("GL_EXT_color_buffer_half_float", GL_RGBA16F_EXT, true);
6336 }
6337
6338 // Tests that GL_CHROMIUM_color_buffer_float_rgb enables component type state queries on
6339 // framebuffer attachments.
TEST_P(FramebufferExtensionsTest,ColorBufferFloatRgb)6340 TEST_P(FramebufferExtensionsTest, ColorBufferFloatRgb)
6341 {
6342 test("GL_CHROMIUM_color_buffer_float_rgb", GL_RGB32F_EXT, false);
6343 }
6344
6345 // Tests that GL_CHROMIUM_color_buffer_float_rgba enables component type state queries on
6346 // framebuffer attachments.
TEST_P(FramebufferExtensionsTest,ColorBufferFloatRgba)6347 TEST_P(FramebufferExtensionsTest, ColorBufferFloatRgba)
6348 {
6349 test("GL_CHROMIUM_color_buffer_float_rgba", GL_RGBA32F_EXT, true);
6350 }
6351
6352 class DefaultFramebufferTest : public ANGLETest<>
6353 {
6354 protected:
DefaultFramebufferTest()6355 DefaultFramebufferTest()
6356 {
6357 setWindowWidth(kWidth);
6358 setWindowHeight(kHeight);
6359 }
6360
6361 static constexpr GLsizei kWidth = 16;
6362 static constexpr GLsizei kHeight = 16;
6363 };
6364
6365 // glReadPixel from default FBO with format and type retrieved from
6366 // GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE
6367 // should work
TEST_P(DefaultFramebufferTest,ReadFromDefaultFBOOnDefaultEGLWindowSurface)6368 TEST_P(DefaultFramebufferTest, ReadFromDefaultFBOOnDefaultEGLWindowSurface)
6369 {
6370 // Bind the default framebuffer
6371 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6372
6373 // Create shader programs
6374 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6375
6376 constexpr char kVS1[] = R"(#version 300 es
6377 in highp vec2 a_position;
6378 in highp vec2 a_texcoord;
6379 out highp vec2 texcoord;
6380 void main()
6381 {
6382 gl_Position = vec4(a_position, 0.0, 1.0);
6383 texcoord = a_texcoord;
6384 })";
6385
6386 constexpr char kFS1[] = R"(#version 300 es
6387 precision highp float;
6388 in highp vec2 texcoord;
6389 out highp vec4 fragColor;
6390 uniform highp sampler2D texSampler;
6391
6392 void main()
6393 {
6394 fragColor = texture(texSampler, texcoord);
6395 })";
6396
6397 ANGLE_GL_PROGRAM(program, kVS1, kFS1);
6398 glUseProgram(program);
6399 ASSERT_GL_NO_ERROR();
6400
6401 // Create Vertex data
6402 const std::vector<float> positions = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f};
6403 GLBuffer vertexBuffer;
6404 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6405 glBufferData(GL_ARRAY_BUFFER, sizeof(positions[0]) * positions.size(), positions.data(),
6406 GL_STATIC_DRAW);
6407 GLint vertexPosLocation = glGetAttribLocation(program, "a_position");
6408 ASSERT_NE(vertexPosLocation, -1);
6409 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6410 glEnableVertexAttribArray(vertexPosLocation);
6411 glVertexAttribPointer(vertexPosLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
6412
6413 const std::vector<float> texcoords = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
6414 GLBuffer texcoordBuffer;
6415 glBindBuffer(GL_ARRAY_BUFFER, texcoordBuffer);
6416 glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords[0]) * texcoords.size(), texcoords.data(),
6417 GL_STATIC_DRAW);
6418 GLint texCoordLocation = glGetAttribLocation(program, "a_texcoord");
6419 ASSERT_NE(texCoordLocation, -1);
6420 glBindBuffer(GL_ARRAY_BUFFER, texcoordBuffer);
6421 glEnableVertexAttribArray(texCoordLocation);
6422 glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
6423
6424 const std::vector<uint16_t> quadIndices = {0, 1, 2, 2, 1, 3};
6425 GLBuffer indexBuffer;
6426 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6427 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices[0]) * quadIndices.size(),
6428 quadIndices.data(), GL_STATIC_DRAW);
6429 ASSERT_GL_NO_ERROR();
6430
6431 // Create Texture
6432 GLTexture texture;
6433 glBindTexture(GL_TEXTURE_2D, texture);
6434 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6435 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6436 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
6437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
6438 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6439
6440 std::vector<uint8_t> texData;
6441
6442 constexpr size_t width = 4;
6443 constexpr size_t height = 4;
6444 constexpr size_t bytePerColorChannel = 4;
6445 constexpr uint8_t texColorPerChannel = 125;
6446
6447 texData.resize(width * height * bytePerColorChannel);
6448
6449 for (size_t i = 0; i < width * height; ++i)
6450 {
6451 texData.push_back(texColorPerChannel);
6452 texData.push_back(texColorPerChannel);
6453 texData.push_back(texColorPerChannel);
6454 texData.push_back(texColorPerChannel);
6455 }
6456
6457 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6458 texData.data());
6459 ASSERT_GL_NO_ERROR();
6460
6461 // Initialize uniform values
6462 GLint uniformTextureSamplerLocation = glGetUniformLocation(program, "texSampler");
6463 glUniform1i(uniformTextureSamplerLocation, 0);
6464 ASSERT_GL_NO_ERROR();
6465
6466 // Disable Dither
6467 glDisable(GL_DITHER);
6468
6469 // Draw quad
6470 glDrawElements(GL_TRIANGLES, quadIndices.size(), GL_UNSIGNED_BYTE, 0);
6471
6472 // Get glReadPixel format and type
6473 GLint readFormat;
6474 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
6475
6476 GLint readType;
6477 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
6478
6479 // Read Pixel with glReadPixel
6480 std::vector<uint8_t> renderResult;
6481 renderResult.resize(width * height * 4);
6482 glReadPixels(0, 0, width, height, readFormat, readType, renderResult.data());
6483
6484 // glReadPixel with format and type retrieved from
6485 // GL_IMPLEMENTATION_COLOR_READ_FORMAT &
6486 // GL_IMPLEMENTATION_COLOR_READ_TYPE
6487 // should not trigger errors
6488 ASSERT_GL_NO_ERROR();
6489 }
6490
6491 // Test resolving the same framebuffer into two different ones
TEST_P(FramebufferTest_ES31,MultisampleResolveMultipleTimes)6492 TEST_P(FramebufferTest_ES31, MultisampleResolveMultipleTimes)
6493 {
6494 constexpr int kWidth = 16;
6495 constexpr int kHeight = 20;
6496 glViewport(0, 0, kWidth, kHeight);
6497
6498 GLFramebuffer msaaFBO;
6499 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6500
6501 GLTexture texture;
6502 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
6503 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
6504 ASSERT_GL_NO_ERROR();
6505 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
6506 0);
6507 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6508
6509 // Create two resolve FBOs and textures. Use different texture levels and layers.
6510 GLTexture resolveTexture1;
6511 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6512 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 2, kHeight * 2);
6513
6514 GLFramebuffer resolveFBO1;
6515 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6516 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 1);
6517 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6518
6519 GLTexture resolveTexture2;
6520 glBindTexture(GL_TEXTURE_2D_ARRAY, resolveTexture2);
6521 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kWidth * 4, kHeight * 4, 5);
6522
6523 GLFramebuffer resolveFBO2;
6524 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6525 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolveTexture2, 2, 3);
6526 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6527
6528 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6529 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
6530 essl31_shaders::fs::RedGreenGradient());
6531 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6532 ASSERT_GL_NO_ERROR();
6533
6534 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6535 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6536 GL_NEAREST);
6537 ASSERT_GL_NO_ERROR();
6538
6539 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6540 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6541 GL_NEAREST);
6542 ASSERT_GL_NO_ERROR();
6543
6544 auto verify = [](GLuint fbo) {
6545 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
6546 constexpr uint8_t kWidthHalfPixelGradient = 256 / kWidth / 2;
6547 constexpr uint8_t kHeightHalfPixelGradient = 256 / kHeight / 2;
6548 EXPECT_PIXEL_NEAR(0, 0, kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0, 255, 1.0);
6549 EXPECT_PIXEL_NEAR(kWidth - 1, 0, 255 - kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0,
6550 255, 1.0);
6551 EXPECT_PIXEL_NEAR(0, kHeight - 1, kWidthHalfPixelGradient, 255 - kHeightHalfPixelGradient,
6552 0, 255, 1.0);
6553 EXPECT_PIXEL_NEAR(kWidth - 1, kHeight - 1, 255 - kWidthHalfPixelGradient,
6554 255 - kHeightHalfPixelGradient, 0, 255, 1.0);
6555 };
6556
6557 verify(resolveFBO1);
6558 verify(resolveFBO2);
6559 ASSERT_GL_NO_ERROR();
6560 }
6561
6562 // Test resolving the same depth/stencil attachment into two different framebuffers
TEST_P(FramebufferTest_ES31,MultisampleDepthStencilResolveMultipleTimes)6563 TEST_P(FramebufferTest_ES31, MultisampleDepthStencilResolveMultipleTimes)
6564 {
6565 enum class DepthStencilResolve
6566 {
6567 Simultaneous,
6568 SeparateAspectsButSameFramebuffer,
6569 SeparateAspectsDifferentFramebuffers,
6570 };
6571
6572 constexpr int kWidth = 24;
6573 constexpr int kHeight = 12;
6574 glViewport(0, 0, kWidth, kHeight);
6575
6576 GLFramebuffer msaaFBO;
6577 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6578
6579 GLRenderbuffer depthStencil;
6580 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
6581 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
6582 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6583 depthStencil);
6584 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6585 ASSERT_GL_NO_ERROR();
6586
6587 // Create two resolve FBOs and textures. Use different texture levels and layers.
6588 GLTexture resolveTexture1;
6589 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6590 glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
6591
6592 GLFramebuffer resolveFBO1;
6593 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6594 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
6595 resolveTexture1, 2);
6596 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6597
6598 GLTexture resolveTexture2;
6599 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
6600 glTexStorage2D(GL_TEXTURE_2D, 2, GL_DEPTH24_STENCIL8, kWidth * 2, kHeight * 2);
6601
6602 GLFramebuffer resolveFBO2;
6603 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6604 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
6605 resolveTexture2, 1);
6606 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6607
6608 ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
6609
6610 auto runTest = [&](float depth, int stencil, DepthStencilResolve resolve) {
6611 glEnable(GL_DEPTH_TEST);
6612 glDepthFunc(GL_ALWAYS);
6613 glDepthMask(GL_TRUE);
6614 glEnable(GL_STENCIL_TEST);
6615 glStencilFunc(GL_ALWAYS, stencil, 0xFF);
6616 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
6617 glStencilMask(0xFF);
6618
6619 // Initialize the depth/stencil image
6620 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6621 drawQuad(red, essl1_shaders::PositionAttrib(), depth);
6622 ASSERT_GL_NO_ERROR();
6623
6624 // Resolve depth and stencil, then verify the results
6625 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6626 switch (resolve)
6627 {
6628 case DepthStencilResolve::Simultaneous:
6629 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6630 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6631 break;
6632 case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
6633 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6634 GL_NEAREST);
6635 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6636 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6637 break;
6638 case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
6639 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6640 GL_NEAREST);
6641 break;
6642 }
6643
6644 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6645 switch (resolve)
6646 {
6647 case DepthStencilResolve::Simultaneous:
6648 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6649 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6650 break;
6651 case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
6652 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6653 GL_NEAREST);
6654 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6655 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6656 break;
6657 case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
6658 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6659 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6660 break;
6661 }
6662 ASSERT_GL_NO_ERROR();
6663
6664 verifyDepth(resolveFBO1, kWidth, kHeight, depth);
6665 if (resolve != DepthStencilResolve::SeparateAspectsDifferentFramebuffers)
6666 {
6667 verifyStencil(resolveFBO1, kWidth, kHeight, stencil);
6668 verifyDepth(resolveFBO2, kWidth, kHeight, depth);
6669 }
6670 verifyStencil(resolveFBO2, kWidth, kHeight, stencil);
6671 };
6672
6673 runTest(0.8f, 0x55, DepthStencilResolve::Simultaneous);
6674 runTest(0.2f, 0x3A, DepthStencilResolve::SeparateAspectsButSameFramebuffer);
6675 runTest(0.5f, 0x98, DepthStencilResolve::SeparateAspectsDifferentFramebuffers);
6676 ASSERT_GL_NO_ERROR();
6677 }
6678
6679 // Test resolving the same framebuffer into two different ones with a draw in between
TEST_P(FramebufferTest_ES31,MultisampleResolveMultipleTimesWithDrawInBetween)6680 TEST_P(FramebufferTest_ES31, MultisampleResolveMultipleTimesWithDrawInBetween)
6681 {
6682 constexpr int kWidth = 16;
6683 constexpr int kHeight = 20;
6684 glViewport(0, 0, kWidth, kHeight);
6685
6686 GLFramebuffer msaaFBO;
6687 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6688
6689 GLTexture texture;
6690 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
6691 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
6692 ASSERT_GL_NO_ERROR();
6693 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
6694 0);
6695 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6696
6697 // Create two resolve FBOs and textures. Use different texture levels and layers.
6698 GLTexture resolveTexture1;
6699 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6700 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 2, kHeight * 2);
6701
6702 GLFramebuffer resolveFBO1;
6703 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6704 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 1);
6705 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6706
6707 GLTexture resolveTexture2;
6708 glBindTexture(GL_TEXTURE_2D_ARRAY, resolveTexture2);
6709 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kWidth * 4, kHeight * 4, 5);
6710
6711 GLFramebuffer resolveFBO2;
6712 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6713 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolveTexture2, 2, 3);
6714 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6715
6716 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6717 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
6718 essl31_shaders::fs::RedGreenGradient());
6719 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6720 ASSERT_GL_NO_ERROR();
6721
6722 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6723 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6724 GL_NEAREST);
6725 ASSERT_GL_NO_ERROR();
6726
6727 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
6728 ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Passthrough(), essl31_shaders::fs::Red());
6729 drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6730
6731 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6732 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6733 GL_NEAREST);
6734 ASSERT_GL_NO_ERROR();
6735
6736 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
6737 constexpr uint8_t kWidthHalfPixelGradient = 256 / kWidth / 2;
6738 constexpr uint8_t kHeightHalfPixelGradient = 256 / kHeight / 2;
6739 EXPECT_PIXEL_NEAR(0, 0, kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0, 255, 1.0);
6740 EXPECT_PIXEL_NEAR(kWidth - 1, 0, 255 - kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0,
6741 255, 1.0);
6742 EXPECT_PIXEL_NEAR(0, kHeight - 1, kWidthHalfPixelGradient, 255 - kHeightHalfPixelGradient, 0,
6743 255, 1.0);
6744 EXPECT_PIXEL_NEAR(kWidth - 1, kHeight - 1, 255 - kWidthHalfPixelGradient,
6745 255 - kHeightHalfPixelGradient, 0, 255, 1.0);
6746
6747 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
6748 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
6749 ASSERT_GL_NO_ERROR();
6750 }
6751
6752 // Test resolving the same depth/stencil framebuffer into two different ones with a draw in between
TEST_P(FramebufferTest_ES31,MultisampleDepthStencilResolveMultipleTimesWithDrawInBetween)6753 TEST_P(FramebufferTest_ES31, MultisampleDepthStencilResolveMultipleTimesWithDrawInBetween)
6754 {
6755 enum class DepthStencilResolve
6756 {
6757 Simultaneous,
6758 SeparateAspectsButSameFramebuffer,
6759 SeparateAspectsDifferentFramebuffers,
6760 };
6761
6762 constexpr int kWidth = 16;
6763 constexpr int kHeight = 20;
6764 glViewport(0, 0, kWidth, kHeight);
6765
6766 GLFramebuffer msaaFBO;
6767 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6768
6769 GLRenderbuffer depthStencil;
6770 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
6771 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
6772 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6773 depthStencil);
6774 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6775 ASSERT_GL_NO_ERROR();
6776
6777 // Create two resolve FBOs and textures. Use different texture levels and layers.
6778 GLTexture resolveTexture1;
6779 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6780 glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
6781
6782 GLFramebuffer resolveFBO1;
6783 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6784 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
6785 resolveTexture1, 2);
6786 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6787
6788 GLTexture resolveTexture2;
6789 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
6790 glTexStorage2D(GL_TEXTURE_2D, 2, GL_DEPTH24_STENCIL8, kWidth * 2, kHeight * 2);
6791
6792 GLFramebuffer resolveFBO2;
6793 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6794 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
6795 resolveTexture2, 1);
6796 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6797
6798 ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
6799
6800 auto runTest = [&](float depth1, int stencil1, float depth2, int stencil2,
6801 DepthStencilResolve resolve) {
6802 glEnable(GL_DEPTH_TEST);
6803 glDepthFunc(GL_ALWAYS);
6804 glDepthMask(GL_TRUE);
6805 glEnable(GL_STENCIL_TEST);
6806 glStencilFunc(GL_ALWAYS, stencil1, 0xFF);
6807 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
6808 glStencilMask(0xFF);
6809
6810 // Initialize the depth/stencil image
6811 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6812 drawQuad(red, essl1_shaders::PositionAttrib(), depth1);
6813 ASSERT_GL_NO_ERROR();
6814
6815 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6816 switch (resolve)
6817 {
6818 case DepthStencilResolve::Simultaneous:
6819 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6820 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6821 break;
6822 case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
6823 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6824 GL_NEAREST);
6825 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6826 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6827 break;
6828 case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
6829 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6830 GL_NEAREST);
6831 break;
6832 }
6833
6834 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
6835 glStencilFunc(GL_ALWAYS, stencil2, 0xFF);
6836 drawQuad(red, essl1_shaders::PositionAttrib(), depth2);
6837
6838 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6839 switch (resolve)
6840 {
6841 case DepthStencilResolve::Simultaneous:
6842 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6843 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6844 break;
6845 case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
6846 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6847 GL_NEAREST);
6848 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6849 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6850 break;
6851 case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
6852 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6853 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6854 break;
6855 }
6856 ASSERT_GL_NO_ERROR();
6857
6858 verifyDepth(resolveFBO1, kWidth, kHeight, depth1);
6859 if (resolve != DepthStencilResolve::SeparateAspectsDifferentFramebuffers)
6860 {
6861 verifyStencil(resolveFBO1, kWidth, kHeight, stencil1);
6862 verifyDepth(resolveFBO2, kWidth, kHeight, depth2);
6863 }
6864 verifyStencil(resolveFBO2, kWidth, kHeight, stencil2);
6865 };
6866
6867 runTest(0.4f, 0x3F, 0.1f, 0xA2, DepthStencilResolve::Simultaneous);
6868 runTest(0.9f, 0x2B, 0.3f, 0xDD, DepthStencilResolve::SeparateAspectsButSameFramebuffer);
6869 runTest(0.5f, 0x6C, 0.6f, 0x7E, DepthStencilResolve::SeparateAspectsDifferentFramebuffers);
6870 ASSERT_GL_NO_ERROR();
6871 }
6872
6873 // Test resolving different attachments of an FBO to separate FBOs
TEST_P(FramebufferTest_ES31,MultisampleResolveBothAttachments)6874 TEST_P(FramebufferTest_ES31, MultisampleResolveBothAttachments)
6875 {
6876 enum class Invalidate
6877 {
6878 None,
6879 AfterEachResolve,
6880 AllAtEnd,
6881 };
6882
6883 constexpr char kFS[] = R"(#version 300 es
6884 precision highp float;
6885
6886 uniform vec4 value0;
6887 uniform vec4 value2;
6888
6889 layout(location = 0) out vec4 color0;
6890 layout(location = 2) out vec4 color2;
6891
6892 void main()
6893 {
6894 color0 = value0;
6895 color2 = value2;
6896 })";
6897
6898 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6899 glUseProgram(program);
6900 const GLint color0Loc = glGetUniformLocation(program, "value0");
6901 const GLint color1Loc = glGetUniformLocation(program, "value2");
6902
6903 constexpr int kWidth = 16;
6904 constexpr int kHeight = 20;
6905 glViewport(0, 0, kWidth, kHeight);
6906
6907 GLTexture msaa0, msaa1;
6908 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa0);
6909 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
6910 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa1);
6911 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
6912
6913 GLFramebuffer msaaFBO;
6914 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6915 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa0,
6916 0);
6917 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D_MULTISAMPLE, msaa1,
6918 0);
6919 ASSERT_GL_NO_ERROR();
6920 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6921
6922 GLenum bufs[3] = {GL_COLOR_ATTACHMENT0, GL_NONE, GL_COLOR_ATTACHMENT2};
6923 glDrawBuffers(3, bufs);
6924
6925 // Create two resolve FBOs and textures. Use different texture levels and layers.
6926 GLTexture resolveTexture1;
6927 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6928 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 2, kHeight * 2);
6929
6930 GLFramebuffer resolveFBO1;
6931 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6932 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 1);
6933 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6934
6935 GLTexture resolveTexture2;
6936 glBindTexture(GL_TEXTURE_2D_ARRAY, resolveTexture2);
6937 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kWidth * 4, kHeight * 4, 5);
6938
6939 GLFramebuffer resolveFBO2;
6940 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6941 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolveTexture2, 2, 3);
6942 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6943
6944 auto test = [&](GLColor color0, GLColor color1, Invalidate invalidate) {
6945 const GLenum discards[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT2};
6946
6947 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6948 glUniform4fv(color0Loc, 1, color0.toNormalizedVector().data());
6949 glUniform4fv(color1Loc, 1, color1.toNormalizedVector().data());
6950 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6951 ASSERT_GL_NO_ERROR();
6952
6953 // Resolve the first attachment
6954 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6955 glReadBuffer(GL_COLOR_ATTACHMENT0);
6956 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6957 GL_NEAREST);
6958 ASSERT_GL_NO_ERROR();
6959
6960 if (invalidate == Invalidate::AfterEachResolve)
6961 {
6962 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, discards);
6963 }
6964
6965 // Resolve the second attachment
6966 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6967 glReadBuffer(GL_COLOR_ATTACHMENT2);
6968 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6969 GL_NEAREST);
6970 ASSERT_GL_NO_ERROR();
6971
6972 if (invalidate == Invalidate::AfterEachResolve)
6973 {
6974 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, discards + 1);
6975 }
6976 else if (invalidate == Invalidate::AllAtEnd)
6977 {
6978 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 2, discards);
6979 }
6980
6981 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
6982 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color0);
6983 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
6984 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color1);
6985 ASSERT_GL_NO_ERROR();
6986 };
6987
6988 test(GLColor::red, GLColor::green, Invalidate::None);
6989 test(GLColor::blue, GLColor::yellow, Invalidate::AfterEachResolve);
6990 test(GLColor::cyan, GLColor::magenta, Invalidate::AllAtEnd);
6991 }
6992
6993 // Test resolving a framebuffer once, then drawing to it again without a resolve. Makes sure there
6994 // is no caching bug that would make the second render pass resolve into the old resolve target
6995 // again.
TEST_P(FramebufferTest_ES31,ResolveThenDrawWithoutResolve)6996 TEST_P(FramebufferTest_ES31, ResolveThenDrawWithoutResolve)
6997 {
6998 enum class Invalidate
6999 {
7000 None,
7001 AfterFirstResolve,
7002 AfterEachResolve,
7003 AtEnd,
7004 };
7005
7006 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7007 glUseProgram(program);
7008 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7009 ASSERT_NE(colorLoc, -1);
7010
7011 constexpr int kWidth = 16;
7012 constexpr int kHeight = 20;
7013 glViewport(0, 0, kWidth, kHeight);
7014
7015 GLTexture msaa;
7016 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa);
7017 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7018
7019 GLFramebuffer msaaFBO;
7020 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7021 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa,
7022 0);
7023 ASSERT_GL_NO_ERROR();
7024 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7025
7026 // Create the resolve FBO and texture.
7027 GLTexture resolveTexture;
7028 glBindTexture(GL_TEXTURE_2D, resolveTexture);
7029 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kWidth * 2 + 1, kHeight * 2 + 1);
7030
7031 GLFramebuffer resolveFBO;
7032 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
7033 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
7034 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7035
7036 auto test = [&](GLColor color1, GLColor color2, Invalidate invalidate) {
7037 const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
7038
7039 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7040 glUniform4fv(colorLoc, 1, color1.toNormalizedVector().data());
7041 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7042 ASSERT_GL_NO_ERROR();
7043
7044 // Resolve
7045 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7046 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7047 GL_NEAREST);
7048 ASSERT_GL_NO_ERROR();
7049
7050 if (invalidate == Invalidate::AfterEachResolve ||
7051 invalidate == Invalidate::AfterFirstResolve)
7052 {
7053 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, discards);
7054 }
7055
7056 // Draw again, but don't resolve.
7057 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
7058 glUniform4fv(colorLoc, 1, color2.toNormalizedVector().data());
7059 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7060
7061 const bool invalidateAtEnd =
7062 invalidate == Invalidate::AfterEachResolve || invalidate == Invalidate::AtEnd;
7063 if (invalidateAtEnd)
7064 {
7065 glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, discards);
7066 }
7067
7068 // Make sure the render pass is flushed so if there's a caching bug and the old render pass
7069 // with resolve is used for the second render pass, the contents of the resolve attachment
7070 // is wrong. Can't rely on glReadPixels doing that because of potential use of
7071 // VK_EXT_host_image_copy.
7072 glFinish();
7073
7074 // Verify the contents of the resolve attachment
7075 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7076 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color1);
7077
7078 if (!invalidateAtEnd)
7079 {
7080 // For completeness, make sure the second draw succeeded.
7081 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
7082 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7083 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7084 GL_NEAREST);
7085 ASSERT_GL_NO_ERROR();
7086
7087 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7088 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color2);
7089 }
7090 ASSERT_GL_NO_ERROR();
7091 };
7092
7093 test(GLColor::red, GLColor::green, Invalidate::None);
7094 test(GLColor::blue, GLColor::yellow, Invalidate::AfterFirstResolve);
7095 test(GLColor::cyan, GLColor::magenta, Invalidate::AfterEachResolve);
7096 test(GLColor::white, GLColor::red, Invalidate::AtEnd);
7097 }
7098
7099 // Test resolving a depth/stencil framebuffer once, then drawing to it again without a resolve.
7100 // Makes sure there is no caching bug that would make the second render pass resolve into the old
7101 // resolve target again.
TEST_P(FramebufferTest_ES31,DepthStencilResolveThenDrawWithoutResolve)7102 TEST_P(FramebufferTest_ES31, DepthStencilResolveThenDrawWithoutResolve)
7103 {
7104 enum class Invalidate
7105 {
7106 None,
7107 AfterFirstResolve,
7108 AfterEachResolve,
7109 AtEnd,
7110 };
7111 enum class DepthStencilResolve
7112 {
7113 Simultaneous,
7114 SeparateAspects,
7115 };
7116
7117 ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7118
7119 constexpr int kWidth = 16;
7120 constexpr int kHeight = 20;
7121 glViewport(0, 0, kWidth, kHeight);
7122
7123 GLFramebuffer msaaFBO;
7124 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7125
7126 GLRenderbuffer depthStencil;
7127 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
7128 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
7129 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7130 depthStencil);
7131 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7132 ASSERT_GL_NO_ERROR();
7133
7134 // Create the resolve FBO and texture. Use different texture levels and layers.
7135 GLTexture resolveTexture;
7136 glBindTexture(GL_TEXTURE_2D, resolveTexture);
7137 glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
7138
7139 GLFramebuffer resolveFBO;
7140 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
7141 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
7142 resolveTexture, 2);
7143 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7144
7145 auto test = [&](float depth1, int stencil1, float depth2, int stencil2,
7146 DepthStencilResolve resolve, Invalidate invalidate) {
7147 const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT,
7148 GL_DEPTH_STENCIL_ATTACHMENT};
7149
7150 glEnable(GL_DEPTH_TEST);
7151 glDepthFunc(GL_ALWAYS);
7152 glDepthMask(GL_TRUE);
7153 glEnable(GL_STENCIL_TEST);
7154 glStencilFunc(GL_ALWAYS, stencil1, 0xFF);
7155 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
7156 glStencilMask(0xFF);
7157
7158 // First draw
7159 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7160 drawQuad(red, essl1_shaders::PositionAttrib(), depth1);
7161 ASSERT_GL_NO_ERROR();
7162
7163 // Resolve
7164 const bool invalidateAfterFirstResolve = invalidate == Invalidate::AfterEachResolve ||
7165 invalidate == Invalidate::AfterFirstResolve;
7166 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7167 switch (resolve)
7168 {
7169 case DepthStencilResolve::Simultaneous:
7170 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7171 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7172 if (invalidateAfterFirstResolve)
7173 {
7174 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &discards[2]);
7175 }
7176 break;
7177 case DepthStencilResolve::SeparateAspects:
7178 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7179 GL_NEAREST);
7180 if (invalidateAfterFirstResolve)
7181 {
7182 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &discards[0]);
7183 }
7184 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7185 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7186 if (invalidateAfterFirstResolve)
7187 {
7188 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &discards[1]);
7189 }
7190 break;
7191 }
7192 ASSERT_GL_NO_ERROR();
7193
7194 // Draw again, but don't resolve.
7195 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
7196 glStencilFunc(GL_ALWAYS, stencil2, 0xFF);
7197 drawQuad(red, essl1_shaders::PositionAttrib(), depth2);
7198
7199 const bool invalidateAtEnd =
7200 invalidate == Invalidate::AfterEachResolve || invalidate == Invalidate::AtEnd;
7201 if (invalidateAtEnd)
7202 {
7203 glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &discards[2]);
7204 }
7205
7206 // Make sure the render pass is flushed so if there's a caching bug and the old render pass
7207 // with resolve is used for the second render pass, the contents of the resolve attachment
7208 // is wrong. Can't rely on glReadPixels doing that because of potential use of
7209 // VK_EXT_host_image_copy.
7210 glFinish();
7211
7212 // Verify the contents of the resolve attachment
7213 verifyDepth(resolveFBO, kWidth, kHeight, depth1);
7214 verifyStencil(resolveFBO, kWidth, kHeight, stencil1);
7215
7216 if (!invalidateAtEnd)
7217 {
7218 // For completeness, make sure the second draw succeeded.
7219 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
7220 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7221 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7222 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7223 ASSERT_GL_NO_ERROR();
7224
7225 verifyDepth(resolveFBO, kWidth, kHeight, depth2);
7226 verifyStencil(resolveFBO, kWidth, kHeight, stencil2);
7227 }
7228 ASSERT_GL_NO_ERROR();
7229 };
7230
7231 test(0.4f, 0x3F, 0.1f, 0xA2, DepthStencilResolve::Simultaneous, Invalidate::None);
7232 test(0.9f, 0x2B, 0.3f, 0xDD, DepthStencilResolve::Simultaneous, Invalidate::AfterFirstResolve);
7233 test(0.5f, 0x6C, 0.6f, 0x7E, DepthStencilResolve::Simultaneous, Invalidate::AfterEachResolve);
7234 test(0.1f, 0x78, 0.4f, 0x34, DepthStencilResolve::Simultaneous, Invalidate::AtEnd);
7235 test(0.6f, 0x7E, 0.5f, 0x6C, DepthStencilResolve::SeparateAspects, Invalidate::None);
7236 test(0.1f, 0xA2, 0.9f, 0x2B, DepthStencilResolve::SeparateAspects,
7237 Invalidate::AfterFirstResolve);
7238 test(0.4f, 0x3F, 0.3f, 0xDD, DepthStencilResolve::SeparateAspects,
7239 Invalidate::AfterEachResolve);
7240 test(0.9f, 0xF0, 0.7f, 0x8A, DepthStencilResolve::SeparateAspects, Invalidate::AtEnd);
7241 }
7242
7243 // Test resolving a framebuffer once, then drawing to it again without a complete resolve, and then
7244 // drawing again with a resolve to same or another framebuffer.
TEST_P(FramebufferTest_ES31,ResolveThenDrawWithoutResolveThenDrawWithResolve)7245 TEST_P(FramebufferTest_ES31, ResolveThenDrawWithoutResolveThenDrawWithResolve)
7246 {
7247 enum class SecondResolve
7248 {
7249 SameFramebuffer,
7250 AnotherFramebuffer,
7251 };
7252
7253 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7254 glUseProgram(program);
7255 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7256 ASSERT_NE(colorLoc, -1);
7257
7258 constexpr int kWidth = 36;
7259 constexpr int kHeight = 12;
7260 glViewport(0, 0, kWidth, kHeight);
7261
7262 GLTexture msaa;
7263 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa);
7264 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7265
7266 GLFramebuffer msaaFBO;
7267 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7268 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa,
7269 0);
7270 ASSERT_GL_NO_ERROR();
7271 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7272
7273 // Create two resolve FBOs and textures. Use different texture levels and layers.
7274 GLTexture resolveTexture1;
7275 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
7276 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 4, kHeight * 4);
7277
7278 GLFramebuffer resolveFBO1;
7279 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
7280 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 2);
7281 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7282
7283 GLTexture resolveTexture2;
7284 glBindTexture(GL_TEXTURE_2D_ARRAY, resolveTexture2);
7285 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, 5);
7286
7287 GLFramebuffer resolveFBO2;
7288 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
7289 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolveTexture2, 0, 4);
7290 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7291
7292 auto test = [&](GLColor color1, GLColor color2, GLColor color3, SecondResolve secondResolve) {
7293 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7294 glUniform4fv(colorLoc, 1, color1.toNormalizedVector().data());
7295 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7296 ASSERT_GL_NO_ERROR();
7297
7298 // Resolve
7299 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
7300 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7301 GL_NEAREST);
7302 ASSERT_GL_NO_ERROR();
7303
7304 // Draw again, but don't resolve.
7305 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
7306 glUniform4fv(colorLoc, 1, color2.toNormalizedVector().data());
7307 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7308
7309 // Make sure the render pass is flushed.
7310 glFinish();
7311
7312 // Verify the contents of the resolve attachment
7313 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
7314 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color1);
7315
7316 // Draw and resolve again
7317 glEnable(GL_BLEND);
7318 glBlendFunc(GL_ONE, GL_ONE);
7319 glUniform4fv(colorLoc, 1, color3.toNormalizedVector().data());
7320 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7321 glDisable(GL_BLEND);
7322
7323 GLint fboToResolve =
7324 secondResolve == SecondResolve::SameFramebuffer ? resolveFBO1 : resolveFBO2;
7325 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboToResolve);
7326 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
7327 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7328 GL_NEAREST);
7329
7330 const GLColor blendedColor = GLColor(
7331 std::clamp(color2.R + color3.R, 0, 255), std::clamp(color2.G + color3.G, 0, 255),
7332 std::clamp(color2.B + color3.B, 0, 255), std::clamp(color2.A + color3.A, 0, 255));
7333 glBindFramebuffer(GL_READ_FRAMEBUFFER, fboToResolve);
7334 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, blendedColor);
7335 };
7336
7337 test(GLColor::red, GLColor::green, GLColor::blue, SecondResolve::SameFramebuffer);
7338 test(GLColor::cyan, GLColor(180, 0, 0, 190), GLColor(100, 255, 0, 80),
7339 SecondResolve::AnotherFramebuffer);
7340 }
7341
7342 // Test resolving a depth/stencil framebuffer once, then drawing to it again without a complete
7343 // resolve, and then drawing again with a resolve to same or another framebuffer.
TEST_P(FramebufferTest_ES31,DepthStencilResolveThenDrawWithoutResolveThenDrawWithResolve)7344 TEST_P(FramebufferTest_ES31, DepthStencilResolveThenDrawWithoutResolveThenDrawWithResolve)
7345 {
7346 enum class SecondResolve
7347 {
7348 SameFramebuffer,
7349 AnotherFramebuffer,
7350 };
7351 enum class DepthStencilResolve
7352 {
7353 Simultaneous,
7354 SeparateAspectsButSameFramebuffer,
7355 SeparateAspectsDifferentFramebuffers,
7356 };
7357
7358 constexpr int kWidth = 24;
7359 constexpr int kHeight = 12;
7360 glViewport(0, 0, kWidth, kHeight);
7361
7362 GLFramebuffer msaaFBO;
7363 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7364
7365 GLRenderbuffer depthStencil;
7366 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
7367 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
7368 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7369 depthStencil);
7370 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7371 ASSERT_GL_NO_ERROR();
7372
7373 // Create two resolve FBOs and textures. Use different texture levels and layers.
7374 GLTexture resolveTexture1;
7375 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
7376 glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
7377
7378 GLFramebuffer resolveFBO1;
7379 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
7380 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
7381 resolveTexture1, 2);
7382 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7383
7384 GLTexture resolveTexture2;
7385 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
7386 glTexStorage2D(GL_TEXTURE_2D, 2, GL_DEPTH24_STENCIL8, kWidth * 2, kHeight * 2);
7387
7388 GLFramebuffer resolveFBO2;
7389 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
7390 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
7391 resolveTexture2, 1);
7392 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7393
7394 ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7395
7396 auto runTest = [&](float depth1, int stencil1, float depth2, int stencil2,
7397 DepthStencilResolve resolve, SecondResolve secondResolve) {
7398 glEnable(GL_DEPTH_TEST);
7399 glDepthFunc(GL_ALWAYS);
7400 glDepthMask(GL_TRUE);
7401 glEnable(GL_STENCIL_TEST);
7402 glStencilFunc(GL_ALWAYS, stencil1, 0xFF);
7403 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
7404 glStencilMask(0xFF);
7405
7406 // Initialize the depth/stencil image
7407 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7408 drawQuad(red, essl1_shaders::PositionAttrib(), depth1);
7409 ASSERT_GL_NO_ERROR();
7410
7411 // Resolve depth and stencil, then verify the results
7412 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
7413 switch (resolve)
7414 {
7415 case DepthStencilResolve::Simultaneous:
7416 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7417 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7418 break;
7419 case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
7420 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7421 GL_NEAREST);
7422 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7423 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7424 break;
7425 case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
7426 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7427 GL_NEAREST);
7428 break;
7429 }
7430
7431 // Draw again, but don't resolve.
7432 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
7433 drawQuad(red, essl31_shaders::PositionAttrib(), 0);
7434
7435 // Make sure the render pass is flushed.
7436 glFinish();
7437
7438 // Draw and resolve again
7439 glStencilFunc(GL_ALWAYS, stencil2, 0xFF);
7440 drawQuad(red, essl31_shaders::PositionAttrib(), depth2);
7441
7442 GLint fboToResolve =
7443 secondResolve == SecondResolve::SameFramebuffer ? resolveFBO1 : resolveFBO2;
7444 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboToResolve);
7445 switch (resolve)
7446 {
7447 case DepthStencilResolve::Simultaneous:
7448 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7449 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7450 break;
7451 case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
7452 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7453 GL_NEAREST);
7454 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7455 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7456 break;
7457 case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
7458 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7459 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7460 break;
7461 }
7462 ASSERT_GL_NO_ERROR();
7463
7464 if (secondResolve == SecondResolve::SameFramebuffer)
7465 {
7466 verifyDepth(resolveFBO1, kWidth, kHeight,
7467 resolve == DepthStencilResolve::SeparateAspectsDifferentFramebuffers
7468 ? depth1
7469 : depth2);
7470 verifyStencil(resolveFBO1, kWidth, kHeight, stencil2);
7471 }
7472 else
7473 {
7474 verifyDepth(resolveFBO1, kWidth, kHeight, depth1);
7475 if (resolve != DepthStencilResolve::SeparateAspectsDifferentFramebuffers)
7476 {
7477 verifyStencil(resolveFBO1, kWidth, kHeight, stencil1);
7478 verifyDepth(resolveFBO2, kWidth, kHeight, depth2);
7479 }
7480 verifyStencil(resolveFBO2, kWidth, kHeight, stencil2);
7481 }
7482 };
7483
7484 runTest(0.4f, 0x3F, 0.1f, 0xA2, DepthStencilResolve::Simultaneous,
7485 SecondResolve::SameFramebuffer);
7486 runTest(0.9f, 0x2B, 0.3f, 0xDD, DepthStencilResolve::Simultaneous,
7487 SecondResolve::AnotherFramebuffer);
7488 runTest(0.6f, 0x7E, 0.6f, 0x7E, DepthStencilResolve::SeparateAspectsButSameFramebuffer,
7489 SecondResolve::SameFramebuffer);
7490 runTest(0.1f, 0xA2, 0.4f, 0x34, DepthStencilResolve::SeparateAspectsButSameFramebuffer,
7491 SecondResolve::AnotherFramebuffer);
7492 runTest(0.4f, 0x3F, 0.5f, 0x6C, DepthStencilResolve::SeparateAspectsDifferentFramebuffers,
7493 SecondResolve::SameFramebuffer);
7494 runTest(0.9f, 0xF0, 0.9f, 0x2B, DepthStencilResolve::SeparateAspectsDifferentFramebuffers,
7495 SecondResolve::AnotherFramebuffer);
7496 ASSERT_GL_NO_ERROR();
7497 }
7498
7499 // Test resolving a framebuffer once, then changing its attachment (with the same format) and
7500 // draw+resolving again. Makes sure the wrong framebuffer or render pass is not picked from a
7501 // cache.
TEST_P(FramebufferTest_ES31,ResolveThenChangeAttachmentThenResolveAgain)7502 TEST_P(FramebufferTest_ES31, ResolveThenChangeAttachmentThenResolveAgain)
7503 {
7504 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7505 glUseProgram(program);
7506 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7507 ASSERT_NE(colorLoc, -1);
7508
7509 constexpr int kWidth = 36;
7510 constexpr int kHeight = 20;
7511 glViewport(0, 0, kWidth, kHeight);
7512
7513 GLTexture msaa0, msaa1;
7514 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa0);
7515 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7516 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa1);
7517 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7518
7519 GLFramebuffer msaaFBO;
7520 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7521 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa0,
7522 0);
7523 ASSERT_GL_NO_ERROR();
7524 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7525
7526 // Create the resolve FBO and texture.
7527 GLTexture resolveTexture;
7528 glBindTexture(GL_TEXTURE_2D, resolveTexture);
7529 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kWidth * 2 + 1, kHeight * 2 + 1);
7530
7531 GLFramebuffer resolveFBO;
7532 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
7533 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
7534 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7535
7536 // Draw and resolve once
7537 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7538 glUniform4fv(colorLoc, 1, GLColor::green.toNormalizedVector().data());
7539 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7540 ASSERT_GL_NO_ERROR();
7541
7542 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7543 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7544 GL_NEAREST);
7545 ASSERT_GL_NO_ERROR();
7546
7547 // Change the framebuffer attachment to another texture
7548 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7549 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa1,
7550 0);
7551 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7552
7553 // Draw and resolve again
7554 glUniform4fv(colorLoc, 1, GLColor::blue.toNormalizedVector().data());
7555 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7556 ASSERT_GL_NO_ERROR();
7557
7558 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7559 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7560 GL_NEAREST);
7561 ASSERT_GL_NO_ERROR();
7562
7563 // Verify results
7564 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7565 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue);
7566 ASSERT_GL_NO_ERROR();
7567 }
7568
7569 // Test resolving a depth/stencil framebuffer once, then changing its attachment (with the same
7570 // format) and draw+resolving again. Makes sure the wrong framebuffer or render pass is not picked
7571 // from a cache.
TEST_P(FramebufferTest_ES31,DepthStencilResolveThenChangeAttachmentThenResolveAgain)7572 TEST_P(FramebufferTest_ES31, DepthStencilResolveThenChangeAttachmentThenResolveAgain)
7573 {
7574 enum class DepthStencilResolve
7575 {
7576 Simultaneous,
7577 SeparateAspects,
7578 };
7579
7580 constexpr int kWidth = 24;
7581 constexpr int kHeight = 12;
7582 glViewport(0, 0, kWidth, kHeight);
7583
7584 GLFramebuffer msaaFBO;
7585 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7586
7587 GLRenderbuffer depthStencil, depth, stencil;
7588 glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
7589 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
7590
7591 glBindRenderbuffer(GL_RENDERBUFFER, depth);
7592 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, kWidth, kHeight);
7593 glBindRenderbuffer(GL_RENDERBUFFER, stencil);
7594 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_STENCIL_INDEX8, kWidth, kHeight);
7595
7596 // Create two resolve FBOs and textures. Use different texture levels and layers.
7597 GLTexture resolveTexture1;
7598 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
7599 glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
7600
7601 GLFramebuffer resolveFBO1;
7602 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
7603 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
7604 resolveTexture1, 2);
7605 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7606
7607 GLTexture resolveTexture2;
7608 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
7609 glTexStorage2D(GL_TEXTURE_2D, 2, GL_DEPTH_COMPONENT16, kWidth * 2, kHeight * 2);
7610
7611 GLFramebuffer resolveFBO2;
7612 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
7613 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, resolveTexture2, 1);
7614 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7615
7616 GLTexture resolveTexture3;
7617 glBindTexture(GL_TEXTURE_2D, resolveTexture3);
7618 glTexStorage2D(GL_TEXTURE_2D, 2, GL_STENCIL_INDEX8, kWidth * 2, kHeight * 2);
7619
7620 GLFramebuffer resolveFBO3;
7621 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO3);
7622 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, resolveTexture3,
7623 1);
7624 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7625
7626 ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7627
7628 auto runTest = [&](float depth1, int stencil1, float depth2, int stencil2,
7629 DepthStencilResolve resolve) {
7630 glEnable(GL_DEPTH_TEST);
7631 glDepthFunc(GL_ALWAYS);
7632 glDepthMask(GL_TRUE);
7633 glEnable(GL_STENCIL_TEST);
7634 glStencilFunc(GL_ALWAYS, stencil1, 0xFF);
7635 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
7636 glStencilMask(0xFF);
7637
7638 // Initialize the depth/stencil image
7639 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7640 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7641 depthStencil);
7642 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7643
7644 drawQuad(red, essl1_shaders::PositionAttrib(), depth1);
7645 ASSERT_GL_NO_ERROR();
7646
7647 // Resolve depth and stencil
7648 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
7649 switch (resolve)
7650 {
7651 case DepthStencilResolve::Simultaneous:
7652 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7653 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7654 break;
7655 case DepthStencilResolve::SeparateAspects:
7656 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7657 GL_NEAREST);
7658 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7659 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7660 break;
7661 }
7662
7663 // Change the framebuffer and draw/resolve again
7664 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7665 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
7666 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
7667 drawQuad(red, essl1_shaders::PositionAttrib(), depth2);
7668 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7669
7670 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
7671 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7672 GL_NEAREST);
7673 ASSERT_GL_NO_ERROR();
7674
7675 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7676 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
7677 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencil);
7678 glStencilFunc(GL_ALWAYS, stencil2, 0xFF);
7679 drawQuad(red, essl1_shaders::PositionAttrib(), 0);
7680 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7681
7682 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO3);
7683 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_STENCIL_BUFFER_BIT,
7684 GL_NEAREST);
7685 ASSERT_GL_NO_ERROR();
7686
7687 verifyDepth(resolveFBO1, kWidth, kHeight, depth1);
7688 verifyStencil(resolveFBO1, kWidth, kHeight, stencil1);
7689 verifyDepth(resolveFBO2, kWidth, kHeight, depth2);
7690 verifyStencil(resolveFBO3, kWidth, kHeight, stencil2);
7691 };
7692
7693 runTest(0.1f, 0x78, 0.4f, 0x34, DepthStencilResolve::Simultaneous);
7694 runTest(0.6f, 0x7E, 0.5f, 0x6C, DepthStencilResolve::SeparateAspects);
7695 ASSERT_GL_NO_ERROR();
7696 }
7697
7698 // Similar to ResolveThenChangeAttachmentThenResolveAgain, but the attachment format is also changed
TEST_P(FramebufferTest_ES31,ResolveThenChangeAttachmentFormatThenResolveAgain)7699 TEST_P(FramebufferTest_ES31, ResolveThenChangeAttachmentFormatThenResolveAgain)
7700 {
7701 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7702 glUseProgram(program);
7703 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7704 ASSERT_NE(colorLoc, -1);
7705
7706 constexpr int kWidth = 32;
7707 constexpr int kHeight = 24;
7708 glViewport(0, 0, kWidth, kHeight);
7709
7710 GLTexture msaa0, msaa1;
7711 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa0);
7712 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7713 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa1);
7714 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB565, kWidth, kHeight, false);
7715
7716 GLFramebuffer msaaFBO;
7717 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7718 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa0,
7719 0);
7720 ASSERT_GL_NO_ERROR();
7721 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7722
7723 // Create two resolve FBOs and textures. Use different texture levels and layers.
7724 GLTexture resolveTexture1;
7725 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
7726 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 4, kHeight * 4);
7727
7728 GLFramebuffer resolveFBO1;
7729 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
7730 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 2);
7731 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7732
7733 GLTexture resolveTexture2;
7734 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
7735 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGB565, kWidth * 4, kHeight * 4);
7736
7737 GLFramebuffer resolveFBO2;
7738 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
7739 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 2);
7740 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7741
7742 // Draw and resolve once
7743 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7744 glUniform4fv(colorLoc, 1, GLColor::blue.toNormalizedVector().data());
7745 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7746 ASSERT_GL_NO_ERROR();
7747
7748 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
7749 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7750 GL_NEAREST);
7751 ASSERT_GL_NO_ERROR();
7752
7753 // Change the framebuffer attachment to another texture with a different format
7754 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7755 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa1,
7756 0);
7757 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7758
7759 // Draw and resolve again
7760 glUniform4fv(colorLoc, 1, GLColor::yellow.toNormalizedVector().data());
7761 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7762 ASSERT_GL_NO_ERROR();
7763
7764 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
7765 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7766 GL_NEAREST);
7767 ASSERT_GL_NO_ERROR();
7768
7769 // Verify results
7770 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
7771 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue);
7772 ASSERT_GL_NO_ERROR();
7773
7774 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
7775 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow);
7776 ASSERT_GL_NO_ERROR();
7777 }
7778
7779 // Draw and resolve once, use the resolve attachment as a storage image, then draw and resolve
7780 // again. The storage image usage may recreate the image internally, and this test makes sure the
7781 // wrong framebuffer or render pass is not picked from a cache.
TEST_P(FramebufferTest_ES31,ResolveThenUseAsStorageImageThenResolveAgain)7782 TEST_P(FramebufferTest_ES31, ResolveThenUseAsStorageImageThenResolveAgain)
7783 {
7784 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7785 glUseProgram(program);
7786 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7787 ASSERT_NE(colorLoc, -1);
7788
7789 constexpr int kWidth = 36;
7790 constexpr int kHeight = 20;
7791 glViewport(0, 0, kWidth, kHeight);
7792
7793 GLTexture msaa0, msaa1;
7794 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa0);
7795 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7796 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa1);
7797 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7798
7799 GLFramebuffer msaaFBO;
7800 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7801 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa0,
7802 0);
7803 ASSERT_GL_NO_ERROR();
7804 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7805
7806 // Create the resolve FBO and texture.
7807 GLTexture resolveTexture;
7808 glBindTexture(GL_TEXTURE_2D, resolveTexture);
7809 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kWidth * 2, kHeight * 2);
7810
7811 GLFramebuffer resolveFBO;
7812 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
7813 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
7814 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7815
7816 // Draw and resolve once
7817 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7818 glUniform4fv(colorLoc, 1, GLColor::green.toNormalizedVector().data());
7819 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7820 ASSERT_GL_NO_ERROR();
7821
7822 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7823 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7824 GL_NEAREST);
7825 ASSERT_GL_NO_ERROR();
7826
7827 // Use the resolve attachment as a storage image. A different level is used to be able to
7828 // verify the compute shader results.
7829 constexpr char kCS[] = R"(#version 310 es
7830 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
7831 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
7832 void main()
7833 {
7834 imageStore(image, ivec2(gl_GlobalInvocationID.xy), vec4(1, 1, 0, 1));
7835 })";
7836
7837 ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCS);
7838 glUseProgram(csProgram);
7839 glBindImageTexture(0, resolveTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
7840 glDispatchCompute(kWidth * 2, kHeight * 2, 1);
7841
7842 // Draw and resolve again
7843 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7844 glUseProgram(program);
7845 glUniform4fv(colorLoc, 1, GLColor::blue.toNormalizedVector().data());
7846 glEnable(GL_BLEND);
7847 glBlendFunc(GL_ONE, GL_ONE);
7848 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7849 ASSERT_GL_NO_ERROR();
7850
7851 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7852 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7853 GL_NEAREST);
7854 ASSERT_GL_NO_ERROR();
7855
7856 // Verify resolve results
7857 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7858 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::cyan);
7859
7860 // For completeness, verify compute shader write results
7861 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
7862
7863 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
7864 0);
7865 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7866 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth * 2, kHeight * 2, GLColor::yellow);
7867 ASSERT_GL_NO_ERROR();
7868 }
7869 ANGLE_INSTANTIATE_TEST_ES2_AND(AddMockTextureNoRenderTargetTest,
7870 ES2_D3D9().enable(Feature::AddMockTextureNoRenderTarget),
7871 ES2_D3D11().enable(Feature::AddMockTextureNoRenderTarget));
7872
7873 ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
7874 ANGLE_INSTANTIATE_TEST_ES2(FramebufferExtensionsTest);
7875 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
7876
7877 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3);
7878 ANGLE_INSTANTIATE_TEST_ES3_AND(FramebufferTest_ES3,
7879 ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
7880 ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
7881 ES3_VULKAN().enable(Feature::EmulatedPrerotation270));
7882
7883 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3Metal);
7884 ANGLE_INSTANTIATE_TEST(FramebufferTest_ES3Metal,
7885 ES3_METAL().enable(Feature::LimitMaxColorTargetBitsForTesting));
7886
7887 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES31);
7888 ANGLE_INSTANTIATE_TEST_ES31_AND(FramebufferTest_ES31,
7889 ES31_VULKAN().disable(Feature::SupportsImagelessFramebuffer));
7890 ANGLE_INSTANTIATE_TEST_ES3(FramebufferTestWithFormatFallback);
7891 ANGLE_INSTANTIATE_TEST_ES3(DefaultFramebufferTest);
7892