blob: 182a5aed1411d23b3376093478d7c70cbf3e9ee7 [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 Radev5e424fa2017-08-09 16:25:36 +030065class FramebufferMultiviewSideBySideClearTest : public FramebufferMultiviewTest
Martin Radev5c00d0d2017-08-07 10:06:59 +030066{
67 protected:
Martin Radev5e424fa2017-08-09 16:25:36 +030068 FramebufferMultiviewSideBySideClearTest() {}
Martin Radev5c00d0d2017-08-07 10:06:59 +030069
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
Martin Radev5e424fa2017-08-09 16:25:36 +0300119 // Generate non-multiview fbo and attach textures.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300120 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 Radev5e424fa2017-08-09 16:25:36 +0300167class FramebufferMultiviewLayeredClearTest : public FramebufferMultiviewTest
168{
169 protected:
170 FramebufferMultiviewLayeredClearTest() {}
171
172 void initializeFBOs(int width,
173 int height,
174 int numLayers,
175 int baseViewIndex,
176 int numViews,
177 int numColorAttachments,
178 bool stencil,
179 bool depth)
180 {
181 ASSERT(baseViewIndex + numViews <= numLayers);
182
183 // Generate textures.
184 mColorTex.resize(numColorAttachments);
185 for (int i = 0; i < numColorAttachments; ++i)
186 {
187 glBindTexture(GL_TEXTURE_2D_ARRAY, mColorTex[i]);
188 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, width, height, numLayers, 0, GL_RGBA,
189 GL_UNSIGNED_BYTE, nullptr);
190 }
191
192 if (stencil)
193 {
194 glBindTexture(GL_TEXTURE_2D_ARRAY, mStencilTex);
195 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, width, height, numLayers, 0,
196 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
197 }
198 else if (depth)
199 {
200 glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthTex);
201 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, width, height, numLayers, 0,
202 GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
203 }
204
205 // Generate multiview FBO and attach textures.
206 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
207 for (int i = 0; i < numColorAttachments; ++i)
208 {
209 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER,
210 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i),
211 mColorTex[i], 0, baseViewIndex, numViews);
212 }
213
214 if (stencil)
215 {
216 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
217 mStencilTex, 0, baseViewIndex, numViews);
218 }
219 else if (depth)
220 {
221 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
222 mDepthTex, 0, baseViewIndex, numViews);
223 }
224
225 const auto &drawBuffers = GetDrawBufferRange(numColorAttachments);
226 glDrawBuffers(numColorAttachments, drawBuffers.data());
227
228 // Generate non-multiview FBOs and attach textures.
229 mNonMultiviewFBO.resize(numLayers);
230 for (int i = 0; i < numLayers; ++i)
231 {
232 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
233 for (int j = 0; j < numColorAttachments; ++j)
234 {
235 glFramebufferTextureLayer(GL_FRAMEBUFFER,
236 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + j),
237 mColorTex[j], 0, i);
238 }
239 if (stencil)
240 {
241 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, mStencilTex,
242 0, i);
243 }
244 else if (depth)
245 {
246 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTex, 0, i);
247 }
248 glDrawBuffers(numColorAttachments, drawBuffers.data());
249
250 glClearColor(1, 0, 0, 1);
251 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
252 }
253
254 ASSERT_GL_NO_ERROR();
255 }
256
257 GLColor getLayerColor(size_t layer, GLenum attachment, GLint x, GLint y)
258 {
259 ASSERT(layer < mNonMultiviewFBO.size());
260 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[layer]);
261 glReadBuffer(attachment);
262 return angle::ReadColor(x, y);
263 }
264
265 GLColor getLayerColor(size_t layer, GLenum attachment)
266 {
267 return getLayerColor(layer, attachment, 0, 0);
268 }
269
270 GLFramebuffer mMultiviewFBO;
271 std::vector<GLFramebuffer> mNonMultiviewFBO;
272 std::vector<GLTexture> mColorTex;
273 GLTexture mDepthTex;
274 GLTexture mStencilTex;
275};
276
277// Test that the framebuffer tokens introduced by ANGLE_multiview can be used to query the
278// framebuffer state and that their corresponding default values are correctly set.
Martin Radeve5285d22017-07-14 16:23:53 +0300279TEST_P(FramebufferMultiviewTest, DefaultState)
280{
Martin Radev137032d2017-07-13 10:11:12 +0300281 if (!requestMultiviewExtension())
Martin Radeve5285d22017-07-14 16:23:53 +0300282 {
Martin Radeve5285d22017-07-14 16:23:53 +0300283 return;
284 }
285
Martin Radev0f7714e2017-08-07 15:13:42 +0300286 GLFramebuffer fbo;
287 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
288
289 GLTexture tex;
290 glBindTexture(GL_TEXTURE_2D, tex);
291 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
292 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300293
Martin Radeve5285d22017-07-14 16:23:53 +0300294 GLint numViews = -1;
295 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
296 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
297 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +0300298 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300299 EXPECT_EQ(1, numViews);
300
301 GLint baseViewIndex = -1;
302 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
303 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
304 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +0300305 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300306 EXPECT_EQ(0, baseViewIndex);
307
308 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
309 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
310 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
311 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +0300312 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300313 EXPECT_EQ(GL_NONE, multiviewLayout);
314
315 GLint viewportOffsets[2] = {-1, -1};
316 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
317 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
318 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +0300319 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300320 EXPECT_EQ(0, viewportOffsets[0]);
321 EXPECT_EQ(0, viewportOffsets[1]);
322}
323
324// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
325// the ANGLE_multiview tokens results in an INVALID_ENUM error.
326TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
327{
Martin Radev0f7714e2017-08-07 15:13:42 +0300328 GLFramebuffer fbo;
329 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
330
331 GLTexture tex;
332 glBindTexture(GL_TEXTURE_2D, tex);
333 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
334 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300335
Martin Radeve5285d22017-07-14 16:23:53 +0300336 GLint numViews = -1;
337 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
338 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
339 &numViews);
340 EXPECT_GL_ERROR(GL_INVALID_ENUM);
341
342 GLint baseViewIndex = -1;
343 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
344 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
345 &baseViewIndex);
346 EXPECT_GL_ERROR(GL_INVALID_ENUM);
347
348 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
349 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
350 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
351 &multiviewLayout);
352 EXPECT_GL_ERROR(GL_INVALID_ENUM);
353
354 GLint viewportOffsets[2] = {-1, -1};
355 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
356 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
357 &viewportOffsets[0]);
358 EXPECT_GL_ERROR(GL_INVALID_ENUM);
359}
360
Martin Radev137032d2017-07-13 10:11:12 +0300361// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
362// is called with invalid arguments.
363TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
364{
365 if (!requestMultiviewExtension())
366 {
367 return;
368 }
369
Martin Radev0f7714e2017-08-07 15:13:42 +0300370 GLFramebuffer fbo;
371 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
372
373 GLTexture tex;
374 glBindTexture(GL_TEXTURE_2D, tex);
375 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
376
Martin Radev137032d2017-07-13 10:11:12 +0300377 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300378 GLint viewportOffsets[2] = {-1};
379 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
380 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300381 EXPECT_GL_ERROR(GL_INVALID_VALUE);
382
383 // Negative number of views.
384 viewportOffsets[0] = 0;
385 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300386 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1,
387 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300388 EXPECT_GL_ERROR(GL_INVALID_VALUE);
389}
390
391// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
392// called with invalid arguments.
393TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
394{
395 if (!requestMultiviewExtension())
396 {
397 return;
398 }
399
Martin Radev0f7714e2017-08-07 15:13:42 +0300400 GLFramebuffer fbo;
401 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
402
403 GLTexture tex;
404 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
405 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
406 ASSERT_GL_NO_ERROR();
407
Martin Radev137032d2017-07-13 10:11:12 +0300408 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300409 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300410 EXPECT_GL_ERROR(GL_INVALID_VALUE);
411
412 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
413 GLint maxTextureLayers = 0;
414 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300415 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
416 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300417 EXPECT_GL_ERROR(GL_INVALID_VALUE);
418}
419
420// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
421// available.
422TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
423{
Martin Radev0f7714e2017-08-07 15:13:42 +0300424 GLFramebuffer fbo;
425 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
426
427 GLTexture tex;
428 glBindTexture(GL_TEXTURE_2D, tex);
429 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
430
Martin Radev9bc9a322017-07-21 14:28:17 +0300431 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300432 const GLint kViewportOffsets[2] = {0};
433 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
434 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300435 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
436}
437
Martin Radev5dae57b2017-07-14 16:15:55 +0300438// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
439TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
440{
441 if (!requestMultiviewExtension())
442 {
443 return;
444 }
445
Martin Radev0f7714e2017-08-07 15:13:42 +0300446 GLFramebuffer fbo;
447 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
448
449 GLTexture tex;
450 glBindTexture(GL_TEXTURE_2D, tex);
451 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
452
453 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
454 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
455 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300456 ASSERT_GL_NO_ERROR();
457
458 GLint numViews = -1;
459 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
460 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
461 &numViews);
462 ASSERT_GL_NO_ERROR();
463 EXPECT_EQ(2, numViews);
464
465 GLint baseViewIndex = -1;
466 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
467 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
468 &baseViewIndex);
469 ASSERT_GL_NO_ERROR();
470 EXPECT_EQ(0, baseViewIndex);
471
472 GLint multiviewLayout = GL_NONE;
473 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
474 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
475 &multiviewLayout);
476 ASSERT_GL_NO_ERROR();
477 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
478
479 GLint internalViewportOffsets[4] = {-1};
480 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
481 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
482 &internalViewportOffsets[0]);
483 ASSERT_GL_NO_ERROR();
484 for (size_t i = 0u; i < 4u; ++i)
485 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300486 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300487 }
488}
489
Martin Radev9bc9a322017-07-21 14:28:17 +0300490// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
491// attachments.
492TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
493{
494 if (!requestMultiviewExtension())
495 {
496 return;
497 }
498
Martin Radev0f7714e2017-08-07 15:13:42 +0300499 GLFramebuffer fbo;
500 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300501
Martin Radev0f7714e2017-08-07 15:13:42 +0300502 GLTexture tex;
503 glBindTexture(GL_TEXTURE_2D, tex);
504 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300505
Martin Radev0f7714e2017-08-07 15:13:42 +0300506 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
507 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300508
509 // 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 +0300510 // attachment will be modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300511 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
512 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300513 ASSERT_GL_NO_ERROR();
514
515 // Color attachment 1.
516 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300517 GLTexture otherTex;
518 glBindTexture(GL_TEXTURE_2D, otherTex);
519 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
520
Martin Radev9bc9a322017-07-21 14:28:17 +0300521 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300522 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
523 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300524 ASSERT_GL_NO_ERROR();
525 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
526 glCheckFramebufferStatus(GL_FRAMEBUFFER));
527
528 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300529 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
530 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300531 ASSERT_GL_NO_ERROR();
532 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
533 glCheckFramebufferStatus(GL_FRAMEBUFFER));
534
535 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300536 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300537 ASSERT_GL_NO_ERROR();
538 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
539 glCheckFramebufferStatus(GL_FRAMEBUFFER));
540
541 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
542 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300543 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
544 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300545 ASSERT_GL_NO_ERROR();
546 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
547
548 // Reset attachment 1
549 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300550 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300551 }
552
553 // Depth attachment.
554 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300555 GLTexture depthTex;
556 glBindTexture(GL_TEXTURE_2D, depthTex);
557 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
558 nullptr);
559
Martin Radev9bc9a322017-07-21 14:28:17 +0300560 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300561 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
562 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300563 ASSERT_GL_NO_ERROR();
564 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
565 glCheckFramebufferStatus(GL_FRAMEBUFFER));
566
567 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300568 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
569 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300570 ASSERT_GL_NO_ERROR();
571 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
572 glCheckFramebufferStatus(GL_FRAMEBUFFER));
573
574 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300575 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300576 ASSERT_GL_NO_ERROR();
577 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
578 glCheckFramebufferStatus(GL_FRAMEBUFFER));
579
580 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
581 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300582 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
583 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300584 ASSERT_GL_NO_ERROR();
585 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
586 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300587}
588
Martin Radev04e2c3b2017-07-27 16:54:35 +0300589// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
590// attachments.
591TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
592{
593 if (!requestMultiviewExtension())
594 {
595 return;
596 }
597
Martin Radev0f7714e2017-08-07 15:13:42 +0300598 GLFramebuffer fbo;
599 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300600
Martin Radev0f7714e2017-08-07 15:13:42 +0300601 GLTexture tex;
602 glBindTexture(GL_TEXTURE_2D, tex);
603 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
604
605 const GLint kViewportOffsets[2] = {0};
606 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
607 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300608 ASSERT_GL_NO_ERROR();
609
610 // Test glCopyTexImage2D and glCopyTexSubImage2D.
611 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300612 GLTexture tex2;
613 glBindTexture(GL_TEXTURE_2D, tex2);
614 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300615
616 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
617 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
618
619 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
620 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300621 }
622
623 // Test glCopyTexSubImage3D.
624 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300625 GLTexture tex2;
626 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300627 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
628
629 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
630 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300631 }
632}
633
Martin Radeva3ed4572017-07-27 18:29:37 +0300634// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
635// draw framebuffer, or current read framebuffer have multiview attachments.
636TEST_P(FramebufferMultiviewTest, InvalidBlit)
637{
638 if (!requestMultiviewExtension())
639 {
640 return;
641 }
642
Martin Radev0f7714e2017-08-07 15:13:42 +0300643 GLFramebuffer fbo;
644 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300645
Martin Radev0f7714e2017-08-07 15:13:42 +0300646 GLTexture tex;
647 glBindTexture(GL_TEXTURE_2D, tex);
648 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
649
650 const GLint kViewportOffsets[2] = {0};
651 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
652 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300653 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
654 ASSERT_GL_NO_ERROR();
655
656 // Blit with the active read framebuffer having multiview attachments.
657 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300658 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300659 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
660 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
661 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
662 }
663
664 // Blit with the active draw framebuffer having multiview attachments.
665 {
666 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300667 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300668 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
669 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
670 }
671}
672
Martin Radev28031682017-07-28 14:47:56 +0300673// Test that glReadPixels generates an invalid framebuffer operation error if the current read
674// framebuffer has a multi-view layout.
675TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
676{
677 if (!requestMultiviewExtension())
678 {
679 return;
680 }
681
Martin Radev0f7714e2017-08-07 15:13:42 +0300682 GLFramebuffer fbo;
683 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300684
Martin Radev0f7714e2017-08-07 15:13:42 +0300685 GLTexture tex;
686 glBindTexture(GL_TEXTURE_2D, tex);
687 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
688
689 const GLint kViewportOffsets[2] = {0};
690 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
691 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300692 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
693 ASSERT_GL_NO_ERROR();
694
695 GLColor pixelColor;
696 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
697 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
698}
699
Martin Radeveef80e42017-08-11 14:44:57 +0300700// Test that glClear clears only the contents of each view if the scissor test is enabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300701TEST_P(FramebufferMultiviewSideBySideClearTest, ColorBufferClear)
Martin Radevb0761932017-07-25 17:42:25 +0300702{
703 if (!requestMultiviewExtension())
704 {
705 return;
706 }
707
Martin Radev5c00d0d2017-08-07 10:06:59 +0300708 initializeFBOs(1, false, false);
Martin Radevb0761932017-07-25 17:42:25 +0300709
710 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300711 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
712 glClearColor(1, 0, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300713 glClear(GL_COLOR_BUFFER_BIT);
714
715 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300716 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300717 glViewport(0, 0, 1, 2);
718 glScissor(0, 0, 1, 2);
Martin Radeveef80e42017-08-11 14:44:57 +0300719 glEnable(GL_SCISSOR_TEST);
Martin Radevb0761932017-07-25 17:42:25 +0300720
Martin Radev5c00d0d2017-08-07 10:06:59 +0300721 glClearColor(0, 1, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300722 glClear(GL_COLOR_BUFFER_BIT);
723
Martin Radev5c00d0d2017-08-07 10:06:59 +0300724 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300725
Martin Radev5c00d0d2017-08-07 10:06:59 +0300726 checkAlternatingColumnsOfRedAndGreenInFBO();
Martin Radevb0761932017-07-25 17:42:25 +0300727}
728
Martin Radev82ef7742017-08-08 17:44:58 +0300729// Test that glFramebufferTextureMultiviewLayeredANGLE modifies the internal multiview state.
730TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
731{
732 if (!requestMultiviewExtension())
733 {
734 return;
735 }
736
737 GLFramebuffer multiviewFBO;
738 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
739
740 GLTexture tex;
741 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
742 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
743 ASSERT_GL_NO_ERROR();
744
745 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
746 ASSERT_GL_NO_ERROR();
747
748 GLint numViews = -1;
749 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
750 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
751 &numViews);
752 ASSERT_GL_NO_ERROR();
753 EXPECT_EQ(2, numViews);
754
755 GLint baseViewIndex = -1;
756 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
757 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
758 &baseViewIndex);
759 ASSERT_GL_NO_ERROR();
760 EXPECT_EQ(1, baseViewIndex);
761
762 GLint multiviewLayout = GL_NONE;
763 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
764 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
765 &multiviewLayout);
766 ASSERT_GL_NO_ERROR();
767 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, multiviewLayout);
768
769 GLint internalViewportOffsets[2] = {-1};
770 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
771 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
772 &internalViewportOffsets[0]);
773 ASSERT_GL_NO_ERROR();
774 EXPECT_EQ(0, internalViewportOffsets[0]);
775 EXPECT_EQ(0, internalViewportOffsets[1]);
776}
777
778// Test framebuffer completeness status of a layered framebuffer with color attachments.
779TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
780{
781 if (!requestMultiviewExtension())
782 {
783 return;
784 }
785
786 GLFramebuffer fbo;
787 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
788
789 GLTexture tex;
790 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
791 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
792
793 // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
794 // attachment will be modified to change the framebuffer's status.
795 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
796 ASSERT_GL_NO_ERROR();
797
798 GLTexture otherTexLayered;
799 glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
800 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
801
802 // Test framebuffer completeness when the base view index differs.
803 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
804 0, 1, 2);
805 ASSERT_GL_NO_ERROR();
806 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
807 glCheckFramebufferStatus(GL_FRAMEBUFFER));
808
809 // Test framebuffer completeness when the 1st attachment has a side-by-side layout.
810 const int kViewportOffsets[4] = {0, 0, 0, 0};
811 GLTexture otherTex2D;
812 glBindTexture(GL_TEXTURE_2D, otherTex2D);
813 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
814 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex2D,
815 0, 2, kViewportOffsets);
816 ASSERT_GL_NO_ERROR();
817 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
818 glCheckFramebufferStatus(GL_FRAMEBUFFER));
819
Martin Radev5e424fa2017-08-09 16:25:36 +0300820 // Test framebuffer completeness when the 1st attachment has a non-multiview layout.
Martin Radev82ef7742017-08-08 17:44:58 +0300821 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
822 ASSERT_GL_NO_ERROR();
823 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
824 glCheckFramebufferStatus(GL_FRAMEBUFFER));
825
826 // Test that framebuffer is complete when the number of views, base view index and layouts are
827 // the same.
828 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
829 0, 0, 2);
830 ASSERT_GL_NO_ERROR();
831 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
832}
833
Martin Radeveef80e42017-08-11 14:44:57 +0300834// Test that glClear clears all of the contents if the scissor test is disabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300835TEST_P(FramebufferMultiviewSideBySideClearTest, ClearWithDisabledScissorTest)
Martin Radeveef80e42017-08-11 14:44:57 +0300836{
837 if (!requestMultiviewExtension())
838 {
839 return;
840 }
841
Martin Radev5c00d0d2017-08-07 10:06:59 +0300842 initializeFBOs(1, false, false);
Martin Radeveef80e42017-08-11 14:44:57 +0300843
844 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300845 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
846 glClearColor(0, 0, 0, 1);
Martin Radeveef80e42017-08-11 14:44:57 +0300847 glClear(GL_COLOR_BUFFER_BIT);
848
849 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300850 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300851 glViewport(0, 0, 1, 2);
852 glScissor(0, 0, 1, 2);
853
854 glClearColor(1, 0, 0, 1);
855 glClear(GL_COLOR_BUFFER_BIT);
856
Martin Radev5c00d0d2017-08-07 10:06:59 +0300857 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300858
859 for (int i = 0; i < 4; ++i)
860 {
861 for (int j = 0; j < 2; ++j)
862 {
863 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
864 }
865 }
866}
867
Martin Radev5c00d0d2017-08-07 10:06:59 +0300868// Test that glClear clears the depth buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300869TEST_P(FramebufferMultiviewSideBySideClearTest, DepthBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +0300870{
871 if (!requestMultiviewExtension())
872 {
873 return;
874 }
875
876 // Create program to draw a quad.
877 const std::string &vs =
878 "#version 300 es\n"
879 "in vec3 vPos;\n"
880 "void main(){\n"
881 " gl_Position = vec4(vPos, 1.);\n"
882 "}\n";
883 const std::string &fs =
884 "#version 300 es\n"
885 "precision mediump float;\n"
886 "uniform vec3 uCol;\n"
887 "out vec4 col;\n"
888 "void main(){\n"
889 " col = vec4(uCol,1.);\n"
890 "}\n";
891 ANGLE_GL_PROGRAM(program, vs, fs);
892 glUseProgram(program);
893 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
894
895 initializeFBOs(1, false, true);
896 glEnable(GL_DEPTH_TEST);
897
898 // Clear the contents of the texture.
899 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
900 glClearColor(0, 0, 0, 0);
901 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
902
903 // Dirty the depth and color buffers.
904 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
905 drawQuad(program, "vPos", 0.0f, 1.0f, true);
906
907 // Switch to the multi-view framebuffer and clear only the rectangles covered by the views.
908 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
909 glViewport(0, 0, 1, 2);
910 glScissor(0, 0, 1, 2);
911 glEnable(GL_SCISSOR_TEST);
912 glClear(GL_DEPTH_BUFFER_BIT);
913
914 // Draw a fullscreen quad to fill the cleared regions.
915 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
916 glViewport(0, 0, 4, 2);
917 glScissor(0, 0, 4, 2);
918 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
919 drawQuad(program, "vPos", 0.5f, 1.0f, true);
920
921 checkAlternatingColumnsOfRedAndGreenInFBO();
922}
923
924// Test that glClear clears the stencil buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300925TEST_P(FramebufferMultiviewSideBySideClearTest, StencilBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +0300926{
927 if (!requestMultiviewExtension())
928 {
929 return;
930 }
931
932 // Create program to draw a quad.
933 const std::string &vs =
934 "#version 300 es\n"
935 "in vec3 vPos;\n"
936 "void main(){\n"
937 " gl_Position = vec4(vPos, 1.);\n"
938 "}\n";
939 const std::string &fs =
940 "#version 300 es\n"
941 "precision mediump float;\n"
942 "uniform vec3 uCol;\n"
943 "out vec4 col;\n"
944 "void main(){\n"
945 " col = vec4(uCol,1.);\n"
946 "}\n";
947 ANGLE_GL_PROGRAM(program, vs, fs);
948 glUseProgram(program);
949 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
950
951 initializeFBOs(1, true, false);
952 glEnable(GL_STENCIL_TEST);
953 glDisable(GL_DEPTH_TEST);
954
955 // Set clear values and clear the whole framebuffer.
956 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
957 glClearColor(0, 0, 0, 0);
958 glClearStencil(0);
959 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
960
961 // Update stencil test to always replace the stencil value with 0xFF.
962 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
963 glStencilFunc(GL_ALWAYS, 0xFF, 0);
964
965 // Draw a quad which covers the whole texture.
966 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
967 drawQuad(program, "vPos", 0.0f, 1.0f, true);
968
969 // Switch to multiview framebuffer and clear portions of the texture.
970 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
971 glViewport(0, 0, 1, 2);
972 glScissor(0, 0, 1, 2);
973 glEnable(GL_SCISSOR_TEST);
974 glClear(GL_STENCIL_BUFFER_BIT);
975
976 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
977 // the test.
978 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
979 glViewport(0, 0, 4, 2);
980 glScissor(0, 0, 4, 2);
981 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
982 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
983 drawQuad(program, "vPos", 0.0f, 1.0f, true);
984
985 checkAlternatingColumnsOfRedAndGreenInFBO();
986}
987
988// Test that glClearBufferf clears the color buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300989TEST_P(FramebufferMultiviewSideBySideClearTest, ClearBufferF)
Martin Radev5c00d0d2017-08-07 10:06:59 +0300990{
991 if (!requestMultiviewExtension())
992 {
993 return;
994 }
995
996 initializeFBOs(2, false, false);
997
998 // Clear the contents of the texture.
999 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1000 glClearColor(1, 0, 0, 1);
1001 glClear(GL_COLOR_BUFFER_BIT);
1002
1003 // Bind and specify viewport/scissor dimensions for each view.
1004 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1005 glViewport(0, 0, 1, 2);
1006 glScissor(0, 0, 1, 2);
1007 glEnable(GL_SCISSOR_TEST);
1008
1009 float kClearValues[4] = {0.f, 1.f, 0.f, 1.f};
1010 glClearBufferfv(GL_COLOR, 1, kClearValues);
1011
1012 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1013
1014 // Check that glClearBufferfv has not modified the 0th color attachment.
1015 glReadBuffer(GL_COLOR_ATTACHMENT0);
1016 for (int i = 0; i < 4; ++i)
1017 {
1018 for (int j = 0; j < 2; ++j)
1019 {
1020 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
1021 }
1022 }
1023
1024 // Check that glClearBufferfv has correctly modified the 1th color attachment.
1025 glReadBuffer(GL_COLOR_ATTACHMENT1);
1026 checkAlternatingColumnsOfRedAndGreenInFBO();
1027}
1028
Martin Radev5e424fa2017-08-09 16:25:36 +03001029// Test that glClear clears the contents of the color buffer for only the attached layers to a
1030// layered FBO.
1031TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
1032{
1033 if (!requestMultiviewExtension())
1034 {
1035 return;
1036 }
1037
1038 initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
1039
1040 // Bind and specify viewport/scissor dimensions for each view.
1041 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1042
1043 glClearColor(0, 1, 0, 1);
1044 glClear(GL_COLOR_BUFFER_BIT);
1045
1046 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1047 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1048 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1049 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1050}
1051
1052// Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
1053TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
1054{
1055 if (!requestMultiviewExtension())
1056 {
1057 return;
1058 }
1059
1060 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1061
1062 for (int i = 0; i < 2; ++i)
1063 {
1064 for (int layer = 0; layer < 4; ++layer)
1065 {
1066 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
1067 EXPECT_EQ(GLColor::red, getLayerColor(layer, colorAttachment));
1068 }
1069 }
1070
1071 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1072
1073 float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
1074 glClearBufferfv(GL_COLOR, 0, clearValues0);
1075
1076 float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
1077 glClearBufferfv(GL_COLOR, 1, clearValues1);
1078
1079 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1080 EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1081 EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1082 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1083
1084 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT1));
1085 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1086 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
1087 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT1));
1088}
1089
1090// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1091// to a layered FBO.
1092TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
1093{
1094 if (!requestMultiviewExtension())
1095 {
1096 return;
1097 }
1098
1099 // Create program to draw a quad.
1100 const std::string &vs =
1101 "#version 300 es\n"
1102 "in vec3 vPos;\n"
1103 "void main(){\n"
1104 " gl_Position = vec4(vPos, 1.);\n"
1105 "}\n";
1106 const std::string &fs =
1107 "#version 300 es\n"
1108 "precision mediump float;\n"
1109 "uniform vec3 uCol;\n"
1110 "out vec4 col;\n"
1111 "void main(){\n"
1112 " col = vec4(uCol,1.);\n"
1113 "}\n";
1114 ANGLE_GL_PROGRAM(program, vs, fs);
1115 glUseProgram(program);
1116 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1117
1118 initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
1119 glEnable(GL_STENCIL_TEST);
1120 glDisable(GL_DEPTH_TEST);
1121
1122 // Set clear values.
1123 glClearColor(1, 0, 0, 1);
1124 glClearStencil(0xFF);
1125
1126 // Clear the color and stencil buffers of each layer.
1127 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1128 {
1129 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1130 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1131 }
1132
1133 // Switch to multiview framebuffer and clear portions of the texture.
1134 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1135 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1136
1137 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1138 // the test.
1139 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1140 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1141 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1142 {
1143 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1144 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1145 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1146 }
1147 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1148 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1149 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1150 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1151}
1152
1153// Test that glClear does not clear the content of a detached texture.
1154TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
1155{
1156 if (!requestMultiviewExtension())
1157 {
1158 return;
1159 }
1160
1161 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1162
1163 // Clear all attachments.
1164 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1165 glClearColor(0, 1, 0, 1);
1166 glClear(GL_COLOR_BUFFER_BIT);
1167
1168 for (int i = 0; i < 2; ++i)
1169 {
1170 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
1171 EXPECT_EQ(GLColor::red, getLayerColor(0, colorAttachment));
1172 EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
1173 EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
1174 EXPECT_EQ(GLColor::red, getLayerColor(3, colorAttachment));
1175 }
1176
1177 // Detach and clear again.
1178 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1179 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
1180 glClearColor(1, 1, 0, 1);
1181 glClear(GL_COLOR_BUFFER_BIT);
1182
1183 // Check that color attachment 0 is modified.
1184 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1185 EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1186 EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1187 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1188
1189 // Check that color attachment 1 is unmodified.
1190 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT1));
1191 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1192 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
1193 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT1));
1194}
1195
1196// Test that glClear clears only the contents within the scissor rectangle of the attached layers.
1197TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
1198{
1199 if (!requestMultiviewExtension())
1200 {
1201 return;
1202 }
1203
1204 initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
1205
1206 // Bind and specify viewport/scissor dimensions for each view.
1207 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1208
1209 glEnable(GL_SCISSOR_TEST);
1210 glScissor(1, 0, 1, 1);
1211 glClearColor(0, 1, 0, 1);
1212 glClear(GL_COLOR_BUFFER_BIT);
1213
1214 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1215 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
1216
1217 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1218 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
1219
1220 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1221 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
1222
1223 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1224 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
1225}
1226
Martin Radev18b75ba2017-08-15 15:50:40 +03001227// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1228// to a layered FBO.
1229TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
1230{
1231 if (!requestMultiviewExtension())
1232 {
1233 return;
1234 }
1235
1236 // Create program to draw a quad.
1237 const std::string &vs =
1238 "#version 300 es\n"
1239 "in vec3 vPos;\n"
1240 "void main(){\n"
1241 " gl_Position = vec4(vPos, 1.);\n"
1242 "}\n";
1243 const std::string &fs =
1244 "#version 300 es\n"
1245 "precision mediump float;\n"
1246 "uniform vec3 uCol;\n"
1247 "out vec4 col;\n"
1248 "void main(){\n"
1249 " col = vec4(uCol,1.);\n"
1250 "}\n";
1251 ANGLE_GL_PROGRAM(program, vs, fs);
1252 glUseProgram(program);
1253 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1254
1255 initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
1256 glEnable(GL_STENCIL_TEST);
1257 glDisable(GL_DEPTH_TEST);
1258
1259 // Set clear values.
1260 glClearColor(1, 0, 0, 1);
1261 glClearStencil(0xFF);
1262
1263 // Clear the color and stencil buffers of each layer.
1264 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1265 {
1266 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1267 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1268 }
1269
1270 // Switch to multiview framebuffer and clear portions of the texture.
1271 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1272 glEnable(GL_SCISSOR_TEST);
1273 glScissor(0, 0, 1, 1);
1274 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1275 glDisable(GL_SCISSOR_TEST);
1276
1277 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1278 // the test.
1279 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1280 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1281 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1282 {
1283 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1284 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1285 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1286 }
1287 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1288 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
1289 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1290 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
1291 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1292 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
1293 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1294 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
1295}
1296
Martin Radev14b21262017-08-25 13:54:37 +03001297// Test that detaching an attachment does not generate an error whenever the multi-view related
1298// arguments are invalid.
1299TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
1300{
1301 if (!requestMultiviewExtension())
1302 {
1303 return;
1304 }
1305
1306 GLFramebuffer fbo;
1307 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1308
1309 // Invalid base view index.
1310 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
1311 EXPECT_GL_NO_ERROR();
1312
1313 // Invalid number of views.
1314 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
1315 EXPECT_GL_NO_ERROR();
1316
1317 // Invalid number of views.
1318 const GLint kValidViewportOffsets[2] = {0, 0};
1319 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0,
1320 kValidViewportOffsets);
1321 EXPECT_GL_NO_ERROR();
1322
1323 // Invalid viewport offsets.
1324 const GLint kInvalidViewportOffsets[2] = {-1, -1};
1325 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 1,
1326 kInvalidViewportOffsets);
1327 EXPECT_GL_NO_ERROR();
1328}
1329
Martin Radev61e710b2017-09-05 11:59:52 +03001330// Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
1331// array are attached. The test is added because a special fast code path is used for this case.
1332TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
1333{
1334 if (!requestMultiviewExtension())
1335 {
1336 return;
1337 }
1338
1339 initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
1340
1341 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1342 glClearColor(0, 1, 0, 1);
1343 glClear(GL_COLOR_BUFFER_BIT);
1344
1345 EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1346 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1347}
1348
Martin Radev5c00d0d2017-08-07 10:06:59 +03001349ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, ES3_OPENGL());
Martin Radev5e424fa2017-08-09 16:25:36 +03001350ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest, ES3_OPENGL(), ES3_D3D11());
Martin Radev18b75ba2017-08-15 15:50:40 +03001351ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest, ES3_OPENGL(), ES3_D3D11());