1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <GLES2/gl2.h>
6#include <GLES2/gl2ext.h>
7#include <GLES2/gl2extchromium.h>
8
9#include "gpu/command_buffer/tests/gl_manager.h"
10#include "gpu/command_buffer/tests/gl_test_utils.h"
11#include "testing/gmock/include/gmock/gmock.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace gpu {
15
16class GLChromiumFramebufferMultisampleTest : public testing::Test {
17 protected:
18  virtual void SetUp() {
19    gl_.Initialize(GLManager::Options());
20  }
21
22  virtual void TearDown() {
23    gl_.Destroy();
24  }
25
26  GLManager gl_;
27};
28
29// Test that GL is at least minimally working.
30TEST_F(GLChromiumFramebufferMultisampleTest, CachedBindingsTest) {
31  if (!GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample")) {
32    return;
33  }
34
35  GLuint fbo = 0;
36  glGenFramebuffers(1, &fbo);
37  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
38  glBindFramebuffer(GL_FRAMEBUFFER, 0);
39
40  // If the caching is bad the second call to glBindFramebuffer will do nothing.
41  // which means the draw buffer is bad and will not return
42  // GL_FRAMEBUFFER_COMPLETE and rendering will generate an error.
43  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
44            glCheckFramebufferStatus(GL_FRAMEBUFFER));
45
46  glClear(GL_COLOR_BUFFER_BIT);
47  GLTestHelper::CheckGLError("no errors", __LINE__);
48}
49
50TEST_F(GLChromiumFramebufferMultisampleTest, DrawAndResolve) {
51  if (!GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample")) {
52    return;
53  }
54
55  static const char* v_shader_str =
56      "attribute vec4 a_Position;\n"
57      "void main()\n"
58      "{\n"
59      "   gl_Position = a_Position;\n"
60      "}\n";
61  static const char* f_shader_str =
62      "precision mediump float;\n"
63      "void main()\n"
64      "{\n"
65      "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
66      "}\n";
67
68  GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
69  glUseProgram(program);
70  GLuint position_loc = glGetAttribLocation(program, "a_Position");
71
72  GLTestHelper::SetupUnitQuad(position_loc);
73
74  const GLuint width = 100;
75  const GLuint height = 100;
76
77  // Create a sample buffer.
78  GLsizei num_samples = 4, max_samples = 0;
79  glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
80  num_samples = std::min(num_samples, max_samples);
81
82  GLuint sample_fbo, sample_rb;
83  glGenRenderbuffers(1, &sample_rb);
84  glBindRenderbuffer(GL_RENDERBUFFER, sample_rb);
85  glRenderbufferStorageMultisampleCHROMIUM(
86      GL_RENDERBUFFER, num_samples, GL_RGBA8_OES, width, height);
87  GLint param = 0;
88  glGetRenderbufferParameteriv(
89      GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &param);
90  EXPECT_GE(param, num_samples);
91
92  glGenFramebuffers(1, &sample_fbo);
93  glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo);
94  glFramebufferRenderbuffer(GL_FRAMEBUFFER,
95                            GL_COLOR_ATTACHMENT0,
96                            GL_RENDERBUFFER,
97                            sample_rb);
98  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
99            glCheckFramebufferStatus(GL_FRAMEBUFFER));
100
101  // Create another FBO to resolve the multisample buffer into.
102  GLuint resolve_fbo, resolve_tex;
103  glGenTextures(1, &resolve_tex);
104  glBindTexture(GL_TEXTURE_2D, resolve_tex);
105  glTexImage2D(GL_TEXTURE_2D,
106               0,
107               GL_RGBA,
108               width,
109               height,
110               0,
111               GL_RGBA,
112               GL_UNSIGNED_BYTE,
113               NULL);
114  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
115  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
116  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
117  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
118  glGenFramebuffers(1, &resolve_fbo);
119  glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo);
120  glFramebufferTexture2D(GL_FRAMEBUFFER,
121                         GL_COLOR_ATTACHMENT0,
122                         GL_TEXTURE_2D,
123                         resolve_tex,
124                         0);
125  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
126            glCheckFramebufferStatus(GL_FRAMEBUFFER));
127
128  // Draw one triangle (bottom left half).
129  glViewport(0, 0, width, height);
130  glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo);
131  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
132  glClear(GL_COLOR_BUFFER_BIT);
133  glDrawArrays(GL_TRIANGLES, 0, 3);
134
135  // Resolve.
136  glBindFramebuffer(GL_READ_FRAMEBUFFER, sample_fbo);
137  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo);
138  glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
139  glClear(GL_COLOR_BUFFER_BIT);
140  glBlitFramebufferCHROMIUM(0,
141                            0,
142                            width,
143                            height,
144                            0,
145                            0,
146                            width,
147                            height,
148                            GL_COLOR_BUFFER_BIT,
149                            GL_NEAREST);
150
151  // Verify.
152  const uint8 green[] = {0, 255, 0, 255};
153  const uint8 black[] = {0, 0, 0, 0};
154  glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo);
155  EXPECT_TRUE(
156      GLTestHelper::CheckPixels(width / 4, (3 * height) / 4, 1, 1, 0, green));
157  EXPECT_TRUE(GLTestHelper::CheckPixels(width - 1, 0, 1, 1, 0, black));
158}
159
160}  // namespace gpu
161
162