blob: 0238d987fad19d5a9f948eb156340567b6a47d49 [file] [log] [blame]
Martin Radeve5285d22017-07-14 16:23:53 +03001//
2// Copyright 2017 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// Framebuffer multiview tests:
7// The tests modify and examine the multiview state.
8//
9
10#include "test_utils/ANGLETest.h"
Martin Radev0f7714e2017-08-07 15:13:42 +030011#include "test_utils/gl_raii.h"
Martin Radeve5285d22017-07-14 16:23:53 +030012
13using namespace angle;
14
15class FramebufferMultiviewTest : public ANGLETest
16{
17 protected:
Martin Radev0f7714e2017-08-07 15:13:42 +030018 FramebufferMultiviewTest()
Martin Radeve5285d22017-07-14 16:23:53 +030019 {
20 setWindowWidth(128);
21 setWindowHeight(128);
22 setWebGLCompatibilityEnabled(true);
23 }
24
25 void SetUp() override
26 {
27 ANGLETest::SetUp();
Martin Radeve5285d22017-07-14 16:23:53 +030028 glRequestExtensionANGLE = reinterpret_cast<PFNGLREQUESTEXTENSIONANGLEPROC>(
29 eglGetProcAddress("glRequestExtensionANGLE"));
30 }
31
Martin Radev137032d2017-07-13 10:11:12 +030032 // Requests the ANGLE_multiview extension and returns true if the operation succeeds.
33 bool requestMultiviewExtension()
34 {
35 if (extensionRequestable("GL_ANGLE_multiview"))
36 {
37 glRequestExtensionANGLE("GL_ANGLE_multiview");
38 }
39
40 if (!extensionEnabled("GL_ANGLE_multiview"))
41 {
42 std::cout << "Test skipped due to missing GL_ANGLE_multiview." << std::endl;
43 return false;
44 }
45 return true;
46 }
47
Martin Radeve5285d22017-07-14 16:23:53 +030048 PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
49};
50
51// Test that the framebuffer tokens introduced by ANGLE_multiview can be used query the framebuffer
52// state and that their corresponding default values are correctly set.
53TEST_P(FramebufferMultiviewTest, DefaultState)
54{
Martin Radev137032d2017-07-13 10:11:12 +030055 if (!requestMultiviewExtension())
Martin Radeve5285d22017-07-14 16:23:53 +030056 {
Martin Radeve5285d22017-07-14 16:23:53 +030057 return;
58 }
59
Martin Radev0f7714e2017-08-07 15:13:42 +030060 GLFramebuffer fbo;
61 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
62
63 GLTexture tex;
64 glBindTexture(GL_TEXTURE_2D, tex);
65 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
66 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +030067
Martin Radeve5285d22017-07-14 16:23:53 +030068 GLint numViews = -1;
69 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
70 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
71 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +030072 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +030073 EXPECT_EQ(1, numViews);
74
75 GLint baseViewIndex = -1;
76 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
77 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
78 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +030079 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +030080 EXPECT_EQ(0, baseViewIndex);
81
82 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
83 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
84 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
85 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +030086 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +030087 EXPECT_EQ(GL_NONE, multiviewLayout);
88
89 GLint viewportOffsets[2] = {-1, -1};
90 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
91 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
92 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +030093 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +030094 EXPECT_EQ(0, viewportOffsets[0]);
95 EXPECT_EQ(0, viewportOffsets[1]);
96}
97
98// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
99// the ANGLE_multiview tokens results in an INVALID_ENUM error.
100TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
101{
Martin Radev0f7714e2017-08-07 15:13:42 +0300102 GLFramebuffer fbo;
103 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
104
105 GLTexture tex;
106 glBindTexture(GL_TEXTURE_2D, tex);
107 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
108 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300109
Martin Radeve5285d22017-07-14 16:23:53 +0300110 GLint numViews = -1;
111 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
112 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
113 &numViews);
114 EXPECT_GL_ERROR(GL_INVALID_ENUM);
115
116 GLint baseViewIndex = -1;
117 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
118 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
119 &baseViewIndex);
120 EXPECT_GL_ERROR(GL_INVALID_ENUM);
121
122 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
123 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
124 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
125 &multiviewLayout);
126 EXPECT_GL_ERROR(GL_INVALID_ENUM);
127
128 GLint viewportOffsets[2] = {-1, -1};
129 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
130 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
131 &viewportOffsets[0]);
132 EXPECT_GL_ERROR(GL_INVALID_ENUM);
133}
134
Martin Radev137032d2017-07-13 10:11:12 +0300135// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
136// is called with invalid arguments.
137TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
138{
139 if (!requestMultiviewExtension())
140 {
141 return;
142 }
143
Martin Radev0f7714e2017-08-07 15:13:42 +0300144 GLFramebuffer fbo;
145 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
146
147 GLTexture tex;
148 glBindTexture(GL_TEXTURE_2D, tex);
149 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
150
Martin Radev137032d2017-07-13 10:11:12 +0300151 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300152 GLint viewportOffsets[2] = {-1};
153 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
154 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300155 EXPECT_GL_ERROR(GL_INVALID_VALUE);
156
157 // Negative number of views.
158 viewportOffsets[0] = 0;
159 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300160 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1,
161 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300162 EXPECT_GL_ERROR(GL_INVALID_VALUE);
163}
164
165// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
166// called with invalid arguments.
167TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
168{
169 if (!requestMultiviewExtension())
170 {
171 return;
172 }
173
Martin Radev0f7714e2017-08-07 15:13:42 +0300174 GLFramebuffer fbo;
175 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
176
177 GLTexture tex;
178 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
179 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
180 ASSERT_GL_NO_ERROR();
181
Martin Radev137032d2017-07-13 10:11:12 +0300182 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300183 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300184 EXPECT_GL_ERROR(GL_INVALID_VALUE);
185
186 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
187 GLint maxTextureLayers = 0;
188 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300189 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
190 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300191 EXPECT_GL_ERROR(GL_INVALID_VALUE);
192}
193
194// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
195// available.
196TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
197{
Martin Radev0f7714e2017-08-07 15:13:42 +0300198 GLFramebuffer fbo;
199 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
200
201 GLTexture tex;
202 glBindTexture(GL_TEXTURE_2D, tex);
203 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
204
Martin Radev9bc9a322017-07-21 14:28:17 +0300205 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300206 const GLint kViewportOffsets[2] = {0};
207 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
208 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300209 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
210}
211
Martin Radev5dae57b2017-07-14 16:15:55 +0300212// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
213TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
214{
215 if (!requestMultiviewExtension())
216 {
217 return;
218 }
219
Martin Radev0f7714e2017-08-07 15:13:42 +0300220 GLFramebuffer fbo;
221 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
222
223 GLTexture tex;
224 glBindTexture(GL_TEXTURE_2D, tex);
225 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
226
227 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
228 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
229 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300230 ASSERT_GL_NO_ERROR();
231
232 GLint numViews = -1;
233 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
234 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
235 &numViews);
236 ASSERT_GL_NO_ERROR();
237 EXPECT_EQ(2, numViews);
238
239 GLint baseViewIndex = -1;
240 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
241 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
242 &baseViewIndex);
243 ASSERT_GL_NO_ERROR();
244 EXPECT_EQ(0, baseViewIndex);
245
246 GLint multiviewLayout = GL_NONE;
247 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
248 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
249 &multiviewLayout);
250 ASSERT_GL_NO_ERROR();
251 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
252
253 GLint internalViewportOffsets[4] = {-1};
254 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
255 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
256 &internalViewportOffsets[0]);
257 ASSERT_GL_NO_ERROR();
258 for (size_t i = 0u; i < 4u; ++i)
259 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300260 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300261 }
262}
263
Martin Radev9bc9a322017-07-21 14:28:17 +0300264// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
265// attachments.
266TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
267{
268 if (!requestMultiviewExtension())
269 {
270 return;
271 }
272
Martin Radev0f7714e2017-08-07 15:13:42 +0300273 GLFramebuffer fbo;
274 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300275
Martin Radev0f7714e2017-08-07 15:13:42 +0300276 GLTexture tex;
277 glBindTexture(GL_TEXTURE_2D, tex);
278 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300279
Martin Radev0f7714e2017-08-07 15:13:42 +0300280 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
281 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300282
283 // Set the 0th attachment and keep it as it is till the end of the test. The 1st or depth
284 // attachment will me modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300285 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
286 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300287 ASSERT_GL_NO_ERROR();
288
289 // Color attachment 1.
290 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300291 GLTexture otherTex;
292 glBindTexture(GL_TEXTURE_2D, otherTex);
293 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
294
Martin Radev9bc9a322017-07-21 14:28:17 +0300295 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300296 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
297 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300298 ASSERT_GL_NO_ERROR();
299 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
300 glCheckFramebufferStatus(GL_FRAMEBUFFER));
301
302 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300303 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
304 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300305 ASSERT_GL_NO_ERROR();
306 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
307 glCheckFramebufferStatus(GL_FRAMEBUFFER));
308
309 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300310 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300311 ASSERT_GL_NO_ERROR();
312 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
313 glCheckFramebufferStatus(GL_FRAMEBUFFER));
314
315 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
316 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300317 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
318 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300319 ASSERT_GL_NO_ERROR();
320 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
321
322 // Reset attachment 1
323 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300324 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300325 }
326
327 // Depth attachment.
328 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300329 GLTexture depthTex;
330 glBindTexture(GL_TEXTURE_2D, depthTex);
331 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
332 nullptr);
333
Martin Radev9bc9a322017-07-21 14:28:17 +0300334 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300335 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
336 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300337 ASSERT_GL_NO_ERROR();
338 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
339 glCheckFramebufferStatus(GL_FRAMEBUFFER));
340
341 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300342 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
343 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300344 ASSERT_GL_NO_ERROR();
345 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
346 glCheckFramebufferStatus(GL_FRAMEBUFFER));
347
348 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300349 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300350 ASSERT_GL_NO_ERROR();
351 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
352 glCheckFramebufferStatus(GL_FRAMEBUFFER));
353
354 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
355 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300356 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
357 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300358 ASSERT_GL_NO_ERROR();
359 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
360 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300361}
362
Martin Radev04e2c3b2017-07-27 16:54:35 +0300363// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
364// attachments.
365TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
366{
367 if (!requestMultiviewExtension())
368 {
369 return;
370 }
371
Martin Radev0f7714e2017-08-07 15:13:42 +0300372 GLFramebuffer fbo;
373 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300374
Martin Radev0f7714e2017-08-07 15:13:42 +0300375 GLTexture tex;
376 glBindTexture(GL_TEXTURE_2D, tex);
377 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
378
379 const GLint kViewportOffsets[2] = {0};
380 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
381 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300382 ASSERT_GL_NO_ERROR();
383
384 // Test glCopyTexImage2D and glCopyTexSubImage2D.
385 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300386 GLTexture tex2;
387 glBindTexture(GL_TEXTURE_2D, tex2);
388 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300389
390 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
391 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
392
393 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
394 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300395 }
396
397 // Test glCopyTexSubImage3D.
398 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300399 GLTexture tex2;
400 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300401 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
402
403 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
404 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300405 }
406}
407
Martin Radeva3ed4572017-07-27 18:29:37 +0300408// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
409// draw framebuffer, or current read framebuffer have multiview attachments.
410TEST_P(FramebufferMultiviewTest, InvalidBlit)
411{
412 if (!requestMultiviewExtension())
413 {
414 return;
415 }
416
Martin Radev0f7714e2017-08-07 15:13:42 +0300417 GLFramebuffer fbo;
418 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300419
Martin Radev0f7714e2017-08-07 15:13:42 +0300420 GLTexture tex;
421 glBindTexture(GL_TEXTURE_2D, tex);
422 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
423
424 const GLint kViewportOffsets[2] = {0};
425 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
426 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300427 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
428 ASSERT_GL_NO_ERROR();
429
430 // Blit with the active read framebuffer having multiview attachments.
431 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300432 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300433 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
434 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
435 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
436 }
437
438 // Blit with the active draw framebuffer having multiview attachments.
439 {
440 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300441 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300442 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
443 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
444 }
445}
446
Martin Radev28031682017-07-28 14:47:56 +0300447// Test that glReadPixels generates an invalid framebuffer operation error if the current read
448// framebuffer has a multi-view layout.
449TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
450{
451 if (!requestMultiviewExtension())
452 {
453 return;
454 }
455
Martin Radev0f7714e2017-08-07 15:13:42 +0300456 GLFramebuffer fbo;
457 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300458
Martin Radev0f7714e2017-08-07 15:13:42 +0300459 GLTexture tex;
460 glBindTexture(GL_TEXTURE_2D, tex);
461 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
462
463 const GLint kViewportOffsets[2] = {0};
464 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
465 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300466 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
467 ASSERT_GL_NO_ERROR();
468
469 GLColor pixelColor;
470 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
471 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
472}
473
Martin Radevb0761932017-07-25 17:42:25 +0300474// Test that glClear clears only the contents of each view.
475TEST_P(FramebufferMultiviewTest, SideBySideClear)
476{
477 if (!requestMultiviewExtension())
478 {
479 return;
480 }
481
Martin Radev0f7714e2017-08-07 15:13:42 +0300482 GLFramebuffer multiviewFBO;
483 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
484
485 GLTexture tex;
486 glBindTexture(GL_TEXTURE_2D, tex);
487 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
488
489 const GLint kViewportOffsets[4] = {1, 0, 3, 0};
490 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
491 &kViewportOffsets[0]);
Martin Radevb0761932017-07-25 17:42:25 +0300492
493 // Create and bind a normal framebuffer to access the 2D texture.
Martin Radev0f7714e2017-08-07 15:13:42 +0300494 GLFramebuffer normalFBO;
495 glBindFramebuffer(GL_FRAMEBUFFER, normalFBO);
496 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300497
498 // Clear the contents of the texture.
499 glClearColor(0, 0, 0, 0);
500 glClear(GL_COLOR_BUFFER_BIT);
501
502 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev0f7714e2017-08-07 15:13:42 +0300503 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300504 glViewport(0, 0, 1, 2);
505 glScissor(0, 0, 1, 2);
506
507 glClearColor(1, 0, 0, 0);
508 glClear(GL_COLOR_BUFFER_BIT);
509
Martin Radev0f7714e2017-08-07 15:13:42 +0300510 glBindFramebuffer(GL_FRAMEBUFFER, normalFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300511
512 // column 0
513 EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
514 EXPECT_PIXEL_EQ(0, 1, 0, 0, 0, 0);
515
516 // column 1
517 EXPECT_PIXEL_EQ(1, 0, 255, 0, 0, 0);
518 EXPECT_PIXEL_EQ(1, 1, 255, 0, 0, 0);
519
520 // column 2
521 EXPECT_PIXEL_EQ(2, 0, 0, 0, 0, 0);
522 EXPECT_PIXEL_EQ(2, 1, 0, 0, 0, 0);
523
524 // column 3
525 EXPECT_PIXEL_EQ(3, 0, 255, 0, 0, 0);
526 EXPECT_PIXEL_EQ(3, 1, 255, 0, 0, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300527}
528
Martin Radeve5285d22017-07-14 16:23:53 +0300529ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, ES3_OPENGL());