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