blob: b8e4aea5f39f6a39eab96aa5adab3d337e8a771b [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:
Martin Radev5e424fa2017-08-09 16:25:36 +030039 FramebufferMultiviewSideBySideClearTest() {}
Martin Radev5c00d0d2017-08-07 10:06:59 +030040
41 void initializeFBOs(size_t numColorBuffers, bool stencil, bool depth)
42 {
43 const std::vector<GLenum> &drawBuffers = GetDrawBufferRange(2);
44
45 // Generate textures.
46 mColorTex.resize(numColorBuffers);
47 for (size_t i = 0u; i < numColorBuffers; ++i)
48 {
49 glBindTexture(GL_TEXTURE_2D, mColorTex[i]);
50 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
51 }
52
53 if (stencil)
54 {
55 glBindTexture(GL_TEXTURE_2D, mStencilTex);
56 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 4, 2, 0, GL_DEPTH_STENCIL,
57 GL_UNSIGNED_INT_24_8, nullptr);
58 }
59 else if (depth)
60 {
61 glBindTexture(GL_TEXTURE_2D, mDepthTex);
62 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 4, 2, 0, GL_DEPTH_COMPONENT,
63 GL_FLOAT, nullptr);
64 }
65
66 // Generate multiview fbo and attach textures.
67 const GLint kViewportOffsets[4] = {1, 0, 3, 0};
68 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
69 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
70 for (size_t i = 0u; i < numColorBuffers; ++i)
71 {
72 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
73 static_cast<GLenum>(kBase + i),
74 mColorTex[i], 0, 2, &kViewportOffsets[0]);
75 }
76
77 if (stencil)
78 {
79 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
80 GL_DEPTH_STENCIL_ATTACHMENT, mStencilTex,
81 0, 2, &kViewportOffsets[0]);
82 }
83 else if (depth)
84 {
85 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
86 mDepthTex, 0, 2, &kViewportOffsets[0]);
87 }
88 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
89
Martin Radev5e424fa2017-08-09 16:25:36 +030090 // Generate non-multiview fbo and attach textures.
Martin Radev5c00d0d2017-08-07 10:06:59 +030091 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
92 for (size_t i = 0u; i < numColorBuffers; ++i)
93 {
94 glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(kBase + i), GL_TEXTURE_2D,
95 mColorTex[i], 0);
96 }
97 if (stencil)
98 {
99 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
100 mStencilTex, 0);
101 }
102 else if (depth)
103 {
104 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTex,
105 0);
106 }
107 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
108
109 ASSERT_GL_NO_ERROR();
110 }
111
112 void checkAlternatingColumnsOfRedAndGreenInFBO()
113 {
114 // column 0
115 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
116 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::red);
117
118 // column 1
119 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
120 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
121
122 // column 2
123 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::red);
124 EXPECT_PIXEL_COLOR_EQ(2, 1, GLColor::red);
125
126 // column 3
127 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
128 EXPECT_PIXEL_COLOR_EQ(3, 1, GLColor::green);
129 }
130
131 GLFramebuffer mMultiviewFBO;
132 GLFramebuffer mNonMultiviewFBO;
133 std::vector<GLTexture> mColorTex;
134 GLTexture mDepthTex;
135 GLTexture mStencilTex;
136};
137
Martin Radev5e424fa2017-08-09 16:25:36 +0300138class FramebufferMultiviewLayeredClearTest : public FramebufferMultiviewTest
139{
140 protected:
141 FramebufferMultiviewLayeredClearTest() {}
142
143 void initializeFBOs(int width,
144 int height,
145 int numLayers,
146 int baseViewIndex,
147 int numViews,
148 int numColorAttachments,
149 bool stencil,
150 bool depth)
151 {
152 ASSERT(baseViewIndex + numViews <= numLayers);
153
154 // Generate textures.
155 mColorTex.resize(numColorAttachments);
156 for (int i = 0; i < numColorAttachments; ++i)
157 {
158 glBindTexture(GL_TEXTURE_2D_ARRAY, mColorTex[i]);
159 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, width, height, numLayers, 0, GL_RGBA,
160 GL_UNSIGNED_BYTE, nullptr);
161 }
162
163 if (stencil)
164 {
165 glBindTexture(GL_TEXTURE_2D_ARRAY, mStencilTex);
166 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, width, height, numLayers, 0,
167 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
168 }
169 else if (depth)
170 {
171 glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthTex);
172 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, width, height, numLayers, 0,
173 GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
174 }
175
176 // Generate multiview FBO and attach textures.
177 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
178 for (int i = 0; i < numColorAttachments; ++i)
179 {
180 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER,
181 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i),
182 mColorTex[i], 0, baseViewIndex, numViews);
183 }
184
185 if (stencil)
186 {
187 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
188 mStencilTex, 0, baseViewIndex, numViews);
189 }
190 else if (depth)
191 {
192 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
193 mDepthTex, 0, baseViewIndex, numViews);
194 }
195
196 const auto &drawBuffers = GetDrawBufferRange(numColorAttachments);
197 glDrawBuffers(numColorAttachments, drawBuffers.data());
198
199 // Generate non-multiview FBOs and attach textures.
200 mNonMultiviewFBO.resize(numLayers);
201 for (int i = 0; i < numLayers; ++i)
202 {
203 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
204 for (int j = 0; j < numColorAttachments; ++j)
205 {
206 glFramebufferTextureLayer(GL_FRAMEBUFFER,
207 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + j),
208 mColorTex[j], 0, i);
209 }
210 if (stencil)
211 {
212 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, mStencilTex,
213 0, i);
214 }
215 else if (depth)
216 {
217 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTex, 0, i);
218 }
219 glDrawBuffers(numColorAttachments, drawBuffers.data());
220
221 glClearColor(1, 0, 0, 1);
222 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
223 }
224
225 ASSERT_GL_NO_ERROR();
226 }
227
228 GLColor getLayerColor(size_t layer, GLenum attachment, GLint x, GLint y)
229 {
230 ASSERT(layer < mNonMultiviewFBO.size());
231 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[layer]);
232 glReadBuffer(attachment);
233 return angle::ReadColor(x, y);
234 }
235
236 GLColor getLayerColor(size_t layer, GLenum attachment)
237 {
238 return getLayerColor(layer, attachment, 0, 0);
239 }
240
241 GLFramebuffer mMultiviewFBO;
242 std::vector<GLFramebuffer> mNonMultiviewFBO;
243 std::vector<GLTexture> mColorTex;
244 GLTexture mDepthTex;
245 GLTexture mStencilTex;
246};
247
248// Test that the framebuffer tokens introduced by ANGLE_multiview can be used to query the
249// framebuffer state and that their corresponding default values are correctly set.
Martin Radeve5285d22017-07-14 16:23:53 +0300250TEST_P(FramebufferMultiviewTest, DefaultState)
251{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300252 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeve5285d22017-07-14 16:23:53 +0300253
Martin Radev0f7714e2017-08-07 15:13:42 +0300254 GLFramebuffer fbo;
255 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
256
257 GLTexture tex;
258 glBindTexture(GL_TEXTURE_2D, tex);
259 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
260 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300261
Martin Radeve5285d22017-07-14 16:23:53 +0300262 GLint numViews = -1;
263 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
264 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
265 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +0300266 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300267 EXPECT_EQ(1, numViews);
268
269 GLint baseViewIndex = -1;
270 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
271 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
272 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +0300273 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300274 EXPECT_EQ(0, baseViewIndex);
275
276 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
277 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
278 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
279 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +0300280 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300281 EXPECT_EQ(GL_NONE, multiviewLayout);
282
283 GLint viewportOffsets[2] = {-1, -1};
284 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
285 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
286 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +0300287 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300288 EXPECT_EQ(0, viewportOffsets[0]);
289 EXPECT_EQ(0, viewportOffsets[1]);
290}
291
292// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
293// the ANGLE_multiview tokens results in an INVALID_ENUM error.
294TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
295{
Martin Radev0f7714e2017-08-07 15:13:42 +0300296 GLFramebuffer fbo;
297 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
298
299 GLTexture tex;
300 glBindTexture(GL_TEXTURE_2D, tex);
301 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
302 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300303
Martin Radeve5285d22017-07-14 16:23:53 +0300304 GLint numViews = -1;
305 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
306 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
307 &numViews);
308 EXPECT_GL_ERROR(GL_INVALID_ENUM);
309
310 GLint baseViewIndex = -1;
311 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
312 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
313 &baseViewIndex);
314 EXPECT_GL_ERROR(GL_INVALID_ENUM);
315
316 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
317 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
318 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
319 &multiviewLayout);
320 EXPECT_GL_ERROR(GL_INVALID_ENUM);
321
322 GLint viewportOffsets[2] = {-1, -1};
323 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
324 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
325 &viewportOffsets[0]);
326 EXPECT_GL_ERROR(GL_INVALID_ENUM);
327}
328
Martin Radev137032d2017-07-13 10:11:12 +0300329// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
330// is called with invalid arguments.
331TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
332{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300333 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300334
Martin Radev0f7714e2017-08-07 15:13:42 +0300335 GLFramebuffer fbo;
336 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
337
338 GLTexture tex;
339 glBindTexture(GL_TEXTURE_2D, tex);
340 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
341
Martin Radev137032d2017-07-13 10:11:12 +0300342 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300343 GLint viewportOffsets[2] = {-1};
344 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
345 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300346 EXPECT_GL_ERROR(GL_INVALID_VALUE);
347
348 // Negative number of views.
349 viewportOffsets[0] = 0;
350 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300351 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1,
352 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300353 EXPECT_GL_ERROR(GL_INVALID_VALUE);
354}
355
356// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
357// called with invalid arguments.
358TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
359{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300360 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300361
Martin Radev0f7714e2017-08-07 15:13:42 +0300362 GLFramebuffer fbo;
363 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
364
365 GLTexture tex;
366 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
367 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
368 ASSERT_GL_NO_ERROR();
369
Martin Radev137032d2017-07-13 10:11:12 +0300370 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300371 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300372 EXPECT_GL_ERROR(GL_INVALID_VALUE);
373
374 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
375 GLint maxTextureLayers = 0;
376 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300377 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
378 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300379 EXPECT_GL_ERROR(GL_INVALID_VALUE);
380}
381
382// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
383// available.
384TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
385{
Martin Radev0f7714e2017-08-07 15:13:42 +0300386 GLFramebuffer fbo;
387 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
388
389 GLTexture tex;
390 glBindTexture(GL_TEXTURE_2D, tex);
391 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
392
Martin Radev9bc9a322017-07-21 14:28:17 +0300393 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300394 const GLint kViewportOffsets[2] = {0};
395 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
396 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300397 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
398}
399
Martin Radev5dae57b2017-07-14 16:15:55 +0300400// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
401TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
402{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300403 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5dae57b2017-07-14 16:15:55 +0300404
Martin Radev0f7714e2017-08-07 15:13:42 +0300405 GLFramebuffer fbo;
406 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
407
408 GLTexture tex;
409 glBindTexture(GL_TEXTURE_2D, tex);
410 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
411
412 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
413 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
414 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300415 ASSERT_GL_NO_ERROR();
416
417 GLint numViews = -1;
418 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
419 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
420 &numViews);
421 ASSERT_GL_NO_ERROR();
422 EXPECT_EQ(2, numViews);
423
424 GLint baseViewIndex = -1;
425 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
426 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
427 &baseViewIndex);
428 ASSERT_GL_NO_ERROR();
429 EXPECT_EQ(0, baseViewIndex);
430
431 GLint multiviewLayout = GL_NONE;
432 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
433 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
434 &multiviewLayout);
435 ASSERT_GL_NO_ERROR();
436 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
437
438 GLint internalViewportOffsets[4] = {-1};
439 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
440 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
441 &internalViewportOffsets[0]);
442 ASSERT_GL_NO_ERROR();
443 for (size_t i = 0u; i < 4u; ++i)
444 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300445 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300446 }
447}
448
Martin Radev9bc9a322017-07-21 14:28:17 +0300449// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
450// attachments.
451TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
452{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300453 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev9bc9a322017-07-21 14:28:17 +0300454
Martin Radev0f7714e2017-08-07 15:13:42 +0300455 GLFramebuffer fbo;
456 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300457
Martin Radev0f7714e2017-08-07 15:13:42 +0300458 GLTexture tex;
459 glBindTexture(GL_TEXTURE_2D, tex);
460 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300461
Martin Radev0f7714e2017-08-07 15:13:42 +0300462 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
463 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300464
465 // 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 +0300466 // attachment will be modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300467 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
468 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300469 ASSERT_GL_NO_ERROR();
470
471 // Color attachment 1.
472 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300473 GLTexture otherTex;
474 glBindTexture(GL_TEXTURE_2D, otherTex);
475 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
476
Martin Radev9bc9a322017-07-21 14:28:17 +0300477 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300478 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
479 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300480 ASSERT_GL_NO_ERROR();
481 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
482 glCheckFramebufferStatus(GL_FRAMEBUFFER));
483
484 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300485 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
486 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300487 ASSERT_GL_NO_ERROR();
488 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
489 glCheckFramebufferStatus(GL_FRAMEBUFFER));
490
491 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300492 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300493 ASSERT_GL_NO_ERROR();
494 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
495 glCheckFramebufferStatus(GL_FRAMEBUFFER));
496
497 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
498 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300499 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
500 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300501 ASSERT_GL_NO_ERROR();
502 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
503
504 // Reset attachment 1
505 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300506 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300507 }
508
509 // Depth attachment.
510 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300511 GLTexture depthTex;
512 glBindTexture(GL_TEXTURE_2D, depthTex);
513 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
514 nullptr);
515
Martin Radev9bc9a322017-07-21 14:28:17 +0300516 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300517 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
518 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300519 ASSERT_GL_NO_ERROR();
520 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
521 glCheckFramebufferStatus(GL_FRAMEBUFFER));
522
523 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300524 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
525 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300526 ASSERT_GL_NO_ERROR();
527 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
528 glCheckFramebufferStatus(GL_FRAMEBUFFER));
529
530 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300531 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300532 ASSERT_GL_NO_ERROR();
533 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
534 glCheckFramebufferStatus(GL_FRAMEBUFFER));
535
536 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
537 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300538 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
539 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300540 ASSERT_GL_NO_ERROR();
541 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
542 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300543}
544
Martin Radev04e2c3b2017-07-27 16:54:35 +0300545// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300546// attachments with a side-by-side layout.
Martin Radev04e2c3b2017-07-27 16:54:35 +0300547TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
548{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300549 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev04e2c3b2017-07-27 16:54:35 +0300550
Martin Radev0f7714e2017-08-07 15:13:42 +0300551 GLFramebuffer fbo;
552 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +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);
557
558 const GLint kViewportOffsets[2] = {0};
559 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
560 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300561 ASSERT_GL_NO_ERROR();
562
563 // Test glCopyTexImage2D and glCopyTexSubImage2D.
564 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300565 GLTexture tex2;
566 glBindTexture(GL_TEXTURE_2D, tex2);
567 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300568
569 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
570 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
571
572 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
573 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300574 }
575
576 // Test glCopyTexSubImage3D.
577 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300578 GLTexture tex2;
579 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300580 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
581
582 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
583 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300584 }
585}
586
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300587// Test that the active read framebuffer can be read with glCopyTex* if it only has one layered
588// view.
589TEST_P(FramebufferMultiviewTest, CopyTex)
590{
591 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
592
593 GLFramebuffer fbo;
594 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
595
596 GLTexture tex;
597 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
598 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
599
600 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
601 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
602 ASSERT_GL_NO_ERROR();
603
604 // Test glCopyTexImage2D and glCopyTexSubImage2D.
605 {
606 GLTexture tex2;
607 glBindTexture(GL_TEXTURE_2D, tex2);
608 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
609
610 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
611 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
612 glClear(GL_COLOR_BUFFER_BIT);
613
614 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
615 ASSERT_GL_NO_ERROR();
616
617 // Test texture contents.
618 glBindFramebuffer(GL_FRAMEBUFFER, 0);
619 draw2DTexturedQuad(0.0f, 1.0f, true);
620 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
621
622 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
623 glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
624 glClear(GL_COLOR_BUFFER_BIT);
625
626 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
627 ASSERT_GL_NO_ERROR();
628
629 glBindFramebuffer(GL_FRAMEBUFFER, 0);
630 draw2DTexturedQuad(0.0f, 1.0f, true);
631 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
632 }
633
634 // Test glCopyTexSubImage3D.
635 {
636 GLTexture tex2;
637 glBindTexture(GL_TEXTURE_3D, tex2);
638 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
639
640 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
641 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
642 glClear(GL_COLOR_BUFFER_BIT);
643 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
644 ASSERT_GL_NO_ERROR();
645
646 glBindFramebuffer(GL_FRAMEBUFFER, 0);
647 draw3DTexturedQuad(0.0f, 1.0f, true, 0.0f);
648 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
649 }
650}
651
Martin Radeva3ed4572017-07-27 18:29:37 +0300652// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300653// draw framebuffer, or current read framebuffer have multiview attachments with a side-by-side
654// layout.
Martin Radeva3ed4572017-07-27 18:29:37 +0300655TEST_P(FramebufferMultiviewTest, InvalidBlit)
656{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300657 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeva3ed4572017-07-27 18:29:37 +0300658
Martin Radev0f7714e2017-08-07 15:13:42 +0300659 GLFramebuffer fbo;
660 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300661
Martin Radev0f7714e2017-08-07 15:13:42 +0300662 GLTexture tex;
663 glBindTexture(GL_TEXTURE_2D, tex);
664 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
665
666 const GLint kViewportOffsets[2] = {0};
667 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
668 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300669 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
670 ASSERT_GL_NO_ERROR();
671
672 // Blit with the active read framebuffer having multiview attachments.
673 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300674 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300675 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
676 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
677 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
678 }
679
680 // Blit with the active draw framebuffer having multiview attachments.
681 {
682 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300683 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300684 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
685 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
686 }
687}
688
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300689// Test that glBlitFramebuffer succeeds if the current read framebuffer has just one layered view.
690TEST_P(FramebufferMultiviewTest, Blit)
691{
692 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
693
694 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
695 glClear(GL_COLOR_BUFFER_BIT);
696
697 GLFramebuffer fbo;
698 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
699
700 GLTexture tex;
701 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
702 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
703
704 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
705 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
706 ASSERT_GL_NO_ERROR();
707
708 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
709 glClear(GL_COLOR_BUFFER_BIT);
710
711 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
712 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
713 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
714 ASSERT_GL_NO_ERROR();
715
716 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
717 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
718}
719
Martin Radev28031682017-07-28 14:47:56 +0300720// Test that glReadPixels generates an invalid framebuffer operation error if the current read
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300721// framebuffer has a side-by-side multi-view layout.
Martin Radev28031682017-07-28 14:47:56 +0300722TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
723{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300724 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev28031682017-07-28 14:47:56 +0300725
Martin Radev0f7714e2017-08-07 15:13:42 +0300726 GLFramebuffer fbo;
727 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300728
Martin Radev0f7714e2017-08-07 15:13:42 +0300729 GLTexture tex;
730 glBindTexture(GL_TEXTURE_2D, tex);
731 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
732
733 const GLint kViewportOffsets[2] = {0};
734 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
735 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300736 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
737 ASSERT_GL_NO_ERROR();
738
739 GLColor pixelColor;
740 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
741 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
742}
743
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300744// Test that glReadPixels succeeds from a layered multiview framebuffer with just one view.
745TEST_P(FramebufferMultiviewTest, ReadPixels)
746{
747 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
748
749 GLFramebuffer fbo;
750 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
751
752 GLTexture tex;
753 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
754 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
755
756 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
757 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
758 ASSERT_GL_NO_ERROR();
759
760 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
761 glClear(GL_COLOR_BUFFER_BIT);
762
763 GLColor pixelColor;
764 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
765 ASSERT_GL_NO_ERROR();
766 EXPECT_COLOR_NEAR(GLColor::green, pixelColor, 2);
767}
768
Martin Radeveef80e42017-08-11 14:44:57 +0300769// Test that glClear clears only the contents of each view if the scissor test is enabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300770TEST_P(FramebufferMultiviewSideBySideClearTest, ColorBufferClear)
Martin Radevb0761932017-07-25 17:42:25 +0300771{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300772 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevb0761932017-07-25 17:42:25 +0300773
Martin Radev5c00d0d2017-08-07 10:06:59 +0300774 initializeFBOs(1, false, false);
Martin Radevb0761932017-07-25 17:42:25 +0300775
776 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300777 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
778 glClearColor(1, 0, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300779 glClear(GL_COLOR_BUFFER_BIT);
780
781 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300782 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300783 glViewport(0, 0, 1, 2);
784 glScissor(0, 0, 1, 2);
Martin Radeveef80e42017-08-11 14:44:57 +0300785 glEnable(GL_SCISSOR_TEST);
Martin Radevb0761932017-07-25 17:42:25 +0300786
Martin Radev5c00d0d2017-08-07 10:06:59 +0300787 glClearColor(0, 1, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300788 glClear(GL_COLOR_BUFFER_BIT);
789
Martin Radev5c00d0d2017-08-07 10:06:59 +0300790 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300791
Martin Radev5c00d0d2017-08-07 10:06:59 +0300792 checkAlternatingColumnsOfRedAndGreenInFBO();
Martin Radevb0761932017-07-25 17:42:25 +0300793}
794
Martin Radev82ef7742017-08-08 17:44:58 +0300795// Test that glFramebufferTextureMultiviewLayeredANGLE modifies the internal multiview state.
796TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
797{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300798 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300799
800 GLFramebuffer multiviewFBO;
801 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
802
803 GLTexture tex;
804 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
805 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
806 ASSERT_GL_NO_ERROR();
807
808 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
809 ASSERT_GL_NO_ERROR();
810
811 GLint numViews = -1;
812 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
813 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
814 &numViews);
815 ASSERT_GL_NO_ERROR();
816 EXPECT_EQ(2, numViews);
817
818 GLint baseViewIndex = -1;
819 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
820 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
821 &baseViewIndex);
822 ASSERT_GL_NO_ERROR();
823 EXPECT_EQ(1, baseViewIndex);
824
825 GLint multiviewLayout = GL_NONE;
826 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
827 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
828 &multiviewLayout);
829 ASSERT_GL_NO_ERROR();
830 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, multiviewLayout);
831
832 GLint internalViewportOffsets[2] = {-1};
833 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
834 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
835 &internalViewportOffsets[0]);
836 ASSERT_GL_NO_ERROR();
837 EXPECT_EQ(0, internalViewportOffsets[0]);
838 EXPECT_EQ(0, internalViewportOffsets[1]);
839}
840
841// Test framebuffer completeness status of a layered framebuffer with color attachments.
842TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
843{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300844 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300845
846 GLFramebuffer fbo;
847 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
848
849 GLTexture tex;
850 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
851 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
852
853 // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
854 // attachment will be modified to change the framebuffer's status.
855 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
856 ASSERT_GL_NO_ERROR();
857
858 GLTexture otherTexLayered;
859 glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
860 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
861
862 // Test framebuffer completeness when the base view index differs.
863 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
864 0, 1, 2);
865 ASSERT_GL_NO_ERROR();
866 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
867 glCheckFramebufferStatus(GL_FRAMEBUFFER));
868
869 // Test framebuffer completeness when the 1st attachment has a side-by-side layout.
870 const int kViewportOffsets[4] = {0, 0, 0, 0};
871 GLTexture otherTex2D;
872 glBindTexture(GL_TEXTURE_2D, otherTex2D);
873 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
874 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex2D,
875 0, 2, kViewportOffsets);
876 ASSERT_GL_NO_ERROR();
877 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
878 glCheckFramebufferStatus(GL_FRAMEBUFFER));
879
Martin Radev5e424fa2017-08-09 16:25:36 +0300880 // Test framebuffer completeness when the 1st attachment has a non-multiview layout.
Martin Radev82ef7742017-08-08 17:44:58 +0300881 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
882 ASSERT_GL_NO_ERROR();
883 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
884 glCheckFramebufferStatus(GL_FRAMEBUFFER));
885
886 // Test that framebuffer is complete when the number of views, base view index and layouts are
887 // the same.
888 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
889 0, 0, 2);
890 ASSERT_GL_NO_ERROR();
891 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
892}
893
Martin Radeveef80e42017-08-11 14:44:57 +0300894// Test that glClear clears all of the contents if the scissor test is disabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300895TEST_P(FramebufferMultiviewSideBySideClearTest, ClearWithDisabledScissorTest)
Martin Radeveef80e42017-08-11 14:44:57 +0300896{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300897 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeveef80e42017-08-11 14:44:57 +0300898
Martin Radev5c00d0d2017-08-07 10:06:59 +0300899 initializeFBOs(1, false, false);
Martin Radeveef80e42017-08-11 14:44:57 +0300900
901 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300902 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
903 glClearColor(0, 0, 0, 1);
Martin Radeveef80e42017-08-11 14:44:57 +0300904 glClear(GL_COLOR_BUFFER_BIT);
905
906 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300907 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300908 glViewport(0, 0, 1, 2);
909 glScissor(0, 0, 1, 2);
910
911 glClearColor(1, 0, 0, 1);
912 glClear(GL_COLOR_BUFFER_BIT);
913
Martin Radev5c00d0d2017-08-07 10:06:59 +0300914 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300915
916 for (int i = 0; i < 4; ++i)
917 {
918 for (int j = 0; j < 2; ++j)
919 {
920 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
921 }
922 }
923}
924
Martin Radev5c00d0d2017-08-07 10:06:59 +0300925// Test that glClear clears the depth buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300926TEST_P(FramebufferMultiviewSideBySideClearTest, DepthBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +0300927{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300928 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +0300929
930 // Create program to draw a quad.
931 const std::string &vs =
932 "#version 300 es\n"
933 "in vec3 vPos;\n"
934 "void main(){\n"
935 " gl_Position = vec4(vPos, 1.);\n"
936 "}\n";
937 const std::string &fs =
938 "#version 300 es\n"
939 "precision mediump float;\n"
940 "uniform vec3 uCol;\n"
941 "out vec4 col;\n"
942 "void main(){\n"
943 " col = vec4(uCol,1.);\n"
944 "}\n";
945 ANGLE_GL_PROGRAM(program, vs, fs);
946 glUseProgram(program);
947 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
948
949 initializeFBOs(1, false, true);
950 glEnable(GL_DEPTH_TEST);
951
952 // Clear the contents of the texture.
953 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
954 glClearColor(0, 0, 0, 0);
955 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
956
957 // Dirty the depth and color buffers.
958 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
959 drawQuad(program, "vPos", 0.0f, 1.0f, true);
960
961 // Switch to the multi-view framebuffer and clear only the rectangles covered by the views.
962 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
963 glViewport(0, 0, 1, 2);
964 glScissor(0, 0, 1, 2);
965 glEnable(GL_SCISSOR_TEST);
966 glClear(GL_DEPTH_BUFFER_BIT);
967
968 // Draw a fullscreen quad to fill the cleared regions.
969 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
970 glViewport(0, 0, 4, 2);
971 glScissor(0, 0, 4, 2);
972 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
973 drawQuad(program, "vPos", 0.5f, 1.0f, true);
974
975 checkAlternatingColumnsOfRedAndGreenInFBO();
976}
977
978// Test that glClear clears the stencil buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300979TEST_P(FramebufferMultiviewSideBySideClearTest, StencilBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +0300980{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300981 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +0300982
983 // Create program to draw a quad.
984 const std::string &vs =
985 "#version 300 es\n"
986 "in vec3 vPos;\n"
987 "void main(){\n"
988 " gl_Position = vec4(vPos, 1.);\n"
989 "}\n";
990 const std::string &fs =
991 "#version 300 es\n"
992 "precision mediump float;\n"
993 "uniform vec3 uCol;\n"
994 "out vec4 col;\n"
995 "void main(){\n"
996 " col = vec4(uCol,1.);\n"
997 "}\n";
998 ANGLE_GL_PROGRAM(program, vs, fs);
999 glUseProgram(program);
1000 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1001
1002 initializeFBOs(1, true, false);
1003 glEnable(GL_STENCIL_TEST);
1004 glDisable(GL_DEPTH_TEST);
1005
1006 // Set clear values and clear the whole framebuffer.
1007 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1008 glClearColor(0, 0, 0, 0);
1009 glClearStencil(0);
1010 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1011
1012 // Update stencil test to always replace the stencil value with 0xFF.
1013 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1014 glStencilFunc(GL_ALWAYS, 0xFF, 0);
1015
1016 // Draw a quad which covers the whole texture.
1017 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1018 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1019
1020 // Switch to multiview framebuffer and clear portions of the texture.
1021 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1022 glViewport(0, 0, 1, 2);
1023 glScissor(0, 0, 1, 2);
1024 glEnable(GL_SCISSOR_TEST);
1025 glClear(GL_STENCIL_BUFFER_BIT);
1026
1027 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1028 // the test.
1029 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1030 glViewport(0, 0, 4, 2);
1031 glScissor(0, 0, 4, 2);
1032 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1033 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1034 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1035
1036 checkAlternatingColumnsOfRedAndGreenInFBO();
1037}
1038
1039// Test that glClearBufferf clears the color buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001040TEST_P(FramebufferMultiviewSideBySideClearTest, ClearBufferF)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001041{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001042 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001043
1044 initializeFBOs(2, false, false);
1045
1046 // Clear the contents of the texture.
1047 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1048 glClearColor(1, 0, 0, 1);
1049 glClear(GL_COLOR_BUFFER_BIT);
1050
1051 // Bind and specify viewport/scissor dimensions for each view.
1052 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1053 glViewport(0, 0, 1, 2);
1054 glScissor(0, 0, 1, 2);
1055 glEnable(GL_SCISSOR_TEST);
1056
1057 float kClearValues[4] = {0.f, 1.f, 0.f, 1.f};
1058 glClearBufferfv(GL_COLOR, 1, kClearValues);
1059
1060 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1061
1062 // Check that glClearBufferfv has not modified the 0th color attachment.
1063 glReadBuffer(GL_COLOR_ATTACHMENT0);
1064 for (int i = 0; i < 4; ++i)
1065 {
1066 for (int j = 0; j < 2; ++j)
1067 {
1068 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
1069 }
1070 }
1071
1072 // Check that glClearBufferfv has correctly modified the 1th color attachment.
1073 glReadBuffer(GL_COLOR_ATTACHMENT1);
1074 checkAlternatingColumnsOfRedAndGreenInFBO();
1075}
1076
Martin Radev5e424fa2017-08-09 16:25:36 +03001077// Test that glClear clears the contents of the color buffer for only the attached layers to a
1078// layered FBO.
1079TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
1080{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001081 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001082
1083 initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
1084
1085 // Bind and specify viewport/scissor dimensions for each view.
1086 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1087
1088 glClearColor(0, 1, 0, 1);
1089 glClear(GL_COLOR_BUFFER_BIT);
1090
1091 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1092 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1093 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1094 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1095}
1096
1097// Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
1098TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
1099{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001100 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001101
1102 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1103
1104 for (int i = 0; i < 2; ++i)
1105 {
1106 for (int layer = 0; layer < 4; ++layer)
1107 {
1108 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
1109 EXPECT_EQ(GLColor::red, getLayerColor(layer, colorAttachment));
1110 }
1111 }
1112
1113 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1114
1115 float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
1116 glClearBufferfv(GL_COLOR, 0, clearValues0);
1117
1118 float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
1119 glClearBufferfv(GL_COLOR, 1, clearValues1);
1120
1121 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1122 EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1123 EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1124 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1125
1126 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT1));
1127 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1128 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
1129 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT1));
1130}
1131
1132// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1133// to a layered FBO.
1134TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
1135{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001136 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001137
1138 // Create program to draw a quad.
1139 const std::string &vs =
1140 "#version 300 es\n"
1141 "in vec3 vPos;\n"
1142 "void main(){\n"
1143 " gl_Position = vec4(vPos, 1.);\n"
1144 "}\n";
1145 const std::string &fs =
1146 "#version 300 es\n"
1147 "precision mediump float;\n"
1148 "uniform vec3 uCol;\n"
1149 "out vec4 col;\n"
1150 "void main(){\n"
1151 " col = vec4(uCol,1.);\n"
1152 "}\n";
1153 ANGLE_GL_PROGRAM(program, vs, fs);
1154 glUseProgram(program);
1155 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1156
1157 initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
1158 glEnable(GL_STENCIL_TEST);
1159 glDisable(GL_DEPTH_TEST);
1160
1161 // Set clear values.
1162 glClearColor(1, 0, 0, 1);
1163 glClearStencil(0xFF);
1164
1165 // Clear the color and stencil buffers of each layer.
1166 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1167 {
1168 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1169 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1170 }
1171
1172 // Switch to multiview framebuffer and clear portions of the texture.
1173 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1174 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1175
1176 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1177 // the test.
1178 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1179 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1180 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1181 {
1182 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1183 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1184 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1185 }
1186 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1187 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1188 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1189 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1190}
1191
1192// Test that glClear does not clear the content of a detached texture.
1193TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
1194{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001195 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001196
1197 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1198
1199 // Clear all attachments.
1200 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1201 glClearColor(0, 1, 0, 1);
1202 glClear(GL_COLOR_BUFFER_BIT);
1203
1204 for (int i = 0; i < 2; ++i)
1205 {
1206 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
1207 EXPECT_EQ(GLColor::red, getLayerColor(0, colorAttachment));
1208 EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
1209 EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
1210 EXPECT_EQ(GLColor::red, getLayerColor(3, colorAttachment));
1211 }
1212
1213 // Detach and clear again.
1214 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1215 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
1216 glClearColor(1, 1, 0, 1);
1217 glClear(GL_COLOR_BUFFER_BIT);
1218
1219 // Check that color attachment 0 is modified.
1220 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1221 EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1222 EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1223 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1224
1225 // Check that color attachment 1 is unmodified.
1226 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT1));
1227 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1228 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
1229 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT1));
1230}
1231
1232// Test that glClear clears only the contents within the scissor rectangle of the attached layers.
1233TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
1234{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001235 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001236
1237 initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
1238
1239 // Bind and specify viewport/scissor dimensions for each view.
1240 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1241
1242 glEnable(GL_SCISSOR_TEST);
1243 glScissor(1, 0, 1, 1);
1244 glClearColor(0, 1, 0, 1);
1245 glClear(GL_COLOR_BUFFER_BIT);
1246
1247 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1248 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
1249
1250 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1251 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
1252
1253 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1254 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
1255
1256 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1257 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
1258}
1259
Martin Radev18b75ba2017-08-15 15:50:40 +03001260// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1261// to a layered FBO.
1262TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
1263{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001264 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev18b75ba2017-08-15 15:50:40 +03001265
1266 // Create program to draw a quad.
1267 const std::string &vs =
1268 "#version 300 es\n"
1269 "in vec3 vPos;\n"
1270 "void main(){\n"
1271 " gl_Position = vec4(vPos, 1.);\n"
1272 "}\n";
1273 const std::string &fs =
1274 "#version 300 es\n"
1275 "precision mediump float;\n"
1276 "uniform vec3 uCol;\n"
1277 "out vec4 col;\n"
1278 "void main(){\n"
1279 " col = vec4(uCol,1.);\n"
1280 "}\n";
1281 ANGLE_GL_PROGRAM(program, vs, fs);
1282 glUseProgram(program);
1283 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1284
1285 initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
1286 glEnable(GL_STENCIL_TEST);
1287 glDisable(GL_DEPTH_TEST);
1288
1289 // Set clear values.
1290 glClearColor(1, 0, 0, 1);
1291 glClearStencil(0xFF);
1292
1293 // Clear the color and stencil buffers of each layer.
1294 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1295 {
1296 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1297 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1298 }
1299
1300 // Switch to multiview framebuffer and clear portions of the texture.
1301 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1302 glEnable(GL_SCISSOR_TEST);
1303 glScissor(0, 0, 1, 1);
1304 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1305 glDisable(GL_SCISSOR_TEST);
1306
1307 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1308 // the test.
1309 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1310 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1311 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1312 {
1313 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1314 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1315 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1316 }
1317 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1318 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
1319 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1320 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
1321 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1322 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
1323 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1324 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
1325}
1326
Martin Radev14b21262017-08-25 13:54:37 +03001327// Test that detaching an attachment does not generate an error whenever the multi-view related
1328// arguments are invalid.
1329TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
1330{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001331 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev14b21262017-08-25 13:54:37 +03001332
1333 GLFramebuffer fbo;
1334 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1335
1336 // Invalid base view index.
1337 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
1338 EXPECT_GL_NO_ERROR();
1339
1340 // Invalid number of views.
1341 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
1342 EXPECT_GL_NO_ERROR();
1343
1344 // Invalid number of views.
1345 const GLint kValidViewportOffsets[2] = {0, 0};
1346 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0,
1347 kValidViewportOffsets);
1348 EXPECT_GL_NO_ERROR();
1349
1350 // Invalid viewport offsets.
1351 const GLint kInvalidViewportOffsets[2] = {-1, -1};
1352 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 1,
1353 kInvalidViewportOffsets);
1354 EXPECT_GL_NO_ERROR();
1355}
1356
Martin Radev61e710b2017-09-05 11:59:52 +03001357// Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
1358// array are attached. The test is added because a special fast code path is used for this case.
1359TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
1360{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001361 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev61e710b2017-09-05 11:59:52 +03001362
1363 initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
1364
1365 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1366 glClearColor(0, 1, 0, 1);
1367 glClear(GL_COLOR_BUFFER_BIT);
1368
1369 EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1370 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1371}
1372
Olli Etuahof26b27e2018-08-17 11:01:19 +03001373ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));
1374ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest,
1375 VertexShaderOpenGL(3, 0),
1376 GeomShaderD3D11(3, 0));
1377ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest,
1378 VertexShaderOpenGL(3, 0),
1379 GeomShaderD3D11(3, 0));