普通文本  |  258行  |  8.1 KB

// Copyright (c) 2010 The Chromium OS 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 "base/logging.h"
#include "main.h"
#include "testbase.h"
#include "utils.h"

#include <algorithm>


namespace glbench {


class FillRateTest : public DrawArraysTestFunc {
 public:
  FillRateTest() {}
  virtual ~FillRateTest() {}
  virtual bool Run();
  virtual const char* Name() const { return "fill_rate"; }

 private:
  DISALLOW_COPY_AND_ASSIGN(FillRateTest);
};

class FboFillRateTest : public DrawArraysTestFunc {
 public:
  FboFillRateTest() {}
  virtual ~FboFillRateTest() {}
  virtual bool Run();
  virtual const char* Name() const { return "fbo_fill_rate"; }

 private:
  DISALLOW_COPY_AND_ASSIGN(FboFillRateTest);
};

const char* kVertexShader1 =
    "attribute vec4 position;"
    "void main() {"
    "  gl_Position = position;"
    "}";

const char* kFragmentShader1 =
    "uniform vec4 color;"
    "void main() {"
    "  gl_FragColor = color;"
    "}";


const char* kVertexShader2 =
    "attribute vec4 position;"
    "attribute vec4 texcoord;"
    "uniform float scale;"
    "varying vec4 v1;"
    "void main() {"
    "  gl_Position = position * vec4(scale, scale, 1., 1.);"
    "  v1 = texcoord;"
    "}";

const char* kFragmentShader2 =
    "uniform sampler2D texture;"
    "varying vec4 v1;"
    "void main() {"
    "  gl_FragColor = texture2D(texture, v1.xy);"
    "}";

const GLfloat buffer_vertex[8] = {
  -1.f, -1.f,
  1.f,  -1.f,
  -1.f, 1.f,
  1.f,  1.f,
};

const GLfloat buffer_texture[8] = {
  0.f, 0.f,
  1.f, 0.f,
  0.f, 1.f,
  1.f, 1.f,
};

const GLfloat red[4] = {1.f, 0.f, 0.f, 1.f};


bool FillRateTest::Run() {
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
  glDisable(GL_DEPTH_TEST);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  GLuint vbo_vertex = SetupVBO(GL_ARRAY_BUFFER,
                               sizeof(buffer_vertex), buffer_vertex);
  GLuint program = InitShaderProgram(kVertexShader1, kFragmentShader1);
  GLint position_attribute = glGetAttribLocation(program, "position");
  glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
  glEnableVertexAttribArray(position_attribute);

  GLint color_uniform = glGetUniformLocation(program, "color");
  glUniform4fv(color_uniform, 1, red);

  FillRateTestNormal("fill_solid");
  FillRateTestBlendDepth("fill_solid");

  glDeleteProgram(program);

  program = InitShaderProgram(kVertexShader2, kFragmentShader2);
  position_attribute = glGetAttribLocation(program, "position");
  // Reusing vbo_vertex buffer from the previous test.
  glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
  glEnableVertexAttribArray(position_attribute);

  GLuint vbo_texture = SetupVBO(GL_ARRAY_BUFFER,
                                sizeof(buffer_texture), buffer_texture);
  GLuint texcoord_attribute = glGetAttribLocation(program, "texcoord");
  glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
  glEnableVertexAttribArray(texcoord_attribute);

  // Get a fractal looking source texture of size 512x512 and full levels
  // of detail.
  GLuint texture = SetupTexture(9);

  GLuint texture_uniform = glGetUniformLocation(program, "texture");
  glUniform1i(texture_uniform, 0);

  GLuint scale_uniform = glGetUniformLocation(program, "scale");
  glUniform1f(scale_uniform, 1.f);

  FillRateTestNormal("fill_tex_nearest");

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  FillRateTestNormal("fill_tex_bilinear");

  // lod = 0.5
  float scale = 0.7071f;
  glUniform1f(scale_uniform, scale);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                  GL_LINEAR_MIPMAP_LINEAR);
  FillRateTestNormalSubWindow("fill_tex_trilinear_linear_05",
                              g_width, g_height);

