blob: 6ba432108dea2aeb57315315cd0b70ae7e763d90 [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
Olli Etuahof26b27e2018-08-17 11:01:19 +030010#include "test_utils/MultiviewTest.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
Olli Etuahof26b27e2018-08-17 11:01:19 +030029// Base class for tests that care mostly about draw call validity and not rendering results.
30class FramebufferMultiviewTest : public MultiviewTest
Martin Radeve5285d22017-07-14 16:23:53 +030031{
32 protected:
Olli Etuahof26b27e2018-08-17 11:01:19 +030033 FramebufferMultiviewTest() : MultiviewTest() {}
Martin Radeve5285d22017-07-14 16:23:53 +030034};
35
Martin Radev5e424fa2017-08-09 16:25:36 +030036class FramebufferMultiviewSideBySideClearTest : public FramebufferMultiviewTest
Martin Radev5c00d0d2017-08-07 10:06:59 +030037{
38 protected:
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030039 FramebufferMultiviewSideBySideClearTest()
40 : mMultiviewFBO(0u), mNonMultiviewFBO(0u), mDepthTex(0u), mDepthStencilTex(0u)
41 {
42 }
43
44 void TearDown() override
45 {
46 if (mMultiviewFBO != 0)
47 {
48 glDeleteFramebuffers(1, &mMultiviewFBO);
49 mMultiviewFBO = 0u;
50 }
51 if (mNonMultiviewFBO != 0)
52 {
53 glDeleteTextures(1, &mNonMultiviewFBO);
54 mNonMultiviewFBO = 0u;
55 }
56 if (!mColorTex.empty())
57 {
58 glDeleteTextures(mColorTex.size(), mColorTex.data());
59 mColorTex.clear();
60 }
61 if (mDepthStencilTex != 0u)
62 {
63 glDeleteTextures(1, &mDepthStencilTex);
64 mDepthStencilTex = 0u;
65 }
66 if (mDepthTex != 0u)
67 {
68 glDeleteTextures(1, &mDepthTex);
69 mDepthTex = 0u;
70 }
71 MultiviewTest::TearDown();
72 }
Martin Radev5c00d0d2017-08-07 10:06:59 +030073
74 void initializeFBOs(size_t numColorBuffers, bool stencil, bool depth)
75 {
76 const std::vector<GLenum> &drawBuffers = GetDrawBufferRange(2);
77
78 // Generate textures.
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030079 // Generate textures.
Martin Radev5c00d0d2017-08-07 10:06:59 +030080 mColorTex.resize(numColorBuffers);
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030081 glGenTextures(mColorTex.size(), mColorTex.data());
82 if (stencil)
83 {
84 glGenTextures(1, &mDepthStencilTex);
85 }
86 else if (depth)
87 {
88 glGenTextures(1, &mDepthTex);
89 }
90
Martin Radev5c00d0d2017-08-07 10:06:59 +030091 for (size_t i = 0u; i < numColorBuffers; ++i)
92 {
93 glBindTexture(GL_TEXTURE_2D, mColorTex[i]);
94 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
95 }
96
97 if (stencil)
98 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030099 glBindTexture(GL_TEXTURE_2D, mDepthStencilTex);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300100 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 4, 2, 0, GL_DEPTH_STENCIL,
101 GL_UNSIGNED_INT_24_8, nullptr);
102 }
103 else if (depth)
104 {
105 glBindTexture(GL_TEXTURE_2D, mDepthTex);
106 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 4, 2, 0, GL_DEPTH_COMPONENT,
107 GL_FLOAT, nullptr);
108 }
109
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300110 glGenFramebuffers(1, &mMultiviewFBO);
111 glGenFramebuffers(1, &mNonMultiviewFBO);
112
Martin Radev5c00d0d2017-08-07 10:06:59 +0300113 // Generate multiview fbo and attach textures.
114 const GLint kViewportOffsets[4] = {1, 0, 3, 0};
115 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
116 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
117 for (size_t i = 0u; i < numColorBuffers; ++i)
118 {
119 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
120 static_cast<GLenum>(kBase + i),
121 mColorTex[i], 0, 2, &kViewportOffsets[0]);
122 }
123
124 if (stencil)
125 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300126 glFramebufferTextureMultiviewSideBySideANGLE(
127 GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, mDepthStencilTex, 0, 2,
128 &kViewportOffsets[0]);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300129 }
130 else if (depth)
131 {
132 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
133 mDepthTex, 0, 2, &kViewportOffsets[0]);
134 }
135 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
136
Martin Radev5e424fa2017-08-09 16:25:36 +0300137 // Generate non-multiview fbo and attach textures.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300138 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
139 for (size_t i = 0u; i < numColorBuffers; ++i)
140 {
141 glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(kBase + i), GL_TEXTURE_2D,
142 mColorTex[i], 0);
143 }
144 if (stencil)
145 {
146 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300147 mDepthStencilTex, 0);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300148 }
149 else if (depth)
150 {
151 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTex,
152 0);
153 }
154 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
155
156 ASSERT_GL_NO_ERROR();
157 }
158
159 void checkAlternatingColumnsOfRedAndGreenInFBO()
160 {
161 // column 0
162 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
163 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::red);
164
165 // column 1
166 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
167 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
168
169 // column 2
170 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::red);
171 EXPECT_PIXEL_COLOR_EQ(2, 1, GLColor::red);
172
173 // column 3
174 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
175 EXPECT_PIXEL_COLOR_EQ(3, 1, GLColor::green);
176 }
177
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300178 GLuint mMultiviewFBO;
179 GLuint mNonMultiviewFBO;
180
181 private:
182 std::vector<GLuint> mColorTex;
183 GLuint mDepthTex;
184 GLuint mDepthStencilTex;
Martin Radev5c00d0d2017-08-07 10:06:59 +0300185};
186
Martin Radev5e424fa2017-08-09 16:25:36 +0300187class FramebufferMultiviewLayeredClearTest : public FramebufferMultiviewTest
188{
189 protected:
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300190 FramebufferMultiviewLayeredClearTest() : mMultiviewFBO(0), mDepthTex(0), mDepthStencilTex(0) {}
191
192 void TearDown() override
193 {
194 if (mMultiviewFBO != 0)
195 {
196 glDeleteFramebuffers(1, &mMultiviewFBO);
197 mMultiviewFBO = 0u;
198 }
199 if (!mNonMultiviewFBO.empty())
200 {
201 glDeleteTextures(mNonMultiviewFBO.size(), mNonMultiviewFBO.data());
202 mNonMultiviewFBO.clear();
203 }
204 if (!mColorTex.empty())
205 {
206 glDeleteTextures(mColorTex.size(), mColorTex.data());
207 mColorTex.clear();
208 }
209 if (mDepthStencilTex != 0u)
210 {
211 glDeleteTextures(1, &mDepthStencilTex);
212 mDepthStencilTex = 0u;
213 }
214 if (mDepthTex != 0u)
215 {
216 glDeleteTextures(1, &mDepthTex);
217 mDepthTex = 0u;
218 }
219 MultiviewTest::TearDown();
220 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300221
222 void initializeFBOs(int width,
223 int height,
224 int numLayers,
225 int baseViewIndex,
226 int numViews,
227 int numColorAttachments,
228 bool stencil,
229 bool depth)
230 {
231 ASSERT(baseViewIndex + numViews <= numLayers);
232
233 // Generate textures.
234 mColorTex.resize(numColorAttachments);
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300235 glGenTextures(mColorTex.size(), mColorTex.data());
236 if (stencil)
237 {
238 glGenTextures(1, &mDepthStencilTex);
239 }
240 else if (depth)
241 {
242 glGenTextures(1, &mDepthTex);
243 }
244
Martin Radev5e424fa2017-08-09 16:25:36 +0300245 for (int i = 0; i < numColorAttachments; ++i)
246 {
247 glBindTexture(GL_TEXTURE_2D_ARRAY, mColorTex[i]);
248 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, width, height, numLayers, 0, GL_RGBA,
249 GL_UNSIGNED_BYTE, nullptr);
250 }
251
252 if (stencil)
253 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300254 glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthStencilTex);
Martin Radev5e424fa2017-08-09 16:25:36 +0300255 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, width, height, numLayers, 0,
256 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
257 }
258 else if (depth)
259 {
260 glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthTex);
261 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, width, height, numLayers, 0,
262 GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
263 }
264
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300265 glGenFramebuffers(1, &mMultiviewFBO);
266
Martin Radev5e424fa2017-08-09 16:25:36 +0300267 // Generate multiview FBO and attach textures.
268 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
269 for (int i = 0; i < numColorAttachments; ++i)
270 {
271 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER,
272 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i),
273 mColorTex[i], 0, baseViewIndex, numViews);
274 }
275
276 if (stencil)
277 {
278 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300279 mDepthStencilTex, 0, baseViewIndex, numViews);
Martin Radev5e424fa2017-08-09 16:25:36 +0300280 }
281 else if (depth)
282 {
283 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
284 mDepthTex, 0, baseViewIndex, numViews);
285 }
286
287 const auto &drawBuffers = GetDrawBufferRange(numColorAttachments);
288 glDrawBuffers(numColorAttachments, drawBuffers.data());
289
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300290 mNonMultiviewFBO.resize(numLayers);
291 glGenFramebuffers(mNonMultiviewFBO.size(), mNonMultiviewFBO.data());
292
Martin Radev5e424fa2017-08-09 16:25:36 +0300293 // Generate non-multiview FBOs and attach textures.
294 mNonMultiviewFBO.resize(numLayers);
295 for (int i = 0; i < numLayers; ++i)
296 {
297 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
298 for (int j = 0; j < numColorAttachments; ++j)
299 {
300 glFramebufferTextureLayer(GL_FRAMEBUFFER,
301 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + j),
302 mColorTex[j], 0, i);
303 }
304 if (stencil)
305 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300306 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
307 mDepthStencilTex, 0, i);
Martin Radev5e424fa2017-08-09 16:25:36 +0300308 }
309 else if (depth)
310 {
311 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTex, 0, i);
312 }
313 glDrawBuffers(numColorAttachments, drawBuffers.data());
314
315 glClearColor(1, 0, 0, 1);
316 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
317 }
318
319 ASSERT_GL_NO_ERROR();
320 }
321
322 GLColor getLayerColor(size_t layer, GLenum attachment, GLint x, GLint y)
323 {
324 ASSERT(layer < mNonMultiviewFBO.size());
325 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[layer]);
326 glReadBuffer(attachment);
327 return angle::ReadColor(x, y);
328 }
329
330 GLColor getLayerColor(size_t layer, GLenum attachment)
331 {
332 return getLayerColor(layer, attachment, 0, 0);
333 }
334
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300335 GLuint mMultiviewFBO;
336 std::vector<GLuint> mNonMultiviewFBO;
337
338 private:
339 std::vector<GLuint> mColorTex;
340 GLuint mDepthTex;
341 GLuint mDepthStencilTex;
Martin Radev5e424fa2017-08-09 16:25:36 +0300342};
343
344// Test that the framebuffer tokens introduced by ANGLE_multiview can be used to query the
345// framebuffer state and that their corresponding default values are correctly set.
Martin Radeve5285d22017-07-14 16:23:53 +0300346TEST_P(FramebufferMultiviewTest, DefaultState)
347{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300348 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeve5285d22017-07-14 16:23:53 +0300349
Martin Radev0f7714e2017-08-07 15:13:42 +0300350 GLFramebuffer fbo;
351 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
352
353 GLTexture tex;
354 glBindTexture(GL_TEXTURE_2D, tex);
355 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
356 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300357
Martin Radeve5285d22017-07-14 16:23:53 +0300358 GLint numViews = -1;
359 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
360 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
361 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +0300362 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300363 EXPECT_EQ(1, numViews);
364
365 GLint baseViewIndex = -1;
366 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
367 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
368 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +0300369 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300370 EXPECT_EQ(0, baseViewIndex);
371
372 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
373 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
374 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
375 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +0300376 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300377 EXPECT_EQ(GL_NONE, multiviewLayout);
378
379 GLint viewportOffsets[2] = {-1, -1};
380 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
381 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
382 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +0300383 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300384 EXPECT_EQ(0, viewportOffsets[0]);
385 EXPECT_EQ(0, viewportOffsets[1]);
386}
387
388// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
389// the ANGLE_multiview tokens results in an INVALID_ENUM error.
390TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
391{
Martin Radev0f7714e2017-08-07 15:13:42 +0300392 GLFramebuffer fbo;
393 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
394
395 GLTexture tex;
396 glBindTexture(GL_TEXTURE_2D, tex);
397 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
398 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300399
Martin Radeve5285d22017-07-14 16:23:53 +0300400 GLint numViews = -1;
401 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
402 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
403 &numViews);
404 EXPECT_GL_ERROR(GL_INVALID_ENUM);
405
406 GLint baseViewIndex = -1;
407 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
408 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
409 &baseViewIndex);
410 EXPECT_GL_ERROR(GL_INVALID_ENUM);
411
412 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
413 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
414 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
415 &multiviewLayout);
416 EXPECT_GL_ERROR(GL_INVALID_ENUM);
417
418 GLint viewportOffsets[2] = {-1, -1};
419 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
420 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
421 &viewportOffsets[0]);
422 EXPECT_GL_ERROR(GL_INVALID_ENUM);
423}
424
Martin Radev137032d2017-07-13 10:11:12 +0300425// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
426// is called with invalid arguments.
427TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
428{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300429 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300430
Martin Radev0f7714e2017-08-07 15:13:42 +0300431 GLFramebuffer fbo;
432 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
433
434 GLTexture tex;
435 glBindTexture(GL_TEXTURE_2D, tex);
436 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
437
Martin Radev137032d2017-07-13 10:11:12 +0300438 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300439 GLint viewportOffsets[2] = {-1};
440 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
441 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300442 EXPECT_GL_ERROR(GL_INVALID_VALUE);
443
444 // Negative number of views.
445 viewportOffsets[0] = 0;
446 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300447 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1,
448 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300449 EXPECT_GL_ERROR(GL_INVALID_VALUE);
450}
451
452// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
453// called with invalid arguments.
454TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
455{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300456 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300457
Martin Radev0f7714e2017-08-07 15:13:42 +0300458 GLFramebuffer fbo;
459 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
460
461 GLTexture tex;
462 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
463 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
464 ASSERT_GL_NO_ERROR();
465
Martin Radev137032d2017-07-13 10:11:12 +0300466 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300467 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300468 EXPECT_GL_ERROR(GL_INVALID_VALUE);
469
470 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
471 GLint maxTextureLayers = 0;
472 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300473 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
474 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300475 EXPECT_GL_ERROR(GL_INVALID_VALUE);
476}
477
478// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
479// available.
480TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
481{
Martin Radev0f7714e2017-08-07 15:13:42 +0300482 GLFramebuffer fbo;
483 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
484
485 GLTexture tex;
486 glBindTexture(GL_TEXTURE_2D, tex);
487 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
488
Martin Radev9bc9a322017-07-21 14:28:17 +0300489 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300490 const GLint kViewportOffsets[2] = {0};
491 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
492 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300493 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
494}
495
Martin Radev5dae57b2017-07-14 16:15:55 +0300496// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
497TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
498{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300499 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5dae57b2017-07-14 16:15:55 +0300500
Martin Radev0f7714e2017-08-07 15:13:42 +0300501 GLFramebuffer fbo;
502 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
503
504 GLTexture tex;
505 glBindTexture(GL_TEXTURE_2D, tex);
506 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
507
508 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
509 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
510 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300511 ASSERT_GL_NO_ERROR();
512
513 GLint numViews = -1;
514 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
515 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
516 &numViews);
517 ASSERT_GL_NO_ERROR();
518 EXPECT_EQ(2, numViews);
519
520 GLint baseViewIndex = -1;
521 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
522 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
523 &baseViewIndex);
524 ASSERT_GL_NO_ERROR();
525 EXPECT_EQ(0, baseViewIndex);
526
527 GLint multiviewLayout = GL_NONE;
528 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
529 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
530 &multiviewLayout);
531 ASSERT_GL_NO_ERROR();
532 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
533
534 GLint internalViewportOffsets[4] = {-1};
535 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
536 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
537 &internalViewportOffsets[0]);
538 ASSERT_GL_NO_ERROR();
539 for (size_t i = 0u; i < 4u; ++i)
540 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300541 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300542 }
543}
544
Martin Radev9bc9a322017-07-21 14:28:17 +0300545// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
546// attachments.
547TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
548{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300549 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev9bc9a322017-07-21 14:28:17 +0300550
Martin Radev0f7714e2017-08-07 15:13:42 +0300551 GLFramebuffer fbo;
552 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300553
Martin Radev0f7714e2017-08-07 15:13:42 +0300554 GLTexture tex;
555 glBindTexture(GL_TEXTURE_2D, tex);
556 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300557
Martin Radev0f7714e2017-08-07 15:13:42 +0300558 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
559 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300560
561 // 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 +0300562 // attachment will be modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300563 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
564 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300565 ASSERT_GL_NO_ERROR();
566
567 // Color attachment 1.
568 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300569 GLTexture otherTex;
570 glBindTexture(GL_TEXTURE_2D, otherTex);
571 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
572
Martin Radev9bc9a322017-07-21 14:28:17 +0300573 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300574 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
575 0, 1, &kViewportOffsets[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 framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300581 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
582 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300583 ASSERT_GL_NO_ERROR();
584 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
585 glCheckFramebufferStatus(GL_FRAMEBUFFER));
586
587 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300588 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300589 ASSERT_GL_NO_ERROR();
590 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
591 glCheckFramebufferStatus(GL_FRAMEBUFFER));
592
593 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
594 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300595 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
596 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300597 ASSERT_GL_NO_ERROR();
598 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
599
600 // Reset attachment 1
601 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300602 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300603 }
604
605 // Depth attachment.
606 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300607 GLTexture depthTex;
608 glBindTexture(GL_TEXTURE_2D, depthTex);
609 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
610 nullptr);
611
Martin Radev9bc9a322017-07-21 14:28:17 +0300612 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300613 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
614 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300615 ASSERT_GL_NO_ERROR();
616 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
617 glCheckFramebufferStatus(GL_FRAMEBUFFER));
618
619 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300620 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
621 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300622 ASSERT_GL_NO_ERROR();
623 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
624 glCheckFramebufferStatus(GL_FRAMEBUFFER));
625
626 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300627 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300628 ASSERT_GL_NO_ERROR();
629 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
630 glCheckFramebufferStatus(GL_FRAMEBUFFER));
631
632 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
633 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300634 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
635 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300636 ASSERT_GL_NO_ERROR();
637 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
638 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300639}
640
Martin Radev04e2c3b2017-07-27 16:54:35 +0300641// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300642// attachments with a side-by-side layout.
Martin Radev04e2c3b2017-07-27 16:54:35 +0300643TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
644{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300645 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev04e2c3b2017-07-27 16:54:35 +0300646
Martin Radev0f7714e2017-08-07 15:13:42 +0300647 GLFramebuffer fbo;
648 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300649
Martin Radev0f7714e2017-08-07 15:13:42 +0300650 GLTexture tex;
651 glBindTexture(GL_TEXTURE_2D, tex);
652 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
653
654 const GLint kViewportOffsets[2] = {0};
655 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
656 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300657 ASSERT_GL_NO_ERROR();
658
659 // Test glCopyTexImage2D and glCopyTexSubImage2D.
660 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300661 GLTexture tex2;
662 glBindTexture(GL_TEXTURE_2D, tex2);
663 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300664
665 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
666 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
667
668 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
669 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300670 }
671
672 // Test glCopyTexSubImage3D.
673 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300674 GLTexture tex2;
675 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300676 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
677
678 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
679 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300680 }
681}
682
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300683// Test that the active read framebuffer can be read with glCopyTex* if it only has one layered
684// view.
685TEST_P(FramebufferMultiviewTest, CopyTex)
686{
687 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
688
689 GLFramebuffer fbo;
690 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
691
692 GLTexture tex;
693 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
694 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
695
696 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
697 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
698 ASSERT_GL_NO_ERROR();
699
700 // Test glCopyTexImage2D and glCopyTexSubImage2D.
701 {
702 GLTexture tex2;
703 glBindTexture(GL_TEXTURE_2D, tex2);
704 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
705
706 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
707 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
708 glClear(GL_COLOR_BUFFER_BIT);
709
710 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
711 ASSERT_GL_NO_ERROR();
712
713 // Test texture contents.
714 glBindFramebuffer(GL_FRAMEBUFFER, 0);
715 draw2DTexturedQuad(0.0f, 1.0f, true);
716 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
717
718 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
719 glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
720 glClear(GL_COLOR_BUFFER_BIT);
721
722 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
723 ASSERT_GL_NO_ERROR();
724
725 glBindFramebuffer(GL_FRAMEBUFFER, 0);
726 draw2DTexturedQuad(0.0f, 1.0f, true);
727 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
728 }
729
730 // Test glCopyTexSubImage3D.
731 {
732 GLTexture tex2;
733 glBindTexture(GL_TEXTURE_3D, tex2);
734 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
735
736 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
737 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
738 glClear(GL_COLOR_BUFFER_BIT);
739 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
740 ASSERT_GL_NO_ERROR();
741
742 glBindFramebuffer(GL_FRAMEBUFFER, 0);
743 draw3DTexturedQuad(0.0f, 1.0f, true, 0.0f);
744 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
745 }
746}
747
Martin Radeva3ed4572017-07-27 18:29:37 +0300748// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300749// draw framebuffer, or current read framebuffer have multiview attachments with a side-by-side
750// layout.
Martin Radeva3ed4572017-07-27 18:29:37 +0300751TEST_P(FramebufferMultiviewTest, InvalidBlit)
752{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300753 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeva3ed4572017-07-27 18:29:37 +0300754
Martin Radev0f7714e2017-08-07 15:13:42 +0300755 GLFramebuffer fbo;
756 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300757
Martin Radev0f7714e2017-08-07 15:13:42 +0300758 GLTexture tex;
759 glBindTexture(GL_TEXTURE_2D, tex);
760 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
761
762 const GLint kViewportOffsets[2] = {0};
763 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
764 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300765 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
766 ASSERT_GL_NO_ERROR();
767
768 // Blit with the active read framebuffer having multiview attachments.
769 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300770 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300771 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
772 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
773 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
774 }
775
776 // Blit with the active draw framebuffer having multiview attachments.
777 {
778 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300779 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300780 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
781 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
782 }
783}
784
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300785// Test that glBlitFramebuffer succeeds if the current read framebuffer has just one layered view.
786TEST_P(FramebufferMultiviewTest, Blit)
787{
788 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
789
790 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
791 glClear(GL_COLOR_BUFFER_BIT);
792
793 GLFramebuffer fbo;
794 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
795
796 GLTexture tex;
797 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
798 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
799
800 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
801 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
802 ASSERT_GL_NO_ERROR();
803
804 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
805 glClear(GL_COLOR_BUFFER_BIT);
806
807 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
808 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
809 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
810 ASSERT_GL_NO_ERROR();
811
812 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
813 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
814}
815
Martin Radev28031682017-07-28 14:47:56 +0300816// Test that glReadPixels generates an invalid framebuffer operation error if the current read
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300817// framebuffer has a side-by-side multi-view layout.
Martin Radev28031682017-07-28 14:47:56 +0300818TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
819{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300820 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev28031682017-07-28 14:47:56 +0300821
Martin Radev0f7714e2017-08-07 15:13:42 +0300822 GLFramebuffer fbo;
823 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300824
Martin Radev0f7714e2017-08-07 15:13:42 +0300825 GLTexture tex;
826 glBindTexture(GL_TEXTURE_2D, tex);
827 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
828
829 const GLint kViewportOffsets[2] = {0};
830 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
831 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300832 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
833 ASSERT_GL_NO_ERROR();
834
835 GLColor pixelColor;
836 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
837 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
838}
839
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300840// Test that glReadPixels succeeds from a layered multiview framebuffer with just one view.
841TEST_P(FramebufferMultiviewTest, ReadPixels)
842{
843 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
844
845 GLFramebuffer fbo;
846 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
847
848 GLTexture tex;
849 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
850 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
851
852 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
853 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
854 ASSERT_GL_NO_ERROR();
855
856 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
857 glClear(GL_COLOR_BUFFER_BIT);
858
859 GLColor pixelColor;
860 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
861 ASSERT_GL_NO_ERROR();
862 EXPECT_COLOR_NEAR(GLColor::green, pixelColor, 2);
863}
864
Martin Radeveef80e42017-08-11 14:44:57 +0300865// Test that glClear clears only the contents of each view if the scissor test is enabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300866TEST_P(FramebufferMultiviewSideBySideClearTest, ColorBufferClear)
Martin Radevb0761932017-07-25 17:42:25 +0300867{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300868 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevb0761932017-07-25 17:42:25 +0300869
Martin Radev5c00d0d2017-08-07 10:06:59 +0300870 initializeFBOs(1, false, false);
Martin Radevb0761932017-07-25 17:42:25 +0300871
872 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300873 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
874 glClearColor(1, 0, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300875 glClear(GL_COLOR_BUFFER_BIT);
876
877 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300878 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300879 glViewport(0, 0, 1, 2);
880 glScissor(0, 0, 1, 2);
Martin Radeveef80e42017-08-11 14:44:57 +0300881 glEnable(GL_SCISSOR_TEST);
Martin Radevb0761932017-07-25 17:42:25 +0300882
Martin Radev5c00d0d2017-08-07 10:06:59 +0300883 glClearColor(0, 1, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300884 glClear(GL_COLOR_BUFFER_BIT);
885
Martin Radev5c00d0d2017-08-07 10:06:59 +0300886 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300887
Martin Radev5c00d0d2017-08-07 10:06:59 +0300888 checkAlternatingColumnsOfRedAndGreenInFBO();
Martin Radevb0761932017-07-25 17:42:25 +0300889}
890
Martin Radev82ef7742017-08-08 17:44:58 +0300891// Test that glFramebufferTextureMultiviewLayeredANGLE modifies the internal multiview state.
892TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
893{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300894 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300895
896 GLFramebuffer multiviewFBO;
897 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
898
899 GLTexture tex;
900 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
901 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
902 ASSERT_GL_NO_ERROR();
903
904 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
905 ASSERT_GL_NO_ERROR();
906
907 GLint numViews = -1;
908 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
909 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
910 &numViews);
911 ASSERT_GL_NO_ERROR();
912 EXPECT_EQ(2, numViews);
913
914 GLint baseViewIndex = -1;
915 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
916 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
917 &baseViewIndex);
918 ASSERT_GL_NO_ERROR();
919 EXPECT_EQ(1, baseViewIndex);
920
921 GLint multiviewLayout = GL_NONE;
922 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
923 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
924 &multiviewLayout);
925 ASSERT_GL_NO_ERROR();
926 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, multiviewLayout);
927
928 GLint internalViewportOffsets[2] = {-1};
929 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
930 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
931 &internalViewportOffsets[0]);
932 ASSERT_GL_NO_ERROR();
933 EXPECT_EQ(0, internalViewportOffsets[0]);
934 EXPECT_EQ(0, internalViewportOffsets[1]);
935}
936
937// Test framebuffer completeness status of a layered framebuffer with color attachments.
938TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
939{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300940 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300941
942 GLFramebuffer fbo;
943 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
944
945 GLTexture tex;
946 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
947 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
948
949 // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
950 // attachment will be modified to change the framebuffer's status.
951 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
952 ASSERT_GL_NO_ERROR();
953
954 GLTexture otherTexLayered;
955 glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
956 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
957
958 // Test framebuffer completeness when the base view index differs.
959 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
960 0, 1, 2);
961 ASSERT_GL_NO_ERROR();
962 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
963 glCheckFramebufferStatus(GL_FRAMEBUFFER));
964
965 // Test framebuffer completeness when the 1st attachment has a side-by-side layout.
966 const int kViewportOffsets[4] = {0, 0, 0, 0};
967 GLTexture otherTex2D;
968 glBindTexture(GL_TEXTURE_2D, otherTex2D);
969 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
970 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex2D,
971 0, 2, kViewportOffsets);
972 ASSERT_GL_NO_ERROR();
973 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
974 glCheckFramebufferStatus(GL_FRAMEBUFFER));
975
Martin Radev5e424fa2017-08-09 16:25:36 +0300976 // Test framebuffer completeness when the 1st attachment has a non-multiview layout.
Martin Radev82ef7742017-08-08 17:44:58 +0300977 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
978 ASSERT_GL_NO_ERROR();
979 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
980 glCheckFramebufferStatus(GL_FRAMEBUFFER));
981
982 // Test that framebuffer is complete when the number of views, base view index and layouts are
983 // the same.
984 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
985 0, 0, 2);
986 ASSERT_GL_NO_ERROR();
987 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
988}
989
Martin Radeveef80e42017-08-11 14:44:57 +0300990// Test that glClear clears all of the contents if the scissor test is disabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300991TEST_P(FramebufferMultiviewSideBySideClearTest, ClearWithDisabledScissorTest)
Martin Radeveef80e42017-08-11 14:44:57 +0300992{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300993 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeveef80e42017-08-11 14:44:57 +0300994
Martin Radev5c00d0d2017-08-07 10:06:59 +0300995 initializeFBOs(1, false, false);
Martin Radeveef80e42017-08-11 14:44:57 +0300996
997 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300998 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
999 glClearColor(0, 0, 0, 1);
Martin Radeveef80e42017-08-11 14:44:57 +03001000 glClear(GL_COLOR_BUFFER_BIT);
1001
1002 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +03001003 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +03001004 glViewport(0, 0, 1, 2);
1005 glScissor(0, 0, 1, 2);
1006
1007 glClearColor(1, 0, 0, 1);
1008 glClear(GL_COLOR_BUFFER_BIT);
1009
Martin Radev5c00d0d2017-08-07 10:06:59 +03001010 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +03001011
1012 for (int i = 0; i < 4; ++i)
1013 {
1014 for (int j = 0; j < 2; ++j)
1015 {
1016 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
1017 }
1018 }
1019}
1020
Martin Radev5c00d0d2017-08-07 10:06:59 +03001021// Test that glClear clears the depth buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001022TEST_P(FramebufferMultiviewSideBySideClearTest, DepthBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001023{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001024 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001025
1026 // Create program to draw a quad.
1027 const std::string &vs =
1028 "#version 300 es\n"
1029 "in vec3 vPos;\n"
1030 "void main(){\n"
1031 " gl_Position = vec4(vPos, 1.);\n"
1032 "}\n";
1033 const std::string &fs =
1034 "#version 300 es\n"
1035 "precision mediump float;\n"
1036 "uniform vec3 uCol;\n"
1037 "out vec4 col;\n"
1038 "void main(){\n"
1039 " col = vec4(uCol,1.);\n"
1040 "}\n";
1041 ANGLE_GL_PROGRAM(program, vs, fs);
1042 glUseProgram(program);
1043 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1044
1045 initializeFBOs(1, false, true);
1046 glEnable(GL_DEPTH_TEST);
1047
1048 // Clear the contents of the texture.
1049 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1050 glClearColor(0, 0, 0, 0);
1051 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1052
1053 // Dirty the depth and color buffers.
1054 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1055 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1056
1057 // Switch to the multi-view framebuffer and clear only the rectangles covered by the views.
1058 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1059 glViewport(0, 0, 1, 2);
1060 glScissor(0, 0, 1, 2);
1061 glEnable(GL_SCISSOR_TEST);
1062 glClear(GL_DEPTH_BUFFER_BIT);
1063
1064 // Draw a fullscreen quad to fill the cleared regions.
1065 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1066 glViewport(0, 0, 4, 2);
1067 glScissor(0, 0, 4, 2);
1068 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1069 drawQuad(program, "vPos", 0.5f, 1.0f, true);
1070
1071 checkAlternatingColumnsOfRedAndGreenInFBO();
1072}
1073
1074// Test that glClear clears the stencil buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001075TEST_P(FramebufferMultiviewSideBySideClearTest, StencilBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001076{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001077 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001078
1079 // Create program to draw a quad.
1080 const std::string &vs =
1081 "#version 300 es\n"
1082 "in vec3 vPos;\n"
1083 "void main(){\n"
1084 " gl_Position = vec4(vPos, 1.);\n"
1085 "}\n";
1086 const std::string &fs =
1087 "#version 300 es\n"
1088 "precision mediump float;\n"
1089 "uniform vec3 uCol;\n"
1090 "out vec4 col;\n"
1091 "void main(){\n"
1092 " col = vec4(uCol,1.);\n"
1093 "}\n";
1094 ANGLE_GL_PROGRAM(program, vs, fs);
1095 glUseProgram(program);
1096 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1097
1098 initializeFBOs(1, true, false);
1099 glEnable(GL_STENCIL_TEST);
1100 glDisable(GL_DEPTH_TEST);
1101
1102 // Set clear values and clear the whole framebuffer.
1103 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1104 glClearColor(0, 0, 0, 0);
1105 glClearStencil(0);
1106 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1107
1108 // Update stencil test to always replace the stencil value with 0xFF.
1109 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1110 glStencilFunc(GL_ALWAYS, 0xFF, 0);
1111
1112 // Draw a quad which covers the whole texture.
1113 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1114 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1115
1116 // Switch to multiview framebuffer and clear portions of the texture.
1117 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1118 glViewport(0, 0, 1, 2);
1119 glScissor(0, 0, 1, 2);
1120 glEnable(GL_SCISSOR_TEST);
1121 glClear(GL_STENCIL_BUFFER_BIT);
1122
1123 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1124 // the test.
1125 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1126 glViewport(0, 0, 4, 2);
1127 glScissor(0, 0, 4, 2);
1128 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1129 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1130 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1131
1132 checkAlternatingColumnsOfRedAndGreenInFBO();
1133}
1134
1135// Test that glClearBufferf clears the color buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001136TEST_P(FramebufferMultiviewSideBySideClearTest, ClearBufferF)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001137{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001138 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001139
1140 initializeFBOs(2, false, false);
1141
1142 // Clear the contents of the texture.
1143 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1144 glClearColor(1, 0, 0, 1);
1145 glClear(GL_COLOR_BUFFER_BIT);
1146
1147 // Bind and specify viewport/scissor dimensions for each view.
1148 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1149 glViewport(0, 0, 1, 2);
1150 glScissor(0, 0, 1, 2);
1151 glEnable(GL_SCISSOR_TEST);
1152
1153 float kClearValues[4] = {0.f, 1.f, 0.f, 1.f};
1154 glClearBufferfv(GL_COLOR, 1, kClearValues);
1155
1156 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1157
1158 // Check that glClearBufferfv has not modified the 0th color attachment.
1159 glReadBuffer(GL_COLOR_ATTACHMENT0);
1160 for (int i = 0; i < 4; ++i)
1161 {
1162 for (int j = 0; j < 2; ++j)
1163 {
1164 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
1165 }
1166 }
1167
1168 // Check that glClearBufferfv has correctly modified the 1th color attachment.
1169 glReadBuffer(GL_COLOR_ATTACHMENT1);
1170 checkAlternatingColumnsOfRedAndGreenInFBO();
1171}
1172
Martin Radev5e424fa2017-08-09 16:25:36 +03001173// Test that glClear clears the contents of the color buffer for only the attached layers to a
1174// layered FBO.
1175TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
1176{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001177 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001178
1179 initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
1180
1181 // Bind and specify viewport/scissor dimensions for each view.
1182 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1183
1184 glClearColor(0, 1, 0, 1);
1185 glClear(GL_COLOR_BUFFER_BIT);
1186
1187 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1188 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1189 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1190 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1191}
1192
1193// Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
1194TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
1195{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001196 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001197
1198 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1199
1200 for (int i = 0; i < 2; ++i)
1201 {
1202 for (int layer = 0; layer < 4; ++layer)
1203 {
1204 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
1205 EXPECT_EQ(GLColor::red, getLayerColor(layer, colorAttachment));
1206 }
1207 }
1208
1209 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1210
1211 float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
1212 glClearBufferfv(GL_COLOR, 0, clearValues0);
1213
1214 float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
1215 glClearBufferfv(GL_COLOR, 1, clearValues1);
1216
1217 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1218 EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1219 EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1220 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1221
1222 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT1));
1223 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1224 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
1225 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT1));
1226}
1227
1228// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1229// to a layered FBO.
1230TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
1231{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001232 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001233
1234 // Create program to draw a quad.
1235 const std::string &vs =
1236 "#version 300 es\n"
1237 "in vec3 vPos;\n"
1238 "void main(){\n"
1239 " gl_Position = vec4(vPos, 1.);\n"
1240 "}\n";
1241 const std::string &fs =
1242 "#version 300 es\n"
1243 "precision mediump float;\n"
1244 "uniform vec3 uCol;\n"
1245 "out vec4 col;\n"
1246 "void main(){\n"
1247 " col = vec4(uCol,1.);\n"
1248 "}\n";
1249 ANGLE_GL_PROGRAM(program, vs, fs);
1250 glUseProgram(program);
1251 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1252
1253 initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
1254 glEnable(GL_STENCIL_TEST);
1255 glDisable(GL_DEPTH_TEST);
1256
1257 // Set clear values.
1258 glClearColor(1, 0, 0, 1);
1259 glClearStencil(0xFF);
1260
1261 // Clear the color and stencil buffers of each layer.
1262 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1263 {
1264 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1265 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1266 }
1267
1268 // Switch to multiview framebuffer and clear portions of the texture.
1269 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1270 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1271
1272 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1273 // the test.
1274 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1275 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1276 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1277 {
1278 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1279 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1280 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1281 }
1282 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1283 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1284 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1285 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1286}
1287
1288// Test that glClear does not clear the content of a detached texture.
1289TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
1290{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001291 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001292
1293 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1294
1295 // Clear all attachments.
1296 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1297 glClearColor(0, 1, 0, 1);
1298 glClear(GL_COLOR_BUFFER_BIT);
1299
1300 for (int i = 0; i < 2; ++i)
1301 {
1302 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
1303 EXPECT_EQ(GLColor::red, getLayerColor(0, colorAttachment));
1304 EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
1305 EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
1306 EXPECT_EQ(GLColor::red, getLayerColor(3, colorAttachment));
1307 }
1308
1309 // Detach and clear again.
1310 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1311 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
1312 glClearColor(1, 1, 0, 1);
1313 glClear(GL_COLOR_BUFFER_BIT);
1314
1315 // Check that color attachment 0 is modified.
1316 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1317 EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1318 EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1319 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1320
1321 // Check that color attachment 1 is unmodified.
1322 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT1));
1323 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1324 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
1325 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT1));
1326}
1327
1328// Test that glClear clears only the contents within the scissor rectangle of the attached layers.
1329TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
1330{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001331 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001332
1333 initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
1334
1335 // Bind and specify viewport/scissor dimensions for each view.
1336 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1337
1338 glEnable(GL_SCISSOR_TEST);
1339 glScissor(1, 0, 1, 1);
1340 glClearColor(0, 1, 0, 1);
1341 glClear(GL_COLOR_BUFFER_BIT);
1342
1343 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1344 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
1345
1346 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1347 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
1348
1349 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1350 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
1351
1352 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1353 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
1354}
1355
Martin Radev18b75ba2017-08-15 15:50:40 +03001356// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1357// to a layered FBO.
1358TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
1359{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001360 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev18b75ba2017-08-15 15:50:40 +03001361
1362 // Create program to draw a quad.
1363 const std::string &vs =
1364 "#version 300 es\n"
1365 "in vec3 vPos;\n"
1366 "void main(){\n"
1367 " gl_Position = vec4(vPos, 1.);\n"
1368 "}\n";
1369 const std::string &fs =
1370 "#version 300 es\n"
1371 "precision mediump float;\n"
1372 "uniform vec3 uCol;\n"
1373 "out vec4 col;\n"
1374 "void main(){\n"
1375 " col = vec4(uCol,1.);\n"
1376 "}\n";
1377 ANGLE_GL_PROGRAM(program, vs, fs);
1378 glUseProgram(program);
1379 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1380
1381 initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
1382 glEnable(GL_STENCIL_TEST);
1383 glDisable(GL_DEPTH_TEST);
1384
1385 // Set clear values.
1386 glClearColor(1, 0, 0, 1);
1387 glClearStencil(0xFF);
1388
1389 // Clear the color and stencil buffers of each layer.
1390 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1391 {
1392 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1393 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1394 }
1395
1396 // Switch to multiview framebuffer and clear portions of the texture.
1397 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1398 glEnable(GL_SCISSOR_TEST);
1399 glScissor(0, 0, 1, 1);
1400 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1401 glDisable(GL_SCISSOR_TEST);
1402
1403 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1404 // the test.
1405 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1406 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1407 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1408 {
1409 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1410 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1411 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1412 }
1413 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1414 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
1415 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1416 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
1417 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1418 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
1419 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1420 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
1421}
1422
Martin Radev14b21262017-08-25 13:54:37 +03001423// Test that detaching an attachment does not generate an error whenever the multi-view related
1424// arguments are invalid.
1425TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
1426{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001427 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev14b21262017-08-25 13:54:37 +03001428
1429 GLFramebuffer fbo;
1430 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1431
1432 // Invalid base view index.
1433 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
1434 EXPECT_GL_NO_ERROR();
1435
1436 // Invalid number of views.
1437 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
1438 EXPECT_GL_NO_ERROR();
1439
1440 // Invalid number of views.
1441 const GLint kValidViewportOffsets[2] = {0, 0};
1442 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0,
1443 kValidViewportOffsets);
1444 EXPECT_GL_NO_ERROR();
1445
1446 // Invalid viewport offsets.
1447 const GLint kInvalidViewportOffsets[2] = {-1, -1};
1448 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 1,
1449 kInvalidViewportOffsets);
1450 EXPECT_GL_NO_ERROR();
1451}
1452
Martin Radev61e710b2017-09-05 11:59:52 +03001453// Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
1454// array are attached. The test is added because a special fast code path is used for this case.
1455TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
1456{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001457 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev61e710b2017-09-05 11:59:52 +03001458
1459 initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
1460
1461 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1462 glClearColor(0, 1, 0, 1);
1463 glClear(GL_COLOR_BUFFER_BIT);
1464
1465 EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1466 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1467}
1468
Olli Etuahof26b27e2018-08-17 11:01:19 +03001469ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));
1470ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest,
1471 VertexShaderOpenGL(3, 0),
1472 GeomShaderD3D11(3, 0));
1473ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest,
1474 VertexShaderOpenGL(3, 0),
1475 GeomShaderD3D11(3, 0));