Merge lp:~linaro-graphics-wg/glmark2/canvas-fbo into lp:glmark2/2011.11
- canvas-fbo
- Merge into trunk
Proposed by
Alexandros Frantzis
Status: | Merged |
---|---|
Merged at revision: | 202 |
Proposed branch: | lp:~linaro-graphics-wg/glmark2/canvas-fbo |
Merge into: | lp:glmark2/2011.11 |
Diff against target: |
724 lines (+393/-35) 14 files modified
doc/glmark2.1.in (+5/-3) src/canvas-x11-egl.cpp (+15/-12) src/canvas-x11-egl.h (+1/-0) src/canvas-x11-glx.cpp (+13/-0) src/canvas-x11-glx.h (+1/-0) src/canvas-x11.cpp (+210/-7) src/canvas-x11.h (+35/-1) src/canvas.h (+17/-1) src/gl-headers.cpp (+20/-0) src/gl-headers.h (+25/-1) src/main.cpp (+2/-0) src/options.cpp (+35/-6) src/options.h (+10/-1) src/scene-desktop.cpp (+4/-3) |
To merge this branch: | bzr merge lp:~linaro-graphics-wg/glmark2/canvas-fbo |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jesse Barker | Approve | ||
Review via email: mp+98416@code.launchpad.net |
Commit message
Description of the change
Add support for rendering to an off-screen surface.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'doc/glmark2.1.in' |
2 | --- doc/glmark2.1.in 2012-02-16 11:45:12 +0000 |
3 | +++ doc/glmark2.1.in 2012-03-20 14:03:47 +0000 |
4 | @@ -21,9 +21,11 @@ |
5 | Run a quick output validation test instead of |
6 | running the benchmarks |
7 | .TP |
8 | -\fB\-\-no\-swap\-buffers\fR |
9 | -Don't update the screen by swapping the front and |
10 | -back buffer, use glFinish() instead |
11 | +\fB\-\-frame-end\fR |
12 | +How to end a frame [default,none,swap,finish,readpixels] |
13 | +.TP |
14 | +\fB\-\-off-screen\fR |
15 | +Render to an off-screen surface |
16 | .TP |
17 | \fB\-\-reuse\-context\fR |
18 | Use a single context for all scenes |
19 | |
20 | === modified file 'src/canvas-x11-egl.cpp' |
21 | --- src/canvas-x11-egl.cpp 2012-01-04 16:51:20 +0000 |
22 | +++ src/canvas-x11-egl.cpp 2012-03-20 14:03:47 +0000 |
23 | @@ -86,6 +86,20 @@ |
24 | return true; |
25 | } |
26 | |
27 | +void |
28 | +CanvasX11EGL::get_glvisualinfo(GLVisualInfo &gl_visinfo) |
29 | +{ |
30 | + if (!ensure_egl_config()) |
31 | + return; |
32 | + |
33 | + eglGetConfigAttrib(egl_display_, egl_config_, EGL_BUFFER_SIZE, &gl_visinfo.buffer_size); |
34 | + eglGetConfigAttrib(egl_display_, egl_config_, EGL_RED_SIZE, &gl_visinfo.red_size); |
35 | + eglGetConfigAttrib(egl_display_, egl_config_, EGL_GREEN_SIZE, &gl_visinfo.green_size); |
36 | + eglGetConfigAttrib(egl_display_, egl_config_, EGL_BLUE_SIZE, &gl_visinfo.blue_size); |
37 | + eglGetConfigAttrib(egl_display_, egl_config_, EGL_ALPHA_SIZE, &gl_visinfo.alpha_size); |
38 | + eglGetConfigAttrib(egl_display_, egl_config_, EGL_DEPTH_SIZE, &gl_visinfo.depth_size); |
39 | +} |
40 | + |
41 | /******************* |
42 | * Private methods * |
43 | *******************/ |
44 | @@ -256,18 +270,7 @@ |
45 | CanvasX11EGL::init_gl_extensions() |
46 | { |
47 | #if USE_GLESv2 |
48 | - /* |
49 | - * Parse the extensions we care about from the extension string. |
50 | - * Don't even bother to get function pointers until we know the |
51 | - * extension is present. |
52 | - */ |
53 | - std::string extString; |
54 | - const char* exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); |
55 | - if (exts) { |
56 | - extString = exts; |
57 | - } |
58 | - |
59 | - if (extString.find("GL_OES_mapbuffer") != std::string::npos) { |
60 | + if (GLExtensions::support("GL_OES_mapbuffer")) { |
61 | GLExtensions::MapBuffer = |
62 | reinterpret_cast<PFNGLMAPBUFFEROESPROC>(eglGetProcAddress("glMapBufferOES")); |
63 | GLExtensions::UnmapBuffer = |
64 | |
65 | === modified file 'src/canvas-x11-egl.h' |
66 | --- src/canvas-x11-egl.h 2012-01-04 00:37:12 +0000 |
67 | +++ src/canvas-x11-egl.h 2012-03-20 14:03:47 +0000 |
68 | @@ -43,6 +43,7 @@ |
69 | bool make_current(); |
70 | bool reset_context(); |
71 | void swap_buffers() { eglSwapBuffers(egl_display_, egl_surface_); } |
72 | + void get_glvisualinfo(GLVisualInfo &gl_visinfo); |
73 | |
74 | private: |
75 | bool ensure_egl_display(); |
76 | |
77 | === modified file 'src/canvas-x11-glx.cpp' |
78 | --- src/canvas-x11-glx.cpp 2012-01-04 00:37:12 +0000 |
79 | +++ src/canvas-x11-glx.cpp 2012-03-20 14:03:47 +0000 |
80 | @@ -68,6 +68,19 @@ |
81 | return true; |
82 | } |
83 | |
84 | +void |
85 | +CanvasX11GLX::get_glvisualinfo(GLVisualInfo &gl_visinfo) |
86 | +{ |
87 | + if (!ensure_glx_fbconfig()) |
88 | + return; |
89 | + |
90 | + glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_BUFFER_SIZE, &gl_visinfo.buffer_size); |
91 | + glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_RED_SIZE, &gl_visinfo.red_size); |
92 | + glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_GREEN_SIZE, &gl_visinfo.green_size); |
93 | + glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_BLUE_SIZE, &gl_visinfo.blue_size); |
94 | + glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_ALPHA_SIZE, &gl_visinfo.alpha_size); |
95 | + glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_DEPTH_SIZE, &gl_visinfo.depth_size); |
96 | +} |
97 | |
98 | /******************* |
99 | * Private methods * |
100 | |
101 | === modified file 'src/canvas-x11-glx.h' |
102 | --- src/canvas-x11-glx.h 2012-01-04 00:37:12 +0000 |
103 | +++ src/canvas-x11-glx.h 2012-03-20 14:03:47 +0000 |
104 | @@ -43,6 +43,7 @@ |
105 | bool make_current(); |
106 | bool reset_context(); |
107 | void swap_buffers() { glXSwapBuffers(xdpy_, xwin_); } |
108 | + void get_glvisualinfo(GLVisualInfo &gl_visinfo); |
109 | |
110 | private: |
111 | bool check_glx_version(); |
112 | |
113 | === modified file 'src/canvas-x11.cpp' |
114 | --- src/canvas-x11.cpp 2012-01-04 00:37:12 +0000 |
115 | +++ src/canvas-x11.cpp 2012-03-20 14:03:47 +0000 |
116 | @@ -35,10 +35,12 @@ |
117 | bool |
118 | CanvasX11::reset() |
119 | { |
120 | + release_fbo(); |
121 | + |
122 | if (!reset_context()) |
123 | return false; |
124 | |
125 | - if (!make_current()) |
126 | + if (!do_make_current()) |
127 | return false; |
128 | |
129 | if (!supports_gl2()) { |
130 | @@ -78,7 +80,7 @@ |
131 | void |
132 | CanvasX11::visible(bool visible) |
133 | { |
134 | - if (visible) |
135 | + if (visible && !offscreen_) |
136 | XMapWindow(xdpy_, xwin_); |
137 | } |
138 | |
139 | @@ -97,16 +99,35 @@ |
140 | void |
141 | CanvasX11::update() |
142 | { |
143 | - if (Options::swap_buffers) |
144 | - swap_buffers(); |
145 | - else |
146 | - glFinish(); |
147 | + Options::FrameEnd m = Options::frame_end; |
148 | + |
149 | + if (m == Options::FrameEndDefault) { |
150 | + if (offscreen_) |
151 | + m = Options::FrameEndFinish; |
152 | + else |
153 | + m = Options::FrameEndSwap; |
154 | + } |
155 | + |
156 | + switch(m) { |
157 | + case Options::FrameEndSwap: |
158 | + swap_buffers(); |
159 | + break; |
160 | + case Options::FrameEndFinish: |
161 | + glFinish(); |
162 | + break; |
163 | + case Options::FrameEndReadPixels: |
164 | + read_pixel(width_ / 2, height_ / 2); |
165 | + break; |
166 | + case Options::FrameEndNone: |
167 | + default: |
168 | + break; |
169 | + } |
170 | } |
171 | |
172 | void |
173 | CanvasX11::print_info() |
174 | { |
175 | - make_current(); |
176 | + do_make_current(); |
177 | |
178 | std::stringstream ss; |
179 | |
180 | @@ -173,6 +194,12 @@ |
181 | glViewport(0, 0, width_, height_); |
182 | } |
183 | |
184 | +unsigned int |
185 | +CanvasX11::fbo() |
186 | +{ |
187 | + return fbo_; |
188 | +} |
189 | + |
190 | bool |
191 | CanvasX11::supports_gl2() |
192 | { |
193 | @@ -285,7 +312,183 @@ |
194 | if (!ensure_x_window()) |
195 | Log::error("Error: Couldn't create X Window!\n"); |
196 | |
197 | + if (color_renderbuffer_) { |
198 | + glBindRenderbuffer(GL_RENDERBUFFER, color_renderbuffer_); |
199 | + glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format_, |
200 | + width_, height_); |
201 | + } |
202 | + |
203 | + if (depth_renderbuffer_) { |
204 | + glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer_); |
205 | + glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format_, |
206 | + width_, height_); |
207 | + } |
208 | + |
209 | projection_ = LibMatrix::Mat4::perspective(60.0, width_ / static_cast<float>(height_), |
210 | 1.0, 1024.0); |
211 | } |
212 | |
213 | +bool |
214 | +CanvasX11::do_make_current() |
215 | +{ |
216 | + if (!make_current()) |
217 | + return false; |
218 | + |
219 | + if (offscreen_) { |
220 | + if (!ensure_fbo()) |
221 | + return false; |
222 | + |
223 | + glBindFramebuffer(GL_FRAMEBUFFER, fbo_); |
224 | + } |
225 | + |
226 | + return true; |
227 | +} |
228 | + |
229 | +bool |
230 | +CanvasX11::ensure_gl_formats() |
231 | +{ |
232 | + if (gl_color_format_ && gl_depth_format_) |
233 | + return true; |
234 | + |
235 | + GLVisualInfo gl_visinfo; |
236 | + get_glvisualinfo(gl_visinfo); |
237 | + |
238 | + gl_color_format_ = 0; |
239 | + gl_depth_format_ = 0; |
240 | + |
241 | + bool supports_rgba8(false); |
242 | + bool supports_rgb8(false); |
243 | + bool supports_depth24(false); |
244 | + bool supports_depth32(false); |
245 | + |
246 | +#if USE_GLESv2 |
247 | + if (GLExtensions::support("GL_ARM_rgba8")) |
248 | + supports_rgba8 = true; |
249 | + |
250 | + if (GLExtensions::support("GL_OES_rgb8_rgba8")) { |
251 | + supports_rgba8 = true; |
252 | + supports_rgb8 = true; |
253 | + } |
254 | + |
255 | + if (GLExtensions::support("GL_OES_depth24")) |
256 | + supports_depth24 = true; |
257 | + |
258 | + if (GLExtensions::support("GL_OES_depth32")) |
259 | + supports_depth32 = true; |
260 | +#elif USE_GL |
261 | + supports_rgba8 = true; |
262 | + supports_rgb8 = true; |
263 | + supports_depth24 = true; |
264 | + supports_depth32 = true; |
265 | +#endif |
266 | + |
267 | + if (gl_visinfo.buffer_size == 32) { |
268 | + if (supports_rgba8) |
269 | + gl_color_format_ = GL_RGBA8; |
270 | + else |
271 | + gl_color_format_ = GL_RGBA4; |
272 | + } |
273 | + else if (gl_visinfo.buffer_size == 24) { |
274 | + if (supports_rgb8) |
275 | + gl_color_format_ = GL_RGB8; |
276 | + else |
277 | + gl_color_format_ = GL_RGB565; |
278 | + } |
279 | + else if (gl_visinfo.buffer_size == 16) { |
280 | + if (gl_visinfo.red_size == 4 && gl_visinfo.green_size == 4 && |
281 | + gl_visinfo.blue_size == 4 && gl_visinfo.alpha_size == 4) |
282 | + { |
283 | + gl_color_format_ = GL_RGBA4; |
284 | + } |
285 | + else if (gl_visinfo.red_size == 5 && gl_visinfo.green_size == 5 && |
286 | + gl_visinfo.blue_size == 5 && gl_visinfo.alpha_size == 1) |
287 | + { |
288 | + gl_color_format_ = GL_RGB5_A1; |
289 | + } |
290 | + else if (gl_visinfo.red_size == 5 && gl_visinfo.green_size == 6 && |
291 | + gl_visinfo.blue_size == 5 && gl_visinfo.alpha_size == 0) |
292 | + { |
293 | + gl_color_format_ = GL_RGB565; |
294 | + } |
295 | + } |
296 | + |
297 | + if (gl_visinfo.depth_size == 32 && supports_depth32) |
298 | + gl_depth_format_ = GL_DEPTH_COMPONENT32; |
299 | + else if (gl_visinfo.depth_size >= 24 && supports_depth24) |
300 | + gl_depth_format_ = GL_DEPTH_COMPONENT24; |
301 | + else if (gl_visinfo.depth_size == 16) |
302 | + gl_depth_format_ = GL_DEPTH_COMPONENT16; |
303 | + |
304 | + Log::debug("Selected Renderbuffer ColorFormat: %s DepthFormat: %s\n", |
305 | + get_gl_format_str(gl_color_format_), |
306 | + get_gl_format_str(gl_depth_format_)); |
307 | + |
308 | + return (gl_color_format_ && gl_depth_format_); |
309 | +} |
310 | + |
311 | +bool |
312 | +CanvasX11::ensure_fbo() |
313 | +{ |
314 | + if (!fbo_) { |
315 | + if (!ensure_gl_formats()) |
316 | + return false; |
317 | + |
318 | + /* Create a texture for the color attachment */ |
319 | + glGenRenderbuffers(1, &color_renderbuffer_); |
320 | + glBindRenderbuffer(GL_RENDERBUFFER, color_renderbuffer_); |
321 | + glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format_, |
322 | + width_, height_); |
323 | + |
324 | + /* Create a renderbuffer for the depth attachment */ |
325 | + glGenRenderbuffers(1, &depth_renderbuffer_); |
326 | + glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer_); |
327 | + glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format_, |
328 | + width_, height_); |
329 | + |
330 | + /* Create a FBO and set it up */ |
331 | + glGenFramebuffers(1, &fbo_); |
332 | + glBindFramebuffer(GL_FRAMEBUFFER, fbo_); |
333 | + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
334 | + GL_RENDERBUFFER, color_renderbuffer_); |
335 | + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
336 | + GL_RENDERBUFFER, depth_renderbuffer_); |
337 | + } |
338 | + |
339 | + return true; |
340 | +} |
341 | + |
342 | +void |
343 | +CanvasX11::release_fbo() |
344 | +{ |
345 | + glDeleteFramebuffers(1, &fbo_); |
346 | + glDeleteRenderbuffers(1, &color_renderbuffer_); |
347 | + glDeleteRenderbuffers(1, &depth_renderbuffer_); |
348 | + fbo_ = 0; |
349 | + color_renderbuffer_ = 0; |
350 | + depth_renderbuffer_ = 0; |
351 | + |
352 | + gl_color_format_ = 0; |
353 | + gl_depth_format_ = 0; |
354 | +} |
355 | + |
356 | +const char * |
357 | +CanvasX11::get_gl_format_str(GLenum f) |
358 | +{ |
359 | + const char *str; |
360 | + |
361 | + switch(f) { |
362 | + case GL_RGBA8: str = "GL_RGBA8"; break; |
363 | + case GL_RGB8: str = "GL_RGB8"; break; |
364 | + case GL_RGBA4: str = "GL_RGBA4"; break; |
365 | + case GL_RGB5_A1: str = "GL_RGB5_A1"; break; |
366 | + case GL_RGB565: str = "GL_RGB565"; break; |
367 | + case GL_DEPTH_COMPONENT16: str = "GL_DEPTH_COMPONENT16"; break; |
368 | + case GL_DEPTH_COMPONENT24: str = "GL_DEPTH_COMPONENT24"; break; |
369 | + case GL_DEPTH_COMPONENT32: str = "GL_DEPTH_COMPONENT32"; break; |
370 | + case GL_NONE: str = "GL_NONE"; break; |
371 | + default: str = "Unknown"; break; |
372 | + } |
373 | + |
374 | + return str; |
375 | +} |
376 | + |
377 | |
378 | === modified file 'src/canvas-x11.h' |
379 | --- src/canvas-x11.h 2012-01-04 00:37:12 +0000 |
380 | +++ src/canvas-x11.h 2012-03-20 14:03:47 +0000 |
381 | @@ -44,10 +44,25 @@ |
382 | virtual void write_to_file(std::string &filename); |
383 | virtual bool should_quit(); |
384 | virtual void resize(int width, int height); |
385 | + virtual unsigned int fbo(); |
386 | |
387 | protected: |
388 | CanvasX11(int width, int height) : |
389 | - Canvas(width, height), xwin_(0), xdpy_(0) {} |
390 | + Canvas(width, height), xwin_(0), xdpy_(0), |
391 | + gl_color_format_(0), gl_depth_format_(0), |
392 | + color_renderbuffer_(0), depth_renderbuffer_(0), fbo_(0) {} |
393 | + |
394 | + /** |
395 | + * Information about a GL visual. |
396 | + */ |
397 | + struct GLVisualInfo { |
398 | + int buffer_size; |
399 | + int red_size; |
400 | + int green_size; |
401 | + int blue_size; |
402 | + int alpha_size; |
403 | + int depth_size; |
404 | + }; |
405 | |
406 | /** |
407 | * Gets the XVisualInfo to use for creating the X window with. |
408 | @@ -88,6 +103,13 @@ |
409 | virtual void swap_buffers() = 0; |
410 | |
411 | /** |
412 | + * Gets information about the GL visual used for this canvas. |
413 | + * |
414 | + * This method should be implemented in derived classes. |
415 | + */ |
416 | + virtual void get_glvisualinfo(GLVisualInfo &gl_visinfo) = 0; |
417 | + |
418 | + /** |
419 | * Whether the current implementation supports GL(ES) 2.0. |
420 | * |
421 | * @return true if it supports GL(ES) 2.0, false otherwise |
422 | @@ -103,6 +125,18 @@ |
423 | private: |
424 | void resize_no_viewport(int width, int height); |
425 | bool ensure_x_window(); |
426 | + bool do_make_current(); |
427 | + bool ensure_gl_formats(); |
428 | + bool ensure_fbo(); |
429 | + void release_fbo(); |
430 | + |
431 | + const char *get_gl_format_str(GLenum f); |
432 | + |
433 | + GLenum gl_color_format_; |
434 | + GLenum gl_depth_format_; |
435 | + GLuint color_renderbuffer_; |
436 | + GLuint depth_renderbuffer_; |
437 | + GLuint fbo_; |
438 | }; |
439 | |
440 | #endif |
441 | |
442 | === modified file 'src/canvas.h' |
443 | --- src/canvas.h 2012-01-04 00:37:12 +0000 |
444 | +++ src/canvas.h 2012-03-20 14:03:47 +0000 |
445 | @@ -191,6 +191,13 @@ |
446 | virtual void resize(int width, int height) { static_cast<void>(width); static_cast<void>(height); } |
447 | |
448 | /** |
449 | + * Gets the FBO associated with the canvas. |
450 | + * |
451 | + * @return the FBO |
452 | + */ |
453 | + virtual unsigned int fbo() { return 0; } |
454 | + |
455 | + /** |
456 | * Gets a dummy canvas object. |
457 | * |
458 | * @return the dummy canvas |
459 | @@ -224,12 +231,21 @@ |
460 | */ |
461 | const LibMatrix::mat4 &projection() { return projection_; } |
462 | |
463 | + /** |
464 | + * Sets whether the canvas should be backed by an off-screen surface. |
465 | + * |
466 | + * This takes effect after the next init()/reset(). |
467 | + */ |
468 | + void offscreen(bool offscreen) { offscreen_ = offscreen; } |
469 | + |
470 | protected: |
471 | - Canvas(int width, int height) : width_(width), height_(height) {} |
472 | + Canvas(int width, int height) : |
473 | + width_(width), height_(height), offscreen_(false) {} |
474 | |
475 | int width_; |
476 | int height_; |
477 | LibMatrix::mat4 projection_; |
478 | + bool offscreen_; |
479 | }; |
480 | |
481 | #endif |
482 | |
483 | === modified file 'src/gl-headers.cpp' |
484 | --- src/gl-headers.cpp 2011-10-10 11:00:36 +0000 |
485 | +++ src/gl-headers.cpp 2012-03-20 14:03:47 +0000 |
486 | @@ -24,3 +24,23 @@ |
487 | void* (*GLExtensions::MapBuffer) (GLenum target, GLenum access) = 0; |
488 | GLboolean (*GLExtensions::UnmapBuffer) (GLenum target) = 0; |
489 | |
490 | +bool |
491 | +GLExtensions::support(const std::string &ext) |
492 | +{ |
493 | + std::string ext_string; |
494 | + const char* exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); |
495 | + if (exts) { |
496 | + ext_string = exts; |
497 | + } |
498 | + |
499 | + const size_t ext_size = ext.size(); |
500 | + size_t pos = 0; |
501 | + |
502 | + while ((pos = ext_string.find(ext, pos)) != std::string::npos) { |
503 | + char c = ext_string[pos + ext_size]; |
504 | + if (c == ' ' || c == '\0') |
505 | + break; |
506 | + } |
507 | + |
508 | + return pos != std::string::npos; |
509 | +} |
510 | |
511 | === modified file 'src/gl-headers.h' |
512 | --- src/gl-headers.h 2011-10-26 11:12:19 +0000 |
513 | +++ src/gl-headers.h 2012-03-20 14:03:47 +0000 |
514 | @@ -27,19 +27,43 @@ |
515 | #if USE_GL |
516 | #include <GL/gl.h> |
517 | #include <GL/glext.h> |
518 | +#ifndef GL_RGB565 |
519 | +#define GL_RGB565 0x8D62 |
520 | +#endif |
521 | #elif USE_GLESv2 |
522 | #include <GLES2/gl2.h> |
523 | #include <GLES2/gl2ext.h> |
524 | #ifndef GL_WRITE_ONLY |
525 | #define GL_WRITE_ONLY GL_WRITE_ONLY_OES |
526 | #endif |
527 | -#endif |
528 | +#ifndef GL_DEPTH_COMPONENT24 |
529 | +#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES |
530 | +#endif |
531 | +#ifndef GL_DEPTH_COMPONENT32 |
532 | +#define GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT32_OES |
533 | +#endif |
534 | +#ifndef GL_RGBA8 |
535 | +#define GL_RGBA8 GL_RGBA8_OES |
536 | +#endif |
537 | +#ifndef GL_RGB8 |
538 | +#define GL_RGB8 GL_RGB8_OES |
539 | +#endif |
540 | +#endif |
541 | + |
542 | +#include <string> |
543 | |
544 | /** |
545 | * Struct that holds pointers to functions that belong to extensions |
546 | * in either GL2.0 or GLES2.0. |
547 | */ |
548 | struct GLExtensions { |
549 | + /** |
550 | + * Whether the current context has support for a GL extension. |
551 | + * |
552 | + * @return true if the extension is supported |
553 | + */ |
554 | + static bool support(const std::string &ext); |
555 | + |
556 | static void* (*MapBuffer) (GLenum target, GLenum access); |
557 | static GLboolean (*UnmapBuffer) (GLenum target); |
558 | }; |
559 | |
560 | === modified file 'src/main.cpp' |
561 | --- src/main.cpp 2012-03-09 09:40:49 +0000 |
562 | +++ src/main.cpp 2012-03-20 14:03:47 +0000 |
563 | @@ -165,6 +165,8 @@ |
564 | CanvasX11EGL canvas(Options::size.first, Options::size.second); |
565 | #endif |
566 | |
567 | + canvas.offscreen(Options::offscreen); |
568 | + |
569 | vector<Scene*> scenes; |
570 | |
571 | // Register the scenes, so they can be looked up by name |
572 | |
573 | === modified file 'src/options.cpp' |
574 | --- src/options.cpp 2012-02-16 09:03:42 +0000 |
575 | +++ src/options.cpp 2012-03-20 14:03:47 +0000 |
576 | @@ -33,7 +33,7 @@ |
577 | std::vector<std::string> Options::benchmarks; |
578 | std::vector<std::string> Options::benchmark_files; |
579 | bool Options::validate = false; |
580 | -bool Options::swap_buffers = true; |
581 | +Options::FrameEnd Options::frame_end = Options::FrameEndDefault; |
582 | std::pair<int,int> Options::size(800, 600); |
583 | bool Options::list_scenes = false; |
584 | bool Options::show_all_options = false; |
585 | @@ -42,13 +42,15 @@ |
586 | bool Options::reuse_context = false; |
587 | bool Options::run_forever = false; |
588 | bool Options::annotate = false; |
589 | +bool Options::offscreen = false; |
590 | |
591 | static struct option long_options[] = { |
592 | {"annotate", 0, 0, 0}, |
593 | {"benchmark", 1, 0, 0}, |
594 | {"benchmark-file", 1, 0, 0}, |
595 | {"validate", 0, 0, 0}, |
596 | - {"no-swap-buffers", 0, 0, 0}, |
597 | + {"frame-end", 1, 0, 0}, |
598 | + {"off-screen", 0, 0, 0}, |
599 | {"reuse-context", 0, 0, 0}, |
600 | {"run-forever", 0, 0, 0}, |
601 | {"size", 1, 0, 0}, |
602 | @@ -83,6 +85,31 @@ |
603 | size.second = size.first; |
604 | } |
605 | |
606 | +/** |
607 | + * Parses a frame-end method string |
608 | + * |
609 | + * @param str the string to parse |
610 | + * |
611 | + * @return the parsed frame end method |
612 | + */ |
613 | +static Options::FrameEnd |
614 | +frame_end_from_str(const std::string &str) |
615 | +{ |
616 | + Options::FrameEnd m = Options::FrameEndDefault; |
617 | + |
618 | + if (str == "swap") |
619 | + m = Options::FrameEndSwap; |
620 | + else if (str == "finish") |
621 | + m = Options::FrameEndFinish; |
622 | + else if (str == "readpixels") |
623 | + m = Options::FrameEndReadPixels; |
624 | + else if (str == "none") |
625 | + m = Options::FrameEndNone; |
626 | + |
627 | + return m; |
628 | +} |
629 | + |
630 | + |
631 | void |
632 | Options::print_help() |
633 | { |
634 | @@ -96,8 +123,8 @@ |
635 | " (the option can be used multiple times)\n" |
636 | " --validate Run a quick output validation test instead of \n" |
637 | " running the benchmarks\n" |
638 | - " --no-swap-buffers Don't update the canvas by swapping the front and\n" |
639 | - " back buffer, use glFinish() instead\n" |
640 | + " --frame-end METHOD How to end a frame [default,none,swap,finish,readpixels]\n" |
641 | + " --off-screen Render to an off-screen surface\n" |
642 | " --reuse-context Use a single context for all scenes\n" |
643 | " (by default, each scene gets its own context)\n" |
644 | " -s, --size WxH Size of the output window (default: 800x600)\n" |
645 | @@ -139,8 +166,10 @@ |
646 | Options::benchmark_files.push_back(optarg); |
647 | else if (!strcmp(optname, "validate")) |
648 | Options::validate = true; |
649 | - else if (!strcmp(optname, "no-swap-buffers")) |
650 | - Options::swap_buffers = false; |
651 | + else if (!strcmp(optname, "frame-end")) |
652 | + Options::frame_end = frame_end_from_str(optarg); |
653 | + else if (!strcmp(optname, "off-screen")) |
654 | + Options::offscreen = true; |
655 | else if (!strcmp(optname, "reuse-context")) |
656 | Options::reuse_context = true; |
657 | else if (c == 's' || !strcmp(optname, "size")) |
658 | |
659 | === modified file 'src/options.h' |
660 | --- src/options.h 2012-02-16 09:03:42 +0000 |
661 | +++ src/options.h 2012-03-20 14:03:47 +0000 |
662 | @@ -28,13 +28,21 @@ |
663 | #include <vector> |
664 | |
665 | struct Options { |
666 | + enum FrameEnd { |
667 | + FrameEndDefault, |
668 | + FrameEndNone, |
669 | + FrameEndSwap, |
670 | + FrameEndFinish, |
671 | + FrameEndReadPixels |
672 | + }; |
673 | + |
674 | static bool parse_args(int argc, char **argv); |
675 | static void print_help(); |
676 | |
677 | static std::vector<std::string> benchmarks; |
678 | static std::vector<std::string> benchmark_files; |
679 | static bool validate; |
680 | - static bool swap_buffers; |
681 | + static FrameEnd frame_end; |
682 | static std::pair<int,int> size; |
683 | static bool list_scenes; |
684 | static bool show_all_options; |
685 | @@ -43,6 +51,7 @@ |
686 | static bool reuse_context; |
687 | static bool run_forever; |
688 | static bool annotate; |
689 | + static bool offscreen; |
690 | }; |
691 | |
692 | #endif /* OPTIONS_H_ */ |
693 | |
694 | === modified file 'src/scene-desktop.cpp' |
695 | --- src/scene-desktop.cpp 2012-02-13 09:43:54 +0000 |
696 | +++ src/scene-desktop.cpp 2012-03-20 14:03:47 +0000 |
697 | @@ -356,6 +356,7 @@ |
698 | class RenderScreen : public RenderObject |
699 | { |
700 | public: |
701 | + RenderScreen(Canvas &canvas) { fbo_ = canvas.fbo(); } |
702 | virtual void init() {} |
703 | virtual void release() {} |
704 | }; |
705 | @@ -736,8 +737,8 @@ |
706 | RenderClearImage desktop; |
707 | std::vector<RenderObject *> windows; |
708 | |
709 | - SceneDesktopPrivate() : |
710 | - desktop(GLMARK_DATA_PATH"/textures/effect-2d.png") {} |
711 | + SceneDesktopPrivate(Canvas &canvas) : |
712 | + screen(canvas), desktop(GLMARK_DATA_PATH"/textures/effect-2d.png") {} |
713 | |
714 | ~SceneDesktopPrivate() { Util::dispose_pointer_vector(windows); } |
715 | |
716 | @@ -747,7 +748,7 @@ |
717 | SceneDesktop::SceneDesktop(Canvas &canvas) : |
718 | Scene(canvas, "desktop") |
719 | { |
720 | - priv_ = new SceneDesktopPrivate(); |
721 | + priv_ = new SceneDesktopPrivate(canvas); |
722 | options_["effect"] = Scene::Option("effect", "blur", |
723 | "the effect to use [blur]"); |
724 | options_["windows"] = Scene::Option("windows", "4", |
Looks good. I think this will really give us some additional flexibility moving forward.