12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <GLES2/gl2.h>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <GLES2/gl2ext.h>
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <GLES2/gl2extchromium.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gpu/command_buffer/tests/gl_manager.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gpu/command_buffer/tests/gl_test_utils.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace gpu {
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GLChromiumFramebufferMultisampleTest : public testing::Test {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gl_.Initialize(GLManager::Options());
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown() {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gl_.Destroy();
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLManager gl_;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test that GL is at least minimally working.
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(GLChromiumFramebufferMultisampleTest, CachedBindingsTest) {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample")) {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLuint fbo = 0;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  glGenFramebuffers(1, &fbo);
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  glBindFramebuffer(GL_FRAMEBUFFER, 0);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the caching is bad the second call to glBindFramebuffer will do nothing.
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // which means the draw buffer is bad and will not return
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GL_FRAMEBUFFER_COMPLETE and rendering will generate an error.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            glCheckFramebufferStatus(GL_FRAMEBUFFER));
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  glClear(GL_COLOR_BUFFER_BIT);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLTestHelper::CheckGLError("no errors", __LINE__);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(GLChromiumFramebufferMultisampleTest, DrawAndResolve) {
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample")) {
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  static const char* v_shader_str =
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "attribute vec4 a_Position;\n"
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "void main()\n"
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "{\n"
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "   gl_Position = a_Position;\n"
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "}\n";
611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  static const char* f_shader_str =
621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "precision mediump float;\n"
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "void main()\n"
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "{\n"
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      "}\n";
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glUseProgram(program);
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GLuint position_loc = glGetAttribLocation(program, "a_Position");
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GLTestHelper::SetupUnitQuad(position_loc);
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const GLuint width = 100;
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const GLuint height = 100;
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Create a sample buffer.
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GLsizei num_samples = 4, max_samples = 0;
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  num_samples = std::min(num_samples, max_samples);
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GLuint sample_fbo, sample_rb;
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glGenRenderbuffers(1, &sample_rb);
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glBindRenderbuffer(GL_RENDERBUFFER, sample_rb);
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  glRenderbufferStorageMultisampleCHROMIUM(
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      GL_RENDERBUFFER, num_samples, GL_RGBA8_OES, width, height);
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GLint param = 0;
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glGetRenderbufferParameteriv(
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &param);
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_GE(param, num_samples);
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glGenFramebuffers(1, &sample_fbo);
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo);
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glFramebufferRenderbuffer(GL_FRAMEBUFFER,
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                            GL_COLOR_ATTACHMENT0,
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                            GL_RENDERBUFFER,
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                            sample_rb);
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            glCheckFramebufferStatus(GL_FRAMEBUFFER));
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Create another FBO to resolve the multisample buffer into.
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GLuint resolve_fbo, resolve_tex;
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glGenTextures(1, &resolve_tex);
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glBindTexture(GL_TEXTURE_2D, resolve_tex);
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glTexImage2D(GL_TEXTURE_2D,
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               0,
1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               GL_RGBA,
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               width,
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               height,
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               0,
1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               GL_RGBA,
1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               GL_UNSIGNED_BYTE,
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               NULL);
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glGenFramebuffers(1, &resolve_fbo);
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo);
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glFramebufferTexture2D(GL_FRAMEBUFFER,
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         GL_COLOR_ATTACHMENT0,
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         GL_TEXTURE_2D,
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         resolve_tex,
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         0);
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            glCheckFramebufferStatus(GL_FRAMEBUFFER));
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Draw one triangle (bottom left half).
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glViewport(0, 0, width, height);
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo);
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glClear(GL_COLOR_BUFFER_BIT);
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glDrawArrays(GL_TRIANGLES, 0, 3);
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Resolve.
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glBindFramebuffer(GL_READ_FRAMEBUFFER, sample_fbo);
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo);
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glClear(GL_COLOR_BUFFER_BIT);
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  glBlitFramebufferCHROMIUM(0,
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0,
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            width,
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            height,
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0,
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0,
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            width,
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            height,
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            GL_COLOR_BUFFER_BIT,
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            GL_NEAREST);
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Verify.
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const uint8 green[] = {0, 255, 0, 255};
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const uint8 black[] = {0, 0, 0, 0};
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo);
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_TRUE(
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      GLTestHelper::CheckPixels(width / 4, (3 * height) / 4, 1, 1, 0, green));
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_TRUE(GLTestHelper::CheckPixels(width - 1, 0, 1, 1, 0, black));
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace gpu
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162