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