Merge lp:~alan-griffiths/unity-system-compositor/spinner-rework into lp:unity-system-compositor
- spinner-rework
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Alan Griffiths |
Approved revision: | 240 |
Merged at revision: | 213 |
Proposed branch: | lp:~alan-griffiths/unity-system-compositor/spinner-rework |
Merge into: | lp:unity-system-compositor |
Prerequisite: | lp:~mir-team/unity-system-compositor/respond-to-event-cleanup |
Diff against target: | 1103 lines (+521/-368) 7 files modified spinner/CMakeLists.txt (+1/-1) spinner/eglapp.cpp (+106/-231) spinner/eglapp.h (+4/-17) spinner/eglspinner.cpp (+146/-118) spinner/miregl.cpp (+198/-0) spinner/miregl.h (+64/-0) tests/integration-tests/test_dbus_event_loop.cpp (+2/-1) |
To merge this branch: | bzr merge lp:~alan-griffiths/unity-system-compositor/spinner-rework |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Alexandros Frantzis (community) | Approve | ||
Kevin DuBois (community) | Approve | ||
Review via email: |
Commit message
Rework of spinner app to avoid deprecated Mir APIs, correctly set fullscreen state and support multiple outputs.
Description of the change
Rework of spinner app to avoid deprecated Mir APIs, correctly set fullscreen state and support multiple outputs.

PS Jenkins bot (ps-jenkins) wrote : | # |

