• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Framebuffer multiview tests:
7 // The tests modify and examine the multiview state.
8 //
9 
10 #include "test_utils/MultiviewTest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 namespace
16 {
GetDrawBufferRange(size_t numColorAttachments)17 std::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 
29 // Base class for tests that care mostly about draw call validity and not rendering results.
30 class FramebufferMultiviewTest : public MultiviewTest
31 {
32   protected:
FramebufferMultiviewTest()33     FramebufferMultiviewTest() : MultiviewTest() {}
34 };
35 
36 class FramebufferMultiviewLayeredClearTest : public FramebufferMultiviewTest
37 {
38   protected:
FramebufferMultiviewLayeredClearTest()39     FramebufferMultiviewLayeredClearTest() : mMultiviewFBO(0), mDepthTex(0), mDepthStencilTex(0) {}
40 
testTearDown()41     void testTearDown() override
42     {
43         if (mMultiviewFBO != 0)
44         {
45             glDeleteFramebuffers(1, &mMultiviewFBO);
46             mMultiviewFBO = 0u;
47         }
48         if (!mNonMultiviewFBO.empty())
49         {
50             GLsizei textureCount = static_cast<GLsizei>(mNonMultiviewFBO.size());
51             glDeleteTextures(textureCount, mNonMultiviewFBO.data());
52             mNonMultiviewFBO.clear();
53         }
54         if (!mColorTex.empty())
55         {
56             GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
57             glDeleteTextures(textureCount, mColorTex.data());
58             mColorTex.clear();
59         }
60         if (mDepthStencilTex != 0u)
61         {
62             glDeleteTextures(1, &mDepthStencilTex);
63             mDepthStencilTex = 0u;
64         }
65         if (mDepthTex != 0u)
66         {
67             glDeleteTextures(1, &mDepthTex);
68             mDepthTex = 0u;
69         }
70         MultiviewTest::testTearDown();
71     }
72 
initializeFBOs(int width,int height,int numLayers,int baseViewIndex,int numViews,int numColorAttachments,bool stencil,bool depth)73     void initializeFBOs(int width,
74                         int height,
75                         int numLayers,
76                         int baseViewIndex,
77                         int numViews,
78                         int numColorAttachments,
79                         bool stencil,
80                         bool depth)
81     {
82         ASSERT_TRUE(mColorTex.empty());
83         ASSERT_EQ(0u, mDepthStencilTex);
84         ASSERT_EQ(0u, mDepthTex);
85         ASSERT_LE(baseViewIndex + numViews, numLayers);
86 
87         // Generate textures.
88         mColorTex.resize(numColorAttachments);
89         GLsizei textureCount = static_cast<GLsizei>(mColorTex.size());
90         glGenTextures(textureCount, mColorTex.data());
91         if (stencil)
92         {
93             glGenTextures(1, &mDepthStencilTex);
94         }
95         else if (depth)
96         {
97             glGenTextures(1, &mDepthTex);
98         }
99 
100         CreateMultiviewBackingTextures(0, width, height, numLayers, mColorTex, mDepthTex,
101                                        mDepthStencilTex);
102 
103         glGenFramebuffers(1, &mMultiviewFBO);
104 
105         // Generate multiview FBO and attach textures.
106         glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
107         AttachMultiviewTextures(GL_FRAMEBUFFER, width, numViews, baseViewIndex, mColorTex,
108                                 mDepthTex, mDepthStencilTex);
109 
110         const auto &drawBuffers = GetDrawBufferRange(numColorAttachments);
111         glDrawBuffers(numColorAttachments, drawBuffers.data());
112 
113         // Generate non-multiview FBOs and attach textures.
114         mNonMultiviewFBO.resize(numLayers);
115         GLsizei framebufferCount = static_cast<GLsizei>(mNonMultiviewFBO.size());
116         glGenFramebuffers(framebufferCount, mNonMultiviewFBO.data());
117         for (int i = 0; i < numLayers; ++i)
118         {
119             glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
120             for (int j = 0; j < numColorAttachments; ++j)
121             {
122                 glFramebufferTextureLayer(GL_FRAMEBUFFER,
123                                           static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + j),
124                                           mColorTex[j], 0, i);
125             }
126             if (stencil)
127             {
128                 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
129                                           mDepthStencilTex, 0, i);
130             }
131             else if (depth)
132             {
133                 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTex, 0, i);
134             }
135             glDrawBuffers(numColorAttachments, drawBuffers.data());
136         }
137 
138         ASSERT_GL_NO_ERROR();
139     }
140 
getLayerColor(size_t layer,GLenum attachment,GLint x,GLint y)141     GLColor getLayerColor(size_t layer, GLenum attachment, GLint x, GLint y)
142     {
143         EXPECT_LT(layer, mNonMultiviewFBO.size());
144         glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[layer]);
145         glReadBuffer(attachment);
146         return angle::ReadColor(x, y);
147     }
148 
getLayerColor(size_t layer,GLenum attachment)149     GLColor getLayerColor(size_t layer, GLenum attachment)
150     {
151         return getLayerColor(layer, attachment, 0, 0);
152     }
153 
154     GLuint mMultiviewFBO;
155     std::vector<GLuint> mNonMultiviewFBO;
156 
157   private:
158     std::vector<GLuint> mColorTex;
159     GLuint mDepthTex;
160     GLuint mDepthStencilTex;
161 };
162 
163 // Test that the framebuffer tokens introduced by OVR_multiview2 can be used to query the
164 // framebuffer state and that their corresponding default values are correctly set.
TEST_P(FramebufferMultiviewTest,DefaultState)165 TEST_P(FramebufferMultiviewTest, DefaultState)
166 {
167     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
168 
169     GLFramebuffer fbo;
170     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
171 
172     GLTexture tex;
173     glBindTexture(GL_TEXTURE_2D, tex);
174     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
175     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
176 
177     GLint numViews = -1;
178     glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
179                                           GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR,
180                                           &numViews);
181     ASSERT_GL_NO_ERROR();
182     EXPECT_EQ(1, numViews);
183 
184     GLint baseViewIndex = -1;
185     glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
186                                           GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR,
187                                           &baseViewIndex);
188     ASSERT_GL_NO_ERROR();
189     EXPECT_EQ(0, baseViewIndex);
190 }
191 
192 // Test that without having the OVR_multiview2 extension, querying for the framebuffer state using
193 // the OVR_multiview2 tokens results in an INVALID_ENUM error.
TEST_P(FramebufferMultiviewTest,NegativeFramebufferStateQueries)194 TEST_P(FramebufferMultiviewTest, NegativeFramebufferStateQueries)
195 {
196     GLFramebuffer fbo;
197     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
198 
199     GLTexture tex;
200     glBindTexture(GL_TEXTURE_2D, tex);
201     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
202     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
203 
204     GLint numViews = -1;
205     glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
206                                           GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR,
207                                           &numViews);
208     EXPECT_GL_ERROR(GL_INVALID_ENUM);
209 
210     GLint baseViewIndex = -1;
211     glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
212                                           GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR,
213                                           &baseViewIndex);
214     EXPECT_GL_ERROR(GL_INVALID_ENUM);
215 }
216 
217 // Test that the correct errors are generated whenever glFramebufferTextureMultiviewOVR is
218 // called with invalid arguments.
TEST_P(FramebufferMultiviewTest,InvalidMultiviewLayeredArguments)219 TEST_P(FramebufferMultiviewTest, InvalidMultiviewLayeredArguments)
220 {
221     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
222 
223     GLFramebuffer fbo;
224     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
225 
226     GLTexture tex;
227     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
228     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
229     ASSERT_GL_NO_ERROR();
230 
231     // Negative base view index.
232     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, -1, 1);
233     EXPECT_GL_ERROR(GL_INVALID_VALUE);
234 
235     // baseViewIndex + numViews is greater than MAX_TEXTURE_LAYERS.
236     GLint maxTextureLayers = 0;
237     glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
238     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, maxTextureLayers,
239                                      1);
240     EXPECT_GL_ERROR(GL_INVALID_VALUE);
241 }
242 
243 // Test that an INVALID_OPERATION error is generated whenever the OVR_multiview2 extension is not
244 // available.
TEST_P(FramebufferMultiviewTest,ExtensionNotAvailableCheck)245 TEST_P(FramebufferMultiviewTest, ExtensionNotAvailableCheck)
246 {
247     GLFramebuffer fbo;
248     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
249 
250     GLTexture tex;
251     glBindTexture(GL_TEXTURE_2D, tex);
252     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
253 
254     ASSERT_GL_NO_ERROR();
255     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 1);
256     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
257 }
258 
259 // Test that the active read framebuffer can be read with glCopyTex* if it only has one layered
260 // view.
TEST_P(FramebufferMultiviewTest,CopyTex)261 TEST_P(FramebufferMultiviewTest, CopyTex)
262 {
263     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
264 
265     // glCopyTexImage2D generates GL_INVALID_FRAMEBUFFER_OPERATION. http://anglebug.com/3857
266     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL());
267 
268     GLFramebuffer fbo;
269     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
270 
271     GLTexture tex;
272     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
273     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
274 
275     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
276     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
277     ASSERT_GL_NO_ERROR();
278 
279     // Test glCopyTexImage2D and glCopyTexSubImage2D.
280     {
281         GLTexture tex2;
282         glBindTexture(GL_TEXTURE_2D, tex2);
283         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
284 
285         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
286         glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
287         glClear(GL_COLOR_BUFFER_BIT);
288 
289         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
290         ASSERT_GL_NO_ERROR();
291 
292         // Test texture contents.
293         glBindFramebuffer(GL_FRAMEBUFFER, 0);
294         draw2DTexturedQuad(0.0f, 1.0f, true);
295         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
296 
297         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
298         glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
299         glClear(GL_COLOR_BUFFER_BIT);
300 
301         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
302         ASSERT_GL_NO_ERROR();
303 
304         glBindFramebuffer(GL_FRAMEBUFFER, 0);
305         draw2DTexturedQuad(0.0f, 1.0f, true);
306         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
307     }
308 
309     // Test glCopyTexSubImage3D.
310     {
311         GLTexture tex2;
312         glBindTexture(GL_TEXTURE_3D, tex2);
313         glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
314 
315         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
316         glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
317         glClear(GL_COLOR_BUFFER_BIT);
318         glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
319         ASSERT_GL_NO_ERROR();
320 
321         glBindFramebuffer(GL_FRAMEBUFFER, 0);
322         draw3DTexturedQuad(0.0f, 1.0f, true, 0.0f);
323         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
324     }
325 }
326 
327 // Test that glBlitFramebuffer succeeds if the current read framebuffer has just one layered view.
TEST_P(FramebufferMultiviewTest,Blit)328 TEST_P(FramebufferMultiviewTest, Blit)
329 {
330     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
331 
332     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
333     glClear(GL_COLOR_BUFFER_BIT);
334 
335     GLFramebuffer fbo;
336     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
337 
338     GLTexture tex;
339     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
340     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
341 
342     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
343     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
344     ASSERT_GL_NO_ERROR();
345 
346     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
347     glClear(GL_COLOR_BUFFER_BIT);
348 
349     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
350     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
351     glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
352     ASSERT_GL_NO_ERROR();
353 
354     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
355     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
356 }
357 
358 // Test that glReadPixels succeeds from a layered multiview framebuffer with just one view.
TEST_P(FramebufferMultiviewTest,ReadPixels)359 TEST_P(FramebufferMultiviewTest, ReadPixels)
360 {
361     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
362 
363     GLFramebuffer fbo;
364     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
365 
366     GLTexture tex;
367     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
368     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
369 
370     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 1);
371     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
372     ASSERT_GL_NO_ERROR();
373 
374     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
375     glClear(GL_COLOR_BUFFER_BIT);
376 
377     GLColor pixelColor;
378     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor.R);
379     ASSERT_GL_NO_ERROR();
380     EXPECT_COLOR_NEAR(GLColor::green, pixelColor, 2);
381 }
382 
383 // Test that glFramebufferTextureMultiviewOVR modifies the internal multiview state.
TEST_P(FramebufferMultiviewTest,ModifyLayeredState)384 TEST_P(FramebufferMultiviewTest, ModifyLayeredState)
385 {
386     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
387 
388     GLFramebuffer multiviewFBO;
389     glBindFramebuffer(GL_FRAMEBUFFER, multiviewFBO);
390 
391     GLTexture tex;
392     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
393     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
394     ASSERT_GL_NO_ERROR();
395 
396     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1, 2);
397     ASSERT_GL_NO_ERROR();
398 
399     GLint numViews = -1;
400     glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
401                                           GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR,
402                                           &numViews);
403     ASSERT_GL_NO_ERROR();
404     EXPECT_EQ(2, numViews);
405 
406     GLint baseViewIndex = -1;
407     glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
408                                           GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR,
409                                           &baseViewIndex);
410     ASSERT_GL_NO_ERROR();
411     EXPECT_EQ(1, baseViewIndex);
412 }
413 
414 // Test framebuffer completeness status of a layered framebuffer with color attachments.
TEST_P(FramebufferMultiviewTest,IncompleteViewTargetsLayered)415 TEST_P(FramebufferMultiviewTest, IncompleteViewTargetsLayered)
416 {
417     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
418 
419     GLFramebuffer fbo;
420     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
421 
422     GLTexture tex;
423     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
424     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
425 
426     // Set the 0th attachment and keep it as it is till the end of the test. The 1st color
427     // attachment will be modified to change the framebuffer's status.
428     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
429     ASSERT_GL_NO_ERROR();
430 
431     GLTexture otherTexLayered;
432     glBindTexture(GL_TEXTURE_2D_ARRAY, otherTexLayered);
433     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
434 
435     // Test framebuffer completeness when the base view index differs.
436     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 1,
437                                      2);
438     ASSERT_GL_NO_ERROR();
439     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
440                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
441 
442     // Test framebuffer completeness when the 1st attachment has a non-multiview layout.
443     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
444     ASSERT_GL_NO_ERROR();
445     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
446                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
447 
448     // Test that framebuffer is complete when the number of views, base view index and layouts are
449     // the same.
450     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0,
451                                      2);
452     ASSERT_GL_NO_ERROR();
453     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
454 }
455 
456 // Test that glClear clears the contents of the color buffer for only the attached layers to a
457 // layered FBO.
TEST_P(FramebufferMultiviewLayeredClearTest,ColorBufferClear)458 TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
459 {
460     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
461 
462     initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
463 
464     // Bind and specify viewport/scissor dimensions for each view.
465     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
466 
467     glClearColor(0, 1, 0, 1);
468     glClear(GL_COLOR_BUFFER_BIT);
469 
470     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
471     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
472     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
473     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
474 }
475 
476 // Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
TEST_P(FramebufferMultiviewLayeredClearTest,ClearIndividualColorBuffer)477 TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
478 {
479     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
480 
481     initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
482 
483     for (int i = 0; i < 2; ++i)
484     {
485         for (int layer = 0; layer < 4; ++layer)
486         {
487             GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
488             EXPECT_EQ(GLColor::transparentBlack, getLayerColor(layer, colorAttachment));
489         }
490     }
491 
492     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
493 
494     float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
495     glClearBufferfv(GL_COLOR, 0, clearValues0);
496 
497     float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
498     glClearBufferfv(GL_COLOR, 1, clearValues1);
499 
500     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
501     EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
502     EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
503     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
504 
505     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
506     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
507     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
508     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
509 }
510 
511 // Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
512 // to a layered FBO.
TEST_P(FramebufferMultiviewLayeredClearTest,ClearBufferfi)513 TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
514 {
515     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
516 
517     // Create program to draw a quad.
518     constexpr char kVS[] =
519         "#version 300 es\n"
520         "in vec3 vPos;\n"
521         "void main(){\n"
522         "   gl_Position = vec4(vPos, 1.);\n"
523         "}\n";
524     constexpr char kFS[] =
525         "#version 300 es\n"
526         "precision mediump float;\n"
527         "uniform vec3 uCol;\n"
528         "out vec4 col;\n"
529         "void main(){\n"
530         "   col = vec4(uCol,1.);\n"
531         "}\n";
532     ANGLE_GL_PROGRAM(program, kVS, kFS);
533     glUseProgram(program);
534     GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
535 
536     initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
537     glEnable(GL_STENCIL_TEST);
538     glDisable(GL_DEPTH_TEST);
539 
540     // Set clear values.
541     glClearColor(1, 0, 0, 1);
542     glClearStencil(0xFF);
543 
544     // Clear the color and stencil buffers of each layer.
545     for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
546     {
547         glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
548         glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
549     }
550 
551     // Switch to multiview framebuffer and clear portions of the texture.
552     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
553     glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
554 
555     // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
556     // the test.
557     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
558     glStencilFunc(GL_EQUAL, 0x00, 0xFF);
559     for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
560     {
561         glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
562         glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
563         drawQuad(program, "vPos", 0.0f, 1.0f, true);
564     }
565     EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
566     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
567     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
568     EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
569 }
570 
571 // Test that glClear does not clear the content of a detached texture.
TEST_P(FramebufferMultiviewLayeredClearTest,UnmodifiedDetachedTexture)572 TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
573 {
574     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
575 
576     initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
577 
578     // Clear all attachments.
579     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
580     glClearColor(0, 1, 0, 1);
581     glClear(GL_COLOR_BUFFER_BIT);
582 
583     for (int i = 0; i < 2; ++i)
584     {
585         GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
586         EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, colorAttachment));
587         EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
588         EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
589         EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, colorAttachment));
590     }
591 
592     // Detach and clear again.
593     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
594     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
595     glClearColor(1, 1, 0, 1);
596     glClear(GL_COLOR_BUFFER_BIT);
597 
598     // Check that color attachment 0 is modified.
599     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
600     EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
601     EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
602     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
603 
604     // Check that color attachment 1 is unmodified.
605     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
606     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
607     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
608     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
609 }
610 
611 // Test that glClear clears only the contents within the scissor rectangle of the attached layers.
TEST_P(FramebufferMultiviewLayeredClearTest,ScissoredClear)612 TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
613 {
614     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
615 
616     initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
617 
618     // Bind and specify viewport/scissor dimensions for each view.
619     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
620 
621     glEnable(GL_SCISSOR_TEST);
622     glScissor(1, 0, 1, 1);
623     glClearColor(0, 1, 0, 1);
624     glClear(GL_COLOR_BUFFER_BIT);
625 
626     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
627     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
628 
629     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
630     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
631 
632     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
633     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
634 
635     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
636     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
637 }
638 
639 // Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
640 // to a layered FBO.
TEST_P(FramebufferMultiviewLayeredClearTest,ScissoredClearBufferfi)641 TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
642 {
643     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
644 
645     // Create program to draw a quad.
646     constexpr char kVS[] =
647         "#version 300 es\n"
648         "in vec3 vPos;\n"
649         "void main(){\n"
650         "   gl_Position = vec4(vPos, 1.);\n"
651         "}\n";
652     constexpr char kFS[] =
653         "#version 300 es\n"
654         "precision mediump float;\n"
655         "uniform vec3 uCol;\n"
656         "out vec4 col;\n"
657         "void main(){\n"
658         "   col = vec4(uCol,1.);\n"
659         "}\n";
660     ANGLE_GL_PROGRAM(program, kVS, kFS);
661     glUseProgram(program);
662     GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
663 
664     initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
665     glEnable(GL_STENCIL_TEST);
666     glDisable(GL_DEPTH_TEST);
667 
668     // Set clear values.
669     glClearColor(1, 0, 0, 1);
670     glClearStencil(0xFF);
671 
672     // Clear the color and stencil buffers of each layer.
673     for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
674     {
675         glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
676         glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
677     }
678 
679     // Switch to multiview framebuffer and clear portions of the texture.
680     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
681     glEnable(GL_SCISSOR_TEST);
682     glScissor(0, 0, 1, 1);
683     glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
684     glDisable(GL_SCISSOR_TEST);
685 
686     // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
687     // the test.
688     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
689     glStencilFunc(GL_EQUAL, 0x00, 0xFF);
690     glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
691     for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
692     {
693         glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
694         drawQuad(program, "vPos", 0.0f, 1.0f, true);
695     }
696     EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
697     EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
698     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
699     EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
700     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
701     EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
702     EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
703     EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
704 }
705 
706 // Test that detaching an attachment does not generate an error whenever the multi-view related
707 // arguments are invalid.
TEST_P(FramebufferMultiviewTest,InvalidMultiviewArgumentsOnDetach)708 TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
709 {
710     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
711 
712     GLFramebuffer fbo;
713     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
714 
715     // Invalid base view index.
716     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
717     EXPECT_GL_NO_ERROR();
718 
719     // Invalid number of views.
720     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
721     EXPECT_GL_NO_ERROR();
722 }
723 
724 // Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
725 // array are attached. The test is added because a special fast code path is used for this case.
TEST_P(FramebufferMultiviewLayeredClearTest,ColorBufferClearAllLayersAttached)726 TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
727 {
728     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
729 
730     initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
731 
732     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
733     glClearColor(0, 1, 0, 1);
734     glClear(GL_COLOR_BUFFER_BIT);
735 
736     EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
737     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
738 }
739 
740 // Test that attaching a multisampled texture array is not possible if all the required extensions
741 // are not enabled.
TEST_P(FramebufferMultiviewTest,NegativeMultisampledFramebufferTest)742 TEST_P(FramebufferMultiviewTest, NegativeMultisampledFramebufferTest)
743 {
744     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
745 
746     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"));
747 
748     // We don't enable OVR_multiview2_multisample
749 
750     GLTexture multisampleTexture;
751     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, multisampleTexture);
752 
753     GLFramebuffer fbo;
754     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
755     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, multisampleTexture, 0, 0,
756                                      2);
757     // From the extension spec: "An INVALID_OPERATION error is generated if texture is not zero, and
758     // does not name an existing texture object of type TEXTURE_2D_ARRAY."
759     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
760 }
761 
762 ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest,
763                        VertexShaderOpenGL(3, 0, ExtensionName::multiview),
764                        GeomShaderD3D11(3, 0, ExtensionName::multiview),
765                        VertexShaderOpenGL(3, 0, ExtensionName::multiview2),
766                        GeomShaderD3D11(3, 0, ExtensionName::multiview2));
767 ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest,
768                        VertexShaderOpenGL(3, 0, ExtensionName::multiview),
769                        GeomShaderD3D11(3, 0, ExtensionName::multiview),
770                        VertexShaderOpenGL(3, 0, ExtensionName::multiview2),
771                        GeomShaderD3D11(3, 0, ExtensionName::multiview2));
772