blob: 5552ba0d605d2fb7372188c3471491465469a443 [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 {
Martin Radev137032d2017-07-13 10:11:12 +030056 return false;
57 }
58 return true;
59 }
60
Martin Radeve5285d22017-07-14 16:23:53 +030061 PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
62};
63
Martin Radev5e424fa2017-08-09 16:25:36 +030064class FramebufferMultiviewSideBySideClearTest : public FramebufferMultiviewTest
Martin Radev5c00d0d2017-08-07 10:06:59 +030065{
66 protected:
Martin Radev5e424fa2017-08-09 16:25:36 +030067 FramebufferMultiviewSideBySideClearTest() {}
Martin Radev5c00d0d2017-08-07 10:06:59 +030068
69 void initializeFBOs(size_t numColorBuffers, bool stencil, bool depth)
70 {
71 const std::vector<GLenum> &drawBuffers = GetDrawBufferRange(2);
72
73 // Generate textures.
74 mColorTex.resize(numColorBuffers);
75 for (size_t i = 0u; i < numColorBuffers; ++i)
76 {
77 glBindTexture(GL_TEXTURE_2D, mColorTex[i]);
78 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
79 }
80
81 if (stencil)
82 {
83 glBindTexture(GL_TEXTURE_2D, mStencilTex);
84 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 4, 2, 0, GL_DEPTH_STENCIL,
85 GL_UNSIGNED_INT_24_8, nullptr);
86 }
87 else if (depth)
88 {
89 glBindTexture(GL_TEXTURE_2D, mDepthTex);
90 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 4, 2, 0, GL_DEPTH_COMPONENT,
91 GL_FLOAT, nullptr);
92 }
93
94 // Generate multiview fbo and attach textures.
95 const GLint kViewportOffsets[4] = {1, 0, 3, 0};
96 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
97 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
98 for (size_t i = 0u; i < numColorBuffers; ++i)
99 {
100 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
101 static_cast<GLenum>(kBase + i),
102 mColorTex[i], 0, 2, &kViewportOffsets[0]);
103 }
104
105 if (stencil)
106 {
107 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
108 GL_DEPTH_STENCIL_ATTACHMENT, mStencilTex,
109 0, 2, &kViewportOffsets[0]);
110 }
111 else if (depth)
112 {
113 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
114 mDepthTex, 0, 2, &kViewportOffsets[0]);
115 }
116 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
117
Martin Radev5e424fa2017-08-09 16:25:36 +0300118 // Generate non-multiview fbo and attach textures.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300119 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
120 for (size_t i = 0u; i < numColorBuffers; ++i)
121 {
122 glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(kBase + i), GL_TEXTURE_2D,
123 mColorTex[i], 0);
124 }
125 if (stencil)
126 {
127 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
128 mStencilTex, 0);
129 }
130 else if (depth)
131 {
132 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTex,
133 0);
134 }
135 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
136
137 ASSERT_GL_NO_ERROR();
138 }
139
140 void checkAlternatingColumnsOfRedAndGreenInFBO()
141 {
142 // column 0
143 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
144 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::red);
145
146 // column 1
147 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
148 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
149
150 // column 2
151 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::red);
152 EXPECT_PIXEL_COLOR_EQ(2, 1, GLColor::red);
153
154 // column 3
155 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
156 EXPECT_PIXEL_COLOR_EQ(3, 1, GLColor::green);
157 }
158
159 GLFramebuffer mMultiviewFBO;
160 GLFramebuffer mNonMultiviewFBO;
161 std::vector<GLTexture> mColorTex;
162 GLTexture mDepthTex;
163 GLTexture mStencilTex;
164};
165
Martin Radev5e424fa2017-08-09 16:25:36 +0300166class FramebufferMultiviewLayeredClearTest : public FramebufferMultiviewTest
167{
168 protected:
169 FramebufferMultiviewLayeredClearTest() {}
170
171 void initializeFBOs(int width,
172 int height,
173 int numLayers,
174 int baseViewIndex,
175 int numViews,
176 int numColorAttachments,
177 bool stencil,
178 bool depth)
179 {
180 ASSERT(baseViewIndex + numViews <= numLayers);
181
182 // Generate textures.
183 mColorTex.resize(numColorAttachments);
184 for (int i = 0; i < numColorAttachments; ++i)
185 {
186 glBindTexture(GL_TEXTURE_2D_ARRAY, mColorTex[i]);
187 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, width, height, numLayers, 0, GL_RGBA,
188 GL_UNSIGNED_BYTE, nullptr);
189 }
190
191 if (stencil)
192 {
193 glBindTexture(GL_TEXTURE_2D_ARRAY, mStencilTex);
194 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, width, height, numLayers, 0,
195 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
196 }
197 else if (depth)
198 {
199 glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthTex);
200 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, width, height, numLayers, 0,
201 GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
202 }
203
204 // Generate multiview FBO and attach textures.
205 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
206 for (int i = 0; i < numColorAttachments; ++i)
207 {
208 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER,
209 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i),
210 mColorTex[i], 0, baseViewIndex, numViews);
211 }
212
213 if (stencil)
214 {
215 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
216 mStencilTex, 0, baseViewIndex, numViews);
217 }
218 else if (depth)
219 {
220 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
221 mDepthTex, 0, baseViewIndex, numViews);
222 }
223
224 const auto &drawBuffers = GetDrawBufferRange(numColorAttachments);
225 glDrawBuffers(numColorAttachments, drawBuffers.data());
226
227 // Generate non-multiview FBOs and attach textures.
228 mNonMultiviewFBO.resize(numLayers);
229 for (int i = 0; i < numLayers; ++i)
230 {
231 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
232 for (int j = 0; j < numColorAttachments; ++j)
233 {
234 glFramebufferTextureLayer(GL_FRAMEBUFFER,
235 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + j),
236 mColorTex[j], 0, i);
237 }
238 if (stencil)
239 {
240 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, mStencilTex,
241 0, i);
242 }
243 else if (depth)
244 {
245 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTex, 0, i);
246 }
247 glDrawBuffers(numColorAttachments, drawBuffers.data());
248
249 glClearColor(1, 0, 0, 1);
250 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
251 }
252
253 ASSERT_GL_NO_ERROR();
254 }
255
256 GLColor getLayerColor(size_t layer, GLenum attachment, GLint x, GLint y)
257 {
258 ASSERT(layer < mNonMultiviewFBO.size());
259 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[layer]);
260 glReadBuffer(attachment);
261 return angle::ReadColor(x, y);
262 }
263
264 GLColor getLayerColor(size_t layer, GLenum attachment)
265 {
266 return getLayerColor(layer, attachment, 0, 0);
267 }
268
269 GLFramebuffer mMultiviewFBO;
270 std::vector<GLFramebuffer> mNonMultiviewFBO;
271 std::vector<GLTexture> mColorTex;
272 GLTexture mDepthTex;
273 GLTexture mStencilTex;
274};
275
276// Test that the framebuffer tokens introduced by ANGLE_multiview can be used to query the
277// framebuffer state and that their corresponding default values are correctly set.
Martin Radeve5285d22017-07-14 16:23:53 +0300278TEST_P(FramebufferMultiviewTest, DefaultState)
279{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300280 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeve5285d22017-07-14 16:23:53 +0300281
Martin Radev0f7714e2017-08-07 15:13:42 +0300282 GLFramebuffer fbo;
283 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
284
285 GLTexture tex;
286 glBindTexture(GL_TEXTURE_2D, tex);
287 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
288 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300289
Martin Radeve5285d22017-07-14 16:23:53 +0300290 GLint numViews = -1;
291 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
292 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
293 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +0300294 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300295 EXPECT_EQ(1, numViews);
296
297 GLint baseViewIndex = -1;
298 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
299 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
300 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +0300301 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300302 EXPECT_EQ(0, baseViewIndex);
303
304 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
305 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
306 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
307 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +0300308 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300309 EXPECT_EQ(GL_NONE, multiviewLayout);
310
311 GLint viewportOffsets[2] = {-1, -1};
312 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
313 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
314 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +0300315 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300316 EXPECT_EQ(0, viewportOffsets[0]);
317 EXPECT_EQ(0, viewportOffsets[1]);
318}
319
320// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
321// the ANGLE_multiview tokens results in an INVALID_ENUM error.
322TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
323{
Martin Radev0f7714e2017-08-07 15:13:42 +0300324 GLFramebuffer fbo;
325 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
326
327 GLTexture tex;
328 glBindTexture(GL_TEXTURE_2D, tex);
329 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
330 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300331
Martin Radeve5285d22017-07-14 16:23:53 +0300332 GLint numViews = -1;
333 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
334 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
335 &numViews);
336 EXPECT_GL_ERROR(GL_INVALID_ENUM);
337
338 GLint baseViewIndex = -1;
339 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
340 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
341 &baseViewIndex);
342 EXPECT_GL_ERROR(GL_INVALID_ENUM);
343
344 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
345 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
346 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
347 &multiviewLayout);
348 EXPECT_GL_ERROR(GL_INVALID_ENUM);
349
350 GLint viewportOffsets[2] = {-1, -1};
351 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
352 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
353 &viewportOffsets[0]);
354 EXPECT_GL_ERROR(GL_INVALID_ENUM);
355}
356
Martin Radev137032d2017-07-13 10:11:12 +0300357// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
358// is called with invalid arguments.
359TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
360{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300361 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300362
Martin Radev0f7714e2017-08-07 15:13:42 +0300363 GLFramebuffer fbo;
364 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
365
366 GLTexture tex;
367 glBindTexture(GL_TEXTURE_2D, tex);
368 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
369
Martin Radev137032d2017-07-13 10:11:12 +0300370 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300371 GLint viewportOffsets[2] = {-1};
372 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
373 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300374 EXPECT_GL_ERROR(GL_INVALID_VALUE);
375
376 // Negative number of views.
377 viewportOffsets[0] = 0;
378 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300379 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
384// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
385// called with invalid arguments.
386TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
387{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300388 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300389
Martin Radev0f7714e2017-08-07 15:13:42 +0300390 GLFramebuffer fbo;
391 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
392
393 GLTexture tex;
394 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
395 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
396 ASSERT_GL_NO_ERROR();
397
Martin Radev137032d2017-07-13 10:11:12 +0300398 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300399 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300400 EXPECT_GL_ERROR(GL_INVALID_VALUE);
401
402 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
403 GLint maxTextureLayers = 0;
404 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300405 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
406 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300407 EXPECT_GL_ERROR(GL_INVALID_VALUE);
408}
409
410// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
411// available.
412TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
413{
Martin Radev0f7714e2017-08-07 15:13:42 +0300414 GLFramebuffer fbo;
415 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
416
417 GLTexture tex;
418 glBindTexture(GL_TEXTURE_2D, tex);
419 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
420
Martin Radev9bc9a322017-07-21 14:28:17 +0300421 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300422 const GLint kViewportOffsets[2] = {0};
423 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
424 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300425 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
426}
427
Martin Radev5dae57b2017-07-14 16:15:55 +0300428// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
429TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
430{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300431 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5dae57b2017-07-14 16:15:55 +0300432
Martin Radev0f7714e2017-08-07 15:13:42 +0300433 GLFramebuffer fbo;
434 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
435
436 GLTexture tex;
437 glBindTexture(GL_TEXTURE_2D, tex);
438 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
439
440 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
441 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
442 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300443 ASSERT_GL_NO_ERROR();
444
445 GLint numViews = -1;
446 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
447 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
448 &numViews);
449 ASSERT_GL_NO_ERROR();
450 EXPECT_EQ(2, numViews);
451
452 GLint baseViewIndex = -1;
453 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
454 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
455 &baseViewIndex);
456 ASSERT_GL_NO_ERROR();
457 EXPECT_EQ(0, baseViewIndex);
458
459 GLint multiviewLayout = GL_NONE;
460 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
461 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
462 &multiviewLayout);
463 ASSERT_GL_NO_ERROR();
464 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
465
466 GLint internalViewportOffsets[4] = {-1};
467 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
468 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
469 &internalViewportOffsets[0]);
470 ASSERT_GL_NO_ERROR();
471 for (size_t i = 0u; i < 4u; ++i)
472 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300473 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300474 }
475}
476
Martin Radev9bc9a322017-07-21 14:28:17 +0300477// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
478// attachments.
479TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
480{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300481 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev9bc9a322017-07-21 14:28:17 +0300482
Martin Radev0f7714e2017-08-07 15:13:42 +0300483 GLFramebuffer fbo;
484 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300485
Martin Radev0f7714e2017-08-07 15:13:42 +0300486 GLTexture tex;
487 glBindTexture(GL_TEXTURE_2D, tex);
488 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300489
Martin Radev0f7714e2017-08-07 15:13:42 +0300490 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
491 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300492
493 // 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 +0300494 // attachment will be modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300495 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
496 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300497 ASSERT_GL_NO_ERROR();
498
499 // Color attachment 1.
500 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300501 GLTexture otherTex;
502 glBindTexture(GL_TEXTURE_2D, otherTex);
503 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
504
Martin Radev9bc9a322017-07-21 14:28:17 +0300505 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300506 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
507 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300508 ASSERT_GL_NO_ERROR();
509 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
510 glCheckFramebufferStatus(GL_FRAMEBUFFER));
511
512 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300513 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
514 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300515 ASSERT_GL_NO_ERROR();
516 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
517 glCheckFramebufferStatus(GL_FRAMEBUFFER));
518
519 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300520 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300521 ASSERT_GL_NO_ERROR();
522 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
523 glCheckFramebufferStatus(GL_FRAMEBUFFER));
524
525 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
526 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300527 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
528 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300529 ASSERT_GL_NO_ERROR();
530 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
531
532 // Reset attachment 1
533 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300534 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300535 }
536
537 // Depth attachment.
538 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300539 GLTexture depthTex;
540 glBindTexture(GL_TEXTURE_2D, depthTex);
541 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
542 nullptr);
543
Martin Radev9bc9a322017-07-21 14:28:17 +0300544 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300545 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
546 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300547 ASSERT_GL_NO_ERROR();
548 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
549 glCheckFramebufferStatus(GL_FRAMEBUFFER));
550
551 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300552 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
553 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300554 ASSERT_GL_NO_ERROR();
555 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
556 glCheckFramebufferStatus(GL_FRAMEBUFFER));
557
558 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300559 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300560 ASSERT_GL_NO_ERROR();
561 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
562 glCheckFramebufferStatus(GL_FRAMEBUFFER));
563
564 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
565 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300566 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
567 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300568 ASSERT_GL_NO_ERROR();
569 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
570 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300571}
572
Martin Radev04e2c3b2017-07-27 16:54:35 +0300573// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300574// attachments with a side-by-side layout.
Martin Radev04e2c3b2017-07-27 16:54:35 +0300575TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
576{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300577 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev04e2c3b2017-07-27 16:54:35 +0300578
Martin Radev0f7714e2017-08-07 15:13:42 +0300579 GLFramebuffer fbo;
580 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300581
Martin Radev0f7714e2017-08-07 15:13:42 +0300582 GLTexture tex;
583 glBindTexture(GL_TEXTURE_2D, tex);
584 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
585
586 const GLint kViewportOffsets[2] = {0};
587 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
588 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300589 ASSERT_GL_NO_ERROR();
590
591 // Test glCopyTexImage2D and glCopyTexSubImage2D.
592 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300593 GLTexture tex2;
594 glBindTexture(GL_TEXTURE_2D, tex2);
595 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300596
597 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
598 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
599
600 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
601 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300602 }
603
604 // Test glCopyTexSubImage3D.
605 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300606 GLTexture tex2;
607 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300608 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
609
610 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
611 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300612 }
613}
614
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300615// Test that the active read framebuffer can be read with glCopyTex* if it only has one layered
616// view.
617TEST_P(FramebufferMultiviewTest, CopyTex)
618{
619 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
620
621 GLFramebuffer fbo;
622 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
623
624 GLTexture tex;
625 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
626 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
627
628 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
629 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
630 ASSERT_GL_NO_ERROR();
631
632 // Test glCopyTexImage2D and glCopyTexSubImage2D.
633 {
634 GLTexture tex2;
635 glBindTexture(GL_TEXTURE_2D, tex2);
636 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
637
638 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
639 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
640 glClear(GL_COLOR_BUFFER_BIT);
641
642 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
643 ASSERT_GL_NO_ERROR();
644
645 // Test texture contents.
646 glBindFramebuffer(GL_FRAMEBUFFER, 0);
647 draw2DTexturedQuad(0.0f, 1.0f, true);
648 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
649
650 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
651 glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
652 glClear(GL_COLOR_BUFFER_BIT);
653
654 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
655 ASSERT_GL_NO_ERROR();
656
657 glBindFramebuffer(GL_FRAMEBUFFER, 0);
658 draw2DTexturedQuad(0.0f, 1.0f, true);
659 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
660 }
661
662 // Test glCopyTexSubImage3D.
663 {
664 GLTexture tex2;
665 glBindTexture(GL_TEXTURE_3D, tex2);
666 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
667
668 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
669 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
670 glClear(GL_COLOR_BUFFER_BIT);
671 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
672 ASSERT_GL_NO_ERROR();
673
674 glBindFramebuffer(GL_FRAMEBUFFER, 0);
675 draw3DTexturedQuad(0.0f, 1.0f, true, 0.0f);
676 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
677 }
678}
679
Martin Radeva3ed4572017-07-27 18:29:37 +0300680// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300681// draw framebuffer, or current read framebuffer have multiview attachments with a side-by-side
682// layout.
Martin Radeva3ed4572017-07-27 18:29:37 +0300683TEST_P(FramebufferMultiviewTest, InvalidBlit)
684{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300685 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeva3ed4572017-07-27 18:29:37 +0300686
Martin Radev0f7714e2017-08-07 15:13:42 +0300687 GLFramebuffer fbo;
688 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300689
Martin Radev0f7714e2017-08-07 15:13:42 +0300690 GLTexture tex;
691 glBindTexture(GL_TEXTURE_2D, tex);
692 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
693
694 const GLint kViewportOffsets[2] = {0};
695 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
696 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300697 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
698 ASSERT_GL_NO_ERROR();
699
700 // Blit with the active read framebuffer having multiview attachments.
701 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300702 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300703 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
704 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
705 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
706 }
707
708 // Blit with the active draw framebuffer having multiview attachments.
709 {
710 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300711 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300712 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
713 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
714 }
715}
716
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300717// Test that glBlitFramebuffer succeeds if the current read framebuffer has just one layered view.
718TEST_P(FramebufferMultiviewTest, Blit)
719{
720 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
721
722 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
723 glClear(GL_COLOR_BUFFER_BIT);
724
725 GLFramebuffer fbo;
726 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
727
728 GLTexture tex;
729 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
730 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
731
732 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
733 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
734 ASSERT_GL_NO_ERROR();
735
736 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
737 glClear(GL_COLOR_BUFFER_BIT);
738
739 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
740 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
741 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
742 ASSERT_GL_NO_ERROR();
743
744 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
745 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
746}
747
Martin Radev28031682017-07-28 14:47:56 +0300748// Test that glReadPixels generates an invalid framebuffer operation error if the current read
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300749// framebuffer has a side-by-side multi-view layout.
Martin Radev28031682017-07-28 14:47:56 +0300750TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
751{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300752 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev28031682017-07-28 14:47:56 +0300753
Martin Radev0f7714e2017-08-07 15:13:42 +0300754 GLFramebuffer fbo;
755 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300756
Martin Radev0f7714e2017-08-07 15:13:42 +0300757 GLTexture tex;
758 glBindTexture(GL_TEXTURE_2D, tex);
759 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
760
761 const GLint kViewportOffsets[2] = {0};
762 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
763 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300764 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
765 ASSERT_GL_NO_ERROR();
766
767 GLColor pixelColor;
768 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
769 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
770}
771
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300772// Test that glReadPixels succeeds from a layered multiview framebuffer with just one view.
773TEST_P(FramebufferMultiviewTest, ReadPixels)
774{
775 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
776
777 GLFramebuffer fbo;
778 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
779
780 GLTexture tex;
781 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
782 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
783
784 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
785 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
786 ASSERT_GL_NO_ERROR();
787
788 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
789 glClear(GL_COLOR_BUFFER_BIT);
790
791 GLColor pixelColor;
792 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
793 ASSERT_GL_NO_ERROR();
794 EXPECT_COLOR_NEAR(GLColor::green, pixelColor, 2);
795}
796
Martin Radeveef80e42017-08-11 14:44:57 +0300797// Test that glClear clears only the contents of each view if the scissor test is enabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300798TEST_P(FramebufferMultiviewSideBySideClearTest, ColorBufferClear)
Martin Radevb0761932017-07-25 17:42:25 +0300799{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300800 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevb0761932017-07-25 17:42:25 +0300801
Martin Radev5c00d0d2017-08-07 10:06:59 +0300802 initializeFBOs(1, false, false);
Martin Radevb0761932017-07-25 17:42:25 +0300803
804 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300805 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
806 glClearColor(1, 0, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300807 glClear(GL_COLOR_BUFFER_BIT);
808
809 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300810 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300811 glViewport(0, 0, 1, 2);
812 glScissor(0, 0, 1, 2);
Martin Radeveef80e42017-08-11 14:44:57 +0300813 glEnable(GL_SCISSOR_TEST);
Martin Radevb0761932017-07-25 17:42:25 +0300814
Martin Radev5c00d0d2017-08-07 10:06:59 +0300815 glClearColor(0, 1, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300816 glClear(GL_COLOR_BUFFER_BIT);
817
Martin Radev5c00d0d2017-08-07 10:06:59 +0300818 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300819
Martin Radev5c00d0d2017-08-07 10:06:59 +0300820 checkAlternatingColumnsOfRedAndGreenInFBO();
Martin Radevb0761932017-07-25 17:42:25 +0300821}
822
Martin Radev82ef7742017-08-08 17:44:58 +0300823// Test that glFramebufferTextureMultiviewLayeredANGLE modifies the internal multiview state.
824TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
825{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300826 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300827
828 GLFramebuffer multiviewFBO;
829 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
830
831 GLTexture tex;
832 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
833 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
834 ASSERT_GL_NO_ERROR();
835
836 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
837 ASSERT_GL_NO_ERROR();
838
839 GLint numViews = -1;
840 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
841 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
842 &numViews);
843 ASSERT_GL_NO_ERROR();
844 EXPECT_EQ(2, numViews);
845
846 GLint baseViewIndex = -1;
847 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
848 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
849 &baseViewIndex);
850 ASSERT_GL_NO_ERROR();
851 EXPECT_EQ(1, baseViewIndex);
852
853 GLint multiviewLayout = GL_NONE;
854 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
855 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
856 &multiviewLayout);
857 ASSERT_GL_NO_ERROR();
858 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, multiviewLayout);
859
860 GLint internalViewportOffsets[2] = {-1};
861 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
862 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
863 &internalViewportOffsets[0]);
864 ASSERT_GL_NO_ERROR();
865 EXPECT_EQ(0, internalViewportOffsets[0]);
866 EXPECT_EQ(0, internalViewportOffsets[1]);
867}
868
869// Test framebuffer completeness status of a layered framebuffer with color attachments.
870TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
871{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300872 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300873
874 GLFramebuffer fbo;
875 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
876
877 GLTexture tex;
878 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
879 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
880
881 // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
882 // attachment will be modified to change the framebuffer's status.
883 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
884 ASSERT_GL_NO_ERROR();
885
886 GLTexture otherTexLayered;
887 glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
888 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
889
890 // Test framebuffer completeness when the base view index differs.
891 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
892 0, 1, 2);
893 ASSERT_GL_NO_ERROR();
894 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
895 glCheckFramebufferStatus(GL_FRAMEBUFFER));
896
897 // Test framebuffer completeness when the 1st attachment has a side-by-side layout.
898 const int kViewportOffsets[4] = {0, 0, 0, 0};
899 GLTexture otherTex2D;
900 glBindTexture(GL_TEXTURE_2D, otherTex2D);
901 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
902 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex2D,
903 0, 2, kViewportOffsets);
904 ASSERT_GL_NO_ERROR();
905 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
906 glCheckFramebufferStatus(GL_FRAMEBUFFER));
907
Martin Radev5e424fa2017-08-09 16:25:36 +0300908 // Test framebuffer completeness when the 1st attachment has a non-multiview layout.
Martin Radev82ef7742017-08-08 17:44:58 +0300909 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
910 ASSERT_GL_NO_ERROR();
911 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
912 glCheckFramebufferStatus(GL_FRAMEBUFFER));
913
914 // Test that framebuffer is complete when the number of views, base view index and layouts are
915 // the same.
916 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
917 0, 0, 2);
918 ASSERT_GL_NO_ERROR();
919 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
920}
921
Martin Radeveef80e42017-08-11 14:44:57 +0300922// Test that glClear clears all of the contents if the scissor test is disabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300923TEST_P(FramebufferMultiviewSideBySideClearTest, ClearWithDisabledScissorTest)
Martin Radeveef80e42017-08-11 14:44:57 +0300924{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300925 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeveef80e42017-08-11 14:44:57 +0300926
Martin Radev5c00d0d2017-08-07 10:06:59 +0300927 initializeFBOs(1, false, false);
Martin Radeveef80e42017-08-11 14:44:57 +0300928
929 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300930 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
931 glClearColor(0, 0, 0, 1);
Martin Radeveef80e42017-08-11 14:44:57 +0300932 glClear(GL_COLOR_BUFFER_BIT);
933
934 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300935 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300936 glViewport(0, 0, 1, 2);
937 glScissor(0, 0, 1, 2);
938
939 glClearColor(1, 0, 0, 1);
940 glClear(GL_COLOR_BUFFER_BIT);
941
Martin Radev5c00d0d2017-08-07 10:06:59 +0300942 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300943
944 for (int i = 0; i < 4; ++i)
945 {
946 for (int j = 0; j < 2; ++j)
947 {
948 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
949 }
950 }
951}
952
Martin Radev5c00d0d2017-08-07 10:06:59 +0300953// Test that glClear clears the depth buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300954TEST_P(FramebufferMultiviewSideBySideClearTest, DepthBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +0300955{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300956 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +0300957
958 // Create program to draw a quad.
959 const std::string &vs =
960 "#version 300 es\n"
961 "in vec3 vPos;\n"
962 "void main(){\n"
963 " gl_Position = vec4(vPos, 1.);\n"
964 "}\n";
965 const std::string &fs =
966 "#version 300 es\n"
967 "precision mediump float;\n"
968 "uniform vec3 uCol;\n"
969 "out vec4 col;\n"
970 "void main(){\n"
971 " col = vec4(uCol,1.);\n"
972 "}\n";
973 ANGLE_GL_PROGRAM(program, vs, fs);
974 glUseProgram(program);
975 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
976
977 initializeFBOs(1, false, true);
978 glEnable(GL_DEPTH_TEST);
979
980 // Clear the contents of the texture.
981 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
982 glClearColor(0, 0, 0, 0);
983 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
984
985 // Dirty the depth and color buffers.
986 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
987 drawQuad(program, "vPos", 0.0f, 1.0f, true);
988
989 // Switch to the multi-view framebuffer and clear only the rectangles covered by the views.
990 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
991 glViewport(0, 0, 1, 2);
992 glScissor(0, 0, 1, 2);
993 glEnable(GL_SCISSOR_TEST);
994 glClear(GL_DEPTH_BUFFER_BIT);
995
996 // Draw a fullscreen quad to fill the cleared regions.
997 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
998 glViewport(0, 0, 4, 2);
999 glScissor(0, 0, 4, 2);
1000 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1001 drawQuad(program, "vPos", 0.5f, 1.0f, true);
1002
1003 checkAlternatingColumnsOfRedAndGreenInFBO();
1004}
1005
1006// Test that glClear clears the stencil buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001007TEST_P(FramebufferMultiviewSideBySideClearTest, StencilBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001008{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001009 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001010
1011 // Create program to draw a quad.
1012 const std::string &vs =
1013 "#version 300 es\n"
1014 "in vec3 vPos;\n"
1015 "void main(){\n"
1016 " gl_Position = vec4(vPos, 1.);\n"
1017 "}\n";
1018 const std::string &fs =
1019 "#version 300 es\n"
1020 "precision mediump float;\n"
1021 "uniform vec3 uCol;\n"
1022 "out vec4 col;\n"
1023 "void main(){\n"
1024 " col = vec4(uCol,1.);\n"
1025 "}\n";
1026 ANGLE_GL_PROGRAM(program, vs, fs);
1027 glUseProgram(program);
1028 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1029
1030 initializeFBOs(1, true, false);
1031 glEnable(GL_STENCIL_TEST);
1032 glDisable(GL_DEPTH_TEST);
1033
1034 // Set clear values and clear the whole framebuffer.
1035 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1036 glClearColor(0, 0, 0, 0);
1037 glClearStencil(0);
1038 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1039
1040 // Update stencil test to always replace the stencil value with 0xFF.
1041 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1042 glStencilFunc(GL_ALWAYS, 0xFF, 0);
1043
1044 // Draw a quad which covers the whole texture.
1045 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1046 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1047
1048 // Switch to multiview framebuffer and clear portions of the texture.
1049 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1050 glViewport(0, 0, 1, 2);
1051 glScissor(0, 0, 1, 2);
1052 glEnable(GL_SCISSOR_TEST);
1053 glClear(GL_STENCIL_BUFFER_BIT);
1054
1055 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1056 // the test.
1057 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1058 glViewport(0, 0, 4, 2);
1059 glScissor(0, 0, 4, 2);
1060 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1061 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1062 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1063
1064 checkAlternatingColumnsOfRedAndGreenInFBO();
1065}
1066
1067// Test that glClearBufferf clears the color buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001068TEST_P(FramebufferMultiviewSideBySideClearTest, ClearBufferF)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001069{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001070 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001071
1072 initializeFBOs(2, false, false);
1073
1074 // Clear the contents of the texture.
1075 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1076 glClearColor(1, 0, 0, 1);
1077 glClear(GL_COLOR_BUFFER_BIT);
1078
1079 // Bind and specify viewport/scissor dimensions for each view.
1080 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1081 glViewport(0, 0, 1, 2);
1082 glScissor(0, 0, 1, 2);
1083 glEnable(GL_SCISSOR_TEST);
1084
1085 float kClearValues[4] = {0.f, 1.f, 0.f, 1.f};
1086 glClearBufferfv(GL_COLOR, 1, kClearValues);
1087
1088 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1089
1090 // Check that glClearBufferfv has not modified the 0th color attachment.
1091 glReadBuffer(GL_COLOR_ATTACHMENT0);
1092 for (int i = 0; i < 4; ++i)
1093 {
1094 for (int j = 0; j < 2; ++j)
1095 {
1096 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
1097 }
1098 }
1099
1100 // Check that glClearBufferfv has correctly modified the 1th color attachment.
1101 glReadBuffer(GL_COLOR_ATTACHMENT1);
1102 checkAlternatingColumnsOfRedAndGreenInFBO();
1103}
1104
Martin Radev5e424fa2017-08-09 16:25:36 +03001105// Test that glClear clears the contents of the color buffer for only the attached layers to a
1106// layered FBO.
1107TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
1108{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001109 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001110
1111 initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
1112
1113 // Bind and specify viewport/scissor dimensions for each view.
1114 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1115
1116 glClearColor(0, 1, 0, 1);
1117 glClear(GL_COLOR_BUFFER_BIT);
1118
1119 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1120 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1121 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1122 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1123}
1124
1125// Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
1126TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
1127{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001128 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001129
1130 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1131
1132 for (int i = 0; i < 2; ++i)
1133 {
1134 for (int layer = 0; layer < 4; ++layer)
1135 {
1136 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
1137 EXPECT_EQ(GLColor::red, getLayerColor(layer, colorAttachment));
1138 }
1139 }
1140
1141 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1142
1143 float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
1144 glClearBufferfv(GL_COLOR, 0, clearValues0);
1145
1146 float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
1147 glClearBufferfv(GL_COLOR, 1, clearValues1);
1148
1149 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1150 EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1151 EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1152 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1153
1154 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT1));
1155 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1156 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
1157 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT1));
1158}
1159
1160// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1161// to a layered FBO.
1162TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
1163{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001164 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001165
1166 // Create program to draw a quad.
1167 const std::string &vs =
1168 "#version 300 es\n"
1169 "in vec3 vPos;\n"
1170 "void main(){\n"
1171 " gl_Position = vec4(vPos, 1.);\n"
1172 "}\n";
1173 const std::string &fs =
1174 "#version 300 es\n"
1175 "precision mediump float;\n"
1176 "uniform vec3 uCol;\n"
1177 "out vec4 col;\n"
1178 "void main(){\n"
1179 " col = vec4(uCol,1.);\n"
1180 "}\n";
1181 ANGLE_GL_PROGRAM(program, vs, fs);
1182 glUseProgram(program);
1183 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1184
1185 initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
1186 glEnable(GL_STENCIL_TEST);
1187 glDisable(GL_DEPTH_TEST);
1188
1189 // Set clear values.
1190 glClearColor(1, 0, 0, 1);
1191 glClearStencil(0xFF);
1192
1193 // Clear the color and stencil buffers of each layer.
1194 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1195 {
1196 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1197 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1198 }
1199
1200 // Switch to multiview framebuffer and clear portions of the texture.
1201 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1202 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1203
1204 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1205 // the test.
1206 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1207 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1208 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1209 {
1210 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1211 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1212 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1213 }
1214 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1215 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1216 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1217 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1218}
1219
1220// Test that glClear does not clear the content of a detached texture.
1221TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
1222{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001223 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001224
1225 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1226
1227 // Clear all attachments.
1228 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1229 glClearColor(0, 1, 0, 1);
1230 glClear(GL_COLOR_BUFFER_BIT);
1231
1232 for (int i = 0; i < 2; ++i)
1233 {
1234 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
1235 EXPECT_EQ(GLColor::red, getLayerColor(0, colorAttachment));
1236 EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
1237 EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
1238 EXPECT_EQ(GLColor::red, getLayerColor(3, colorAttachment));
1239 }
1240
1241 // Detach and clear again.
1242 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1243 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
1244 glClearColor(1, 1, 0, 1);
1245 glClear(GL_COLOR_BUFFER_BIT);
1246
1247 // Check that color attachment 0 is modified.
1248 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1249 EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1250 EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1251 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1252
1253 // Check that color attachment 1 is unmodified.
1254 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT1));
1255 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1256 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
1257 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT1));
1258}
1259
1260// Test that glClear clears only the contents within the scissor rectangle of the attached layers.
1261TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
1262{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001263 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001264
1265 initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
1266
1267 // Bind and specify viewport/scissor dimensions for each view.
1268 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1269
1270 glEnable(GL_SCISSOR_TEST);
1271 glScissor(1, 0, 1, 1);
1272 glClearColor(0, 1, 0, 1);
1273 glClear(GL_COLOR_BUFFER_BIT);
1274
1275 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1276 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
1277
1278 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1279 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
1280
1281 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1282 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
1283
1284 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1285 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
1286}
1287
Martin Radev18b75ba2017-08-15 15:50:40 +03001288// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1289// to a layered FBO.
1290TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
1291{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001292 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev18b75ba2017-08-15 15:50:40 +03001293
1294 // Create program to draw a quad.
1295 const std::string &vs =
1296 "#version 300 es\n"
1297 "in vec3 vPos;\n"
1298 "void main(){\n"
1299 " gl_Position = vec4(vPos, 1.);\n"
1300 "}\n";
1301 const std::string &fs =
1302 "#version 300 es\n"
1303 "precision mediump float;\n"
1304 "uniform vec3 uCol;\n"
1305 "out vec4 col;\n"
1306 "void main(){\n"
1307 " col = vec4(uCol,1.);\n"
1308 "}\n";
1309 ANGLE_GL_PROGRAM(program, vs, fs);
1310 glUseProgram(program);
1311 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1312
1313 initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
1314 glEnable(GL_STENCIL_TEST);
1315 glDisable(GL_DEPTH_TEST);
1316
1317 // Set clear values.
1318 glClearColor(1, 0, 0, 1);
1319 glClearStencil(0xFF);
1320
1321 // Clear the color and stencil buffers of each layer.
1322 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1323 {
1324 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1325 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1326 }
1327
1328 // Switch to multiview framebuffer and clear portions of the texture.
1329 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1330 glEnable(GL_SCISSOR_TEST);
1331 glScissor(0, 0, 1, 1);
1332 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1333 glDisable(GL_SCISSOR_TEST);
1334
1335 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1336 // the test.
1337 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1338 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1339 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1340 {
1341 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1342 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1343 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1344 }
1345 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1346 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
1347 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1348 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
1349 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1350 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
1351 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1352 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
1353}
1354
Martin Radev14b21262017-08-25 13:54:37 +03001355// Test that detaching an attachment does not generate an error whenever the multi-view related
1356// arguments are invalid.
1357TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
1358{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001359 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev14b21262017-08-25 13:54:37 +03001360
1361 GLFramebuffer fbo;
1362 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1363
1364 // Invalid base view index.
1365 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
1366 EXPECT_GL_NO_ERROR();
1367
1368 // Invalid number of views.
1369 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
1370 EXPECT_GL_NO_ERROR();
1371
1372 // Invalid number of views.
1373 const GLint kValidViewportOffsets[2] = {0, 0};
1374 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0,
1375 kValidViewportOffsets);
1376 EXPECT_GL_NO_ERROR();
1377
1378 // Invalid viewport offsets.
1379 const GLint kInvalidViewportOffsets[2] = {-1, -1};
1380 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 1,
1381 kInvalidViewportOffsets);
1382 EXPECT_GL_NO_ERROR();
1383}
1384
Martin Radev61e710b2017-09-05 11:59:52 +03001385// Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
1386// array are attached. The test is added because a special fast code path is used for this case.
1387TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
1388{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001389 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev61e710b2017-09-05 11:59:52 +03001390
1391 initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
1392
1393 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1394 glClearColor(0, 1, 0, 1);
1395 glClear(GL_COLOR_BUFFER_BIT);
1396
1397 EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1398 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1399}
1400
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001401ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, ES3_OPENGL(), ES3_D3D11());
Martin Radev5e424fa2017-08-09 16:25:36 +03001402ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest, ES3_OPENGL(), ES3_D3D11());
Martin Radev18b75ba2017-08-15 15:50:40 +03001403ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest, ES3_OPENGL(), ES3_D3D11());