Kevin DuBois (kdub) wrote : | # |
Looks like a good translation of the existing code, but some things could use fixing (esp the resource cleanup)
887+ eglMakeCurrent(
Unless theres a reason to keep the context current, the line should be:
eglMakeCurrent(
pre-existing:
862+ eglctx = eglCreateContex
874+ auto const eglsurface = eglCreateWindow
resources should be destroyed with eglDestroySurface and eglDestroyContext
847+ if (!eglInitialize
would be good to check that the version is 1.4 (major == 1) && (minor == 4)
nits: (although, maybe not nits for the USC style guide, not sure where to find that)
515+const char vShaderSrcSpinner[] =
516+ "attribute vec4 vPosition; \n"
526+const char fShaderSrcGlow[] =
527+ "precision mediump float; \n"
spacing
651,652,656-660: c-casts, (although not sure if thats a usc policy)
648+ for (auto const& surface : surfaces)
braces for multiline statement following

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:236
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

Alan Griffiths (alan-griffiths) wrote : | # |
[ RUN ] ADBusEventLoop.
/tmp/buildd/
Value of: delay
Expected: is >= 8-byte object <64-00 00-00 00-00 00-00>
Actual: 8-byte object <8F-52 F1-05 00-00 00-00>
[ FAILED ] ADBusEventLoop.
Not code touched by this MP (and can't reproduce locally).
But two failures in a row can't be an accident. Adding a little debug code in the hope of enlightenment.

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:237
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

Alan Griffiths (alan-griffiths) wrote : | # |
[ RUN ] ADBusEventLoop.
DEBUG delay=99878419 in ms=99, lbound=100
/tmp/buildd/
Value of: delay
Expected: is >= 8-byte object <64-00 00-00 00-00 00-00>
Actual: 8-byte object <13-06 F4-05 00-00 00-00>
[ FAILED ] ADBusEventLoop.
Ok, the measured delay is just under the timeout. Which could be because the timeout is enqueued (and therefore could initiate) before noting the start time.

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:238
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

Alexandros Frantzis (afrantzis) wrote : | # |
Not a full review yet:
> Ok, the measured delay is just under the timeout. Which could be because the timeout is
> enqueued (and therefore could initiate) before noting the start time.
This is correct. Thanks for the fix.
> nits: (although, maybe not nits for the USC style guide, not sure where to find that)
Let's just use the Mir style guide for USC (I think most of us have been doing that when updating USC anyway).

Alexandros Frantzis (afrantzis) wrote : | # |
Looks good.
Nits:
167+ printf("Active output [%u] at (%d, %d) is %dx%d\n",168+ output-
for_each_
1094+ egl_release_
In general, releasing a current context is a pessimization, but not a big deal for the spinner app.
+//#define MID_AUBERGINE 0.368627451f, 0.152941176f, 0.31372549f498
+//#define ORANGE 0.866666667f, 0.282352941f, 0.141414141f499
...
We could just remove these. We can look up the ubuntu color scheme definitions again if we want to change colors.
712 glClearColor(BLACK, mir_eglapp_
Pre-existing: not needed. We set the clear color (in the main loop) before we invoke glClear().

Alan Griffiths (alan-griffiths) wrote : | # |
I've left the colors in the comment as a cheap convenience for a future maintainer.

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:240
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'spinner/CMakeLists.txt' |
2 | --- spinner/CMakeLists.txt 2014-05-06 20:06:27 +0000 |
3 | +++ spinner/CMakeLists.txt 2015-05-28 15:29:59 +0000 |
4 | @@ -33,7 +33,7 @@ |
5 | |
6 | link_directories(${MIRCLIENT_LIBRARY_DIRS}) |
7 | |
8 | -add_executable(unity-system-compositor-spinner eglapp.c eglapp.h eglspinner.c) |
9 | +add_executable(unity-system-compositor-spinner eglapp.cpp eglapp.h eglspinner.cpp miregl.h miregl.cpp) |
10 | target_link_libraries(unity-system-compositor-spinner |
11 | EGL |
12 | ${CAIRO_LDFLAGS} |
13 | |
14 | === renamed file 'spinner/eglapp.c' => 'spinner/eglapp.cpp' |
15 | --- spinner/eglapp.c 2015-04-24 12:48:10 +0000 |
16 | +++ spinner/eglapp.cpp 2015-05-28 15:29:59 +0000 |
17 | @@ -1,5 +1,5 @@ |
18 | /* |
19 | - * Copyright © 2013 Canonical Ltd. |
20 | + * Copyright © 2013, 2015 Canonical Ltd. |
21 | * |
22 | * This program is free software: you can redistribute it and/or modify |
23 | * it under the terms of the GNU General Public License version 3 as |
24 | @@ -12,145 +12,77 @@ |
25 | * |
26 | * You should have received a copy of the GNU General Public License |
27 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
28 | - * |
29 | - * Author: Daniel van Vugt <daniel.van.vugt@canonical.com> |
30 | */ |
31 | |
32 | #include "eglapp.h" |
33 | -#include "mir_toolkit/mir_client_library.h" |
34 | -#include <stdio.h> |
35 | -#include <stdlib.h> |
36 | -#include <signal.h> |
37 | -#include <time.h> |
38 | -#include <EGL/egl.h> |
39 | -#include <GLES2/gl2.h> |
40 | + |
41 | +#include "miregl.h" |
42 | + |
43 | + |
44 | |
45 | float mir_eglapp_background_opacity = 1.0f; |
46 | |
47 | static const char appname[] = "eglspinner"; |
48 | |
49 | -static MirConnection *connection; |
50 | -static MirSurface *surface; |
51 | -static EGLDisplay egldisplay; |
52 | -static EGLSurface eglsurface; |
53 | -static volatile sig_atomic_t running = 0; |
54 | - |
55 | -#define CHECK(_cond, _err) \ |
56 | - if (!(_cond)) \ |
57 | - { \ |
58 | - printf("%s\n", (_err)); \ |
59 | - return 0; \ |
60 | - } |
61 | - |
62 | -void mir_eglapp_shutdown(void) |
63 | -{ |
64 | - eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
65 | - eglTerminate(egldisplay); |
66 | - mir_surface_release_sync(surface); |
67 | - surface = NULL; |
68 | - mir_connection_release(connection); |
69 | - connection = NULL; |
70 | -} |
71 | - |
72 | -static void shutdown(int signum) |
73 | -{ |
74 | - if (running) |
75 | - { |
76 | - running = 0; |
77 | - printf("Signal %d received. Good night.\n", signum); |
78 | - } |
79 | -} |
80 | - |
81 | -mir_eglapp_bool mir_eglapp_running(void) |
82 | -{ |
83 | - return running; |
84 | -} |
85 | - |
86 | -void mir_eglapp_swap_buffers(void) |
87 | -{ |
88 | - EGLint width, height; |
89 | - |
90 | - if (!running) |
91 | - return; |
92 | - |
93 | - eglSwapBuffers(egldisplay, eglsurface); |
94 | - |
95 | - /* |
96 | - * Querying the surface (actually the current buffer) dimensions here is |
97 | - * the only truly safe way to be sure that the dimensions we think we |
98 | - * have are those of the buffer being rendered to. But this should be |
99 | - * improved in future; https://bugs.launchpad.net/mir/+bug/1194384 |
100 | - */ |
101 | - if (eglQuerySurface(egldisplay, eglsurface, EGL_WIDTH, &width) && |
102 | - eglQuerySurface(egldisplay, eglsurface, EGL_HEIGHT, &height)) |
103 | - { |
104 | - glViewport(0, 0, width, height); |
105 | - } |
106 | -} |
107 | - |
108 | -static void mir_eglapp_handle_event(MirSurface* surface, MirEvent const* ev, void* context) |
109 | -{ |
110 | - (void) surface; |
111 | - (void) context; |
112 | - if (mir_event_get_type(ev) == mir_event_type_resize) |
113 | - { |
114 | - MirResizeEvent const* resize = mir_event_get_resize_event(ev); |
115 | - /* |
116 | - * FIXME: https://bugs.launchpad.net/mir/+bug/1194384 |
117 | - * It is unsafe to set the width and height here because we're in a |
118 | - * different thread to that doing the rendering. So we either need |
119 | - * support for event queuing (directing them to another thread) or |
120 | - * full single-threaded callbacks. (LP: #1194384). |
121 | - */ |
122 | - printf("Resized to %dx%d\n", |
123 | - mir_resize_event_get_width(resize), |
124 | - mir_resize_event_get_height(resize)); |
125 | - } |
126 | -} |
127 | - |
128 | -static const MirDisplayOutput *find_active_output( |
129 | - const MirDisplayConfiguration *conf) |
130 | -{ |
131 | - const MirDisplayOutput *output = NULL; |
132 | - int d; |
133 | - |
134 | - for (d = 0; d < (int)conf->num_outputs; d++) |
135 | - { |
136 | - const MirDisplayOutput *out = conf->outputs + d; |
137 | - |
138 | - if (out->used && |
139 | - out->connected && |
140 | - out->num_modes && |
141 | - out->current_mode < out->num_modes) |
142 | + |
143 | +namespace |
144 | +{ |
145 | +template<typename ActiveOutputHandler> |
146 | +void for_each_active_output( |
147 | + MirConnection* const connection, ActiveOutputHandler const& handler) |
148 | +{ |
149 | + /* eglapps are interested in the screen size, so |
150 | + use mir_connection_create_display_config */ |
151 | + MirDisplayConfiguration* display_config = |
152 | + mir_connection_create_display_config(connection); |
153 | + |
154 | + for (MirDisplayOutput* output = display_config->outputs; |
155 | + output != display_config->outputs + display_config->num_outputs; |
156 | + ++output) |
157 | + { |
158 | + if (output->used && |
159 | + output->connected && |
160 | + output->num_modes && |
161 | + output->current_mode < output->num_modes) |
162 | { |
163 | - output = out; |
164 | - break; |
165 | + handler(output); |
166 | } |
167 | } |
168 | |
169 | - return output; |
170 | -} |
171 | - |
172 | -mir_eglapp_bool mir_eglapp_init(int argc, char *argv[], |
173 | - unsigned int *width, unsigned int *height) |
174 | -{ |
175 | - EGLint ctxattribs[] = |
176 | - { |
177 | - EGL_CONTEXT_CLIENT_VERSION, 2, |
178 | - EGL_NONE |
179 | - }; |
180 | + mir_display_config_destroy(display_config); |
181 | +} |
182 | + |
183 | +MirPixelFormat select_pixel_format(MirConnection* connection) |
184 | +{ |
185 | + unsigned int format[mir_pixel_formats]; |
186 | + unsigned int nformats; |
187 | + |
188 | + mir_connection_get_available_surface_formats( |
189 | + connection, |
190 | + (MirPixelFormat*) format, |
191 | + mir_pixel_formats, |
192 | + &nformats); |
193 | + |
194 | + auto const pixel_format = (MirPixelFormat) format[0]; |
195 | + |
196 | + printf("Server supports %d of %d surface pixel formats. Using format: %d\n", |
197 | + nformats, mir_pixel_formats, pixel_format); |
198 | + |
199 | + return pixel_format; |
200 | +} |
201 | +} |
202 | + |
203 | +std::vector<std::shared_ptr<MirEglSurface>> mir_eglapp_init(int argc, char *argv[]) |
204 | +{ |
205 | MirSurfaceParameters surfaceparm = |
206 | - { |
207 | - "eglappsurface", |
208 | - 256, 256, |
209 | - mir_pixel_format_xbgr_8888, |
210 | - mir_buffer_usage_hardware, |
211 | - mir_display_output_id_invalid |
212 | - }; |
213 | - EGLConfig eglconfig; |
214 | - EGLint neglconfigs; |
215 | - EGLContext eglctx; |
216 | - EGLBoolean ok; |
217 | + { |
218 | + "eglappsurface", |
219 | + 0, 0, |
220 | + mir_pixel_format_xbgr_8888, |
221 | + mir_buffer_usage_hardware, |
222 | + mir_display_output_id_invalid |
223 | + }; |
224 | + |
225 | EGLint swapinterval = 1; |
226 | char *mir_socket = NULL; |
227 | |
228 | @@ -159,7 +91,7 @@ |
229 | int i; |
230 | for (i = 1; i < argc; i++) |
231 | { |
232 | - mir_eglapp_bool help = 0; |
233 | + bool help = 0; |
234 | const char *arg = argv[i]; |
235 | |
236 | if (arg[0] == '-') |
237 | @@ -209,10 +141,6 @@ |
238 | } |
239 | } |
240 | break; |
241 | - case 'f': |
242 | - *width = 0; |
243 | - *height = 0; |
244 | - break; |
245 | case 's': |
246 | { |
247 | unsigned int w, h; |
248 | @@ -224,8 +152,8 @@ |
249 | } |
250 | if (sscanf(arg, "%ux%u", &w, &h) == 2) |
251 | { |
252 | - *width = w; |
253 | - *height = h; |
254 | + surfaceparm.width = w; |
255 | + surfaceparm.height = h; |
256 | } |
257 | else |
258 | { |
259 | @@ -259,111 +187,58 @@ |
260 | printf("Usage: %s [<options>]\n" |
261 | " -b Background opacity (0.0 - 1.0)\n" |
262 | " -h Show this help text\n" |
263 | - " -f Force full screen\n" |
264 | " -o ID Force placement on output monitor ID\n" |
265 | " -n Don't sync to vblank\n" |
266 | " -m socket Mir server socket\n" |
267 | " -s WIDTHxHEIGHT Force surface size\n" |
268 | " -q Quiet mode (no messages output)\n" |
269 | , argv[0]); |
270 | - return 0; |
271 | + return {}; |
272 | } |
273 | } |
274 | } |
275 | |
276 | - connection = mir_connect_sync(mir_socket, appname); |
277 | - CHECK(mir_connection_is_valid(connection), "Can't get connection"); |
278 | - |
279 | - /* eglapps are interested in the screen size, so |
280 | - use mir_connection_create_display_config */ |
281 | - MirDisplayConfiguration* display_config = |
282 | - mir_connection_create_display_config(connection); |
283 | - |
284 | - const MirDisplayOutput *output = find_active_output(display_config); |
285 | - |
286 | - if (output == NULL) |
287 | - { |
288 | - printf("No active outputs found.\n"); |
289 | - return 0; |
290 | - } |
291 | - |
292 | - const MirDisplayMode *mode = &output->modes[output->current_mode]; |
293 | - |
294 | - unsigned int format[mir_pixel_formats]; |
295 | - unsigned int nformats; |
296 | - |
297 | - mir_connection_get_available_surface_formats(connection, |
298 | - (MirPixelFormat*) format, mir_pixel_formats, &nformats); |
299 | - |
300 | - surfaceparm.pixel_format = (MirPixelFormat) format[0]; |
301 | - |
302 | - printf("Current active output is %dx%d %+d%+d\n", |
303 | - mode->horizontal_resolution, mode->vertical_resolution, |
304 | - output->position_x, output->position_y); |
305 | - |
306 | - surfaceparm.width = *width > 0 ? *width : mode->horizontal_resolution; |
307 | - surfaceparm.height = *height > 0 ? *height : mode->vertical_resolution; |
308 | - |
309 | - mir_display_config_destroy(display_config); |
310 | - |
311 | - printf("Server supports %d of %d surface pixel formats. Using format: %d\n", |
312 | - nformats, mir_pixel_formats, surfaceparm.pixel_format); |
313 | - unsigned int bpp = 8 * MIR_BYTES_PER_PIXEL(surfaceparm.pixel_format); |
314 | - EGLint attribs[] = |
315 | - { |
316 | - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
317 | - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
318 | - EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, |
319 | - EGL_BUFFER_SIZE, (EGLint) bpp, |
320 | - EGL_NONE |
321 | - }; |
322 | - |
323 | - surface = mir_connection_create_surface_sync(connection, &surfaceparm); |
324 | - CHECK(mir_surface_is_valid(surface), "Can't create a surface"); |
325 | - |
326 | - mir_surface_set_event_handler(surface, mir_eglapp_handle_event, NULL); |
327 | - |
328 | - egldisplay = eglGetDisplay( |
329 | - (EGLNativeDisplayType) mir_connection_get_egl_native_display(connection)); |
330 | - CHECK(egldisplay != EGL_NO_DISPLAY, "Can't eglGetDisplay"); |
331 | - |
332 | - ok = eglInitialize(egldisplay, NULL, NULL); |
333 | - CHECK(ok, "Can't eglInitialize"); |
334 | - |
335 | - ok = eglChooseConfig(egldisplay, attribs, &eglconfig, 1, &neglconfigs); |
336 | - CHECK(ok, "Could not eglChooseConfig"); |
337 | - CHECK(neglconfigs > 0, "No EGL config available"); |
338 | - |
339 | - eglsurface = eglCreateWindowSurface(egldisplay, eglconfig, |
340 | - (EGLNativeWindowType)mir_buffer_stream_get_egl_native_window(mir_surface_get_buffer_stream(surface)), NULL); |
341 | - CHECK(eglsurface != EGL_NO_SURFACE, "eglCreateWindowSurface failed"); |
342 | - |
343 | - eglctx = eglCreateContext(egldisplay, eglconfig, EGL_NO_CONTEXT, |
344 | - ctxattribs); |
345 | - CHECK(eglctx != EGL_NO_CONTEXT, "eglCreateContext failed"); |
346 | - |
347 | - ok = eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglctx); |
348 | - CHECK(ok, "Can't eglMakeCurrent"); |
349 | - |
350 | - signal(SIGINT, shutdown); |
351 | - signal(SIGTERM, shutdown); |
352 | - |
353 | - *width = surfaceparm.width; |
354 | - *height = surfaceparm.height; |
355 | - |
356 | - eglSwapInterval(egldisplay, swapinterval); |
357 | - |
358 | - running = 1; |
359 | - |
360 | - return 1; |
361 | -} |
362 | - |
363 | -struct MirConnection* mir_eglapp_native_connection() |
364 | -{ |
365 | - return connection; |
366 | -} |
367 | - |
368 | -struct MirSurface* mir_eglapp_native_surface() |
369 | -{ |
370 | - return surface; |
371 | + MirConnection* const connection{mir_connect_sync(mir_socket, appname)}; |
372 | + if (!mir_connection_is_valid(connection)) |
373 | + throw std::runtime_error("Can't get connection"); |
374 | + |
375 | + auto const pixel_format = select_pixel_format(connection); |
376 | + surfaceparm.pixel_format = pixel_format; |
377 | + |
378 | + auto const mir_egl_app = make_mir_eglapp(connection, pixel_format, swapinterval); |
379 | + |
380 | + std::vector<std::shared_ptr<MirEglSurface>> result; |
381 | + |
382 | + // If a size has been specified just do that |
383 | + if (surfaceparm.width && surfaceparm.height) |
384 | + { |
385 | + result.push_back(std::make_shared<MirEglSurface>(mir_egl_app, surfaceparm)); |
386 | + return result; |
387 | + } |
388 | + |
389 | + // If an output has been specified just do that |
390 | + if (surfaceparm.output_id != mir_display_output_id_invalid) |
391 | + { |
392 | + result.push_back(std::make_shared<MirEglSurface>(mir_egl_app, surfaceparm)); |
393 | + return result; |
394 | + } |
395 | + |
396 | + // but normally, we're fullscreen on every active output |
397 | + for_each_active_output(connection, [&](MirDisplayOutput const* output) |
398 | + { |
399 | + auto const& mode = output->modes[output->current_mode]; |
400 | + |
401 | + printf("Active output [%u] at (%d, %d) is %dx%d\n", |
402 | + output->output_id, |
403 | + output->position_x, output->position_y, |
404 | + mode.horizontal_resolution, mode.vertical_resolution); |
405 | + |
406 | + surfaceparm.output_id = output->output_id; |
407 | + result.push_back(std::make_shared<MirEglSurface>(mir_egl_app, surfaceparm)); |
408 | + }); |
409 | + |
410 | + if (result.empty()) |
411 | + throw std::runtime_error("No active outputs found."); |
412 | + |
413 | + return result; |
414 | } |
415 | |
416 | === modified file 'spinner/eglapp.h' |
417 | --- spinner/eglapp.h 2014-03-08 22:01:45 +0000 |
418 | +++ spinner/eglapp.h 2015-05-28 15:29:59 +0000 |
419 | @@ -19,26 +19,13 @@ |
420 | #ifndef __EGLAPP_H__ |
421 | #define __EGLAPP_H__ |
422 | |
423 | -#ifdef __cplusplus |
424 | -extern "C" { |
425 | -#endif |
426 | +#include <memory> |
427 | +#include <vector> |
428 | |
429 | -typedef int mir_eglapp_bool; |
430 | -struct MirConnection; |
431 | -struct MirSurface; |
432 | +class MirEglSurface; |
433 | |
434 | extern float mir_eglapp_background_opacity; |
435 | |
436 | -mir_eglapp_bool mir_eglapp_init(int argc, char *argv[], |
437 | - unsigned int *width, unsigned int *height); |
438 | -void mir_eglapp_swap_buffers(void); |
439 | -mir_eglapp_bool mir_eglapp_running(void); |
440 | -void mir_eglapp_shutdown(void); |
441 | - |
442 | -struct MirConnection* mir_eglapp_native_connection(); |
443 | -struct MirSurface* mir_eglapp_native_surface(); |
444 | -#ifdef __cplusplus |
445 | -} |
446 | -#endif |
447 | +std::vector<std::shared_ptr<MirEglSurface>> mir_eglapp_init(int argc, char *argv[]); |
448 | |
449 | #endif |
450 | |
451 | === renamed file 'spinner/eglspinner.c' => 'spinner/eglspinner.cpp' |
452 | --- spinner/eglspinner.c 2015-05-01 14:16:27 +0000 |
453 | +++ spinner/eglspinner.cpp 2015-05-28 15:29:59 +0000 |
454 | @@ -18,19 +18,17 @@ |
455 | */ |
456 | |
457 | #include "eglapp.h" |
458 | +#include "miregl.h" |
459 | #include <assert.h> |
460 | #include <cairo.h> |
461 | #include <glib.h> |
462 | -#include <stdio.h> |
463 | #include <string.h> |
464 | -#include <strings.h> |
465 | -#include <stdlib.h> |
466 | #include <GLES2/gl2.h> |
467 | -#include <math.h> |
468 | #include <sys/stat.h> |
469 | #if HAVE_PROPS |
470 | #include <hybris/properties/properties.h> |
471 | #endif |
472 | +#include <signal.h> |
473 | |
474 | // this is needed for get_gu() to obtain the grid-unit value |
475 | #define MAX_LENGTH 256 |
476 | @@ -63,7 +61,7 @@ |
477 | else |
478 | { |
479 | #ifdef HAVE_PROPS |
480 | - char* defaultValue = ""; |
481 | + char const* defaultValue = ""; |
482 | char value[PROP_VALUE_MAX]; |
483 | property_get (PROP_KEY, value, defaultValue); |
484 | strcat (filename, value); |
485 | @@ -125,26 +123,25 @@ |
486 | } |
487 | |
488 | // Colours from http://design.ubuntu.com/brand/colour-palette |
489 | -#define MID_AUBERGINE 0.368627451f, 0.152941176f, 0.31372549f |
490 | -#define ORANGE 0.866666667f, 0.282352941f, 0.141414141f |
491 | -#define WARM_GREY 0.682352941f, 0.654901961f, 0.623529412f |
492 | -#define COOL_GREY 0.2f, 0.2f, 0.2f |
493 | -#define LIGHT_AUBERGINE 0.466666667f, 0.297297297f, 0.435294118f |
494 | -#define DARK_AUBERGINE 0.17254902f, 0.0f, 0.117647059f |
495 | +//#define MID_AUBERGINE 0.368627451f, 0.152941176f, 0.31372549f |
496 | +//#define ORANGE 0.866666667f, 0.282352941f, 0.141414141f |
497 | +//#define WARM_GREY 0.682352941f, 0.654901961f, 0.623529412f |
498 | +//#define COOL_GREY 0.2f, 0.2f, 0.2f |
499 | +//#define LIGHT_AUBERGINE 0.466666667f, 0.297297297f, 0.435294118f |
500 | +//#define DARK_AUBERGINE 0.17254902f, 0.0f, 0.117647059f |
501 | #define BLACK 0.0f, 0.0f, 0.0f |
502 | -#define WHITE 1.0f, 1.0f, 1.0f |
503 | +//#define WHITE 1.0f, 1.0f, 1.0f |
504 | |
505 | cairo_surface_t* pngToSurface (const char* filename) |
506 | { |
507 | - // sanity check |
508 | - if (!filename) |
509 | - return NULL; |
510 | + if (access(filename, F_OK & R_OK) != 0) |
511 | + throw std::runtime_error("Failed to load png: " + std::string(filename) + "\n"); |
512 | |
513 | // create surface from PNG |
514 | cairo_surface_t* surface = NULL; |
515 | surface = cairo_image_surface_create_from_png (filename); |
516 | if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) |
517 | - return NULL; |
518 | + throw std::runtime_error("Failed to load png: " + std::string(filename) + "\n"); |
519 | |
520 | return surface; |
521 | } |
522 | @@ -215,10 +212,10 @@ |
523 | typedef struct _AnimationValues |
524 | { |
525 | double lastTimeStamp; |
526 | - double angle; |
527 | - double fadeBackground; |
528 | - double fadeLogo; |
529 | - double fadeGlow; |
530 | + GLfloat angle; |
531 | + GLfloat fadeBackground; |
532 | + GLfloat fadeLogo; |
533 | + GLfloat fadeGlow; |
534 | } AnimationValues; |
535 | |
536 | void |
537 | @@ -264,56 +261,76 @@ |
538 | // anim->fadeLogo -= 1.6f * dt; |
539 | } |
540 | |
541 | +namespace |
542 | +{ |
543 | +const char vShaderSrcSpinner[] = |
544 | + "attribute vec4 vPosition; \n" |
545 | + "attribute vec2 aTexCoords; \n" |
546 | + "uniform float theta; \n" |
547 | + "varying vec2 vTexCoords; \n" |
548 | + "void main() \n" |
549 | + "{ \n" |
550 | + " float c = cos(theta); \n" |
551 | + " float s = sin(theta); \n" |
552 | + " mat2 m; \n" |
553 | + " m[0] = vec2(c, s); \n" |
554 | + " m[1] = vec2(-s, c); \n" |
555 | + " vTexCoords = m * aTexCoords + vec2 (0.5, 0.5); \n" |
556 | + " gl_Position = vec4(vPosition.xy, -1.0, 1.0); \n" |
557 | + "} \n"; |
558 | + |
559 | +const char fShaderSrcGlow[] = |
560 | + "precision mediump float; \n" |
561 | + "varying vec2 vTexCoords; \n" |
562 | + "uniform sampler2D uSampler; \n" |
563 | + "uniform float uFadeGlow; \n" |
564 | + "void main() \n" |
565 | + "{ \n" |
566 | + " // swizzle because texture was created with cairo\n" |
567 | + " vec4 col = texture2D(uSampler, vTexCoords).bgra; \n" |
568 | + " float r = col.r * uFadeGlow; \n" |
569 | + " float g = col.g * uFadeGlow; \n" |
570 | + " float b = col.b * uFadeGlow; \n" |
571 | + " float a = col.a * uFadeGlow; \n" |
572 | + " gl_FragColor = vec4(r, g, b, a); \n" |
573 | + "} \n"; |
574 | + |
575 | +const char fShaderSrcLogo[] = |
576 | + "precision mediump float; \n" |
577 | + "varying vec2 vTexCoords; \n" |
578 | + "uniform sampler2D uSampler; \n" |
579 | + "uniform float uFadeLogo; \n" |
580 | + "void main() \n" |
581 | + "{ \n" |
582 | + " // swizzle because texture was created with cairo\n" |
583 | + " vec4 col = texture2D(uSampler, vTexCoords).bgra; \n" |
584 | + " float r = col.r * uFadeLogo; \n" |
585 | + " float g = col.g * uFadeLogo; \n" |
586 | + " float b = col.b * uFadeLogo; \n" |
587 | + " float a = col.a * uFadeLogo; \n" |
588 | + " gl_FragColor = vec4(r, g, b, a); \n" |
589 | + "} \n"; |
590 | + |
591 | +static volatile sig_atomic_t running = 0; |
592 | + |
593 | +static void shutdown(int signum) |
594 | +{ |
595 | + if (running) |
596 | + { |
597 | + running = 0; |
598 | + printf("Signal %d received. Good night.\n", signum); |
599 | + } |
600 | +} |
601 | + |
602 | +bool mir_eglapp_running() |
603 | +{ |
604 | + return running; |
605 | +} |
606 | +} |
607 | + |
608 | int main(int argc, char *argv[]) |
609 | +try |
610 | { |
611 | - const char vShaderSrcSpinner[] = |
612 | - "attribute vec4 vPosition; \n" |
613 | - "attribute vec2 aTexCoords; \n" |
614 | - "uniform float theta; \n" |
615 | - "varying vec2 vTexCoords; \n" |
616 | - "void main() \n" |
617 | - "{ \n" |
618 | - " float c = cos(theta); \n" |
619 | - " float s = sin(theta); \n" |
620 | - " mat2 m; \n" |
621 | - " m[0] = vec2(c, s); \n" |
622 | - " m[1] = vec2(-s, c); \n" |
623 | - " vTexCoords = m * aTexCoords + vec2 (0.5, 0.5); \n" |
624 | - " gl_Position = vec4(vPosition.xy, -1.0, 1.0); \n" |
625 | - "} \n"; |
626 | - |
627 | - const char fShaderSrcGlow[] = |
628 | - "precision mediump float; \n" |
629 | - "varying vec2 vTexCoords; \n" |
630 | - "uniform sampler2D uSampler; \n" |
631 | - "uniform float uFadeGlow; \n" |
632 | - "void main() \n" |
633 | - "{ \n" |
634 | - " // swizzle because texture was created with cairo\n" |
635 | - " vec4 col = texture2D(uSampler, vTexCoords).bgra; \n" |
636 | - " float r = col.r * uFadeGlow; \n" |
637 | - " float g = col.g * uFadeGlow; \n" |
638 | - " float b = col.b * uFadeGlow; \n" |
639 | - " float a = col.a * uFadeGlow; \n" |
640 | - " gl_FragColor = vec4(r, g, b, a); \n" |
641 | - "} \n"; |
642 | - |
643 | - const char fShaderSrcLogo[] = |
644 | - "precision mediump float; \n" |
645 | - "varying vec2 vTexCoords; \n" |
646 | - "uniform sampler2D uSampler; \n" |
647 | - "uniform float uFadeLogo; \n" |
648 | - "void main() \n" |
649 | - "{ \n" |
650 | - " // swizzle because texture was created with cairo\n" |
651 | - " vec4 col = texture2D(uSampler, vTexCoords).bgra; \n" |
652 | - " float r = col.r * uFadeLogo; \n" |
653 | - " float g = col.g * uFadeLogo; \n" |
654 | - " float b = col.b * uFadeLogo; \n" |
655 | - " float a = col.a * uFadeLogo; \n" |
656 | - " gl_FragColor = vec4(r, g, b, a); \n" |
657 | - "} \n"; |
658 | - |
659 | GLuint prog[2]; |
660 | GLuint texture[2]; |
661 | GLint vpos[2]; |
662 | @@ -322,24 +339,20 @@ |
663 | GLint fadeLogo; |
664 | GLint aTexCoords[2]; |
665 | GLint sampler[2]; |
666 | - unsigned int width = 0; |
667 | - unsigned int height = 0; |
668 | - |
669 | - if (!mir_eglapp_init(argc, argv, &width, &height)) |
670 | - return 1; |
671 | - |
672 | - double pixelSize = (double) get_gu () * 11.18; |
673 | - double halfRealWidth = ((2.0 / (double) width) * pixelSize) / 2.0; |
674 | - double halfRealHeight = ((2.0 / (double) height) * pixelSize) / 2.0; |
675 | - |
676 | - const GLfloat vertices[] = |
677 | + |
678 | + auto const surfaces = mir_eglapp_init(argc, argv); |
679 | + |
680 | + if (!surfaces.size()) |
681 | { |
682 | - halfRealWidth, halfRealHeight, |
683 | - halfRealWidth, -halfRealHeight, |
684 | - -halfRealWidth, halfRealHeight, |
685 | - -halfRealWidth, -halfRealHeight, |
686 | - }; |
687 | - |
688 | + printf("No surfaces created\n"); |
689 | + return EXIT_SUCCESS; |
690 | + } |
691 | + |
692 | + running = 1; |
693 | + signal(SIGINT, shutdown); |
694 | + signal(SIGTERM, shutdown); |
695 | + |
696 | + double pixelSize = get_gu() * 11.18; |
697 | const GLfloat texCoordsSpinner[] = |
698 | { |
699 | -0.5f, 0.5f, |
700 | @@ -348,12 +361,8 @@ |
701 | 0.5f, -0.5f, |
702 | }; |
703 | |
704 | - prog[0] = createShaderProgram (vShaderSrcSpinner, fShaderSrcGlow); |
705 | - prog[1] = createShaderProgram (vShaderSrcSpinner, fShaderSrcLogo); |
706 | - |
707 | - // setup viewport and projection |
708 | - glClearColor(BLACK, mir_eglapp_background_opacity); |
709 | - glViewport(0, 0, width, height); |
710 | + prog[0] = createShaderProgram(vShaderSrcSpinner, fShaderSrcGlow); |
711 | + prog[1] = createShaderProgram(vShaderSrcSpinner, fShaderSrcLogo); |
712 | |
713 | // setup proper GL-blending |
714 | glEnable(GL_BLEND); |
715 | @@ -377,8 +386,6 @@ |
716 | uploadTexture(texture[1], PKGDATADIR "/spinner-logo.png"); |
717 | |
718 | // bunch of shader-attributes to enable |
719 | - glVertexAttribPointer(vpos[0], 2, GL_FLOAT, GL_FALSE, 0, vertices); |
720 | - glVertexAttribPointer(vpos[1], 2, GL_FLOAT, GL_FALSE, 0, vertices); |
721 | glVertexAttribPointer(aTexCoords[0], 2, GL_FLOAT, GL_FALSE, 0, texCoordsSpinner); |
722 | glVertexAttribPointer(aTexCoords[1], 2, GL_FLOAT, GL_FALSE, 0, texCoordsSpinner); |
723 | glEnableVertexAttribArray(vpos[0]); |
724 | @@ -388,39 +395,60 @@ |
725 | glActiveTexture(GL_TEXTURE0); |
726 | |
727 | AnimationValues anim = {0.0, 0.0, 1.0, 0.0, 0.0}; |
728 | - GTimer* timer = g_timer_new (); |
729 | + GTimer* timer = g_timer_new(); |
730 | |
731 | while (mir_eglapp_running()) |
732 | { |
733 | - glClearColor(BLACK, anim.fadeBackground); |
734 | - glClear(GL_COLOR_BUFFER_BIT); |
735 | - |
736 | - // draw glow |
737 | - glUseProgram(prog[0]); |
738 | - glBindTexture(GL_TEXTURE_2D, texture[0]); |
739 | - glUniform1i(sampler[0], 0); |
740 | - glUniform1f(theta, anim.angle); |
741 | - glUniform1f(fadeGlow, anim.fadeGlow); |
742 | - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
743 | - |
744 | - // draw logo |
745 | - glUseProgram(prog[1]); |
746 | - glBindTexture(GL_TEXTURE_2D, texture[1]); |
747 | - glUniform1i(sampler[1], 0); |
748 | - glUniform1f(theta, anim.angle); |
749 | - glUniform1f(fadeLogo, anim.fadeLogo); |
750 | - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
751 | + for (auto const& surface : surfaces) |
752 | + surface->paint([&](unsigned int width, unsigned int height) |
753 | + { |
754 | + GLfloat halfRealWidth = ((2.0 / width) * pixelSize) / 2.0; |
755 | + GLfloat halfRealHeight = ((2.0 / height) * pixelSize) / 2.0; |
756 | + |
757 | + const GLfloat vertices[] = |
758 | + { |
759 | + halfRealWidth, halfRealHeight, |
760 | + halfRealWidth, -halfRealHeight, |
761 | + -halfRealWidth, halfRealHeight, |
762 | + -halfRealWidth,-halfRealHeight, |
763 | + }; |
764 | + |
765 | + glVertexAttribPointer(vpos[0], 2, GL_FLOAT, GL_FALSE, 0, vertices); |
766 | + glVertexAttribPointer(vpos[1], 2, GL_FLOAT, GL_FALSE, 0, vertices); |
767 | + |
768 | + glViewport(0, 0, width, height); |
769 | + |
770 | + glClearColor(BLACK, anim.fadeBackground); |
771 | + glClear(GL_COLOR_BUFFER_BIT); |
772 | + |
773 | + // draw glow |
774 | + glUseProgram(prog[0]); |
775 | + glBindTexture(GL_TEXTURE_2D, texture[0]); |
776 | + glUniform1i(sampler[0], 0); |
777 | + glUniform1f(theta, anim.angle); |
778 | + glUniform1f(fadeGlow, anim.fadeGlow); |
779 | + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
780 | + |
781 | + // draw logo |
782 | + glUseProgram(prog[1]); |
783 | + glBindTexture(GL_TEXTURE_2D, texture[1]); |
784 | + glUniform1i(sampler[1], 0); |
785 | + glUniform1f(theta, anim.angle); |
786 | + glUniform1f(fadeLogo, anim.fadeLogo); |
787 | + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
788 | + }); |
789 | |
790 | // update animation variable |
791 | - updateAnimation (timer, &anim); |
792 | - |
793 | - mir_eglapp_swap_buffers(); |
794 | + updateAnimation(timer, &anim); |
795 | } |
796 | |
797 | - mir_eglapp_shutdown(); |
798 | - |
799 | glDeleteTextures(2, texture); |
800 | g_timer_destroy (timer); |
801 | |
802 | - return 0; |
803 | + return EXIT_SUCCESS; |
804 | } |
805 | +catch (std::exception const& x) |
806 | +{ |
807 | + printf("%s\n", x.what()); |
808 | + return EXIT_FAILURE; |
809 | +} |
810 | \ No newline at end of file |
811 | |
812 | === added file 'spinner/miregl.cpp' |
813 | --- spinner/miregl.cpp 1970-01-01 00:00:00 +0000 |
814 | +++ spinner/miregl.cpp 2015-05-28 15:29:59 +0000 |
815 | @@ -0,0 +1,198 @@ |
816 | +/* |
817 | + * Copyright © 2015 Canonical Ltd. |
818 | + * |
819 | + * This program is free software: you can redistribute it and/or modify |
820 | + * it under the terms of the GNU General Public License version 3 as |
821 | + * published by the Free Software Foundation. |
822 | + * |
823 | + * This program is distributed in the hope that it will be useful, |
824 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
825 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
826 | + * GNU General Public License for more details. |
827 | + * |
828 | + * You should have received a copy of the GNU General Public License |
829 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
830 | + */ |
831 | + |
832 | +#include "miregl.h" |
833 | + |
834 | +#include <GLES2/gl2.h> |
835 | + |
836 | +class MirEglApp |
837 | +{ |
838 | +public: |
839 | + MirEglApp(MirConnection* const connection, MirPixelFormat pixel_format, EGLint swapinterval); |
840 | + |
841 | + EGLSurface create_surface(MirSurface* surface); |
842 | + |
843 | + void release_current(); |
844 | + |
845 | + void make_current(EGLSurface eglsurface) const; |
846 | + |
847 | + void swap_buffers(EGLSurface eglsurface) const; |
848 | + |
849 | + void destroy_surface(EGLSurface eglsurface) const; |
850 | + |
851 | + ~MirEglApp(); |
852 | + |
853 | + MirConnection* const connection; |
854 | +private: |
855 | + EGLDisplay egldisplay; |
856 | + EGLContext eglctx; |
857 | + EGLConfig eglconfig; |
858 | + EGLint neglconfigs; |
859 | +}; |
860 | + |
861 | +std::shared_ptr<MirEglApp> make_mir_eglapp( |
862 | + MirConnection* const connection, MirPixelFormat const& pixel_format, EGLint swapinterval) |
863 | +{ |
864 | + return std::make_shared<MirEglApp>(connection, pixel_format, swapinterval); |
865 | +} |
866 | + |
867 | +namespace |
868 | +{ |
869 | +MirSurface* create_surface(MirConnection* const connection, MirSurfaceParameters const& surfaceparm) |
870 | +{ |
871 | + auto const spec = mir_connection_create_spec_for_normal_surface( |
872 | + connection, |
873 | + surfaceparm.width, |
874 | + surfaceparm.height, |
875 | + surfaceparm.pixel_format); |
876 | + |
877 | + mir_surface_spec_set_name(spec, surfaceparm.name); |
878 | + mir_surface_spec_set_buffer_usage(spec, surfaceparm.buffer_usage); |
879 | + mir_surface_spec_set_fullscreen_on_output(spec, surfaceparm.output_id); |
880 | + |
881 | + auto const surface = mir_surface_create_sync(spec); |
882 | + mir_surface_spec_release(spec); |
883 | + |
884 | + if (!mir_surface_is_valid(surface)) |
885 | + throw std::runtime_error("Can't create a surface"); |
886 | + |
887 | + if (surfaceparm.output_id != mir_display_output_id_invalid) |
888 | + mir_surface_set_state(surface, mir_surface_state_fullscreen); |
889 | + |
890 | + return surface; |
891 | +} |
892 | +} |
893 | + |
894 | +MirEglSurface::MirEglSurface(std::shared_ptr<MirEglApp> const& mir_egl_app, MirSurfaceParameters const& surfaceparm) : |
895 | + mir_egl_app{mir_egl_app}, |
896 | + surface{create_surface(mir_egl_app->connection, surfaceparm)}, |
897 | + eglsurface{mir_egl_app->create_surface(surface)} |
898 | +{ |
899 | +} |
900 | + |
901 | +MirEglSurface::~MirEglSurface() |
902 | +{ |
903 | + mir_egl_app->destroy_surface(eglsurface); |
904 | + mir_surface_release_sync(surface); |
905 | +} |
906 | + |
907 | +void MirEglSurface::egl_make_current() |
908 | +{ |
909 | + auto const buffer_stream = mir_surface_get_buffer_stream(surface); |
910 | + mir_buffer_stream_get_current_buffer(buffer_stream, &buffer_package); |
911 | + mir_egl_app->make_current(eglsurface); |
912 | +} |
913 | + |
914 | +void MirEglSurface::swap_buffers() |
915 | +{ |
916 | + mir_egl_app->swap_buffers(eglsurface); |
917 | +} |
918 | + |
919 | +unsigned int MirEglSurface::width() const |
920 | +{ |
921 | + return buffer_package->width; |
922 | +} |
923 | + |
924 | +unsigned int MirEglSurface::height() const |
925 | +{ |
926 | + return buffer_package->height; |
927 | +} |
928 | + |
929 | +MirEglApp::MirEglApp(MirConnection* const connection, MirPixelFormat pixel_format, EGLint swapinterval) : |
930 | + connection{connection} |
931 | +{ |
932 | + unsigned int bpp = 8*MIR_BYTES_PER_PIXEL(pixel_format); |
933 | + |
934 | + EGLint attribs[] = |
935 | + { |
936 | + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
937 | + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
938 | + EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, |
939 | + EGL_BUFFER_SIZE, (EGLint) bpp, |
940 | + EGL_NONE |
941 | + }; |
942 | + |
943 | + egldisplay = eglGetDisplay((EGLNativeDisplayType) mir_connection_get_egl_native_display(connection)); |
944 | + if (egldisplay == EGL_NO_DISPLAY) |
945 | + throw std::runtime_error("Can't eglGetDisplay"); |
946 | + |
947 | + EGLint major; |
948 | + EGLint minor; |
949 | + if (!eglInitialize(egldisplay, &major, &minor)) |
950 | + throw std::runtime_error("Can't eglInitialize"); |
951 | + |
952 | + if (major != 1 || minor != 4) |
953 | + throw std::runtime_error("EGL version is not 1.4"); |
954 | + |
955 | + if (!eglChooseConfig(egldisplay, attribs, &eglconfig, 1, &neglconfigs)) |
956 | + throw std::runtime_error("Could not eglChooseConfig"); |
957 | + |
958 | + if (neglconfigs == 0) |
959 | + throw std::runtime_error("No EGL config available"); |
960 | + |
961 | + EGLint ctxattribs[] = |
962 | + { |
963 | + EGL_CONTEXT_CLIENT_VERSION, 2, |
964 | + EGL_NONE |
965 | + }; |
966 | + |
967 | + eglctx = eglCreateContext(egldisplay, eglconfig, EGL_NO_CONTEXT, ctxattribs); |
968 | + if (eglctx == EGL_NO_CONTEXT) |
969 | + throw std::runtime_error("eglCreateContext failed"); |
970 | + |
971 | + if (!eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglctx)) |
972 | + throw std::runtime_error("Can't eglMakeCurrent"); |
973 | + |
974 | + eglSwapInterval(egldisplay, swapinterval); |
975 | +} |
976 | + |
977 | +EGLSurface MirEglApp::create_surface(MirSurface* surface) |
978 | +{ |
979 | + auto const eglsurface = eglCreateWindowSurface( |
980 | + egldisplay, |
981 | + eglconfig, |
982 | + (EGLNativeWindowType) mir_buffer_stream_get_egl_native_window(mir_surface_get_buffer_stream(surface)), NULL); |
983 | + |
984 | + if (eglsurface == EGL_NO_SURFACE) |
985 | + throw std::runtime_error("eglCreateWindowSurface failed"); |
986 | + |
987 | + return eglsurface; |
988 | +} |
989 | + |
990 | +void MirEglApp::make_current(EGLSurface eglsurface) const |
991 | +{ |
992 | + if (!eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglctx)) |
993 | + throw std::runtime_error("Can't eglMakeCurrent"); |
994 | +} |
995 | + |
996 | +void MirEglApp::swap_buffers(EGLSurface eglsurface) const |
997 | +{ |
998 | + eglSwapBuffers(egldisplay, eglsurface); |
999 | +} |
1000 | + |
1001 | +void MirEglApp::destroy_surface(EGLSurface eglsurface) const |
1002 | +{ |
1003 | + eglDestroySurface(egldisplay, eglsurface); |
1004 | +} |
1005 | + |
1006 | + |
1007 | +MirEglApp::~MirEglApp() |
1008 | +{ |
1009 | + eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
1010 | + eglDestroyContext(egldisplay, eglctx); |
1011 | + eglTerminate(egldisplay); |
1012 | + mir_connection_release(connection); |
1013 | +} |
1014 | |
1015 | === added file 'spinner/miregl.h' |
1016 | --- spinner/miregl.h 1970-01-01 00:00:00 +0000 |
1017 | +++ spinner/miregl.h 2015-05-28 15:29:59 +0000 |
1018 | @@ -0,0 +1,64 @@ |
1019 | +/* |
1020 | + * Copyright © 2015 Canonical Ltd. |
1021 | + * |
1022 | + * This program is free software: you can redistribute it and/or modify |
1023 | + * it under the terms of the GNU General Public License version 3 as |
1024 | + * published by the Free Software Foundation. |
1025 | + * |
1026 | + * This program is distributed in the hope that it will be useful, |
1027 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1028 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1029 | + * GNU General Public License for more details. |
1030 | + * |
1031 | + * You should have received a copy of the GNU General Public License |
1032 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1033 | + */ |
1034 | + |
1035 | +#ifndef UNITYSYSTEMCOMPOSITOR_MIREGL_H |
1036 | +#define UNITYSYSTEMCOMPOSITOR_MIREGL_H |
1037 | + |
1038 | +#include <mir_toolkit/common.h> |
1039 | +#include <mir_toolkit/client_types.h> |
1040 | +#include "mir_toolkit/mir_client_library.h" |
1041 | + |
1042 | +#include <EGL/egl.h> |
1043 | + |
1044 | +#include <memory> |
1045 | + |
1046 | +class MirEglApp; |
1047 | +class MirEglSurface; |
1048 | + |
1049 | +std::shared_ptr<MirEglApp> make_mir_eglapp( |
1050 | + MirConnection* const connection, |
1051 | + MirPixelFormat const& pixel_format, |
1052 | + EGLint swapinterval); |
1053 | + |
1054 | +class MirEglSurface |
1055 | +{ |
1056 | +public: |
1057 | + MirEglSurface(std::shared_ptr<MirEglApp> const& mir_egl_app, MirSurfaceParameters const& surfaceparm); |
1058 | + |
1059 | + ~MirEglSurface(); |
1060 | + |
1061 | + template<typename Painter> |
1062 | + void paint(Painter const& functor) |
1063 | + { |
1064 | + egl_make_current(); |
1065 | + functor(width(), height()); |
1066 | + swap_buffers(); |
1067 | + } |
1068 | + |
1069 | +private: |
1070 | + void egl_make_current(); |
1071 | + |
1072 | + void swap_buffers(); |
1073 | + unsigned int width() const; |
1074 | + unsigned int height() const; |
1075 | + |
1076 | + std::shared_ptr<MirEglApp> const mir_egl_app; |
1077 | + MirSurface* const surface; |
1078 | + MirBufferPackage* buffer_package; |
1079 | + EGLSurface const eglsurface; |
1080 | +}; |
1081 | + |
1082 | +#endif //UNITYSYSTEMCOMPOSITOR_MIREGL_H |
1083 | |
1084 | === modified file 'tests/integration-tests/test_dbus_event_loop.cpp' |
1085 | --- tests/integration-tests/test_dbus_event_loop.cpp 2015-03-18 12:48:33 +0000 |
1086 | +++ tests/integration-tests/test_dbus_event_loop.cpp 2015-05-28 15:29:59 +0000 |
1087 | @@ -201,6 +201,8 @@ |
1088 | |
1089 | static int const timeout_ms = 100; |
1090 | |
1091 | + auto const start = std::chrono::steady_clock::now(); |
1092 | + |
1093 | dbus_event_loop.enqueue( |
1094 | [this,&pending_promise] |
1095 | { |
1096 | @@ -218,7 +220,6 @@ |
1097 | }); |
1098 | |
1099 | // No one is going to reply to the signal, so the notification should time out |
1100 | - auto const start = std::chrono::steady_clock::now(); |
1101 | auto pending = pending_future.get(); |
1102 | auto const end = std::chrono::steady_clock::now(); |
1103 | auto const delay = end - start; |
FAILED: Continuous integration, rev:232 jenkins. qa.ubuntu. com/job/ unity-system- compositor- ci/215/ jenkins. qa.ubuntu. com/job/ unity-system- compositor- wily-amd64- ci/3/console jenkins. qa.ubuntu. com/job/ unity-system- compositor- wily-armhf- ci/3 jenkins. qa.ubuntu. com/job/ unity-system- compositor- wily-armhf- ci/3/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-system- compositor- wily-i386- ci/3
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- system- compositor- ci/215/ rebuild
http://