Merge lp:~glcompbench-dev/glcompbench/blur into lp:glcompbench

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
Reviewer Review Type Date Requested Status
Alexandros Frantzis Pending
Review via email: mp+98238@code.launchpad.net

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.
lp:~glcompbench-dev/glcompbench/blur updated
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'
2Binary 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'
53Binary 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)

Subscribers

People subscribed via source and target branches

to all changes: