2
* Copyright © 2013 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 3 as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
20
#include "mir_toolkit/mir_client_library.h"
26
#include <GLES2/gl2.h>
28
float mir_eglapp_background_opacity = 1.0f;
30
static const char appname[] = "eglspinner";
32
static MirConnection *connection;
33
static MirSurface *surface;
34
static EGLDisplay egldisplay;
35
static EGLSurface eglsurface;
36
static volatile sig_atomic_t running = 0;
38
#define CHECK(_cond, _err) \
41
printf("%s\n", (_err)); \
45
void mir_eglapp_shutdown(void)
47
eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
48
eglTerminate(egldisplay);
49
mir_surface_release_sync(surface);
51
mir_connection_release(connection);
55
static void shutdown(int signum)
60
printf("Signal %d received. Good night.\n", signum);
64
mir_eglapp_bool mir_eglapp_running(void)
69
void mir_eglapp_swap_buffers(void)
76
eglSwapBuffers(egldisplay, eglsurface);
79
* Querying the surface (actually the current buffer) dimensions here is
80
* the only truly safe way to be sure that the dimensions we think we
81
* have are those of the buffer being rendered to. But this should be
82
* improved in future; https://bugs.launchpad.net/mir/+bug/1194384
84
if (eglQuerySurface(egldisplay, eglsurface, EGL_WIDTH, &width) &&
85
eglQuerySurface(egldisplay, eglsurface, EGL_HEIGHT, &height))
87
glViewport(0, 0, width, height);
91
static void mir_eglapp_handle_event(MirSurface* surface, MirEvent const* ev, void* context)
95
if (ev->type == mir_event_type_resize)
98
* FIXME: https://bugs.launchpad.net/mir/+bug/1194384
99
* It is unsafe to set the width and height here because we're in a
100
* different thread to that doing the rendering. So we either need
101
* support for event queuing (directing them to another thread) or
102
* full single-threaded callbacks. (LP: #1194384).
104
printf("Resized to %dx%d\n", ev->resize.width, ev->resize.height);
108
static const MirDisplayOutput *find_active_output(
109
const MirDisplayConfiguration *conf)
111
const MirDisplayOutput *output = NULL;
114
for (d = 0; d < (int)conf->num_outputs; d++)
116
const MirDisplayOutput *out = conf->outputs + d;
121
out->current_mode < out->num_modes)
131
mir_eglapp_bool mir_eglapp_init(int argc, char *argv[],
132
unsigned int *width, unsigned int *height)
134
EGLint ctxattribs[] =
136
EGL_CONTEXT_CLIENT_VERSION, 2,
139
MirSurfaceParameters surfaceparm =
143
mir_pixel_format_xbgr_8888,
144
mir_buffer_usage_hardware,
145
mir_display_output_id_invalid
147
MirEventDelegate delegate =
149
mir_eglapp_handle_event,
156
EGLint swapinterval = 1;
157
char *mir_socket = NULL;
162
for (i = 1; i < argc; i++)
164
mir_eglapp_bool help = 0;
165
const char *arg = argv[i];
175
if (!arg[0] && i < argc-1)
180
if (sscanf(arg, "%f", &alpha) == 1)
182
mir_eglapp_background_opacity = alpha;
186
printf("Invalid opacity value: %s\n", arg);
196
unsigned int output_id = 0;
198
if (!arg[0] && i < argc-1)
203
if (sscanf(arg, "%u", &output_id) == 1)
205
surfaceparm.output_id = output_id;
209
printf("Invalid output ID: %s\n", arg);
222
if (!arg[0] && i < argc-1)
227
if (sscanf(arg, "%ux%u", &w, &h) == 2)
234
printf("Invalid size: %s\n", arg);
240
mir_socket = argv[++i];
244
FILE *unused = freopen("/dev/null", "a", stdout);
261
printf("Usage: %s [<options>]\n"
262
" -b Background opacity (0.0 - 1.0)\n"
263
" -h Show this help text\n"
264
" -f Force full screen\n"
265
" -o ID Force placement on output monitor ID\n"
266
" -n Don't sync to vblank\n"
267
" -m socket Mir server socket\n"
268
" -s WIDTHxHEIGHT Force surface size\n"
269
" -q Quiet mode (no messages output)\n"
276
connection = mir_connect_sync(mir_socket, appname);
277
CHECK(mir_connection_is_valid(connection), "Can't get connection");
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);
284
const MirDisplayOutput *output = find_active_output(display_config);
288
printf("No active outputs found.\n");
292
const MirDisplayMode *mode = &output->modes[output->current_mode];
294
unsigned int format[mir_pixel_formats];
295
unsigned int nformats;
297
mir_connection_get_available_surface_formats(connection,
298
(MirPixelFormat*) format, mir_pixel_formats, &nformats);
300
surfaceparm.pixel_format = (MirPixelFormat) format[0];
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);
306
surfaceparm.width = *width > 0 ? *width : mode->horizontal_resolution;
307
surfaceparm.height = *height > 0 ? *height : mode->vertical_resolution;
309
mir_display_config_destroy(display_config);
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);
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,
323
surface = mir_connection_create_surface_sync(connection, &surfaceparm);
324
CHECK(mir_surface_is_valid(surface), "Can't create a surface");
326
mir_surface_set_event_handler(surface, &delegate);
328
egldisplay = eglGetDisplay(
329
(EGLNativeDisplayType) mir_connection_get_egl_native_display(connection));
330
CHECK(egldisplay != EGL_NO_DISPLAY, "Can't eglGetDisplay");
332
ok = eglInitialize(egldisplay, NULL, NULL);
333
CHECK(ok, "Can't eglInitialize");
335
ok = eglChooseConfig(egldisplay, attribs, &eglconfig, 1, &neglconfigs);
336
CHECK(ok, "Could not eglChooseConfig");
337
CHECK(neglconfigs > 0, "No EGL config available");
339
eglsurface = eglCreateWindowSurface(egldisplay, eglconfig,
340
(EGLNativeWindowType)mir_surface_get_egl_native_window(surface),
342
CHECK(eglsurface != EGL_NO_SURFACE, "eglCreateWindowSurface failed");
344
eglctx = eglCreateContext(egldisplay, eglconfig, EGL_NO_CONTEXT,
346
CHECK(eglctx != EGL_NO_CONTEXT, "eglCreateContext failed");
348
ok = eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglctx);
349
CHECK(ok, "Can't eglMakeCurrent");
351
signal(SIGINT, shutdown);
352
signal(SIGTERM, shutdown);
354
*width = surfaceparm.width;
355
*height = surfaceparm.height;
357
eglSwapInterval(egldisplay, swapinterval);
364
struct MirConnection* mir_eglapp_native_connection()
369
struct MirSurface* mir_eglapp_native_surface()