  // lod = 0.4
  scale = 0.758f;
  glUniform1f(scale_uniform, scale);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                  GL_LINEAR_MIPMAP_LINEAR);
  FillRateTestNormalSubWindow("fill_tex_trilinear_linear_04",
                              g_width, g_height);

  // lod = 0.1
  scale = 0.933f;
  glUniform1f(scale_uniform, scale);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                  GL_LINEAR_MIPMAP_LINEAR);
  FillRateTestNormalSubWindow("fill_tex_trilinear_linear_01",
                              g_width, g_height);

  glDeleteProgram(program);
  glDeleteBuffers(1, &vbo_vertex);
  glDeleteBuffers(1, &vbo_texture);
  glDeleteTextures(1, &texture);

  return true;
}

bool FboFillRateTest::Run() {
  char name[256];
  CHECK(!glGetError());
  GLuint vbo_vertex = SetupVBO(GL_ARRAY_BUFFER,
                               sizeof(buffer_vertex), buffer_vertex);
  GLuint program = InitShaderProgram(kVertexShader2, kFragmentShader2);
  GLint position_attribute = glGetAttribLocation(program, "position");
  glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
  glEnableVertexAttribArray(position_attribute);
  GLuint vbo_texture = SetupVBO(GL_ARRAY_BUFFER,
                                sizeof(buffer_texture), buffer_texture);
  GLuint texcoord_attribute = glGetAttribLocation(program, "texcoord");
  glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
  glEnableVertexAttribArray(texcoord_attribute);
  glDisable(GL_DEPTH_TEST);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  CHECK(!glGetError());

  // We don't care for tiny texture sizes. And why the 8K*8K reference is
  // only 700kB in size in the failure case it could be huge to upload to GS.
  // In hasty mode we ignore huge textures all together.
  const int max_size = std::min(g_hasty ? 512 : 4096, g_max_texture_size);
  // Start with 32x32 textures and go up from there.
  int size_log2 = 5;
  for (int size = 1 << size_log2; size <= max_size; size *= 2) {
    sprintf(name, "fbofill_tex_bilinear_%d", size);

    // Setup texture for FBO.
    GLuint destination_texture = 0;
    glGenTextures(1, &destination_texture);
    glBindTexture(GL_TEXTURE_2D, destination_texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 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);
    CHECK(!glGetError());

    // Setup Framebuffer.
    // TODO(fjhenigman): In WAFFLE_PLATFORM_NULL the default framebuffer
    // is NOT zero, so we have to save the current binding and restore
    // that value later.  Fix this.
    GLint save_fb;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &save_fb);
    GLuint framebuffer = 0;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                              GL_TEXTURE_2D, destination_texture, 0);
    CHECK(!glGetError());

    // Attach texture and check for completeness.
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    CHECK(status == GL_FRAMEBUFFER_COMPLETE);
    glViewport(0, 0, size, size);

    // Get a fractal looking source texture of size size*size.
    GLuint source_texture = SetupTexture(size_log2);
    GLuint texture_uniform = glGetUniformLocation(program, "texture");
    glUniform1i(texture_uniform, 0);
    GLuint scale_uniform = glGetUniformLocation(program, "scale");
    glUniform1f(scale_uniform, 1.f);

    // Run the benchmark, save the images if desired.
    FillRateTestNormalSubWindow(name, size, size);

    // Clean up for this loop.
    glBindFramebuffer(GL_FRAMEBUFFER, save_fb);
    glDeleteFramebuffers(1, &framebuffer);
    glDeleteTextures(1, &source_texture);
    glDeleteTextures(1, &destination_texture);
    CHECK(!glGetError());

    size_log2++;
  }
  // Clean up invariants.
  glDeleteProgram(program);
  glDeleteBuffers(1, &vbo_vertex);
  glDeleteBuffers(1, &vbo_texture);
  // Just in case restore the viewport for all other tests.
  glViewport(0, 0, g_width, g_height);

  return true;
}

TestBase* GetFillRateTest() {
  return new FillRateTest;
}

TestBase* GetFboFillRateTest() {
  return new FboFillRateTest;
}

} // namespace glbench