glx-multithread-texture: Avoid front-buffer rendering.
[piglit.git] / tests / util / piglit-framework-gl / piglit_wl_framework.c
blobf0583a67b23a33738229f78e772d53cd13b07e9f
1 /*
2 * Copyright © 2012 Intel Corporation
3 * Copyright © 2008 Kristian Høgsberg
4 * Copyright © 2012-2013 Collabora, Ltd.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * IN THE SOFTWARE.
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <unistd.h>
30 #include "piglit-util-gl.h"
31 #include "piglit_wl_framework.h"
33 #include <wayland-client.h>
34 #include <waffle_wayland.h>
35 #include <xkbcommon/xkbcommon.h>
36 #include <sys/mman.h>
38 struct piglit_wl_framework {
39 struct piglit_winsys_framework winsys_fw;
41 struct wl_display *dpy;
42 struct wl_registry *registry;
44 struct wl_seat *seat;
45 struct wl_keyboard *keyboard;
47 struct {
48 struct xkb_context *context;
49 struct xkb_keymap *keymap;
50 struct xkb_state *state;
51 } xkb;
54 /* Most of the code here taken from window.c in Weston source code. */
55 static void keymap(void *data,
56 struct wl_keyboard *wl_keyboard,
57 uint32_t format,
58 int32_t fd,
59 uint32_t size)
61 struct piglit_wl_framework *wl_fw =
62 (struct piglit_wl_framework *) data;
63 struct xkb_keymap *keymap;
64 struct xkb_state *state;
65 char *locale;
66 char *map_str;
68 if (!data || format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
69 close(fd);
70 return;
73 map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
74 if (map_str == MAP_FAILED) {
75 close(fd);
76 return;
79 /* Set up XKB keymap */
80 keymap = xkb_keymap_new_from_string(wl_fw->xkb.context,
81 map_str,
82 XKB_KEYMAP_FORMAT_TEXT_V1,
83 0);
85 munmap(map_str, size);
86 close(fd);
88 if (!keymap) {
89 fprintf(stderr, "failed to compile keymap\n");
90 return;
93 /* Set up XKB state */
94 state = xkb_state_new(keymap);
95 if (!state) {
96 fprintf(stderr, "failed to create XKB state\n");
97 xkb_keymap_unref(keymap);
98 return;
101 /* Look up the preferred locale, falling back to "C" as default */
102 if (!(locale = getenv("LC_ALL")))
103 if (!(locale = getenv("LC_CTYPE")))
104 if (!(locale = getenv("LANG")))
105 locale = "C";
107 xkb_keymap_unref(wl_fw->xkb.keymap);
108 xkb_state_unref(wl_fw->xkb.state);
109 wl_fw->xkb.keymap = keymap;
110 wl_fw->xkb.state = state;
113 static void enter(void *data,
114 struct wl_keyboard *wl_keyboard,
115 uint32_t serial,
116 struct wl_surface *surface,
117 struct wl_array *keys)
121 static void leave(void *data,
122 struct wl_keyboard *wl_keyboard,
123 uint32_t serial,
124 struct wl_surface *surface)
128 static void key(void *data,
129 struct wl_keyboard *wl_keyboard,
130 uint32_t serial,
131 uint32_t time,
132 uint32_t key,
133 uint32_t state)
135 struct piglit_wl_framework *wl_fw =
136 (struct piglit_wl_framework *) data;
137 struct piglit_winsys_framework *winsys_fw = &wl_fw->winsys_fw;
138 const struct piglit_gl_test_config *test_config =
139 winsys_fw->wfl_fw.gl_fw.test_config;
141 const xkb_keysym_t *syms;
142 xkb_keysym_t sym;
144 uint32_t code = key + 8;
145 uint32_t num_syms;
147 if (!wl_fw->xkb.state)
148 return;
150 num_syms = xkb_state_key_get_syms(wl_fw->xkb.state, code, &syms);
151 sym = XKB_KEY_NoSymbol;
152 if (num_syms == 1)
153 sym = syms[0];
155 winsys_fw->need_redisplay = true;
157 if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
158 return;
160 if (winsys_fw->user_keyboard_func)
161 winsys_fw->user_keyboard_func(sym, 0, 0);
163 if (winsys_fw->need_redisplay) {
164 enum piglit_result result = PIGLIT_PASS;
165 if (test_config->display)
166 result = test_config->display();
167 if (piglit_automatic)
168 piglit_report_result(result);
169 winsys_fw->need_redisplay = false;
173 static void modifiers(void *data,
174 struct wl_keyboard *wl_keyboard,
175 uint32_t serial,
176 uint32_t mods_depressed,
177 uint32_t mods_latched,
178 uint32_t mods_locked,
179 uint32_t group)
183 static const struct wl_keyboard_listener keyboard_listener = {
184 keymap,
185 enter,
186 leave,
187 key,
188 modifiers
191 static void
192 process_events(struct wl_display *dpy)
194 while (1) {
195 if (wl_display_dispatch(dpy) == -1)
196 break;
200 static void global(void *data,
201 struct wl_registry *wl_registry,
202 uint32_t name,
203 const char *interface,
204 uint32_t version)
206 struct piglit_wl_framework *wl_fw =
207 (struct piglit_wl_framework *) data;
209 if (strcmp(interface, "wl_seat") != 0)
210 return;
212 wl_fw->seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 1);
213 wl_fw->keyboard = wl_seat_get_keyboard(wl_fw->seat);
215 if (wl_fw->keyboard)
216 wl_keyboard_add_listener(wl_fw->keyboard, &keyboard_listener, data);
219 static void global_remove(void *data,
220 struct wl_registry *wl_registry,
221 uint32_t name)
225 static const struct wl_registry_listener registry_listener = {
226 global,
227 global_remove
230 static void
231 enter_event_loop(struct piglit_winsys_framework *winsys_fw)
233 struct piglit_wl_framework *wl_fw =
234 (struct piglit_wl_framework *) winsys_fw;
235 const struct piglit_gl_test_config *test_config =
236 winsys_fw->wfl_fw.gl_fw.test_config;
237 enum piglit_result result = PIGLIT_PASS;
239 /* The Wayland window fails to appear on the first call to
240 * swapBuffers (which occured in display_cb above). This is
241 * likely due to swapBuffers being called before receiving an
242 * expose event. Until piglit has proper Wayland support,
243 * redraw as a workaround.
245 if (test_config->display)
246 result = test_config->display();
248 /* Do not proceed to event loop in case of piglit_automatic. */
249 if (piglit_automatic)
250 piglit_report_result(result);
252 process_events(wl_fw->dpy);
255 static void
256 show_window(struct piglit_winsys_framework *winsys_fw)
258 waffle_window_show(winsys_fw->wfl_fw.window);
261 static void
262 destroy(struct piglit_gl_framework *gl_fw)
264 struct piglit_wl_framework *wl_fw =
265 (struct piglit_wl_framework *) gl_fw;
267 if (wl_fw == NULL)
268 return;
270 xkb_keymap_unref(wl_fw->xkb.keymap);
271 xkb_state_unref(wl_fw->xkb.state);
272 xkb_context_unref(wl_fw->xkb.context);
274 wl_registry_destroy(wl_fw->registry);
276 piglit_winsys_framework_teardown(&wl_fw->winsys_fw);
277 free(wl_fw);
280 struct piglit_gl_framework*
281 piglit_wl_framework_create(const struct piglit_gl_test_config *test_config)
283 struct piglit_wl_framework *wl_fw = NULL;
284 struct piglit_winsys_framework *winsys_fw = NULL;
285 struct piglit_gl_framework *gl_fw = NULL;
286 bool ok = true;
288 wl_fw = calloc(1, sizeof(*wl_fw));
289 winsys_fw = &wl_fw->winsys_fw;
290 gl_fw = &wl_fw->winsys_fw.wfl_fw.gl_fw;
292 ok = piglit_winsys_framework_init(&wl_fw->winsys_fw,
293 test_config, WAFFLE_PLATFORM_WAYLAND);
294 if (!ok)
295 goto fail;
297 wl_fw->xkb.context = xkb_context_new(0);
298 wl_fw->xkb.keymap = NULL;
299 wl_fw->xkb.state = NULL;
301 if (!wl_fw->xkb.context)
302 goto fail;
304 union waffle_native_window *n_window =
305 waffle_window_get_native(winsys_fw->wfl_fw.window);
307 wl_fw->dpy = n_window->wayland->display.wl_display;
308 wl_fw->registry = wl_display_get_registry(wl_fw->dpy);
310 wl_registry_add_listener(wl_fw->registry, &registry_listener, wl_fw);
312 winsys_fw->show_window = show_window;
313 winsys_fw->enter_event_loop = enter_event_loop;
314 gl_fw->destroy = destroy;
316 return gl_fw;
318 fail:
319 destroy(gl_fw);
320 return NULL;