summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuel Gil Peyrot <linkmauve@linkmauve.fr>2015-03-18 01:14:45 +0100
committerEmmanuel Gil Peyrot <linkmauve@linkmauve.fr>2015-03-18 01:14:45 +0100
commit95d858e3a4948d01b98bca3372ee79d878981166 (patch)
tree512d43d2e4c8ae0ed4153e8d61b292f1b345e624
parentab92b65f23a6def236f9c07d5e288c92e606c156 (diff)
downloadsdl-95d858e3a4948d01b98bca3372ee79d878981166.tar.gz
Wayland: Properly discover displays and their modes.
Fixes Bugzilla #2913.
-rw-r--r--src/video/wayland/SDL_waylandvideo.c194
-rw-r--r--src/video/wayland/SDL_waylandvideo.h13
-rw-r--r--src/video/wayland/SDL_waylandwindow.c11
3 files changed, 74 insertions, 144 deletions
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 43826b831..3fb741b7b 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -43,11 +43,6 @@
#define WAYLANDVID_DRIVER_NAME "wayland"
-struct wayland_mode {
- SDL_DisplayMode mode;
- struct wl_list link;
-};
-
/* Initialization/Query functions */
static int
Wayland_VideoInit(_THIS);
@@ -87,7 +82,7 @@ static SDL_VideoDevice *
Wayland_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
-
+
if (!SDL_WAYLAND_LoadSymbols()) {
return NULL;
}
@@ -136,27 +131,6 @@ VideoBootStrap Wayland_bootstrap = {
};
static void
-wayland_add_mode(SDL_VideoData *d, SDL_DisplayMode m)
-{
- struct wayland_mode *mode;
-
- /* Check for duplicate mode */
- wl_list_for_each(mode, &d->modes_list, link)
- if (mode->mode.w == m.w && mode->mode.h == m.h &&
- mode->mode.refresh_rate == m.refresh_rate)
- return;
-
- /* Add new mode to the list */
- mode = (struct wayland_mode *) SDL_calloc(1, sizeof *mode);
-
- if (!mode)
- return;
-
- mode->mode = m;
- WAYLAND_wl_list_insert(&d->modes_list, &mode->link);
-}
-
-static void
display_handle_geometry(void *data,
struct wl_output *output,
int x, int y,
@@ -168,54 +142,78 @@ display_handle_geometry(void *data,
int transform)
{
- SDL_VideoData *d = data;
+ SDL_VideoDisplay *display = data;
- d->screen_allocation.x = x;
- d->screen_allocation.y = y;
+ display->name = strdup(model);
+ display->driverdata = output;
}
static void
display_handle_mode(void *data,
- struct wl_output *wl_output,
+ struct wl_output *output,
uint32_t flags,
int width,
int height,
int refresh)
{
- SDL_VideoData *d = data;
+ SDL_VideoDisplay *display = data;
SDL_DisplayMode mode;
SDL_zero(mode);
mode.w = width;
mode.h = height;
- mode.refresh_rate = refresh / 1000;
-
- wayland_add_mode(d, mode);
+ mode.refresh_rate = refresh / 1000; // mHz to Hz
+ SDL_AddDisplayMode(display, &mode);
if (flags & WL_OUTPUT_MODE_CURRENT) {
- d->screen_allocation.width = width;
- d->screen_allocation.height = height;
+ display->current_mode = mode;
+ display->desktop_mode = mode;
}
}
+static void
+display_handle_done(void *data,
+ struct wl_output *output)
+{
+ SDL_VideoDisplay *display = data;
+ SDL_AddVideoDisplay(display);
+ SDL_free(display->name);
+ SDL_free(display);
+}
+
+static void
+display_handle_scale(void *data,
+ struct wl_output *output,
+ int32_t factor)
+{
+ // TODO: do HiDPI stuff.
+}
+
static const struct wl_output_listener output_listener = {
display_handle_geometry,
- display_handle_mode
+ display_handle_mode,
+ display_handle_done,
+ display_handle_scale
};
static void
-shm_handle_format(void *data,
- struct wl_shm *shm,
- uint32_t format)
+Wayland_add_display(SDL_VideoData *d, uint32_t id)
{
- SDL_VideoData *d = data;
+ SDL_VideoDisplay *display = SDL_malloc(sizeof *display);
+ if (!display) {
+ SDL_OutOfMemory();
+ return;
+ }
+ SDL_zero(*display);
- d->shm_formats |= (1 << format);
-}
+ struct wl_output *output = wl_registry_bind(d->registry, id, &wl_output_interface, 2);
+ if (!output) {
+ SDL_SetError("Failed to retrieve output.");
+ return;
+ }
-static const struct wl_shm_listener shm_listener = {
- shm_handle_format
-};
+ wl_output_add_listener(output, &output_listener, display);
+}
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
static void
@@ -238,15 +236,14 @@ static const struct qt_windowmanager_listener windowmanager_listener = {
static void
display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
- const char *interface, uint32_t version)
+ const char *interface, uint32_t version)
{
SDL_VideoData *d = data;
-
+
if (strcmp(interface, "wl_compositor") == 0) {
d->compositor = wl_registry_bind(d->registry, id, &wl_compositor_interface, 1);
} else if (strcmp(interface, "wl_output") == 0) {
- d->output = wl_registry_bind(d->registry, id, &wl_output_interface, 1);
- wl_output_add_listener(d->output, &output_listener, d);
+ Wayland_add_display(d, id);
} else if (strcmp(interface, "wl_seat") == 0) {
Wayland_display_add_input(d, id);
} else if (strcmp(interface, "wl_shell") == 0) {
@@ -255,8 +252,7 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
d->cursor_theme = WAYLAND_wl_cursor_theme_load(NULL, 32, d->shm);
d->default_cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
- wl_shm_add_listener(d->shm, &shm_listener, d);
-
+
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (strcmp(interface, "qt_touch_extension") == 0) {
Wayland_touch_create(d, id);
@@ -272,26 +268,19 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
}
static const struct wl_registry_listener registry_listener = {
- display_handle_global
+ display_handle_global
};
int
Wayland_VideoInit(_THIS)
{
- SDL_VideoData *data;
- SDL_VideoDisplay display;
- SDL_DisplayMode mode;
- int i;
-
- data = malloc(sizeof *data);
+ SDL_VideoData *data = SDL_malloc(sizeof *data);
if (data == NULL)
return 0;
memset(data, 0, sizeof *data);
_this->driverdata = data;
- WAYLAND_wl_list_init(&data->modes_list);
-
data->display = WAYLAND_wl_display_connect(NULL);
if (data->display == NULL) {
SDL_SetError("Failed to connect to a Wayland display");
@@ -299,25 +288,18 @@ Wayland_VideoInit(_THIS)
}
data->registry = wl_display_get_registry(data->display);
-
- if ( data->registry == NULL) {
+ if (data->registry == NULL) {
SDL_SetError("Failed to get the Wayland registry");
return 0;
}
-
+
wl_registry_add_listener(data->registry, &registry_listener, data);
- for (i=0; i < 100; i++) {
- if (data->screen_allocation.width != 0 || WAYLAND_wl_display_get_error(data->display) != 0) {
- break;
- }
- WAYLAND_wl_display_dispatch(data->display);
- }
-
- if (data->screen_allocation.width == 0) {
- SDL_SetError("Failed while waiting for screen allocation: %d ", WAYLAND_wl_display_get_error(data->display));
- return 0;
- }
+ // First roundtrip to receive all registry objects.
+ wl_display_roundtrip(data->display);
+
+ // Second roundtrip to receive all output events.
+ wl_display_roundtrip(data->display);
data->xkb_context = WAYLAND_xkb_context_new(0);
if (!data->xkb_context) {
@@ -325,20 +307,7 @@ Wayland_VideoInit(_THIS)
return 0;
}
- /* Use a fake 32-bpp desktop mode */
- mode.format = SDL_PIXELFORMAT_RGB888;
- mode.w = data->screen_allocation.width;
- mode.h = data->screen_allocation.height;
- mode.refresh_rate = 0;
- mode.driverdata = NULL;
- wayland_add_mode(data, mode);
- SDL_zero(display);
- display.desktop_mode = mode;
- display.current_mode = mode;
- display.driverdata = NULL;
- SDL_AddVideoDisplay(&display);
-
- Wayland_InitMouse ();
+ Wayland_InitMouse();
WAYLAND_wl_display_flush(data->display);
@@ -348,46 +317,30 @@ Wayland_VideoInit(_THIS)
static void
Wayland_GetDisplayModes(_THIS, SDL_VideoDisplay *sdl_display)
{
- SDL_VideoData *data = _this->driverdata;
- SDL_DisplayMode mode;
- struct wayland_mode *m;
-
- Wayland_PumpEvents(_this);
-
- wl_list_for_each(m, &data->modes_list, link) {
- m->mode.format = SDL_PIXELFORMAT_RGB888;
- SDL_AddDisplayMode(sdl_display, &m->mode);
- m->mode.format = SDL_PIXELFORMAT_RGBA8888;
- SDL_AddDisplayMode(sdl_display, &m->mode);
- }
-
- mode.w = data->screen_allocation.width;
- mode.h = data->screen_allocation.height;
- mode.refresh_rate = 0;
- mode.driverdata = NULL;
-
- mode.format = SDL_PIXELFORMAT_RGB888;
- SDL_AddDisplayMode(sdl_display, &mode);
- mode.format = SDL_PIXELFORMAT_RGBA8888;
- SDL_AddDisplayMode(sdl_display, &mode);
+ // Nothing to do here, everything was already done in the wl_output
+ // callbacks.
}
static int
Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
{
- return 0;
+ SDL_SetError("SetDisplayMode not (yet?) supported on Wayland.");
+ return -1;
}
void
Wayland_VideoQuit(_THIS)
{
SDL_VideoData *data = _this->driverdata;
- struct wayland_mode *t, *m;
+ int i;
Wayland_FiniMouse ();
- if (data->output)
- wl_output_destroy(data->output);
+ for (i = 0; i < _this->num_displays; ++i) {
+ SDL_VideoDisplay *display = &_this->displays[i];
+ wl_output_destroy(display->driverdata);
+ display->driverdata = NULL;
+ }
Wayland_display_destroy_input(data);
@@ -417,16 +370,13 @@ Wayland_VideoQuit(_THIS)
if (data->compositor)
wl_compositor_destroy(data->compositor);
+ if (data->registry)
+ wl_registry_destroy(data->registry);
+
if (data->display) {
WAYLAND_wl_display_flush(data->display);
WAYLAND_wl_display_disconnect(data->display);
}
-
- wl_list_for_each_safe(m, t, &data->modes_list, link) {
- WAYLAND_wl_list_remove(&m->link);
- free(m);
- }
-
free(data);
_this->driverdata = NULL;
diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h
index 77d431e42..d56e0c939 100644
--- a/src/video/wayland/SDL_waylandvideo.h
+++ b/src/video/wayland/SDL_waylandvideo.h
@@ -40,33 +40,24 @@ typedef struct {
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
- struct wl_output *output;
struct wl_shm *shm;
struct wl_cursor_theme *cursor_theme;
struct wl_cursor *default_cursor;
struct wl_pointer *pointer;
struct wl_shell *shell;
- struct {
- int32_t x, y, width, height;
- } screen_allocation;
-
- struct wl_list modes_list;
-
EGLDisplay edpy;
EGLContext context;
EGLConfig econf;
struct xkb_context *xkb_context;
struct SDL_WaylandInput *input;
-
-#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct SDL_WaylandTouch *touch;
struct qt_surface_extension *surface_extension;
struct qt_windowmanager *windowmanager;
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
-
- uint32_t shm_formats;
} SDL_VideoData;
#endif /* _SDL_waylandvideo_h */
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 81bdc81b1..576745e00 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -179,17 +179,6 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
- /**
- * If the user specified 0x0 as the size (turned to 1x1 by SDL_CreateWindow
- * in SDL_video.c), we want to make the window fill the whole screen
- **/
- if (window->w == 1) {
- window->w = c->screen_allocation.width;
- }
- if (window->h == 1) {
- window->h = c->screen_allocation.height;
- }
-
data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
window->w, window->h);