• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 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 
7 // MultisampledRenderToTextureTest: Tests of EXT_multisampled_render_to_texture extension
8 
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11 
12 using namespace angle;
13 
14 namespace
15 {
16 constexpr char kBasicVertexShader[] =
17     R"(attribute vec3 position;
18 void main()
19 {
20     gl_Position = vec4(position, 1);
21 })";
22 
23 constexpr char kGreenFragmentShader[] =
24     R"(void main()
25 {
26     gl_FragColor = vec4(0, 1, 0, 1);
27 })";
28 
29 constexpr char kRedFragmentShader[] =
30     R"(void main()
31 {
32     gl_FragColor = vec4(1, 0, 0, 1);
33 })";
34 
35 constexpr char kVS[] =
36     "precision highp float;\n"
37     "attribute vec4 position;\n"
38     "varying vec2 texcoord;\n"
39     "\n"
40     "void main()\n"
41     "{\n"
42     "    gl_Position = position;\n"
43     "    texcoord = (position.xy * 0.5) + 0.5;\n"
44     "}\n";
45 
46 constexpr char kFS[] =
47     "precision highp float;\n"
48     "uniform sampler2D tex;\n"
49     "varying vec2 texcoord;\n"
50     "\n"
51     "void main()\n"
52     "{\n"
53     "    gl_FragColor = texture2D(tex, texcoord);\n"
54     "}\n";
55 
56 class MultisampledRenderToTextureTest : public ANGLETest
57 {
58   protected:
MultisampledRenderToTextureTest()59     MultisampledRenderToTextureTest()
60     {
61         setWindowWidth(64);
62         setWindowHeight(64);
63         setConfigRedBits(8);
64         setConfigGreenBits(8);
65         setConfigBlueBits(8);
66         setConfigAlphaBits(8);
67     }
68 
testSetUp()69     void testSetUp() override {}
70 
testTearDown()71     void testTearDown() override {}
72 
setupCopyTexProgram()73     void setupCopyTexProgram()
74     {
75         mCopyTextureProgram.makeRaster(kVS, kFS);
76         ASSERT_GL_TRUE(mCopyTextureProgram.valid());
77 
78         mCopyTextureUniformLocation = glGetUniformLocation(mCopyTextureProgram, "tex");
79 
80         ASSERT_GL_NO_ERROR();
81     }
82 
verifyResults(GLuint texture,GLubyte data[4],GLint fboSize,GLint xs,GLint ys,GLint xe,GLint ye)83     void verifyResults(GLuint texture,
84                        GLubyte data[4],
85                        GLint fboSize,
86                        GLint xs,
87                        GLint ys,
88                        GLint xe,
89                        GLint ye)
90     {
91         glViewport(0, 0, fboSize, fboSize);
92 
93         glBindFramebuffer(GL_FRAMEBUFFER, 0);
94 
95         // Draw a quad with the target texture
96         glUseProgram(mCopyTextureProgram);
97         glBindTexture(GL_TEXTURE_2D, texture);
98         glUniform1i(mCopyTextureUniformLocation, 0);
99 
100         drawQuad(mCopyTextureProgram, "position", 0.5f);
101 
102         // Expect that the rendered quad has the same color as the source texture
103         EXPECT_PIXEL_NEAR(xs, ys, data[0], data[1], data[2], data[3], 1.0);
104         EXPECT_PIXEL_NEAR(xs, ye - 1, data[0], data[1], data[2], data[3], 1.0);
105         EXPECT_PIXEL_NEAR(xe - 1, ys, data[0], data[1], data[2], data[3], 1.0);
106         EXPECT_PIXEL_NEAR(xe - 1, ye - 1, data[0], data[1], data[2], data[3], 1.0);
107         EXPECT_PIXEL_NEAR((xs + xe) / 2, (ys + ye) / 2, data[0], data[1], data[2], data[3], 1.0);
108     }
109 
clearAndDrawQuad(GLuint program,GLsizei viewportWidth,GLsizei viewportHeight)110     void clearAndDrawQuad(GLuint program, GLsizei viewportWidth, GLsizei viewportHeight)
111     {
112         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
113         glClear(GL_COLOR_BUFFER_BIT);
114         glViewport(0, 0, viewportWidth, viewportHeight);
115         ASSERT_GL_NO_ERROR();
116 
117         drawQuad(program, "position", 0.0f);
118     }
119 
120     GLProgram mCopyTextureProgram;
121     GLint mCopyTextureUniformLocation = -1;
122 };
123 
124 class MultisampledRenderToTextureES3Test : public MultisampledRenderToTextureTest
125 {};
126 
127 // Checking against invalid parameters for RenderbufferStorageMultisampleEXT.
TEST_P(MultisampledRenderToTextureTest,RenderbufferParameterCheck)128 TEST_P(MultisampledRenderToTextureTest, RenderbufferParameterCheck)
129 {
130     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
131 
132     GLRenderbuffer renderbuffer;
133     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
134 
135     // Positive test case
136     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, 64, 64);
137     ASSERT_GL_NO_ERROR();
138 
139     GLint samples;
140     glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples);
141     ASSERT_GL_NO_ERROR();
142     EXPECT_GE(samples, 1);
143 
144     // Samples too large
145     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples + 1, GL_DEPTH_COMPONENT16, 64, 64);
146     ASSERT_GL_ERROR(GL_INVALID_VALUE);
147 
148     // Renderbuffer size too large
149     GLint maxSize;
150     glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize);
151     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT16, maxSize + 1,
152                                         maxSize);
153     ASSERT_GL_ERROR(GL_INVALID_VALUE);
154     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT16, maxSize,
155                                         maxSize + 1);
156     ASSERT_GL_ERROR(GL_INVALID_VALUE);
157 
158     // Retrieving samples
159     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, 64, 64);
160     GLint param = 0;
161     glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES_EXT, &param);
162     // GE because samples may vary base on implementation. Spec says "the resulting value for
163     // RENDERBUFFER_SAMPLES_EXT is guaranteed to be greater than or equal to samples and no more
164     // than the next larger sample count supported by the implementation"
165     EXPECT_GE(param, 4);
166 }
167 
168 // Checking against invalid parameters for FramebufferTexture2DMultisampleEXT.
TEST_P(MultisampledRenderToTextureTest,Texture2DParameterCheck)169 TEST_P(MultisampledRenderToTextureTest, Texture2DParameterCheck)
170 {
171     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
172 
173     GLTexture texture;
174     glBindTexture(GL_TEXTURE_2D, texture);
175     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
176     ASSERT_GL_NO_ERROR();
177 
178     GLFramebuffer fbo;
179     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
180     // Positive test case
181     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
182                                          texture, 0, 4);
183     ASSERT_GL_NO_ERROR();
184 
185     // Attachment not COLOR_ATTACHMENT0
186     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
187                                          texture, 0, 4);
188     ASSERT_GL_ERROR(GL_INVALID_ENUM);
189 
190     // Target not framebuffer
191     glFramebufferTexture2DMultisampleEXT(GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
192                                          texture, 0, 4);
193     ASSERT_GL_ERROR(GL_INVALID_ENUM);
194 
195     GLint samples;
196     glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples);
197     ASSERT_GL_NO_ERROR();
198     EXPECT_GE(samples, 1);
199 
200     // Samples too large
201     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
202                                          texture, 0, samples + 1);
203     ASSERT_GL_ERROR(GL_INVALID_VALUE);
204 
205     // Retrieving samples
206     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
207                                          texture, 0, 4);
208     GLint param = 0;
209     glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
210                                           GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT, &param);
211     // GE because samples may vary base on implementation. Spec says "the resulting value for
212     // TEXTURE_SAMPLES_EXT is guaranteed to be greater than or equal to samples and no more than the
213     // next larger sample count supported by the implementation"
214     EXPECT_GE(param, 4);
215 }
216 
217 // Checking against invalid parameters for FramebufferTexture2DMultisampleEXT (cubemap).
TEST_P(MultisampledRenderToTextureTest,TextureCubeMapParameterCheck)218 TEST_P(MultisampledRenderToTextureTest, TextureCubeMapParameterCheck)
219 {
220     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
221 
222     GLTexture texture;
223     glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
224     for (GLenum face = 0; face < 6; face++)
225     {
226         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, 64, 64, 0, GL_RGBA,
227                      GL_UNSIGNED_BYTE, nullptr);
228         ASSERT_GL_NO_ERROR();
229     }
230 
231     GLint samples;
232     glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples);
233     ASSERT_GL_NO_ERROR();
234     EXPECT_GE(samples, 1);
235 
236     GLFramebuffer FBO;
237     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
238     for (GLenum face = 0; face < 6; face++)
239     {
240         // Positive test case
241         glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
242                                              GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0, 4);
243         ASSERT_GL_NO_ERROR();
244 
245         // Attachment not COLOR_ATTACHMENT0
246         glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
247                                              GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0, 4);
248         ASSERT_GL_ERROR(GL_INVALID_ENUM);
249 
250         // Target not framebuffer
251         glFramebufferTexture2DMultisampleEXT(GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0,
252                                              GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0, 4);
253         ASSERT_GL_ERROR(GL_INVALID_ENUM);
254 
255         // Samples too large
256         glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
257                                              GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0,
258                                              samples + 1);
259         ASSERT_GL_ERROR(GL_INVALID_VALUE);
260 
261         // Retrieving samples
262         glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
263                                              GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture, 0, 4);
264         GLint param = 0;
265         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
266                                               GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT,
267                                               &param);
268         // GE because samples may vary base on implementation. Spec says "the resulting value for
269         // TEXTURE_SAMPLES_EXT is guaranteed to be greater than or equal to samples and no more than
270         // the next larger sample count supported by the implementation"
271         EXPECT_GE(param, 4);
272     }
273 }
274 
275 // Checking for framebuffer completeness using extension methods.
TEST_P(MultisampledRenderToTextureTest,FramebufferCompleteness)276 TEST_P(MultisampledRenderToTextureTest, FramebufferCompleteness)
277 {
278     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
279 
280     // Checking that Renderbuffer and texture2d having different number of samples results
281     // in a FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
282     GLTexture texture;
283     glBindTexture(GL_TEXTURE_2D, texture);
284     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
285     ASSERT_GL_NO_ERROR();
286 
287     GLFramebuffer FBO;
288     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
289     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
290                                          texture, 0, 4);
291     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
292 
293     GLRenderbuffer renderbuffer;
294     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
295     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 8, GL_DEPTH_COMPONENT16, 64, 64);
296     ASSERT_GL_NO_ERROR();
297     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
298     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
299                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
300 }
301 
302 // Draw test with color attachment only.
303 TEST_P(MultisampledRenderToTextureTest, 2DColorAttachmentMultisampleDrawTest)
304 {
305     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
306     // Set up texture and bind to FBO
307     GLsizei size = 6;
308     GLTexture texture;
309     glBindTexture(GL_TEXTURE_2D, texture);
310     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
311     ASSERT_GL_NO_ERROR();
312 
313     GLFramebuffer FBO;
314     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
315     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
316                                          texture, 0, 4);
317     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
318 
319     // Set viewport and clear to black
320     glViewport(0, 0, size, size);
321     glClearColor(0.0, 0.0, 0.0, 1.0);
322     glClear(GL_COLOR_BUFFER_BIT);
323 
324     // Set up Green square program
325     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
326     glUseProgram(program);
327     GLint positionLocation = glGetAttribLocation(program, "position");
328     ASSERT_NE(-1, positionLocation);
329 
330     setupQuadVertexBuffer(0.5f, 0.5f);
331     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
332     glEnableVertexAttribArray(positionLocation);
333 
334     // Draw green square
335     glDrawArrays(GL_TRIANGLES, 0, 6);
336     ASSERT_GL_NO_ERROR();
337 
338     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
339     EXPECT_PIXEL_COLOR_EQ(size / 2, size / 2, GLColor::green);
340 
341     // Set up Red square program
342     ANGLE_GL_PROGRAM(program2, kBasicVertexShader, kRedFragmentShader);
343     glUseProgram(program2);
344     GLint positionLocation2 = glGetAttribLocation(program2, "position");
345     ASSERT_NE(-1, positionLocation2);
346 
347     setupQuadVertexBuffer(0.5f, 0.75f);
348     glVertexAttribPointer(positionLocation2, 3, GL_FLOAT, GL_FALSE, 0, 0);
349 
350     // Draw red square
351     glDrawArrays(GL_TRIANGLES, 0, 6);
352     ASSERT_GL_NO_ERROR();
353 
354     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
355     EXPECT_PIXEL_COLOR_EQ(size / 2, size / 2, GLColor::red);
356 
357     glDisableVertexAttribArray(0);
358     glBindBuffer(GL_ARRAY_BUFFER, 0);
359 }
360 
361 // Draw test using both color and depth attachments.
362 TEST_P(MultisampledRenderToTextureTest, 2DColorDepthMultisampleDrawTest)
363 {
364     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
365     GLsizei size = 6;
366     // create complete framebuffer with depth buffer
367     GLTexture texture;
368     glBindTexture(GL_TEXTURE_2D, texture);
369     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
370     ASSERT_GL_NO_ERROR();
371 
372     GLFramebuffer FBO;
373     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
374     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
375                                          texture, 0, 4);
376 
377     GLRenderbuffer renderbuffer;
378     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
379     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, size, size);
380     ASSERT_GL_NO_ERROR();
381     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
382     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
383 
384     // Set viewport and clear framebuffer
385     glViewport(0, 0, size, size);
386     glClearColor(0.0, 0.0, 0.0, 1.0);
387     glClearDepthf(0.5f);
388     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
389 
390     // Draw first green square
391     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
392     glEnable(GL_DEPTH_TEST);
393     glDepthFunc(GL_GREATER);
394     glUseProgram(program);
395     GLint positionLocation = glGetAttribLocation(program, "position");
396     ASSERT_NE(-1, positionLocation);
397 
398     setupQuadVertexBuffer(0.8f, 0.5f);
399     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
400     glEnableVertexAttribArray(positionLocation);
401 
402     // Tests that TRIANGLES works.
403     glDrawArrays(GL_TRIANGLES, 0, 6);
404     ASSERT_GL_NO_ERROR();
405 
406     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
407     EXPECT_PIXEL_COLOR_EQ(size / 2, size / 2, GLColor::green);
408 
409     // Draw red square behind green square
410     ANGLE_GL_PROGRAM(program2, kBasicVertexShader, kRedFragmentShader);
411     glUseProgram(program2);
412     GLint positionLocation2 = glGetAttribLocation(program2, "position");
413     ASSERT_NE(-1, positionLocation2);
414 
415     setupQuadVertexBuffer(0.7f, 1.0f);
416     glVertexAttribPointer(positionLocation2, 3, GL_FLOAT, GL_FALSE, 0, 0);
417 
418     glDrawArrays(GL_TRIANGLES, 0, 6);
419     ASSERT_GL_NO_ERROR();
420     glDisable(GL_DEPTH_TEST);
421 
422     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
423     EXPECT_PIXEL_COLOR_EQ(size / 2, size / 2, GLColor::green);
424 
425     glDisableVertexAttribArray(0);
426     glBindBuffer(GL_ARRAY_BUFFER, 0);
427 }
428 
429 // Read pixels with pack buffer. ES3+.
TEST_P(MultisampledRenderToTextureES3Test,MultisampleReadPixelsTest)430 TEST_P(MultisampledRenderToTextureES3Test, MultisampleReadPixelsTest)
431 {
432     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
433 
434     // PBO only available ES3 and above
435     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
436     GLsizei size = 6;
437     GLTexture texture;
438     glBindTexture(GL_TEXTURE_2D, texture);
439     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, size, size);
440     ASSERT_GL_NO_ERROR();
441 
442     GLFramebuffer FBO;
443     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
444     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
445                                          texture, 0, 4);
446     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
447 
448     // Set viewport and clear to red
449     glViewport(0, 0, size, size);
450     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
451     glClear(GL_COLOR_BUFFER_BIT);
452     ASSERT_GL_NO_ERROR();
453 
454     // Bind Pack Pixel Buffer and read to it
455     GLBuffer PBO;
456     glBindBuffer(GL_PIXEL_PACK_BUFFER, PBO);
457     glBufferData(GL_PIXEL_PACK_BUFFER, 4 * size * size, nullptr, GL_STATIC_DRAW);
458     glReadPixels(0, 0, size, size, GL_RGBA, GL_UNSIGNED_BYTE, 0);
459     ASSERT_GL_NO_ERROR();
460 
461     // Retrieving pixel color
462     void *mappedPtr    = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
463     GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
464     EXPECT_GL_NO_ERROR();
465 
466     EXPECT_EQ(GLColor::red, dataColor[0]);
467 
468     glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
469     EXPECT_GL_NO_ERROR();
470 }
471 
472 // CopyTexImage from a multisampled texture functionality test.
TEST_P(MultisampledRenderToTextureTest,MultisampleCopyTexImageTest)473 TEST_P(MultisampledRenderToTextureTest, MultisampleCopyTexImageTest)
474 {
475     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
476     GLsizei size = 16;
477 
478     setupCopyTexProgram();
479     GLTexture texture;
480     glBindTexture(GL_TEXTURE_2D, texture);
481     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
482 
483     // Disable mipmapping
484     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
485     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
486 
487     GLFramebuffer FBO;
488     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
489     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
490                                          texture, 0, 4);
491 
492     // Set color for framebuffer
493     glClearColor(0.25f, 1.0f, 0.75f, 0.5f);
494     glClear(GL_COLOR_BUFFER_BIT);
495     ASSERT_GL_NO_ERROR();
496 
497     GLTexture copyToTex;
498     glBindTexture(GL_TEXTURE_2D, copyToTex);
499 
500     // Disable mipmapping
501     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
502     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
503 
504     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size, size, 0);
505     ASSERT_GL_NO_ERROR();
506 
507     GLubyte expected[4] = {64, 255, 191, 255};
508     verifyResults(copyToTex, expected, size, 0, 0, size, size);
509 }
510 
511 // CopyTexSubImage from a multisampled texture functionality test.
TEST_P(MultisampledRenderToTextureTest,MultisampleCopyTexSubImageTest)512 TEST_P(MultisampledRenderToTextureTest, MultisampleCopyTexSubImageTest)
513 {
514     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
515     GLsizei size = 16;
516 
517     setupCopyTexProgram();
518 
519     GLTexture texture;
520     // Create texture in copyFBO0 with color (.25, 1, .75, .5)
521     glBindTexture(GL_TEXTURE_2D, texture);
522     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
523 
524     // Disable mipmapping
525     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
526     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
527 
528     GLFramebuffer copyFBO0;
529     glBindFramebuffer(GL_FRAMEBUFFER, copyFBO0);
530     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
531                                          texture, 0, 4);
532 
533     // Set color for
534     glClearColor(0.25f, 1.0f, 0.75f, 0.5f);
535     glClear(GL_COLOR_BUFFER_BIT);
536     ASSERT_GL_NO_ERROR();
537 
538     // Create texture in copyFBO[1] with color (1, .75, .5, .25)
539     GLTexture texture1;
540     glBindTexture(GL_TEXTURE_2D, texture1);
541     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
542 
543     // Disable mipmapping
544     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
545     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
546 
547     GLFramebuffer copyFBO1;
548     glBindFramebuffer(GL_FRAMEBUFFER, copyFBO1);
549     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
550                                          texture1, 0, 4);
551 
552     // Set color for
553     glClearColor(1.0f, 0.75f, 0.5f, 0.25f);
554     glClear(GL_COLOR_BUFFER_BIT);
555     ASSERT_GL_NO_ERROR();
556 
557     GLTexture copyToTex;
558     glBindTexture(GL_TEXTURE_2D, copyToTex);
559 
560     // Disable mipmapping
561     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
562     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
563 
564     // copyFBO0 -> copyToTex
565     // copyToTex should hold what was originally in copyFBO0 : (.25, 1, .75, .5)
566     glBindFramebuffer(GL_FRAMEBUFFER, copyFBO0);
567     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size, size, 0);
568     ASSERT_GL_NO_ERROR();
569 
570     GLubyte expected0[4] = {64, 255, 191, 255};
571     verifyResults(copyToTex, expected0, size, 0, 0, size, size);
572 
573     // copyFBO[1] - copySubImage -> copyToTex
574     // copyToTex should have subportion what was in copyFBO[1] : (1, .75, .5, .25)
575     // The rest should still be untouched: (.25, 1, .75, .5)
576     GLint half = size / 2;
577     glBindFramebuffer(GL_FRAMEBUFFER, copyFBO1);
578     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, half, half, half, half, half, half);
579     ASSERT_GL_NO_ERROR();
580 
581     GLubyte expected1[4] = {255, 191, 127, 255};
582     verifyResults(copyToTex, expected1, size, half, half, size, size);
583 
584     // Verify rest is untouched
585     verifyResults(copyToTex, expected0, size, 0, 0, half, half);
586     verifyResults(copyToTex, expected0, size, 0, half, half, size);
587     verifyResults(copyToTex, expected0, size, half, 0, size, half);
588 }
589 
590 // BlitFramebuffer functionality test. ES3+.
TEST_P(MultisampledRenderToTextureES3Test,MultisampleBlitFramebufferTest)591 TEST_P(MultisampledRenderToTextureES3Test, MultisampleBlitFramebufferTest)
592 {
593     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
594     // blitFramebuffer only available ES3 and above
595     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
596 
597     GLsizei size = 16;
598 
599     // Create multisampled framebuffer to use as source.
600     GLRenderbuffer depthMS;
601     glBindRenderbuffer(GL_RENDERBUFFER, depthMS.get());
602     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT24, size, size);
603 
604     GLTexture colorMS;
605     glBindTexture(GL_TEXTURE_2D, colorMS);
606     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
607 
608     GLFramebuffer fboMS;
609     glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
610     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthMS.get());
611     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
612                                          colorMS, 0, 4);
613     ASSERT_GL_NO_ERROR();
614 
615     // Clear depth to 0.5 and color to green.
616     glClearDepthf(0.5f);
617     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
618     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
619     glFlush();
620     ASSERT_GL_NO_ERROR();
621 
622     // Draw red into the multisampled color buffer.
623     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
624     glEnable(GL_DEPTH_TEST);
625     glDepthFunc(GL_EQUAL);
626     drawQuad(drawRed.get(), essl1_shaders::PositionAttrib(), 0.0f);
627     ASSERT_GL_NO_ERROR();
628 
629     // Create single sampled framebuffer to use as dest.
630     GLFramebuffer fboSS;
631     glBindFramebuffer(GL_FRAMEBUFFER, fboSS);
632     GLTexture colorSS;
633     glBindTexture(GL_TEXTURE_2D, colorSS);
634     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
635     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorSS, 0);
636     ASSERT_GL_NO_ERROR();
637 
638     // Bind MS to READ as SS is already bound to DRAW.
639     glBindFramebuffer(GL_READ_FRAMEBUFFER, fboMS.get());
640     glBlitFramebuffer(0, 0, size, size, 0, 0, size, size, GL_COLOR_BUFFER_BIT, GL_NEAREST);
641     ASSERT_GL_NO_ERROR();
642 
643     // Bind SS to READ so we can readPixels from it
644     glBindFramebuffer(GL_FRAMEBUFFER, fboSS.get());
645 
646     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
647     EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::red);
648     EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::red);
649     EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::red);
650     EXPECT_PIXEL_COLOR_EQ(size / 2, size / 2, GLColor::red);
651     ASSERT_GL_NO_ERROR();
652 }
653 
654 // GenerateMipmap functionality test
TEST_P(MultisampledRenderToTextureTest,MultisampleGenerateMipmapTest)655 TEST_P(MultisampledRenderToTextureTest, MultisampleGenerateMipmapTest)
656 {
657     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
658     GLsizei size = 64;
659     // Vertex Shader source
660     constexpr char kVS[] = R"(attribute vec4 position;
661 varying vec2 vTexCoord;
662 
663 void main()
664 {
665     gl_Position = position;
666     vTexCoord   = (position.xy * 0.5) + 0.5;
667 })";
668 
669     // Fragment Shader source
670     constexpr char kFS[] = R"(precision mediump float;
671 uniform sampler2D uTexture;
672 varying vec2 vTexCoord;
673 
674 void main()
675 {
676     gl_FragColor = texture2D(uTexture, vTexCoord);
677 })";
678 
679     GLProgram m2DProgram;
680     m2DProgram.makeRaster(kVS, kFS);
681     ASSERT_GL_TRUE(m2DProgram.valid());
682 
683     ASSERT_GL_NO_ERROR();
684 
685     // Initialize texture with blue
686     GLTexture texture;
687     glBindTexture(GL_TEXTURE_2D, texture);
688     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
689     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
690     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
691 
692     GLFramebuffer FBO;
693     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
694     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
695                                          texture, 0, 4);
696     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
697     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
698     glClear(GL_COLOR_BUFFER_BIT);
699     glViewport(0, 0, size, size);
700     glBindFramebuffer(GL_FRAMEBUFFER, 0);
701     ASSERT_GL_NO_ERROR();
702 
703     // Generate mipmap
704     glGenerateMipmap(GL_TEXTURE_2D);
705     ASSERT_GL_NO_ERROR();
706 
707     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
708 
709     // Now draw the texture to various different sized areas.
710     clearAndDrawQuad(m2DProgram, size, size);
711     EXPECT_PIXEL_COLOR_EQ(size / 2, size / 2, GLColor::blue);
712 
713     // Use mip level 1
714     clearAndDrawQuad(m2DProgram, size / 2, size / 2);
715     EXPECT_PIXEL_COLOR_EQ(size / 4, size / 4, GLColor::blue);
716 
717     // Use mip level 2
718     clearAndDrawQuad(m2DProgram, size / 4, size / 4);
719     EXPECT_PIXEL_COLOR_EQ(size / 8, size / 8, GLColor::blue);
720 
721     ASSERT_GL_NO_ERROR();
722 }
723 ANGLE_INSTANTIATE_TEST(MultisampledRenderToTextureTest,
724                        ES2_D3D9(),
725                        ES2_D3D11(),
726                        ES3_D3D11(),
727                        ES2_OPENGL(),
728                        ES3_OPENGL(),
729                        ES2_OPENGLES(),
730                        ES3_OPENGLES(),
731                        ES2_VULKAN(),
732                        ES3_VULKAN());
733 ANGLE_INSTANTIATE_TEST(MultisampledRenderToTextureES3Test,
734                        ES3_D3D11(),
735                        ES3_OPENGL(),
736                        ES3_OPENGLES(),
737                        ES3_VULKAN());
738 }  // namespace
739