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
13 namespace glbench {
14
15
16 class FillRateTest : public DrawArraysTestFunc {
17 public:
FillRateTest()18 FillRateTest() {}
~FillRateTest()19 virtual ~FillRateTest() {}
20 virtual bool Run();
Name() const21 virtual const char* Name() const { return "fill_rate"; }
22
23 private:
24 DISALLOW_COPY_AND_ASSIGN(FillRateTest);
25 };
26
27 class FboFillRateTest : public DrawArraysTestFunc {
28 public:
FboFillRateTest()29 FboFillRateTest() {}
~FboFillRateTest()30 virtual ~FboFillRateTest() {}
31 virtual bool Run();
Name() const32 virtual const char* Name() const { return "fbo_fill_rate"; }
33
34 private:
35 DISALLOW_COPY_AND_ASSIGN(FboFillRateTest);
36 };
37
38 const char* kVertexShader1 =
39 "attribute vec4 position;"
40 "void main() {"
41 " gl_Position = position;"
42 "}";
43
44 const char* kFragmentShader1 =
45 "uniform vec4 color;"
46 "void main() {"
47 " gl_FragColor = color;"
48 "}";
49
50
51 const 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
61 const char* kFragmentShader2 =
62 "uniform sampler2D texture;"
63 "varying vec4 v1;"
64 "void main() {"
65 " gl_FragColor = texture2D(texture, v1.xy);"
66 "}";
67
68 const 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
75 const 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
82 const GLfloat red[4] = {1.f, 0.f, 0.f, 1.f};
83
84
Run()85 bool 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
Run()165 bool 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
GetFillRateTest()249 TestBase* GetFillRateTest() {
250 return new FillRateTest;
251 }
252
GetFboFillRateTest()253 TestBase* GetFboFillRateTest() {
254 return new FboFillRateTest;
255 }
256
257 } // namespace glbench
258