blob: 7ace41e34f33952916d56322bf641de6deafe85a [file] [log] [blame]
Martin Radeve5285d22017-07-14 16:23:53 +03001//
2// Copyright 2017 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// Framebuffer multiview tests:
7// The tests modify and examine the multiview state.
8//
9
10#include "test_utils/ANGLETest.h"
Martin Radev0f7714e2017-08-07 15:13:42 +030011#include "test_utils/gl_raii.h"
Martin Radeve5285d22017-07-14 16:23:53 +030012
13using namespace angle;
14
Martin Radev5c00d0d2017-08-07 10:06:59 +030015namespace
16{
17std::vector<GLenum> GetDrawBufferRange(size_t numColorAttachments)
18{
19 std::vector<GLenum> drawBuffers(numColorAttachments);
20 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
21 for (size_t i = 0u; i < drawBuffers.size(); ++i)
22 {
23 drawBuffers[i] = static_cast<GLenum>(kBase + i);
24 }
25 return drawBuffers;
26}
27} // namespace
28
Martin Radeve5285d22017-07-14 16:23:53 +030029class FramebufferMultiviewTest : public ANGLETest
30{
31 protected:
Martin Radev0f7714e2017-08-07 15:13:42 +030032 FramebufferMultiviewTest()
Martin Radeve5285d22017-07-14 16:23:53 +030033 {
34 setWindowWidth(128);
35 setWindowHeight(128);
36 setWebGLCompatibilityEnabled(true);
37 }
38
39 void SetUp() override
40 {
41 ANGLETest::SetUp();
Martin Radeve5285d22017-07-14 16:23:53 +030042 glRequestExtensionANGLE = reinterpret_cast<PFNGLREQUESTEXTENSIONANGLEPROC>(
43 eglGetProcAddress("glRequestExtensionANGLE"));
44 }
45
Martin Radev137032d2017-07-13 10:11:12 +030046 // Requests the ANGLE_multiview extension and returns true if the operation succeeds.
47 bool requestMultiviewExtension()
48 {
49 if (extensionRequestable("GL_ANGLE_multiview"))
50 {
51 glRequestExtensionANGLE("GL_ANGLE_multiview");
52 }
53
54 if (!extensionEnabled("GL_ANGLE_multiview"))
55 {
56 std::cout << "Test skipped due to missing GL_ANGLE_multiview." << std::endl;
57 return false;
58 }
59 return true;
60 }
61
Martin Radeve5285d22017-07-14 16:23:53 +030062 PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
63};
64
Martin Radev5c00d0d2017-08-07 10:06:59 +030065class FramebufferMultiviewClearTest : public FramebufferMultiviewTest
66{
67 protected:
68 FramebufferMultiviewClearTest() {}
69
70 void initializeFBOs(size_t numColorBuffers, bool stencil, bool depth)
71 {
72 const std::vector<GLenum> &drawBuffers = GetDrawBufferRange(2);
73
74 // Generate textures.
75 mColorTex.resize(numColorBuffers);
76 for (size_t i = 0u; i < numColorBuffers; ++i)
77 {
78 glBindTexture(GL_TEXTURE_2D, mColorTex[i]);
79 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
80 }
81
82 if (stencil)
83 {
84 glBindTexture(GL_TEXTURE_2D, mStencilTex);
85 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 4, 2, 0, GL_DEPTH_STENCIL,
86 GL_UNSIGNED_INT_24_8, nullptr);
87 }
88 else if (depth)
89 {
90 glBindTexture(GL_TEXTURE_2D, mDepthTex);
91 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 4, 2, 0, GL_DEPTH_COMPONENT,
92 GL_FLOAT, nullptr);
93 }
94
95 // Generate multiview fbo and attach textures.
96 const GLint kViewportOffsets[4] = {1, 0, 3, 0};
97 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
98 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
99 for (size_t i = 0u; i < numColorBuffers; ++i)
100 {
101 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
102 static_cast<GLenum>(kBase + i),
103 mColorTex[i], 0, 2, &kViewportOffsets[0]);
104 }
105
106 if (stencil)
107 {
108 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
109 GL_DEPTH_STENCIL_ATTACHMENT, mStencilTex,
110 0, 2, &kViewportOffsets[0]);
111 }
112 else if (depth)
113 {
114 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
115 mDepthTex, 0, 2, &kViewportOffsets[0]);
116 }
117 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
118
119 // Generate normal fbo and attach textures.
120 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
121 for (size_t i = 0u; i < numColorBuffers; ++i)
122 {
123 glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(kBase + i), GL_TEXTURE_2D,
124 mColorTex[i], 0);
125 }
126 if (stencil)
127 {
128 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
129 mStencilTex, 0);
130 }
131 else if (depth)
132 {
133 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTex,
134 0);
135 }
136 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
137
138 ASSERT_GL_NO_ERROR();
139 }
140
141 void checkAlternatingColumnsOfRedAndGreenInFBO()
142 {
143 // column 0
144 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
145 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::red);
146
147 // column 1
148 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
149 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
150
151 // column 2
152 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::red);
153 EXPECT_PIXEL_COLOR_EQ(2, 1, GLColor::red);
154
155 // column 3
156 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
157 EXPECT_PIXEL_COLOR_EQ(3, 1, GLColor::green);
158 }
159
160 GLFramebuffer mMultiviewFBO;
161 GLFramebuffer mNonMultiviewFBO;
162 std::vector<GLTexture> mColorTex;
163 GLTexture mDepthTex;
164 GLTexture mStencilTex;
165};
166
Martin Radeve5285d22017-07-14 16:23:53 +0300167// Test that the framebuffer tokens introduced by ANGLE_multiview can be used query the framebuffer
168// state and that their corresponding default values are correctly set.
169TEST_P(FramebufferMultiviewTest, DefaultState)
170{
Martin Radev137032d2017-07-13 10:11:12 +0300171 if (!requestMultiviewExtension())
Martin Radeve5285d22017-07-14 16:23:53 +0300172 {
Martin Radeve5285d22017-07-14 16:23:53 +0300173 return;
174 }
175
Martin Radev0f7714e2017-08-07 15:13:42 +0300176 GLFramebuffer fbo;
177 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
178
179 GLTexture tex;
180 glBindTexture(GL_TEXTURE_2D, tex);
181 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
182 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300183
Martin Radeve5285d22017-07-14 16:23:53 +0300184 GLint numViews = -1;
185 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
186 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
187 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +0300188 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300189 EXPECT_EQ(1, numViews);
190
191 GLint baseViewIndex = -1;
192 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
193 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
194 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +0300195 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300196 EXPECT_EQ(0, baseViewIndex);
197
198 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
199 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
200 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
201 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +0300202 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300203 EXPECT_EQ(GL_NONE, multiviewLayout);
204
205 GLint viewportOffsets[2] = {-1, -1};
206 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
207 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
208 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +0300209 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300210 EXPECT_EQ(0, viewportOffsets[0]);
211 EXPECT_EQ(0, viewportOffsets[1]);
212}
213
214// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
215// the ANGLE_multiview tokens results in an INVALID_ENUM error.
216TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
217{
Martin Radev0f7714e2017-08-07 15:13:42 +0300218 GLFramebuffer fbo;
219 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
220
221 GLTexture tex;
222 glBindTexture(GL_TEXTURE_2D, tex);
223 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
224 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300225
Martin Radeve5285d22017-07-14 16:23:53 +0300226 GLint numViews = -1;
227 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
228 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
229 &numViews);
230 EXPECT_GL_ERROR(GL_INVALID_ENUM);
231
232 GLint baseViewIndex = -1;
233 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
234 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
235 &baseViewIndex);
236 EXPECT_GL_ERROR(GL_INVALID_ENUM);
237
238 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
239 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
240 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
241 &multiviewLayout);
242 EXPECT_GL_ERROR(GL_INVALID_ENUM);
243
244 GLint viewportOffsets[2] = {-1, -1};
245 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
246 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
247 &viewportOffsets[0]);
248 EXPECT_GL_ERROR(GL_INVALID_ENUM);
249}
250
Martin Radev137032d2017-07-13 10:11:12 +0300251// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
252// is called with invalid arguments.
253TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
254{
255 if (!requestMultiviewExtension())
256 {
257 return;
258 }
259
Martin Radev0f7714e2017-08-07 15:13:42 +0300260 GLFramebuffer fbo;
261 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
262
263 GLTexture tex;
264 glBindTexture(GL_TEXTURE_2D, tex);
265 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
266
Martin Radev137032d2017-07-13 10:11:12 +0300267 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300268 GLint viewportOffsets[2] = {-1};
269 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
270 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300271 EXPECT_GL_ERROR(GL_INVALID_VALUE);
272
273 // Negative number of views.
274 viewportOffsets[0] = 0;
275 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300276 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1,
277 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300278 EXPECT_GL_ERROR(GL_INVALID_VALUE);
279}
280
281// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
282// called with invalid arguments.
283TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
284{
285 if (!requestMultiviewExtension())
286 {
287 return;
288 }
289
Martin Radev0f7714e2017-08-07 15:13:42 +0300290 GLFramebuffer fbo;
291 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
292
293 GLTexture tex;
294 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
295 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
296 ASSERT_GL_NO_ERROR();
297
Martin Radev137032d2017-07-13 10:11:12 +0300298 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300299 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300300 EXPECT_GL_ERROR(GL_INVALID_VALUE);
301
302 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
303 GLint maxTextureLayers = 0;
304 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300305 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
306 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300307 EXPECT_GL_ERROR(GL_INVALID_VALUE);
308}
309
310// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
311// available.
312TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
313{
Martin Radev0f7714e2017-08-07 15:13:42 +0300314 GLFramebuffer fbo;
315 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
316
317 GLTexture tex;
318 glBindTexture(GL_TEXTURE_2D, tex);
319 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
320
Martin Radev9bc9a322017-07-21 14:28:17 +0300321 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300322 const GLint kViewportOffsets[2] = {0};
323 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
324 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300325 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
326}
327
Martin Radev5dae57b2017-07-14 16:15:55 +0300328// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
329TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
330{
331 if (!requestMultiviewExtension())
332 {
333 return;
334 }
335
Martin Radev0f7714e2017-08-07 15:13:42 +0300336 GLFramebuffer fbo;
337 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
338
339 GLTexture tex;
340 glBindTexture(GL_TEXTURE_2D, tex);
341 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
342
343 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
344 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
345 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300346 ASSERT_GL_NO_ERROR();
347
348 GLint numViews = -1;
349 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
350 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
351 &numViews);
352 ASSERT_GL_NO_ERROR();
353 EXPECT_EQ(2, numViews);
354
355 GLint baseViewIndex = -1;
356 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
357 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
358 &baseViewIndex);
359 ASSERT_GL_NO_ERROR();
360 EXPECT_EQ(0, baseViewIndex);
361
362 GLint multiviewLayout = GL_NONE;
363 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
364 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
365 &multiviewLayout);
366 ASSERT_GL_NO_ERROR();
367 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
368
369 GLint internalViewportOffsets[4] = {-1};
370 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
371 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
372 &internalViewportOffsets[0]);
373 ASSERT_GL_NO_ERROR();
374 for (size_t i = 0u; i < 4u; ++i)
375 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300376 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300377 }
378}
379
Martin Radev9bc9a322017-07-21 14:28:17 +0300380// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
381// attachments.
382TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
383{
384 if (!requestMultiviewExtension())
385 {
386 return;
387 }
388
Martin Radev0f7714e2017-08-07 15:13:42 +0300389 GLFramebuffer fbo;
390 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300391
Martin Radev0f7714e2017-08-07 15:13:42 +0300392 GLTexture tex;
393 glBindTexture(GL_TEXTURE_2D, tex);
394 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300395
Martin Radev0f7714e2017-08-07 15:13:42 +0300396 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
397 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300398
399 // Set the 0th attachment and keep it as it is till the end of the test. The 1st or depth
Martin Radev82ef7742017-08-08 17:44:58 +0300400 // attachment will be modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300401 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
402 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300403 ASSERT_GL_NO_ERROR();
404
405 // Color attachment 1.
406 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300407 GLTexture otherTex;
408 glBindTexture(GL_TEXTURE_2D, otherTex);
409 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
410
Martin Radev9bc9a322017-07-21 14:28:17 +0300411 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300412 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
413 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300414 ASSERT_GL_NO_ERROR();
415 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
416 glCheckFramebufferStatus(GL_FRAMEBUFFER));
417
418 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300419 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
420 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300421 ASSERT_GL_NO_ERROR();
422 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
423 glCheckFramebufferStatus(GL_FRAMEBUFFER));
424
425 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300426 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300427 ASSERT_GL_NO_ERROR();
428 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
429 glCheckFramebufferStatus(GL_FRAMEBUFFER));
430
431 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
432 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300433 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
434 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300435 ASSERT_GL_NO_ERROR();
436 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
437
438 // Reset attachment 1
439 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300440 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300441 }
442
443 // Depth attachment.
444 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300445 GLTexture depthTex;
446 glBindTexture(GL_TEXTURE_2D, depthTex);
447 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
448 nullptr);
449
Martin Radev9bc9a322017-07-21 14:28:17 +0300450 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300451 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
452 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300453 ASSERT_GL_NO_ERROR();
454 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
455 glCheckFramebufferStatus(GL_FRAMEBUFFER));
456
457 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300458 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
459 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300460 ASSERT_GL_NO_ERROR();
461 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
462 glCheckFramebufferStatus(GL_FRAMEBUFFER));
463
464 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300465 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300466 ASSERT_GL_NO_ERROR();
467 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
468 glCheckFramebufferStatus(GL_FRAMEBUFFER));
469
470 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
471 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300472 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
473 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300474 ASSERT_GL_NO_ERROR();
475 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
476 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300477}
478
Martin Radev04e2c3b2017-07-27 16:54:35 +0300479// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
480// attachments.
481TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
482{
483 if (!requestMultiviewExtension())
484 {
485 return;
486 }
487
Martin Radev0f7714e2017-08-07 15:13:42 +0300488 GLFramebuffer fbo;
489 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300490
Martin Radev0f7714e2017-08-07 15:13:42 +0300491 GLTexture tex;
492 glBindTexture(GL_TEXTURE_2D, tex);
493 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
494
495 const GLint kViewportOffsets[2] = {0};
496 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
497 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300498 ASSERT_GL_NO_ERROR();
499
500 // Test glCopyTexImage2D and glCopyTexSubImage2D.
501 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300502 GLTexture tex2;
503 glBindTexture(GL_TEXTURE_2D, tex2);
504 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300505
506 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
507 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
508
509 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
510 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300511 }
512
513 // Test glCopyTexSubImage3D.
514 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300515 GLTexture tex2;
516 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300517 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
518
519 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
520 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300521 }
522}
523
Martin Radeva3ed4572017-07-27 18:29:37 +0300524// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
525// draw framebuffer, or current read framebuffer have multiview attachments.
526TEST_P(FramebufferMultiviewTest, InvalidBlit)
527{
528 if (!requestMultiviewExtension())
529 {
530 return;
531 }
532
Martin Radev0f7714e2017-08-07 15:13:42 +0300533 GLFramebuffer fbo;
534 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300535
Martin Radev0f7714e2017-08-07 15:13:42 +0300536 GLTexture tex;
537 glBindTexture(GL_TEXTURE_2D, tex);
538 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
539
540 const GLint kViewportOffsets[2] = {0};
541 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
542 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300543 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
544 ASSERT_GL_NO_ERROR();
545
546 // Blit with the active read framebuffer having multiview attachments.
547 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300548 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300549 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
550 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
551 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
552 }
553
554 // Blit with the active draw framebuffer having multiview attachments.
555 {
556 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300557 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300558 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
559 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
560 }
561}
562
Martin Radev28031682017-07-28 14:47:56 +0300563// Test that glReadPixels generates an invalid framebuffer operation error if the current read
564// framebuffer has a multi-view layout.
565TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
566{
567 if (!requestMultiviewExtension())
568 {
569 return;
570 }
571
Martin Radev0f7714e2017-08-07 15:13:42 +0300572 GLFramebuffer fbo;
573 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300574
Martin Radev0f7714e2017-08-07 15:13:42 +0300575 GLTexture tex;
576 glBindTexture(GL_TEXTURE_2D, tex);
577 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
578
579 const GLint kViewportOffsets[2] = {0};
580 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
581 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300582 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
583 ASSERT_GL_NO_ERROR();
584
585 GLColor pixelColor;
586 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
587 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
588}
589
Martin Radeveef80e42017-08-11 14:44:57 +0300590// Test that glClear clears only the contents of each view if the scissor test is enabled.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300591TEST_P(FramebufferMultiviewClearTest, SideBySideColorBufferClear)
Martin Radevb0761932017-07-25 17:42:25 +0300592{
593 if (!requestMultiviewExtension())
594 {
595 return;
596 }
597
Martin Radev5c00d0d2017-08-07 10:06:59 +0300598 initializeFBOs(1, false, false);
Martin Radevb0761932017-07-25 17:42:25 +0300599
600 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300601 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
602 glClearColor(1, 0, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300603 glClear(GL_COLOR_BUFFER_BIT);
604
605 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300606 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300607 glViewport(0, 0, 1, 2);
608 glScissor(0, 0, 1, 2);
Martin Radeveef80e42017-08-11 14:44:57 +0300609 glEnable(GL_SCISSOR_TEST);
Martin Radevb0761932017-07-25 17:42:25 +0300610
Martin Radev5c00d0d2017-08-07 10:06:59 +0300611 glClearColor(0, 1, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300612 glClear(GL_COLOR_BUFFER_BIT);
613
Martin Radev5c00d0d2017-08-07 10:06:59 +0300614 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300615
Martin Radev5c00d0d2017-08-07 10:06:59 +0300616 checkAlternatingColumnsOfRedAndGreenInFBO();
Martin Radevb0761932017-07-25 17:42:25 +0300617}
618
Martin Radev82ef7742017-08-08 17:44:58 +0300619// Test that glFramebufferTextureMultiviewLayeredANGLE modifies the internal multiview state.
620TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
621{
622 if (!requestMultiviewExtension())
623 {
624 return;
625 }
626
627 GLFramebuffer multiviewFBO;
628 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
629
630 GLTexture tex;
631 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
632 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
633 ASSERT_GL_NO_ERROR();
634
635 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
636 ASSERT_GL_NO_ERROR();
637
638 GLint numViews = -1;
639 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
640 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
641 &numViews);
642 ASSERT_GL_NO_ERROR();
643 EXPECT_EQ(2, numViews);
644
645 GLint baseViewIndex = -1;
646 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
647 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
648 &baseViewIndex);
649 ASSERT_GL_NO_ERROR();
650 EXPECT_EQ(1, baseViewIndex);
651
652 GLint multiviewLayout = GL_NONE;
653 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
654 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
655 &multiviewLayout);
656 ASSERT_GL_NO_ERROR();
657 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, multiviewLayout);
658
659 GLint internalViewportOffsets[2] = {-1};
660 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
661 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
662 &internalViewportOffsets[0]);
663 ASSERT_GL_NO_ERROR();
664 EXPECT_EQ(0, internalViewportOffsets[0]);
665 EXPECT_EQ(0, internalViewportOffsets[1]);
666}
667
668// Test framebuffer completeness status of a layered framebuffer with color attachments.
669TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
670{
671 if (!requestMultiviewExtension())
672 {
673 return;
674 }
675
676 GLFramebuffer fbo;
677 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
678
679 GLTexture tex;
680 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
681 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
682
683 // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
684 // attachment will be modified to change the framebuffer's status.
685 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
686 ASSERT_GL_NO_ERROR();
687
688 GLTexture otherTexLayered;
689 glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
690 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
691
692 // Test framebuffer completeness when the base view index differs.
693 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
694 0, 1, 2);
695 ASSERT_GL_NO_ERROR();
696 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
697 glCheckFramebufferStatus(GL_FRAMEBUFFER));
698
699 // Test framebuffer completeness when the 1st attachment has a side-by-side layout.
700 const int kViewportOffsets[4] = {0, 0, 0, 0};
701 GLTexture otherTex2D;
702 glBindTexture(GL_TEXTURE_2D, otherTex2D);
703 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
704 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex2D,
705 0, 2, kViewportOffsets);
706 ASSERT_GL_NO_ERROR();
707 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
708 glCheckFramebufferStatus(GL_FRAMEBUFFER));
709
710 // Test framebuffer completeness when the 1st attachment has a normal layout.
711 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
712 ASSERT_GL_NO_ERROR();
713 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
714 glCheckFramebufferStatus(GL_FRAMEBUFFER));
715
716 // Test that framebuffer is complete when the number of views, base view index and layouts are
717 // the same.
718 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
719 0, 0, 2);
720 ASSERT_GL_NO_ERROR();
721 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
722}
723
Martin Radeveef80e42017-08-11 14:44:57 +0300724// Test that glClear clears all of the contents if the scissor test is disabled.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300725TEST_P(FramebufferMultiviewClearTest, SideBySideClearWithDisabledScissorTest)
Martin Radeveef80e42017-08-11 14:44:57 +0300726{
727 if (!requestMultiviewExtension())
728 {
729 return;
730 }
731
Martin Radev5c00d0d2017-08-07 10:06:59 +0300732 initializeFBOs(1, false, false);
Martin Radeveef80e42017-08-11 14:44:57 +0300733
734 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300735 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
736 glClearColor(0, 0, 0, 1);
Martin Radeveef80e42017-08-11 14:44:57 +0300737 glClear(GL_COLOR_BUFFER_BIT);
738
739 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300740 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300741 glViewport(0, 0, 1, 2);
742 glScissor(0, 0, 1, 2);
743
744 glClearColor(1, 0, 0, 1);
745 glClear(GL_COLOR_BUFFER_BIT);
746
Martin Radev5c00d0d2017-08-07 10:06:59 +0300747 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300748
749 for (int i = 0; i < 4; ++i)
750 {
751 for (int j = 0; j < 2; ++j)
752 {
753 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
754 }
755 }
756}
757
Martin Radev5c00d0d2017-08-07 10:06:59 +0300758// Test that glClear clears the depth buffer of each view.
759TEST_P(FramebufferMultiviewClearTest, SideBySideDepthBufferClear)
760{
761 if (!requestMultiviewExtension())
762 {
763 return;
764 }
765
766 // Create program to draw a quad.
767 const std::string &vs =
768 "#version 300 es\n"
769 "in vec3 vPos;\n"
770 "void main(){\n"
771 " gl_Position = vec4(vPos, 1.);\n"
772 "}\n";
773 const std::string &fs =
774 "#version 300 es\n"
775 "precision mediump float;\n"
776 "uniform vec3 uCol;\n"
777 "out vec4 col;\n"
778 "void main(){\n"
779 " col = vec4(uCol,1.);\n"
780 "}\n";
781 ANGLE_GL_PROGRAM(program, vs, fs);
782 glUseProgram(program);
783 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
784
785 initializeFBOs(1, false, true);
786 glEnable(GL_DEPTH_TEST);
787
788 // Clear the contents of the texture.
789 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
790 glClearColor(0, 0, 0, 0);
791 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
792
793 // Dirty the depth and color buffers.
794 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
795 drawQuad(program, "vPos", 0.0f, 1.0f, true);
796
797 // Switch to the multi-view framebuffer and clear only the rectangles covered by the views.
798 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
799 glViewport(0, 0, 1, 2);
800 glScissor(0, 0, 1, 2);
801 glEnable(GL_SCISSOR_TEST);
802 glClear(GL_DEPTH_BUFFER_BIT);
803
804 // Draw a fullscreen quad to fill the cleared regions.
805 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
806 glViewport(0, 0, 4, 2);
807 glScissor(0, 0, 4, 2);
808 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
809 drawQuad(program, "vPos", 0.5f, 1.0f, true);
810
811 checkAlternatingColumnsOfRedAndGreenInFBO();
812}
813
814// Test that glClear clears the stencil buffer of each view.
815TEST_P(FramebufferMultiviewClearTest, SideBySideStencilBufferClear)
816{
817 if (!requestMultiviewExtension())
818 {
819 return;
820 }
821
822 // Create program to draw a quad.
823 const std::string &vs =
824 "#version 300 es\n"
825 "in vec3 vPos;\n"
826 "void main(){\n"
827 " gl_Position = vec4(vPos, 1.);\n"
828 "}\n";
829 const std::string &fs =
830 "#version 300 es\n"
831 "precision mediump float;\n"
832 "uniform vec3 uCol;\n"
833 "out vec4 col;\n"
834 "void main(){\n"
835 " col = vec4(uCol,1.);\n"
836 "}\n";
837 ANGLE_GL_PROGRAM(program, vs, fs);
838 glUseProgram(program);
839 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
840
841 initializeFBOs(1, true, false);
842 glEnable(GL_STENCIL_TEST);
843 glDisable(GL_DEPTH_TEST);
844
845 // Set clear values and clear the whole framebuffer.
846 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
847 glClearColor(0, 0, 0, 0);
848 glClearStencil(0);
849 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
850
851 // Update stencil test to always replace the stencil value with 0xFF.
852 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
853 glStencilFunc(GL_ALWAYS, 0xFF, 0);
854
855 // Draw a quad which covers the whole texture.
856 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
857 drawQuad(program, "vPos", 0.0f, 1.0f, true);
858
859 // Switch to multiview framebuffer and clear portions of the texture.
860 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
861 glViewport(0, 0, 1, 2);
862 glScissor(0, 0, 1, 2);
863 glEnable(GL_SCISSOR_TEST);
864 glClear(GL_STENCIL_BUFFER_BIT);
865
866 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
867 // the test.
868 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
869 glViewport(0, 0, 4, 2);
870 glScissor(0, 0, 4, 2);
871 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
872 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
873 drawQuad(program, "vPos", 0.0f, 1.0f, true);
874
875 checkAlternatingColumnsOfRedAndGreenInFBO();
876}
877
878// Test that glClearBufferf clears the color buffer of each view.
879TEST_P(FramebufferMultiviewClearTest, SideBySideClearBufferF)
880{
881 if (!requestMultiviewExtension())
882 {
883 return;
884 }
885
886 initializeFBOs(2, false, false);
887
888 // Clear the contents of the texture.
889 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
890 glClearColor(1, 0, 0, 1);
891 glClear(GL_COLOR_BUFFER_BIT);
892
893 // Bind and specify viewport/scissor dimensions for each view.
894 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
895 glViewport(0, 0, 1, 2);
896 glScissor(0, 0, 1, 2);
897 glEnable(GL_SCISSOR_TEST);
898
899 float kClearValues[4] = {0.f, 1.f, 0.f, 1.f};
900 glClearBufferfv(GL_COLOR, 1, kClearValues);
901
902 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
903
904 // Check that glClearBufferfv has not modified the 0th color attachment.
905 glReadBuffer(GL_COLOR_ATTACHMENT0);
906 for (int i = 0; i < 4; ++i)
907 {
908 for (int j = 0; j < 2; ++j)
909 {
910 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
911 }
912 }
913
914 // Check that glClearBufferfv has correctly modified the 1th color attachment.
915 glReadBuffer(GL_COLOR_ATTACHMENT1);
916 checkAlternatingColumnsOfRedAndGreenInFBO();
917}
918
919ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, ES3_OPENGL());
920ANGLE_INSTANTIATE_TEST(FramebufferMultiviewClearTest, ES3_OPENGL(), ES3_D3D11());