blob: 6108ad13da1461258386a7fe06194d066da694fd [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 {
Yuly Novikov9f088622018-12-29 20:46:15 +000076 ASSERT(mColorTex.empty() && mDepthStencilTex == 0u && mDepthTex == 0u);
Olli Etuahoa7b35c32018-08-21 16:32:24 +030077 const std::vector<GLenum> &drawBuffers = GetDrawBufferRange(numColorBuffers);
Martin Radev5c00d0d2017-08-07 10:06:59 +030078
79 // Generate textures.
80 mColorTex.resize(numColorBuffers);
Shahbaz Youssefic4097442018-08-22 12:14:52 -040081 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
82 glGenTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030083 if (stencil)
84 {
85 glGenTextures(1, &mDepthStencilTex);
86 }
87 else if (depth)
88 {
89 glGenTextures(1, &mDepthTex);
90 }
91
Olli Etuaho2c8f0842018-09-12 14:44:55 +030092 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0, 2, 2, 2,
Olli Etuahoa7b35c32018-08-21 16:32:24 +030093 mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5c00d0d2017-08-07 10:06:59 +030094
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030095 glGenFramebuffers(1, &mMultiviewFBO);
96 glGenFramebuffers(1, &mNonMultiviewFBO);
97
Martin Radev5c00d0d2017-08-07 10:06:59 +030098 // Generate multiview fbo and attach textures.
99 const GLint kViewportOffsets[4] = {1, 0, 3, 0};
100 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
101 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
102 for (size_t i = 0u; i < numColorBuffers; ++i)
103 {
104 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
105 static_cast<GLenum>(kBase + i),
106 mColorTex[i], 0, 2, &kViewportOffsets[0]);
107 }
108
109 if (stencil)
110 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300111 glFramebufferTextureMultiviewSideBySideANGLE(
112 GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, mDepthStencilTex, 0, 2,
113 &kViewportOffsets[0]);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300114 }
115 else if (depth)
116 {
117 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
118 mDepthTex, 0, 2, &kViewportOffsets[0]);
119 }
120 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
121
Martin Radev5e424fa2017-08-09 16:25:36 +0300122 // Generate non-multiview fbo and attach textures.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300123 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
124 for (size_t i = 0u; i < numColorBuffers; ++i)
125 {
126 glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(kBase + i), GL_TEXTURE_2D,
127 mColorTex[i], 0);
128 }
129 if (stencil)
130 {
131 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300132 mDepthStencilTex, 0);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300133 }
134 else if (depth)
135 {
136 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTex,
137 0);
138 }
139 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
140
141 ASSERT_GL_NO_ERROR();
142 }
143
144 void checkAlternatingColumnsOfRedAndGreenInFBO()
145 {
146 // column 0
147 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
148 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::red);
149
150 // column 1
151 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
152 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
153
154 // column 2
155 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::red);
156 EXPECT_PIXEL_COLOR_EQ(2, 1, GLColor::red);
157
158 // column 3
159 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
160 EXPECT_PIXEL_COLOR_EQ(3, 1, GLColor::green);
161 }
162
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300163 GLuint mMultiviewFBO;
164 GLuint mNonMultiviewFBO;
165
166 private:
167 std::vector<GLuint> mColorTex;
168 GLuint mDepthTex;
169 GLuint mDepthStencilTex;
Martin Radev5c00d0d2017-08-07 10:06:59 +0300170};
171
Martin Radev5e424fa2017-08-09 16:25:36 +0300172class FramebufferMultiviewLayeredClearTest : public FramebufferMultiviewTest
173{
174 protected:
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300175 FramebufferMultiviewLayeredClearTest() : mMultiviewFBO(0), mDepthTex(0), mDepthStencilTex(0) {}
176
177 void TearDown() override
178 {
179 if (mMultiviewFBO != 0)
180 {
181 glDeleteFramebuffers(1, &mMultiviewFBO);
182 mMultiviewFBO = 0u;
183 }
184 if (!mNonMultiviewFBO.empty())
185 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400186 GLsizei textureCount = static_cast<GLsizei>(mNonMultiviewFBO.size());
187 glDeleteTextures(textureCount, mNonMultiviewFBO.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300188 mNonMultiviewFBO.clear();
189 }
190 if (!mColorTex.empty())
191 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400192 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
193 glDeleteTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300194 mColorTex.clear();
195 }
196 if (mDepthStencilTex != 0u)
197 {
198 glDeleteTextures(1, &mDepthStencilTex);
199 mDepthStencilTex = 0u;
200 }
201 if (mDepthTex != 0u)
202 {
203 glDeleteTextures(1, &mDepthTex);
204 mDepthTex = 0u;
205 }
206 MultiviewTest::TearDown();
207 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300208
209 void initializeFBOs(int width,
210 int height,
211 int numLayers,
212 int baseViewIndex,
213 int numViews,
214 int numColorAttachments,
215 bool stencil,
216 bool depth)
217 {
Yuly Novikov9f088622018-12-29 20:46:15 +0000218 ASSERT(mColorTex.empty() && mDepthStencilTex == 0u && mDepthTex == 0u);
219 ASSERT(baseViewIndex + numViews <= numLayers);
Martin Radev5e424fa2017-08-09 16:25:36 +0300220
221 // Generate textures.
222 mColorTex.resize(numColorAttachments);
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400223 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
224 glGenTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300225 if (stencil)
226 {
227 glGenTextures(1, &mDepthStencilTex);
228 }
229 else if (depth)
230 {
231 glGenTextures(1, &mDepthTex);
232 }
233
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300234 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0, width, height,
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300235 numLayers, mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5e424fa2017-08-09 16:25:36 +0300236
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300237 glGenFramebuffers(1, &mMultiviewFBO);
238
Martin Radev5e424fa2017-08-09 16:25:36 +0300239 // Generate multiview FBO and attach textures.
240 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300241 AttachMultiviewTextures(GL_FRAMEBUFFER, GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, width,
242 numViews, baseViewIndex, mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5e424fa2017-08-09 16:25:36 +0300243
244 const auto &drawBuffers = GetDrawBufferRange(numColorAttachments);
245 glDrawBuffers(numColorAttachments, drawBuffers.data());
246
247 // Generate non-multiview FBOs and attach textures.
248 mNonMultiviewFBO.resize(numLayers);
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400249 GLsizei framebufferCount = static_cast<GLsizei>(mNonMultiviewFBO.size());
250 glGenFramebuffers(framebufferCount, mNonMultiviewFBO.data());
Martin Radev5e424fa2017-08-09 16:25:36 +0300251 for (int i = 0; i < numLayers; ++i)
252 {
253 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
254 for (int j = 0; j < numColorAttachments; ++j)
255 {
256 glFramebufferTextureLayer(GL_FRAMEBUFFER,
257 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + j),
258 mColorTex[j], 0, i);
259 }
260 if (stencil)
261 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300262 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
263 mDepthStencilTex, 0, i);
Martin Radev5e424fa2017-08-09 16:25:36 +0300264 }
265 else if (depth)
266 {
267 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTex, 0, i);
268 }
269 glDrawBuffers(numColorAttachments, drawBuffers.data());
Martin Radev5e424fa2017-08-09 16:25:36 +0300270 }
271
272 ASSERT_GL_NO_ERROR();
273 }
274
275 GLColor getLayerColor(size_t layer, GLenum attachment, GLint x, GLint y)
276 {
Yuly Novikov9f088622018-12-29 20:46:15 +0000277 ASSERT(layer < mNonMultiviewFBO.size());
Martin Radev5e424fa2017-08-09 16:25:36 +0300278 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[layer]);
279 glReadBuffer(attachment);
280 return angle::ReadColor(x, y);
281 }
282
283 GLColor getLayerColor(size_t layer, GLenum attachment)
284 {
285 return getLayerColor(layer, attachment, 0, 0);
286 }
287
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300288 GLuint mMultiviewFBO;
289 std::vector<GLuint> mNonMultiviewFBO;
290
291 private:
292 std::vector<GLuint> mColorTex;
293 GLuint mDepthTex;
294 GLuint mDepthStencilTex;
Martin Radev5e424fa2017-08-09 16:25:36 +0300295};
296
297// Test that the framebuffer tokens introduced by ANGLE_multiview can be used to query the
298// framebuffer state and that their corresponding default values are correctly set.
Martin Radeve5285d22017-07-14 16:23:53 +0300299TEST_P(FramebufferMultiviewTest, DefaultState)
300{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300301 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeve5285d22017-07-14 16:23:53 +0300302
Martin Radev0f7714e2017-08-07 15:13:42 +0300303 GLFramebuffer fbo;
304 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
305
306 GLTexture tex;
307 glBindTexture(GL_TEXTURE_2D, tex);
308 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
309 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300310
Martin Radeve5285d22017-07-14 16:23:53 +0300311 GLint numViews = -1;
312 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
313 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
314 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +0300315 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300316 EXPECT_EQ(1, numViews);
317
318 GLint baseViewIndex = -1;
319 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
320 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
321 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +0300322 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300323 EXPECT_EQ(0, baseViewIndex);
324
325 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
326 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
327 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
328 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +0300329 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300330 EXPECT_EQ(GL_NONE, multiviewLayout);
331
332 GLint viewportOffsets[2] = {-1, -1};
333 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
334 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
335 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +0300336 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300337 EXPECT_EQ(0, viewportOffsets[0]);
338 EXPECT_EQ(0, viewportOffsets[1]);
339}
340
341// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
342// the ANGLE_multiview tokens results in an INVALID_ENUM error.
343TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
344{
Martin Radev0f7714e2017-08-07 15:13:42 +0300345 GLFramebuffer fbo;
346 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
347
348 GLTexture tex;
349 glBindTexture(GL_TEXTURE_2D, tex);
350 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
351 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300352
Martin Radeve5285d22017-07-14 16:23:53 +0300353 GLint numViews = -1;
354 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
355 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
356 &numViews);
357 EXPECT_GL_ERROR(GL_INVALID_ENUM);
358
359 GLint baseViewIndex = -1;
360 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
361 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
362 &baseViewIndex);
363 EXPECT_GL_ERROR(GL_INVALID_ENUM);
364
365 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
366 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
367 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
368 &multiviewLayout);
369 EXPECT_GL_ERROR(GL_INVALID_ENUM);
370
371 GLint viewportOffsets[2] = {-1, -1};
372 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
373 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
374 &viewportOffsets[0]);
375 EXPECT_GL_ERROR(GL_INVALID_ENUM);
376}
377
Martin Radev137032d2017-07-13 10:11:12 +0300378// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
379// is called with invalid arguments.
380TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
381{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300382 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300383
Martin Radev0f7714e2017-08-07 15:13:42 +0300384 GLFramebuffer fbo;
385 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
386
387 GLTexture tex;
388 glBindTexture(GL_TEXTURE_2D, tex);
389 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
390
Martin Radev137032d2017-07-13 10:11:12 +0300391 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300392 GLint viewportOffsets[2] = {-1};
393 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
394 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300395 EXPECT_GL_ERROR(GL_INVALID_VALUE);
396
397 // Negative number of views.
398 viewportOffsets[0] = 0;
399 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300400 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1,
401 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300402 EXPECT_GL_ERROR(GL_INVALID_VALUE);
403}
404
405// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
406// called with invalid arguments.
407TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
408{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300409 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300410
Martin Radev0f7714e2017-08-07 15:13:42 +0300411 GLFramebuffer fbo;
412 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
413
414 GLTexture tex;
415 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
416 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
417 ASSERT_GL_NO_ERROR();
418
Martin Radev137032d2017-07-13 10:11:12 +0300419 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300420 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300421 EXPECT_GL_ERROR(GL_INVALID_VALUE);
422
423 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
424 GLint maxTextureLayers = 0;
425 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300426 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
427 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300428 EXPECT_GL_ERROR(GL_INVALID_VALUE);
429}
430
431// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
432// available.
433TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
434{
Martin Radev0f7714e2017-08-07 15:13:42 +0300435 GLFramebuffer fbo;
436 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
437
438 GLTexture tex;
439 glBindTexture(GL_TEXTURE_2D, tex);
440 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
441
Martin Radev9bc9a322017-07-21 14:28:17 +0300442 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300443 const GLint kViewportOffsets[2] = {0};
444 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
445 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300446 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
447}
448
Martin Radev5dae57b2017-07-14 16:15:55 +0300449// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
450TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
451{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300452 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5dae57b2017-07-14 16:15:55 +0300453
Martin Radev0f7714e2017-08-07 15:13:42 +0300454 GLFramebuffer fbo;
455 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
456
457 GLTexture tex;
458 glBindTexture(GL_TEXTURE_2D, tex);
459 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
460
461 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
462 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
463 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300464 ASSERT_GL_NO_ERROR();
465
466 GLint numViews = -1;
467 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
468 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
469 &numViews);
470 ASSERT_GL_NO_ERROR();
471 EXPECT_EQ(2, numViews);
472
473 GLint baseViewIndex = -1;
474 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
475 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
476 &baseViewIndex);
477 ASSERT_GL_NO_ERROR();
478 EXPECT_EQ(0, baseViewIndex);
479
480 GLint multiviewLayout = GL_NONE;
481 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
482 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
483 &multiviewLayout);
484 ASSERT_GL_NO_ERROR();
485 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
486
487 GLint internalViewportOffsets[4] = {-1};
488 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
489 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
490 &internalViewportOffsets[0]);
491 ASSERT_GL_NO_ERROR();
492 for (size_t i = 0u; i < 4u; ++i)
493 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300494 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300495 }
496}
497
Martin Radev9bc9a322017-07-21 14:28:17 +0300498// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
499// attachments.
500TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
501{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300502 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev9bc9a322017-07-21 14:28:17 +0300503
Martin Radev0f7714e2017-08-07 15:13:42 +0300504 GLFramebuffer fbo;
505 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300506
Martin Radev0f7714e2017-08-07 15:13:42 +0300507 GLTexture tex;
508 glBindTexture(GL_TEXTURE_2D, tex);
509 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300510
Martin Radev0f7714e2017-08-07 15:13:42 +0300511 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
512 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300513
514 // 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 +0300515 // attachment will be modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300516 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
517 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300518 ASSERT_GL_NO_ERROR();
519
520 // Color attachment 1.
521 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300522 GLTexture otherTex;
523 glBindTexture(GL_TEXTURE_2D, otherTex);
524 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
525
Martin Radev9bc9a322017-07-21 14:28:17 +0300526 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300527 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
528 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300529 ASSERT_GL_NO_ERROR();
530 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
531 glCheckFramebufferStatus(GL_FRAMEBUFFER));
532
533 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300534 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
535 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300536 ASSERT_GL_NO_ERROR();
537 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
538 glCheckFramebufferStatus(GL_FRAMEBUFFER));
539
540 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300541 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300542 ASSERT_GL_NO_ERROR();
543 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
544 glCheckFramebufferStatus(GL_FRAMEBUFFER));
545
546 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
547 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300548 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
549 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300550 ASSERT_GL_NO_ERROR();
551 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
552
553 // Reset attachment 1
554 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300555 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300556 }
557
558 // Depth attachment.
559 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300560 GLTexture depthTex;
561 glBindTexture(GL_TEXTURE_2D, depthTex);
562 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
563 nullptr);
564
Martin Radev9bc9a322017-07-21 14:28:17 +0300565 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300566 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
567 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300568 ASSERT_GL_NO_ERROR();
569 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
570 glCheckFramebufferStatus(GL_FRAMEBUFFER));
571
572 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300573 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
574 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300575 ASSERT_GL_NO_ERROR();
576 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
577 glCheckFramebufferStatus(GL_FRAMEBUFFER));
578
579 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300580 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300581 ASSERT_GL_NO_ERROR();
582 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
583 glCheckFramebufferStatus(GL_FRAMEBUFFER));
584
585 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
586 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300587 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
588 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300589 ASSERT_GL_NO_ERROR();
590 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
591 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300592}
593
Martin Radev04e2c3b2017-07-27 16:54:35 +0300594// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300595// attachments with a side-by-side layout.
Martin Radev04e2c3b2017-07-27 16:54:35 +0300596TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
597{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300598 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev04e2c3b2017-07-27 16:54:35 +0300599
Martin Radev0f7714e2017-08-07 15:13:42 +0300600 GLFramebuffer fbo;
601 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300602
Martin Radev0f7714e2017-08-07 15:13:42 +0300603 GLTexture tex;
604 glBindTexture(GL_TEXTURE_2D, tex);
605 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
606
607 const GLint kViewportOffsets[2] = {0};
608 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
609 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300610 ASSERT_GL_NO_ERROR();
611
612 // Test glCopyTexImage2D and glCopyTexSubImage2D.
613 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300614 GLTexture tex2;
615 glBindTexture(GL_TEXTURE_2D, tex2);
616 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300617
618 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
619 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
620
621 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
622 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300623 }
624
625 // Test glCopyTexSubImage3D.
626 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300627 GLTexture tex2;
628 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300629 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
630
631 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
632 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300633 }
634}
635
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300636// Test that the active read framebuffer can be read with glCopyTex* if it only has one layered
637// view.
638TEST_P(FramebufferMultiviewTest, CopyTex)
639{
640 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
641
642 GLFramebuffer fbo;
643 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
644
645 GLTexture tex;
646 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
647 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
648
649 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
650 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
651 ASSERT_GL_NO_ERROR();
652
653 // Test glCopyTexImage2D and glCopyTexSubImage2D.
654 {
655 GLTexture tex2;
656 glBindTexture(GL_TEXTURE_2D, tex2);
657 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
658
659 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
660 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
661 glClear(GL_COLOR_BUFFER_BIT);
662
663 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
664 ASSERT_GL_NO_ERROR();
665
666 // Test texture contents.
667 glBindFramebuffer(GL_FRAMEBUFFER, 0);
668 draw2DTexturedQuad(0.0f, 1.0f, true);
669 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
670
671 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
672 glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
673 glClear(GL_COLOR_BUFFER_BIT);
674
675 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
676 ASSERT_GL_NO_ERROR();
677
678 glBindFramebuffer(GL_FRAMEBUFFER, 0);
679 draw2DTexturedQuad(0.0f, 1.0f, true);
680 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
681 }
682
683 // Test glCopyTexSubImage3D.
684 {
685 GLTexture tex2;
686 glBindTexture(GL_TEXTURE_3D, tex2);
687 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
688
689 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
690 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
691 glClear(GL_COLOR_BUFFER_BIT);
692 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
693 ASSERT_GL_NO_ERROR();
694
695 glBindFramebuffer(GL_FRAMEBUFFER, 0);
696 draw3DTexturedQuad(0.0f, 1.0f, true, 0.0f);
697 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
698 }
699}
700
Martin Radeva3ed4572017-07-27 18:29:37 +0300701// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300702// draw framebuffer, or current read framebuffer have multiview attachments with a side-by-side
703// layout.
Martin Radeva3ed4572017-07-27 18:29:37 +0300704TEST_P(FramebufferMultiviewTest, InvalidBlit)
705{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300706 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeva3ed4572017-07-27 18:29:37 +0300707
Martin Radev0f7714e2017-08-07 15:13:42 +0300708 GLFramebuffer fbo;
709 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300710
Martin Radev0f7714e2017-08-07 15:13:42 +0300711 GLTexture tex;
712 glBindTexture(GL_TEXTURE_2D, tex);
713 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
714
715 const GLint kViewportOffsets[2] = {0};
716 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
717 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300718 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
719 ASSERT_GL_NO_ERROR();
720
721 // Blit with the active read framebuffer having multiview attachments.
722 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300723 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300724 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
725 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
726 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
727 }
728
729 // Blit with the active draw framebuffer having multiview attachments.
730 {
731 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300732 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300733 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
734 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
735 }
736}
737
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300738// Test that glBlitFramebuffer succeeds if the current read framebuffer has just one layered view.
739TEST_P(FramebufferMultiviewTest, Blit)
740{
741 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
742
743 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
744 glClear(GL_COLOR_BUFFER_BIT);
745
746 GLFramebuffer fbo;
747 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
748
749 GLTexture tex;
750 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
751 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
752
753 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
754 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
755 ASSERT_GL_NO_ERROR();
756
757 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
758 glClear(GL_COLOR_BUFFER_BIT);
759
760 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
761 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
762 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
763 ASSERT_GL_NO_ERROR();
764
765 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
767}
768
Martin Radev28031682017-07-28 14:47:56 +0300769// Test that glReadPixels generates an invalid framebuffer operation error if the current read
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300770// framebuffer has a side-by-side multi-view layout.
Martin Radev28031682017-07-28 14:47:56 +0300771TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
772{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300773 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev28031682017-07-28 14:47:56 +0300774
Martin Radev0f7714e2017-08-07 15:13:42 +0300775 GLFramebuffer fbo;
776 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300777
Martin Radev0f7714e2017-08-07 15:13:42 +0300778 GLTexture tex;
779 glBindTexture(GL_TEXTURE_2D, tex);
780 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
781
782 const GLint kViewportOffsets[2] = {0};
783 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
784 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300785 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
786 ASSERT_GL_NO_ERROR();
787
788 GLColor pixelColor;
789 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
790 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
791}
792
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300793// Test that glReadPixels succeeds from a layered multiview framebuffer with just one view.
794TEST_P(FramebufferMultiviewTest, ReadPixels)
795{
796 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
797
798 GLFramebuffer fbo;
799 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
800
801 GLTexture tex;
802 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
803 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
804
805 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
806 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
807 ASSERT_GL_NO_ERROR();
808
809 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
810 glClear(GL_COLOR_BUFFER_BIT);
811
812 GLColor pixelColor;
813 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
814 ASSERT_GL_NO_ERROR();
815 EXPECT_COLOR_NEAR(GLColor::green, pixelColor, 2);
816}
817
Martin Radeveef80e42017-08-11 14:44:57 +0300818// Test that glClear clears only the contents of each view if the scissor test is enabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300819TEST_P(FramebufferMultiviewSideBySideClearTest, ColorBufferClear)
Martin Radevb0761932017-07-25 17:42:25 +0300820{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300821 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevb0761932017-07-25 17:42:25 +0300822
Martin Radev5c00d0d2017-08-07 10:06:59 +0300823 initializeFBOs(1, false, false);
Martin Radevb0761932017-07-25 17:42:25 +0300824
825 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300826 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
827 glClearColor(1, 0, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300828 glClear(GL_COLOR_BUFFER_BIT);
829
830 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300831 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300832 glViewport(0, 0, 1, 2);
833 glScissor(0, 0, 1, 2);
Martin Radeveef80e42017-08-11 14:44:57 +0300834 glEnable(GL_SCISSOR_TEST);
Martin Radevb0761932017-07-25 17:42:25 +0300835
Martin Radev5c00d0d2017-08-07 10:06:59 +0300836 glClearColor(0, 1, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300837 glClear(GL_COLOR_BUFFER_BIT);
838
Martin Radev5c00d0d2017-08-07 10:06:59 +0300839 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300840
Martin Radev5c00d0d2017-08-07 10:06:59 +0300841 checkAlternatingColumnsOfRedAndGreenInFBO();
Martin Radevb0761932017-07-25 17:42:25 +0300842}
843
Martin Radev82ef7742017-08-08 17:44:58 +0300844// Test that glFramebufferTextureMultiviewLayeredANGLE modifies the internal multiview state.
845TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
846{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300847 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300848
849 GLFramebuffer multiviewFBO;
850 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
851
852 GLTexture tex;
853 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
854 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
855 ASSERT_GL_NO_ERROR();
856
857 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
858 ASSERT_GL_NO_ERROR();
859
860 GLint numViews = -1;
861 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
862 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
863 &numViews);
864 ASSERT_GL_NO_ERROR();
865 EXPECT_EQ(2, numViews);
866
867 GLint baseViewIndex = -1;
868 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
869 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
870 &baseViewIndex);
871 ASSERT_GL_NO_ERROR();
872 EXPECT_EQ(1, baseViewIndex);
873
874 GLint multiviewLayout = GL_NONE;
875 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
876 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
877 &multiviewLayout);
878 ASSERT_GL_NO_ERROR();
879 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, multiviewLayout);
880
881 GLint internalViewportOffsets[2] = {-1};
882 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
883 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
884 &internalViewportOffsets[0]);
885 ASSERT_GL_NO_ERROR();
886 EXPECT_EQ(0, internalViewportOffsets[0]);
887 EXPECT_EQ(0, internalViewportOffsets[1]);
888}
889
890// Test framebuffer completeness status of a layered framebuffer with color attachments.
891TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
892{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300893 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300894
895 GLFramebuffer fbo;
896 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
897
898 GLTexture tex;
899 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
900 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
901
902 // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
903 // attachment will be modified to change the framebuffer's status.
904 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
905 ASSERT_GL_NO_ERROR();
906
907 GLTexture otherTexLayered;
908 glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
909 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
910
911 // Test framebuffer completeness when the base view index differs.
912 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
913 0, 1, 2);
914 ASSERT_GL_NO_ERROR();
915 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
916 glCheckFramebufferStatus(GL_FRAMEBUFFER));
917
918 // Test framebuffer completeness when the 1st attachment has a side-by-side layout.
919 const int kViewportOffsets[4] = {0, 0, 0, 0};
920 GLTexture otherTex2D;
921 glBindTexture(GL_TEXTURE_2D, otherTex2D);
922 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
923 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex2D,
924 0, 2, kViewportOffsets);
925 ASSERT_GL_NO_ERROR();
926 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
927 glCheckFramebufferStatus(GL_FRAMEBUFFER));
928
Martin Radev5e424fa2017-08-09 16:25:36 +0300929 // Test framebuffer completeness when the 1st attachment has a non-multiview layout.
Martin Radev82ef7742017-08-08 17:44:58 +0300930 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
931 ASSERT_GL_NO_ERROR();
932 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
933 glCheckFramebufferStatus(GL_FRAMEBUFFER));
934
935 // Test that framebuffer is complete when the number of views, base view index and layouts are
936 // the same.
937 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
938 0, 0, 2);
939 ASSERT_GL_NO_ERROR();
940 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
941}
942
Martin Radeveef80e42017-08-11 14:44:57 +0300943// Test that glClear clears all of the contents if the scissor test is disabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300944TEST_P(FramebufferMultiviewSideBySideClearTest, ClearWithDisabledScissorTest)
Martin Radeveef80e42017-08-11 14:44:57 +0300945{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300946 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeveef80e42017-08-11 14:44:57 +0300947
Martin Radev5c00d0d2017-08-07 10:06:59 +0300948 initializeFBOs(1, false, false);
Martin Radeveef80e42017-08-11 14:44:57 +0300949
950 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300951 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
952 glClearColor(0, 0, 0, 1);
Martin Radeveef80e42017-08-11 14:44:57 +0300953 glClear(GL_COLOR_BUFFER_BIT);
954
955 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300956 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300957 glViewport(0, 0, 1, 2);
958 glScissor(0, 0, 1, 2);
959
960 glClearColor(1, 0, 0, 1);
961 glClear(GL_COLOR_BUFFER_BIT);
962
Martin Radev5c00d0d2017-08-07 10:06:59 +0300963 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300964
965 for (int i = 0; i < 4; ++i)
966 {
967 for (int j = 0; j < 2; ++j)
968 {
969 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
970 }
971 }
972}
973
Martin Radev5c00d0d2017-08-07 10:06:59 +0300974// Test that glClear clears the depth buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300975TEST_P(FramebufferMultiviewSideBySideClearTest, DepthBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +0300976{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300977 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +0300978
979 // Create program to draw a quad.
Jamie Madill35cd7332018-12-02 12:03:33 -0500980 constexpr char kVS[] =
Martin Radev5c00d0d2017-08-07 10:06:59 +0300981 "#version 300 es\n"
982 "in vec3 vPos;\n"
983 "void main(){\n"
984 " gl_Position = vec4(vPos, 1.);\n"
985 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500986 constexpr char kFS[] =
Martin Radev5c00d0d2017-08-07 10:06:59 +0300987 "#version 300 es\n"
988 "precision mediump float;\n"
989 "uniform vec3 uCol;\n"
990 "out vec4 col;\n"
991 "void main(){\n"
992 " col = vec4(uCol,1.);\n"
993 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500994 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300995 glUseProgram(program);
996 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
997
998 initializeFBOs(1, false, true);
999 glEnable(GL_DEPTH_TEST);
1000
1001 // Clear the contents of the texture.
1002 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1003 glClearColor(0, 0, 0, 0);
1004 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1005
1006 // Dirty the depth and color buffers.
1007 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1008 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1009
1010 // Switch to the multi-view framebuffer and clear only the rectangles covered by the views.
1011 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1012 glViewport(0, 0, 1, 2);
1013 glScissor(0, 0, 1, 2);
1014 glEnable(GL_SCISSOR_TEST);
1015 glClear(GL_DEPTH_BUFFER_BIT);
1016
1017 // Draw a fullscreen quad to fill the cleared regions.
1018 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1019 glViewport(0, 0, 4, 2);
1020 glScissor(0, 0, 4, 2);
1021 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1022 drawQuad(program, "vPos", 0.5f, 1.0f, true);
1023
1024 checkAlternatingColumnsOfRedAndGreenInFBO();
1025}
1026
1027// Test that glClear clears the stencil buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001028TEST_P(FramebufferMultiviewSideBySideClearTest, StencilBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001029{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001030 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001031
1032 // Create program to draw a quad.
Jamie Madill35cd7332018-12-02 12:03:33 -05001033 constexpr char kVS[] =
Martin Radev5c00d0d2017-08-07 10:06:59 +03001034 "#version 300 es\n"
1035 "in vec3 vPos;\n"
1036 "void main(){\n"
1037 " gl_Position = vec4(vPos, 1.);\n"
1038 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001039 constexpr char kFS[] =
Martin Radev5c00d0d2017-08-07 10:06:59 +03001040 "#version 300 es\n"
1041 "precision mediump float;\n"
1042 "uniform vec3 uCol;\n"
1043 "out vec4 col;\n"
1044 "void main(){\n"
1045 " col = vec4(uCol,1.);\n"
1046 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001047 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev5c00d0d2017-08-07 10:06:59 +03001048 glUseProgram(program);
1049 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1050
1051 initializeFBOs(1, true, false);
1052 glEnable(GL_STENCIL_TEST);
1053 glDisable(GL_DEPTH_TEST);
1054
1055 // Set clear values and clear the whole framebuffer.
1056 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1057 glClearColor(0, 0, 0, 0);
1058 glClearStencil(0);
1059 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1060
1061 // Update stencil test to always replace the stencil value with 0xFF.
1062 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1063 glStencilFunc(GL_ALWAYS, 0xFF, 0);
1064
1065 // Draw a quad which covers the whole texture.
1066 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1067 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1068
1069 // Switch to multiview framebuffer and clear portions of the texture.
1070 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1071 glViewport(0, 0, 1, 2);
1072 glScissor(0, 0, 1, 2);
1073 glEnable(GL_SCISSOR_TEST);
1074 glClear(GL_STENCIL_BUFFER_BIT);
1075
1076 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1077 // the test.
1078 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1079 glViewport(0, 0, 4, 2);
1080 glScissor(0, 0, 4, 2);
1081 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1082 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1083 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1084
1085 checkAlternatingColumnsOfRedAndGreenInFBO();
1086}
1087
1088// Test that glClearBufferf clears the color buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001089TEST_P(FramebufferMultiviewSideBySideClearTest, ClearBufferF)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001090{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001091 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001092
1093 initializeFBOs(2, false, false);
1094
1095 // Clear the contents of the texture.
1096 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1097 glClearColor(1, 0, 0, 1);
1098 glClear(GL_COLOR_BUFFER_BIT);
1099
1100 // Bind and specify viewport/scissor dimensions for each view.
1101 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1102 glViewport(0, 0, 1, 2);
1103 glScissor(0, 0, 1, 2);
1104 glEnable(GL_SCISSOR_TEST);
1105
1106 float kClearValues[4] = {0.f, 1.f, 0.f, 1.f};
1107 glClearBufferfv(GL_COLOR, 1, kClearValues);
1108
1109 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1110
1111 // Check that glClearBufferfv has not modified the 0th color attachment.
1112 glReadBuffer(GL_COLOR_ATTACHMENT0);
1113 for (int i = 0; i < 4; ++i)
1114 {
1115 for (int j = 0; j < 2; ++j)
1116 {
1117 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
1118 }
1119 }
1120
1121 // Check that glClearBufferfv has correctly modified the 1th color attachment.
1122 glReadBuffer(GL_COLOR_ATTACHMENT1);
1123 checkAlternatingColumnsOfRedAndGreenInFBO();
1124}
1125
Martin Radev5e424fa2017-08-09 16:25:36 +03001126// Test that glClear clears the contents of the color buffer for only the attached layers to a
1127// layered FBO.
1128TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
1129{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001130 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001131
1132 initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
1133
1134 // Bind and specify viewport/scissor dimensions for each view.
1135 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1136
1137 glClearColor(0, 1, 0, 1);
1138 glClear(GL_COLOR_BUFFER_BIT);
1139
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001140 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001141 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1142 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001143 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001144}
1145
1146// Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
1147TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
1148{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001149 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001150
1151 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1152
1153 for (int i = 0; i < 2; ++i)
1154 {
1155 for (int layer = 0; layer < 4; ++layer)
1156 {
1157 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001158 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(layer, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001159 }
1160 }
1161
1162 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1163
1164 float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
1165 glClearBufferfv(GL_COLOR, 0, clearValues0);
1166
1167 float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
1168 glClearBufferfv(GL_COLOR, 1, clearValues1);
1169
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001170 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001171 EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1172 EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001173 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001174
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001175 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001176 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1177 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001178 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001179}
1180
1181// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1182// to a layered FBO.
1183TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
1184{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001185 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001186
1187 // Create program to draw a quad.
Jamie Madill35cd7332018-12-02 12:03:33 -05001188 constexpr char kVS[] =
Martin Radev5e424fa2017-08-09 16:25:36 +03001189 "#version 300 es\n"
1190 "in vec3 vPos;\n"
1191 "void main(){\n"
1192 " gl_Position = vec4(vPos, 1.);\n"
1193 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001194 constexpr char kFS[] =
Martin Radev5e424fa2017-08-09 16:25:36 +03001195 "#version 300 es\n"
1196 "precision mediump float;\n"
1197 "uniform vec3 uCol;\n"
1198 "out vec4 col;\n"
1199 "void main(){\n"
1200 " col = vec4(uCol,1.);\n"
1201 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001202 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev5e424fa2017-08-09 16:25:36 +03001203 glUseProgram(program);
1204 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1205
1206 initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
1207 glEnable(GL_STENCIL_TEST);
1208 glDisable(GL_DEPTH_TEST);
1209
1210 // Set clear values.
1211 glClearColor(1, 0, 0, 1);
1212 glClearStencil(0xFF);
1213
1214 // Clear the color and stencil buffers of each layer.
1215 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1216 {
1217 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1218 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1219 }
1220
1221 // Switch to multiview framebuffer and clear portions of the texture.
1222 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1223 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1224
1225 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1226 // the test.
1227 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1228 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1229 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1230 {
1231 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1232 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1233 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1234 }
1235 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1236 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1237 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1238 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1239}
1240
1241// Test that glClear does not clear the content of a detached texture.
1242TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
1243{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001244 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001245
1246 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1247
1248 // Clear all attachments.
1249 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1250 glClearColor(0, 1, 0, 1);
1251 glClear(GL_COLOR_BUFFER_BIT);
1252
1253 for (int i = 0; i < 2; ++i)
1254 {
1255 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001256 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001257 EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
1258 EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001259 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001260 }
1261
1262 // Detach and clear again.
1263 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1264 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
1265 glClearColor(1, 1, 0, 1);
1266 glClear(GL_COLOR_BUFFER_BIT);
1267
1268 // Check that color attachment 0 is modified.
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001269 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001270 EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1271 EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001272 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001273
1274 // Check that color attachment 1 is unmodified.
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001275 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001276 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1277 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001278 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001279}
1280
1281// Test that glClear clears only the contents within the scissor rectangle of the attached layers.
1282TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
1283{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001284 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001285
1286 initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
1287
1288 // Bind and specify viewport/scissor dimensions for each view.
1289 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1290
1291 glEnable(GL_SCISSOR_TEST);
1292 glScissor(1, 0, 1, 1);
1293 glClearColor(0, 1, 0, 1);
1294 glClear(GL_COLOR_BUFFER_BIT);
1295
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001296 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1297 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001298
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001299 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001300 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
1301
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001302 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001303 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
1304
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001305 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1306 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001307}
1308
Martin Radev18b75ba2017-08-15 15:50:40 +03001309// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1310// to a layered FBO.
1311TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
1312{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001313 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev18b75ba2017-08-15 15:50:40 +03001314
1315 // Create program to draw a quad.
Jamie Madill35cd7332018-12-02 12:03:33 -05001316 constexpr char kVS[] =
Martin Radev18b75ba2017-08-15 15:50:40 +03001317 "#version 300 es\n"
1318 "in vec3 vPos;\n"
1319 "void main(){\n"
1320 " gl_Position = vec4(vPos, 1.);\n"
1321 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001322 constexpr char kFS[] =
Martin Radev18b75ba2017-08-15 15:50:40 +03001323 "#version 300 es\n"
1324 "precision mediump float;\n"
1325 "uniform vec3 uCol;\n"
1326 "out vec4 col;\n"
1327 "void main(){\n"
1328 " col = vec4(uCol,1.);\n"
1329 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001330 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev18b75ba2017-08-15 15:50:40 +03001331 glUseProgram(program);
1332 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1333
1334 initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
1335 glEnable(GL_STENCIL_TEST);
1336 glDisable(GL_DEPTH_TEST);
1337
1338 // Set clear values.
1339 glClearColor(1, 0, 0, 1);
1340 glClearStencil(0xFF);
1341
1342 // Clear the color and stencil buffers of each layer.
1343 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1344 {
1345 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1346 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1347 }
1348
1349 // Switch to multiview framebuffer and clear portions of the texture.
1350 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1351 glEnable(GL_SCISSOR_TEST);
1352 glScissor(0, 0, 1, 1);
1353 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1354 glDisable(GL_SCISSOR_TEST);
1355
1356 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1357 // the test.
1358 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1359 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001360 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
Martin Radev18b75ba2017-08-15 15:50:40 +03001361 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1362 {
1363 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
Martin Radev18b75ba2017-08-15 15:50:40 +03001364 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1365 }
1366 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1367 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
1368 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1369 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
1370 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1371 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
1372 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1373 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
1374}
1375
Martin Radev14b21262017-08-25 13:54:37 +03001376// Test that detaching an attachment does not generate an error whenever the multi-view related
1377// arguments are invalid.
1378TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
1379{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001380 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev14b21262017-08-25 13:54:37 +03001381
1382 GLFramebuffer fbo;
1383 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1384
1385 // Invalid base view index.
1386 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
1387 EXPECT_GL_NO_ERROR();
1388
1389 // Invalid number of views.
1390 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
1391 EXPECT_GL_NO_ERROR();
1392
1393 // Invalid number of views.
1394 const GLint kValidViewportOffsets[2] = {0, 0};
1395 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0,
1396 kValidViewportOffsets);
1397 EXPECT_GL_NO_ERROR();
1398
1399 // Invalid viewport offsets.
1400 const GLint kInvalidViewportOffsets[2] = {-1, -1};
1401 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 1,
1402 kInvalidViewportOffsets);
1403 EXPECT_GL_NO_ERROR();
1404}
1405
Martin Radev61e710b2017-09-05 11:59:52 +03001406// Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
1407// array are attached. The test is added because a special fast code path is used for this case.
1408TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
1409{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001410 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev61e710b2017-09-05 11:59:52 +03001411
1412 initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
1413
1414 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1415 glClearColor(0, 1, 0, 1);
1416 glClear(GL_COLOR_BUFFER_BIT);
1417
1418 EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1419 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1420}
1421
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001422// Test that attaching a multisampled texture array is not possible if all the required extensions
1423// are not enabled.
1424TEST_P(FramebufferMultiviewTest, NegativeMultisampledFramebufferTest)
1425{
1426 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1427
1428 ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"));
1429
1430 // We don't enable ANGLE_multiview_multisample
1431
1432 GLTexture multisampleTexture;
1433 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, multisampleTexture);
1434
1435 GLFramebuffer fbo;
1436 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1437 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1438 multisampleTexture, 0, 0, 2);
1439 // From the extension spec: "An INVALID_OPERATION error is generated if texture is not zero, and
1440 // does not name an existing texture object of type TEXTURE_2D_ARRAY."
1441 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1442}
1443
Olli Etuahof26b27e2018-08-17 11:01:19 +03001444ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));
1445ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest,
1446 VertexShaderOpenGL(3, 0),
1447 GeomShaderD3D11(3, 0));
1448ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest,
1449 VertexShaderOpenGL(3, 0),
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001450 GeomShaderD3D11(3, 0));