blob: 04853a95a33589e74956473e0f3bba02f66b3b73 [file] [log] [blame]
Martin Radeve5285d22017-07-14 16:23:53 +03001//
2// Copyright 2017 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// Framebuffer multiview tests:
7// The tests modify and examine the multiview state.
8//
9
Olli Etuahof26b27e2018-08-17 11:01:19 +030010#include "test_utils/MultiviewTest.h"
Martin Radev0f7714e2017-08-07 15:13:42 +030011#include "test_utils/gl_raii.h"
Martin Radeve5285d22017-07-14 16:23:53 +030012
13using namespace angle;
14
Martin Radev5c00d0d2017-08-07 10:06:59 +030015namespace
16{
17std::vector<GLenum> GetDrawBufferRange(size_t numColorAttachments)
18{
19 std::vector<GLenum> drawBuffers(numColorAttachments);
20 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
21 for (size_t i = 0u; i < drawBuffers.size(); ++i)
22 {
23 drawBuffers[i] = static_cast<GLenum>(kBase + i);
24 }
25 return drawBuffers;
26}
27} // namespace
28
Olli Etuahof26b27e2018-08-17 11:01:19 +030029// Base class for tests that care mostly about draw call validity and not rendering results.
30class FramebufferMultiviewTest : public MultiviewTest
Martin Radeve5285d22017-07-14 16:23:53 +030031{
32 protected:
Olli Etuahof26b27e2018-08-17 11:01:19 +030033 FramebufferMultiviewTest() : MultiviewTest() {}
Martin Radeve5285d22017-07-14 16:23:53 +030034};
35
Martin Radev5e424fa2017-08-09 16:25:36 +030036class FramebufferMultiviewSideBySideClearTest : public FramebufferMultiviewTest
Martin Radev5c00d0d2017-08-07 10:06:59 +030037{
38 protected:
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030039 FramebufferMultiviewSideBySideClearTest()
40 : mMultiviewFBO(0u), mNonMultiviewFBO(0u), mDepthTex(0u), mDepthStencilTex(0u)
41 {
42 }
43
44 void TearDown() override
45 {
46 if (mMultiviewFBO != 0)
47 {
48 glDeleteFramebuffers(1, &mMultiviewFBO);
49 mMultiviewFBO = 0u;
50 }
51 if (mNonMultiviewFBO != 0)
52 {
53 glDeleteTextures(1, &mNonMultiviewFBO);
54 mNonMultiviewFBO = 0u;
55 }
56 if (!mColorTex.empty())
57 {
58 glDeleteTextures(mColorTex.size(), mColorTex.data());
59 mColorTex.clear();
60 }
61 if (mDepthStencilTex != 0u)
62 {
63 glDeleteTextures(1, &mDepthStencilTex);
64 mDepthStencilTex = 0u;
65 }
66 if (mDepthTex != 0u)
67 {
68 glDeleteTextures(1, &mDepthTex);
69 mDepthTex = 0u;
70 }
71 MultiviewTest::TearDown();
72 }
Martin Radev5c00d0d2017-08-07 10:06:59 +030073
74 void initializeFBOs(size_t numColorBuffers, bool stencil, bool depth)
75 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +030076 ASSERT(mColorTex.empty() && mDepthStencilTex == 0u && mDepthTex == 0u);
77 const std::vector<GLenum> &drawBuffers = GetDrawBufferRange(numColorBuffers);
Martin Radev5c00d0d2017-08-07 10:06:59 +030078
79 // Generate textures.
80 mColorTex.resize(numColorBuffers);
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030081 glGenTextures(mColorTex.size(), mColorTex.data());
82 if (stencil)
83 {
84 glGenTextures(1, &mDepthStencilTex);
85 }
86 else if (depth)
87 {
88 glGenTextures(1, &mDepthTex);
89 }
90
Olli Etuahoa7b35c32018-08-21 16:32:24 +030091 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 2, 2, 2,
92 mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5c00d0d2017-08-07 10:06:59 +030093
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030094 glGenFramebuffers(1, &mMultiviewFBO);
95 glGenFramebuffers(1, &mNonMultiviewFBO);
96
Martin Radev5c00d0d2017-08-07 10:06:59 +030097 // Generate multiview fbo and attach textures.
98 const GLint kViewportOffsets[4] = {1, 0, 3, 0};
99 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
100 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
101 for (size_t i = 0u; i < numColorBuffers; ++i)
102 {
103 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
104 static_cast<GLenum>(kBase + i),
105 mColorTex[i], 0, 2, &kViewportOffsets[0]);
106 }
107
108 if (stencil)
109 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300110 glFramebufferTextureMultiviewSideBySideANGLE(
111 GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, mDepthStencilTex, 0, 2,
112 &kViewportOffsets[0]);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300113 }
114 else if (depth)
115 {
116 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
117 mDepthTex, 0, 2, &kViewportOffsets[0]);
118 }
119 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
120
Martin Radev5e424fa2017-08-09 16:25:36 +0300121 // Generate non-multiview fbo and attach textures.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300122 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
123 for (size_t i = 0u; i < numColorBuffers; ++i)
124 {
125 glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(kBase + i), GL_TEXTURE_2D,
126 mColorTex[i], 0);
127 }
128 if (stencil)
129 {
130 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300131 mDepthStencilTex, 0);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300132 }
133 else if (depth)
134 {
135 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTex,
136 0);
137 }
138 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
139
140 ASSERT_GL_NO_ERROR();
141 }
142
143 void checkAlternatingColumnsOfRedAndGreenInFBO()
144 {
145 // column 0
146 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
147 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::red);
148
149 // column 1
150 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
151 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
152
153 // column 2
154 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::red);
155 EXPECT_PIXEL_COLOR_EQ(2, 1, GLColor::red);
156
157 // column 3
158 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
159 EXPECT_PIXEL_COLOR_EQ(3, 1, GLColor::green);
160 }
161
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300162 GLuint mMultiviewFBO;
163 GLuint mNonMultiviewFBO;
164
165 private:
166 std::vector<GLuint> mColorTex;
167 GLuint mDepthTex;
168 GLuint mDepthStencilTex;
Martin Radev5c00d0d2017-08-07 10:06:59 +0300169};
170
Martin Radev5e424fa2017-08-09 16:25:36 +0300171class FramebufferMultiviewLayeredClearTest : public FramebufferMultiviewTest
172{
173 protected:
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300174 FramebufferMultiviewLayeredClearTest() : mMultiviewFBO(0), mDepthTex(0), mDepthStencilTex(0) {}
175
176 void TearDown() override
177 {
178 if (mMultiviewFBO != 0)
179 {
180 glDeleteFramebuffers(1, &mMultiviewFBO);
181 mMultiviewFBO = 0u;
182 }
183 if (!mNonMultiviewFBO.empty())
184 {
185 glDeleteTextures(mNonMultiviewFBO.size(), mNonMultiviewFBO.data());
186 mNonMultiviewFBO.clear();
187 }
188 if (!mColorTex.empty())
189 {
190 glDeleteTextures(mColorTex.size(), mColorTex.data());
191 mColorTex.clear();
192 }
193 if (mDepthStencilTex != 0u)
194 {
195 glDeleteTextures(1, &mDepthStencilTex);
196 mDepthStencilTex = 0u;
197 }
198 if (mDepthTex != 0u)
199 {
200 glDeleteTextures(1, &mDepthTex);
201 mDepthTex = 0u;
202 }
203 MultiviewTest::TearDown();
204 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300205
206 void initializeFBOs(int width,
207 int height,
208 int numLayers,
209 int baseViewIndex,
210 int numViews,
211 int numColorAttachments,
212 bool stencil,
213 bool depth)
214 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300215 ASSERT(mColorTex.empty() && mDepthStencilTex == 0u && mDepthTex == 0u);
Martin Radev5e424fa2017-08-09 16:25:36 +0300216 ASSERT(baseViewIndex + numViews <= numLayers);
217
218 // Generate textures.
219 mColorTex.resize(numColorAttachments);
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300220 glGenTextures(mColorTex.size(), mColorTex.data());
221 if (stencil)
222 {
223 glGenTextures(1, &mDepthStencilTex);
224 }
225 else if (depth)
226 {
227 glGenTextures(1, &mDepthTex);
228 }
229
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300230 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, width, height,
231 numLayers, mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5e424fa2017-08-09 16:25:36 +0300232
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300233 glGenFramebuffers(1, &mMultiviewFBO);
234
Martin Radev5e424fa2017-08-09 16:25:36 +0300235 // Generate multiview FBO and attach textures.
236 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300237 AttachMultiviewTextures(GL_FRAMEBUFFER, GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, width,
238 numViews, baseViewIndex, mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5e424fa2017-08-09 16:25:36 +0300239
240 const auto &drawBuffers = GetDrawBufferRange(numColorAttachments);
241 glDrawBuffers(numColorAttachments, drawBuffers.data());
242
243 // Generate non-multiview FBOs and attach textures.
244 mNonMultiviewFBO.resize(numLayers);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300245 glGenFramebuffers(mNonMultiviewFBO.size(), mNonMultiviewFBO.data());
Martin Radev5e424fa2017-08-09 16:25:36 +0300246 for (int i = 0; i < numLayers; ++i)
247 {
248 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
249 for (int j = 0; j < numColorAttachments; ++j)
250 {
251 glFramebufferTextureLayer(GL_FRAMEBUFFER,
252 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + j),
253 mColorTex[j], 0, i);
254 }
255 if (stencil)
256 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300257 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
258 mDepthStencilTex, 0, i);
Martin Radev5e424fa2017-08-09 16:25:36 +0300259 }
260 else if (depth)
261 {
262 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTex, 0, i);
263 }
264 glDrawBuffers(numColorAttachments, drawBuffers.data());
Martin Radev5e424fa2017-08-09 16:25:36 +0300265 }
266
267 ASSERT_GL_NO_ERROR();
268 }
269
270 GLColor getLayerColor(size_t layer, GLenum attachment, GLint x, GLint y)
271 {
272 ASSERT(layer < mNonMultiviewFBO.size());
273 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[layer]);
274 glReadBuffer(attachment);
275 return angle::ReadColor(x, y);
276 }
277
278 GLColor getLayerColor(size_t layer, GLenum attachment)
279 {
280 return getLayerColor(layer, attachment, 0, 0);
281 }
282
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300283 GLuint mMultiviewFBO;
284 std::vector<GLuint> mNonMultiviewFBO;
285
286 private:
287 std::vector<GLuint> mColorTex;
288 GLuint mDepthTex;
289 GLuint mDepthStencilTex;
Martin Radev5e424fa2017-08-09 16:25:36 +0300290};
291
292// Test that the framebuffer tokens introduced by ANGLE_multiview can be used to query the
293// framebuffer state and that their corresponding default values are correctly set.
Martin Radeve5285d22017-07-14 16:23:53 +0300294TEST_P(FramebufferMultiviewTest, DefaultState)
295{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300296 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeve5285d22017-07-14 16:23:53 +0300297
Martin Radev0f7714e2017-08-07 15:13:42 +0300298 GLFramebuffer fbo;
299 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
300
301 GLTexture tex;
302 glBindTexture(GL_TEXTURE_2D, tex);
303 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
304 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300305
Martin Radeve5285d22017-07-14 16:23:53 +0300306 GLint numViews = -1;
307 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
308 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
309 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +0300310 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300311 EXPECT_EQ(1, numViews);
312
313 GLint baseViewIndex = -1;
314 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
315 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
316 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +0300317 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300318 EXPECT_EQ(0, baseViewIndex);
319
320 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
321 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
322 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
323 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +0300324 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300325 EXPECT_EQ(GL_NONE, multiviewLayout);
326
327 GLint viewportOffsets[2] = {-1, -1};
328 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
329 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
330 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +0300331 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300332 EXPECT_EQ(0, viewportOffsets[0]);
333 EXPECT_EQ(0, viewportOffsets[1]);
334}
335
336// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
337// the ANGLE_multiview tokens results in an INVALID_ENUM error.
338TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
339{
Martin Radev0f7714e2017-08-07 15:13:42 +0300340 GLFramebuffer fbo;
341 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
342
343 GLTexture tex;
344 glBindTexture(GL_TEXTURE_2D, tex);
345 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
346 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300347
Martin Radeve5285d22017-07-14 16:23:53 +0300348 GLint numViews = -1;
349 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
350 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
351 &numViews);
352 EXPECT_GL_ERROR(GL_INVALID_ENUM);
353
354 GLint baseViewIndex = -1;
355 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
356 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
357 &baseViewIndex);
358 EXPECT_GL_ERROR(GL_INVALID_ENUM);
359
360 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
361 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
362 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
363 &multiviewLayout);
364 EXPECT_GL_ERROR(GL_INVALID_ENUM);
365
366 GLint viewportOffsets[2] = {-1, -1};
367 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
368 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
369 &viewportOffsets[0]);
370 EXPECT_GL_ERROR(GL_INVALID_ENUM);
371}
372
Martin Radev137032d2017-07-13 10:11:12 +0300373// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
374// is called with invalid arguments.
375TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
376{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300377 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300378
Martin Radev0f7714e2017-08-07 15:13:42 +0300379 GLFramebuffer fbo;
380 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
381
382 GLTexture tex;
383 glBindTexture(GL_TEXTURE_2D, tex);
384 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
385
Martin Radev137032d2017-07-13 10:11:12 +0300386 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300387 GLint viewportOffsets[2] = {-1};
388 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
389 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300390 EXPECT_GL_ERROR(GL_INVALID_VALUE);
391
392 // Negative number of views.
393 viewportOffsets[0] = 0;
394 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300395 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1,
396 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300397 EXPECT_GL_ERROR(GL_INVALID_VALUE);
398}
399
400// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
401// called with invalid arguments.
402TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
403{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300404 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300405
Martin Radev0f7714e2017-08-07 15:13:42 +0300406 GLFramebuffer fbo;
407 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
408
409 GLTexture tex;
410 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
411 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
412 ASSERT_GL_NO_ERROR();
413
Martin Radev137032d2017-07-13 10:11:12 +0300414 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300415 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300416 EXPECT_GL_ERROR(GL_INVALID_VALUE);
417
418 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
419 GLint maxTextureLayers = 0;
420 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300421 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
422 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300423 EXPECT_GL_ERROR(GL_INVALID_VALUE);
424}
425
426// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
427// available.
428TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
429{
Martin Radev0f7714e2017-08-07 15:13:42 +0300430 GLFramebuffer fbo;
431 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
432
433 GLTexture tex;
434 glBindTexture(GL_TEXTURE_2D, tex);
435 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
436
Martin Radev9bc9a322017-07-21 14:28:17 +0300437 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300438 const GLint kViewportOffsets[2] = {0};
439 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
440 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300441 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
442}
443
Martin Radev5dae57b2017-07-14 16:15:55 +0300444// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
445TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
446{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300447 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5dae57b2017-07-14 16:15:55 +0300448
Martin Radev0f7714e2017-08-07 15:13:42 +0300449 GLFramebuffer fbo;
450 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
451
452 GLTexture tex;
453 glBindTexture(GL_TEXTURE_2D, tex);
454 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
455
456 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
457 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
458 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300459 ASSERT_GL_NO_ERROR();
460
461 GLint numViews = -1;
462 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
463 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
464 &numViews);
465 ASSERT_GL_NO_ERROR();
466 EXPECT_EQ(2, numViews);
467
468 GLint baseViewIndex = -1;
469 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
470 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
471 &baseViewIndex);
472 ASSERT_GL_NO_ERROR();
473 EXPECT_EQ(0, baseViewIndex);
474
475 GLint multiviewLayout = GL_NONE;
476 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
477 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
478 &multiviewLayout);
479 ASSERT_GL_NO_ERROR();
480 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
481
482 GLint internalViewportOffsets[4] = {-1};
483 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
484 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
485 &internalViewportOffsets[0]);
486 ASSERT_GL_NO_ERROR();
487 for (size_t i = 0u; i < 4u; ++i)
488 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300489 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300490 }
491}
492
Martin Radev9bc9a322017-07-21 14:28:17 +0300493// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
494// attachments.
495TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
496{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300497 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev9bc9a322017-07-21 14:28:17 +0300498
Martin Radev0f7714e2017-08-07 15:13:42 +0300499 GLFramebuffer fbo;
500 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300501
Martin Radev0f7714e2017-08-07 15:13:42 +0300502 GLTexture tex;
503 glBindTexture(GL_TEXTURE_2D, tex);
504 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300505
Martin Radev0f7714e2017-08-07 15:13:42 +0300506 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
507 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300508
509 // 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 +0300510 // attachment will be modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300511 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
512 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300513 ASSERT_GL_NO_ERROR();
514
515 // Color attachment 1.
516 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300517 GLTexture otherTex;
518 glBindTexture(GL_TEXTURE_2D, otherTex);
519 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
520
Martin Radev9bc9a322017-07-21 14:28:17 +0300521 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300522 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
523 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300524 ASSERT_GL_NO_ERROR();
525 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
526 glCheckFramebufferStatus(GL_FRAMEBUFFER));
527
528 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300529 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
530 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300531 ASSERT_GL_NO_ERROR();
532 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
533 glCheckFramebufferStatus(GL_FRAMEBUFFER));
534
535 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300536 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300537 ASSERT_GL_NO_ERROR();
538 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
539 glCheckFramebufferStatus(GL_FRAMEBUFFER));
540
541 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
542 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300543 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
544 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300545 ASSERT_GL_NO_ERROR();
546 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
547
548 // Reset attachment 1
549 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300550 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300551 }
552
553 // Depth attachment.
554 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300555 GLTexture depthTex;
556 glBindTexture(GL_TEXTURE_2D, depthTex);
557 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
558 nullptr);
559
Martin Radev9bc9a322017-07-21 14:28:17 +0300560 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300561 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
562 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300563 ASSERT_GL_NO_ERROR();
564 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
565 glCheckFramebufferStatus(GL_FRAMEBUFFER));
566
567 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300568 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
569 0, 2, &kOtherViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300570 ASSERT_GL_NO_ERROR();
571 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
572 glCheckFramebufferStatus(GL_FRAMEBUFFER));
573
574 // Test framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300575 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300576 ASSERT_GL_NO_ERROR();
577 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
578 glCheckFramebufferStatus(GL_FRAMEBUFFER));
579
580 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
581 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300582 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
583 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300584 ASSERT_GL_NO_ERROR();
585 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
586 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300587}
588
Martin Radev04e2c3b2017-07-27 16:54:35 +0300589// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300590// attachments with a side-by-side layout.
Martin Radev04e2c3b2017-07-27 16:54:35 +0300591TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
592{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300593 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev04e2c3b2017-07-27 16:54:35 +0300594
Martin Radev0f7714e2017-08-07 15:13:42 +0300595 GLFramebuffer fbo;
596 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300597
Martin Radev0f7714e2017-08-07 15:13:42 +0300598 GLTexture tex;
599 glBindTexture(GL_TEXTURE_2D, tex);
600 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
601
602 const GLint kViewportOffsets[2] = {0};
603 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
604 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300605 ASSERT_GL_NO_ERROR();
606
607 // Test glCopyTexImage2D and glCopyTexSubImage2D.
608 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300609 GLTexture tex2;
610 glBindTexture(GL_TEXTURE_2D, tex2);
611 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300612
613 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
614 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
615
616 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
617 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300618 }
619
620 // Test glCopyTexSubImage3D.
621 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300622 GLTexture tex2;
623 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300624 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
625
626 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
627 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300628 }
629}
630
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300631// Test that the active read framebuffer can be read with glCopyTex* if it only has one layered
632// view.
633TEST_P(FramebufferMultiviewTest, CopyTex)
634{
635 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
636
637 GLFramebuffer fbo;
638 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
639
640 GLTexture tex;
641 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
642 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
643
644 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
645 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
646 ASSERT_GL_NO_ERROR();
647
648 // Test glCopyTexImage2D and glCopyTexSubImage2D.
649 {
650 GLTexture tex2;
651 glBindTexture(GL_TEXTURE_2D, tex2);
652 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
653
654 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
655 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
656 glClear(GL_COLOR_BUFFER_BIT);
657
658 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
659 ASSERT_GL_NO_ERROR();
660
661 // Test texture contents.
662 glBindFramebuffer(GL_FRAMEBUFFER, 0);
663 draw2DTexturedQuad(0.0f, 1.0f, true);
664 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
665
666 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
667 glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
668 glClear(GL_COLOR_BUFFER_BIT);
669
670 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
671 ASSERT_GL_NO_ERROR();
672
673 glBindFramebuffer(GL_FRAMEBUFFER, 0);
674 draw2DTexturedQuad(0.0f, 1.0f, true);
675 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
676 }
677
678 // Test glCopyTexSubImage3D.
679 {
680 GLTexture tex2;
681 glBindTexture(GL_TEXTURE_3D, tex2);
682 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
683
684 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
685 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
686 glClear(GL_COLOR_BUFFER_BIT);
687 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
688 ASSERT_GL_NO_ERROR();
689
690 glBindFramebuffer(GL_FRAMEBUFFER, 0);
691 draw3DTexturedQuad(0.0f, 1.0f, true, 0.0f);
692 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
693 }
694}
695
Martin Radeva3ed4572017-07-27 18:29:37 +0300696// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300697// draw framebuffer, or current read framebuffer have multiview attachments with a side-by-side
698// layout.
Martin Radeva3ed4572017-07-27 18:29:37 +0300699TEST_P(FramebufferMultiviewTest, InvalidBlit)
700{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300701 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeva3ed4572017-07-27 18:29:37 +0300702
Martin Radev0f7714e2017-08-07 15:13:42 +0300703 GLFramebuffer fbo;
704 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300705
Martin Radev0f7714e2017-08-07 15:13:42 +0300706 GLTexture tex;
707 glBindTexture(GL_TEXTURE_2D, tex);
708 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
709
710 const GLint kViewportOffsets[2] = {0};
711 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
712 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300713 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
714 ASSERT_GL_NO_ERROR();
715
716 // Blit with the active read framebuffer having multiview attachments.
717 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300718 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300719 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
720 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
721 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
722 }
723
724 // Blit with the active draw framebuffer having multiview attachments.
725 {
726 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300727 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300728 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
729 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
730 }
731}
732
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300733// Test that glBlitFramebuffer succeeds if the current read framebuffer has just one layered view.
734TEST_P(FramebufferMultiviewTest, Blit)
735{
736 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
737
738 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
739 glClear(GL_COLOR_BUFFER_BIT);
740
741 GLFramebuffer fbo;
742 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
743
744 GLTexture tex;
745 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
746 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
747
748 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
749 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
750 ASSERT_GL_NO_ERROR();
751
752 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
753 glClear(GL_COLOR_BUFFER_BIT);
754
755 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
756 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
757 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
758 ASSERT_GL_NO_ERROR();
759
760 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
761 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
762}
763
Martin Radev28031682017-07-28 14:47:56 +0300764// Test that glReadPixels generates an invalid framebuffer operation error if the current read
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300765// framebuffer has a side-by-side multi-view layout.
Martin Radev28031682017-07-28 14:47:56 +0300766TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
767{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300768 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev28031682017-07-28 14:47:56 +0300769
Martin Radev0f7714e2017-08-07 15:13:42 +0300770 GLFramebuffer fbo;
771 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300772
Martin Radev0f7714e2017-08-07 15:13:42 +0300773 GLTexture tex;
774 glBindTexture(GL_TEXTURE_2D, tex);
775 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
776
777 const GLint kViewportOffsets[2] = {0};
778 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
779 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300780 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
781 ASSERT_GL_NO_ERROR();
782
783 GLColor pixelColor;
784 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
785 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
786}
787
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300788// Test that glReadPixels succeeds from a layered multiview framebuffer with just one view.
789TEST_P(FramebufferMultiviewTest, ReadPixels)
790{
791 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
792
793 GLFramebuffer fbo;
794 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
795
796 GLTexture tex;
797 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
798 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
799
800 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
801 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
802 ASSERT_GL_NO_ERROR();
803
804 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
805 glClear(GL_COLOR_BUFFER_BIT);
806
807 GLColor pixelColor;
808 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
809 ASSERT_GL_NO_ERROR();
810 EXPECT_COLOR_NEAR(GLColor::green, pixelColor, 2);
811}
812
Martin Radeveef80e42017-08-11 14:44:57 +0300813// Test that glClear clears only the contents of each view if the scissor test is enabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300814TEST_P(FramebufferMultiviewSideBySideClearTest, ColorBufferClear)
Martin Radevb0761932017-07-25 17:42:25 +0300815{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300816 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevb0761932017-07-25 17:42:25 +0300817
Martin Radev5c00d0d2017-08-07 10:06:59 +0300818 initializeFBOs(1, false, false);
Martin Radevb0761932017-07-25 17:42:25 +0300819
820 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300821 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
822 glClearColor(1, 0, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300823 glClear(GL_COLOR_BUFFER_BIT);
824
825 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300826 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300827 glViewport(0, 0, 1, 2);
828 glScissor(0, 0, 1, 2);
Martin Radeveef80e42017-08-11 14:44:57 +0300829 glEnable(GL_SCISSOR_TEST);
Martin Radevb0761932017-07-25 17:42:25 +0300830
Martin Radev5c00d0d2017-08-07 10:06:59 +0300831 glClearColor(0, 1, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300832 glClear(GL_COLOR_BUFFER_BIT);
833
Martin Radev5c00d0d2017-08-07 10:06:59 +0300834 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300835
Martin Radev5c00d0d2017-08-07 10:06:59 +0300836 checkAlternatingColumnsOfRedAndGreenInFBO();
Martin Radevb0761932017-07-25 17:42:25 +0300837}
838
Martin Radev82ef7742017-08-08 17:44:58 +0300839// Test that glFramebufferTextureMultiviewLayeredANGLE modifies the internal multiview state.
840TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
841{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300842 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300843
844 GLFramebuffer multiviewFBO;
845 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
846
847 GLTexture tex;
848 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
849 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
850 ASSERT_GL_NO_ERROR();
851
852 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
853 ASSERT_GL_NO_ERROR();
854
855 GLint numViews = -1;
856 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
857 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
858 &numViews);
859 ASSERT_GL_NO_ERROR();
860 EXPECT_EQ(2, numViews);
861
862 GLint baseViewIndex = -1;
863 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
864 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
865 &baseViewIndex);
866 ASSERT_GL_NO_ERROR();
867 EXPECT_EQ(1, baseViewIndex);
868
869 GLint multiviewLayout = GL_NONE;
870 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
871 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
872 &multiviewLayout);
873 ASSERT_GL_NO_ERROR();
874 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, multiviewLayout);
875
876 GLint internalViewportOffsets[2] = {-1};
877 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
878 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
879 &internalViewportOffsets[0]);
880 ASSERT_GL_NO_ERROR();
881 EXPECT_EQ(0, internalViewportOffsets[0]);
882 EXPECT_EQ(0, internalViewportOffsets[1]);
883}
884
885// Test framebuffer completeness status of a layered framebuffer with color attachments.
886TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
887{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300888 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300889
890 GLFramebuffer fbo;
891 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
892
893 GLTexture tex;
894 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
895 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
896
897 // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
898 // attachment will be modified to change the framebuffer's status.
899 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
900 ASSERT_GL_NO_ERROR();
901
902 GLTexture otherTexLayered;
903 glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
904 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
905
906 // Test framebuffer completeness when the base view index differs.
907 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
908 0, 1, 2);
909 ASSERT_GL_NO_ERROR();
910 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
911 glCheckFramebufferStatus(GL_FRAMEBUFFER));
912
913 // Test framebuffer completeness when the 1st attachment has a side-by-side layout.
914 const int kViewportOffsets[4] = {0, 0, 0, 0};
915 GLTexture otherTex2D;
916 glBindTexture(GL_TEXTURE_2D, otherTex2D);
917 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
918 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex2D,
919 0, 2, kViewportOffsets);
920 ASSERT_GL_NO_ERROR();
921 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
922 glCheckFramebufferStatus(GL_FRAMEBUFFER));
923
Martin Radev5e424fa2017-08-09 16:25:36 +0300924 // Test framebuffer completeness when the 1st attachment has a non-multiview layout.
Martin Radev82ef7742017-08-08 17:44:58 +0300925 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
926 ASSERT_GL_NO_ERROR();
927 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
928 glCheckFramebufferStatus(GL_FRAMEBUFFER));
929
930 // Test that framebuffer is complete when the number of views, base view index and layouts are
931 // the same.
932 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
933 0, 0, 2);
934 ASSERT_GL_NO_ERROR();
935 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
936}
937
Martin Radeveef80e42017-08-11 14:44:57 +0300938// Test that glClear clears all of the contents if the scissor test is disabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300939TEST_P(FramebufferMultiviewSideBySideClearTest, ClearWithDisabledScissorTest)
Martin Radeveef80e42017-08-11 14:44:57 +0300940{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300941 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeveef80e42017-08-11 14:44:57 +0300942
Martin Radev5c00d0d2017-08-07 10:06:59 +0300943 initializeFBOs(1, false, false);
Martin Radeveef80e42017-08-11 14:44:57 +0300944
945 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300946 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
947 glClearColor(0, 0, 0, 1);
Martin Radeveef80e42017-08-11 14:44:57 +0300948 glClear(GL_COLOR_BUFFER_BIT);
949
950 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300951 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300952 glViewport(0, 0, 1, 2);
953 glScissor(0, 0, 1, 2);
954
955 glClearColor(1, 0, 0, 1);
956 glClear(GL_COLOR_BUFFER_BIT);
957
Martin Radev5c00d0d2017-08-07 10:06:59 +0300958 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300959
960 for (int i = 0; i < 4; ++i)
961 {
962 for (int j = 0; j < 2; ++j)
963 {
964 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
965 }
966 }
967}
968
Martin Radev5c00d0d2017-08-07 10:06:59 +0300969// Test that glClear clears the depth buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300970TEST_P(FramebufferMultiviewSideBySideClearTest, DepthBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +0300971{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300972 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +0300973
974 // Create program to draw a quad.
975 const std::string &vs =
976 "#version 300 es\n"
977 "in vec3 vPos;\n"
978 "void main(){\n"
979 " gl_Position = vec4(vPos, 1.);\n"
980 "}\n";
981 const std::string &fs =
982 "#version 300 es\n"
983 "precision mediump float;\n"
984 "uniform vec3 uCol;\n"
985 "out vec4 col;\n"
986 "void main(){\n"
987 " col = vec4(uCol,1.);\n"
988 "}\n";
989 ANGLE_GL_PROGRAM(program, vs, fs);
990 glUseProgram(program);
991 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
992
993 initializeFBOs(1, false, true);
994 glEnable(GL_DEPTH_TEST);
995
996 // Clear the contents of the texture.
997 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
998 glClearColor(0, 0, 0, 0);
999 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1000
1001 // Dirty the depth and color buffers.
1002 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1003 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1004
1005 // Switch to the multi-view framebuffer and clear only the rectangles covered by the views.
1006 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1007 glViewport(0, 0, 1, 2);
1008 glScissor(0, 0, 1, 2);
1009 glEnable(GL_SCISSOR_TEST);
1010 glClear(GL_DEPTH_BUFFER_BIT);
1011
1012 // Draw a fullscreen quad to fill the cleared regions.
1013 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1014 glViewport(0, 0, 4, 2);
1015 glScissor(0, 0, 4, 2);
1016 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1017 drawQuad(program, "vPos", 0.5f, 1.0f, true);
1018
1019 checkAlternatingColumnsOfRedAndGreenInFBO();
1020}
1021
1022// Test that glClear clears the stencil buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001023TEST_P(FramebufferMultiviewSideBySideClearTest, StencilBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001024{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001025 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001026
1027 // Create program to draw a quad.
1028 const std::string &vs =
1029 "#version 300 es\n"
1030 "in vec3 vPos;\n"
1031 "void main(){\n"
1032 " gl_Position = vec4(vPos, 1.);\n"
1033 "}\n";
1034 const std::string &fs =
1035 "#version 300 es\n"
1036 "precision mediump float;\n"
1037 "uniform vec3 uCol;\n"
1038 "out vec4 col;\n"
1039 "void main(){\n"
1040 " col = vec4(uCol,1.);\n"
1041 "}\n";
1042 ANGLE_GL_PROGRAM(program, vs, fs);
1043 glUseProgram(program);
1044 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1045
1046 initializeFBOs(1, true, false);
1047 glEnable(GL_STENCIL_TEST);
1048 glDisable(GL_DEPTH_TEST);
1049
1050 // Set clear values and clear the whole framebuffer.
1051 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1052 glClearColor(0, 0, 0, 0);
1053 glClearStencil(0);
1054 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1055
1056 // Update stencil test to always replace the stencil value with 0xFF.
1057 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1058 glStencilFunc(GL_ALWAYS, 0xFF, 0);
1059
1060 // Draw a quad which covers the whole texture.
1061 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1062 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1063
1064 // Switch to multiview framebuffer and clear portions of the texture.
1065 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1066 glViewport(0, 0, 1, 2);
1067 glScissor(0, 0, 1, 2);
1068 glEnable(GL_SCISSOR_TEST);
1069 glClear(GL_STENCIL_BUFFER_BIT);
1070
1071 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1072 // the test.
1073 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1074 glViewport(0, 0, 4, 2);
1075 glScissor(0, 0, 4, 2);
1076 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1077 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1078 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1079
1080 checkAlternatingColumnsOfRedAndGreenInFBO();
1081}
1082
1083// Test that glClearBufferf clears the color buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001084TEST_P(FramebufferMultiviewSideBySideClearTest, ClearBufferF)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001085{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001086 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001087
1088 initializeFBOs(2, false, false);
1089
1090 // Clear the contents of the texture.
1091 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1092 glClearColor(1, 0, 0, 1);
1093 glClear(GL_COLOR_BUFFER_BIT);
1094
1095 // Bind and specify viewport/scissor dimensions for each view.
1096 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1097 glViewport(0, 0, 1, 2);
1098 glScissor(0, 0, 1, 2);
1099 glEnable(GL_SCISSOR_TEST);
1100
1101 float kClearValues[4] = {0.f, 1.f, 0.f, 1.f};
1102 glClearBufferfv(GL_COLOR, 1, kClearValues);
1103
1104 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1105
1106 // Check that glClearBufferfv has not modified the 0th color attachment.
1107 glReadBuffer(GL_COLOR_ATTACHMENT0);
1108 for (int i = 0; i < 4; ++i)
1109 {
1110 for (int j = 0; j < 2; ++j)
1111 {
1112 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
1113 }
1114 }
1115
1116 // Check that glClearBufferfv has correctly modified the 1th color attachment.
1117 glReadBuffer(GL_COLOR_ATTACHMENT1);
1118 checkAlternatingColumnsOfRedAndGreenInFBO();
1119}
1120
Martin Radev5e424fa2017-08-09 16:25:36 +03001121// Test that glClear clears the contents of the color buffer for only the attached layers to a
1122// layered FBO.
1123TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
1124{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001125 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001126
1127 initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
1128
1129 // Bind and specify viewport/scissor dimensions for each view.
1130 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1131
1132 glClearColor(0, 1, 0, 1);
1133 glClear(GL_COLOR_BUFFER_BIT);
1134
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001135 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001136 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1137 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001138 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001139}
1140
1141// Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
1142TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
1143{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001144 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001145
1146 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1147
1148 for (int i = 0; i < 2; ++i)
1149 {
1150 for (int layer = 0; layer < 4; ++layer)
1151 {
1152 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001153 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(layer, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001154 }
1155 }
1156
1157 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1158
1159 float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
1160 glClearBufferfv(GL_COLOR, 0, clearValues0);
1161
1162 float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
1163 glClearBufferfv(GL_COLOR, 1, clearValues1);
1164
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001165 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001166 EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1167 EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001168 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001169
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001170 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001171 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1172 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001173 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001174}
1175
1176// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1177// to a layered FBO.
1178TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
1179{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001180 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001181
1182 // Create program to draw a quad.
1183 const std::string &vs =
1184 "#version 300 es\n"
1185 "in vec3 vPos;\n"
1186 "void main(){\n"
1187 " gl_Position = vec4(vPos, 1.);\n"
1188 "}\n";
1189 const std::string &fs =
1190 "#version 300 es\n"
1191 "precision mediump float;\n"
1192 "uniform vec3 uCol;\n"
1193 "out vec4 col;\n"
1194 "void main(){\n"
1195 " col = vec4(uCol,1.);\n"
1196 "}\n";
1197 ANGLE_GL_PROGRAM(program, vs, fs);
1198 glUseProgram(program);
1199 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1200
1201 initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
1202 glEnable(GL_STENCIL_TEST);
1203 glDisable(GL_DEPTH_TEST);
1204
1205 // Set clear values.
1206 glClearColor(1, 0, 0, 1);
1207 glClearStencil(0xFF);
1208
1209 // Clear the color and stencil buffers of each layer.
1210 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1211 {
1212 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1213 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1214 }
1215
1216 // Switch to multiview framebuffer and clear portions of the texture.
1217 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1218 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1219
1220 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1221 // the test.
1222 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1223 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1224 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1225 {
1226 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1227 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1228 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1229 }
1230 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1231 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1232 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1233 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1234}
1235
1236// Test that glClear does not clear the content of a detached texture.
1237TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
1238{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001239 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001240
1241 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1242
1243 // Clear all attachments.
1244 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1245 glClearColor(0, 1, 0, 1);
1246 glClear(GL_COLOR_BUFFER_BIT);
1247
1248 for (int i = 0; i < 2; ++i)
1249 {
1250 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001251 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001252 EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
1253 EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001254 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001255 }
1256
1257 // Detach and clear again.
1258 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1259 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
1260 glClearColor(1, 1, 0, 1);
1261 glClear(GL_COLOR_BUFFER_BIT);
1262
1263 // Check that color attachment 0 is modified.
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001264 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001265 EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1266 EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001267 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001268
1269 // Check that color attachment 1 is unmodified.
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001270 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001271 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1272 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001273 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001274}
1275
1276// Test that glClear clears only the contents within the scissor rectangle of the attached layers.
1277TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
1278{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001279 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001280
1281 initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
1282
1283 // Bind and specify viewport/scissor dimensions for each view.
1284 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1285
1286 glEnable(GL_SCISSOR_TEST);
1287 glScissor(1, 0, 1, 1);
1288 glClearColor(0, 1, 0, 1);
1289 glClear(GL_COLOR_BUFFER_BIT);
1290
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001291 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1292 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001293
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001294 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001295 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
1296
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001297 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001298 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
1299
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001300 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1301 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001302}
1303
Martin Radev18b75ba2017-08-15 15:50:40 +03001304// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1305// to a layered FBO.
1306TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
1307{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001308 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev18b75ba2017-08-15 15:50:40 +03001309
1310 // Create program to draw a quad.
1311 const std::string &vs =
1312 "#version 300 es\n"
1313 "in vec3 vPos;\n"
1314 "void main(){\n"
1315 " gl_Position = vec4(vPos, 1.);\n"
1316 "}\n";
1317 const std::string &fs =
1318 "#version 300 es\n"
1319 "precision mediump float;\n"
1320 "uniform vec3 uCol;\n"
1321 "out vec4 col;\n"
1322 "void main(){\n"
1323 " col = vec4(uCol,1.);\n"
1324 "}\n";
1325 ANGLE_GL_PROGRAM(program, vs, fs);
1326 glUseProgram(program);
1327 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1328
1329 initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
1330 glEnable(GL_STENCIL_TEST);
1331 glDisable(GL_DEPTH_TEST);
1332
1333 // Set clear values.
1334 glClearColor(1, 0, 0, 1);
1335 glClearStencil(0xFF);
1336
1337 // Clear the color and stencil buffers of each layer.
1338 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1339 {
1340 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1341 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1342 }
1343
1344 // Switch to multiview framebuffer and clear portions of the texture.
1345 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1346 glEnable(GL_SCISSOR_TEST);
1347 glScissor(0, 0, 1, 1);
1348 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1349 glDisable(GL_SCISSOR_TEST);
1350
1351 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1352 // the test.
1353 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1354 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001355 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
Martin Radev18b75ba2017-08-15 15:50:40 +03001356 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1357 {
1358 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
Martin Radev18b75ba2017-08-15 15:50:40 +03001359 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1360 }
1361 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1362 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
1363 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1364 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
1365 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1366 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
1367 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1368 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
1369}
1370
Martin Radev14b21262017-08-25 13:54:37 +03001371// Test that detaching an attachment does not generate an error whenever the multi-view related
1372// arguments are invalid.
1373TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
1374{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001375 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev14b21262017-08-25 13:54:37 +03001376
1377 GLFramebuffer fbo;
1378 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1379
1380 // Invalid base view index.
1381 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
1382 EXPECT_GL_NO_ERROR();
1383
1384 // Invalid number of views.
1385 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
1386 EXPECT_GL_NO_ERROR();
1387
1388 // Invalid number of views.
1389 const GLint kValidViewportOffsets[2] = {0, 0};
1390 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0,
1391 kValidViewportOffsets);
1392 EXPECT_GL_NO_ERROR();
1393
1394 // Invalid viewport offsets.
1395 const GLint kInvalidViewportOffsets[2] = {-1, -1};
1396 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 1,
1397 kInvalidViewportOffsets);
1398 EXPECT_GL_NO_ERROR();
1399}
1400
Martin Radev61e710b2017-09-05 11:59:52 +03001401// Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
1402// array are attached. The test is added because a special fast code path is used for this case.
1403TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
1404{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001405 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev61e710b2017-09-05 11:59:52 +03001406
1407 initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
1408
1409 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1410 glClearColor(0, 1, 0, 1);
1411 glClear(GL_COLOR_BUFFER_BIT);
1412
1413 EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1414 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1415}
1416
Olli Etuahof26b27e2018-08-17 11:01:19 +03001417ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));
1418ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest,
1419 VertexShaderOpenGL(3, 0),
1420 GeomShaderD3D11(3, 0));
1421ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest,
1422 VertexShaderOpenGL(3, 0),
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001423 GeomShaderD3D11(3, 0));