2 * Copyright © 2011 Collabora, Ltd.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 #include "../config.h"
25 #include "wscreensaver.h"
33 #include <EGL/eglext.h>
35 #include <wayland-client.h>
37 #include "desktop-shell-client-protocol.h"
40 extern struct wscreensaver_plugin glmatrix_screensaver;
42 static const struct wscreensaver_plugin * const plugins[] = {
43 &glmatrix_screensaver,
47 const char *progname = NULL;
52 struct screensaver *interface;
54 struct display *display;
56 struct ModeInfo *demomode;
63 const struct wscreensaver_plugin *plugin;
67 frame_callback(void *data, struct wl_callback *callback, uint32_t time)
69 struct ModeInfo *mi = data;
71 window_schedule_redraw(mi->window);
72 wl_callback_destroy(callback);
75 static const struct wl_callback_listener listener = {
80 redraw_handler(struct widget *widget, void *data)
82 struct ModeInfo *mi = data;
83 struct wscreensaver *wscr = mi->priv;
84 struct rectangle drawarea;
85 struct rectangle winarea;
86 struct wl_callback *callback;
91 widget_get_allocation(mi->widget, &drawarea);
92 window_get_allocation(mi->window, &winarea);
94 if (display_acquire_window_surface(wscr->display,
97 fprintf(stderr, "%s: unable to acquire window surface",
102 bottom = winarea.height - (drawarea.height + drawarea.y);
103 glViewport(drawarea.x, bottom, drawarea.width, drawarea.height);
104 glScissor(drawarea.x, bottom, drawarea.width, drawarea.height);
105 glEnable(GL_SCISSOR_TEST);
107 if (mi->width != drawarea.width || mi->height != drawarea.height) {
108 mi->width = drawarea.width;
109 mi->height = drawarea.height;
110 wscr->plugin->reshape(mi, mi->width, mi->height);
113 wscr->plugin->draw(mi);
115 if (mi->swap_buffers == 0)
116 fprintf(stderr, "%s: swapBuffers not called\n", progname);
118 display_release_window_surface(wscr->display, mi->window);
120 callback = wl_surface_frame(window_get_wl_surface(mi->window));
121 wl_callback_add_listener(callback, &listener, mi);
128 gettimeofday(&tv, NULL);
129 srandom(tv.tv_sec * 100 + tv.tv_usec / 10000);
132 WL_EXPORT EGLContext *
133 init_GL(struct ModeInfo *mi)
135 struct wscreensaver *wscr = mi->priv;
138 pctx = malloc(sizeof *pctx);
142 if (mi->eglctx != EGL_NO_CONTEXT) {
143 fprintf(stderr, "%s: multiple GL contexts are not supported",
148 mi->eglctx = eglCreateContext(wscr->egl.display, wscr->egl.config,
149 EGL_NO_CONTEXT, NULL);
150 if (mi->eglctx == EGL_NO_CONTEXT) {
151 fprintf(stderr, "%s: init_GL failed to create EGL context\n",
156 if (!eglMakeCurrent(wscr->egl.display, NULL, NULL, mi->eglctx)) {
157 fprintf(stderr, "%s: init_GL failed on eglMakeCurrent\n",
162 glClearColor(0.0, 0.0, 0.0, 1.0);
172 static struct ModeInfo *
173 create_wscreensaver_instance(struct wscreensaver *screensaver,
174 struct wl_output *output, int width, int height)
178 struct rectangle drawarea;
180 mi = calloc(1, sizeof *mi);
185 mi->window = window_create(screensaver->display);
187 mi->window = window_create_custom(screensaver->display);
190 fprintf(stderr, "%s: creating a window failed.\n", progname);
195 window_set_title(mi->window, progname);
197 if (screensaver->interface && !demo_mode) {
198 mi->widget = window_add_widget(mi->window, mi);
199 screensaver_set_surface(screensaver->interface,
200 window_get_wl_surface(mi->window),
203 mi->widget = window_frame_create(mi->window, mi);
205 widget_set_redraw_handler(mi->widget, redraw_handler);
207 mi->priv = screensaver;
208 mi->eglctx = EGL_NO_CONTEXT;
209 mi->instance_number = instance++; /* XXX */
211 widget_get_allocation(mi->widget, &drawarea);
212 mi->width = drawarea.width;
213 mi->height = drawarea.height;
215 screensaver->plugin->init(mi);
217 window_schedule_resize(mi->window, width, height);
222 handle_output_destroy(struct output *output, void *data)
224 /* struct ModeInfo *mi = data;
229 handle_output_configure(struct output *output, void *data)
231 struct wscreensaver *screensaver = data;
233 struct rectangle area;
235 /* skip existing outputs */
236 if (output_get_user_data(output))
239 output_get_allocation(output, &area);
240 mi = create_wscreensaver_instance(screensaver,
241 output_get_wl_output(output),
242 area.width, area.height);
243 output_set_user_data(output, mi);
244 output_set_destroy_handler(output, handle_output_destroy);
248 init_wscreensaver(struct wscreensaver *wscr, struct display *display)
251 const char prefix[] = "wscreensaver::";
254 display_set_user_data(display, wscr);
255 wscr->display = display;
256 wscr->plugin = plugins[0];
258 size = sizeof(prefix) + strlen(wscr->plugin->name);
261 fprintf(stderr, "init: out of memory\n");
264 snprintf(str, size, "%s%s", prefix, wscr->plugin->name);
267 wscr->egl.display = display_get_egl_display(wscr->display);
268 if (!wscr->egl.display) {
269 fprintf(stderr, "init: no EGL display\n");
273 eglBindAPI(EGL_OPENGL_API);
274 wscr->egl.config = display_get_argb_egl_config(wscr->display);
277 struct wl_output *o =
278 output_get_wl_output(display_get_output(display));
279 /* only one instance */
281 create_wscreensaver_instance(wscr, o, 400, 300);
285 display_set_output_configure_handler(display, handle_output_configure);
291 global_handler(struct display *display, uint32_t name,
292 const char *interface, uint32_t version, void *data)
294 struct wscreensaver *screensaver = data;
296 if (!strcmp(interface, "screensaver")) {
297 screensaver->interface =
298 display_bind(display, name, &screensaver_interface, 1);
302 static const struct weston_option wscreensaver_options[] = {
303 { WESTON_OPTION_BOOLEAN, "demo", 0, &demo_mode },
306 int main(int argc, char *argv[])
309 struct wscreensaver screensaver = { 0 };
313 if (parse_options(wscreensaver_options,
314 ARRAY_LENGTH(wscreensaver_options), &argc, argv) > 1) {
315 printf("Usage: %s [OPTIONS]\n --demo for demo mode\n",
320 d = display_create(&argc, argv);
322 fprintf(stderr, "failed to create display: %m\n");
327 /* iterates already known globals immediately */
328 display_set_user_data(d, &screensaver);
329 display_set_global_handler(d, global_handler);
330 if (!screensaver.interface) {
332 "Server did not offer screensaver interface,"
338 if (init_wscreensaver(&screensaver, d) < 0) {
339 fprintf(stderr, "wscreensaver init failed.\n");
345 free((void *)progname);