Merge lp:~glcompbench-dev/glcompbench/blur into lp:glcompbench
- blur
- Merge into trunk
Proposed by
Jesse Barker
Status: | Merged |
---|---|
Merged at revision: | 78 |
Proposed branch: | lp:~glcompbench-dev/glcompbench/blur |
Merge into: | lp:glcompbench |
Diff against target: |
1511 lines (+1231/-21) 20 files modified
data/desktop-blur.frag (+13/-0) data/desktop.frag (+10/-0) data/desktop.vert (+11/-0) src/benchmark.cc (+3/-2) src/benchmark.h (+1/-1) src/composite-canvas.cc (+1/-1) src/composite-test-default-options.cc (+3/-1) src/composite-test-pixman.cc (+3/-1) src/composite-test-simple-base.cc (+3/-1) src/composite-test-simple-blur.cc (+474/-0) src/composite-test-simple-brick.cc (+2/-2) src/composite-test-xrender.cc (+3/-1) src/composite-test.h (+25/-6) src/glcompbench.cc (+2/-0) src/render-object.cc (+282/-0) src/render-object.h (+152/-0) src/texture.cc (+201/-0) src/texture.h (+37/-0) src/wscript_build (+4/-4) wscript (+1/-1) |
To merge this branch: | bzr merge lp:~glcompbench-dev/glcompbench/blur |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexandros Frantzis | Pending | ||
Review via email: mp+98238@code.launchpad.net |
Commit message
Description of the change
Adds a new test for a blur effect. This is derived from the work on glmark2 in its SceneDesktop, but with a somewhat refactored set of objects, and the window contents come from the window list (rather than being static as they are in glmark2). The canvas background image is preserved as blur is largely uninteresting against a solid background (even if the GPU is going through all of the same computations).
To post a comment you must log in.
- 93. By Jesse Barker
-
Change the condition of a RenderObject missing from the map from error to debug.
The current state of the test is targeted at the scripted mode where we have a
fixed window list, but if windows are added during the test run, they currently
will not have a RenderObject. That's a follow on feature.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'data/background.png' |
2 | Binary files data/background.png 1970-01-01 00:00:00 +0000 and data/background.png 2012-03-20 16:31:20 +0000 differ |
3 | === added file 'data/desktop-blur.frag' |
4 | --- data/desktop-blur.frag 1970-01-01 00:00:00 +0000 |
5 | +++ data/desktop-blur.frag 2012-03-20 16:31:20 +0000 |
6 | @@ -0,0 +1,13 @@ |
7 | +uniform sampler2D Texture0; |
8 | + |
9 | +varying vec2 TextureCoord; |
10 | + |
11 | +void main(void) |
12 | +{ |
13 | + vec4 result; |
14 | + |
15 | + $CONVOLUTION$ |
16 | + |
17 | + gl_FragColor = result; |
18 | +} |
19 | + |
20 | |
21 | === added file 'data/desktop.frag' |
22 | --- data/desktop.frag 1970-01-01 00:00:00 +0000 |
23 | +++ data/desktop.frag 2012-03-20 16:31:20 +0000 |
24 | @@ -0,0 +1,10 @@ |
25 | +uniform sampler2D MaterialTexture0; |
26 | + |
27 | +varying vec2 TextureCoord; |
28 | + |
29 | +void main(void) |
30 | +{ |
31 | + vec4 texel = texture2D(MaterialTexture0, TextureCoord); |
32 | + gl_FragColor = vec4(texel.xyz, 0.5); |
33 | +} |
34 | + |
35 | |
36 | === added file 'data/desktop.vert' |
37 | --- data/desktop.vert 1970-01-01 00:00:00 +0000 |
38 | +++ data/desktop.vert 2012-03-20 16:31:20 +0000 |
39 | @@ -0,0 +1,11 @@ |
40 | +attribute vec2 position; |
41 | +attribute vec2 texcoord; |
42 | + |
43 | +varying vec2 TextureCoord; |
44 | + |
45 | +void main(void) |
46 | +{ |
47 | + gl_Position = vec4(position, 0.0, 1.0); |
48 | + |
49 | + TextureCoord = texcoord; |
50 | +} |
51 | |
52 | === added file 'data/window.png' |
53 | Binary files data/window.png 1970-01-01 00:00:00 +0000 and data/window.png 2012-03-20 16:31:20 +0000 differ |
54 | === modified file 'src/benchmark.cc' |
55 | --- src/benchmark.cc 2011-06-22 11:35:50 +0000 |
56 | +++ src/benchmark.cc 2012-03-20 16:31:20 +0000 |
57 | @@ -28,6 +28,7 @@ |
58 | using std::string; |
59 | using std::vector; |
60 | using std::map; |
61 | +using std::list; |
62 | |
63 | std::map<string, CompositeTest *> Benchmark::test_map_; |
64 | |
65 | @@ -113,12 +114,12 @@ |
66 | } |
67 | |
68 | CompositeTest & |
69 | -Benchmark::setup_test() |
70 | +Benchmark::setup_test(list<CompositeWindow*> &window_list) |
71 | { |
72 | test_.reset_options(); |
73 | load_options(); |
74 | |
75 | - test_.prepare_for_run(); |
76 | + test_.prepare_for_run(window_list); |
77 | |
78 | return test_; |
79 | } |
80 | |
81 | === modified file 'src/benchmark.h' |
82 | --- src/benchmark.h 2011-07-15 10:20:09 +0000 |
83 | +++ src/benchmark.h 2012-03-20 16:31:20 +0000 |
84 | @@ -40,7 +40,7 @@ |
85 | // test[:opt1=val1:opt2=val2...] |
86 | Benchmark(const std::string &s); |
87 | |
88 | - CompositeTest &setup_test(); |
89 | + CompositeTest &setup_test(std::list<CompositeWindow*> &window_list); |
90 | void teardown_test(); |
91 | |
92 | CompositeTest &get_test() { return test_; } |
93 | |
94 | === modified file 'src/composite-canvas.cc' |
95 | --- src/composite-canvas.cc 2011-09-21 13:57:01 +0000 |
96 | +++ src/composite-canvas.cc 2012-03-20 16:31:20 +0000 |
97 | @@ -633,7 +633,7 @@ |
98 | benchIt++) |
99 | { |
100 | Benchmark *benchmark = *benchIt; |
101 | - current_test_ = &benchmark->setup_test(); |
102 | + current_test_ = &benchmark->setup_test(this->window_list_); |
103 | |
104 | if (!current_test_->name().empty()) { |
105 | load_current_test_options(); |
106 | |
107 | === modified file 'src/composite-test-default-options.cc' |
108 | --- src/composite-test-default-options.cc 2011-06-23 13:52:16 +0000 |
109 | +++ src/composite-test-default-options.cc 2012-03-20 16:31:20 +0000 |
110 | @@ -29,8 +29,10 @@ |
111 | * Prepares the test for a test run. |
112 | */ |
113 | void |
114 | -CompositeTestDefaultOptions::prepare_for_run() |
115 | +CompositeTestDefaultOptions::prepare_for_run(std::list<CompositeWindow*> &window_list) |
116 | { |
117 | + CompositeTest::prepare_for_run(window_list); |
118 | + |
119 | const std::map<std::string, CompositeTest *> &tests = Benchmark::tests(); |
120 | |
121 | for (std::list<std::pair<std::string, std::string> >::const_iterator iter = default_options_.begin(); |
122 | |
123 | === modified file 'src/composite-test-pixman.cc' |
124 | --- src/composite-test-pixman.cc 2011-07-19 13:54:14 +0000 |
125 | +++ src/composite-test-pixman.cc 2012-03-20 16:31:20 +0000 |
126 | @@ -49,8 +49,10 @@ |
127 | } |
128 | |
129 | void |
130 | -CompositeTestPixman::prepare_for_run() |
131 | +CompositeTestPixman::prepare_for_run(std::list<CompositeWindow*> &window_list) |
132 | { |
133 | + CompositeTest::prepare_for_run(window_list); |
134 | + |
135 | if (options_["filter"].value == "bilinear") |
136 | pixman_filter_ = PIXMAN_FILTER_BILINEAR; |
137 | else |
138 | |
139 | === modified file 'src/composite-test-simple-base.cc' |
140 | --- src/composite-test-simple-base.cc 2011-12-05 19:01:24 +0000 |
141 | +++ src/composite-test-simple-base.cc 2012-03-20 16:31:20 +0000 |
142 | @@ -138,8 +138,10 @@ |
143 | * Prepares the test for a test run. |
144 | */ |
145 | void |
146 | -CompositeTestSimpleBase::prepare_for_run() |
147 | +CompositeTestSimpleBase::prepare_for_run(std::list<CompositeWindow*> &window_list) |
148 | { |
149 | + CompositeTest::prepare_for_run(window_list); |
150 | + |
151 | vboData_.useBufferObject(options_["use-vbo"].value == "true"); |
152 | |
153 | program_.start(); |
154 | |
155 | === added file 'src/composite-test-simple-blur.cc' |
156 | --- src/composite-test-simple-blur.cc 1970-01-01 00:00:00 +0000 |
157 | +++ src/composite-test-simple-blur.cc 2012-03-20 16:31:20 +0000 |
158 | @@ -0,0 +1,474 @@ |
159 | +/* |
160 | + * Copyright © 2011 Linaro Limited |
161 | + * |
162 | + * This file is part of glcompbench. |
163 | + * |
164 | + * glcompbench is free software: you can redistribute it and/or modify |
165 | + * it under the terms of the GNU General Public License as published by |
166 | + * the Free Software Foundation, either version 3 of the License, or |
167 | + * (at your option) any later version. |
168 | + * |
169 | + * glcompbench is distributed in the hope that it will be useful, |
170 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
171 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
172 | + * GNU General Public License for more details. |
173 | + * |
174 | + * You should have received a copy of the GNU General Public License |
175 | + * along with glcompbench. If not, see <http://www.gnu.org/licenses/>. |
176 | + * |
177 | + * Authors: |
178 | + * Alexandros Frantzis <alexandros.frantzis@linaro.org> |
179 | + * Jesse Barker <jesse.barker@linaro.org> |
180 | + */ |
181 | + |
182 | +#include <sstream> |
183 | +#include <cmath> |
184 | +#include "gl-headers.h" |
185 | +#include "composite-test.h" |
186 | +#include "options.h" |
187 | +#include "log.h" |
188 | +#include "util.h" |
189 | +#include "render-object.h" |
190 | +#include "texture.h" |
191 | +#include "composite-window-ximage.h" |
192 | + |
193 | +using std::string; |
194 | +using std::map; |
195 | +using std::list; |
196 | +using LibMatrix::vec2; |
197 | + |
198 | +// |
199 | +// A RenderObject that blurs the target it is drawn to. |
200 | +// |
201 | +class RenderWindowBlur : public RenderObject |
202 | +{ |
203 | +public: |
204 | + RenderWindowBlur(unsigned int passes, unsigned int radius, bool separable) : |
205 | + RenderObject(), |
206 | + passes_(passes), |
207 | + radius_(radius), |
208 | + separable_(separable), |
209 | + window_contents_() {} |
210 | + |
211 | + virtual void init(Program& program) |
212 | + { |
213 | + RenderObject::init(program); |
214 | + window_contents_.init(program); |
215 | + } |
216 | + |
217 | + virtual void set_background(unsigned int background_texture) |
218 | + { |
219 | + window_contents_.set_background(background_texture); |
220 | + } |
221 | + |
222 | + void refresh_window(unsigned int background_texture) |
223 | + { |
224 | + glClearColor(0.0, 0.0, 0.0, 0.0); |
225 | + window_contents_.set_background(background_texture); |
226 | + window_contents_.clear(); |
227 | + } |
228 | + |
229 | + virtual void release() |
230 | + { |
231 | + window_contents_.release(); |
232 | + RenderObject::release(); |
233 | + } |
234 | + |
235 | + virtual void resize(const vec2& size) |
236 | + { |
237 | + RenderObject::resize(size); |
238 | + window_contents_.resize(size); |
239 | + } |
240 | + |
241 | + virtual void render_to(RenderObject& target) |
242 | + { |
243 | + if (separable_) { |
244 | + Program& blur_program_h1 = blur_program_h(target.size().x()); |
245 | + Program& blur_program_v1 = blur_program_v(target.size().y()); |
246 | + |
247 | + for (unsigned int i = 0; i < passes_; i++) { |
248 | + render_from(target, blur_program_h1); |
249 | + RenderObject::render_to(target, blur_program_v1); |
250 | + } |
251 | + } |
252 | + else { |
253 | + Program& blur_program1 = blur_program(target.size().x(), target.size().y()); |
254 | + |
255 | + for (unsigned int i = 0; i < passes_; i++) { |
256 | + if (i % 2 == 0) |
257 | + render_from(target, blur_program1); |
258 | + else |
259 | + RenderObject::render_to(target, blur_program1); |
260 | + } |
261 | + |
262 | + if (passes_ % 2 == 1) |
263 | + RenderObject::render_to(target); |
264 | + } |
265 | + |
266 | + // Blend the window contents with the target texture. |
267 | + glEnable(GL_BLEND); |
268 | + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
269 | + window_contents_.position(position()); |
270 | + window_contents_.render_to(target); |
271 | + glDisable(GL_BLEND); |
272 | + } |
273 | + |
274 | +private: |
275 | + enum BlurDirection { |
276 | + BlurDirectionHorizontal, |
277 | + BlurDirectionVertical, |
278 | + BlurDirectionBoth |
279 | + }; |
280 | + |
281 | + void render_from(RenderObject& target, Program& program) |
282 | + { |
283 | + vec2 final_pos(pos_ + size_); |
284 | + vec2 ll_tex(target.normalize_texcoord(pos_)); |
285 | + vec2 ur_tex(target.normalize_texcoord(final_pos)); |
286 | + |
287 | + static const GLfloat position_blur[2 * 4] = { |
288 | + -1.0, -1.0, |
289 | + 1.0, -1.0, |
290 | + -1.0, 1.0, |
291 | + 1.0, 1.0, |
292 | + }; |
293 | + GLfloat texcoord_blur[2 * 4] = { |
294 | + ll_tex.x(), ll_tex.y(), |
295 | + ur_tex.x(), ll_tex.y(), |
296 | + ll_tex.x(), ur_tex.y(), |
297 | + ur_tex.x(), ur_tex.y(), |
298 | + }; |
299 | + |
300 | + make_current(); |
301 | + glBindTexture(GL_TEXTURE_2D, target.texture()); |
302 | + draw_quad_with_program(position_blur, texcoord_blur, program); |
303 | + } |
304 | + |
305 | + Program& blur_program(unsigned int w, unsigned int h) |
306 | + { |
307 | + /* |
308 | + * If the size of the window has changed we must recreate |
309 | + * the shader to contain the correct texture step values. |
310 | + */ |
311 | + if (blur_program_dim_.x() != w || blur_program_dim_.y() != h || |
312 | + !blur_program_.ready()) |
313 | + { |
314 | + blur_program_dim_.x(w); |
315 | + blur_program_dim_.y(h); |
316 | + |
317 | + blur_program_.release(); |
318 | + |
319 | + ShaderSource vtx_source; |
320 | + ShaderSource frg_source; |
321 | + create_blur_shaders(vtx_source, frg_source, radius_, |
322 | + radius_ / 3.0, BlurDirectionBoth); |
323 | + frg_source.add_const("TextureStepX", 1.0 / w); |
324 | + frg_source.add_const("TextureStepY", 1.0 / h); |
325 | + load_shaders_from_strings(blur_program_, vtx_source.str(), |
326 | + frg_source.str()); |
327 | + } |
328 | + |
329 | + return blur_program_; |
330 | + } |
331 | + |
332 | + Program& blur_program_h(unsigned int w) |
333 | + { |
334 | + /* |
335 | + * If the size of the window has changed we must recreate |
336 | + * the shader to contain the correct texture step values. |
337 | + */ |
338 | + if (blur_program_dim_.x() != w || |
339 | + !blur_program_h_.ready()) |
340 | + { |
341 | + blur_program_dim_.x(w); |
342 | + |
343 | + blur_program_h_.release(); |
344 | + |
345 | + ShaderSource vtx_source; |
346 | + ShaderSource frg_source; |
347 | + create_blur_shaders(vtx_source, frg_source, radius_, |
348 | + radius_ / 3.0, BlurDirectionHorizontal); |
349 | + frg_source.add_const("TextureStepX", 1.0 / w); |
350 | + load_shaders_from_strings(blur_program_h_, vtx_source.str(), |
351 | + frg_source.str()); |
352 | + } |
353 | + |
354 | + return blur_program_h_; |
355 | + } |
356 | + |
357 | + Program& blur_program_v(unsigned int h) |
358 | + { |
359 | + /* |
360 | + * If the size of the window has changed we must recreate |
361 | + * the shader to contain the correct texture step values. |
362 | + */ |
363 | + if (blur_program_dim_.y() != h || |
364 | + !blur_program_v_.ready()) |
365 | + { |
366 | + blur_program_dim_.y(h); |
367 | + |
368 | + blur_program_v_.release(); |
369 | + |
370 | + ShaderSource vtx_source; |
371 | + ShaderSource frg_source; |
372 | + create_blur_shaders(vtx_source, frg_source, radius_, |
373 | + radius_ / 3.0, BlurDirectionVertical); |
374 | + frg_source.add_const("TextureStepY", 1.0 / h); |
375 | + load_shaders_from_strings(blur_program_v_, vtx_source.str(), |
376 | + frg_source.str()); |
377 | + } |
378 | + |
379 | + return blur_program_v_; |
380 | + } |
381 | + |
382 | + static void |
383 | + create_blur_shaders(ShaderSource& vtx_source, ShaderSource& frg_source, |
384 | + unsigned int radius, float sigma, BlurDirection direction); |
385 | + LibMatrix::uvec2 blur_program_dim_; |
386 | + Program blur_program_; |
387 | + Program blur_program_h_; |
388 | + Program blur_program_v_; |
389 | + unsigned int passes_; |
390 | + unsigned int radius_; |
391 | + bool separable_; |
392 | + RenderClearImage window_contents_; |
393 | +}; |
394 | + |
395 | +void |
396 | +RenderWindowBlur::create_blur_shaders(ShaderSource& vtx_source, |
397 | + ShaderSource& frg_source, unsigned int radius, float sigma, |
398 | + BlurDirection direction) |
399 | +{ |
400 | + vtx_source.append_file(GLCOMPBENCH_DATA_PATH"/desktop.vert"); |
401 | + frg_source.append_file(GLCOMPBENCH_DATA_PATH"/desktop-blur.frag"); |
402 | + |
403 | + /* Don't let the gaussian curve become too narrow */ |
404 | + if (sigma < 1.0) |
405 | + sigma = 1.0; |
406 | + |
407 | + unsigned int side = 2 * radius + 1; |
408 | + |
409 | + for (unsigned int i = 0; i < radius + 1; i++) { |
410 | + float s2 = 2.0 * sigma * sigma; |
411 | + float k = 1.0 / std::sqrt(M_PI * s2) * std::exp( - (static_cast<float>(i) * i) / s2); |
412 | + std::stringstream ss_tmp; |
413 | + ss_tmp << "Kernel" << i; |
414 | + frg_source.add_const(ss_tmp.str(), k); |
415 | + } |
416 | + |
417 | + std::stringstream ss; |
418 | + ss << "result = " << std::endl; |
419 | + |
420 | + if (direction == BlurDirectionHorizontal) { |
421 | + for (unsigned int i = 0; i < side; i++) { |
422 | + int offset = static_cast<int>(i - radius); |
423 | + ss << "texture2D(Texture0, TextureCoord + vec2(" << |
424 | + offset << ".0 * TextureStepX, 0.0)) * Kernel" << |
425 | + std::abs(offset) << " +" << std::endl; |
426 | + } |
427 | + ss << "0.0 ;" << std::endl; |
428 | + } |
429 | + else if (direction == BlurDirectionVertical) { |
430 | + for (unsigned int i = 0; i < side; i++) { |
431 | + int offset = static_cast<int>(i - radius); |
432 | + ss << "texture2D(Texture0, TextureCoord + vec2(0.0, " << |
433 | + offset << ".0 * TextureStepY)) * Kernel" << |
434 | + std::abs(offset) << " +" << std::endl; |
435 | + } |
436 | + ss << "0.0 ;" << std::endl; |
437 | + } |
438 | + else if (direction == BlurDirectionBoth) { |
439 | + for (unsigned int i = 0; i < side; i++) { |
440 | + int ioffset = static_cast<int>(i - radius); |
441 | + for (unsigned int j = 0; j < side; j++) { |
442 | + int joffset = static_cast<int>(j - radius); |
443 | + ss << "texture2D(Texture0, TextureCoord + vec2(" << |
444 | + ioffset << ".0 * TextureStepX, " << |
445 | + joffset << ".0 * TextureStepY))" << |
446 | + " * Kernel" << std::abs(ioffset) << |
447 | + " * Kernel" << std::abs(joffset) << " +" << std::endl; |
448 | + } |
449 | + } |
450 | + ss << " 0.0;" << std::endl; |
451 | + } |
452 | + |
453 | + frg_source.replace("$CONVOLUTION$", ss.str()); |
454 | +} |
455 | + |
456 | +// |
457 | +// Private structure used to avoid contaminating composite-test.h with all of |
458 | +// the CompositeTestSimpleBlur internal classes. |
459 | +// |
460 | +struct BlurPrivate |
461 | +{ |
462 | + RenderScreen screen; |
463 | + RenderClearImage desktop; |
464 | + map<unsigned int, RenderWindowBlur*> windowMap; |
465 | + int screen_width; |
466 | + int screen_height; |
467 | + double lastUpdateTime; |
468 | + float window_scale_factor; |
469 | + |
470 | + BlurPrivate() : |
471 | + desktop(GLCOMPBENCH_DATA_PATH"/background.png"), |
472 | + screen_width(0), |
473 | + screen_height(0), |
474 | + lastUpdateTime(0), |
475 | + window_scale_factor(0.4) {} |
476 | + |
477 | + ~BlurPrivate() {} |
478 | +}; |
479 | + |
480 | +CompositeTestSimpleBlur::CompositeTestSimpleBlur() : |
481 | + CompositeTestSimpleBase("blur", |
482 | + GLCOMPBENCH_DATA_PATH"/desktop.vert", |
483 | + GLCOMPBENCH_DATA_PATH"/desktop.frag") |
484 | +{ |
485 | + options_["use-vbo"] = CompositeTest::Option("use-vbo", "false", |
486 | + "Whether to use VBOs for rendering [true,false]"); |
487 | + options_["window-size"] = CompositeTest::Option("window-size", "0.5", |
488 | + "a scaling factor for the window size (relative to screen screen size) [0.0 - 0.5]"); |
489 | + options_["passes"] = CompositeTest::Option("passes", "1", |
490 | + "the number of effect passes (effect dependent)"); |
491 | + options_["blur-radius"] = CompositeTest::Option("blur-radius", "5", |
492 | + "the blur effect radius (in pixels)"); |
493 | + options_["separable"] = CompositeTest::Option("separable", "true", |
494 | + "use separable convolution for the blur effect"); |
495 | + priv_ = new BlurPrivate(); |
496 | +} |
497 | + |
498 | +CompositeTestSimpleBlur::~CompositeTestSimpleBlur() |
499 | +{ |
500 | + for (map<unsigned int, RenderWindowBlur*>::iterator winIt = priv_->windowMap.begin(); |
501 | + winIt != priv_->windowMap.end(); |
502 | + winIt++) |
503 | + { |
504 | + RenderWindowBlur* ro = winIt->second; |
505 | + delete ro; |
506 | + } |
507 | + delete priv_; |
508 | +} |
509 | + |
510 | +// |
511 | +// Width/height values used to compute buffer sizes are likely to generate |
512 | +// errors in the GL implementation if they are not at least 1, so make sure we |
513 | +// have sane values. |
514 | +// |
515 | +static void |
516 | +clamp_size(vec2& size) |
517 | +{ |
518 | + if (size.x() < 1.0) |
519 | + { |
520 | + size.x(1.0); |
521 | + } |
522 | + if (size.y() < 1.0) |
523 | + { |
524 | + size.y(1.0); |
525 | + } |
526 | +} |
527 | + |
528 | +void |
529 | +CompositeTestSimpleBlur::prepare_for_run(list<CompositeWindow*>& window_list) |
530 | +{ |
531 | + // See how our options tell us to behave... |
532 | + priv_->window_scale_factor = Util::fromString<float>(options_["window-size"].value); |
533 | + unsigned int passes(Util::fromString<unsigned int>(options_["passes"].value)); |
534 | + unsigned int radius(Util::fromString<unsigned int>(options_["blur-radius"].value)); |
535 | + bool separable(options_["separable"].value == "true"); |
536 | + |
537 | + // Ensure we get a transparent clear color for all following operations |
538 | + glClearColor(0.0, 0.0, 0.0, 0.0); |
539 | + glDisable(GL_DEPTH_TEST); |
540 | + glDepthMask(GL_FALSE); |
541 | + |
542 | + priv_->screen.init(program_); |
543 | + priv_->desktop.init(program_); |
544 | + |
545 | + unsigned int visible_windows(num_visible_windows(window_list)); |
546 | + float angular_step(2 * M_PI / visible_windows); |
547 | + vec2 screen_size = priv_->screen.size(); |
548 | + unsigned int i(0); |
549 | + for(list<CompositeWindow*>::iterator iter = window_list.begin(); |
550 | + iter != window_list.end(); |
551 | + ++iter) |
552 | + { |
553 | + CompositeWindow* win = *iter; |
554 | + if (!win->get_texture().is_valid()) |
555 | + { |
556 | + continue; |
557 | + } |
558 | + vec2 window_size(win->width(), win->height()); |
559 | + window_size *= priv_->window_scale_factor; |
560 | + clamp_size(window_size); |
561 | + vec2 corner_offset(window_size / 2.0); |
562 | + RenderWindowBlur* ro = new RenderWindowBlur(passes, radius, separable); |
563 | + ro->init(program_); |
564 | + ro->set_background(win->get_texture().i); |
565 | + vec2 center(screen_size.x() * (0.5 + 0.25 * cos(i * angular_step)), |
566 | + screen_size.y() * (0.5 + 0.25 * sin(i * angular_step))); |
567 | + ro->position(center - corner_offset); |
568 | + ro->resize(window_size); |
569 | + priv_->windowMap.insert(make_pair(win->get_xwindow(), ro)); |
570 | + i++; |
571 | + } |
572 | + // |
573 | + // Ensure the screen is the current rendering target (it might have changed |
574 | + // to a FBO in the previous steps). |
575 | + // |
576 | + priv_->screen.make_current(); |
577 | +} |
578 | + |
579 | +void |
580 | +CompositeTestSimpleBlur::reshape(int width, int height) |
581 | +{ |
582 | + CompositeTestSimpleBase::reshape(width, height); |
583 | + vec2 screen_size(width, height); |
584 | + priv_->screen.resize(screen_size); |
585 | + priv_->desktop.resize(screen_size); |
586 | +} |
587 | + |
588 | +void |
589 | +CompositeTestSimpleBlur::draw(list<CompositeWindow *> &window_list) |
590 | +{ |
591 | + unsigned int visible_windows(num_visible_windows(window_list)); |
592 | + float angular_step(2 * M_PI / visible_windows); |
593 | + vec2 screen_size = priv_->screen.size(); |
594 | + unsigned int i(0); |
595 | + |
596 | + // Ensure we get a transparent clear color for all following operations. |
597 | + glClearColor(0.0, 0.0, 0.0, 0.0); |
598 | + priv_->desktop.clear(); |
599 | + |
600 | + for(list<CompositeWindow*>::iterator cwIt = window_list.begin(); |
601 | + cwIt != window_list.end(); |
602 | + ++cwIt) |
603 | + { |
604 | + CompositeWindow* cw = *cwIt; |
605 | + if (!cw->get_texture().is_valid()) |
606 | + { |
607 | + continue; |
608 | + } |
609 | + unsigned int winHandle(cw->get_xwindow()); |
610 | + map<unsigned int, RenderWindowBlur*>::iterator roIt = priv_->windowMap.find(winHandle); |
611 | + if (roIt == priv_->windowMap.end()) |
612 | + { |
613 | + Log::debug("Failed to find window 0x%x in window map\n", winHandle); |
614 | + continue; |
615 | + } |
616 | + RenderWindowBlur* ro = roIt->second; |
617 | + ro->refresh_window(cw->get_texture().i); |
618 | + vec2 window_size(cw->width(), cw->height()); |
619 | + window_size *= priv_->window_scale_factor; |
620 | + clamp_size(window_size); |
621 | + vec2 corner_offset(window_size / 2.0); |
622 | + vec2 center(screen_size.x() * (0.5 + 0.25 * cos(i * angular_step)), |
623 | + screen_size.y() * (0.5 + 0.25 * sin(i * angular_step))); |
624 | + ro->position(center - corner_offset); |
625 | + ro->resize(window_size); |
626 | + ro->render_to(priv_->desktop); |
627 | + i++; |
628 | + } |
629 | + |
630 | + // Present the results to the screen. |
631 | + priv_->desktop.render_to(priv_->screen); |
632 | +} |
633 | |
634 | === modified file 'src/composite-test-simple-brick.cc' |
635 | --- src/composite-test-simple-brick.cc 2011-09-05 15:23:11 +0000 |
636 | +++ src/composite-test-simple-brick.cc 2012-03-20 16:31:20 +0000 |
637 | @@ -37,9 +37,9 @@ |
638 | const vec2 CompositeTestSimpleBrick::brickPct_(0.90, 0.85); |
639 | |
640 | void |
641 | -CompositeTestSimpleBrick::prepare_for_run() |
642 | +CompositeTestSimpleBrick::prepare_for_run(std::list<CompositeWindow*> &window_list) |
643 | { |
644 | - CompositeTestSimpleBase::prepare_for_run(); |
645 | + CompositeTestSimpleBase::prepare_for_run(window_list); |
646 | |
647 | lightPos_ = LibMatrix::vec4(0.0, 1.0, 1.0, 0.0); |
648 | |
649 | |
650 | === modified file 'src/composite-test-xrender.cc' |
651 | --- src/composite-test-xrender.cc 2011-08-03 17:14:34 +0000 |
652 | +++ src/composite-test-xrender.cc 2012-03-20 16:31:20 +0000 |
653 | @@ -52,8 +52,10 @@ |
654 | } |
655 | |
656 | void |
657 | -CompositeTestXRender::prepare_for_run() |
658 | +CompositeTestXRender::prepare_for_run(std::list<CompositeWindow*> &window_list) |
659 | { |
660 | + CompositeTest::prepare_for_run(window_list); |
661 | + |
662 | if (options_["filter"].value == "bilinear") |
663 | xrender_filter_ = FilterBilinear; |
664 | else |
665 | |
666 | === modified file 'src/composite-test.h' |
667 | --- src/composite-test.h 2011-12-05 18:14:07 +0000 |
668 | +++ src/composite-test.h 2012-03-20 16:31:20 +0000 |
669 | @@ -45,7 +45,11 @@ |
670 | |
671 | virtual void init() {} |
672 | virtual void deinit() {} |
673 | - virtual void prepare_for_run() {} |
674 | + virtual void prepare_for_run(std::list<CompositeWindow*> &window_list) |
675 | + { |
676 | + if (window_list.empty()) |
677 | + return; |
678 | + } |
679 | virtual void draw(std::list<CompositeWindow*> &window_list) |
680 | { |
681 | (void)window_list; |
682 | @@ -105,7 +109,7 @@ |
683 | public: |
684 | CompositeTestDefaultOptions() : CompositeTest("", "") {} |
685 | |
686 | - virtual void prepare_for_run(); |
687 | + virtual void prepare_for_run(std::list<CompositeWindow*> &window_list); |
688 | virtual bool set_option(const std::string &opt, const std::string &val); |
689 | |
690 | protected: |
691 | @@ -121,7 +125,7 @@ |
692 | |
693 | virtual void init(); |
694 | virtual void deinit(); |
695 | - virtual void prepare_for_run(); |
696 | + virtual void prepare_for_run(std::list<CompositeWindow*> &window_list); |
697 | virtual void cleanup(); |
698 | virtual void reshape(int width, int height); |
699 | |
700 | @@ -168,7 +172,7 @@ |
701 | {} |
702 | |
703 | virtual void draw(std::list<CompositeWindow*> &window_list); |
704 | - virtual void prepare_for_run(); |
705 | + virtual void prepare_for_run(std::list<CompositeWindow*> &window_list); |
706 | private: |
707 | LibMatrix::vec4 lightPos_; |
708 | static const LibMatrix::vec3 mortarColor_; |
709 | @@ -187,7 +191,7 @@ |
710 | |
711 | virtual void init(); |
712 | virtual void deinit(); |
713 | - virtual void prepare_for_run(); |
714 | + virtual void prepare_for_run(std::list<CompositeWindow*> &window_list); |
715 | virtual void draw(std::list<CompositeWindow*> &window_list); |
716 | |
717 | private: |
718 | @@ -202,7 +206,7 @@ |
719 | |
720 | virtual void init(); |
721 | virtual void deinit(); |
722 | - virtual void prepare_for_run(); |
723 | + virtual void prepare_for_run(std::list<CompositeWindow*> &window_list); |
724 | virtual void draw(std::list<CompositeWindow*> &window_list); |
725 | |
726 | private: |
727 | @@ -225,4 +229,19 @@ |
728 | virtual bool init_shaders(ShaderSource& vtx, ShaderSource& frg); |
729 | }; |
730 | |
731 | +struct BlurPrivate; |
732 | + |
733 | +class CompositeTestSimpleBlur : public CompositeTestSimpleBase |
734 | +{ |
735 | + static const std::string fade_bias_name_; |
736 | + BlurPrivate* priv_; |
737 | +public: |
738 | + CompositeTestSimpleBlur(); |
739 | + ~CompositeTestSimpleBlur(); |
740 | + |
741 | + virtual void draw(std::list<CompositeWindow*> &window_list); |
742 | + virtual void reshape(int width, int height); |
743 | + virtual void prepare_for_run(std::list<CompositeWindow*> &window_list); |
744 | +}; |
745 | + |
746 | #endif // COMPOSITE_TEST_H_ |
747 | |
748 | === modified file 'src/glcompbench.cc' |
749 | --- src/glcompbench.cc 2012-02-17 11:51:23 +0000 |
750 | +++ src/glcompbench.cc 2012-03-20 16:31:20 +0000 |
751 | @@ -45,6 +45,7 @@ |
752 | static const char *default_benchmarks[] = { |
753 | "default", |
754 | "fade", |
755 | + "blur", |
756 | "brick", |
757 | "pixman", |
758 | "xrender", |
759 | @@ -195,6 +196,7 @@ |
760 | |
761 | Benchmark::register_test(*new CompositeTestDefaultOptions()); |
762 | Benchmark::register_test(*new CompositeTestSimpleDefault()); |
763 | + Benchmark::register_test(*new CompositeTestSimpleBlur()); |
764 | Benchmark::register_test(*new CompositeTestSimpleFade()); |
765 | Benchmark::register_test(*new CompositeTestSimpleBrick()); |
766 | Benchmark::register_test(*new CompositeTestPixman()); |
767 | |
768 | === added file 'src/render-object.cc' |
769 | --- src/render-object.cc 1970-01-01 00:00:00 +0000 |
770 | +++ src/render-object.cc 2012-03-20 16:31:20 +0000 |
771 | @@ -0,0 +1,282 @@ |
772 | +/* |
773 | + * Copyright © 2012 Linaro Limited |
774 | + * |
775 | + * This file is part of glcompbench. |
776 | + * |
777 | + * glcompbench is free software: you can redistribute it and/or modify |
778 | + * it under the terms of the GNU General Public License as published by |
779 | + * the Free Software Foundation, either version 3 of the License, or |
780 | + * (at your option) any later version. |
781 | + * |
782 | + * glcompbench is distributed in the hope that it will be useful, |
783 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
784 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
785 | + * GNU General Public License for more details. |
786 | + * |
787 | + * You should have received a copy of the GNU General Public License |
788 | + * along with glcompbench. If not, see <http://www.gnu.org/licenses/>. |
789 | + * |
790 | + * Authors: |
791 | + * Alexandros Frantzis <alexandros.frantzis@linaro.org> |
792 | + * Jesse Barker <jesse.barker@linaro.org> |
793 | + */ |
794 | + |
795 | +#include "log.h" |
796 | +#include "render-object.h" |
797 | +#include "shader-source.h" |
798 | +#include "gl-headers.h" |
799 | +#include "texture.h" |
800 | + |
801 | +using LibMatrix::vec2; |
802 | +using std::string; |
803 | + |
804 | +bool |
805 | +RenderObject::load_shaders_from_strings(Program &program, |
806 | + const string &vtx_shader, const string &frg_shader) |
807 | +{ |
808 | + program.init(); |
809 | + |
810 | + Log::debug("Loading vertex shader:\n%s", vtx_shader.c_str()); |
811 | + |
812 | + program.addShader(GL_VERTEX_SHADER, vtx_shader); |
813 | + if (!program.valid()) { |
814 | + Log::error("Failed to add vertex shader:\n %s\n", "RenderObject: ", |
815 | + program.errorMessage().c_str()); |
816 | + program.release(); |
817 | + return false; |
818 | + } |
819 | + |
820 | + Log::debug("Loading fragment shader:\n%s", frg_shader.c_str()); |
821 | + |
822 | + program.addShader(GL_FRAGMENT_SHADER, frg_shader); |
823 | + if (!program.valid()) { |
824 | + Log::error("Failed to add fragment shader:\n %s\n", |
825 | + program.errorMessage().c_str()); |
826 | + program.release(); |
827 | + return false; |
828 | + } |
829 | + |
830 | + program.build(); |
831 | + if (!program.ready()) { |
832 | + Log::error("Failed to link program: %s\n", |
833 | + program.errorMessage().c_str()); |
834 | + program.release(); |
835 | + return false; |
836 | + } |
837 | + |
838 | + return true; |
839 | +} |
840 | + |
841 | +void |
842 | +RenderObject::init(Program& default_program) |
843 | +{ |
844 | + default_program_ = &default_program; |
845 | + |
846 | + // Create a texture to use as a render target |
847 | + glGenTextures(1, &texture_); |
848 | + glBindTexture(GL_TEXTURE_2D, texture_); |
849 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
850 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
851 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
852 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
853 | + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.x(), size_.y(), 0, |
854 | + GL_RGBA, GL_UNSIGNED_BYTE, 0); |
855 | + |
856 | + // Create a FBO |
857 | + glGenFramebuffers(1, &fbo_); |
858 | + glBindFramebuffer(GL_FRAMEBUFFER, fbo_); |
859 | + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
860 | + GL_TEXTURE_2D, texture_, 0); |
861 | + |
862 | + glBindFramebuffer(GL_FRAMEBUFFER, 0); |
863 | + |
864 | + texture_contents_invalid_ = true; |
865 | +} |
866 | + |
867 | +void |
868 | +RenderObject::release() |
869 | +{ |
870 | + // Release resources |
871 | + if (texture_ != 0) |
872 | + { |
873 | + glDeleteTextures(1, &texture_); |
874 | + texture_ = 0; |
875 | + } |
876 | + if (fbo_ != 0) |
877 | + { |
878 | + glDeleteFramebuffers(1, &fbo_); |
879 | + fbo_ = 0; |
880 | + } |
881 | +} |
882 | + |
883 | +void |
884 | +RenderObject::make_current() |
885 | +{ |
886 | + glBindFramebuffer(GL_FRAMEBUFFER, fbo_); |
887 | + glViewport(0, 0, size_.x(), size_.y()); |
888 | +} |
889 | + |
890 | +void |
891 | +RenderObject::resize(const vec2& size) |
892 | +{ |
893 | + /// Recreate the backing texture with correct size |
894 | + if (size_ != size) { |
895 | + size_ = size; |
896 | + glBindTexture(GL_TEXTURE_2D, texture_); |
897 | + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.x(), size_.y(), 0, |
898 | + GL_RGBA, GL_UNSIGNED_BYTE, 0); |
899 | + texture_contents_invalid_ = true; |
900 | + } |
901 | + |
902 | + if (texture_contents_invalid_) { |
903 | + clear(); |
904 | + texture_contents_invalid_ = false; |
905 | + } |
906 | +} |
907 | + |
908 | +void |
909 | +RenderObject::clear() |
910 | +{ |
911 | + make_current(); |
912 | + glClear(GL_COLOR_BUFFER_BIT); |
913 | +} |
914 | + |
915 | +void |
916 | +RenderObject::render_to(RenderObject& target) |
917 | +{ |
918 | + render_to(target, *default_program_); |
919 | +} |
920 | + |
921 | +void |
922 | +RenderObject::render_to(RenderObject& target, Program& program) |
923 | +{ |
924 | + vec2 anchor(pos_); |
925 | + vec2 ll(pos_ - anchor); |
926 | + vec2 ur(pos_ + size_ - anchor); |
927 | + |
928 | + /* Calculate new position according to rotation value */ |
929 | + GLfloat position[2 * 4] = { |
930 | + rotate_x(ll.x(), ll.y()) + anchor.x(), rotate_y(ll.x(), ll.y()) + anchor.y(), |
931 | + rotate_x(ur.x(), ll.y()) + anchor.x(), rotate_y(ur.x(), ll.y()) + anchor.y(), |
932 | + rotate_x(ll.x(), ur.y()) + anchor.x(), rotate_y(ll.x(), ur.y()) + anchor.y(), |
933 | + rotate_x(ur.x(), ur.y()) + anchor.x(), rotate_y(ur.x(), ur.y()) + anchor.y(), |
934 | + }; |
935 | + |
936 | + /* Normalize position and write back to array */ |
937 | + for (unsigned int i = 0; i < 4; i++) { |
938 | + unsigned int idx1(2 * i); |
939 | + unsigned int idx2(2 * i + 1); |
940 | + const vec2& v2(target.normalize_position(vec2(position[idx1], position[idx2]))); |
941 | + position[idx1] = v2.x(); |
942 | + position[idx2] = v2.y(); |
943 | + } |
944 | + |
945 | + static const GLfloat texcoord[2 * 4] = { |
946 | + 0.0, 0.0, |
947 | + 1.0, 0.0, |
948 | + 0.0, 1.0, |
949 | + 1.0, 1.0, |
950 | + }; |
951 | + |
952 | + target.make_current(); |
953 | + |
954 | + glActiveTexture(GL_TEXTURE0); |
955 | + glBindTexture(GL_TEXTURE_2D, texture_); |
956 | + draw_quad_with_program(position, texcoord, program); |
957 | +} |
958 | + |
959 | +void |
960 | +RenderObject::draw_quad_with_program(const float *position, |
961 | + const float *texcoord, Program &program) |
962 | +{ |
963 | + int pos_index = program["position"].location(); |
964 | + int tex_index = program["texcoord"].location(); |
965 | + |
966 | + program.start(); |
967 | + |
968 | + glEnableVertexAttribArray(pos_index); |
969 | + glEnableVertexAttribArray(tex_index); |
970 | + glVertexAttribPointer(pos_index, 2, |
971 | + GL_FLOAT, GL_FALSE, 0, position); |
972 | + glVertexAttribPointer(tex_index, 2, |
973 | + GL_FLOAT, GL_FALSE, 0, texcoord); |
974 | + |
975 | + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
976 | + |
977 | + glDisableVertexAttribArray(tex_index); |
978 | + glDisableVertexAttribArray(pos_index); |
979 | + |
980 | + program.stop(); |
981 | +} |
982 | + |
983 | +RenderClearImage::RenderClearImage(const string& image_file) : |
984 | + RenderObject(), background_texture_name_(image_file), |
985 | + background_texture_(0), background_is_image_(false), |
986 | + texcoord_(texcoord_window_) |
987 | +{ |
988 | + if (!background_texture_name_.empty()) |
989 | + { |
990 | + background_is_image_ = true; |
991 | + texcoord_ = texcoord_image_; |
992 | + } |
993 | +} |
994 | + |
995 | +RenderClearImage::RenderClearImage() : |
996 | + RenderObject(), |
997 | + background_texture_(0), background_is_image_(false), |
998 | + texcoord_(texcoord_window_) |
999 | +{ |
1000 | +} |
1001 | + |
1002 | +void |
1003 | +RenderClearImage::init(Program& program) |
1004 | +{ |
1005 | + RenderObject::init(program); |
1006 | + if (background_is_image_) |
1007 | + { |
1008 | + // Load the image into a texture. |
1009 | + Texture::load(background_texture_name_, |
1010 | + &background_texture_, GL_LINEAR, GL_LINEAR, 0); |
1011 | + } |
1012 | +} |
1013 | + |
1014 | +void |
1015 | +RenderClearImage::set_background(unsigned int background_texture) |
1016 | +{ |
1017 | + background_texture_ = background_texture; |
1018 | +} |
1019 | + |
1020 | +void |
1021 | +RenderClearImage::clear() |
1022 | +{ |
1023 | + make_current(); |
1024 | + glClear(GL_COLOR_BUFFER_BIT); |
1025 | + |
1026 | + glActiveTexture(GL_TEXTURE0); |
1027 | + glBindTexture(GL_TEXTURE_2D, background_texture_); |
1028 | + |
1029 | + glEnable(GL_BLEND); |
1030 | + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
1031 | + draw_quad_with_program(position_, texcoord_, *default_program_); |
1032 | + glDisable(GL_BLEND); |
1033 | +} |
1034 | + |
1035 | +const float RenderClearImage::position_[8] = { |
1036 | + -1.0, -1.0, |
1037 | + 1.0, -1.0, |
1038 | + -1.0, 1.0, |
1039 | + 1.0, 1.0, |
1040 | +}; |
1041 | +const float RenderClearImage::texcoord_image_[8] = { |
1042 | + 0.0, 0.0, |
1043 | + 1.0, 0.0, |
1044 | + 0.0, 1.0, |
1045 | + 1.0, 1.0, |
1046 | +}; |
1047 | +const float RenderClearImage::texcoord_window_[8] = { |
1048 | + 0.0, 1.0, |
1049 | + 1.0, 1.0, |
1050 | + 0.0, 0.0, |
1051 | + 1.0, 0.0, |
1052 | +}; |
1053 | + |
1054 | |
1055 | === added file 'src/render-object.h' |
1056 | --- src/render-object.h 1970-01-01 00:00:00 +0000 |
1057 | +++ src/render-object.h 2012-03-20 16:31:20 +0000 |
1058 | @@ -0,0 +1,152 @@ |
1059 | +/* |
1060 | + * Copyright © 2012 Linaro Limited |
1061 | + * |
1062 | + * This file is part of glcompbench. |
1063 | + * |
1064 | + * glcompbench is free software: you can redistribute it and/or modify |
1065 | + * it under the terms of the GNU General Public License as published by |
1066 | + * the Free Software Foundation, either version 3 of the License, or |
1067 | + * (at your option) any later version. |
1068 | + * |
1069 | + * glcompbench is distributed in the hope that it will be useful, |
1070 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1071 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1072 | + * GNU General Public License for more details. |
1073 | + * |
1074 | + * You should have received a copy of the GNU General Public License |
1075 | + * along with glcompbench. If not, see <http://www.gnu.org/licenses/>. |
1076 | + * |
1077 | + * Authors: |
1078 | + * Alexandros Frantzis <alexandros.frantzis@linaro.org> |
1079 | + * Jesse Barker <jesse.barker@linaro.org> |
1080 | + */ |
1081 | +#ifndef RENDER_OBJECT_H_ |
1082 | +#define RENDER_OBJECT_H_ |
1083 | + |
1084 | +#include "vec.h" |
1085 | +#include "program.h" |
1086 | + |
1087 | +// |
1088 | +// A RenderObject represents a source and target of rendering |
1089 | +// operations. |
1090 | +// |
1091 | +class RenderObject |
1092 | +{ |
1093 | +public: |
1094 | + RenderObject() : |
1095 | + texture_(0), fbo_(0), rotation_rad_(0), |
1096 | + texture_contents_invalid_(true) {} |
1097 | + |
1098 | + // Public interfaces with default implementations |
1099 | + virtual void init(Program& default_program); |
1100 | + virtual void release(); |
1101 | + virtual void resize(const LibMatrix::vec2& size); |
1102 | + virtual void clear(); |
1103 | + virtual void render_to(RenderObject& target); |
1104 | + virtual void render_to(RenderObject& target, Program& program); |
1105 | + |
1106 | + // Public methods |
1107 | + void make_current(); |
1108 | + |
1109 | + // Get/set methods |
1110 | + void position(const LibMatrix::vec2& pos) { pos_ = pos; } |
1111 | + const LibMatrix::vec2& position() { return pos_; } |
1112 | + const LibMatrix::vec2& size() { return size_; } |
1113 | + unsigned int texture() { return texture_; } |
1114 | + |
1115 | + // Normalizes a position from [0, size] to [-1.0, 1.0] |
1116 | + LibMatrix::vec2 normalize_position(const LibMatrix::vec2& pos) |
1117 | + { |
1118 | + return pos * 2.0 / size_ - 1.0; |
1119 | + } |
1120 | + |
1121 | + // Normalizes a position from [0, size] to [0.0, 1.0] |
1122 | + LibMatrix::vec2 normalize_texcoord(const LibMatrix::vec2& pos) |
1123 | + { |
1124 | + return pos / size_; |
1125 | + } |
1126 | + |
1127 | + void rotation(float degrees) |
1128 | + { |
1129 | + rotation_rad_ = (M_PI * degrees / 180.0); |
1130 | + } |
1131 | + |
1132 | +protected: |
1133 | + static bool load_shaders_from_strings(Program& program, |
1134 | + const std::string& vtx_shader, const std::string& frg_shader); |
1135 | + static void draw_quad_with_program(const float *position, const float *texcoord, |
1136 | + Program &program); |
1137 | + |
1138 | + LibMatrix::vec2 pos_; |
1139 | + LibMatrix::vec2 size_; |
1140 | + unsigned int texture_; |
1141 | + unsigned int fbo_; |
1142 | + Program* default_program_; |
1143 | + |
1144 | +private: |
1145 | + float rotate_x(float x, float y) |
1146 | + { |
1147 | + return x * cos(rotation_rad_) - y * sin(rotation_rad_); |
1148 | + } |
1149 | + |
1150 | + float rotate_y(float x, float y) |
1151 | + { |
1152 | + return x * sin(rotation_rad_) + y * cos(rotation_rad_); |
1153 | + } |
1154 | + |
1155 | + float rotation_rad_; |
1156 | + bool texture_contents_invalid_; |
1157 | +}; |
1158 | + |
1159 | +// |
1160 | +// A RenderObject representing the screen. |
1161 | +// |
1162 | +// Rendering to this objects renders to the screen framebuffer. |
1163 | +// |
1164 | +class RenderScreen : public RenderObject |
1165 | +{ |
1166 | +public: |
1167 | + // Our own implementation of the init and release interfaces. |
1168 | + virtual void init(Program& program) { default_program_ = &program; } |
1169 | + virtual void release() {} |
1170 | +}; |
1171 | + |
1172 | +// |
1173 | +// A RenderObject with a background image. |
1174 | +// |
1175 | +// The image is drawn to the RenderObject automatically when the |
1176 | +// object is cleared, resized etc. The background texture for this object |
1177 | +// can either be an image loaded from a named file (in which case the texture |
1178 | +// name is created during the load), or it can be set from an existing texture |
1179 | +// object. |
1180 | +// |
1181 | +class RenderClearImage : public RenderObject |
1182 | +{ |
1183 | +public: |
1184 | + RenderClearImage(); |
1185 | + RenderClearImage(const std::string& image_file); |
1186 | + |
1187 | + // Our own implementation of the init interface. |
1188 | + virtual void init(Program& program); |
1189 | + |
1190 | + // Sets the background texture name. |
1191 | + void set_background(unsigned int background_texture); |
1192 | + |
1193 | + // "Clears" the object to the contents of the background texture. |
1194 | + void clear(); |
1195 | + |
1196 | +private: |
1197 | + std::string background_texture_name_; |
1198 | + unsigned int background_texture_; |
1199 | + bool background_is_image_; |
1200 | + // Vertex position is always the same for any rendering with this object, |
1201 | + // however, texture coordinates vary depending upon whether the texture |
1202 | + // came from a static image loaded from a file (for example) or a window |
1203 | + // system pixmap (inverted sense of y direction). |
1204 | + const float* texcoord_; |
1205 | + static const float position_[8]; |
1206 | + static const float texcoord_image_[8]; |
1207 | + static const float texcoord_window_[8]; |
1208 | +}; |
1209 | + |
1210 | +#endif // RENDER_OBJECT_H_ |
1211 | |
1212 | === added file 'src/texture.cc' |
1213 | --- src/texture.cc 1970-01-01 00:00:00 +0000 |
1214 | +++ src/texture.cc 2012-03-20 16:31:20 +0000 |
1215 | @@ -0,0 +1,201 @@ |
1216 | +/* |
1217 | + * Copyright © 2008 Ben Smith |
1218 | + * Copyright © 2010-2011 Linaro Limited |
1219 | + * |
1220 | + * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark. |
1221 | + * |
1222 | + * glmark2 is free software: you can redistribute it and/or modify it under the |
1223 | + * terms of the GNU General Public License as published by the Free Software |
1224 | + * Foundation, either version 3 of the License, or (at your option) any later |
1225 | + * version. |
1226 | + * |
1227 | + * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY |
1228 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
1229 | + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
1230 | + * details. |
1231 | + * |
1232 | + * You should have received a copy of the GNU General Public License along with |
1233 | + * glmark2. If not, see <http://www.gnu.org/licenses/>. |
1234 | + * |
1235 | + * Authors: |
1236 | + * Ben Smith (original glmark benchmark) |
1237 | + * Alexandros Frantzis (glmark2) |
1238 | + */ |
1239 | +#include "texture.h" |
1240 | +#include "log.h" |
1241 | +#include "util.h" |
1242 | + |
1243 | +#include <cstdarg> |
1244 | +#include <png.h> |
1245 | +#include <memory> |
1246 | + |
1247 | +class PNGState |
1248 | +{ |
1249 | +public: |
1250 | + PNGState() : |
1251 | + png_(0), |
1252 | + info_(0), |
1253 | + rows_(0) {} |
1254 | + ~PNGState() |
1255 | + { |
1256 | + if (png_) |
1257 | + { |
1258 | + png_destroy_read_struct(&png_, &info_, 0); |
1259 | + } |
1260 | + } |
1261 | + bool gotData(const std::string& filename) |
1262 | + { |
1263 | + static const int png_transforms = PNG_TRANSFORM_STRIP_16 | |
1264 | + PNG_TRANSFORM_GRAY_TO_RGB | |
1265 | + PNG_TRANSFORM_PACKING | |
1266 | + PNG_TRANSFORM_EXPAND; |
1267 | + |
1268 | + Log::debug("Reading PNG file %s\n", filename.c_str()); |
1269 | + |
1270 | + const std::auto_ptr<std::istream> is_ptr(Util::get_resource(filename)); |
1271 | + if (!(*is_ptr)) { |
1272 | + Log::error("Cannot open file %s!\n", filename.c_str()); |
1273 | + return false; |
1274 | + } |
1275 | + |
1276 | + /* Set up all the libpng structs we need */ |
1277 | + png_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); |
1278 | + if (!png_) { |
1279 | + Log::error("Couldn't create libpng read struct\n"); |
1280 | + return false; |
1281 | + } |
1282 | + |
1283 | + info_ = png_create_info_struct(png_); |
1284 | + if (!info_) { |
1285 | + Log::error("Couldn't create libpng info struct\n"); |
1286 | + return false; |
1287 | + } |
1288 | + |
1289 | + /* Set up libpng error handling */ |
1290 | + if (setjmp(png_jmpbuf(png_))) { |
1291 | + Log::error("libpng error while reading file %s\n", filename.c_str()); |
1292 | + return false; |
1293 | + } |
1294 | + |
1295 | + /* Read the image information and data */ |
1296 | + png_set_read_fn(png_, reinterpret_cast<voidp>(is_ptr.get()), png_read_fn); |
1297 | + |
1298 | + png_read_png(png_, info_, png_transforms, 0); |
1299 | + |
1300 | + rows_ = png_get_rows(png_, info_); |
1301 | + |
1302 | + return true; |
1303 | + } |
1304 | + unsigned int width() const { return png_get_image_width(png_, info_); } |
1305 | + unsigned int height() const { return png_get_image_height(png_, info_); } |
1306 | + unsigned int pixelBytes() const |
1307 | + { |
1308 | + if (png_get_color_type(png_, info_) == PNG_COLOR_TYPE_RGB) |
1309 | + { |
1310 | + return 3; |
1311 | + } |
1312 | + return 4; |
1313 | + } |
1314 | + const unsigned char* row(unsigned int idx) const { return rows_[idx]; } |
1315 | +private: |
1316 | + static void png_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) |
1317 | + { |
1318 | + std::istream *is = reinterpret_cast<std::istream*>(png_get_io_ptr(png_ptr)); |
1319 | + is->read(reinterpret_cast<char *>(data), length); |
1320 | + } |
1321 | + png_structp png_; |
1322 | + png_infop info_; |
1323 | + png_bytepp rows_; |
1324 | +}; |
1325 | + |
1326 | +class ImageData { |
1327 | + void resize(unsigned int w, unsigned int h, unsigned int b) |
1328 | + { |
1329 | + width = w; |
1330 | + height = h; |
1331 | + bpp = b; |
1332 | + delete [] pixels; |
1333 | + pixels = new unsigned char[bpp * width * height]; |
1334 | + } |
1335 | + |
1336 | +public: |
1337 | + ImageData() : pixels(0), width(0), height(0), bpp(0) {} |
1338 | + ~ImageData() { delete [] pixels; } |
1339 | + bool load_png(const std::string &filename); |
1340 | + |
1341 | + unsigned char *pixels; |
1342 | + unsigned int width; |
1343 | + unsigned int height; |
1344 | + unsigned int bpp; |
1345 | +}; |
1346 | + |
1347 | +bool |
1348 | +ImageData::load_png(const std::string &filename) |
1349 | +{ |
1350 | + PNGState png; |
1351 | + bool ret = png.gotData(filename); |
1352 | + if (!ret) |
1353 | + { |
1354 | + return ret; |
1355 | + } |
1356 | + |
1357 | + resize(png.width(), png.height(), png.pixelBytes()); |
1358 | + |
1359 | + Log::debug(" Height: %d Width: %d Bpp: %d\n", width, height, bpp); |
1360 | + |
1361 | + /* |
1362 | + * Copy the image data to a contiguous memory area suitable for texture |
1363 | + * upload. |
1364 | + */ |
1365 | + for (unsigned int i = 0; i < height; i++) { |
1366 | + memcpy(&pixels[bpp * width * i], |
1367 | + png.row(height - i - 1), |
1368 | + width * bpp); |
1369 | + } |
1370 | + |
1371 | + return ret; |
1372 | +} |
1373 | + |
1374 | +static void |
1375 | +setup_texture(GLuint *tex, ImageData &image, GLint min_filter, GLint mag_filter) |
1376 | +{ |
1377 | + GLenum format = image.bpp == 3 ? GL_RGB : GL_RGBA; |
1378 | + |
1379 | + glGenTextures(1, tex); |
1380 | + glBindTexture(GL_TEXTURE_2D, *tex); |
1381 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); |
1382 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); |
1383 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1384 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1385 | + glTexImage2D(GL_TEXTURE_2D, 0, format, image.width, image.height, 0, |
1386 | + format, GL_UNSIGNED_BYTE, image.pixels); |
1387 | + |
1388 | + if ((min_filter != GL_NEAREST && min_filter != GL_LINEAR) || |
1389 | + (mag_filter != GL_NEAREST && mag_filter != GL_LINEAR)) |
1390 | + { |
1391 | + glGenerateMipmap(GL_TEXTURE_2D); |
1392 | + } |
1393 | +} |
1394 | + |
1395 | +bool |
1396 | +Texture::load(const std::string &filename, GLuint *pTexture, ...) |
1397 | +{ |
1398 | + ImageData image; |
1399 | + |
1400 | + if (!image.load_png(filename)) |
1401 | + return false; |
1402 | + |
1403 | + va_list ap; |
1404 | + va_start(ap, pTexture); |
1405 | + GLint arg; |
1406 | + |
1407 | + while ((arg = va_arg(ap, GLint)) != 0) { |
1408 | + GLint arg2 = va_arg(ap, GLint); |
1409 | + setup_texture(pTexture, image, arg, arg2); |
1410 | + pTexture++; |
1411 | + } |
1412 | + |
1413 | + va_end(ap); |
1414 | + |
1415 | + return true; |
1416 | +} |
1417 | |
1418 | === added file 'src/texture.h' |
1419 | --- src/texture.h 1970-01-01 00:00:00 +0000 |
1420 | +++ src/texture.h 2012-03-20 16:31:20 +0000 |
1421 | @@ -0,0 +1,37 @@ |
1422 | +/* |
1423 | + * Copyright © 2008 Ben Smith |
1424 | + * Copyright © 2010-2011 Linaro Limited |
1425 | + * |
1426 | + * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark. |
1427 | + * |
1428 | + * glmark2 is free software: you can redistribute it and/or modify it under the |
1429 | + * terms of the GNU General Public License as published by the Free Software |
1430 | + * Foundation, either version 3 of the License, or (at your option) any later |
1431 | + * version. |
1432 | + * |
1433 | + * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY |
1434 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
1435 | + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
1436 | + * details. |
1437 | + * |
1438 | + * You should have received a copy of the GNU General Public License along with |
1439 | + * glmark2. If not, see <http://www.gnu.org/licenses/>. |
1440 | + * |
1441 | + * Authors: |
1442 | + * Ben Smith (original glmark benchmark) |
1443 | + * Alexandros Frantzis (glmark2) |
1444 | + */ |
1445 | +#ifndef GLMARK2_TEXTURE_H_ |
1446 | +#define GLMARK2_TEXTURE_H_ |
1447 | + |
1448 | +#include "gl-headers.h" |
1449 | + |
1450 | +#include <string> |
1451 | + |
1452 | +class Texture |
1453 | +{ |
1454 | +public: |
1455 | + static bool load(const std::string &filename, GLuint *pTexture, ...); |
1456 | +}; |
1457 | + |
1458 | +#endif |
1459 | |
1460 | === modified file 'src/wscript_build' |
1461 | --- src/wscript_build 2011-12-12 13:18:23 +0000 |
1462 | +++ src/wscript_build 2012-03-20 16:31:20 +0000 |
1463 | @@ -49,7 +49,7 @@ |
1464 | source = common_sources + egl_sources, |
1465 | target = 'glcompbench-egl-gl', |
1466 | uselib = ['egl', 'gl'] + common_libs, |
1467 | - use = ['matrix'], |
1468 | + use = ['matrix', 'libpng12'], |
1469 | lib = ['m'], |
1470 | defines = ['USE_EGL', 'USE_GL'] |
1471 | ) |
1472 | @@ -60,7 +60,7 @@ |
1473 | source = common_sources + egl_sources, |
1474 | target = 'glcompbench-egl-es2', |
1475 | uselib = ['egl', 'glesv2'] + common_libs, |
1476 | - use = ['matrix-es2'], |
1477 | + use = ['matrix-es2', 'libpng12'], |
1478 | lib = ['m'], |
1479 | defines = ['USE_EGL', 'USE_GLES2'] |
1480 | ) |
1481 | @@ -71,7 +71,7 @@ |
1482 | source = common_sources + glx_sources, |
1483 | target = 'glcompbench-glx', |
1484 | uselib = ['gl'] + common_libs, |
1485 | - use = ['matrix'], |
1486 | + use = ['matrix', 'libpng12'], |
1487 | lib = ['m'], |
1488 | defines = ['USE_GLX', 'USE_GL'] |
1489 | ) |
1490 | @@ -82,7 +82,7 @@ |
1491 | source = common_sources + egl_sources + glx_sources, |
1492 | target = 'glcompbench', |
1493 | uselib = ['glproxy'] + common_libs, |
1494 | - use = ['matrix-glproxy'], |
1495 | + use = ['matrix-glproxy', 'libpng12'], |
1496 | lib = ['m'], |
1497 | defines = ['USE_EGL', 'USE_GLES2', 'USE_GLX', 'USE_GL', 'USE_GLPROXY'] |
1498 | ) |
1499 | |
1500 | === modified file 'wscript' |
1501 | --- wscript 2012-02-16 12:19:54 +0000 |
1502 | +++ wscript 2012-03-20 16:31:20 +0000 |
1503 | @@ -64,7 +64,7 @@ |
1504 | # Check required packages |
1505 | req_pkgs = [('x11', 'x11'), ('xdamage', 'xdamage'), |
1506 | ('xcomposite', 'xcomposite'), ('pixman-1', 'pixman'), |
1507 | - ('xext', 'xext'), ('xrender', 'xrender')] |
1508 | + ('xext', 'xext'), ('xrender', 'xrender'), ('libpng12', 'libpng12')] |
1509 | for (pkg, uselib) in req_pkgs: |
1510 | ctx.check_cfg(package = pkg, uselib_store = uselib, args = '--cflags --libs', |
1511 | mandatory = True) |