| // 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, nullptr); | |
| 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, nullptr)); | |
| EXPECT_TRUE(GLTestHelper::CheckPixels(width - 1, 0, 1, 1, 0, black, nullptr)); | |
| } | |
| } // namespace gpu | |