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