| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include <GLES2/gl2.h> | 
 | #include <GLES2/gl2ext.h> | 
 | #include <GLES2/gl2extchromium.h> | 
 | #include <stdint.h> | 
 |  | 
 | #include "gpu/command_buffer/tests/gl_manager.h" | 
 | #include "gpu/command_buffer/tests/gl_test_utils.h" | 
 | #include "testing/gmock/include/gmock/gmock.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 |  | 
 | namespace gpu { | 
 |  | 
 | class GLChromiumFramebufferMultisampleTest : public testing::Test { | 
 |  protected: | 
 |   void SetUp() override { gl_.Initialize(GLManager::Options()); } | 
 |  | 
 |   void TearDown() override { gl_.Destroy(); } | 
 |  | 
 |   GLManager gl_; | 
 | }; | 
 |  | 
 | // Test that GL is at least minimally working. | 
 | TEST_F(GLChromiumFramebufferMultisampleTest, CachedBindingsTest) { | 
 |   if (!GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample")) { | 
 |     return; | 
 |   } | 
 |  | 
 |   GLuint fbo = 0; | 
 |   glGenFramebuffers(1, &fbo); | 
 |   glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); | 
 |   glBindFramebuffer(GL_FRAMEBUFFER, 0); | 
 |  | 
 |   // If the caching is bad the second call to glBindFramebuffer will do nothing. | 
 |   // which means the draw buffer is bad and will not return | 
 |   // GL_FRAMEBUFFER_COMPLETE and rendering will generate an error. | 
 |   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), | 
 |             glCheckFramebufferStatus(GL_FRAMEBUFFER)); | 
 |  | 
 |   glClear(GL_COLOR_BUFFER_BIT); | 
 |   GLTestHelper::CheckGLError("no errors", __LINE__); | 
 | } | 
 |  | 
 | TEST_F(GLChromiumFramebufferMultisampleTest, DrawAndResolve) { | 
 |   if (!(GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample") && | 
 |         GLTestHelper::HasExtension("GL_OES_rgb8_rgba8"))) { | 
 |     return; | 
 |   } | 
 |  | 
 |   static const char* v_shader_str = | 
 |       "attribute vec4 a_Position;\n" | 
 |       "void main()\n" | 
 |       "{\n" | 
 |       "   gl_Position = a_Position;\n" | 
 |       "}\n"; | 
 |   static const char* f_shader_str = | 
 |       "precision mediump float;\n" | 
 |       "void main()\n" | 
 |       "{\n" | 
 |       "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" | 
 |       "}\n"; | 
 |  | 
 |   GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str); | 
 |   glUseProgram(program); | 
 |   GLuint position_loc = glGetAttribLocation(program, "a_Position"); | 
 |  | 
 |   GLTestHelper::SetupUnitQuad(position_loc); | 
 |  | 
 |   const GLuint width = 100; | 
 |   const GLuint height = 100; | 
 |  | 
 |   // Create a sample buffer. | 
 |   GLsizei num_samples = 4, max_samples = 0; | 
 |   glGetIntegerv(GL_MAX_SAMPLES, &max_samples); | 
 |   num_samples = std::min(num_samples, max_samples); | 
 |  | 
 |   GLuint sample_fbo, sample_rb; | 
 |   glGenRenderbuffers(1, &sample_rb); | 
 |   glBindRenderbuffer(GL_RENDERBUFFER, sample_rb); | 
 |   glRenderbufferStorageMultisampleCHROMIUM( | 
 |       GL_RENDERBUFFER, num_samples, GL_RGBA8_OES, width, height); | 
 |   GLint param = 0; | 
 |   glGetRenderbufferParameteriv( | 
 |       GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, ¶m); | 
 |   EXPECT_GE(param, num_samples); | 
 |  | 
 |   glGenFramebuffers(1, &sample_fbo); | 
 |   glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo); | 
 |   glFramebufferRenderbuffer(GL_FRAMEBUFFER, | 
 |                             GL_COLOR_ATTACHMENT0, | 
 |                             GL_RENDERBUFFER, | 
 |                             sample_rb); | 
 |   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), | 
 |             glCheckFramebufferStatus(GL_FRAMEBUFFER)); | 
 |  | 
 |   // Create another FBO to resolve the multisample buffer into. | 
 |   GLuint resolve_fbo, resolve_tex; | 
 |   glGenTextures(1, &resolve_tex); | 
 |   glBindTexture(GL_TEXTURE_2D, resolve_tex); | 
 |   glTexImage2D(GL_TEXTURE_2D, | 
 |                0, | 
 |                GL_RGBA, | 
 |                width, | 
 |                height, | 
 |                0, | 
 |                GL_RGBA, | 
 |                GL_UNSIGNED_BYTE, | 
 |                NULL); | 
 |   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
 |   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
 |   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 
 |   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
 |   glGenFramebuffers(1, &resolve_fbo); | 
 |   glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo); | 
 |   glFramebufferTexture2D(GL_FRAMEBUFFER, | 
 |                          GL_COLOR_ATTACHMENT0, | 
 |                          GL_TEXTURE_2D, | 
 |                          resolve_tex, | 
 |                          0); | 
 |   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), | 
 |             glCheckFramebufferStatus(GL_FRAMEBUFFER)); | 
 |  | 
 |   // Draw one triangle (bottom left half). | 
 |   glViewport(0, 0, width, height); | 
 |   glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo); | 
 |   glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | 
 |   glClear(GL_COLOR_BUFFER_BIT); | 
 |   glDrawArrays(GL_TRIANGLES, 0, 3); | 
 |  | 
 |   // Resolve. | 
 |   glBindFramebuffer(GL_READ_FRAMEBUFFER, sample_fbo); | 
 |   glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo); | 
 |   glClearColor(1.0f, 0.0f, 0.0f, 0.0f); | 
 |   glClear(GL_COLOR_BUFFER_BIT); | 
 |   glBlitFramebufferCHROMIUM(0, | 
 |                             0, | 
 |                             width, | 
 |                             height, | 
 |                             0, | 
 |                             0, | 
 |                             width, | 
 |                             height, | 
 |                             GL_COLOR_BUFFER_BIT, | 
 |                             GL_NEAREST); | 
 |  | 
 |   // Verify. | 
 |   const uint8_t green[] = {0, 255, 0, 255}; | 
 |   const uint8_t black[] = {0, 0, 0, 0}; | 
 |   glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo); | 
 |   EXPECT_TRUE( | 
 |       GLTestHelper::CheckPixels(width / 4, (3 * height) / 4, 1, 1, 0, green)); | 
 |   EXPECT_TRUE(GLTestHelper::CheckPixels(width - 1, 0, 1, 1, 0, black)); | 
 | } | 
 |  | 
 | }  // namespace gpu | 
 |  |