blob: f373f2dd9356acfd79be12e4f3d40adcdd42520f [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 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -040058 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
59 glDeleteTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030060 mColorTex.clear();
61 }
62 if (mDepthStencilTex != 0u)
63 {
64 glDeleteTextures(1, &mDepthStencilTex);
65 mDepthStencilTex = 0u;
66 }
67 if (mDepthTex != 0u)
68 {
69 glDeleteTextures(1, &mDepthTex);
70 mDepthTex = 0u;
71 }
72 MultiviewTest::TearDown();
73 }
Martin Radev5c00d0d2017-08-07 10:06:59 +030074
75 void initializeFBOs(size_t numColorBuffers, bool stencil, bool depth)
76 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +030077 ASSERT(mColorTex.empty() && mDepthStencilTex == 0u && mDepthTex == 0u);
78 const std::vector<GLenum> &drawBuffers = GetDrawBufferRange(numColorBuffers);
Martin Radev5c00d0d2017-08-07 10:06:59 +030079
80 // Generate textures.
81 mColorTex.resize(numColorBuffers);
Shahbaz Youssefic4097442018-08-22 12:14:52 -040082 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
83 glGenTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030084 if (stencil)
85 {
86 glGenTextures(1, &mDepthStencilTex);
87 }
88 else if (depth)
89 {
90 glGenTextures(1, &mDepthTex);
91 }
92
Olli Etuaho2c8f0842018-09-12 14:44:55 +030093 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0, 2, 2, 2,
Olli Etuahoa7b35c32018-08-21 16:32:24 +030094 mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5c00d0d2017-08-07 10:06:59 +030095
Olli Etuaho7a4f6b82018-08-17 11:38:11 +030096 glGenFramebuffers(1, &mMultiviewFBO);
97 glGenFramebuffers(1, &mNonMultiviewFBO);
98
Martin Radev5c00d0d2017-08-07 10:06:59 +030099 // Generate multiview fbo and attach textures.
100 const GLint kViewportOffsets[4] = {1, 0, 3, 0};
101 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
102 const size_t kBase = static_cast<size_t>(GL_COLOR_ATTACHMENT0);
103 for (size_t i = 0u; i < numColorBuffers; ++i)
104 {
105 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER,
106 static_cast<GLenum>(kBase + i),
107 mColorTex[i], 0, 2, &kViewportOffsets[0]);
108 }
109
110 if (stencil)
111 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300112 glFramebufferTextureMultiviewSideBySideANGLE(
113 GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, mDepthStencilTex, 0, 2,
114 &kViewportOffsets[0]);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300115 }
116 else if (depth)
117 {
118 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
119 mDepthTex, 0, 2, &kViewportOffsets[0]);
120 }
121 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
122
Martin Radev5e424fa2017-08-09 16:25:36 +0300123 // Generate non-multiview fbo and attach textures.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300124 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
125 for (size_t i = 0u; i < numColorBuffers; ++i)
126 {
127 glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(kBase + i), GL_TEXTURE_2D,
128 mColorTex[i], 0);
129 }
130 if (stencil)
131 {
132 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300133 mDepthStencilTex, 0);
Martin Radev5c00d0d2017-08-07 10:06:59 +0300134 }
135 else if (depth)
136 {
137 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTex,
138 0);
139 }
140 glDrawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
141
142 ASSERT_GL_NO_ERROR();
143 }
144
145 void checkAlternatingColumnsOfRedAndGreenInFBO()
146 {
147 // column 0
148 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
149 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::red);
150
151 // column 1
152 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
153 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
154
155 // column 2
156 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::red);
157 EXPECT_PIXEL_COLOR_EQ(2, 1, GLColor::red);
158
159 // column 3
160 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
161 EXPECT_PIXEL_COLOR_EQ(3, 1, GLColor::green);
162 }
163
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300164 GLuint mMultiviewFBO;
165 GLuint mNonMultiviewFBO;
166
167 private:
168 std::vector<GLuint> mColorTex;
169 GLuint mDepthTex;
170 GLuint mDepthStencilTex;
Martin Radev5c00d0d2017-08-07 10:06:59 +0300171};
172
Martin Radev5e424fa2017-08-09 16:25:36 +0300173class FramebufferMultiviewLayeredClearTest : public FramebufferMultiviewTest
174{
175 protected:
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300176 FramebufferMultiviewLayeredClearTest() : mMultiviewFBO(0), mDepthTex(0), mDepthStencilTex(0) {}
177
178 void TearDown() override
179 {
180 if (mMultiviewFBO != 0)
181 {
182 glDeleteFramebuffers(1, &mMultiviewFBO);
183 mMultiviewFBO = 0u;
184 }
185 if (!mNonMultiviewFBO.empty())
186 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400187 GLsizei textureCount = static_cast<GLsizei>(mNonMultiviewFBO.size());
188 glDeleteTextures(textureCount, mNonMultiviewFBO.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300189 mNonMultiviewFBO.clear();
190 }
191 if (!mColorTex.empty())
192 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400193 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
194 glDeleteTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300195 mColorTex.clear();
196 }
197 if (mDepthStencilTex != 0u)
198 {
199 glDeleteTextures(1, &mDepthStencilTex);
200 mDepthStencilTex = 0u;
201 }
202 if (mDepthTex != 0u)
203 {
204 glDeleteTextures(1, &mDepthTex);
205 mDepthTex = 0u;
206 }
207 MultiviewTest::TearDown();
208 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300209
210 void initializeFBOs(int width,
211 int height,
212 int numLayers,
213 int baseViewIndex,
214 int numViews,
215 int numColorAttachments,
216 bool stencil,
217 bool depth)
218 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300219 ASSERT(mColorTex.empty() && mDepthStencilTex == 0u && mDepthTex == 0u);
Martin Radev5e424fa2017-08-09 16:25:36 +0300220 ASSERT(baseViewIndex + numViews <= numLayers);
221
222 // Generate textures.
223 mColorTex.resize(numColorAttachments);
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400224 GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
225 glGenTextures(textureCount, mColorTex.data());
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300226 if (stencil)
227 {
228 glGenTextures(1, &mDepthStencilTex);
229 }
230 else if (depth)
231 {
232 glGenTextures(1, &mDepthTex);
233 }
234
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300235 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0, width, height,
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300236 numLayers, mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5e424fa2017-08-09 16:25:36 +0300237
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300238 glGenFramebuffers(1, &mMultiviewFBO);
239
Martin Radev5e424fa2017-08-09 16:25:36 +0300240 // Generate multiview FBO and attach textures.
241 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300242 AttachMultiviewTextures(GL_FRAMEBUFFER, GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, width,
243 numViews, baseViewIndex, mColorTex, mDepthTex, mDepthStencilTex);
Martin Radev5e424fa2017-08-09 16:25:36 +0300244
245 const auto &drawBuffers = GetDrawBufferRange(numColorAttachments);
246 glDrawBuffers(numColorAttachments, drawBuffers.data());
247
248 // Generate non-multiview FBOs and attach textures.
249 mNonMultiviewFBO.resize(numLayers);
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400250 GLsizei framebufferCount = static_cast<GLsizei>(mNonMultiviewFBO.size());
251 glGenFramebuffers(framebufferCount, mNonMultiviewFBO.data());
Martin Radev5e424fa2017-08-09 16:25:36 +0300252 for (int i = 0; i < numLayers; ++i)
253 {
254 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
255 for (int j = 0; j < numColorAttachments; ++j)
256 {
257 glFramebufferTextureLayer(GL_FRAMEBUFFER,
258 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + j),
259 mColorTex[j], 0, i);
260 }
261 if (stencil)
262 {
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300263 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
264 mDepthStencilTex, 0, i);
Martin Radev5e424fa2017-08-09 16:25:36 +0300265 }
266 else if (depth)
267 {
268 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTex, 0, i);
269 }
270 glDrawBuffers(numColorAttachments, drawBuffers.data());
Martin Radev5e424fa2017-08-09 16:25:36 +0300271 }
272
273 ASSERT_GL_NO_ERROR();
274 }
275
276 GLColor getLayerColor(size_t layer, GLenum attachment, GLint x, GLint y)
277 {
278 ASSERT(layer < mNonMultiviewFBO.size());
279 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[layer]);
280 glReadBuffer(attachment);
281 return angle::ReadColor(x, y);
282 }
283
284 GLColor getLayerColor(size_t layer, GLenum attachment)
285 {
286 return getLayerColor(layer, attachment, 0, 0);
287 }
288
Olli Etuaho7a4f6b82018-08-17 11:38:11 +0300289 GLuint mMultiviewFBO;
290 std::vector<GLuint> mNonMultiviewFBO;
291
292 private:
293 std::vector<GLuint> mColorTex;
294 GLuint mDepthTex;
295 GLuint mDepthStencilTex;
Martin Radev5e424fa2017-08-09 16:25:36 +0300296};
297
298// Test that the framebuffer tokens introduced by ANGLE_multiview can be used to query the
299// framebuffer state and that their corresponding default values are correctly set.
Martin Radeve5285d22017-07-14 16:23:53 +0300300TEST_P(FramebufferMultiviewTest, DefaultState)
301{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300302 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeve5285d22017-07-14 16:23:53 +0300303
Martin Radev0f7714e2017-08-07 15:13:42 +0300304 GLFramebuffer fbo;
305 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
306
307 GLTexture tex;
308 glBindTexture(GL_TEXTURE_2D, tex);
309 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
310 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300311
Martin Radeve5285d22017-07-14 16:23:53 +0300312 GLint numViews = -1;
313 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
314 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
315 &numViews);
Martin Radev0f7714e2017-08-07 15:13:42 +0300316 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300317 EXPECT_EQ(1, numViews);
318
319 GLint baseViewIndex = -1;
320 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
321 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
322 &baseViewIndex);
Martin Radev0f7714e2017-08-07 15:13:42 +0300323 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300324 EXPECT_EQ(0, baseViewIndex);
325
326 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
327 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
328 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
329 &multiviewLayout);
Martin Radev0f7714e2017-08-07 15:13:42 +0300330 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300331 EXPECT_EQ(GL_NONE, multiviewLayout);
332
333 GLint viewportOffsets[2] = {-1, -1};
334 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
335 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
336 &viewportOffsets[0]);
Martin Radev0f7714e2017-08-07 15:13:42 +0300337 ASSERT_GL_NO_ERROR();
Martin Radeve5285d22017-07-14 16:23:53 +0300338 EXPECT_EQ(0, viewportOffsets[0]);
339 EXPECT_EQ(0, viewportOffsets[1]);
340}
341
342// Test that without having the ANGLE_multiview extension, querying for the framebuffer state using
343// the ANGLE_multiview tokens results in an INVALID_ENUM error.
344TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
345{
Martin Radev0f7714e2017-08-07 15:13:42 +0300346 GLFramebuffer fbo;
347 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
348
349 GLTexture tex;
350 glBindTexture(GL_TEXTURE_2D, tex);
351 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
352 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
Martin Radev137032d2017-07-13 10:11:12 +0300353
Martin Radeve5285d22017-07-14 16:23:53 +0300354 GLint numViews = -1;
355 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
356 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
357 &numViews);
358 EXPECT_GL_ERROR(GL_INVALID_ENUM);
359
360 GLint baseViewIndex = -1;
361 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
362 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
363 &baseViewIndex);
364 EXPECT_GL_ERROR(GL_INVALID_ENUM);
365
366 GLint multiviewLayout = GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
367 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
368 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
369 &multiviewLayout);
370 EXPECT_GL_ERROR(GL_INVALID_ENUM);
371
372 GLint viewportOffsets[2] = {-1, -1};
373 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
374 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
375 &viewportOffsets[0]);
376 EXPECT_GL_ERROR(GL_INVALID_ENUM);
377}
378
Martin Radev137032d2017-07-13 10:11:12 +0300379// Test that the correct errors are generated whenever glFramebufferTextureMultiviewSideBySideANGLE
380// is called with invalid arguments.
381TEST_P(FramebufferMultiviewTest, InvalidMultiviewSideBySideArguments)
382{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300383 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300384
Martin Radev0f7714e2017-08-07 15:13:42 +0300385 GLFramebuffer fbo;
386 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
387
388 GLTexture tex;
389 glBindTexture(GL_TEXTURE_2D, tex);
390 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
391
Martin Radev137032d2017-07-13 10:11:12 +0300392 // Negative offsets.
Martin Radev0f7714e2017-08-07 15:13:42 +0300393 GLint viewportOffsets[2] = {-1};
394 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
395 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300396 EXPECT_GL_ERROR(GL_INVALID_VALUE);
397
398 // Negative number of views.
399 viewportOffsets[0] = 0;
400 viewportOffsets[1] = 0;
Martin Radev0f7714e2017-08-07 15:13:42 +0300401 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1,
402 &viewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300403 EXPECT_GL_ERROR(GL_INVALID_VALUE);
404}
405
406// Test that the correct errors are generated whenever glFramebufferTextureMultiviewLayeredANGLE is
407// called with invalid arguments.
408TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
409{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300410 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev137032d2017-07-13 10:11:12 +0300411
Martin Radev0f7714e2017-08-07 15:13:42 +0300412 GLFramebuffer fbo;
413 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
414
415 GLTexture tex;
416 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
417 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
418 ASSERT_GL_NO_ERROR();
419
Martin Radev137032d2017-07-13 10:11:12 +0300420 // Negative base view index.
Martin Radev0f7714e2017-08-07 15:13:42 +0300421 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300422 EXPECT_GL_ERROR(GL_INVALID_VALUE);
423
424 // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
425 GLint maxTextureLayers = 0;
426 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
Martin Radev0f7714e2017-08-07 15:13:42 +0300427 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0,
428 maxTextureLayers, 1);
Martin Radev137032d2017-07-13 10:11:12 +0300429 EXPECT_GL_ERROR(GL_INVALID_VALUE);
430}
431
432// Test that an INVALID_OPERATION error is generated whenever the ANGLE_multiview extension is not
433// available.
434TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
435{
Martin Radev0f7714e2017-08-07 15:13:42 +0300436 GLFramebuffer fbo;
437 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
438
439 GLTexture tex;
440 glBindTexture(GL_TEXTURE_2D, tex);
441 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
442
Martin Radev9bc9a322017-07-21 14:28:17 +0300443 ASSERT_GL_NO_ERROR();
Martin Radev0f7714e2017-08-07 15:13:42 +0300444 const GLint kViewportOffsets[2] = {0};
445 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
446 &kViewportOffsets[0]);
Martin Radev137032d2017-07-13 10:11:12 +0300447 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
448}
449
Martin Radev5dae57b2017-07-14 16:15:55 +0300450// Test that glFramebufferTextureMultiviewSideBySideANGLE modifies the internal multiview state.
451TEST_P(FramebufferMultiviewTest, ModifySideBySideState)
452{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300453 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5dae57b2017-07-14 16:15:55 +0300454
Martin Radev0f7714e2017-08-07 15:13:42 +0300455 GLFramebuffer fbo;
456 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
457
458 GLTexture tex;
459 glBindTexture(GL_TEXTURE_2D, tex);
460 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
461
462 const GLint kViewportOffsets[4] = {0, 0, 1, 2};
463 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
464 &kViewportOffsets[0]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300465 ASSERT_GL_NO_ERROR();
466
467 GLint numViews = -1;
468 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
469 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
470 &numViews);
471 ASSERT_GL_NO_ERROR();
472 EXPECT_EQ(2, numViews);
473
474 GLint baseViewIndex = -1;
475 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
476 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
477 &baseViewIndex);
478 ASSERT_GL_NO_ERROR();
479 EXPECT_EQ(0, baseViewIndex);
480
481 GLint multiviewLayout = GL_NONE;
482 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
483 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
484 &multiviewLayout);
485 ASSERT_GL_NO_ERROR();
486 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, multiviewLayout);
487
488 GLint internalViewportOffsets[4] = {-1};
489 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
490 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
491 &internalViewportOffsets[0]);
492 ASSERT_GL_NO_ERROR();
493 for (size_t i = 0u; i < 4u; ++i)
494 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300495 EXPECT_EQ(kViewportOffsets[i], internalViewportOffsets[i]);
Martin Radev5dae57b2017-07-14 16:15:55 +0300496 }
497}
498
Martin Radev9bc9a322017-07-21 14:28:17 +0300499// Test framebuffer completeness status of a side-by-side framebuffer with color and depth
500// attachments.
501TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsSideBySide)
502{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300503 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev9bc9a322017-07-21 14:28:17 +0300504
Martin Radev0f7714e2017-08-07 15:13:42 +0300505 GLFramebuffer fbo;
506 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev9bc9a322017-07-21 14:28:17 +0300507
Martin Radev0f7714e2017-08-07 15:13:42 +0300508 GLTexture tex;
509 glBindTexture(GL_TEXTURE_2D, tex);
510 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev9bc9a322017-07-21 14:28:17 +0300511
Martin Radev0f7714e2017-08-07 15:13:42 +0300512 const GLint kViewportOffsets[4] = {0, 0, 2, 0};
513 const GLint kOtherViewportOffsets[4] = {2, 0, 4, 0};
Martin Radev9bc9a322017-07-21 14:28:17 +0300514
515 // 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 +0300516 // attachment will be modified to change the framebuffer's status.
Martin Radev0f7714e2017-08-07 15:13:42 +0300517 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2,
518 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300519 ASSERT_GL_NO_ERROR();
520
521 // Color attachment 1.
522 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300523 GLTexture otherTex;
524 glBindTexture(GL_TEXTURE_2D, otherTex);
525 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
526
Martin Radev9bc9a322017-07-21 14:28:17 +0300527 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300528 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
529 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300530 ASSERT_GL_NO_ERROR();
531 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
532 glCheckFramebufferStatus(GL_FRAMEBUFFER));
533
534 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300535 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
536 0, 2, &kOtherViewportOffsets[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 framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300542 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, otherTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300543 ASSERT_GL_NO_ERROR();
544 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
545 glCheckFramebufferStatus(GL_FRAMEBUFFER));
546
547 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
548 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300549 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex,
550 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300551 ASSERT_GL_NO_ERROR();
552 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
553
554 // Reset attachment 1
555 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1,
Martin Radev0f7714e2017-08-07 15:13:42 +0300556 &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300557 }
558
559 // Depth attachment.
560 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300561 GLTexture depthTex;
562 glBindTexture(GL_TEXTURE_2D, depthTex);
563 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
564 nullptr);
565
Martin Radev9bc9a322017-07-21 14:28:17 +0300566 // Test framebuffer completeness when the number of views differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300567 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
568 0, 1, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300569 ASSERT_GL_NO_ERROR();
570 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
571 glCheckFramebufferStatus(GL_FRAMEBUFFER));
572
573 // Test framebuffer completeness when the viewport offsets differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300574 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
575 0, 2, &kOtherViewportOffsets[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 framebuffer completeness when attachment layouts differ.
Martin Radev0f7714e2017-08-07 15:13:42 +0300581 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex, 0);
Martin Radev9bc9a322017-07-21 14:28:17 +0300582 ASSERT_GL_NO_ERROR();
583 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
584 glCheckFramebufferStatus(GL_FRAMEBUFFER));
585
586 // Test that framebuffer is complete when the number of views, viewport offsets and layouts
587 // are the same.
Martin Radev0f7714e2017-08-07 15:13:42 +0300588 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex,
589 0, 2, &kViewportOffsets[0]);
Martin Radev9bc9a322017-07-21 14:28:17 +0300590 ASSERT_GL_NO_ERROR();
591 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
592 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300593}
594
Martin Radev04e2c3b2017-07-27 16:54:35 +0300595// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300596// attachments with a side-by-side layout.
Martin Radev04e2c3b2017-07-27 16:54:35 +0300597TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
598{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300599 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev04e2c3b2017-07-27 16:54:35 +0300600
Martin Radev0f7714e2017-08-07 15:13:42 +0300601 GLFramebuffer fbo;
602 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300603
Martin Radev0f7714e2017-08-07 15:13:42 +0300604 GLTexture tex;
605 glBindTexture(GL_TEXTURE_2D, tex);
606 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
607
608 const GLint kViewportOffsets[2] = {0};
609 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
610 &kViewportOffsets[0]);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300611 ASSERT_GL_NO_ERROR();
612
613 // Test glCopyTexImage2D and glCopyTexSubImage2D.
614 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300615 GLTexture tex2;
616 glBindTexture(GL_TEXTURE_2D, tex2);
617 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300618
619 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
620 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
621
622 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
623 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300624 }
625
626 // Test glCopyTexSubImage3D.
627 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300628 GLTexture tex2;
629 glBindTexture(GL_TEXTURE_3D, tex2);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300630 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
631
632 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
633 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
Martin Radev04e2c3b2017-07-27 16:54:35 +0300634 }
635}
636
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300637// Test that the active read framebuffer can be read with glCopyTex* if it only has one layered
638// view.
639TEST_P(FramebufferMultiviewTest, CopyTex)
640{
641 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
642
643 GLFramebuffer fbo;
644 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
645
646 GLTexture tex;
647 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
648 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
649
650 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
651 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
652 ASSERT_GL_NO_ERROR();
653
654 // Test glCopyTexImage2D and glCopyTexSubImage2D.
655 {
656 GLTexture tex2;
657 glBindTexture(GL_TEXTURE_2D, tex2);
658 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
659
660 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
661 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
662 glClear(GL_COLOR_BUFFER_BIT);
663
664 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
665 ASSERT_GL_NO_ERROR();
666
667 // Test texture contents.
668 glBindFramebuffer(GL_FRAMEBUFFER, 0);
669 draw2DTexturedQuad(0.0f, 1.0f, true);
670 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
671
672 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
673 glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
674 glClear(GL_COLOR_BUFFER_BIT);
675
676 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
677 ASSERT_GL_NO_ERROR();
678
679 glBindFramebuffer(GL_FRAMEBUFFER, 0);
680 draw2DTexturedQuad(0.0f, 1.0f, true);
681 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
682 }
683
684 // Test glCopyTexSubImage3D.
685 {
686 GLTexture tex2;
687 glBindTexture(GL_TEXTURE_3D, tex2);
688 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
689
690 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
691 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
692 glClear(GL_COLOR_BUFFER_BIT);
693 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
694 ASSERT_GL_NO_ERROR();
695
696 glBindFramebuffer(GL_FRAMEBUFFER, 0);
697 draw3DTexturedQuad(0.0f, 1.0f, true, 0.0f);
698 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
699 }
700}
701
Martin Radeva3ed4572017-07-27 18:29:37 +0300702// Test that glBlitFramebuffer generates an invalid framebuffer operation when either the current
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300703// draw framebuffer, or current read framebuffer have multiview attachments with a side-by-side
704// layout.
Martin Radeva3ed4572017-07-27 18:29:37 +0300705TEST_P(FramebufferMultiviewTest, InvalidBlit)
706{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300707 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeva3ed4572017-07-27 18:29:37 +0300708
Martin Radev0f7714e2017-08-07 15:13:42 +0300709 GLFramebuffer fbo;
710 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300711
Martin Radev0f7714e2017-08-07 15:13:42 +0300712 GLTexture tex;
713 glBindTexture(GL_TEXTURE_2D, tex);
714 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
715
716 const GLint kViewportOffsets[2] = {0};
717 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
718 &kViewportOffsets[0]);
Martin Radeva3ed4572017-07-27 18:29:37 +0300719 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
720 ASSERT_GL_NO_ERROR();
721
722 // Blit with the active read framebuffer having multiview attachments.
723 {
Martin Radev0f7714e2017-08-07 15:13:42 +0300724 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300725 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
726 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
727 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
728 }
729
730 // Blit with the active draw framebuffer having multiview attachments.
731 {
732 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Martin Radev0f7714e2017-08-07 15:13:42 +0300733 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
Martin Radeva3ed4572017-07-27 18:29:37 +0300734 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
735 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
736 }
737}
738
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300739// Test that glBlitFramebuffer succeeds if the current read framebuffer has just one layered view.
740TEST_P(FramebufferMultiviewTest, Blit)
741{
742 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
743
744 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
745 glClear(GL_COLOR_BUFFER_BIT);
746
747 GLFramebuffer fbo;
748 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
749
750 GLTexture tex;
751 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
752 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
753
754 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
755 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
756 ASSERT_GL_NO_ERROR();
757
758 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
759 glClear(GL_COLOR_BUFFER_BIT);
760
761 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
762 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
763 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
764 ASSERT_GL_NO_ERROR();
765
766 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
767 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
768}
769
Martin Radev28031682017-07-28 14:47:56 +0300770// Test that glReadPixels generates an invalid framebuffer operation error if the current read
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300771// framebuffer has a side-by-side multi-view layout.
Martin Radev28031682017-07-28 14:47:56 +0300772TEST_P(FramebufferMultiviewTest, InvalidReadPixels)
773{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300774 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev28031682017-07-28 14:47:56 +0300775
Martin Radev0f7714e2017-08-07 15:13:42 +0300776 GLFramebuffer fbo;
777 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
Martin Radev28031682017-07-28 14:47:56 +0300778
Martin Radev0f7714e2017-08-07 15:13:42 +0300779 GLTexture tex;
780 glBindTexture(GL_TEXTURE_2D, tex);
781 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
782
783 const GLint kViewportOffsets[2] = {0};
784 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1,
785 &kViewportOffsets[0]);
Martin Radev28031682017-07-28 14:47:56 +0300786 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
787 ASSERT_GL_NO_ERROR();
788
789 GLColor pixelColor;
790 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
791 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
792}
793
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300794// Test that glReadPixels succeeds from a layered multiview framebuffer with just one view.
795TEST_P(FramebufferMultiviewTest, ReadPixels)
796{
797 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
798
799 GLFramebuffer fbo;
800 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
801
802 GLTexture tex;
803 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
804 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
805
806 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
807 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
808 ASSERT_GL_NO_ERROR();
809
810 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
811 glClear(GL_COLOR_BUFFER_BIT);
812
813 GLColor pixelColor;
814 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
815 ASSERT_GL_NO_ERROR();
816 EXPECT_COLOR_NEAR(GLColor::green, pixelColor, 2);
817}
818
Martin Radeveef80e42017-08-11 14:44:57 +0300819// Test that glClear clears only the contents of each view if the scissor test is enabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300820TEST_P(FramebufferMultiviewSideBySideClearTest, ColorBufferClear)
Martin Radevb0761932017-07-25 17:42:25 +0300821{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300822 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevb0761932017-07-25 17:42:25 +0300823
Martin Radev5c00d0d2017-08-07 10:06:59 +0300824 initializeFBOs(1, false, false);
Martin Radevb0761932017-07-25 17:42:25 +0300825
826 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300827 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
828 glClearColor(1, 0, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300829 glClear(GL_COLOR_BUFFER_BIT);
830
831 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300832 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300833 glViewport(0, 0, 1, 2);
834 glScissor(0, 0, 1, 2);
Martin Radeveef80e42017-08-11 14:44:57 +0300835 glEnable(GL_SCISSOR_TEST);
Martin Radevb0761932017-07-25 17:42:25 +0300836
Martin Radev5c00d0d2017-08-07 10:06:59 +0300837 glClearColor(0, 1, 0, 1);
Martin Radevb0761932017-07-25 17:42:25 +0300838 glClear(GL_COLOR_BUFFER_BIT);
839
Martin Radev5c00d0d2017-08-07 10:06:59 +0300840 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radevb0761932017-07-25 17:42:25 +0300841
Martin Radev5c00d0d2017-08-07 10:06:59 +0300842 checkAlternatingColumnsOfRedAndGreenInFBO();
Martin Radevb0761932017-07-25 17:42:25 +0300843}
844
Martin Radev82ef7742017-08-08 17:44:58 +0300845// Test that glFramebufferTextureMultiviewLayeredANGLE modifies the internal multiview state.
846TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
847{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300848 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300849
850 GLFramebuffer multiviewFBO;
851 glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
852
853 GLTexture tex;
854 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
855 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
856 ASSERT_GL_NO_ERROR();
857
858 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
859 ASSERT_GL_NO_ERROR();
860
861 GLint numViews = -1;
862 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
863 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE,
864 &numViews);
865 ASSERT_GL_NO_ERROR();
866 EXPECT_EQ(2, numViews);
867
868 GLint baseViewIndex = -1;
869 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
870 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE,
871 &baseViewIndex);
872 ASSERT_GL_NO_ERROR();
873 EXPECT_EQ(1, baseViewIndex);
874
875 GLint multiviewLayout = GL_NONE;
876 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
877 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE,
878 &multiviewLayout);
879 ASSERT_GL_NO_ERROR();
880 EXPECT_EQ(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, multiviewLayout);
881
882 GLint internalViewportOffsets[2] = {-1};
883 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
884 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE,
885 &internalViewportOffsets[0]);
886 ASSERT_GL_NO_ERROR();
887 EXPECT_EQ(0, internalViewportOffsets[0]);
888 EXPECT_EQ(0, internalViewportOffsets[1]);
889}
890
891// Test framebuffer completeness status of a layered framebuffer with color attachments.
892TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
893{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300894 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev82ef7742017-08-08 17:44:58 +0300895
896 GLFramebuffer fbo;
897 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
898
899 GLTexture tex;
900 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
901 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
902
903 // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
904 // attachment will be modified to change the framebuffer's status.
905 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
906 ASSERT_GL_NO_ERROR();
907
908 GLTexture otherTexLayered;
909 glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
910 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
911
912 // Test framebuffer completeness when the base view index differs.
913 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
914 0, 1, 2);
915 ASSERT_GL_NO_ERROR();
916 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
917 glCheckFramebufferStatus(GL_FRAMEBUFFER));
918
919 // Test framebuffer completeness when the 1st attachment has a side-by-side layout.
920 const int kViewportOffsets[4] = {0, 0, 0, 0};
921 GLTexture otherTex2D;
922 glBindTexture(GL_TEXTURE_2D, otherTex2D);
923 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
924 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTex2D,
925 0, 2, kViewportOffsets);
926 ASSERT_GL_NO_ERROR();
927 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
928 glCheckFramebufferStatus(GL_FRAMEBUFFER));
929
Martin Radev5e424fa2017-08-09 16:25:36 +0300930 // Test framebuffer completeness when the 1st attachment has a non-multiview layout.
Martin Radev82ef7742017-08-08 17:44:58 +0300931 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
932 ASSERT_GL_NO_ERROR();
933 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE,
934 glCheckFramebufferStatus(GL_FRAMEBUFFER));
935
936 // Test that framebuffer is complete when the number of views, base view index and layouts are
937 // the same.
938 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered,
939 0, 0, 2);
940 ASSERT_GL_NO_ERROR();
941 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
942}
943
Martin Radeveef80e42017-08-11 14:44:57 +0300944// Test that glClear clears all of the contents if the scissor test is disabled.
Martin Radev5e424fa2017-08-09 16:25:36 +0300945TEST_P(FramebufferMultiviewSideBySideClearTest, ClearWithDisabledScissorTest)
Martin Radeveef80e42017-08-11 14:44:57 +0300946{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300947 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radeveef80e42017-08-11 14:44:57 +0300948
Martin Radev5c00d0d2017-08-07 10:06:59 +0300949 initializeFBOs(1, false, false);
Martin Radeveef80e42017-08-11 14:44:57 +0300950
951 // Clear the contents of the texture.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300952 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
953 glClearColor(0, 0, 0, 1);
Martin Radeveef80e42017-08-11 14:44:57 +0300954 glClear(GL_COLOR_BUFFER_BIT);
955
956 // Bind and specify viewport/scissor dimensions for each view.
Martin Radev5c00d0d2017-08-07 10:06:59 +0300957 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300958 glViewport(0, 0, 1, 2);
959 glScissor(0, 0, 1, 2);
960
961 glClearColor(1, 0, 0, 1);
962 glClear(GL_COLOR_BUFFER_BIT);
963
Martin Radev5c00d0d2017-08-07 10:06:59 +0300964 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
Martin Radeveef80e42017-08-11 14:44:57 +0300965
966 for (int i = 0; i < 4; ++i)
967 {
968 for (int j = 0; j < 2; ++j)
969 {
970 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
971 }
972 }
973}
974
Martin Radev5c00d0d2017-08-07 10:06:59 +0300975// Test that glClear clears the depth buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +0300976TEST_P(FramebufferMultiviewSideBySideClearTest, DepthBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +0300977{
Olli Etuaho8acb1b62018-07-30 16:20:54 +0300978 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +0300979
980 // Create program to draw a quad.
981 const std::string &vs =
982 "#version 300 es\n"
983 "in vec3 vPos;\n"
984 "void main(){\n"
985 " gl_Position = vec4(vPos, 1.);\n"
986 "}\n";
987 const std::string &fs =
988 "#version 300 es\n"
989 "precision mediump float;\n"
990 "uniform vec3 uCol;\n"
991 "out vec4 col;\n"
992 "void main(){\n"
993 " col = vec4(uCol,1.);\n"
994 "}\n";
995 ANGLE_GL_PROGRAM(program, vs, fs);
996 glUseProgram(program);
997 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
998
999 initializeFBOs(1, false, true);
1000 glEnable(GL_DEPTH_TEST);
1001
1002 // Clear the contents of the texture.
1003 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1004 glClearColor(0, 0, 0, 0);
1005 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1006
1007 // Dirty the depth and color buffers.
1008 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1009 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1010
1011 // Switch to the multi-view framebuffer and clear only the rectangles covered by the views.
1012 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1013 glViewport(0, 0, 1, 2);
1014 glScissor(0, 0, 1, 2);
1015 glEnable(GL_SCISSOR_TEST);
1016 glClear(GL_DEPTH_BUFFER_BIT);
1017
1018 // Draw a fullscreen quad to fill the cleared regions.
1019 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1020 glViewport(0, 0, 4, 2);
1021 glScissor(0, 0, 4, 2);
1022 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1023 drawQuad(program, "vPos", 0.5f, 1.0f, true);
1024
1025 checkAlternatingColumnsOfRedAndGreenInFBO();
1026}
1027
1028// Test that glClear clears the stencil buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001029TEST_P(FramebufferMultiviewSideBySideClearTest, StencilBufferClear)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001030{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001031 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001032
1033 // Create program to draw a quad.
1034 const std::string &vs =
1035 "#version 300 es\n"
1036 "in vec3 vPos;\n"
1037 "void main(){\n"
1038 " gl_Position = vec4(vPos, 1.);\n"
1039 "}\n";
1040 const std::string &fs =
1041 "#version 300 es\n"
1042 "precision mediump float;\n"
1043 "uniform vec3 uCol;\n"
1044 "out vec4 col;\n"
1045 "void main(){\n"
1046 " col = vec4(uCol,1.);\n"
1047 "}\n";
1048 ANGLE_GL_PROGRAM(program, vs, fs);
1049 glUseProgram(program);
1050 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1051
1052 initializeFBOs(1, true, false);
1053 glEnable(GL_STENCIL_TEST);
1054 glDisable(GL_DEPTH_TEST);
1055
1056 // Set clear values and clear the whole framebuffer.
1057 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1058 glClearColor(0, 0, 0, 0);
1059 glClearStencil(0);
1060 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1061
1062 // Update stencil test to always replace the stencil value with 0xFF.
1063 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1064 glStencilFunc(GL_ALWAYS, 0xFF, 0);
1065
1066 // Draw a quad which covers the whole texture.
1067 glUniform3f(mColorUniformLoc, 1.0f, 0.0f, 0.0f);
1068 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1069
1070 // Switch to multiview framebuffer and clear portions of the texture.
1071 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1072 glViewport(0, 0, 1, 2);
1073 glScissor(0, 0, 1, 2);
1074 glEnable(GL_SCISSOR_TEST);
1075 glClear(GL_STENCIL_BUFFER_BIT);
1076
1077 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1078 // the test.
1079 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1080 glViewport(0, 0, 4, 2);
1081 glScissor(0, 0, 4, 2);
1082 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1083 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1084 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1085
1086 checkAlternatingColumnsOfRedAndGreenInFBO();
1087}
1088
1089// Test that glClearBufferf clears the color buffer of each view.
Martin Radev5e424fa2017-08-09 16:25:36 +03001090TEST_P(FramebufferMultiviewSideBySideClearTest, ClearBufferF)
Martin Radev5c00d0d2017-08-07 10:06:59 +03001091{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001092 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5c00d0d2017-08-07 10:06:59 +03001093
1094 initializeFBOs(2, false, false);
1095
1096 // Clear the contents of the texture.
1097 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1098 glClearColor(1, 0, 0, 1);
1099 glClear(GL_COLOR_BUFFER_BIT);
1100
1101 // Bind and specify viewport/scissor dimensions for each view.
1102 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1103 glViewport(0, 0, 1, 2);
1104 glScissor(0, 0, 1, 2);
1105 glEnable(GL_SCISSOR_TEST);
1106
1107 float kClearValues[4] = {0.f, 1.f, 0.f, 1.f};
1108 glClearBufferfv(GL_COLOR, 1, kClearValues);
1109
1110 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO);
1111
1112 // Check that glClearBufferfv has not modified the 0th color attachment.
1113 glReadBuffer(GL_COLOR_ATTACHMENT0);
1114 for (int i = 0; i < 4; ++i)
1115 {
1116 for (int j = 0; j < 2; ++j)
1117 {
1118 EXPECT_PIXEL_COLOR_EQ(i, j, GLColor::red);
1119 }
1120 }
1121
1122 // Check that glClearBufferfv has correctly modified the 1th color attachment.
1123 glReadBuffer(GL_COLOR_ATTACHMENT1);
1124 checkAlternatingColumnsOfRedAndGreenInFBO();
1125}
1126
Martin Radev5e424fa2017-08-09 16:25:36 +03001127// Test that glClear clears the contents of the color buffer for only the attached layers to a
1128// layered FBO.
1129TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
1130{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001131 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001132
1133 initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
1134
1135 // Bind and specify viewport/scissor dimensions for each view.
1136 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1137
1138 glClearColor(0, 1, 0, 1);
1139 glClear(GL_COLOR_BUFFER_BIT);
1140
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001141 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001142 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1143 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001144 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001145}
1146
1147// Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
1148TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
1149{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001150 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001151
1152 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1153
1154 for (int i = 0; i < 2; ++i)
1155 {
1156 for (int layer = 0; layer < 4; ++layer)
1157 {
1158 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001159 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(layer, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001160 }
1161 }
1162
1163 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1164
1165 float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
1166 glClearBufferfv(GL_COLOR, 0, clearValues0);
1167
1168 float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
1169 glClearBufferfv(GL_COLOR, 1, clearValues1);
1170
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001171 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001172 EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1173 EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001174 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001175
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001176 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001177 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1178 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001179 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001180}
1181
1182// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1183// to a layered FBO.
1184TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
1185{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001186 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001187
1188 // Create program to draw a quad.
1189 const std::string &vs =
1190 "#version 300 es\n"
1191 "in vec3 vPos;\n"
1192 "void main(){\n"
1193 " gl_Position = vec4(vPos, 1.);\n"
1194 "}\n";
1195 const std::string &fs =
1196 "#version 300 es\n"
1197 "precision mediump float;\n"
1198 "uniform vec3 uCol;\n"
1199 "out vec4 col;\n"
1200 "void main(){\n"
1201 " col = vec4(uCol,1.);\n"
1202 "}\n";
1203 ANGLE_GL_PROGRAM(program, vs, fs);
1204 glUseProgram(program);
1205 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1206
1207 initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
1208 glEnable(GL_STENCIL_TEST);
1209 glDisable(GL_DEPTH_TEST);
1210
1211 // Set clear values.
1212 glClearColor(1, 0, 0, 1);
1213 glClearStencil(0xFF);
1214
1215 // Clear the color and stencil buffers of each layer.
1216 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1217 {
1218 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1219 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1220 }
1221
1222 // Switch to multiview framebuffer and clear portions of the texture.
1223 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1224 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1225
1226 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1227 // the test.
1228 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1229 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
1230 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1231 {
1232 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1233 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
1234 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1235 }
1236 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1237 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1238 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
1239 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
1240}
1241
1242// Test that glClear does not clear the content of a detached texture.
1243TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
1244{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001245 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001246
1247 initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
1248
1249 // Clear all attachments.
1250 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1251 glClearColor(0, 1, 0, 1);
1252 glClear(GL_COLOR_BUFFER_BIT);
1253
1254 for (int i = 0; i < 2; ++i)
1255 {
1256 GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001257 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001258 EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
1259 EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001260 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, colorAttachment));
Martin Radev5e424fa2017-08-09 16:25:36 +03001261 }
1262
1263 // Detach and clear again.
1264 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1265 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
1266 glClearColor(1, 1, 0, 1);
1267 glClear(GL_COLOR_BUFFER_BIT);
1268
1269 // Check that color attachment 0 is modified.
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001270 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001271 EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1272 EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001273 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001274
1275 // Check that color attachment 1 is unmodified.
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001276 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001277 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
1278 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001279 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
Martin Radev5e424fa2017-08-09 16:25:36 +03001280}
1281
1282// Test that glClear clears only the contents within the scissor rectangle of the attached layers.
1283TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
1284{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001285 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev5e424fa2017-08-09 16:25:36 +03001286
1287 initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
1288
1289 // Bind and specify viewport/scissor dimensions for each view.
1290 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1291
1292 glEnable(GL_SCISSOR_TEST);
1293 glScissor(1, 0, 1, 1);
1294 glClearColor(0, 1, 0, 1);
1295 glClear(GL_COLOR_BUFFER_BIT);
1296
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001297 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1298 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001299
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001300 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001301 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
1302
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001303 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001304 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
1305
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001306 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1307 EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
Martin Radev5e424fa2017-08-09 16:25:36 +03001308}
1309
Martin Radev18b75ba2017-08-15 15:50:40 +03001310// Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
1311// to a layered FBO.
1312TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
1313{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001314 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev18b75ba2017-08-15 15:50:40 +03001315
1316 // Create program to draw a quad.
1317 const std::string &vs =
1318 "#version 300 es\n"
1319 "in vec3 vPos;\n"
1320 "void main(){\n"
1321 " gl_Position = vec4(vPos, 1.);\n"
1322 "}\n";
1323 const std::string &fs =
1324 "#version 300 es\n"
1325 "precision mediump float;\n"
1326 "uniform vec3 uCol;\n"
1327 "out vec4 col;\n"
1328 "void main(){\n"
1329 " col = vec4(uCol,1.);\n"
1330 "}\n";
1331 ANGLE_GL_PROGRAM(program, vs, fs);
1332 glUseProgram(program);
1333 GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
1334
1335 initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
1336 glEnable(GL_STENCIL_TEST);
1337 glDisable(GL_DEPTH_TEST);
1338
1339 // Set clear values.
1340 glClearColor(1, 0, 0, 1);
1341 glClearStencil(0xFF);
1342
1343 // Clear the color and stencil buffers of each layer.
1344 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1345 {
1346 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
1347 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1348 }
1349
1350 // Switch to multiview framebuffer and clear portions of the texture.
1351 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1352 glEnable(GL_SCISSOR_TEST);
1353 glScissor(0, 0, 1, 1);
1354 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1355 glDisable(GL_SCISSOR_TEST);
1356
1357 // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
1358 // the test.
1359 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1360 glStencilFunc(GL_EQUAL, 0x00, 0xFF);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001361 glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
Martin Radev18b75ba2017-08-15 15:50:40 +03001362 for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
1363 {
1364 glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
Martin Radev18b75ba2017-08-15 15:50:40 +03001365 drawQuad(program, "vPos", 0.0f, 1.0f, true);
1366 }
1367 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
1368 EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
1369 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
1370 EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
1371 EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
1372 EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
1373 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
1374 EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
1375}
1376
Martin Radev14b21262017-08-25 13:54:37 +03001377// Test that detaching an attachment does not generate an error whenever the multi-view related
1378// arguments are invalid.
1379TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
1380{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001381 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev14b21262017-08-25 13:54:37 +03001382
1383 GLFramebuffer fbo;
1384 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1385
1386 // Invalid base view index.
1387 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
1388 EXPECT_GL_NO_ERROR();
1389
1390 // Invalid number of views.
1391 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
1392 EXPECT_GL_NO_ERROR();
1393
1394 // Invalid number of views.
1395 const GLint kValidViewportOffsets[2] = {0, 0};
1396 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0,
1397 kValidViewportOffsets);
1398 EXPECT_GL_NO_ERROR();
1399
1400 // Invalid viewport offsets.
1401 const GLint kInvalidViewportOffsets[2] = {-1, -1};
1402 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 1,
1403 kInvalidViewportOffsets);
1404 EXPECT_GL_NO_ERROR();
1405}
1406
Martin Radev61e710b2017-09-05 11:59:52 +03001407// Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
1408// array are attached. The test is added because a special fast code path is used for this case.
1409TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
1410{
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001411 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev61e710b2017-09-05 11:59:52 +03001412
1413 initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
1414
1415 glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
1416 glClearColor(0, 1, 0, 1);
1417 glClear(GL_COLOR_BUFFER_BIT);
1418
1419 EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
1420 EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
1421}
1422
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001423// Test that attaching a multisampled texture array is not possible if all the required extensions
1424// are not enabled.
1425TEST_P(FramebufferMultiviewTest, NegativeMultisampledFramebufferTest)
1426{
1427 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1428
1429 ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"));
1430
1431 // We don't enable ANGLE_multiview_multisample
1432
1433 GLTexture multisampleTexture;
1434 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, multisampleTexture);
1435
1436 GLFramebuffer fbo;
1437 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1438 glFramebufferTextureMultiviewLayeredANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1439 multisampleTexture, 0, 0, 2);
1440 // From the extension spec: "An INVALID_OPERATION error is generated if texture is not zero, and
1441 // does not name an existing texture object of type TEXTURE_2D_ARRAY."
1442 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1443}
1444
Olli Etuahof26b27e2018-08-17 11:01:19 +03001445ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));
1446ANGLE_INSTANTIATE_TEST(FramebufferMultiviewSideBySideClearTest,
1447 VertexShaderOpenGL(3, 0),
1448 GeomShaderD3D11(3, 0));
1449ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest,
1450 VertexShaderOpenGL(3, 0),
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001451 GeomShaderD3D11(3, 0));