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/FeaturesD3D.h"
12 #include "test_utils/ANGLETest.h"
13 #include "test_utils/gl_raii.h"
14
15 using namespace angle;
16
17 namespace
18 {
19
ExpectFramebufferCompleteOrUnsupported(GLenum binding)20 void ExpectFramebufferCompleteOrUnsupported(GLenum binding)
21 {
22 GLenum status = glCheckFramebufferStatus(binding);
23 EXPECT_TRUE(status == GL_FRAMEBUFFER_COMPLETE || status == GL_FRAMEBUFFER_UNSUPPORTED);
24 }
25
26 } // anonymous namespace
27
28 class FramebufferFormatsTest : public ANGLETest
29 {
30 protected:
FramebufferFormatsTest()31 FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
32 {
33 setWindowWidth(128);
34 setWindowHeight(128);
35 setConfigRedBits(8);
36 setConfigGreenBits(8);
37 setConfigBlueBits(8);
38 setConfigAlphaBits(8);
39 }
40
checkBitCount(GLuint fbo,GLenum channel,GLint minBits)41 void checkBitCount(GLuint fbo, GLenum channel, GLint minBits)
42 {
43 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
44
45 GLint bits = 0;
46 glGetIntegerv(channel, &bits);
47
48 if (minBits == 0)
49 {
50 EXPECT_EQ(minBits, bits);
51 }
52 else
53 {
54 EXPECT_GE(bits, minBits);
55 }
56 }
57
testBitCounts(GLuint fbo,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits,GLint minDepthBits,GLint minStencilBits)58 void testBitCounts(GLuint fbo,
59 GLint minRedBits,
60 GLint minGreenBits,
61 GLint minBlueBits,
62 GLint minAlphaBits,
63 GLint minDepthBits,
64 GLint minStencilBits)
65 {
66 checkBitCount(fbo, GL_RED_BITS, minRedBits);
67 checkBitCount(fbo, GL_GREEN_BITS, minGreenBits);
68 checkBitCount(fbo, GL_BLUE_BITS, minBlueBits);
69 checkBitCount(fbo, GL_ALPHA_BITS, minAlphaBits);
70 checkBitCount(fbo, GL_DEPTH_BITS, minDepthBits);
71 checkBitCount(fbo, GL_STENCIL_BITS, minStencilBits);
72 }
73
testTextureFormat(GLenum internalFormat,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits)74 void testTextureFormat(GLenum internalFormat,
75 GLint minRedBits,
76 GLint minGreenBits,
77 GLint minBlueBits,
78 GLint minAlphaBits)
79 {
80 glGenTextures(1, &mTexture);
81 glBindTexture(GL_TEXTURE_2D, mTexture);
82
83 if (getClientMajorVersion() >= 3)
84 {
85 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
86 }
87 else
88 {
89 glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
90 }
91
92 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
93
94 testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
95 }
96
testRenderbufferMultisampleFormat(int minESVersion,GLenum attachmentType,GLenum internalFormat)97 void testRenderbufferMultisampleFormat(int minESVersion,
98 GLenum attachmentType,
99 GLenum internalFormat)
100 {
101 int clientVersion = getClientMajorVersion();
102 if (clientVersion < minESVersion)
103 {
104 return;
105 }
106
107 // Check that multisample is supported with at least two samples (minimum required is 1)
108 bool supports2Samples = false;
109
110 if (clientVersion == 2)
111 {
112 if (IsGLExtensionEnabled("ANGLE_framebuffer_multisample"))
113 {
114 int maxSamples;
115 glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples);
116 supports2Samples = maxSamples >= 2;
117 }
118 }
119 else
120 {
121 assert(clientVersion >= 3);
122 int maxSamples;
123 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
124 supports2Samples = maxSamples >= 2;
125 }
126
127 if (!supports2Samples)
128 {
129 return;
130 }
131
132 glGenRenderbuffers(1, &mRenderbuffer);
133 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
134
135 EXPECT_GL_NO_ERROR();
136 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
137 EXPECT_GL_NO_ERROR();
138 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
139 EXPECT_GL_NO_ERROR();
140 }
141
testZeroHeightRenderbuffer()142 void testZeroHeightRenderbuffer()
143 {
144 glGenRenderbuffers(1, &mRenderbuffer);
145 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
146 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 0);
147 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
148 mRenderbuffer);
149 EXPECT_GL_NO_ERROR();
150 }
151
testSetUp()152 void testSetUp() override
153 {
154 glGenFramebuffers(1, &mFramebuffer);
155 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
156 }
157
testTearDown()158 void testTearDown() override
159 {
160 if (mTexture != 0)
161 {
162 glDeleteTextures(1, &mTexture);
163 mTexture = 0;
164 }
165
166 if (mRenderbuffer != 0)
167 {
168 glDeleteRenderbuffers(1, &mRenderbuffer);
169 mRenderbuffer = 0;
170 }
171
172 if (mFramebuffer != 0)
173 {
174 glDeleteFramebuffers(1, &mFramebuffer);
175 mFramebuffer = 0;
176 }
177
178 if (mProgram != 0)
179 {
180 glDeleteProgram(mProgram);
181 mProgram = 0;
182 }
183 }
184
185 GLuint mFramebuffer;
186 GLuint mTexture;
187 GLuint mRenderbuffer;
188 GLuint mProgram;
189 };
190
TEST_P(FramebufferFormatsTest,RGBA4)191 TEST_P(FramebufferFormatsTest, RGBA4)
192 {
193 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
194 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
195
196 testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
197 }
198
TEST_P(FramebufferFormatsTest,RGB565)199 TEST_P(FramebufferFormatsTest, RGB565)
200 {
201 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
202 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
203
204 testTextureFormat(GL_RGB565, 5, 6, 5, 0);
205 }
206
TEST_P(FramebufferFormatsTest,RGB8)207 TEST_P(FramebufferFormatsTest, RGB8)
208 {
209 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
210 (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
211 !IsGLExtensionEnabled("GL_EXT_texture_storage")));
212
213 testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
214 }
215
TEST_P(FramebufferFormatsTest,BGRA8)216 TEST_P(FramebufferFormatsTest, BGRA8)
217 {
218 ANGLE_SKIP_TEST_IF(
219 !IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888") ||
220 (getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_texture_storage")));
221
222 testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
223 }
224
TEST_P(FramebufferFormatsTest,RGBA8)225 TEST_P(FramebufferFormatsTest, RGBA8)
226 {
227 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
228 (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
229 !IsGLExtensionEnabled("GL_EXT_texture_storage")));
230
231 testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
232 }
233
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH16)234 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
235 {
236 testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
237 }
238
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24)239 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
240 {
241 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
242 }
243
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F)244 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
245 {
246 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
247
248 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
249 }
250
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24_STENCIL8)251 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
252 {
253 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
254 }
255
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F_STENCIL8)256 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
257 {
258 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
259
260 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
261 }
262
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_STENCIL_INDEX8)263 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
264 {
265 // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
266 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
267
268 testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
269 }
270
271 // Test that binding an incomplete cube map is rejected by ANGLE.
TEST_P(FramebufferFormatsTest,IncompleteCubeMap)272 TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
273 {
274 // http://anglebug.com/3145
275 ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
276
277 // First make a complete CubeMap.
278 glGenTextures(1, &mTexture);
279 glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
280 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
281 nullptr);
282 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
283 nullptr);
284 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
285 nullptr);
286 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
287 nullptr);
288 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
289 nullptr);
290 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
291 nullptr);
292 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
293 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
294
295 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
296 mTexture, 0);
297
298 // Verify the framebuffer is complete.
299 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
300
301 // Make the CubeMap cube-incomplete.
302 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
303 nullptr);
304
305 // Verify the framebuffer is incomplete.
306 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
307 glCheckFramebufferStatus(GL_FRAMEBUFFER));
308
309 ASSERT_GL_NO_ERROR();
310
311 // Verify drawing with the incomplete framebuffer produces a GL error
312 mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
313 ASSERT_NE(0u, mProgram);
314 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
315 ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
316 }
317
318 // Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts.
TEST_P(FramebufferFormatsTest,ZeroHeightRenderbuffer)319 TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
320 {
321 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
322
323 testZeroHeightRenderbuffer();
324 }
325
326 // Test to cover a bug where the read framebuffer affects the completeness of the draw framebuffer.
TEST_P(FramebufferFormatsTest,ReadDrawCompleteness)327 TEST_P(FramebufferFormatsTest, ReadDrawCompleteness)
328 {
329 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
330
331 GLTexture incompleteTexture;
332 glBindTexture(GL_TEXTURE_2D, incompleteTexture);
333
334 GLFramebuffer incompleteFBO;
335 glBindFramebuffer(GL_FRAMEBUFFER, incompleteFBO);
336 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, incompleteTexture,
337 0);
338 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
339 glCheckFramebufferStatus(GL_FRAMEBUFFER));
340
341 GLTexture completeTexture;
342 glBindTexture(GL_TEXTURE_2D, completeTexture);
343 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
344
345 GLFramebuffer completeFBO;
346 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, completeFBO);
347 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
348 completeTexture, 0);
349
350 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
351 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
352 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
353
354 ASSERT_GL_NO_ERROR();
355
356 // Simple draw program.
357 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
358
359 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
360 EXPECT_GL_NO_ERROR();
361
362 glBindFramebuffer(GL_READ_FRAMEBUFFER, completeFBO);
363 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
364 }
365
366 // Test that a renderbuffer with RGB565 format works as expected. This test is intended for some
367 // back-end having no support for native RGB565 renderbuffer and thus having to emulate using RGBA
368 // format.
TEST_P(FramebufferFormatsTest,RGB565Renderbuffer)369 TEST_P(FramebufferFormatsTest, RGB565Renderbuffer)
370 {
371 GLRenderbuffer rbo;
372 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
373 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, 1, 1);
374
375 GLFramebuffer completeFBO;
376 glBindFramebuffer(GL_FRAMEBUFFER, completeFBO);
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, 0, 0.5f);
384 glClear(GL_COLOR_BUFFER_BIT);
385 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
386 }
387
388 class FramebufferTest_ES3 : public ANGLETest
389 {
390 protected:
FramebufferTest_ES3()391 FramebufferTest_ES3()
392 {
393 setWindowWidth(kWidth);
394 setWindowHeight(kHeight);
395 setConfigRedBits(8);
396 setConfigGreenBits(8);
397 setConfigBlueBits(8);
398 setConfigAlphaBits(8);
399 setConfigDepthBits(24);
400 setConfigStencilBits(8);
401 }
402
403 static constexpr GLsizei kWidth = 64;
404 static constexpr GLsizei kHeight = 256;
405 };
406
407 // Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3,InvalidateIncomplete)408 TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
409 {
410 GLFramebuffer framebuffer;
411 GLRenderbuffer renderbuffer;
412
413 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
414 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
415 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
416 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
417 glCheckFramebufferStatus(GL_FRAMEBUFFER));
418
419 std::vector<GLenum> attachments;
420 attachments.push_back(GL_COLOR_ATTACHMENT0);
421
422 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
423 EXPECT_GL_NO_ERROR();
424 }
425
426 // Covers sub-invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3,SubInvalidateIncomplete)427 TEST_P(FramebufferTest_ES3, SubInvalidateIncomplete)
428 {
429 GLFramebuffer framebuffer;
430 GLRenderbuffer renderbuffer;
431
432 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
433 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
434 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
435 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
436 glCheckFramebufferStatus(GL_FRAMEBUFFER));
437
438 std::vector<GLenum> attachments;
439 attachments.push_back(GL_COLOR_ATTACHMENT0);
440
441 glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 1, attachments.data(), 5, 5, 10, 10);
442 EXPECT_GL_NO_ERROR();
443 }
444
445 // Test that subinvalidate with no prior command works. Regression test for the Vulkan backend that
446 // assumed a render pass is started when sub invalidate is called.
TEST_P(FramebufferTest_ES3,SubInvalidateFirst)447 TEST_P(FramebufferTest_ES3, SubInvalidateFirst)
448 {
449 glBindFramebuffer(GL_FRAMEBUFFER, 0);
450
451 // Invalidate half of the framebuffer using swapped dimensions.
452 std::array<GLenum, 1> attachments = {GL_COLOR};
453 glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, attachments.data(), 0, 0, kHeight, kWidth);
454 EXPECT_GL_NO_ERROR();
455 }
456
457 // Test that subinvalidate doesn't discard data outside area. Uses swapped width/height for
458 // invalidate which results in a partial invalidate, but also prevents bugs with Vulkan
459 // pre-rotation.
TEST_P(FramebufferTest_ES3,SubInvalidatePartial)460 TEST_P(FramebufferTest_ES3, SubInvalidatePartial)
461 {
462 glBindFramebuffer(GL_FRAMEBUFFER, 0);
463
464 // Clear the attachment.
465 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
466 glClear(GL_COLOR_BUFFER_BIT);
467 EXPECT_GL_NO_ERROR();
468
469 // Invalidate half of the framebuffer using swapped dimensions.
470 std::array<GLenum, 1> attachments = {GL_COLOR};
471 glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, attachments.data(), 0, 0, kHeight, kWidth);
472 EXPECT_GL_NO_ERROR();
473
474 // Make sure the other half is correct.
475 EXPECT_PIXEL_COLOR_EQ(0, kWidth, GLColor::red);
476 EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kWidth, GLColor::red);
477 EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
478 EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::red);
479 }
480
481 // Test that a scissored draw followed by subinvalidate followed by a non-scissored draw retains the
482 // part that is not invalidated. Uses swapped width/height for invalidate which results in a
483 // partial invalidate, but also prevents bugs with Vulkan pre-rotation.
TEST_P(FramebufferTest_ES3,ScissoredDrawSubInvalidateThenNonScissoredDraw)484 TEST_P(FramebufferTest_ES3, ScissoredDrawSubInvalidateThenNonScissoredDraw)
485 {
486 swapBuffers();
487 glBindFramebuffer(GL_FRAMEBUFFER, 0);
488
489 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
490 glUseProgram(drawColor);
491 GLint colorUniformLocation =
492 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
493 ASSERT_NE(colorUniformLocation, -1);
494
495 // Clear color to red and the depth/stencil buffer to 1.0 and 0x55
496 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
497 glClearDepthf(1);
498 glClearStencil(0x55);
499 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
500 EXPECT_GL_NO_ERROR();
501
502 // Break rendering so the following draw call starts rendering with a scissored area.
503 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
504
505 // Issue a scissored draw call that changes depth to 0.5 and stencil 0x3C
506 glScissor(0, 0, kHeight, kWidth);
507 glEnable(GL_SCISSOR_TEST);
508
509 glEnable(GL_DEPTH_TEST);
510 glDepthFunc(GL_ALWAYS);
511
512 glEnable(GL_STENCIL_TEST);
513 glStencilFunc(GL_ALWAYS, 0x3C, 0xFF);
514 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
515 glStencilMask(0xFF);
516
517 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
518 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0);
519
520 // Invalidate the draw region (half of the framebuffer using swapped dimensions).
521 std::array<GLenum, 3> attachments = {GL_COLOR, GL_DEPTH, GL_STENCIL};
522 glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 3, attachments.data(), 0, 0, kHeight, kWidth);
523 EXPECT_GL_NO_ERROR();
524
525 // Match the scissor to the framebuffer size and issue a draw call that blends blue, and expects
526 // depth to be 1 and stencil to be 0x55. This is only valid for the half that was not
527 // invalidated.
528 glScissor(0, 0, kWidth, kHeight);
529 glDepthFunc(GL_LESS);
530 glStencilFunc(GL_EQUAL, 0x55, 0xFF);
531 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
532
533 glEnable(GL_BLEND);
534 glBlendFunc(GL_ONE, GL_ONE);
535 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
536 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
537 ASSERT_GL_NO_ERROR();
538
539 // Make sure the half that was not invalidated is correct.
540 EXPECT_PIXEL_COLOR_EQ(0, kWidth, GLColor::magenta);
541 EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kWidth, GLColor::magenta);
542 EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
543 EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
544 }
545
546 // Test that the framebuffer state tracking robustly handles a depth-only attachment being set
547 // as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
TEST_P(FramebufferTest_ES3,DepthOnlyAsDepthStencil)548 TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
549 {
550 GLFramebuffer framebuffer;
551 GLRenderbuffer renderbuffer;
552
553 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
554 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
555 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
556
557 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
558 renderbuffer);
559 EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
560 }
561
562 // Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
563 // are bound
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevels)564 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
565 {
566 GLFramebuffer framebuffer;
567 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
568
569 GLTexture texture;
570 glBindTexture(GL_TEXTURE_2D, texture);
571
572 // Create a complete mip chain in mips 1 to 3
573 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
574 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
575 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
576
577 // Create another complete mip chain in mips 4 to 5
578 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
579 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
580
581 // Create a non-complete mip chain in mip 6
582 glTexImage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
583
584 // Incomplete, mipLevel != baseLevel and texture is not mip complete
585 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
586 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
587 glCheckFramebufferStatus(GL_FRAMEBUFFER));
588
589 // Complete, mipLevel == baseLevel
590 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
591 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
592
593 // Complete, mipLevel != baseLevel but texture is now mip complete
594 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
595 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
596 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
597 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
598
599 // Incomplete, attached level below the base level
600 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
601 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
602 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
603 glCheckFramebufferStatus(GL_FRAMEBUFFER));
604
605 // Incomplete, attached level is beyond effective max level
606 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 4);
607 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
608 glCheckFramebufferStatus(GL_FRAMEBUFFER));
609
610 // Complete, mipLevel == baseLevel
611 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
612 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
613
614 // Complete, mipLevel != baseLevel but texture is now mip complete
615 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 5);
616 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
617
618 // Complete, mipLevel == baseLevel
619 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 6);
620 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 6);
621 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
622 }
623
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevelsReadBack)624 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBack)
625 {
626 GLFramebuffer framebuffer;
627 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
628
629 GLTexture texture;
630 glBindTexture(GL_TEXTURE_2D, texture);
631
632 const std::array<GLColor, 4 * 4> mip0Data = {
633 GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
634 GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
635 GLColor::red, GLColor::red, GLColor::red, GLColor::red};
636 const std::array<GLColor, 2 * 2> mip1Data = {GLColor::green, GLColor::green, GLColor::green,
637 GLColor::green};
638
639 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
640 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
641
642 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
643 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
644 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
645
646 glClearColor(0, 0, 1.0f, 1.0f);
647 glClear(GL_COLOR_BUFFER_BIT);
648 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
649 }
650
651 // TextureAttachmentMipLevelsReadBackWithDraw is a copy of TextureAttachmentMipLevelsReadBack except
652 // for adding a draw after the last clear. The draw forces ANGLE's Vulkan backend to use the
653 // framebuffer that is level 1 of the texture which will trigger the mismatch use of the GL level
654 // and Vulkan level in referring to that rendertarget.
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevelsReadBackWithDraw)655 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBackWithDraw)
656 {
657 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
658
659 GLFramebuffer framebuffer;
660 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
661
662 GLTexture texture;
663 glBindTexture(GL_TEXTURE_2D, texture);
664
665 const std::array<GLColor, 4 * 4> mip0Data = {
666 GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
667 GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
668 GLColor::red, GLColor::red, GLColor::red, GLColor::red};
669 const std::array<GLColor, 2 * 2> mip1Data = {GLColor::green, GLColor::green, GLColor::green,
670 GLColor::green};
671
672 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
673 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
674
675 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
676 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
677 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
678
679 glClearColor(0, 0, 1.0f, 1.0f);
680 glClear(GL_COLOR_BUFFER_BIT);
681
682 // This draw triggers the use of the framebuffer
683 glUseProgram(greenProgram);
684 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
685 ASSERT_GL_NO_ERROR();
686 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
687 }
688
689 // Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
690 // generates an INVALID_OPERATION.
691 // OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
692 // 208
TEST_P(FramebufferTest_ES3,ColorAttachmentIndexOutOfBounds)693 TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
694 {
695 GLFramebuffer framebuffer;
696 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
697
698 GLint maxColorAttachments = 0;
699 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
700 GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
701
702 GLTexture texture;
703 glBindTexture(GL_TEXTURE_2D, texture.get());
704 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
705 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.get(), 0);
706 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
707 }
708
709 // Check that depth-only attachments report the correct number of samples.
TEST_P(FramebufferTest_ES3,MultisampleDepthOnly)710 TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
711 {
712 GLRenderbuffer renderbuffer;
713 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
714 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
715
716 GLFramebuffer framebuffer;
717 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
718 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
719 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
720 EXPECT_GL_NO_ERROR();
721
722 GLint samples = 0;
723 glGetIntegerv(GL_SAMPLES, &samples);
724 EXPECT_GL_NO_ERROR();
725 EXPECT_GE(samples, 2);
726 }
727
728 // Check that we only compare width and height of attachments, not depth.
TEST_P(FramebufferTest_ES3,AttachmentWith3DLayers)729 TEST_P(FramebufferTest_ES3, AttachmentWith3DLayers)
730 {
731 GLTexture texA;
732 glBindTexture(GL_TEXTURE_2D, texA);
733 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
734
735 GLTexture texB;
736 glBindTexture(GL_TEXTURE_3D, texB);
737 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
738
739 GLFramebuffer framebuffer;
740 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
741 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
742 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texB, 0, 0);
743 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
744 EXPECT_GL_NO_ERROR();
745 }
746
747 // Check that invalid layer is detected in framebuffer completeness check.
748 TEST_P(FramebufferTest_ES3, 3DAttachmentInvalidLayer)
749 {
750 GLTexture tex;
751 glBindTexture(GL_TEXTURE_3D, tex);
752 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
753
754 GLFramebuffer framebuffer;
755 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
756 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
757 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
758 glCheckFramebufferStatus(GL_FRAMEBUFFER));
759
760 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
761 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
762 EXPECT_GL_NO_ERROR();
763 }
764
765 // Check that invalid layer is detected in framebuffer completeness check.
766 TEST_P(FramebufferTest_ES3, 2DArrayInvalidLayer)
767 {
768 GLTexture tex;
769 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
770 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
771
772 GLFramebuffer framebuffer;
773 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
774 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
775 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
776 glCheckFramebufferStatus(GL_FRAMEBUFFER));
777
778 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
779 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
780 EXPECT_GL_NO_ERROR();
781 }
782
783 // Test that clearing the stencil buffer when the framebuffer only has a color attachment does not
784 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentStencil)785 TEST_P(FramebufferTest_ES3, ClearNonexistentStencil)
786 {
787 GLRenderbuffer rbo;
788 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
789 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
790
791 GLFramebuffer fbo;
792 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
793 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
794
795 GLint clearValue = 0;
796 glClearBufferiv(GL_STENCIL, 0, &clearValue);
797
798 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
799 EXPECT_GL_NO_ERROR();
800 }
801
802 // Test that clearing the depth buffer when the framebuffer only has a color attachment does not
803 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepth)804 TEST_P(FramebufferTest_ES3, ClearNonexistentDepth)
805 {
806 GLRenderbuffer rbo;
807 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
808 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
809
810 GLFramebuffer fbo;
811 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
812 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
813
814 GLfloat clearValue = 0.0f;
815 glClearBufferfv(GL_DEPTH, 0, &clearValue);
816
817 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
818 EXPECT_GL_NO_ERROR();
819 }
820
821 // Test that clearing a nonexistent color attachment does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentColor)822 TEST_P(FramebufferTest_ES3, ClearNonexistentColor)
823 {
824 GLRenderbuffer rbo;
825 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
826 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
827
828 GLFramebuffer fbo;
829 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
830 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
831
832 std::vector<GLfloat> clearValue = {{0.0f, 1.0f, 0.0f, 1.0f}};
833 glClearBufferfv(GL_COLOR, 1, clearValue.data());
834
835 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
836 EXPECT_GL_NO_ERROR();
837 }
838
839 // Test that clearing the depth and stencil buffers when the framebuffer only has a color attachment
840 // does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepthStencil)841 TEST_P(FramebufferTest_ES3, ClearNonexistentDepthStencil)
842 {
843 GLRenderbuffer rbo;
844 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
845 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
846
847 GLFramebuffer fbo;
848 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
849 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
850
851 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
852
853 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
854 EXPECT_GL_NO_ERROR();
855 }
856
857 // Test that clearing a color attachment that has been deleted doesn't crash.
TEST_P(FramebufferTest_ES3,ClearDeletedAttachment)858 TEST_P(FramebufferTest_ES3, ClearDeletedAttachment)
859 {
860 // An INVALID_FRAMEBUFFER_OPERATION error was seen in this test on Mac, not sure where it might
861 // be originating from. http://anglebug.com/2834
862 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
863
864 GLFramebuffer fbo;
865 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
866
867 // There used to be a bug where some draw buffer state used to remain set even after the
868 // attachment was detached via deletion. That's why we create, attach and delete this RBO here.
869 GLuint rbo = 0u;
870 glGenRenderbuffers(1, &rbo);
871 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
872 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
873 glDeleteRenderbuffers(1, &rbo);
874
875 // There needs to be at least one color attachment to prevent early out from the clear calls.
876 GLRenderbuffer rbo2;
877 glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
878 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
879 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo2);
880
881 ASSERT_GL_NO_ERROR();
882
883 // There's no error specified for clearing nonexistent buffers, it's simply a no-op, so we
884 // expect no GL errors below.
885 std::array<GLfloat, 4> floatClearValue = {0.0f, 0.0f, 0.0f, 0.0f};
886 glClearBufferfv(GL_COLOR, 0, floatClearValue.data());
887 EXPECT_GL_NO_ERROR();
888 std::array<GLuint, 4> uintClearValue = {0u, 0u, 0u, 0u};
889 glClearBufferuiv(GL_COLOR, 0, uintClearValue.data());
890 EXPECT_GL_NO_ERROR();
891 std::array<GLint, 4> intClearValue = {0, 0, 0, 0};
892 glClearBufferiv(GL_COLOR, 0, intClearValue.data());
893 EXPECT_GL_NO_ERROR();
894 }
895
896 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentSmallToLarge)897 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
898 {
899 GLFramebuffer fbo;
900 GLTexture smallTexture;
901 GLTexture largeTexture;
902
903 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
904 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
905
906 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
907
908 // Bind the small texture
909 glBindTexture(GL_TEXTURE_2D, smallTexture);
910 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
911 GL_UNSIGNED_BYTE, nullptr);
912 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
913 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
914 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
915 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
916
917 // Draw to FBO backed by the small texture
918 glUseProgram(greenProgram);
919 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
920 ASSERT_GL_NO_ERROR();
921 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
922 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
923
924 // Change the attachment to the larger texture that fills the window
925 glBindTexture(GL_TEXTURE_2D, largeTexture);
926 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
927 GL_UNSIGNED_BYTE, nullptr);
928 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
929 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
930 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
931 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
932
933 // Draw to FBO backed by the large texture
934 glUseProgram(blueProgram);
935 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
936 ASSERT_GL_NO_ERROR();
937 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
938 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
939 }
940
941 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentLargeToSmall)942 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
943 {
944 GLFramebuffer fbo;
945 GLTexture smallTexture;
946 GLTexture largeTexture;
947
948 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
949 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
950
951 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
952
953 // Bind the large texture
954 glBindTexture(GL_TEXTURE_2D, largeTexture);
955 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
956 GL_UNSIGNED_BYTE, nullptr);
957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
958 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
959 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
960 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
961
962 // Draw to FBO backed by the large texture
963 glUseProgram(blueProgram);
964 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
965 ASSERT_GL_NO_ERROR();
966 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
967 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
968
969 // Change the attachment to the smaller texture
970 glBindTexture(GL_TEXTURE_2D, smallTexture);
971 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
972 GL_UNSIGNED_BYTE, nullptr);
973 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
974 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
975 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
976 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
977
978 // Draw to FBO backed by the small texture
979 glUseProgram(greenProgram);
980 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
981 ASSERT_GL_NO_ERROR();
982 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
983 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
984 }
985
986 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureLargeToSmall)987 TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
988 {
989 GLFramebuffer fbo;
990 GLTexture texture;
991
992 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
993 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
994
995 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
996
997 // Allocate a large texture
998 glBindTexture(GL_TEXTURE_2D, texture);
999 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1000 GL_UNSIGNED_BYTE, nullptr);
1001 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1002 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1003 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1004 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1005
1006 // Draw to FBO backed by the large texture
1007 glUseProgram(blueProgram);
1008 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1009 ASSERT_GL_NO_ERROR();
1010 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1011 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
1012
1013 // Shrink the texture
1014 glBindTexture(GL_TEXTURE_2D, texture);
1015 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1016 GL_UNSIGNED_BYTE, nullptr);
1017 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1018 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1019 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1020 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1021
1022 // Draw to FBO backed by the small texture
1023 glUseProgram(greenProgram);
1024 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1025 ASSERT_GL_NO_ERROR();
1026 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1027 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
1028 }
1029
1030 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureSmallToLarge)1031 TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
1032 {
1033 GLFramebuffer fbo;
1034 GLTexture texture;
1035
1036 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1037 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1038
1039 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1040
1041 // Allocate a small texture
1042 glBindTexture(GL_TEXTURE_2D, texture);
1043 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1044 GL_UNSIGNED_BYTE, nullptr);
1045 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1046 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1047 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1048 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1049
1050 // Draw to FBO backed by the large texture
1051 glUseProgram(blueProgram);
1052 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1053 ASSERT_GL_NO_ERROR();
1054 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1055 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
1056
1057 // Grow the texture
1058 glBindTexture(GL_TEXTURE_2D, texture);
1059 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1060 GL_UNSIGNED_BYTE, nullptr);
1061 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1062 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1063 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1064 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1065
1066 // Draw to FBO backed by the small texture
1067 glUseProgram(greenProgram);
1068 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1069 ASSERT_GL_NO_ERROR();
1070 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1071 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
1072 }
1073
1074 // Test that fewer outputs than framebuffer attachments doesn't crash. This causes a Vulkan
1075 // validation warning, but should not be fatal.
TEST_P(FramebufferTest_ES3,FewerShaderOutputsThanAttachments)1076 TEST_P(FramebufferTest_ES3, FewerShaderOutputsThanAttachments)
1077 {
1078 constexpr char kFS[] = R"(#version 300 es
1079 precision highp float;
1080
1081 layout(location = 0) out vec4 color0;
1082 layout(location = 1) out vec4 color1;
1083 layout(location = 2) out vec4 color2;
1084
1085 void main()
1086 {
1087 color0 = vec4(1.0, 0.0, 0.0, 1.0);
1088 color1 = vec4(0.0, 1.0, 0.0, 1.0);
1089 color2 = vec4(0.0, 0.0, 1.0, 1.0);
1090 }
1091 )";
1092
1093 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1094
1095 constexpr GLint kDrawBufferCount = 4;
1096
1097 GLint maxDrawBuffers;
1098 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1099 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
1100
1101 GLTexture textures[kDrawBufferCount];
1102
1103 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
1104 {
1105 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
1106 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1107 GL_UNSIGNED_BYTE, nullptr);
1108 }
1109
1110 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
1111 GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
1112
1113 GLFramebuffer fbo;
1114 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1115
1116 // Enable all draw buffers.
1117 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
1118 {
1119 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
1120 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
1121 textures[texIndex], 0);
1122 }
1123 glDrawBuffers(kDrawBufferCount, allBufs);
1124
1125 // Draw with simple program.
1126 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1127 ASSERT_GL_NO_ERROR();
1128 }
1129
1130 class FramebufferTestWithFormatFallback : public ANGLETest
1131 {
1132 protected:
FramebufferTestWithFormatFallback()1133 FramebufferTestWithFormatFallback()
1134 {
1135 setWindowWidth(16);
1136 setWindowHeight(16);
1137 setConfigRedBits(8);
1138 setConfigGreenBits(8);
1139 setConfigBlueBits(8);
1140 setConfigAlphaBits(8);
1141 setConfigDepthBits(24);
1142 setConfigStencilBits(8);
1143 }
1144
1145 void texImageFollowedByFBORead(GLenum internalFormat, GLenum type);
1146 void blitCopyFollowedByFBORead(GLenum internalFormat, GLenum type);
1147 void copyTexImageFollowedBySampling(GLenum internalFormat, GLenum type);
1148 void cubeTexImageFollowedByFBORead(GLenum internalFormat, GLenum type);
1149 GLushort convertGLColorToUShort(GLenum internalFormat, const GLColor &color);
1150 static constexpr GLsizei kTexWidth = 16;
1151 static constexpr GLsizei kTexHeight = 16;
1152 static constexpr GLsizei kMaxLevel = 4;
1153 };
1154
convertGLColorToUShort(GLenum internalFormat,const GLColor & color)1155 GLushort FramebufferTestWithFormatFallback::convertGLColorToUShort(GLenum internalFormat,
1156 const GLColor &color)
1157 {
1158 GLushort r, g, b, a;
1159 switch (internalFormat)
1160 {
1161 case GL_RGB5_A1:
1162 r = (color.R >> 3) << 11;
1163 g = (color.G >> 3) << 6;
1164 b = (color.B >> 3) << 1;
1165 a = color.A >> 7;
1166 break;
1167 case GL_RGBA4:
1168 r = (color.R >> 4) << 12;
1169 g = (color.G >> 4) << 8;
1170 b = (color.B >> 4) << 4;
1171 a = color.A >> 4;
1172 break;
1173 default:
1174 UNREACHABLE();
1175 r = 0;
1176 g = 0;
1177 b = 0;
1178 a = 0;
1179 break;
1180 }
1181 return r | g | b | a;
1182 }
1183
1184 // Test texture format fallback while it has staged updates.
texImageFollowedByFBORead(GLenum internalFormat,GLenum type)1185 void FramebufferTestWithFormatFallback::texImageFollowedByFBORead(GLenum internalFormat,
1186 GLenum type)
1187 {
1188 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1189 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1190 ASSERT_NE(-1, textureLocation);
1191 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1192 ASSERT_NE(-1, lodLocation);
1193
1194 const GLColor kColor = GLColor::blue;
1195
1196 for (int loop = 0; loop < 4; loop++)
1197 {
1198 GLTexture texture;
1199 glBindTexture(GL_TEXTURE_2D, texture);
1200 const GLushort u16Color = convertGLColorToUShort(internalFormat, kColor);
1201 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1202 if (loop == 0 || loop == 2)
1203 {
1204 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1205 pixels.data());
1206 }
1207 else
1208 {
1209 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kTexWidth, kTexHeight);
1210 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, type,
1211 pixels.data());
1212 }
1213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1215
1216 if (loop >= 2)
1217 {
1218 // Draw quad using texture
1219 glUseProgram(program);
1220 glActiveTexture(GL_TEXTURE0);
1221 glBindTexture(GL_TEXTURE_2D, texture);
1222 glClearColor(0, 0, 0, 1);
1223 glClear(GL_COLOR_BUFFER_BIT);
1224 glUniform1f(lodLocation, 0);
1225 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1226 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
1227 ASSERT_GL_NO_ERROR();
1228 }
1229
1230 // attach blue texture to FBO
1231 GLFramebuffer fbo;
1232 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1233 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1234 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1235 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, kColor.R, kColor.G, kColor.B, kColor.A);
1236 ASSERT_GL_NO_ERROR();
1237 }
1238 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_TexImage)1239 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_TexImage)
1240 {
1241 texImageFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1242 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_TexImage)1243 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_TexImage)
1244 {
1245 texImageFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1246 }
1247
1248 // Test texture format fallback while it has staged updates and then do copyTexImage2D and followed
1249 // by sampling.
copyTexImageFollowedBySampling(GLenum internalFormat,GLenum type)1250 void FramebufferTestWithFormatFallback::copyTexImageFollowedBySampling(GLenum internalFormat,
1251 GLenum type)
1252 {
1253 const GLColor kColor = GLColor::blue;
1254 // Create blue texture
1255 GLTexture blueTex2D;
1256 glBindTexture(GL_TEXTURE_2D, blueTex2D);
1257 const GLushort u16Color = convertGLColorToUShort(internalFormat, kColor);
1258 std::vector<GLushort> bluePixels(kTexWidth * kTexHeight, u16Color);
1259 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1260 bluePixels.data());
1261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1263
1264 // attach blue texture to FBO and read back to verify. This should trigger format conversion
1265 GLFramebuffer blueFbo;
1266 glBindFramebuffer(GL_FRAMEBUFFER, blueFbo);
1267 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blueTex2D, 0);
1268 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1269 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 0, 0, 255, 255);
1270 ASSERT_GL_NO_ERROR();
1271
1272 // Create red texture
1273 GLTexture copyTex2D;
1274 glBindTexture(GL_TEXTURE_2D, copyTex2D);
1275 std::vector<GLushort> redPixels(kTexWidth * kTexHeight, 0xF801);
1276 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1277 redPixels.data());
1278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1280
1281 // CopyTexImage from blue to red
1282 glCopyTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 0, 0, kTexWidth, kTexHeight, 0);
1283 ASSERT_GL_NO_ERROR();
1284
1285 // Draw with copyTex2D
1286 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1287 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1288 glUseProgram(program);
1289 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1290 ASSERT_NE(-1, textureLocation);
1291 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1292 ASSERT_NE(-1, lodLocation);
1293 glActiveTexture(GL_TEXTURE0);
1294 glBindTexture(GL_TEXTURE_2D, copyTex2D);
1295 glClearColor(0, 1, 0, 1);
1296 glClear(GL_COLOR_BUFFER_BIT);
1297 glUniform1f(lodLocation, 0);
1298 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1299 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, kColor.R, kColor.G, kColor.B,
1300 kColor.A);
1301 ASSERT_GL_NO_ERROR();
1302 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_CopyTexImage)1303 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_CopyTexImage)
1304 {
1305 copyTexImageFollowedBySampling(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1306 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_CopyTexImage)1307 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_CopyTexImage)
1308 {
1309 copyTexImageFollowedBySampling(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1310 }
1311
1312 // Test texture format fallback while it has staged updates and then do FBO blit and followed by
1313 // copyTexImage2D.
blitCopyFollowedByFBORead(GLenum internalFormat,GLenum type)1314 void FramebufferTestWithFormatFallback::blitCopyFollowedByFBORead(GLenum internalFormat,
1315 GLenum type)
1316 {
1317 for (int loop = 0; loop < 2; loop++)
1318 {
1319 // Create blue texture
1320 GLTexture blueTex2D;
1321 glBindTexture(GL_TEXTURE_2D, blueTex2D);
1322 GLushort u16Color = convertGLColorToUShort(internalFormat, GLColor::blue);
1323 std::vector<GLushort> bluePixels(kTexWidth * kTexHeight, u16Color);
1324 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1325 bluePixels.data());
1326 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1328
1329 // attach blue texture to FBO
1330 GLFramebuffer readFbo;
1331 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1332 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blueTex2D,
1333 0);
1334 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1335
1336 GLTexture redTex2D;
1337 GLRenderbuffer renderBuffer;
1338 GLFramebuffer drawFbo;
1339 if (loop == 0)
1340 {
1341 glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
1342 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, kTexWidth, kTexHeight);
1343
1344 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
1345 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1346 renderBuffer);
1347 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1348 glClearColor(1.0, 0.0, 0.0, 1.0);
1349 glClear(GL_COLOR_BUFFER_BIT);
1350 }
1351 else
1352 {
1353 glBindTexture(GL_TEXTURE_2D, redTex2D);
1354 u16Color = convertGLColorToUShort(internalFormat, GLColor::red);
1355 std::vector<GLushort> redPixels(kTexWidth * kTexHeight, u16Color);
1356 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1357 redPixels.data());
1358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1359 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1360
1361 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
1362 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1363 redTex2D, 0);
1364 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1365 }
1366
1367 // Blit
1368 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1369 glBlitFramebuffer(0, 0, kTexWidth, kTexHeight, 0, 0, kTexWidth, kTexHeight,
1370 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1371 ASSERT_GL_NO_ERROR();
1372
1373 GLFramebuffer readFbo2;
1374 if (loop == 0)
1375 {
1376 // CopyTexImage from renderBuffer to copyTex2D
1377 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo2);
1378 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1379 renderBuffer);
1380 }
1381 else
1382 {
1383
1384 // CopyTexImage from redTex2D to copyTex2D
1385 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo2);
1386 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1387 redTex2D, 0);
1388 }
1389 GLTexture copyTex2D;
1390 glBindTexture(GL_TEXTURE_2D, copyTex2D);
1391 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kTexWidth, kTexHeight, 0);
1392 ASSERT_GL_NO_ERROR();
1393 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1394 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1395 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1396 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1397 glBindTexture(GL_TEXTURE_2D, 0);
1398
1399 // Read out red texture
1400 GLFramebuffer readFbo3;
1401 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo3);
1402 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex2D,
1403 0);
1404 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1405 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 0, 0, 255, 255);
1406 ASSERT_GL_NO_ERROR();
1407 }
1408 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_BlitCopyTexImage)1409 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_BlitCopyTexImage)
1410 {
1411 blitCopyFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1412 }
TEST_P(FramebufferTestWithFormatFallback,RGBA4444_BlitCopyTexImage)1413 TEST_P(FramebufferTestWithFormatFallback, RGBA4444_BlitCopyTexImage)
1414 {
1415 blitCopyFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1416 }
1417
1418 // Test texture format fallback while it has staged updates, specially for cubemap target.
cubeTexImageFollowedByFBORead(GLenum internalFormat,GLenum type)1419 void FramebufferTestWithFormatFallback::cubeTexImageFollowedByFBORead(GLenum internalFormat,
1420 GLenum type)
1421 {
1422 const GLColor kColors[6] = {GLColor::red, GLColor::green, GLColor::blue,
1423 GLColor::cyan, GLColor::yellow, GLColor::magenta};
1424 GLTexture cubeTex2D;
1425 glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex2D);
1426 for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1427 target++)
1428 {
1429 int j = target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1430 const GLushort u16Color = convertGLColorToUShort(internalFormat, kColors[j]);
1431 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1432 glTexImage2D(target, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1433 pixels.data());
1434 }
1435 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1436 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1437
1438 // attach blue texture to FBO
1439 GLFramebuffer fbo;
1440 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1441 for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1442 target++)
1443 {
1444 GLint j = target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1445 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, cubeTex2D, 0);
1446 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1447 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, kColors[j].R, kColors[j].G, kColors[j].B,
1448 kColors[j].A);
1449 }
1450 ASSERT_GL_NO_ERROR();
1451 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_CubeTexImage)1452 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_CubeTexImage)
1453 {
1454 cubeTexImageFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1455 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_CubeTexImage)1456 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_CubeTexImage)
1457 {
1458 cubeTexImageFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1459 }
1460
1461 // Tests that the out-of-range staged update is reformated when mipmapping is enabled, but not
1462 // before it.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_OutOfRangeStagedUpdateReformated)1463 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_OutOfRangeStagedUpdateReformated)
1464 {
1465 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1466 glUseProgram(program);
1467 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1468 ASSERT_NE(-1, textureLocation);
1469 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1470 ASSERT_NE(-1, lodLocation);
1471
1472 GLTexture texture;
1473 glBindTexture(GL_TEXTURE_2D, texture);
1474 GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
1475 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1476 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1477 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1478 u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::green);
1479 pixels.assign(kTexWidth * kTexHeight, u16Color);
1480 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
1481 GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
1482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1483 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1484
1485 // Draw quad
1486 glActiveTexture(GL_TEXTURE0);
1487 glBindTexture(GL_TEXTURE_2D, texture);
1488 glUniform1f(lodLocation, 0);
1489 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1490 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1491
1492 // Now trigger format conversion
1493 GLFramebuffer readFbo;
1494 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1495 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1496 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1497 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowWidth() / 2, 255, 0, 0, 255);
1498
1499 // update level0 with compatible data and enable mipmap
1500 u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::blue);
1501 pixels.assign(kTexWidth * kTexHeight, u16Color);
1502 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1503 GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
1504 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1505 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1506 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
1507
1508 // Draw quad with lod0 and lod1 and verify color
1509 glUniform1f(lodLocation, 0);
1510 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1511 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
1512 glUniform1f(lodLocation, 1);
1513 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1514 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
1515 ASSERT_GL_NO_ERROR();
1516 }
1517
1518 // Tests that the texture is reformatted when the clear is done through the draw path.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_MaskedClear)1519 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_MaskedClear)
1520 {
1521 for (int loop = 0; loop < 2; loop++)
1522 {
1523 GLTexture texture;
1524 glBindTexture(GL_TEXTURE_2D, texture);
1525 GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
1526 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1527 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1528 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1529 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1531
1532 if (loop == 0)
1533 {
1534 // Draw quad
1535 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(),
1536 essl3_shaders::fs::Texture2DLod());
1537 glUseProgram(program);
1538 GLint textureLocation =
1539 glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1540 ASSERT_NE(-1, textureLocation);
1541 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1542 ASSERT_NE(-1, lodLocation);
1543 glActiveTexture(GL_TEXTURE0);
1544 glBindTexture(GL_TEXTURE_2D, texture);
1545 glClearColor(0, 0, 0, 1);
1546 glClear(GL_COLOR_BUFFER_BIT);
1547 glUniform1f(lodLocation, 0);
1548 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1549 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1550 ASSERT_GL_NO_ERROR();
1551 }
1552
1553 // Now trigger format conversion with masked clear
1554 GLFramebuffer fbo;
1555 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1556 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1557 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1558 glClearColor(0, 1, 1, 1);
1559 glColorMask(false, true, false, false);
1560 glClear(GL_COLOR_BUFFER_BIT);
1561 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 255, 255, 0, 255);
1562 ASSERT_GL_NO_ERROR();
1563 }
1564 }
1565
1566 // Tests that glGenerateMipmap works when the format is converted to renderable..
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_GenerateMipmap)1567 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_GenerateMipmap)
1568 {
1569 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1570 glUseProgram(program);
1571 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1572 ASSERT_NE(-1, textureLocation);
1573 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1574 ASSERT_NE(-1, lodLocation);
1575
1576 for (int loop = 0; loop < 4; loop++)
1577 {
1578 GLTexture texture;
1579 glBindTexture(GL_TEXTURE_2D, texture);
1580 GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
1581 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1582 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1583 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1584 u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::green);
1585 pixels.assign(kTexWidth * kTexHeight, u16Color);
1586 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
1587 GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
1588 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1589 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1590
1591 if (loop == 0 || loop == 2)
1592 {
1593 // Draw quad
1594 glUniform1f(lodLocation, 0);
1595 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1596 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1597 ASSERT_GL_NO_ERROR();
1598 }
1599
1600 if (loop > 2)
1601 {
1602 // Now trigger format conversion
1603 GLFramebuffer readFbo;
1604 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1605 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1606 texture, 0);
1607 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1608 }
1609
1610 // GenerateMipmap
1611 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1612 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1613 glGenerateMipmap(GL_TEXTURE_2D);
1614
1615 // Verify each lod
1616 for (int lod = 0; lod <= kMaxLevel; lod++)
1617 {
1618 glUniform1f(lodLocation, lod);
1619 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1620 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1621 }
1622 ASSERT_GL_NO_ERROR();
1623 }
1624 }
1625
1626 // Tests that when reformatting the image, incompatible updates don't cause a problem.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_InCompatibleFormat)1627 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_InCompatibleFormat)
1628 {
1629 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1630 glUseProgram(program);
1631 GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1632 ASSERT_NE(-1, textureLocation);
1633 GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1634 ASSERT_NE(-1, lodLocation);
1635
1636 for (int loop = 0; loop < 4; loop++)
1637 {
1638 GLTexture texture;
1639 glBindTexture(GL_TEXTURE_2D, texture);
1640 // Define a texture with lod0 and lod1 with two different effective internal formats or size
1641 GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
1642 std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1643 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1644 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1645 if (loop < 2)
1646 {
1647 u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::green);
1648 pixels.assign(kTexWidth * kTexHeight, u16Color);
1649 // bad effective internal format
1650 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
1651 GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
1652 }
1653 else
1654 {
1655 u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::green);
1656 pixels.assign(kTexWidth * kTexHeight, u16Color);
1657 // bad size
1658 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1659 GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1660 }
1661 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1662 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1663
1664 // Now trigger format conversion and verify lod0
1665 GLFramebuffer readFbo;
1666 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1667 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,
1668 0);
1669 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1670 EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 255, 0, 0, 255);
1671
1672 if (loop == 1 || loop == 3)
1673 {
1674 // Disable mipmap and sample from lod0 and verify
1675 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1676 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1677 glUniform1f(lodLocation, 0);
1678 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1679 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1680 }
1681 }
1682 }
1683
1684 class FramebufferTest_ES31 : public ANGLETest
1685 {
1686 protected:
validateSamplePass(GLuint & query,GLuint & passedCount,GLint width,GLint height)1687 void validateSamplePass(GLuint &query, GLuint &passedCount, GLint width, GLint height)
1688 {
1689 glUniform2i(0, width - 1, height - 1);
1690 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
1691 glDrawArrays(GL_TRIANGLES, 0, 6);
1692 glEndQuery(GL_ANY_SAMPLES_PASSED);
1693 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
1694 EXPECT_GT(static_cast<GLint>(passedCount), 0);
1695
1696 glUniform2i(0, width - 1, height);
1697 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
1698 glDrawArrays(GL_TRIANGLES, 0, 6);
1699 glEndQuery(GL_ANY_SAMPLES_PASSED);
1700 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
1701 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
1702
1703 glUniform2i(0, width, height - 1);
1704 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
1705 glDrawArrays(GL_TRIANGLES, 0, 6);
1706 glEndQuery(GL_ANY_SAMPLES_PASSED);
1707 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
1708 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
1709 }
1710
1711 static constexpr char kFSWriteRedGreen[] = R"(#extension GL_EXT_draw_buffers : enable
1712 precision highp float;
1713 void main()
1714 {
1715 gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0); // attachment 0: red
1716 gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0); // attachment 1: green
1717 })";
1718 };
1719
1720 // Until C++17, need to redundantly declare the constexpr array members outside the class.
1721 constexpr char FramebufferTest_ES31::kFSWriteRedGreen[];
1722
1723 // Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
1724 // FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
TEST_P(FramebufferTest_ES31,IncompleteMissingAttachmentDefaultParam)1725 TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
1726 {
1727 GLFramebuffer mFramebuffer;
1728 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1729
1730 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
1731 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
1732 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1733
1734 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
1735 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
1736 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1737 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1738
1739 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
1740 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
1741 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1742 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1743
1744 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
1745 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
1746 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1747 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1748
1749 ASSERT_GL_NO_ERROR();
1750 }
1751
1752 // Test that the sample count of a mix of texture and renderbuffer should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountMix)1753 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
1754 {
1755 GLFramebuffer mFramebuffer;
1756 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1757
1758 // Lookup the supported number of sample counts (rely on fact that ANGLE uses the same set of
1759 // sample counts for textures and renderbuffers)
1760 GLint numSampleCounts = 0;
1761 std::vector<GLint> sampleCounts;
1762 GLsizei queryBufferSize = 1;
1763 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
1764 queryBufferSize, &numSampleCounts);
1765 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
1766 sampleCounts.resize(numSampleCounts);
1767 queryBufferSize = numSampleCounts;
1768 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
1769 sampleCounts.data());
1770
1771 GLTexture mTexture;
1772 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
1773 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
1774
1775 GLRenderbuffer mRenderbuffer;
1776 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
1777 glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[1], GL_RGBA8, 1, 1);
1778 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1779 mTexture.get(), 0);
1780 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1781 mRenderbuffer.get());
1782 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1783 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1784
1785 ASSERT_GL_NO_ERROR();
1786 }
1787
1788 // Test that the sample count of texture attachments should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountTex)1789 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
1790 {
1791 GLFramebuffer mFramebuffer;
1792 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1793
1794 // Lookup the supported number of sample counts
1795 GLint numSampleCounts = 0;
1796 std::vector<GLint> sampleCounts;
1797 GLsizei queryBufferSize = 1;
1798 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
1799 queryBufferSize, &numSampleCounts);
1800 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
1801 sampleCounts.resize(numSampleCounts);
1802 queryBufferSize = numSampleCounts;
1803 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
1804 sampleCounts.data());
1805
1806 GLTexture mTextures[2];
1807 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
1808 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
1809 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
1810 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[1], GL_RGBA8, 1, 1, true);
1811 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1812 mTextures[0].get(), 0);
1813 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1814 mTextures[1].get(), 0);
1815 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1816 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1817
1818 ASSERT_GL_NO_ERROR();
1819 }
1820
1821 // Test that if the attached images are a mix of renderbuffers and textures, the value of
1822 // TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsMix)1823 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
1824 {
1825 GLFramebuffer mFramebuffer;
1826 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1827
1828 GLTexture mTexture;
1829 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
1830 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1831
1832 GLRenderbuffer mRenderbuffer;
1833 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
1834 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
1835 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1836 mTexture.get(), 0);
1837 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1838 mRenderbuffer.get());
1839 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1840 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1841
1842 ASSERT_GL_NO_ERROR();
1843 }
1844
1845 // Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsTex)1846 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
1847 {
1848 GLFramebuffer mFramebuffer;
1849 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1850
1851 GLTexture mTextures[2];
1852 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
1853 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1854 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1855 mTextures[0].get(), 0);
1856 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
1857 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
1858 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1859 mTextures[1].get(), 0);
1860 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1861 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1862
1863 ASSERT_GL_NO_ERROR();
1864 }
1865
1866 // Test resolving a multisampled texture with blit
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlit)1867 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlit)
1868 {
1869 constexpr int kSize = 16;
1870 glViewport(0, 0, kSize, kSize);
1871
1872 GLFramebuffer msaaFBO;
1873 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1874
1875 GLTexture texture;
1876 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1877 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1878 ASSERT_GL_NO_ERROR();
1879 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1880 texture.get(), 0);
1881 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1882
1883 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1884 essl31_shaders::fs::RedGreenGradient());
1885 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1886 ASSERT_GL_NO_ERROR();
1887
1888 // Create another FBO to resolve the multisample buffer into.
1889 GLTexture resolveTexture;
1890 GLFramebuffer resolveFBO;
1891 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1892 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1893 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1894 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1895 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1896
1897 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1898 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1899 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1900 ASSERT_GL_NO_ERROR();
1901
1902 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1903 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
1904 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1905 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1906 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
1907 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
1908 255, 1.0);
1909 }
1910
1911 // Test resolving a multisampled texture with blit to a different format
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitDifferentFormats)1912 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitDifferentFormats)
1913 {
1914 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888"));
1915
1916 constexpr int kSize = 16;
1917 glViewport(0, 0, kSize, kSize);
1918
1919 GLFramebuffer msaaFBO;
1920 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1921
1922 GLTexture texture;
1923 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1924 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1925 ASSERT_GL_NO_ERROR();
1926 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1927 texture.get(), 0);
1928 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1929
1930 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1931 essl31_shaders::fs::RedGreenGradient());
1932 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1933 ASSERT_GL_NO_ERROR();
1934
1935 // Create another FBO to resolve the multisample buffer into.
1936 GLTexture resolveTexture;
1937 GLFramebuffer resolveFBO;
1938 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1939 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA8_EXT, kSize, kSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1940 nullptr);
1941 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1942 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1943 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1944
1945 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1946 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1947 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1948 ASSERT_GL_NO_ERROR();
1949
1950 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1951 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
1952 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1953 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1954 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
1955 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
1956 255, 1.0);
1957 }
1958
1959 // Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitMultipleFBOs)1960 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleFBOs)
1961 {
1962 // FBO 1 -> multisample draw (red)
1963 // FBO 2 -> multisample draw (green)
1964 // Bind FBO 1 as read
1965 // Bind FBO 3 as draw
1966 // Resolve
1967
1968 constexpr int kSize = 16;
1969 glViewport(0, 0, kSize, kSize);
1970
1971 GLFramebuffer msaaFBORed;
1972 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed.get());
1973
1974 GLTexture textureRed;
1975 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed.get());
1976 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1977 ASSERT_GL_NO_ERROR();
1978 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1979 textureRed.get(), 0);
1980 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1981
1982 ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
1983 drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1984 ASSERT_GL_NO_ERROR();
1985
1986 GLFramebuffer msaaFBOGreen;
1987 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBOGreen.get());
1988
1989 GLTexture textureGreen;
1990 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureGreen.get());
1991 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1992 ASSERT_GL_NO_ERROR();
1993 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1994 textureGreen.get(), 0);
1995 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1996
1997 ANGLE_GL_PROGRAM(greenProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Green());
1998 drawQuad(greenProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1999 ASSERT_GL_NO_ERROR();
2000
2001 // Create another FBO to resolve the multisample buffer into.
2002 GLTexture resolveTexture;
2003 GLFramebuffer resolveFBO;
2004 glBindTexture(GL_TEXTURE_2D, resolveTexture);
2005 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2006 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2007 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2008 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2009
2010 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2011 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2012 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2013 ASSERT_GL_NO_ERROR();
2014
2015 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2016 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2017 }
2018
2019 // Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitMultipleResolves)2020 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleResolves)
2021 {
2022 // Draw multisampled in FBO 1
2023 // Bind FBO 1 as read
2024 // Bind FBO 2 as draw
2025 // Resolve
2026 // Bind FBO 3 as draw
2027 // Resolve
2028
2029 constexpr int kSize = 16;
2030 glViewport(0, 0, kSize, kSize);
2031
2032 GLFramebuffer msaaFBORed;
2033 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed.get());
2034
2035 GLTexture textureRed;
2036 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed.get());
2037 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2038 ASSERT_GL_NO_ERROR();
2039 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2040 textureRed.get(), 0);
2041 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2042
2043 ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
2044 drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2045 ASSERT_GL_NO_ERROR();
2046
2047 // Create another FBO to resolve the multisample buffer into.
2048 GLTexture resolveTexture1;
2049 GLFramebuffer resolveFBO1;
2050 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2051 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2052 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2053 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2054 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2055
2056 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2057 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2058 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2059 ASSERT_GL_NO_ERROR();
2060
2061 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2062 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2063
2064 // Create another FBO to resolve the multisample buffer into.
2065 GLTexture resolveTexture2;
2066 GLFramebuffer resolveFBO2;
2067 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2068 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2069 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
2070 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
2071 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2072
2073 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2074 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
2075 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2076 ASSERT_GL_NO_ERROR();
2077
2078 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
2079 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2080 }
2081
2082 // Test resolving a multisampled texture with blit into an FBO with different read and draw
2083 // attachments.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitDifferentReadDrawBuffers)2084 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitDifferentReadDrawBuffers)
2085 {
2086 constexpr int kSize = 16;
2087 glViewport(0, 0, kSize, kSize);
2088
2089 GLFramebuffer msaaFBO;
2090 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2091
2092 GLTexture texture;
2093 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2094 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2095 ASSERT_GL_NO_ERROR();
2096 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2097 texture.get(), 0);
2098 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2099
2100 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2101 essl31_shaders::fs::RedGreenGradient());
2102 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2103 ASSERT_GL_NO_ERROR();
2104
2105 // Create another FBO to resolve the multisample buffer into.
2106 GLFramebuffer resolveFBO;
2107 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2108
2109 // Bind both read and draw textures as separate attachments.
2110 const std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
2111 GLTexture resolveReadTexture;
2112 glBindTexture(GL_TEXTURE_2D, resolveReadTexture);
2113 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2114 blueColors.data());
2115 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveReadTexture,
2116 0);
2117 glReadBuffer(GL_COLOR_ATTACHMENT0);
2118 ASSERT_GL_NO_ERROR();
2119
2120 GLTexture resolveDrawTexture;
2121 glBindTexture(GL_TEXTURE_2D, resolveDrawTexture);
2122 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2123 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, resolveDrawTexture,
2124 0);
2125 // Only enable color attachment 1 to be drawn to, since the Vulkan back end (currently) only
2126 // supports using resolve attachments when there is a single draw attachment enabled. This
2127 // ensures that the read and draw images are treated separately, including their layouts.
2128 GLenum drawBuffers[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
2129 glDrawBuffers(2, drawBuffers);
2130 ASSERT_GL_NO_ERROR();
2131 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2132
2133 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2134 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2135 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2136 ASSERT_GL_NO_ERROR();
2137
2138 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2139 glReadBuffer(GL_COLOR_ATTACHMENT1);
2140 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2141 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2142 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2143 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2144 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2145 255, 1.0);
2146 }
2147
2148 // Test resolving a multisampled texture into a mipmaped texture with blit
TEST_P(FramebufferTest_ES31,MultisampleResolveIntoMipMapWithBlit)2149 TEST_P(FramebufferTest_ES31, MultisampleResolveIntoMipMapWithBlit)
2150 {
2151 // FBO 1 is attached to a 64x64 texture
2152 // FBO 2 attached to level 1 of a 128x128 texture
2153
2154 constexpr int kSize = 64;
2155 glViewport(0, 0, kSize, kSize);
2156
2157 // Create the textures early and call glGenerateMipmap() so it doesn't break the render pass
2158 // between the drawQuad() and glBlitFramebuffer(), so we can test the resolve with subpass path
2159 // in the Vulkan back end.
2160 GLTexture texture;
2161 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2162 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2163 ASSERT_GL_NO_ERROR();
2164
2165 GLTexture resolveTexture;
2166 glBindTexture(GL_TEXTURE_2D, resolveTexture);
2167 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
2169 ASSERT_GL_NO_ERROR();
2170
2171 GLFramebuffer msaaFBO;
2172 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2173 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2174 texture.get(), 0);
2175 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2176
2177 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2178 essl31_shaders::fs::RedGreenGradient());
2179 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2180 ASSERT_GL_NO_ERROR();
2181
2182 // Create another FBO to resolve the multisample buffer into.
2183 GLFramebuffer resolveFBO;
2184 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2185 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
2186 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2187
2188 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2189 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2190 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2191 ASSERT_GL_NO_ERROR();
2192
2193 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2194 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2195 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2196 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2197 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2198 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2199 255, 1.0);
2200 }
2201
2202 // Test resolving a multisampled texture with blit after drawing to multiple FBOs.
TEST_P(FramebufferTest_ES31,MultipleTextureMultisampleResolveWithBlitMultipleResolves)2203 TEST_P(FramebufferTest_ES31, MultipleTextureMultisampleResolveWithBlitMultipleResolves)
2204 {
2205 // Attach two MSAA textures to FBO1
2206 // Set read buffer 0
2207 // Resolve into FBO2
2208 // Set read buffer 1
2209 // Resolve into FBO3
2210
2211 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
2212
2213 constexpr int kSize = 16;
2214 glViewport(0, 0, kSize, kSize);
2215
2216 GLFramebuffer msaaFBO;
2217 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2218
2219 GLTexture msaaTextureRed;
2220 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
2221 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2222 ASSERT_GL_NO_ERROR();
2223 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2224 msaaTextureRed.get(), 0);
2225 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2226
2227 GLTexture msaaTextureGreen;
2228 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
2229 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2230 ASSERT_GL_NO_ERROR();
2231 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2232 msaaTextureGreen.get(), 0);
2233 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2234
2235 // Setup program to render red into attachment 0 and green into attachment 1.
2236 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
2237 glUseProgram(program);
2238 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
2239 glDrawBuffers(2, kDrawBuffers);
2240
2241 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2242 ASSERT_GL_NO_ERROR();
2243
2244 // Create another FBO to resolve the multisample buffer into.
2245 GLTexture resolveTexture1;
2246 GLFramebuffer resolveFBO1;
2247 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2248 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2249 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2250 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2251 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2252
2253 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2254 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2255 glReadBuffer(GL_COLOR_ATTACHMENT0); // Red
2256 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2257 ASSERT_GL_NO_ERROR();
2258
2259 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2260 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2261
2262 // Create another FBO to resolve the multisample buffer into.
2263 GLTexture resolveTexture2;
2264 GLFramebuffer resolveFBO2;
2265 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2266 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2267 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
2268 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
2269 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2270
2271 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2272 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
2273 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
2274 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2275 ASSERT_GL_NO_ERROR();
2276
2277 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
2278 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2279 }
2280
2281 // Test resolving a multisampled texture with blit after drawing to multiple FBOs, with color
2282 // attachment 1 resolved first.
TEST_P(FramebufferTest_ES31,MultipleTextureMultisampleResolveWithBlitMultipleResolvesAttachment1First)2283 TEST_P(FramebufferTest_ES31,
2284 MultipleTextureMultisampleResolveWithBlitMultipleResolvesAttachment1First)
2285 {
2286 // Attach two MSAA textures to FBO1
2287 // Set read buffer 1
2288 // Resolve into FBO2
2289 // Set read buffer 0
2290 // Resolve into FBO3
2291
2292 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
2293
2294 constexpr int kSize = 16;
2295 glViewport(0, 0, kSize, kSize);
2296
2297 GLFramebuffer msaaFBO;
2298 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2299
2300 GLTexture msaaTextureRed;
2301 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
2302 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2303 ASSERT_GL_NO_ERROR();
2304 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2305 msaaTextureRed.get(), 0);
2306 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2307
2308 GLTexture msaaTextureGreen;
2309 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
2310 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2311 ASSERT_GL_NO_ERROR();
2312 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2313 msaaTextureGreen.get(), 0);
2314 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2315
2316 // Setup program to render red into attachment 0 and green into attachment 1.
2317 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
2318 glUseProgram(program);
2319 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
2320 glDrawBuffers(2, kDrawBuffers);
2321
2322 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2323 ASSERT_GL_NO_ERROR();
2324
2325 // Create another FBO to resolve the multisample buffer into.
2326 GLTexture resolveTexture1;
2327 GLFramebuffer resolveFBO1;
2328 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2329 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2330 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2331 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2332 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2333
2334 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2335 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2336 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
2337 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2338 ASSERT_GL_NO_ERROR();
2339
2340 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2341 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2342
2343 // Create another FBO to resolve the multisample buffer into.
2344 GLTexture resolveTexture2;
2345 GLFramebuffer resolveFBO2;
2346 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2347 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2348 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
2349 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
2350 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2351
2352 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2353 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
2354 glReadBuffer(GL_COLOR_ATTACHMENT0); // Red
2355 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2356 ASSERT_GL_NO_ERROR();
2357
2358 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
2359 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2360 }
2361
2362 // Test resolving a multisampled texture with blit, then drawing multisampled again. The latter
2363 // should not get re-resolved automatically.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDraw)2364 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDraw)
2365 {
2366 constexpr int kSize = 16;
2367 glViewport(0, 0, kSize, kSize);
2368
2369 GLFramebuffer msaaFBO;
2370 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2371
2372 GLTexture texture;
2373 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2374 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2375 ASSERT_GL_NO_ERROR();
2376 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2377 texture.get(), 0);
2378 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2379
2380 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2381 essl31_shaders::fs::RedGreenGradient());
2382 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2383 ASSERT_GL_NO_ERROR();
2384
2385 // Create another FBO to resolve the multisample buffer into.
2386 GLTexture resolveTexture;
2387 GLFramebuffer resolveFBO;
2388 glBindTexture(GL_TEXTURE_2D, resolveTexture);
2389 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2390 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2391 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2392 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2393
2394 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2395 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2396 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2397 ASSERT_GL_NO_ERROR();
2398
2399 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2400 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2401 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2402 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2403 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2404 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2405 255, 1.0);
2406
2407 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
2408 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
2409 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2410 ASSERT_GL_NO_ERROR();
2411
2412 // The resolved FBO should be unaffected by the last draw call.
2413 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2414 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2415 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2416 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2417 255, 1.0);
2418 }
2419
2420 // Test resolving a multisampled texture with blit, then drawing multisampled again. The latter
2421 // should not get re-resolved automatically. Resoloves color attachment 1.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawAttachment1)2422 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawAttachment1)
2423 {
2424 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
2425
2426 constexpr int kSize = 16;
2427 glViewport(0, 0, kSize, kSize);
2428
2429 GLFramebuffer msaaFBO;
2430 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2431
2432 GLTexture msaaTextureRed;
2433 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
2434 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2435 ASSERT_GL_NO_ERROR();
2436 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2437 msaaTextureRed.get(), 0);
2438 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2439
2440 GLTexture msaaTextureGreen;
2441 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
2442 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2443 ASSERT_GL_NO_ERROR();
2444 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2445 msaaTextureGreen.get(), 0);
2446 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2447
2448 // Setup program to render red into attachment 0 and green into attachment 1.
2449 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
2450 glUseProgram(program);
2451 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
2452 glDrawBuffers(2, kDrawBuffers);
2453
2454 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2455 ASSERT_GL_NO_ERROR();
2456
2457 // Create another FBO to resolve the multisample buffer into.
2458 GLTexture resolveTexture;
2459 GLFramebuffer resolveFBO;
2460 glBindTexture(GL_TEXTURE_2D, resolveTexture);
2461 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2462 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2463 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2464 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2465
2466 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2467 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2468 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
2469 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2470 ASSERT_GL_NO_ERROR();
2471
2472 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2473 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2474 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
2475 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
2476 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
2477
2478 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
2479 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
2480 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2481 ASSERT_GL_NO_ERROR();
2482
2483 // The resolved FBO should be unaffected by the last draw call.
2484 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2485 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
2486 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
2487 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
2488 }
2489
2490 // Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
2491 // same framebuffer.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawThenResolveAgain)2492 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgain)
2493 {
2494 constexpr int kSize = 16;
2495 glViewport(0, 0, kSize, kSize);
2496
2497 GLFramebuffer msaaFBO;
2498 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2499
2500 GLTexture texture;
2501 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2502 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2503 ASSERT_GL_NO_ERROR();
2504 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2505 texture.get(), 0);
2506 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2507
2508 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2509 essl31_shaders::fs::RedGreenGradient());
2510 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2511 ASSERT_GL_NO_ERROR();
2512
2513 // Create another FBO to resolve the multisample buffer into.
2514 GLTexture resolveTexture;
2515 GLFramebuffer resolveFBO;
2516 glBindTexture(GL_TEXTURE_2D, resolveTexture);
2517 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2518 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2519 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2520 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2521
2522 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2523 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2524 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2525 ASSERT_GL_NO_ERROR();
2526
2527 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2528 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2529 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2530 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2531 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2532 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2533 255, 1.0);
2534
2535 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
2536 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
2537 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2538 ASSERT_GL_NO_ERROR();
2539
2540 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2541 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2542 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2543 ASSERT_GL_NO_ERROR();
2544
2545 // Verify that the resolve happened correctly
2546 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2547 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2548 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
2549 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
2550 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
2551 }
2552
2553 // Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
2554 // another framebuffer.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawThenResolveAgainToDifferentFBO)2555 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgainToDifferentFBO)
2556 {
2557 constexpr int kSize = 16;
2558 glViewport(0, 0, kSize, kSize);
2559
2560 GLFramebuffer msaaFBO;
2561 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2562
2563 GLTexture texture;
2564 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2565 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2566 ASSERT_GL_NO_ERROR();
2567 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2568 texture.get(), 0);
2569 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2570
2571 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2572 essl31_shaders::fs::RedGreenGradient());
2573 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2574 ASSERT_GL_NO_ERROR();
2575
2576 // Create another FBO to resolve the multisample buffer into.
2577 GLTexture resolveTexture1;
2578 GLFramebuffer resolveFBO1;
2579 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2580 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2581 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2582 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2583 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2584
2585 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2586 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2587 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2588 ASSERT_GL_NO_ERROR();
2589
2590 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2591 constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2592 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2593 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2594 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2595 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2596 255, 1.0);
2597
2598 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
2599 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
2600 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2601 ASSERT_GL_NO_ERROR();
2602
2603 // Create another FBO to resolve the multisample buffer into.
2604 GLTexture resolveTexture2;
2605 GLFramebuffer resolveFBO2;
2606 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2607 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2608 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
2609 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
2610 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2611
2612 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2613 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
2614 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2615 ASSERT_GL_NO_ERROR();
2616
2617 // Verify that the resolve happened to the correct FBO
2618 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
2619 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2620 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
2621 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
2622 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
2623
2624 // The first resolve FBO should be untouched.
2625 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2626 EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2627 EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2628 EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2629 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2630 255, 1.0);
2631 }
2632
2633 // If there are no attachments, rendering will be limited to a rectangle having a lower left of
2634 // (0, 0) and an upper right of(width, height), where width and height are the framebuffer
2635 // object's default width and height.
TEST_P(FramebufferTest_ES31,RenderingLimitToDefaultFBOSizeWithNoAttachments)2636 TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttachments)
2637 {
2638 // anglebug.com/2253
2639 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
2640 // Occlusion query reports fragments outside the render area are still rendered
2641 ANGLE_SKIP_TEST_IF(IsAndroid() || (IsWindows() && (IsIntel() || IsAMD())));
2642
2643 constexpr char kVS1[] = R"(#version 310 es
2644 in layout(location = 0) highp vec2 a_position;
2645 void main()
2646 {
2647 gl_Position = vec4(a_position, 0.0, 1.0);
2648 })";
2649
2650 constexpr char kFS1[] = R"(#version 310 es
2651 uniform layout(location = 0) highp ivec2 u_expectedSize;
2652 out layout(location = 3) mediump vec4 f_color;
2653 void main()
2654 {
2655 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
2656 f_color = vec4(1.0, 0.5, 0.25, 1.0);
2657 })";
2658
2659 constexpr char kVS2[] = R"(#version 310 es
2660 in layout(location = 0) highp vec2 a_position;
2661 void main()
2662 {
2663 gl_Position = vec4(a_position, 0.0, 1.0);
2664 })";
2665
2666 constexpr char kFS2[] = R"(#version 310 es
2667 uniform layout(location = 0) highp ivec2 u_expectedSize;
2668 out layout(location = 2) mediump vec4 f_color;
2669 void main()
2670 {
2671 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
2672 f_color = vec4(1.0, 0.5, 0.25, 1.0);
2673 })";
2674
2675 ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
2676 ANGLE_GL_PROGRAM(program2, kVS2, kFS2);
2677
2678 glUseProgram(program1);
2679
2680 GLFramebuffer mFramebuffer;
2681 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
2682 GLuint defaultWidth = 1;
2683 GLuint defaultHeight = 1;
2684
2685 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
2686 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
2687 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2688
2689 const float data[] = {
2690 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
2691 };
2692
2693 GLuint vertexArray = 0;
2694 GLuint vertexBuffer = 0;
2695 GLuint query = 0;
2696 GLuint passedCount = 0;
2697
2698 glGenQueries(1, &query);
2699 glGenVertexArrays(1, &vertexArray);
2700 glBindVertexArray(vertexArray);
2701
2702 glGenBuffers(1, &vertexBuffer);
2703 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2704 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2705
2706 glEnableVertexAttribArray(0);
2707 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
2708 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2709
2710 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
2711
2712 glUseProgram(program2);
2713 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
2714
2715 glUseProgram(program1);
2716 // If fbo has attachments, the rendering size should be the same as its attachment.
2717 GLTexture mTexture;
2718 GLuint width = 2;
2719 GLuint height = 2;
2720 glBindTexture(GL_TEXTURE_2D, mTexture.get());
2721 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2722
2723 const GLenum bufs[] = {GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
2724
2725 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTexture.get(),
2726 0);
2727 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2728 glDrawBuffers(4, bufs);
2729
2730 validateSamplePass(query, passedCount, width, height);
2731
2732 // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
2733 // default size.
2734 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, 0, 0);
2735 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2736
2737 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
2738
2739 glDisableVertexAttribArray(0);
2740 glBindBuffer(GL_ARRAY_BUFFER, 0);
2741 glBindVertexArray(0);
2742 glDeleteBuffers(1, &vertexBuffer);
2743 glDeleteVertexArrays(1, &vertexArray);
2744
2745 ASSERT_GL_NO_ERROR();
2746 }
2747
2748 class AddMockTextureNoRenderTargetTest : public ANGLETest
2749 {
2750 public:
AddMockTextureNoRenderTargetTest()2751 AddMockTextureNoRenderTargetTest()
2752 {
2753 setWindowWidth(512);
2754 setWindowHeight(512);
2755 setConfigRedBits(8);
2756 setConfigGreenBits(8);
2757 setConfigBlueBits(8);
2758 setConfigAlphaBits(8);
2759 }
2760
overrideWorkaroundsD3D(FeaturesD3D * features)2761 void overrideWorkaroundsD3D(FeaturesD3D *features) override
2762 {
2763 features->overrideFeatures({"add_mock_texture_no_render_target"}, true);
2764 }
2765 };
2766
2767 // Test to verify workaround succeeds when no program outputs exist http://anglebug.com/2283
TEST_P(AddMockTextureNoRenderTargetTest,NoProgramOutputWorkaround)2768 TEST_P(AddMockTextureNoRenderTargetTest, NoProgramOutputWorkaround)
2769 {
2770 constexpr char kVS[] = "void main() {}";
2771 constexpr char kFS[] = "void main() {}";
2772
2773 ANGLE_GL_PROGRAM(drawProgram, kVS, kFS);
2774
2775 glUseProgram(drawProgram);
2776
2777 glDrawArrays(GL_TRIANGLES, 0, 6);
2778
2779 ASSERT_GL_NO_ERROR();
2780 }
2781
2782 // Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
2783 // calls to DrawBuffers.
TEST_P(FramebufferTest_ES3,AttachmentStateChange)2784 TEST_P(FramebufferTest_ES3, AttachmentStateChange)
2785 {
2786 constexpr GLuint kSize = 2;
2787
2788 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2789
2790 GLTexture colorTexture;
2791 glBindTexture(GL_TEXTURE_2D, colorTexture);
2792 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2793
2794 GLFramebuffer fbo;
2795 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2796 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2797
2798 ASSERT_GL_NO_ERROR();
2799 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2800
2801 // First draw without a depth buffer.
2802 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2803
2804 GLRenderbuffer depthBuffer;
2805 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
2806 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
2807
2808 // Bind just a renderbuffer and draw.
2809 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
2810
2811 ASSERT_GL_NO_ERROR();
2812 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2813
2814 glDrawBuffers(0, nullptr);
2815 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2816
2817 // Re-enable color buffer and draw one final time. This previously triggered a crash.
2818 GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
2819 glDrawBuffers(1, &drawBuffs);
2820
2821 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2822 ASSERT_GL_NO_ERROR();
2823 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2824 }
2825
2826 // Tests that we can support a feedback loop between a depth textures and the depth buffer.
2827 // The test emulates the read-only feedback loop in Manhattan.
TEST_P(FramebufferTest_ES3,ReadOnlyDepthFeedbackLoopSupported)2828 TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopSupported)
2829 {
2830 // Feedback loops are only supported on Vulkan.
2831 // TODO(jmadill): Make GL extension. http://anglebug.com/4969
2832 ANGLE_SKIP_TEST_IF(!IsVulkan());
2833
2834 constexpr GLuint kSize = 2;
2835 glViewport(0, 0, kSize, kSize);
2836
2837 constexpr char kFS[] = R"(precision mediump float;
2838 varying vec2 v_texCoord;
2839 uniform sampler2D depth;
2840 void main()
2841 {
2842 if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
2843 {
2844 gl_FragColor = vec4(0, 1, 0, 1);
2845 }
2846 else
2847 {
2848 gl_FragColor = vec4(1, 0, 0, 1);
2849 }
2850 })";
2851
2852 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
2853
2854 GLFramebuffer framebuffer;
2855 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
2856
2857 GLTexture colorTexture;
2858 glBindTexture(GL_TEXTURE_2D, colorTexture);
2859 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2860
2861 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2862 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2863 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2864
2865 GLTexture depthTexture;
2866 glBindTexture(GL_TEXTURE_2D, depthTexture);
2867 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
2868 GL_UNSIGNED_INT, nullptr);
2869 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2870 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2871 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2872
2873 ASSERT_GL_NO_ERROR();
2874 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2875
2876 // Clear depth to 0.5.
2877 glClearDepthf(0.5f);
2878 glClear(GL_DEPTH_BUFFER_BIT);
2879
2880 // Disable depth. Although this does not remove the feedback loop as defined by the
2881 // spec it mimics what gfxbench does in its rendering tests.
2882 glDepthMask(false);
2883 glDisable(GL_DEPTH_TEST);
2884
2885 // Verify we can sample the depth texture and get 0.5.
2886 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
2887
2888 ASSERT_GL_NO_ERROR();
2889 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2890 }
2891
2892 // Tests corner cases with read-only depth-stencil feedback loops.
TEST_P(FramebufferTest_ES3,ReadOnlyDepthFeedbackLoopStateChanges)2893 TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopStateChanges)
2894 {
2895 // Feedback loops are only supported on Vulkan.
2896 // TODO(jmadill): Make GL extension. http://anglebug.com/4969
2897 ANGLE_SKIP_TEST_IF(!IsVulkan());
2898
2899 constexpr GLuint kSize = 2;
2900 glViewport(0, 0, kSize, kSize);
2901
2902 constexpr char kFS[] = R"(precision mediump float;
2903 varying vec2 v_texCoord;
2904 uniform sampler2D depth;
2905 void main()
2906 {
2907 if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
2908 {
2909 gl_FragColor = vec4(0, 1, 0, 1);
2910 }
2911 else
2912 {
2913 gl_FragColor = vec4(1, 0, 0, 1);
2914 }
2915 })";
2916
2917 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
2918 glUseProgram(program);
2919
2920 setupQuadVertexBuffer(0.5f, 1.0f);
2921 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
2922 glEnableVertexAttribArray(0);
2923
2924 GLFramebuffer framebuffer1;
2925 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
2926
2927 GLTexture colorTexture;
2928 glBindTexture(GL_TEXTURE_2D, colorTexture);
2929 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2930
2931 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2932 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2933 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2934
2935 GLTexture depthTexture;
2936 glBindTexture(GL_TEXTURE_2D, depthTexture);
2937 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
2938 GL_UNSIGNED_INT, nullptr);
2939 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2940 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2941 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2942 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2943
2944 GLFramebuffer framebuffer2;
2945 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
2946 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2947 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2948
2949 ASSERT_GL_NO_ERROR();
2950
2951 // Clear depth to 0.5.
2952 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
2953 glClearDepthf(0.5f);
2954 glClear(GL_DEPTH_BUFFER_BIT);
2955 glFlush();
2956
2957 // Disable depth. Although this does not remove the feedback loop as defined by the
2958 // spec it mimics what gfxbench does in its rendering tests.
2959 glDepthMask(false);
2960 glDisable(GL_DEPTH_TEST);
2961
2962 // Draw with loop.
2963 glDrawArrays(GL_TRIANGLES, 0, 6);
2964 ASSERT_GL_NO_ERROR();
2965
2966 // Draw with no loop and second FBO. Starts RP in writable mode.
2967 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
2968 glBindTexture(GL_TEXTURE_2D, 0);
2969 glDrawArrays(GL_TRIANGLES, 0, 6);
2970 ASSERT_GL_NO_ERROR();
2971
2972 // Draw with loop, restarts RP.
2973 glBindTexture(GL_TEXTURE_2D, depthTexture);
2974 glDrawArrays(GL_TRIANGLES, 0, 6);
2975 ASSERT_GL_NO_ERROR();
2976 }
2977
2978 // Tests that if the framebuffer is cleared, a feedback loop between a depth textures and the depth
2979 // buffer is established, and a scissored clear is issued, that the clear is not mistakenly
2980 // scissored.
TEST_P(FramebufferTest_ES3,ReadOnlyDepthFeedbackLoopWithClearAndScissoredDraw)2981 TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopWithClearAndScissoredDraw)
2982 {
2983 // Feedback loops are only supported on Vulkan.
2984 // TODO(jmadill): Make GL extension. http://anglebug.com/4969
2985 ANGLE_SKIP_TEST_IF(!IsVulkan());
2986
2987 constexpr GLuint kSize = 16;
2988 glViewport(0, 0, kSize, kSize);
2989
2990 constexpr char kFS[] = R"(precision mediump float;
2991 varying vec2 v_texCoord;
2992 uniform sampler2D depth;
2993 void main()
2994 {
2995 if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
2996 {
2997 gl_FragColor = vec4(0, 1, 0, 1);
2998 }
2999 else
3000 {
3001 gl_FragColor = vec4(1, 0, 0, 1);
3002 }
3003 })";
3004
3005 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
3006
3007 GLFramebuffer framebuffer;
3008 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3009
3010 GLTexture colorTexture;
3011 glBindTexture(GL_TEXTURE_2D, colorTexture);
3012 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3013
3014 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3015 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3016 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3017
3018 GLTexture depthTexture;
3019 glBindTexture(GL_TEXTURE_2D, depthTexture);
3020 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
3021 GL_UNSIGNED_INT, nullptr);
3022 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3023 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3024 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
3025
3026 ASSERT_GL_NO_ERROR();
3027 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3028
3029 // Clear color to blue and depth to 0.5.
3030 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
3031 glClearDepthf(0.5f);
3032 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3033
3034 // Disable depth. Although this does not remove the feedback loop as defined by the
3035 // spec it mimics what gfxbench does in its rendering tests.
3036 glDepthMask(false);
3037 glDisable(GL_DEPTH_TEST);
3038
3039 // Verify we can sample the depth texture and get 0.5. Use a scissor.
3040 glScissor(0, 0, kSize / 2, kSize);
3041 glEnable(GL_SCISSOR_TEST);
3042 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3043 ASSERT_GL_NO_ERROR();
3044
3045 // Make sure the scissored region passes the depth test and is changed to green.
3046 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3047 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
3048 EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, 0, GLColor::green);
3049 EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, kSize - 1, GLColor::green);
3050
3051 // Make sure the region outside the scissor is cleared to blue.
3052 EXPECT_PIXEL_COLOR_EQ(kSize / 2, 0, GLColor::blue);
3053 EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize - 1, GLColor::blue);
3054 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
3055 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
3056 }
3057
3058 // Tests that we can support a color texture also attached to the color attachment but
3059 // with different LOD. From GLES3.0 spec section 4.4.3.2, if min_filter is GL_NEAREST_MIPMAP_NEAREST
3060 // and the lod is within the [base_level, max_level] range, and it is possible to sample from a LOD
3061 // that is rendering to then it does form a feedback loop. But if it is using textureLOD to
3062 // explicitly fetching texture on different LOD, there is no loop and should still work. Aztec_ruins
3063 // (https://issuetracker.google.com/175584609) is doing exactly this.
TEST_P(FramebufferTest_ES3,SampleFromAttachedTextureWithDifferentLOD)3064 TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLOD)
3065 {
3066 // TODO: https://anglebug.com/5760
3067 ANGLE_SKIP_TEST_IF(IsD3D());
3068
3069 constexpr GLuint kLevel0Size = 4;
3070 constexpr GLuint kLevel1Size = kLevel0Size / 2;
3071 constexpr GLuint kLevel2Size = kLevel1Size / 2;
3072 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3073
3074 GLTexture colorTexture;
3075 glBindTexture(GL_TEXTURE_2D, colorTexture);
3076 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3077 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3078 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
3079 gData.fill(GLColor::red);
3080 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
3081 gData.data());
3082 gData.fill(GLColor::green);
3083 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
3084 gData.data());
3085 gData.fill(GLColor::blue);
3086 glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, kLevel2Size, kLevel2Size, GL_RGBA, GL_UNSIGNED_BYTE,
3087 gData.data());
3088
3089 // Attach level 1 to a FBO
3090 GLFramebuffer framebuffer;
3091 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3092 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3093 ASSERT_GL_NO_ERROR();
3094 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3095
3096 // Render to FBO with color texture level 1 and textureLod from level 0.
3097 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3098 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3099 glViewport(0, 0, kLevel1Size, kLevel1Size);
3100 glScissor(0, 0, kLevel1Size, kLevel1Size);
3101 glEnable(GL_CULL_FACE);
3102 glCullFace(GL_BACK);
3103 glDisable(GL_BLEND);
3104 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3105 glActiveTexture(GL_TEXTURE0);
3106 glBindTexture(GL_TEXTURE_2D, colorTexture);
3107
3108 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
3109 glUseProgram(program);
3110 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
3111 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
3112 ASSERT_NE(-1, textureLoc);
3113 ASSERT_NE(-1, lodLoc);
3114 glUniform1i(textureLoc, 0); // texture unit 0
3115 glUniform1f(lodLoc, 0); // with Lod=0
3116 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3117
3118 glDisable(GL_CULL_FACE);
3119 glDisable(GL_DEPTH_TEST);
3120 glDisable(GL_BLEND);
3121 glDisable(GL_SCISSOR_TEST);
3122 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3123
3124 ASSERT_GL_NO_ERROR();
3125 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3126 }
3127
3128 // This extends the test SampleFromAttachedTextureWithDifferentLOD by creating two renderpasses
3129 // without changing texture binding. This is to make sure that sample/render to the same texture
3130 // still function properly when transition from one renderpass to another without texture binding
3131 // change.
TEST_P(FramebufferTest_ES3,SampleFromAttachedTextureWithDifferentLODAndFBOSwitch)3132 TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLODAndFBOSwitch)
3133 {
3134 // TODO: https://anglebug.com/5760
3135 ANGLE_SKIP_TEST_IF(IsD3D());
3136
3137 constexpr GLuint kLevel0Size = 4;
3138 constexpr GLuint kLevel1Size = kLevel0Size / 2;
3139 constexpr GLuint kLevel2Size = kLevel1Size / 2;
3140 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3141
3142 GLTexture colorTexture;
3143 glBindTexture(GL_TEXTURE_2D, colorTexture);
3144 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3145 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3146 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
3147 gData.fill(GLColor::red);
3148 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
3149 gData.data());
3150 gData.fill(GLColor::green);
3151 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
3152 gData.data());
3153 gData.fill(GLColor::blue);
3154 glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, kLevel2Size, kLevel2Size, GL_RGBA, GL_UNSIGNED_BYTE,
3155 gData.data());
3156
3157 // Attach level 1 to two FBOs
3158 GLFramebuffer framebuffer1;
3159 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3160 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3161 ASSERT_GL_NO_ERROR();
3162 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3163 GLFramebuffer framebuffer2;
3164 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3165 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3166 ASSERT_GL_NO_ERROR();
3167 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3168
3169 // Render to left half of FBO1 and textureLod from level 0.
3170 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3171 glViewport(0, 0, kLevel1Size / 2, kLevel1Size);
3172 glScissor(0, 0, kLevel1Size / 2, kLevel1Size);
3173 glActiveTexture(GL_TEXTURE0);
3174 glBindTexture(GL_TEXTURE_2D, colorTexture);
3175 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
3176 glUseProgram(program);
3177 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
3178 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
3179 ASSERT_NE(-1, textureLoc);
3180 ASSERT_NE(-1, lodLoc);
3181 glUniform1i(textureLoc, 0); // texture unit 0
3182 glUniform1f(lodLoc, 0); // with Lod=0
3183 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3184 ASSERT_GL_NO_ERROR();
3185
3186 // Render to right half of FBO2 and textureLod from level 0 without trigger texture binding
3187 // change.
3188 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3189 glViewport(kLevel1Size / 2, 0, kLevel1Size / 2, kLevel1Size);
3190 glScissor(kLevel1Size / 2, 0, kLevel1Size / 2, kLevel1Size);
3191 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3192 ASSERT_GL_NO_ERROR();
3193 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3194 EXPECT_PIXEL_COLOR_EQ(kLevel1Size - 1, 0, GLColor::red);
3195 }
3196
3197 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
3198 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
3199 // texture itself has not been initialized with any data before rendering (TexSubImage call may
3200 // initialize a VkImage object).
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithBeyondMaxLevel)3201 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBeyondMaxLevel)
3202 {
3203 constexpr GLuint kLevel0Size = 4;
3204 constexpr GLuint kLevel1Size = kLevel0Size / 2;
3205
3206 GLTexture colorTexture;
3207 glBindTexture(GL_TEXTURE_2D, colorTexture);
3208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3210 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
3211 // set max_level to 0
3212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3213
3214 // Attach level 1 to a FBO
3215 GLFramebuffer framebuffer;
3216 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3217 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3218 ASSERT_GL_NO_ERROR();
3219 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3220
3221 // Render to FBO
3222 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3223 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3224 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3225 glViewport(0, 0, kLevel1Size, kLevel1Size);
3226 glScissor(0, 0, kLevel1Size, kLevel1Size);
3227 glEnable(GL_CULL_FACE);
3228 glCullFace(GL_BACK);
3229 glDisable(GL_BLEND);
3230 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3231 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
3232 glUseProgram(program);
3233 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3234
3235 glDisable(GL_CULL_FACE);
3236 glDisable(GL_DEPTH_TEST);
3237 glDisable(GL_BLEND);
3238 glDisable(GL_SCISSOR_TEST);
3239 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3240
3241 ASSERT_GL_NO_ERROR();
3242 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3243 }
3244
3245 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
3246 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
3247 // texture itself has been initialized with data before rendering.
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithSubImageWithBeyondMaxLevel)3248 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithSubImageWithBeyondMaxLevel)
3249 {
3250 constexpr GLuint kLevel0Size = 4;
3251 constexpr GLuint kLevel1Size = kLevel0Size / 2;
3252 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3253
3254 GLTexture colorTexture;
3255 glBindTexture(GL_TEXTURE_2D, colorTexture);
3256 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3257 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3258 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
3259 // set max_level to 0
3260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3261 // Initialize with TexSubImage call
3262 gData.fill(GLColor::blue);
3263 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
3264 gData.data());
3265
3266 // Attach level 1 to a FBO
3267 GLFramebuffer framebuffer;
3268 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3269 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3270 ASSERT_GL_NO_ERROR();
3271 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3272
3273 // Render to FBO
3274 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3275 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3276 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3277 glViewport(0, 0, kLevel1Size, kLevel1Size);
3278 glScissor(0, 0, kLevel1Size, kLevel1Size);
3279 glEnable(GL_CULL_FACE);
3280 glCullFace(GL_BACK);
3281 glDisable(GL_BLEND);
3282 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3283 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
3284 glUseProgram(program);
3285 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3286
3287 glDisable(GL_CULL_FACE);
3288 glDisable(GL_DEPTH_TEST);
3289 glDisable(GL_BLEND);
3290 glDisable(GL_SCISSOR_TEST);
3291 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3292
3293 ASSERT_GL_NO_ERROR();
3294 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3295 }
3296
3297 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
3298 // renders to an immutable texture at the level that is smaller than GL_TEXTURE_BASE_LEVEL. The
3299 // texture itself has been initialized with data before rendering. Filament is using it this way
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithBellowBaseLevelLOD)3300 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBellowBaseLevelLOD)
3301 {
3302 constexpr GLuint kLevel0Size = 4;
3303 constexpr GLuint kLevel1Size = kLevel0Size / 2;
3304 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3305
3306 GLTexture colorTexture;
3307 glBindTexture(GL_TEXTURE_2D, colorTexture);
3308 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3310 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
3311 // set base_level to 1
3312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
3313 gData.fill(GLColor::blue);
3314 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
3315 gData.data());
3316
3317 // Attach level 0 to a FBO
3318 GLFramebuffer framebuffer;
3319 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3320 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3321 ASSERT_GL_NO_ERROR();
3322 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3323
3324 // Render to FBO
3325 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3326 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3327 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3328 glViewport(0, 0, kLevel0Size, kLevel0Size);
3329 glScissor(0, 0, kLevel0Size, kLevel0Size);
3330 glEnable(GL_CULL_FACE);
3331 glCullFace(GL_BACK);
3332 glDisable(GL_BLEND);
3333 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3334 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
3335 glUseProgram(program);
3336 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3337
3338 glDisable(GL_CULL_FACE);
3339 glDisable(GL_DEPTH_TEST);
3340 glDisable(GL_BLEND);
3341 glDisable(GL_SCISSOR_TEST);
3342 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3343
3344 ASSERT_GL_NO_ERROR();
3345 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3346 }
3347
3348 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
3349 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
3350 // texture level that we render to has been initialized with data before rendering. This test if
3351 // render to that level will get flush the level update even though it is outside [base, max]
3352 // levels.
TEST_P(FramebufferTest_ES3,RenderImmutableTextureWithSubImageWithBeyondMaxLevel)3353 TEST_P(FramebufferTest_ES3, RenderImmutableTextureWithSubImageWithBeyondMaxLevel)
3354 {
3355 // Set up program to sample from specific lod level.
3356 GLProgram textureLodProgram;
3357 textureLodProgram.makeRaster(essl3_shaders::vs::Texture2DLod(),
3358 essl3_shaders::fs::Texture2DLod());
3359 ASSERT(textureLodProgram.valid());
3360 glUseProgram(textureLodProgram);
3361
3362 GLint textureLocation =
3363 glGetUniformLocation(textureLodProgram, essl3_shaders::Texture2DUniform());
3364 ASSERT_NE(-1, textureLocation);
3365 GLint lodLocation = glGetUniformLocation(textureLodProgram, essl3_shaders::LodUniform());
3366 ASSERT_NE(-1, lodLocation);
3367
3368 constexpr GLuint kLevel0Size = 4;
3369 constexpr GLuint kLevel1Size = kLevel0Size / 2;
3370 std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3371
3372 GLTexture colorTexture;
3373 glBindTexture(GL_TEXTURE_2D, colorTexture);
3374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3376 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
3377 // Initialize level 0 with blue
3378 gData.fill(GLColor::blue);
3379 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
3380 gData.data());
3381 // set max_level to 0
3382 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3383 // Draw with level 0
3384 glUniform1f(lodLocation, 0);
3385 drawQuad(textureLodProgram, essl3_shaders::PositionAttrib(), 0.5f);
3386 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3387
3388 // Initalize level 1 with green
3389 gData.fill(GLColor::green);
3390 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
3391 gData.data());
3392 // Attach level 1 to a FBO
3393 GLFramebuffer framebuffer;
3394 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3395 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3396 ASSERT_GL_NO_ERROR();
3397 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3398 // Render to FBO (i.e. level 1) with Red and blend with existing texture level data
3399 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3400 glViewport(0, 0, kLevel1Size, kLevel1Size);
3401 glScissor(0, 0, kLevel1Size, kLevel1Size);
3402 glEnable(GL_CULL_FACE);
3403 glCullFace(GL_BACK);
3404 glEnable(GL_BLEND);
3405 glBlendFunc(GL_ONE, GL_ONE);
3406 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3407 ANGLE_GL_PROGRAM(redProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
3408 glUseProgram(redProgram);
3409 drawQuad(redProgram, essl3_shaders::PositionAttrib(), 0.5f);
3410
3411 glDisable(GL_CULL_FACE);
3412 glDisable(GL_DEPTH_TEST);
3413 glDisable(GL_BLEND);
3414 glDisable(GL_SCISSOR_TEST);
3415 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3416
3417 ASSERT_GL_NO_ERROR();
3418 // Expect to see Red + Green, which is Yellow
3419 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
3420 }
3421
3422 // Similar to the other RenderImmutableTexture*** tests, but test on depth attachment instead of
3423 // color attachment. This tests render to a depth texture level that is less than
3424 // GL_TEXTURE_BASE_LEVEL and sample from it at the same time.
TEST_P(FramebufferTest_ES3,RenderSampleDepthTextureWithExcludedLevel)3425 TEST_P(FramebufferTest_ES3, RenderSampleDepthTextureWithExcludedLevel)
3426 {
3427 // Set up program to copy depth texture's value to color.red.
3428 constexpr char kVS[] = R"(precision mediump float;
3429 attribute vec4 a_position;
3430 varying vec2 v_texCoord;
3431 void main()
3432 {
3433 gl_Position = a_position;
3434 v_texCoord = a_position.xy * 0.5 + vec2(0.5);
3435 })";
3436 constexpr char kFS[] = R"(precision mediump float;
3437 varying vec2 v_texCoord;
3438 uniform sampler2D depth;
3439 void main()
3440 {
3441 gl_FragColor = vec4(texture2D(depth, v_texCoord).x, 1, 0, 1);
3442 })";
3443 ANGLE_GL_PROGRAM(program, kVS, kFS);
3444
3445 constexpr GLuint kLevel0Size = 4;
3446 constexpr GLuint kLevel1Size = kLevel0Size / 2;
3447
3448 GLTexture colorTexture;
3449 glBindTexture(GL_TEXTURE_2D, colorTexture);
3450 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3451 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3452 glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
3453
3454 GLTexture depthTexture;
3455 glBindTexture(GL_TEXTURE_2D, depthTexture);
3456 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3457 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3458 glTexStorage2D(GL_TEXTURE_2D, 3, GL_DEPTH_COMPONENT32F, kLevel0Size, kLevel0Size);
3459 // Initialize level 1 with known depth value
3460 std::array<GLfloat, kLevel1Size *kLevel1Size> gData = {0.2, 0.4, 0.6, 0.8};
3461 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_DEPTH_COMPONENT, GL_FLOAT,
3462 gData.data());
3463 // set base_level and max_level to 1, exclude level 0
3464 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
3465 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
3466
3467 // Attach level 0 to a FBO
3468 GLFramebuffer framebuffer;
3469 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3470 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3471 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
3472 ASSERT_GL_NO_ERROR();
3473 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3474
3475 // Render to FBO (LOD 0) with depth texture LOD 1
3476 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3477 glViewport(0, 0, kLevel0Size, kLevel0Size);
3478 glScissor(0, 0, kLevel0Size, kLevel0Size);
3479 glDepthMask(GL_TRUE);
3480 glEnable(GL_DEPTH_TEST);
3481 glDepthFunc(GL_ALWAYS);
3482 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3483 ASSERT_GL_NO_ERROR();
3484 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51u, 255u, 0, 255u), 1);
3485 EXPECT_PIXEL_COLOR_NEAR(kLevel0Size - 1, 0, GLColor(102u, 255u, 0, 255u), 1);
3486 EXPECT_PIXEL_COLOR_NEAR(0, kLevel0Size - 1, GLColor(153u, 255u, 0, 255u), 1);
3487 EXPECT_PIXEL_COLOR_NEAR(kLevel0Size - 1, kLevel0Size - 1, GLColor(204u, 255u, 0, 255u), 1);
3488
3489 // Now check depth value is 0.5
3490 glDepthFunc(GL_LESS);
3491 glDepthMask(GL_FALSE);
3492 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3493 glUseProgram(blueProgram);
3494 // should fail depth test
3495 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.51f);
3496 ASSERT_GL_NO_ERROR();
3497 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51u, 255u, 0, 255u), 1);
3498 // should pass depth test
3499 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.49f);
3500 ASSERT_GL_NO_ERROR();
3501 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3502 }
3503
3504 // Covers a bug in ANGLE's Vulkan back-end. Our VkFramebuffer cache would in some cases forget to
3505 // check the draw states when computing a cache key.
TEST_P(FramebufferTest_ES3,DisabledAttachmentRedefinition)3506 TEST_P(FramebufferTest_ES3, DisabledAttachmentRedefinition)
3507 {
3508 constexpr GLuint kSize = 2;
3509
3510 // Make a Framebuffer with two attachments with one enabled and one disabled.
3511 GLTexture texA, texB;
3512 glBindTexture(GL_TEXTURE_2D, texA);
3513 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3514 glBindTexture(GL_TEXTURE_2D, texB);
3515 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3516
3517 GLFramebuffer fbo;
3518 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3519 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
3520 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
3521
3522 // Mask out the second texture.
3523 constexpr GLenum kOneDrawBuf = GL_COLOR_ATTACHMENT0;
3524 glDrawBuffers(1, &kOneDrawBuf);
3525
3526 ASSERT_GL_NO_ERROR();
3527 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3528
3529 // Set up a very simple shader.
3530 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
3531 glViewport(0, 0, kSize, kSize);
3532
3533 // Draw
3534 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3535 ASSERT_GL_NO_ERROR();
3536 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3537
3538 // Update the masked out attachment and draw again.
3539 std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
3540 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
3541 redPixels.data());
3542
3543 // Draw
3544 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3545 ASSERT_GL_NO_ERROR();
3546 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3547
3548 glReadBuffer(GL_COLOR_ATTACHMENT1);
3549 ASSERT_GL_NO_ERROR();
3550 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3551 }
3552
3553 // Test that changing the attachment of a framebuffer then sync'ing both READ and DRAW framebuffer
3554 // (currently possible with glInvalidateFramebuffer) updates the scissor correctly.
TEST_P(FramebufferTest_ES3,ChangeAttachmentThenInvalidateAndDraw)3555 TEST_P(FramebufferTest_ES3, ChangeAttachmentThenInvalidateAndDraw)
3556 {
3557 constexpr GLsizei kSizeLarge = 32;
3558 constexpr GLsizei kSizeSmall = 16;
3559
3560 GLTexture color1;
3561 glBindTexture(GL_TEXTURE_2D, color1);
3562 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeSmall, kSizeSmall, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3563 nullptr);
3564
3565 GLTexture color2;
3566 glBindTexture(GL_TEXTURE_2D, color2);
3567 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3568 nullptr);
3569
3570 GLFramebuffer fbo;
3571 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3572 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
3573
3574 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3575 glUseProgram(drawColor);
3576 GLint colorUniformLocation =
3577 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3578 ASSERT_NE(colorUniformLocation, -1);
3579
3580 glViewport(0, 0, kSizeLarge, kSizeLarge);
3581
3582 // Draw red into the framebuffer.
3583 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3584 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3585 ASSERT_GL_NO_ERROR();
3586
3587 // Change the attachment, invalidate it and draw green.
3588 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color2, 0);
3589 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3590
3591 std::array<GLenum, 1> attachments = {GL_COLOR_ATTACHMENT0};
3592 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
3593 ASSERT_GL_NO_ERROR();
3594
3595 glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3596 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3597 ASSERT_GL_NO_ERROR();
3598
3599 // Validate the result.
3600 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::green);
3601
3602 // Do the same, but changing from the large to small attachment.
3603
3604 // Draw red into the framebuffer.
3605 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3606 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3607 ASSERT_GL_NO_ERROR();
3608
3609 // Change the attachment, invalidate it and draw blue.
3610 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
3611 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3612 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
3613
3614 glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
3615 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3616 ASSERT_GL_NO_ERROR();
3617
3618 // Validate the result.
3619 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::blue);
3620 }
3621
3622 // Test Framebuffer object with two attachments that have unequal size. In OpenGLES3.0, this is
3623 // a supported config. The common intersection area should be correctly rendered. The contents
3624 // outside common intersection area are undefined.
TEST_P(FramebufferTest_ES3,AttachmentsWithUnequalDimensions)3625 TEST_P(FramebufferTest_ES3, AttachmentsWithUnequalDimensions)
3626 {
3627 ANGLE_SKIP_TEST_IF(IsD3D());
3628
3629 constexpr GLsizei kSizeLarge = 32;
3630 constexpr GLsizei kSizeSmall = 16;
3631
3632 GLTexture colorTexture;
3633 glBindTexture(GL_TEXTURE_2D, colorTexture);
3634 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeSmall, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3635 nullptr);
3636
3637 GLRenderbuffer color;
3638 glBindRenderbuffer(GL_RENDERBUFFER, color);
3639 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSizeSmall, kSizeLarge);
3640
3641 GLRenderbuffer depth;
3642 glBindRenderbuffer(GL_RENDERBUFFER, depth);
3643 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kSizeSmall, kSizeLarge);
3644
3645 GLRenderbuffer stencil;
3646 glBindRenderbuffer(GL_RENDERBUFFER, stencil);
3647 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSizeSmall, kSizeLarge);
3648
3649 struct
3650 {
3651 GLenum attachment;
3652 GLuint renderbuffer;
3653 } attachment2[4] = {{GL_COLOR_ATTACHMENT1, 0},
3654 {GL_COLOR_ATTACHMENT1, color},
3655 {GL_DEPTH_ATTACHMENT, depth},
3656 {GL_STENCIL_ATTACHMENT, stencil}};
3657 for (int i = 0; i < 4; i++)
3658 {
3659 GLFramebuffer fbo;
3660 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3661 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
3662 0);
3663 if (attachment2[i].renderbuffer)
3664 {
3665 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment2[i].attachment, GL_RENDERBUFFER,
3666 attachment2[i].renderbuffer);
3667 }
3668 ASSERT_GL_NO_ERROR();
3669 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3670
3671 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3672 glUseProgram(drawColor);
3673 GLint colorUniformLocation =
3674 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3675 ASSERT_NE(colorUniformLocation, -1);
3676
3677 glViewport(0, 0, kSizeLarge, kSizeLarge);
3678 const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3679 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3680
3681 // Draw red into the framebuffer.
3682 glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3683 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3684 ASSERT_GL_NO_ERROR();
3685
3686 // Validate the result. The intersected common area should be red now
3687 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::red);
3688 }
3689 }
3690
3691 class FramebufferTest : public ANGLETest
3692 {};
3693
3694 template <typename T>
FillTexture2D(GLuint texture,GLsizei width,GLsizei height,const T & onePixelData,GLint level,GLint internalFormat,GLenum format,GLenum type)3695 void FillTexture2D(GLuint texture,
3696 GLsizei width,
3697 GLsizei height,
3698 const T &onePixelData,
3699 GLint level,
3700 GLint internalFormat,
3701 GLenum format,
3702 GLenum type)
3703 {
3704 std::vector<T> allPixelsData(width * height, onePixelData);
3705
3706 glBindTexture(GL_TEXTURE_2D, texture);
3707 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
3708 allPixelsData.data());
3709 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3710 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3711 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3712 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3713 }
3714
3715 // Multi-context uses of textures should not cause rendering feedback loops.
TEST_P(FramebufferTest,MultiContextNoRenderingFeedbackLoops)3716 TEST_P(FramebufferTest, MultiContextNoRenderingFeedbackLoops)
3717 {
3718 constexpr char kTextureVS[] =
3719 R"(attribute vec4 a_position;
3720 varying vec2 v_texCoord;
3721 void main() {
3722 gl_Position = a_position;
3723 v_texCoord = (a_position.xy * 0.5) + 0.5;
3724 })";
3725
3726 constexpr char kTextureFS[] =
3727 R"(precision mediump float;
3728 varying vec2 v_texCoord;
3729 uniform sampler2D u_texture;
3730 void main() {
3731 gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
3732 })";
3733
3734 ANGLE_GL_PROGRAM(textureProgram, kTextureVS, kTextureFS);
3735
3736 glUseProgram(textureProgram.get());
3737 GLint uniformLoc = glGetUniformLocation(textureProgram.get(), "u_texture");
3738 ASSERT_NE(-1, uniformLoc);
3739 glUniform1i(uniformLoc, 0);
3740
3741 GLTexture texture;
3742 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3743 glBindTexture(GL_TEXTURE_2D, texture.get());
3744 // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
3745
3746 EGLWindow *window = getEGLWindow();
3747 EGLDisplay display = window->getDisplay();
3748 EGLConfig config = window->getConfig();
3749 EGLSurface surface = window->getSurface();
3750 EGLint contextAttributes[] = {
3751 EGL_CONTEXT_MAJOR_VERSION_KHR,
3752 GetParam().majorVersion,
3753 EGL_CONTEXT_MINOR_VERSION_KHR,
3754 GetParam().minorVersion,
3755 EGL_NONE,
3756 };
3757 EGLContext context1 = eglGetCurrentContext();
3758 // Create context2, sharing resources with context1.
3759 EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
3760 ASSERT_NE(context2, EGL_NO_CONTEXT);
3761 eglMakeCurrent(display, surface, surface, context2);
3762
3763 constexpr char kVS[] =
3764 R"(attribute vec4 a_position;
3765 void main() {
3766 gl_Position = a_position;
3767 })";
3768
3769 constexpr char kFS[] =
3770 R"(precision mediump float;
3771 void main() {
3772 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
3773 })";
3774
3775 ANGLE_GL_PROGRAM(program, kVS, kFS);
3776 glUseProgram(program.get());
3777
3778 ASSERT_GL_NO_ERROR();
3779
3780 // Render to the texture in context2.
3781 GLFramebuffer framebuffer;
3782 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3783 // Texture is still a valid name in context2.
3784 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
3785 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3786 // There is no rendering feedback loop at this point.
3787
3788 glDisable(GL_BLEND);
3789 glDisable(GL_DEPTH_TEST);
3790 ASSERT_GL_NO_ERROR();
3791
3792 // If draw is no-op'ed, texture will not be filled appropriately.
3793 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
3794 ASSERT_GL_NO_ERROR();
3795 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3796
3797 // Make context1 current again.
3798 eglMakeCurrent(display, surface, surface, context1);
3799
3800 // Render texture to screen.
3801 drawQuad(textureProgram.get(), "a_position", 0.5f, 1.0f, true);
3802 ASSERT_GL_NO_ERROR();
3803 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3804
3805 eglDestroyContext(display, context2);
3806 }
3807
3808 // Ensure cube-incomplete attachments cause incomplete Framebuffers.
TEST_P(FramebufferTest,IncompleteCubeMap)3809 TEST_P(FramebufferTest, IncompleteCubeMap)
3810 {
3811 constexpr GLuint kSize = 2;
3812
3813 GLTexture srcTex;
3814 glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex);
3815 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
3816 GL_UNSIGNED_BYTE, nullptr);
3817
3818 GLFramebuffer fbo;
3819 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3820 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
3821 srcTex, 0);
3822
3823 ASSERT_GL_NO_ERROR();
3824 ASSERT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
3825 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
3826 }
3827
3828 // Test FBOs with different sizes are drawn correctly
TEST_P(FramebufferTest,BindAndDrawDifferentSizedFBOs)3829 TEST_P(FramebufferTest, BindAndDrawDifferentSizedFBOs)
3830 {
3831 // 1. Create FBO 1 with dimensions 16x16
3832 // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
3833 // 3. Create FBO 2 with dimensions 8x8
3834 // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
3835 // 5. Bind FBO 1 (note, it's not dirty)
3836 // 6. Draw blue into FBO 1
3837 // 7. Verify FBO 1 is entirely blue
3838
3839 GLFramebuffer smallFbo;
3840 GLFramebuffer largeFbo;
3841 GLTexture smallTexture;
3842 GLTexture largeTexture;
3843 constexpr GLsizei kLargeWidth = 16;
3844 constexpr GLsizei kLargeHeight = 16;
3845 constexpr GLsizei kSmallWidth = 8;
3846 constexpr GLsizei kSmallHeight = 8;
3847
3848 ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3849 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
3850 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3851
3852 // 1. Create FBO 1 with dimensions 16x16
3853 glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
3854 glBindTexture(GL_TEXTURE_2D, largeTexture);
3855 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kLargeWidth, kLargeHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3856 nullptr);
3857 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3858 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3859 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
3860 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3861
3862 // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
3863 glUseProgram(redProgram);
3864 drawQuad(redProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
3865 ASSERT_GL_NO_ERROR();
3866
3867 // 3. Create FBO 2 with dimensions 8x8
3868 glBindFramebuffer(GL_FRAMEBUFFER, smallFbo);
3869 glBindTexture(GL_TEXTURE_2D, smallTexture);
3870 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallWidth, kSmallHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3871 nullptr);
3872 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3873 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3874 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
3875 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3876
3877 // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
3878 glUseProgram(greenProgram);
3879 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
3880 ASSERT_GL_NO_ERROR();
3881
3882 // 5. Bind FBO 1 (note, it's not dirty)
3883 glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
3884
3885 // 6. Draw blue into FBO 1
3886 glUseProgram(blueProgram);
3887 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
3888 ASSERT_GL_NO_ERROR();
3889
3890 // 7. Verify FBO 1 is entirely blue
3891 EXPECT_PIXEL_RECT_EQ(0, 0, kLargeWidth, kLargeHeight, GLColor::blue);
3892 }
3893
3894 // Regression test based on a fuzzer failure. A crash was encountered in the following situation:
3895 //
3896 // - Texture bound as sampler with MAX_LEVEL 0
3897 // - Framebuffer bound to level 0
3898 // - Draw
3899 // - Texture MAX_LEVEL changed to 1
3900 // - Framebuffer bound to level 1
3901 // - Draw
3902 //
3903 // Notes: Removing the first half removed the crash. MIN_FILTERING of LINEAR vs
3904 // LINEAR_MIPMAP_LINEAR did not make any changes.
TEST_P(FramebufferTest_ES3,FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash)3905 TEST_P(FramebufferTest_ES3, FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash)
3906 {
3907 constexpr char kFS[] = R"(precision mediump float;
3908 uniform sampler2D u_tex0;
3909 void main() {
3910 gl_FragColor = texture2D(u_tex0, vec2(0));
3911 })";
3912
3913 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), kFS);
3914 glUseProgram(program);
3915
3916 GLTexture mutTex;
3917 glBindTexture(GL_TEXTURE_2D, mutTex);
3918 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3919 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3920
3921 GLFramebuffer fb;
3922 glBindFramebuffer(GL_FRAMEBUFFER, fb);
3923
3924 // Attempt a draw with level 0 (feedback loop)
3925 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3926 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3927
3928 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutTex, 0);
3929 glDrawArrays(GL_POINTS, 0, 1);
3930
3931 // Attempt another draw with level 1.
3932 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
3933
3934 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutTex, 1);
3935
3936 // This shouldn't crash.
3937 glDrawArrays(GL_POINTS, 0, 1);
3938 ASSERT_GL_NO_ERROR();
3939 }
3940
3941 // Modify renderbuffer attachment samples after bind
TEST_P(FramebufferTest_ES3,BindRenderbufferThenModifySamples)3942 TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySamples)
3943 {
3944 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3945 glUseProgram(program);
3946 GLint colorUniformLocation =
3947 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
3948 ASSERT_NE(colorUniformLocation, -1);
3949
3950 GLFramebuffer fbo;
3951 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3952
3953 GLsizei size = 16;
3954 glViewport(0, 0, size, size);
3955
3956 GLRenderbuffer color;
3957 glBindRenderbuffer(GL_RENDERBUFFER, color);
3958
3959 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, size, size);
3960 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
3961 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
3962
3963 glUniform4f(colorUniformLocation, 1, 0, 0, 1);
3964 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3965
3966 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3967 ASSERT_GL_NO_ERROR();
3968 }
3969
3970 // Modify renderbuffer attachment size after bind
TEST_P(FramebufferTest_ES3,BindRenderbufferThenModifySize)3971 TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySize)
3972 {
3973 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3974 glUseProgram(program);
3975 GLint colorUniformLocation =
3976 glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
3977 ASSERT_NE(colorUniformLocation, -1);
3978
3979 GLFramebuffer fbo;
3980 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3981
3982 GLsizei size = 16;
3983 glViewport(0, 0, size, size);
3984
3985 GLRenderbuffer color;
3986 glBindRenderbuffer(GL_RENDERBUFFER, color);
3987
3988 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
3989 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
3990 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size / 2, size * 2);
3991
3992 glUniform4f(colorUniformLocation, 1, 0, 0, 1);
3993 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3994
3995 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3996 ASSERT_GL_NO_ERROR();
3997 }
3998
3999 ANGLE_INSTANTIATE_TEST_ES2(AddMockTextureNoRenderTargetTest);
4000 ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
4001 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
4002
4003 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3);
4004 ANGLE_INSTANTIATE_TEST_ES3_AND(FramebufferTest_ES3,
4005 WithEmulatedPrerotation(ES3_VULKAN(), 90),
4006 WithEmulatedPrerotation(ES3_VULKAN(), 180),
4007 WithEmulatedPrerotation(ES3_VULKAN(), 270));
4008
4009 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES31);
4010 ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31);
4011 ANGLE_INSTANTIATE_TEST_ES3(FramebufferTestWithFormatFallback);
4012