1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152

gpu / command_buffer / tests / gl_chromium_framebuffer_multisample_unittest.cc [blame]

// Copyright 2012 The Chromium Authors
// 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