1// Copyright (c) 2010 The Chromium OS 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 "base/logging.h"
6#include "main.h"
7#include "testbase.h"
8#include "utils.h"
9
10#include <algorithm>
11
12
13namespace glbench {
14
15
16class FillRateTest : public DrawArraysTestFunc {
17 public:
18  FillRateTest() {}
19  virtual ~FillRateTest() {}
20  virtual bool Run();
21  virtual const char* Name() const { return "fill_rate"; }
22
23 private:
24  DISALLOW_COPY_AND_ASSIGN(FillRateTest);
25};
26
27class FboFillRateTest : public DrawArraysTestFunc {
28 public:
29  FboFillRateTest() {}
30  virtual ~FboFillRateTest() {}
31  virtual bool Run();
32  virtual const char* Name() const { return "fbo_fill_rate"; }
33
34 private:
35  DISALLOW_COPY_AND_ASSIGN(FboFillRateTest);
36};
37
38const char* kVertexShader1 =
39    "attribute vec4 position;"
40    "void main() {"
41    "  gl_Position = position;"
42    "}";
43
44const char* kFragmentShader1 =
45    "uniform vec4 color;"
46    "void main() {"
47    "  gl_FragColor = color;"
48    "}";
49
50
51const char* kVertexShader2 =
52    "attribute vec4 position;"
53    "attribute vec4 texcoord;"
54    "uniform float scale;"
55    "varying vec4 v1;"
56    "void main() {"
57    "  gl_Position = position * vec4(scale, scale, 1., 1.);"
58    "  v1 = texcoord;"
59    "}";
60
61const char* kFragmentShader2 =
62    "uniform sampler2D texture;"
63    "varying vec4 v1;"
64    "void main() {"
65    "  gl_FragColor = texture2D(texture, v1.xy);"
66    "}";
67
68const GLfloat buffer_vertex[8] = {
69  -1.f, -1.f,
70  1.f,  -1.f,
71  -1.f, 1.f,
72  1.f,  1.f,
73};
74
75const GLfloat buffer_texture[8] = {
76  0.f, 0.f,
77  1.f, 0.f,
78  0.f, 1.f,
79  1.f, 1.f,
80};
81
82const GLfloat red[4] = {1.f, 0.f, 0.f, 1.f};
83
84
85bool FillRateTest::Run() {
86  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
87  glDisable(GL_DEPTH_TEST);
88  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
89
90  GLuint vbo_vertex = SetupVBO(GL_ARRAY_BUFFER,
91                               sizeof(buffer_vertex), buffer_vertex);
92  GLuint program = InitShaderProgram(kVertexShader1, kFragmentShader1);
93  GLint position_attribute = glGetAttribLocation(program, "position");
94  glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
95  glEnableVertexAttribArray(position_attribute);
96
97  GLint color_uniform = glGetUniformLocation(program, "color");
98  glUniform4fv(color_uniform, 1, red);
99
100  FillRateTestNormal("fill_solid");
101  FillRateTestBlendDepth("fill_solid");
102
103  glDeleteProgram(program);
104
105  program = InitShaderProgram(kVertexShader2, kFragmentShader2);
106  position_attribute = glGetAttribLocation(program, "position");
107  // Reusing vbo_vertex buffer from the previous test.
108  glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
109  glEnableVertexAttribArray(position_attribute);
110
111  GLuint vbo_texture = SetupVBO(GL_ARRAY_BUFFER,
112                                sizeof(buffer_texture), buffer_texture);
113  GLuint texcoord_attribute = glGetAttribLocation(program, "texcoord");
114  glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
115  glEnableVertexAttribArray(texcoord_attribute);
116
117  // Get a fractal looking source texture of size 512x512 and full levels
118  // of detail.
119  GLuint texture = SetupTexture(9);
120
121  GLuint texture_uniform = glGetUniformLocation(program, "texture");
122  glUniform1i(texture_uniform, 0);
123
124  GLuint scale_uniform = glGetUniformLocation(program, "scale");
125  glUniform1f(scale_uniform, 1.f);
126
127  FillRateTestNormal("fill_tex_nearest");
128
129  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
130  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
131  FillRateTestNormal("fill_tex_bilinear");
132
133  // lod = 0.5
134  float scale = 0.7071f;
135  glUniform1f(scale_uniform, scale);
136  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
137                  GL_LINEAR_MIPMAP_LINEAR);
138  FillRateTestNormalSubWindow("fill_tex_trilinear_linear_05",
139                              g_width, g_height);
140
141  // lod = 0.4
142  scale = 0.758f;
143  glUniform1f(scale_uniform, scale);
144  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
145                  GL_LINEAR_MIPMAP_LINEAR);
146  FillRateTestNormalSubWindow("fill_tex_trilinear_linear_04",
147                              g_width, g_height);
148
149  // lod = 0.1
150  scale = 0.933f;
151  glUniform1f(scale_uniform, scale);
152  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
153                  GL_LINEAR_MIPMAP_LINEAR);
154  FillRateTestNormalSubWindow("fill_tex_trilinear_linear_01",
155                              g_width, g_height);
156
157  glDeleteProgram(program);
158  glDeleteBuffers(1, &vbo_vertex);
159  glDeleteBuffers(1, &vbo_texture);
160  glDeleteTextures(1, &texture);
161
162  return true;
163}
164
165bool FboFillRateTest::Run() {
166  char name[256];
167  CHECK(!glGetError());
168  GLuint vbo_vertex = SetupVBO(GL_ARRAY_BUFFER,
169                               sizeof(buffer_vertex), buffer_vertex);
170  GLuint program = InitShaderProgram(kVertexShader2, kFragmentShader2);
171  GLint position_attribute = glGetAttribLocation(program, "position");
172  glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
173  glEnableVertexAttribArray(position_attribute);
174  GLuint vbo_texture = SetupVBO(GL_ARRAY_BUFFER,
175                                sizeof(buffer_texture), buffer_texture);
176  GLuint texcoord_attribute = glGetAttribLocation(program, "texcoord");
177  glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 0, NULL);
178  glEnableVertexAttribArray(texcoord_attribute);
179  glDisable(GL_DEPTH_TEST);
180  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
181  CHECK(!glGetError());
182
183  // We don't care for tiny texture sizes. And why the 8K*8K reference is
184  // only 700kB in size in the failure case it could be huge to upload to GS.
185  // In hasty mode we ignore huge textures all together.
186  const int max_size = std::min(g_hasty ? 512 : 4096, g_max_texture_size);
187  // Start with 32x32 textures and go up from there.
188  int size_log2 = 5;
189  for (int size = 1 << size_log2; size <= max_size; size *= 2) {
190    sprintf(name, "fbofill_tex_bilinear_%d", size);
191
192    // Setup texture for FBO.
193    GLuint destination_texture = 0;
194    glGenTextures(1, &destination_texture);
195    glBindTexture(GL_TEXTURE_2D, destination_texture);
196    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA,
197                 GL_UNSIGNED_BYTE, NULL);
198    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
199    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
200    CHECK(!glGetError());
201
202    // Setup Framebuffer.
203    // TODO(fjhenigman): In WAFFLE_PLATFORM_NULL the default framebuffer
204    // is NOT zero, so we have to save the current binding and restore
205    // that value later.  Fix this.
206    GLint save_fb;
207    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &save_fb);
208    GLuint framebuffer = 0;
209    glGenFramebuffers(1, &framebuffer);
210    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
211    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
212                              GL_TEXTURE_2D, destination_texture, 0);
213    CHECK(!glGetError());
214
215    // Attach texture and check for completeness.
216    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
217    CHECK(status == GL_FRAMEBUFFER_COMPLETE);
218    glViewport(0, 0, size, size);
219
220    // Get a fractal looking source texture of size size*size.
221    GLuint source_texture = SetupTexture(size_log2);
222    GLuint texture_uniform = glGetUniformLocation(program, "texture");
223    glUniform1i(texture_uniform, 0);
224    GLuint scale_uniform = glGetUniformLocation(program, "scale");
225    glUniform1f(scale_uniform, 1.f);
226
227    // Run the benchmark, save the images if desired.
228    FillRateTestNormalSubWindow(name, size, size);
229
230    // Clean up for this loop.
231    glBindFramebuffer(GL_FRAMEBUFFER, save_fb);
232    glDeleteFramebuffers(1, &framebuffer);
233    glDeleteTextures(1, &source_texture);
234    glDeleteTextures(1, &destination_texture);
235    CHECK(!glGetError());
236
237    size_log2++;
238  }
239  // Clean up invariants.
240  glDeleteProgram(program);
241  glDeleteBuffers(1, &vbo_vertex);
242  glDeleteBuffers(1, &vbo_texture);
243  // Just in case restore the viewport for all other tests.
244  glViewport(0, 0, g_width, g_height);
245
246  return true;
247}
248
249TestBase* GetFillRateTest() {
250  return new FillRateTest;
251}
252
253TestBase* GetFboFillRateTest() {
254  return new FboFillRateTest;
255}
256
257} // namespace glbench
258