xref: /aosp_15_r20/external/angle/src/tests/gl_tests/FramebufferMultiviewTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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/42262501
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_GL_FRAMEBUFFER_COMPLETE(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_GL_FRAMEBUFFER_COMPLETE(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_GL_FRAMEBUFFER_COMPLETE(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 1st attachment has a non-multiview layout.
436     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0);
437     ASSERT_GL_NO_ERROR();
438     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
439                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
440 
441     // Test that framebuffer is complete when the base view index differs.
442     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 1,
443                                      2);
444     ASSERT_GL_NO_ERROR();
445     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
446 
447     // Test framebuffer completeness when an attachment's base+count layers is beyond the texture
448     // layers.
449     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 3,
450                                      2);
451     ASSERT_GL_NO_ERROR();
452     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
453                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
454 
455     // Test that framebuffer is complete when the number of views, base view index and layouts are
456     // the same.
457     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, otherTexLayered, 0, 0,
458                                      2);
459     ASSERT_GL_NO_ERROR();
460     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
461 }
462 
463 // Test that glClear clears the contents of the color buffer for only the attached layers to a
464 // layered FBO.
TEST_P(FramebufferMultiviewLayeredClearTest,ColorBufferClear)465 TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClear)
466 {
467     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
468 
469     initializeFBOs(1, 1, 4, 1, 2, 1, false, false);
470 
471     // Bind and specify viewport/scissor dimensions for each view.
472     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
473 
474     glClearColor(0, 1, 0, 1);
475     glClear(GL_COLOR_BUFFER_BIT);
476 
477     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
478     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
479     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
480     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
481 }
482 
483 // Test that glClearBufferfv can be used to clear individual color buffers of a layered FBO.
TEST_P(FramebufferMultiviewLayeredClearTest,ClearIndividualColorBuffer)484 TEST_P(FramebufferMultiviewLayeredClearTest, ClearIndividualColorBuffer)
485 {
486     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
487 
488     initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
489 
490     for (int i = 0; i < 2; ++i)
491     {
492         for (int layer = 0; layer < 4; ++layer)
493         {
494             GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
495             EXPECT_EQ(GLColor::transparentBlack, getLayerColor(layer, colorAttachment));
496         }
497     }
498 
499     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
500 
501     float clearValues0[4] = {0.f, 0.f, 1.f, 1.f};
502     glClearBufferfv(GL_COLOR, 0, clearValues0);
503 
504     float clearValues1[4] = {0.f, 1.f, 0.f, 1.f};
505     glClearBufferfv(GL_COLOR, 1, clearValues1);
506 
507     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
508     EXPECT_EQ(GLColor::blue, getLayerColor(1, GL_COLOR_ATTACHMENT0));
509     EXPECT_EQ(GLColor::blue, getLayerColor(2, GL_COLOR_ATTACHMENT0));
510     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
511 
512     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
513     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
514     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
515     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
516 }
517 
518 // Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
519 // to a layered FBO.
TEST_P(FramebufferMultiviewLayeredClearTest,ClearBufferfi)520 TEST_P(FramebufferMultiviewLayeredClearTest, ClearBufferfi)
521 {
522     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
523 
524     // Create program to draw a quad.
525     constexpr char kVS[] =
526         "#version 300 es\n"
527         "in vec3 vPos;\n"
528         "void main(){\n"
529         "   gl_Position = vec4(vPos, 1.);\n"
530         "}\n";
531     constexpr char kFS[] =
532         "#version 300 es\n"
533         "precision mediump float;\n"
534         "uniform vec3 uCol;\n"
535         "out vec4 col;\n"
536         "void main(){\n"
537         "   col = vec4(uCol,1.);\n"
538         "}\n";
539     ANGLE_GL_PROGRAM(program, kVS, kFS);
540     glUseProgram(program);
541     GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
542 
543     initializeFBOs(1, 1, 4, 1, 2, 1, true, false);
544     glEnable(GL_STENCIL_TEST);
545     glDisable(GL_DEPTH_TEST);
546 
547     // Set clear values.
548     glClearColor(1, 0, 0, 1);
549     glClearStencil(0xFF);
550 
551     // Clear the color and stencil buffers of each layer.
552     for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
553     {
554         glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
555         glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
556     }
557 
558     // Switch to multiview framebuffer and clear portions of the texture.
559     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
560     glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
561 
562     // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
563     // the test.
564     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
565     glStencilFunc(GL_EQUAL, 0x00, 0xFF);
566     for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
567     {
568         glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
569         glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
570         drawQuad(program, "vPos", 0.0f, 1.0f, true);
571     }
572     EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0));
573     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
574     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0));
575     EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0));
576 }
577 
578 // Test that glClear does not clear the content of a detached texture.
TEST_P(FramebufferMultiviewLayeredClearTest,UnmodifiedDetachedTexture)579 TEST_P(FramebufferMultiviewLayeredClearTest, UnmodifiedDetachedTexture)
580 {
581     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
582 
583     initializeFBOs(1, 1, 4, 1, 2, 2, false, false);
584 
585     // Clear all attachments.
586     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
587     glClearColor(0, 1, 0, 1);
588     glClear(GL_COLOR_BUFFER_BIT);
589 
590     for (int i = 0; i < 2; ++i)
591     {
592         GLenum colorAttachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
593         EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, colorAttachment));
594         EXPECT_EQ(GLColor::green, getLayerColor(1, colorAttachment));
595         EXPECT_EQ(GLColor::green, getLayerColor(2, colorAttachment));
596         EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, colorAttachment));
597     }
598 
599     // Detach and clear again.
600     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
601     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0, 0, 1, 2);
602     glClearColor(1, 1, 0, 1);
603     glClear(GL_COLOR_BUFFER_BIT);
604 
605     // Check that color attachment 0 is modified.
606     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0));
607     EXPECT_EQ(GLColor::yellow, getLayerColor(1, GL_COLOR_ATTACHMENT0));
608     EXPECT_EQ(GLColor::yellow, getLayerColor(2, GL_COLOR_ATTACHMENT0));
609     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0));
610 
611     // Check that color attachment 1 is unmodified.
612     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT1));
613     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT1));
614     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT1));
615     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT1));
616 }
617 
618 // Test that glClear clears only the contents within the scissor rectangle of the attached layers.
TEST_P(FramebufferMultiviewLayeredClearTest,ScissoredClear)619 TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClear)
620 {
621     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
622 
623     initializeFBOs(2, 1, 4, 1, 2, 1, false, false);
624 
625     // Bind and specify viewport/scissor dimensions for each view.
626     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
627 
628     glEnable(GL_SCISSOR_TEST);
629     glScissor(1, 0, 1, 1);
630     glClearColor(0, 1, 0, 1);
631     glClear(GL_COLOR_BUFFER_BIT);
632 
633     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
634     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(0, GL_COLOR_ATTACHMENT0, 1, 0));
635 
636     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
637     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 1, 0));
638 
639     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
640     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 1, 0));
641 
642     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
643     EXPECT_EQ(GLColor::transparentBlack, getLayerColor(3, GL_COLOR_ATTACHMENT0, 1, 0));
644 }
645 
646 // Test that glClearBufferfi clears the contents of the stencil buffer for only the attached layers
647 // to a layered FBO.
TEST_P(FramebufferMultiviewLayeredClearTest,ScissoredClearBufferfi)648 TEST_P(FramebufferMultiviewLayeredClearTest, ScissoredClearBufferfi)
649 {
650     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
651 
652     // Create program to draw a quad.
653     constexpr char kVS[] =
654         "#version 300 es\n"
655         "in vec3 vPos;\n"
656         "void main(){\n"
657         "   gl_Position = vec4(vPos, 1.);\n"
658         "}\n";
659     constexpr char kFS[] =
660         "#version 300 es\n"
661         "precision mediump float;\n"
662         "uniform vec3 uCol;\n"
663         "out vec4 col;\n"
664         "void main(){\n"
665         "   col = vec4(uCol,1.);\n"
666         "}\n";
667     ANGLE_GL_PROGRAM(program, kVS, kFS);
668     glUseProgram(program);
669     GLuint mColorUniformLoc = glGetUniformLocation(program, "uCol");
670 
671     initializeFBOs(1, 2, 4, 1, 2, 1, true, false);
672     glEnable(GL_STENCIL_TEST);
673     glDisable(GL_DEPTH_TEST);
674 
675     // Set clear values.
676     glClearColor(1, 0, 0, 1);
677     glClearStencil(0xFF);
678 
679     // Clear the color and stencil buffers of each layer.
680     for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
681     {
682         glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
683         glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
684     }
685 
686     // Switch to multiview framebuffer and clear portions of the texture.
687     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
688     glEnable(GL_SCISSOR_TEST);
689     glScissor(0, 0, 1, 1);
690     glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
691     glDisable(GL_SCISSOR_TEST);
692 
693     // Draw a fullscreen quad, but adjust the stencil function so that only the cleared regions pass
694     // the test.
695     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
696     glStencilFunc(GL_EQUAL, 0x00, 0xFF);
697     glUniform3f(mColorUniformLoc, 0.0f, 1.0f, 0.0f);
698     for (size_t i = 0u; i < mNonMultiviewFBO.size(); ++i)
699     {
700         glBindFramebuffer(GL_FRAMEBUFFER, mNonMultiviewFBO[i]);
701         drawQuad(program, "vPos", 0.0f, 1.0f, true);
702     }
703     EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 0));
704     EXPECT_EQ(GLColor::red, getLayerColor(0, GL_COLOR_ATTACHMENT0, 0, 1));
705     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 0));
706     EXPECT_EQ(GLColor::red, getLayerColor(1, GL_COLOR_ATTACHMENT0, 0, 1));
707     EXPECT_EQ(GLColor::green, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 0));
708     EXPECT_EQ(GLColor::red, getLayerColor(2, GL_COLOR_ATTACHMENT0, 0, 1));
709     EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 0));
710     EXPECT_EQ(GLColor::red, getLayerColor(3, GL_COLOR_ATTACHMENT0, 0, 1));
711 }
712 
713 // Test that detaching an attachment does not generate an error whenever the multi-view related
714 // arguments are invalid.
TEST_P(FramebufferMultiviewTest,InvalidMultiviewArgumentsOnDetach)715 TEST_P(FramebufferMultiviewTest, InvalidMultiviewArgumentsOnDetach)
716 {
717     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
718 
719     GLFramebuffer fbo;
720     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
721 
722     // Invalid base view index.
723     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, -1, 1);
724     EXPECT_GL_NO_ERROR();
725 
726     // Invalid number of views.
727     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0);
728     EXPECT_GL_NO_ERROR();
729 }
730 
731 // Test that glClear clears the contents of the color buffer whenever all layers of a 2D texture
732 // array are attached. The test is added because a special fast code path is used for this case.
TEST_P(FramebufferMultiviewLayeredClearTest,ColorBufferClearAllLayersAttached)733 TEST_P(FramebufferMultiviewLayeredClearTest, ColorBufferClearAllLayersAttached)
734 {
735     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
736 
737     initializeFBOs(1, 1, 2, 0, 2, 1, false, false);
738 
739     glBindFramebuffer(GL_FRAMEBUFFER, mMultiviewFBO);
740     glClearColor(0, 1, 0, 1);
741     glClear(GL_COLOR_BUFFER_BIT);
742 
743     EXPECT_EQ(GLColor::green, getLayerColor(0, GL_COLOR_ATTACHMENT0));
744     EXPECT_EQ(GLColor::green, getLayerColor(1, GL_COLOR_ATTACHMENT0));
745 }
746 
747 // Test that attaching a multisampled texture array is not possible if all the required extensions
748 // are not enabled.
TEST_P(FramebufferMultiviewTest,NegativeMultisampledFramebufferTest)749 TEST_P(FramebufferMultiviewTest, NegativeMultisampledFramebufferTest)
750 {
751     ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
752 
753     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_storage_multisample_2d_array"));
754 
755     // We don't enable OVR_multiview2_multisample
756 
757     GLTexture multisampleTexture;
758     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, multisampleTexture);
759 
760     GLFramebuffer fbo;
761     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
762     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, multisampleTexture, 0, 0,
763                                      2);
764     // From the extension spec: "An INVALID_OPERATION error is generated if texture is not zero, and
765     // does not name an existing texture object of type TEXTURE_2D_ARRAY."
766     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
767 }
768 
769 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferMultiviewTest);
770 ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest,
771                        VertexShaderOpenGL(3, 0, ExtensionName::multiview),
772                        VertexShaderVulkan(3, 0, ExtensionName::multiview),
773                        GeomShaderD3D11(3, 0, ExtensionName::multiview),
774                        VertexShaderOpenGL(3, 0, ExtensionName::multiview2),
775                        VertexShaderVulkan(3, 0, ExtensionName::multiview2),
776                        GeomShaderD3D11(3, 0, ExtensionName::multiview2));
777 
778 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferMultiviewLayeredClearTest);
779 ANGLE_INSTANTIATE_TEST(FramebufferMultiviewLayeredClearTest,
780                        VertexShaderOpenGL(3, 0, ExtensionName::multiview),
781                        VertexShaderVulkan(3, 0, ExtensionName::multiview),
782                        GeomShaderD3D11(3, 0, ExtensionName::multiview),
783                        VertexShaderOpenGL(3, 0, ExtensionName::multiview2),
784                        VertexShaderVulkan(3, 0, ExtensionName::multiview2),
785                        GeomShaderD3D11(3, 0, ExtensionName::multiview2));
786