blob: 420b8aeaa77c1943f15a2800eaa9ad026f6a11f3 [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)
Jamie Madillb980c562018-11-27 11:34:27 -050041 {}
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030042
43 void TearDown() override
44 {
45 if (mMultiviewFBO != 0)
46 {
47 glDeleteFramebuffers(1, &mMultiviewFBO);
48 mMultiviewFBO = 0u;
49 }
50 if (mNonMultiviewFBO != 0)
51 {
52 glDeleteTextures(1, &mNonMultiviewFBO);
53 mNonMultiviewFBO = 0u;
54 }
55 if (!mColorTex.empty())
56 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -040057 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
58 glDeleteTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030059 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 {
Jamie Madillba319ba2018-12-29 10:29:33 -050076 ASSERT_TRUE(mColorTex.empty());
77 ASSERT_EQ(0u, mDepthStencilTex);
78 ASSERT_EQ(0u, mDepthTex);
Olli Etuahoa7b35c32018-08-21 16:32:24 +030079 const std::vector<GLenum> &drawBuffers = GetDrawBufferRange(numColorBuffers);
Martin Radev5c00d0d2017-08-07 10:06:59 +030080
81 // Generate textures.
82 mColorTex.resize(numColorBuffers);
Shahbaz Youssefic4097442018-08-22 12:14:52 -040083 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
84 glGenTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030085 if (stencil)
86 {
87 glGenTextures(1, &mDepthStencilTex);
88 }
89 else if (depth)
90 {
91 glGenTextures(1, &mDepthTex);
92 }
93
Olli Etuaho2c8f0842018-09-12 14:44:55 +030094 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0, 2, 2, 2,
Olli Etuahoa7b35c32018-08-21 16:32:24 +030095 mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5c00d0d2017-08-07 10:06:59 +030096
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030097 glGenFramebuffers(1, &mMultiviewFBO);
98 glGenFramebuffers(1, &mNonMultiviewFBO);
99
Martin Radev5c00d0d2017-08-07 10:06:59 +0300100 // Generate multiview fbo and attach textures.
101 const GLint kViewportOffsets[4] = {1, 0, 3, 0};
102 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
103 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
104 for (size_t i = 0u; i < numColorBuffers; ++i)
105 {
106 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
107 static_cast<GLenum>(kBase + i),
108 mColorTex[i], 0, 2, &kViewportOffsets[0]);
109 }
110
111 if (stencil)
112 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300113 glFramebufferTextureMultiviewSideBySideANGLE(
114 GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, mDepthStencilTex, 0, 2,
115 &kViewportOffsets[0]);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300116 }
117 else if (depth)
118 {
119 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
120 mDepthTex, 0, 2, &kViewportOffsets[0]);
121 }
122 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
123
Martin Radev5e424fa2017-08-09 16:25:36 +0300124 // Generate non-multiview fbo and attach textures.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300125 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
126 for (size_t i = 0u; i < numColorBuffers; ++i)
127 {
128 glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(kBase + i), GL_TEXTURE_2D,
129 mColorTex[i], 0);
130 }
131 if (stencil)
132 {
133 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300134 mDepthStencilTex, 0);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300135 }
136 else if (depth)
137 {
138 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTex,
139 0);
140 }
141 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
142
143 ASSERT_GL_NO_ERROR();
144 }
145
146 void checkAlternatingColumnsOfRedAndGreenInFBO()
147 {
148 // column 0
149 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
150 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::red);
151
152 // column 1
153 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
154 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
155
156 // column 2
157 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::red);
158 EXPECT_PIXEL_COLOR_EQ(2, 1, GLColor::red);
159
160 // column 3
161 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
162 EXPECT_PIXEL_COLOR_EQ(3, 1, GLColor::green);
163 }
164
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300165 GLuint mMultiviewFBO;
166 GLuint mNonMultiviewFBO;
167
168 private:
169 std::vector<GLuint> mColorTex;
170 GLuint mDepthTex;
171 GLuint mDepthStencilTex;
Martin Radev5c00d0d2017-08-07 10:06:59 +0300172};
173
Martin Radev5e424fa2017-08-09 16:25:36 +0300174class FramebufferMultiviewLayeredClearTest : public FramebufferMultiviewTest
175{
176 protected:
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300177 FramebufferMultiviewLayeredClearTest() : mMultiviewFBO(0), mDepthTex(0), mDepthStencilTex(0) {}
178
179 void TearDown() override
180 {
181 if (mMultiviewFBO != 0)
182 {
183 glDeleteFramebuffers(1, &mMultiviewFBO);
184 mMultiviewFBO = 0u;
185 }
186 if (!mNonMultiviewFBO.empty())
187 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400188 GLsizei textureCount = static_cast<GLsizei>(mNonMultiviewFBO.size());
189 glDeleteTextures(textureCount, mNonMultiviewFBO.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300190 mNonMultiviewFBO.clear();
191 }
192 if (!mColorTex.empty())
193 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400194 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
195 glDeleteTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300196 mColorTex.clear();
197 }
198 if (mDepthStencilTex != 0u)
199 {
200 glDeleteTextures(1, &mDepthStencilTex);
201 mDepthStencilTex = 0u;
202 }
203 if (mDepthTex != 0u)
204 {
205 glDeleteTextures(1, &mDepthTex);
206 mDepthTex = 0u;
207 }
208 MultiviewTest::TearDown();
209 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300210
211 void initializeFBOs(int width,
212 int height,
213 int numLayers,
214 int baseViewIndex,
215 int numViews,
216 int numColorAttachments,
217 bool stencil,
218 bool depth)
219 {
Jamie Madillba319ba2018-12-29 10:29:33 -0500220 ASSERT_TRUE(mColorTex.empty());
221 ASSERT_EQ(0u, mDepthStencilTex);
222 ASSERT_EQ(0u, mDepthTex);
223 ASSERT_LE(baseViewIndex + numViews, numLayers);
Martin Radev5e424fa2017-08-09 16:25:36 +0300224
225 // Generate textures.
226 mColorTex.resize(numColorAttachments);
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400227 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
228 glGenTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300229 if (stencil)
230 {
231 glGenTextures(1, &mDepthStencilTex);
232 }
233 else if (depth)
234 {
235 glGenTextures(1, &mDepthTex);
236 }
237
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300238 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0, width, height,
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300239 numLayers, mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5e424fa2017-08-09 16:25:36 +0300240
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300241 glGenFramebuffers(1, &mMultiviewFBO);
242
Martin Radev5e424fa2017-08-09 16:25:36 +0300243 // Generate multiview FBO and attach textures.
244 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300245 AttachMultiviewTextures(GL_FRAMEBUFFER, GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, width,
246 numViews, baseViewIndex, mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5e424fa2017-08-09 16:25:36 +0300247
248 const auto &drawBuffers = GetDrawBufferRange(numColorAttachments);
249 glDrawBuffers(numColorAttachments, drawBuffers.data());
250
251 // Generate non-multiview FBOs and attach textures.
252 mNonMultiviewFBO.resize(numLayers);
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400253 GLsizei framebufferCount = static_cast<GLsizei>(mNonMultiviewFBO.size());
254 glGenFramebuffers(framebufferCount, mNonMultiviewFBO.data());
Martin Radev5e424fa2017-08-09 16:25:36 +0300255 for (int i = 0; i < numLayers; ++i)
256 {
257 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
258 for (int j = 0; j < numColorAttachments; ++j)
259 {
260 glFramebufferTextureLayer(GL_FRAMEBUFFER,
261 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + j),
262 mColorTex[j], 0, i);
263 }
264 if (stencil)
265 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300266 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
267 mDepthStencilTex, 0, i);
Martin Radev5e424fa2017-08-09 16:25:36 +0300268 }
269 else if (depth)
270 {
271 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTex, 0, i);
272 }
273 glDrawBuffers(numColorAttachments, drawBuffers.data());
Martin Radev5e424fa2017-08-09 16:25:36 +0300274 }
275
276 ASSERT_GL_NO_ERROR();
277 }
278
279 GLColor getLayerColor(size_t layer, GLenum attachment, GLint x, GLint y)
280 {
Jamie Madillba319ba2018-12-29 10:29:33 -0500281 EXPECT_LT(layer, mNonMultiviewFBO.size());
Martin Radev5e424fa2017-08-09 16:25:36 +0300282 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[layer]);
283 glReadBuffer(attachment);
284 return angle::ReadColor(x, y);
285 }
286
287 GLColor getLayerColor(size_t layer, GLenum attachment)
288 {
289 return getLayerColor(layer, attachment, 0, 0);
290 }
291
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300292 GLuint mMultiviewFBO;
293 std::vector<GLuint> mNonMultiviewFBO;
294
295 private:
296 std::vector<GLuint> mColorTex;
297 GLuint mDepthTex;
298 GLuint mDepthStencilTex;
Martin Radev5e424fa2017-08-09 16:25:36 +0300299};
300
301// Test that the framebuffer tokens introduced by ANGLE_multiview can be used to query the
302// framebuffer state and that their corresponding default values are correctly set.
Martin Radeve5285d22017-07-14 16:23:53 +0300303TEST_P(FramebufferMultiviewTest, DefaultState)
304{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300305 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeve5285d22017-07-14 16:23:53 +0300306
Martin Radev0f7714e2017-08-07 15:13:42 +0300307 GLFramebuffer fbo;
308 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
309
310 GLTexture tex;
311 glBindTexture(GL_TEXTURE_2D, tex);
312 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
313 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300314
Martin Radeve5285d22017-07-14 16:23:53 +0300315 GLint numViews = -1;
316 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
317 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
318 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +0300319 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300320 EXPECT_EQ(1, numViews);
321
322 GLint baseViewIndex = -1;
323 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
324 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
325 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +0300326 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300327 EXPECT_EQ(0, baseViewIndex);
328
329 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
330 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
331 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
332 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +0300333 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300334 EXPECT_EQ(GL_NONE, multiviewLayout);
335
336 GLint viewportOffsets[2] = {-1, -1};
337 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
338 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
339 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +0300340 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300341 EXPECT_EQ(0, viewportOffsets[0]);
342 EXPECT_EQ(0, viewportOffsets[1]);
343}
344
345// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
346// the ANGLE_multiview tokens results in an INVALID_ENUM error.
347TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
348{
Martin Radev0f7714e2017-08-07 15:13:42 +0300349 GLFramebuffer fbo;
350 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
351
352 GLTexture tex;
353 glBindTexture(GL_TEXTURE_2D, tex);
354 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
355 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300356
Martin Radeve5285d22017-07-14 16:23:53 +0300357 GLint numViews = -1;
358 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
359 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
360 &numViews);
361 EXPECT_GL_ERROR(GL_INVALID_ENUM);
362
363 GLint baseViewIndex = -1;
364 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
365 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
366 &baseViewIndex);
367 EXPECT_GL_ERROR(GL_INVALID_ENUM);
368
369 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
370 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
371 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
372 &multiviewLayout);
373 EXPECT_GL_ERROR(GL_INVALID_ENUM);
374
375 GLint viewportOffsets[2] = {-1, -1};
376 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
377 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
378 &viewportOffsets[0]);
379 EXPECT_GL_ERROR(GL_INVALID_ENUM);
380}
381
Martin Radev137032d2017-07-13 10:11:12 +0300382// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
383// is called with invalid arguments.
384TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
385{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300386 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300387
Martin Radev0f7714e2017-08-07 15:13:42 +0300388 GLFramebuffer fbo;
389 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
390
391 GLTexture tex;
392 glBindTexture(GL_TEXTURE_2D, tex);
393 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
394
Martin Radev137032d2017-07-13 10:11:12 +0300395 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300396 GLint viewportOffsets[2] = {-1};
397 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
398 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300399 EXPECT_GL_ERROR(GL_INVALID_VALUE);
400
401 // Negative number of views.
402 viewportOffsets[0] = 0;
403 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300404 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1,
405 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300406 EXPECT_GL_ERROR(GL_INVALID_VALUE);
407}
408
409// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
410// called with invalid arguments.
411TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
412{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300413 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300414
Martin Radev0f7714e2017-08-07 15:13:42 +0300415 GLFramebuffer fbo;
416 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
417
418 GLTexture tex;
419 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
420 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
421 ASSERT_GL_NO_ERROR();
422
Martin Radev137032d2017-07-13 10:11:12 +0300423 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300424 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300425 EXPECT_GL_ERROR(GL_INVALID_VALUE);
426
427 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
428 GLint maxTextureLayers = 0;
429 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300430 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
431 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300432 EXPECT_GL_ERROR(GL_INVALID_VALUE);
433}
434
435// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
436// available.
437TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
438{
Martin Radev0f7714e2017-08-07 15:13:42 +0300439 GLFramebuffer fbo;
440 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
441
442 GLTexture tex;
443 glBindTexture(GL_TEXTURE_2D, tex);
444 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
445
Martin Radev9bc9a322017-07-21 14:28:17 +0300446 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300447 const GLint kViewportOffsets[2] = {0};
448 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
449 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300450 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
451}
452
Martin Radev5dae57b2017-07-14 16:15:55 +0300453// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
454TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
455{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300456 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5dae57b2017-07-14 16:15:55 +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, tex);
463 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
464
465 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
466 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
467 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300468 ASSERT_GL_NO_ERROR();
469
470 GLint numViews = -1;
471 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
472 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
473 &numViews);
474 ASSERT_GL_NO_ERROR();
475 EXPECT_EQ(2, numViews);
476
477 GLint baseViewIndex = -1;
478 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
479 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
480 &baseViewIndex);
481 ASSERT_GL_NO_ERROR();
482 EXPECT_EQ(0, baseViewIndex);
483
484 GLint multiviewLayout = GL_NONE;
485 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
486 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
487 &multiviewLayout);
488 ASSERT_GL_NO_ERROR();
489 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
490
491 GLint internalViewportOffsets[4] = {-1};
492 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
493 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
494 &internalViewportOffsets[0]);
495 ASSERT_GL_NO_ERROR();
496 for (size_t i = 0u; i < 4u; ++i)
497 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300498 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300499 }
500}
501
Martin Radev9bc9a322017-07-21 14:28:17 +0300502// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
503// attachments.
504TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
505{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300506 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev9bc9a322017-07-21 14:28:17 +0300507
Martin Radev0f7714e2017-08-07 15:13:42 +0300508 GLFramebuffer fbo;
509 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300510
Martin Radev0f7714e2017-08-07 15:13:42 +0300511 GLTexture tex;
512 glBindTexture(GL_TEXTURE_2D, tex);
513 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300514
Martin Radev0f7714e2017-08-07 15:13:42 +0300515 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
516 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300517
518 // 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 +0300519 // attachment will be modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300520 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
521 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300522 ASSERT_GL_NO_ERROR();
523
524 // Color attachment 1.
525 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300526 GLTexture otherTex;
527 glBindTexture(GL_TEXTURE_2D, otherTex);
528 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
529
Martin Radev9bc9a322017-07-21 14:28:17 +0300530 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300531 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
532 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300533 ASSERT_GL_NO_ERROR();
534 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
535 glCheckFramebufferStatus(GL_FRAMEBUFFER));
536
537 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300538 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
539 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300540 ASSERT_GL_NO_ERROR();
541 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
542 glCheckFramebufferStatus(GL_FRAMEBUFFER));
543
544 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300545 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300546 ASSERT_GL_NO_ERROR();
547 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
548 glCheckFramebufferStatus(GL_FRAMEBUFFER));
549
550 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
551 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300552 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
553 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300554 ASSERT_GL_NO_ERROR();
555 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
556
557 // Reset attachment 1
558 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300559 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300560 }
561
562 // Depth attachment.
563 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300564 GLTexture depthTex;
565 glBindTexture(GL_TEXTURE_2D, depthTex);
566 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
567 nullptr);
568
Martin Radev9bc9a322017-07-21 14:28:17 +0300569 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300570 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
571 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300572 ASSERT_GL_NO_ERROR();
573 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
574 glCheckFramebufferStatus(GL_FRAMEBUFFER));
575
576 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300577 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
578 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300579 ASSERT_GL_NO_ERROR();
580 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
581 glCheckFramebufferStatus(GL_FRAMEBUFFER));
582
583 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300584 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300585 ASSERT_GL_NO_ERROR();
586 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
587 glCheckFramebufferStatus(GL_FRAMEBUFFER));
588
589 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
590 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300591 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
592 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300593 ASSERT_GL_NO_ERROR();
594 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
595 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300596}
597
Martin Radev04e2c3b2017-07-27 16:54:35 +0300598// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300599// attachments with a side-by-side layout.
Martin Radev04e2c3b2017-07-27 16:54:35 +0300600TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
601{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300602 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev04e2c3b2017-07-27 16:54:35 +0300603
Martin Radev0f7714e2017-08-07 15:13:42 +0300604 GLFramebuffer fbo;
605 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300606
Martin Radev0f7714e2017-08-07 15:13:42 +0300607 GLTexture tex;
608 glBindTexture(GL_TEXTURE_2D, tex);
609 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
610
611 const GLint kViewportOffsets[2] = {0};
612 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
613 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300614 ASSERT_GL_NO_ERROR();
615
616 // Test glCopyTexImage2D and glCopyTexSubImage2D.
617 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300618 GLTexture tex2;
619 glBindTexture(GL_TEXTURE_2D, tex2);
620 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300621
622 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
623 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
624
625 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
626 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300627 }
628
629 // Test glCopyTexSubImage3D.
630 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300631 GLTexture tex2;
632 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300633 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
634
635 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
636 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300637 }
638}
639
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300640// Test that the active read framebuffer can be read with glCopyTex* if it only has one layered
641// view.
642TEST_P(FramebufferMultiviewTest, CopyTex)
643{
644 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
645
646 GLFramebuffer fbo;
647 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
648
649 GLTexture tex;
650 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
651 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
652
653 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
654 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
655 ASSERT_GL_NO_ERROR();
656
657 // Test glCopyTexImage2D and glCopyTexSubImage2D.
658 {
659 GLTexture tex2;
660 glBindTexture(GL_TEXTURE_2D, tex2);
661 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
662
663 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
664 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
665 glClear(GL_COLOR_BUFFER_BIT);
666
667 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
668 ASSERT_GL_NO_ERROR();
669
670 // Test texture contents.
671 glBindFramebuffer(GL_FRAMEBUFFER, 0);
672 draw2DTexturedQuad(0.0f, 1.0f, true);
673 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
674
675 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
676 glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
677 glClear(GL_COLOR_BUFFER_BIT);
678
679 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
680 ASSERT_GL_NO_ERROR();
681
682 glBindFramebuffer(GL_FRAMEBUFFER, 0);
683 draw2DTexturedQuad(0.0f, 1.0f, true);
684 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
685 }
686
687 // Test glCopyTexSubImage3D.
688 {
689 GLTexture tex2;
690 glBindTexture(GL_TEXTURE_3D, tex2);
691 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
692
693 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
694 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
695 glClear(GL_COLOR_BUFFER_BIT);
696 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
697 ASSERT_GL_NO_ERROR();
698
699 glBindFramebuffer(GL_FRAMEBUFFER, 0);
700 draw3DTexturedQuad(0.0f, 1.0f, true, 0.0f);
701 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
702 }
703}
704
Martin Radeva3ed4572017-07-27 18:29:37 +0300705// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300706// draw framebuffer, or current read framebuffer have multiview attachments with a side-by-side
707// layout.
Martin Radeva3ed4572017-07-27 18:29:37 +0300708TEST_P(FramebufferMultiviewTest, InvalidBlit)
709{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300710 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeva3ed4572017-07-27 18:29:37 +0300711
Martin Radev0f7714e2017-08-07 15:13:42 +0300712 GLFramebuffer fbo;
713 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300714
Martin Radev0f7714e2017-08-07 15:13:42 +0300715 GLTexture tex;
716 glBindTexture(GL_TEXTURE_2D, tex);
717 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
718
719 const GLint kViewportOffsets[2] = {0};
720 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
721 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300722 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
723 ASSERT_GL_NO_ERROR();
724
725 // Blit with the active read framebuffer having multiview attachments.
726 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300727 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300728 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
729 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
730 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
731 }
732
733 // Blit with the active draw framebuffer having multiview attachments.
734 {
735 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300736 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300737 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
738 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
739 }
740}
741
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300742// Test that glBlitFramebuffer succeeds if the current read framebuffer has just one layered view.
743TEST_P(FramebufferMultiviewTest, Blit)
744{
745 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
746
747 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
748 glClear(GL_COLOR_BUFFER_BIT);
749
750 GLFramebuffer fbo;
751 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
752
753 GLTexture tex;
754 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
755 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
756
757 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
758 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
759 ASSERT_GL_NO_ERROR();
760
761 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
762 glClear(GL_COLOR_BUFFER_BIT);
763
764 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
765 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
766 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
767 ASSERT_GL_NO_ERROR();
768
769 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
770 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
771}
772
Martin Radev28031682017-07-28 14:47:56 +0300773// Test that glReadPixels generates an invalid framebuffer operation error if the current read
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300774// framebuffer has a side-by-side multi-view layout.
Martin Radev28031682017-07-28 14:47:56 +0300775TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
776{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300777 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev28031682017-07-28 14:47:56 +0300778
Martin Radev0f7714e2017-08-07 15:13:42 +0300779 GLFramebuffer fbo;
780 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300781
Martin Radev0f7714e2017-08-07 15:13:42 +0300782 GLTexture tex;
783 glBindTexture(GL_TEXTURE_2D, tex);
784 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
785
786 const GLint kViewportOffsets[2] = {0};
787 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
788 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300789 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
790 ASSERT_GL_NO_ERROR();
791
792 GLColor pixelColor;
793 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
794 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
795}
796
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300797// Test that glReadPixels succeeds from a layered multiview framebuffer with just one view.
798TEST_P(FramebufferMultiviewTest, ReadPixels)
799{
800 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
801
802 GLFramebuffer fbo;
803 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
804
805 GLTexture tex;
806 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
807 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
808
809 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
810 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
811 ASSERT_GL_NO_ERROR();
812
813 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
814 glClear(GL_COLOR_BUFFER_BIT);
815
816 GLColor pixelColor;
817 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
818 ASSERT_GL_NO_ERROR();
819 EXPECT_COLOR_NEAR(GLColor::green, pixelColor, 2);
820}
821
Martin Radeveef80e42017-08-11 14:44:57 +0300822// Test that glClear clears only the contents of each view if the scissor test is enabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300823TEST_P(FramebufferMultiviewSideBySideClearTest, ColorBufferClear)
Martin Radevb0761932017-07-25 17:42:25 +0300824{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300825 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevb0761932017-07-25 17:42:25 +0300826
Martin Radev5c00d0d2017-08-07 10:06:59 +0300827 initializeFBOs(1, false, false);
Martin Radevb0761932017-07-25 17:42:25 +0300828
829 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300830 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
831 glClearColor(1, 0, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300832 glClear(GL_COLOR_BUFFER_BIT);
833
834 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300835 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300836 glViewport(0, 0, 1, 2);
837 glScissor(0, 0, 1, 2);
Martin Radeveef80e42017-08-11 14:44:57 +0300838 glEnable(GL_SCISSOR_TEST);
Martin Radevb0761932017-07-25 17:42:25 +0300839
Martin Radev5c00d0d2017-08-07 10:06:59 +0300840 glClearColor(0, 1, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300841 glClear(GL_COLOR_BUFFER_BIT);
842
Martin Radev5c00d0d2017-08-07 10:06:59 +0300843 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300844
Martin Radev5c00d0d2017-08-07 10:06:59 +0300845 checkAlternatingColumnsOfRedAndGreenInFBO();
Martin Radevb0761932017-07-25 17:42:25 +0300846}
847
Martin Radev82ef7742017-08-08 17:44:58 +0300848// Test that glFramebufferTextureMultiviewLayeredANGLE modifies the internal multiview state.
849TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
850{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300851 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300852
853 GLFramebuffer multiviewFBO;
854 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
855
856 GLTexture tex;
857 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
858 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
859 ASSERT_GL_NO_ERROR();
860
861 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
862 ASSERT_GL_NO_ERROR();
863
864 GLint numViews = -1;
865 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
866 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
867 &numViews);
868 ASSERT_GL_NO_ERROR();
869 EXPECT_EQ(2, numViews);
870
871 GLint baseViewIndex = -1;
872 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
873 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
874 &baseViewIndex);
875 ASSERT_GL_NO_ERROR();
876 EXPECT_EQ(1, baseViewIndex);
877
878 GLint multiviewLayout = GL_NONE;
879 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
880 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
881 &multiviewLayout);
882 ASSERT_GL_NO_ERROR();
883 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, multiviewLayout);
884
885 GLint internalViewportOffsets[2] = {-1};
886 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
887 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
888 &internalViewportOffsets[0]);
889 ASSERT_GL_NO_ERROR();
890 EXPECT_EQ(0, internalViewportOffsets[0]);
891 EXPECT_EQ(0, internalViewportOffsets[1]);
892}
893
894// Test framebuffer completeness status of a layered framebuffer with color attachments.
895TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
896{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300897 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300898
899 GLFramebuffer fbo;
900 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
901
902 GLTexture tex;
903 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
904 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
905
906 // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
907 // attachment will be modified to change the framebuffer's status.
908 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
909 ASSERT_GL_NO_ERROR();
910
911 GLTexture otherTexLayered;
912 glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
913 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
914
915 // Test framebuffer completeness when the base view index differs.
916 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
917 0, 1, 2);
918 ASSERT_GL_NO_ERROR();
919 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
920 glCheckFramebufferStatus(GL_FRAMEBUFFER));
921
922 // Test framebuffer completeness when the 1st attachment has a side-by-side layout.
923 const int kViewportOffsets[4] = {0, 0, 0, 0};
924 GLTexture otherTex2D;
925 glBindTexture(GL_TEXTURE_2D, otherTex2D);
926 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
927 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex2D,
928 0, 2, kViewportOffsets);
929 ASSERT_GL_NO_ERROR();
930 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
931 glCheckFramebufferStatus(GL_FRAMEBUFFER));
932
Martin Radev5e424fa2017-08-09 16:25:36 +0300933 // Test framebuffer completeness when the 1st attachment has a non-multiview layout.
Martin Radev82ef7742017-08-08 17:44:58 +0300934 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
935 ASSERT_GL_NO_ERROR();
936 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
937 glCheckFramebufferStatus(GL_FRAMEBUFFER));
938
939 // Test that framebuffer is complete when the number of views, base view index and layouts are
940 // the same.
941 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
942 0, 0, 2);
943 ASSERT_GL_NO_ERROR();
944 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
945}
946
Martin Radeveef80e42017-08-11 14:44:57 +0300947// Test that glClear clears all of the contents if the scissor test is disabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300948TEST_P(FramebufferMultiviewSideBySideClearTest, ClearWithDisabledScissorTest)
Martin Radeveef80e42017-08-11 14:44:57 +0300949{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300950 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeveef80e42017-08-11 14:44:57 +0300951
Martin Radev5c00d0d2017-08-07 10:06:59 +0300952 initializeFBOs(1, false, false);
Martin Radeveef80e42017-08-11 14:44:57 +0300953
954 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300955 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
956 glClearColor(0, 0, 0, 1);
Martin Radeveef80e42017-08-11 14:44:57 +0300957 glClear(GL_COLOR_BUFFER_BIT);
958
959 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300960 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300961 glViewport(0, 0, 1, 2);
962 glScissor(0, 0, 1, 2);
963
964 glClearColor(1, 0, 0, 1);
965 glClear(GL_COLOR_BUFFER_BIT);
966
Martin Radev5c00d0d2017-08-07 10:06:59 +0300967 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300968
969 for (int i = 0; i < 4; ++i)
970 {
971 for (int j = 0; j < 2; ++j)
972 {
973 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
974 }
975 }
976}
977
Martin Radev5c00d0d2017-08-07 10:06:59 +0300978// Test that glClear clears the depth buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300979TEST_P(FramebufferMultiviewSideBySideClearTest, DepthBufferClear)
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.
Jamie Madill35cd7332018-12-02 12:03:33 -0500984 constexpr char kVS[] =
Martin Radev5c00d0d2017-08-07 10:06:59 +0300985 "#version 300 es\n"
986 "in vec3 vPos;\n"
987 "void main(){\n"
988 " gl_Position = vec4(vPos, 1.);\n"
989 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500990 constexpr char kFS[] =
Martin Radev5c00d0d2017-08-07 10:06:59 +0300991 "#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";
Jamie Madill35cd7332018-12-02 12:03:33 -0500998 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300999 glUseProgram(program);
1000 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1001
1002 initializeFBOs(1, false, true);
1003 glEnable(GL_DEPTH_TEST);
1004
1005 // Clear the contents of the texture.
1006 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1007 glClearColor(0, 0, 0, 0);
1008 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1009
1010 // Dirty the depth and color buffers.
1011 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1012 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1013
1014 // Switch to the multi-view framebuffer and clear only the rectangles covered by the views.
1015 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1016 glViewport(0, 0, 1, 2);
1017 glScissor(0, 0, 1, 2);
1018 glEnable(GL_SCISSOR_TEST);
1019 glClear(GL_DEPTH_BUFFER_BIT);
1020
1021 // Draw a fullscreen quad to fill the cleared regions.
1022 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1023 glViewport(0, 0, 4, 2);
1024 glScissor(0, 0, 4, 2);
1025 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1026 drawQuad(program, "vPos", 0.5f, 1.0f, true);
1027
1028 checkAlternatingColumnsOfRedAndGreenInFBO();
1029}
1030
1031// Test that glClear clears the stencil buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001032TEST_P(FramebufferMultiviewSideBySideClearTest, StencilBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001033{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001034 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001035
1036 // Create program to draw a quad.
Jamie Madill35cd7332018-12-02 12:03:33 -05001037 constexpr char kVS[] =
Martin Radev5c00d0d2017-08-07 10:06:59 +03001038 "#version 300 es\n"
1039 "in vec3 vPos;\n"
1040 "void main(){\n"
1041 " gl_Position = vec4(vPos, 1.);\n"
1042 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001043 constexpr char kFS[] =
Martin Radev5c00d0d2017-08-07 10:06:59 +03001044 "#version 300 es\n"
1045 "precision mediump float;\n"
1046 "uniform vec3 uCol;\n"
1047 "out vec4 col;\n"
1048 "void main(){\n"
1049 " col = vec4(uCol,1.);\n"
1050 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001051 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev5c00d0d2017-08-07 10:06:59 +03001052 glUseProgram(program);
1053 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1054
1055 initializeFBOs(1, true, false);
1056 glEnable(GL_STENCIL_TEST);
1057 glDisable(GL_DEPTH_TEST);
1058
1059 // Set clear values and clear the whole framebuffer.
1060 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1061 glClearColor(0, 0, 0, 0);
1062 glClearStencil(0);
1063 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1064
1065 // Update stencil test to always replace the stencil value with 0xFF.
1066 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1067 glStencilFunc(GL_ALWAYS, 0xFF, 0);
1068
1069 // Draw a quad which covers the whole texture.
1070 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1071 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1072
1073 // Switch to multiview framebuffer and clear portions of the texture.
1074 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1075 glViewport(0, 0, 1, 2);
1076 glScissor(0, 0, 1, 2);
1077 glEnable(GL_SCISSOR_TEST);
1078 glClear(GL_STENCIL_BUFFER_BIT);
1079
1080 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1081 // the test.
1082 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1083 glViewport(0, 0, 4, 2);
1084 glScissor(0, 0, 4, 2);
1085 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1086 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1087 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1088
1089 checkAlternatingColumnsOfRedAndGreenInFBO();
1090}
1091
1092// Test that glClearBufferf clears the color buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001093TEST_P(FramebufferMultiviewSideBySideClearTest, ClearBufferF)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001094{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001095 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001096
1097 initializeFBOs(2, false, false);
1098
1099 // Clear the contents of the texture.
1100 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1101 glClearColor(1, 0, 0, 1);
1102 glClear(GL_COLOR_BUFFER_BIT);
1103
1104 // Bind and specify viewport/scissor dimensions for each view.
1105 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1106 glViewport(0, 0, 1, 2);
1107 glScissor(0, 0, 1, 2);
1108 glEnable(GL_SCISSOR_TEST);
1109
1110 float kClearValues[4] = {0.f, 1.f, 0.f, 1.f};
1111 glClearBufferfv(GL_COLOR, 1, kClearValues);
1112
1113 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1114
1115 // Check that glClearBufferfv has not modified the 0th color attachment.
1116 glReadBuffer(GL_COLOR_ATTACHMENT0);
1117 for (int i = 0; i < 4; ++i)
1118 {
1119 for (int j = 0; j < 2; ++j)
1120 {
1121 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
1122 }
1123 }
1124
1125 // Check that glClearBufferfv has correctly modified the 1th color attachment.
1126 glReadBuffer(GL_COLOR_ATTACHMENT1);
1127 checkAlternatingColumnsOfRedAndGreenInFBO();
1128}
1129
Martin Radev5e424fa2017-08-09 16:25:36 +03001130// Test that glClear clears the contents of the color buffer for only the attached layers to a
1131// layered FBO.
1132TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
1133{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001134 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001135
1136 initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
1137
1138 // Bind and specify viewport/scissor dimensions for each view.
1139 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1140
1141 glClearColor(0, 1, 0, 1);
1142 glClear(GL_COLOR_BUFFER_BIT);
1143
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001144 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001145 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1146 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001147 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001148}
1149
1150// Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
1151TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
1152{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001153 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001154
1155 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1156
1157 for (int i = 0; i < 2; ++i)
1158 {
1159 for (int layer = 0; layer < 4; ++layer)
1160 {
1161 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001162 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(layer, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001163 }
1164 }
1165
1166 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1167
1168 float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
1169 glClearBufferfv(GL_COLOR, 0, clearValues0);
1170
1171 float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
1172 glClearBufferfv(GL_COLOR, 1, clearValues1);
1173
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001174 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001175 EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1176 EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001177 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001178
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001179 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001180 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1181 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001182 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001183}
1184
1185// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1186// to a layered FBO.
1187TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
1188{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001189 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001190
1191 // Create program to draw a quad.
Jamie Madill35cd7332018-12-02 12:03:33 -05001192 constexpr char kVS[] =
Martin Radev5e424fa2017-08-09 16:25:36 +03001193 "#version 300 es\n"
1194 "in vec3 vPos;\n"
1195 "void main(){\n"
1196 " gl_Position = vec4(vPos, 1.);\n"
1197 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001198 constexpr char kFS[] =
Martin Radev5e424fa2017-08-09 16:25:36 +03001199 "#version 300 es\n"
1200 "precision mediump float;\n"
1201 "uniform vec3 uCol;\n"
1202 "out vec4 col;\n"
1203 "void main(){\n"
1204 " col = vec4(uCol,1.);\n"
1205 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001206 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev5e424fa2017-08-09 16:25:36 +03001207 glUseProgram(program);
1208 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1209
1210 initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
1211 glEnable(GL_STENCIL_TEST);
1212 glDisable(GL_DEPTH_TEST);
1213
1214 // Set clear values.
1215 glClearColor(1, 0, 0, 1);
1216 glClearStencil(0xFF);
1217
1218 // Clear the color and stencil buffers of each layer.
1219 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1220 {
1221 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1222 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1223 }
1224
1225 // Switch to multiview framebuffer and clear portions of the texture.
1226 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1227 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1228
1229 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1230 // the test.
1231 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1232 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1233 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1234 {
1235 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1236 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1237 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1238 }
1239 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1240 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1241 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1242 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1243}
1244
1245// Test that glClear does not clear the content of a detached texture.
1246TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
1247{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001248 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001249
1250 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1251
1252 // Clear all attachments.
1253 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1254 glClearColor(0, 1, 0, 1);
1255 glClear(GL_COLOR_BUFFER_BIT);
1256
1257 for (int i = 0; i < 2; ++i)
1258 {
1259 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001260 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001261 EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
1262 EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001263 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001264 }
1265
1266 // Detach and clear again.
1267 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1268 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
1269 glClearColor(1, 1, 0, 1);
1270 glClear(GL_COLOR_BUFFER_BIT);
1271
1272 // Check that color attachment 0 is modified.
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001273 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001274 EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1275 EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001276 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001277
1278 // Check that color attachment 1 is unmodified.
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001279 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001280 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1281 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001282 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001283}
1284
1285// Test that glClear clears only the contents within the scissor rectangle of the attached layers.
1286TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
1287{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001288 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001289
1290 initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
1291
1292 // Bind and specify viewport/scissor dimensions for each view.
1293 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1294
1295 glEnable(GL_SCISSOR_TEST);
1296 glScissor(1, 0, 1, 1);
1297 glClearColor(0, 1, 0, 1);
1298 glClear(GL_COLOR_BUFFER_BIT);
1299
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001300 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1301 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001302
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001303 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001304 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
1305
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001306 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001307 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
1308
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001309 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1310 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001311}
1312
Martin Radev18b75ba2017-08-15 15:50:40 +03001313// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1314// to a layered FBO.
1315TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
1316{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001317 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev18b75ba2017-08-15 15:50:40 +03001318
1319 // Create program to draw a quad.
Jamie Madill35cd7332018-12-02 12:03:33 -05001320 constexpr char kVS[] =
Martin Radev18b75ba2017-08-15 15:50:40 +03001321 "#version 300 es\n"
1322 "in vec3 vPos;\n"
1323 "void main(){\n"
1324 " gl_Position = vec4(vPos, 1.);\n"
1325 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001326 constexpr char kFS[] =
Martin Radev18b75ba2017-08-15 15:50:40 +03001327 "#version 300 es\n"
1328 "precision mediump float;\n"
1329 "uniform vec3 uCol;\n"
1330 "out vec4 col;\n"
1331 "void main(){\n"
1332 " col = vec4(uCol,1.);\n"
1333 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001334 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev18b75ba2017-08-15 15:50:40 +03001335 glUseProgram(program);
1336 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1337
1338 initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
1339 glEnable(GL_STENCIL_TEST);
1340 glDisable(GL_DEPTH_TEST);
1341
1342 // Set clear values.
1343 glClearColor(1, 0, 0, 1);
1344 glClearStencil(0xFF);
1345
1346 // Clear the color and stencil buffers of each layer.
1347 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1348 {
1349 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1350 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1351 }
1352
1353 // Switch to multiview framebuffer and clear portions of the texture.
1354 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1355 glEnable(GL_SCISSOR_TEST);
1356 glScissor(0, 0, 1, 1);
1357 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1358 glDisable(GL_SCISSOR_TEST);
1359
1360 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1361 // the test.
1362 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1363 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001364 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
Martin Radev18b75ba2017-08-15 15:50:40 +03001365 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1366 {
1367 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
Martin Radev18b75ba2017-08-15 15:50:40 +03001368 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1369 }
1370 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1371 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
1372 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1373 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
1374 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1375 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
1376 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1377 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
1378}
1379
Martin Radev14b21262017-08-25 13:54:37 +03001380// Test that detaching an attachment does not generate an error whenever the multi-view related
1381// arguments are invalid.
1382TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
1383{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001384 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev14b21262017-08-25 13:54:37 +03001385
1386 GLFramebuffer fbo;
1387 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1388
1389 // Invalid base view index.
1390 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
1391 EXPECT_GL_NO_ERROR();
1392
1393 // Invalid number of views.
1394 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
1395 EXPECT_GL_NO_ERROR();
1396
1397 // Invalid number of views.
1398 const GLint kValidViewportOffsets[2] = {0, 0};
1399 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0,
1400 kValidViewportOffsets);
1401 EXPECT_GL_NO_ERROR();
1402
1403 // Invalid viewport offsets.
1404 const GLint kInvalidViewportOffsets[2] = {-1, -1};
1405 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 1,
1406 kInvalidViewportOffsets);
1407 EXPECT_GL_NO_ERROR();
1408}
1409
Martin Radev61e710b2017-09-05 11:59:52 +03001410// Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
1411// array are attached. The test is added because a special fast code path is used for this case.
1412TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
1413{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001414 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev61e710b2017-09-05 11:59:52 +03001415
1416 initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
1417
1418 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1419 glClearColor(0, 1, 0, 1);
1420 glClear(GL_COLOR_BUFFER_BIT);
1421
1422 EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1423 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1424}
1425
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001426// Test that attaching a multisampled texture array is not possible if all the required extensions
1427// are not enabled.
1428TEST_P(FramebufferMultiviewTest, NegativeMultisampledFramebufferTest)
1429{
1430 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1431
1432 ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"));
1433
1434 // We don't enable ANGLE_multiview_multisample
1435
1436 GLTexture multisampleTexture;
1437 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, multisampleTexture);
1438
1439 GLFramebuffer fbo;
1440 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1441 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1442 multisampleTexture, 0, 0, 2);
1443 // From the extension spec: "An INVALID_OPERATION error is generated if texture is not zero, and
1444 // does not name an existing texture object of type TEXTURE_2D_ARRAY."
1445 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1446}
1447
Olli Etuahof26b27e2018-08-17 11:01:19 +03001448ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));
1449ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest,
1450 VertexShaderOpenGL(3, 0),
1451 GeomShaderD3D11(3, 0));
1452ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest,
1453 VertexShaderOpenGL(3, 0),
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001454 GeomShaderD3D11(3, 0));