mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-04 13:29:51 -05:00
Make ack event signal that the requests have been composited.
This commit is contained in:
parent
f3723fe79e
commit
44f36e3585
5 changed files with 111 additions and 74 deletions
|
|
@ -541,6 +541,8 @@ repaint(void *data)
|
||||||
|
|
||||||
eglSwapBuffers(ec->display, ec->surface);
|
eglSwapBuffers(ec->display, ec->surface);
|
||||||
|
|
||||||
|
wl_display_post_acknowledge(ec->wl_display);
|
||||||
|
|
||||||
animate_overlay(ec);
|
animate_overlay(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
22
flower.c
22
flower.c
|
|
@ -82,23 +82,30 @@ draw_stuff(int width, int height)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct flower {
|
struct flower {
|
||||||
|
struct wl_display *display;
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
int i;
|
int i;
|
||||||
int x, y, width, height;
|
int x, y, width, height;
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
move_flower(gpointer data)
|
move_flower(struct flower *flower)
|
||||||
{
|
{
|
||||||
struct flower *flower = data;
|
|
||||||
|
|
||||||
wl_surface_map(flower->surface,
|
wl_surface_map(flower->surface,
|
||||||
flower->x + cos(flower->i / 31.0) * 400 - flower->width / 2,
|
flower->x + cos(flower->i / 31.0) * 400 - flower->width / 2,
|
||||||
flower->y + sin(flower->i / 27.0) * 300 - flower->height / 2,
|
flower->y + sin(flower->i / 27.0) * 300 - flower->height / 2,
|
||||||
flower->width, flower->height);
|
flower->width, flower->height);
|
||||||
flower->i++;
|
flower->i++;
|
||||||
|
wl_display_commit(flower->display, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
static void
|
||||||
|
event_handler(struct wl_display *display,
|
||||||
|
uint32_t object, uint32_t opcode,
|
||||||
|
uint32_t size, uint32_t *p, void *data)
|
||||||
|
{
|
||||||
|
if (object == 1)
|
||||||
|
move_flower(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
|
@ -129,6 +136,7 @@ int main(int argc, char *argv[])
|
||||||
source = wayland_source_new(display);
|
source = wayland_source_new(display);
|
||||||
g_source_attach(source, NULL);
|
g_source_attach(source, NULL);
|
||||||
|
|
||||||
|
flower.display = display;
|
||||||
flower.x = 512;
|
flower.x = 512;
|
||||||
flower.y = 384;
|
flower.y = 384;
|
||||||
flower.width = 200;
|
flower.width = 200;
|
||||||
|
|
@ -144,8 +152,8 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
wl_surface_attach(flower.surface, buffer->name, flower.width, flower.height,
|
wl_surface_attach(flower.surface, buffer->name, flower.width, flower.height,
|
||||||
buffer->stride);
|
buffer->stride);
|
||||||
|
wl_display_set_event_handler(display, event_handler, &flower);
|
||||||
g_timeout_add(20, move_flower, &flower);
|
move_flower(&flower);
|
||||||
|
|
||||||
g_main_loop_run(loop);
|
g_main_loop_run(loop);
|
||||||
|
|
||||||
|
|
|
||||||
34
wayland.c
34
wayland.c
|
|
@ -19,6 +19,8 @@ struct wl_client {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_list object_list;
|
struct wl_list object_list;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
uint32_t pending_acknowledge;
|
||||||
|
uint32_t acknowledge_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wl_display {
|
struct wl_display {
|
||||||
|
|
@ -500,12 +502,8 @@ static int
|
||||||
wl_display_commit(struct wl_client *client,
|
wl_display_commit(struct wl_client *client,
|
||||||
struct wl_display *display, uint32_t key)
|
struct wl_display *display, uint32_t key)
|
||||||
{
|
{
|
||||||
uint32_t event[3];
|
client->pending_acknowledge = 1;
|
||||||
|
client->acknowledge_key = key;
|
||||||
event[0] = display->base.id;
|
|
||||||
event[1] = WL_DISPLAY_ACKNOWLEDGE | ((sizeof event) << 16);
|
|
||||||
event[2] = key;
|
|
||||||
wl_connection_write(client->connection, event, sizeof event);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -687,6 +685,30 @@ wl_display_post_key_event(struct wl_display *display,
|
||||||
wl_display_send_event(display, p, sizeof p);
|
wl_display_send_event(display, p, sizeof p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WL_EXPORT void
|
||||||
|
wl_display_post_acknowledge(struct wl_display *display)
|
||||||
|
{
|
||||||
|
struct wl_client *client;
|
||||||
|
uint32_t event[3];
|
||||||
|
|
||||||
|
event[0] = display->base.id;
|
||||||
|
event[1] = WL_DISPLAY_ACKNOWLEDGE | ((sizeof event) << 16);
|
||||||
|
|
||||||
|
client = container_of(display->client_list.next,
|
||||||
|
struct wl_client, link);
|
||||||
|
|
||||||
|
while (&client->link != &display->client_list) {
|
||||||
|
if (client->pending_acknowledge) {
|
||||||
|
event[2] = client->acknowledge_key;
|
||||||
|
wl_connection_write(client->connection,
|
||||||
|
event, sizeof event);
|
||||||
|
client->pending_acknowledge = 0;
|
||||||
|
}
|
||||||
|
client = container_of(client->link.next,
|
||||||
|
struct wl_client, link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_display_set_compositor(struct wl_display *display,
|
wl_display_set_compositor(struct wl_display *display,
|
||||||
struct wl_compositor *compositor)
|
struct wl_compositor *compositor)
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,8 @@ wl_display_post_button_event(struct wl_display *display,
|
||||||
void
|
void
|
||||||
wl_display_post_key_event(struct wl_display *display,
|
wl_display_post_key_event(struct wl_display *display,
|
||||||
struct wl_object *source, int key, int state);
|
struct wl_object *source, int key, int state);
|
||||||
|
void
|
||||||
|
wl_display_post_acknowledge(struct wl_display *display);
|
||||||
|
|
||||||
struct wl_compositor {
|
struct wl_compositor {
|
||||||
const struct wl_compositor_interface *interface;
|
const struct wl_compositor_interface *interface;
|
||||||
|
|
|
||||||
123
window.c
123
window.c
|
|
@ -36,7 +36,6 @@ struct window {
|
||||||
int state;
|
int state;
|
||||||
uint32_t name;
|
uint32_t name;
|
||||||
int fd;
|
int fd;
|
||||||
int redraw_scheduled;
|
|
||||||
int resized;
|
int resized;
|
||||||
cairo_pattern_t *background;
|
cairo_pattern_t *background;
|
||||||
|
|
||||||
|
|
@ -155,12 +154,6 @@ draw_window(void *data)
|
||||||
window->buffer->height,
|
window->buffer->height,
|
||||||
window->buffer->stride);
|
window->buffer->stride);
|
||||||
|
|
||||||
wl_surface_map(window->surface,
|
|
||||||
window->x - window->margin,
|
|
||||||
window->y - window->margin,
|
|
||||||
window->buffer->width,
|
|
||||||
window->buffer->height);
|
|
||||||
|
|
||||||
width = window->width - 20;
|
width = window->width - 20;
|
||||||
height = window->height - 60;
|
height = window->height - 60;
|
||||||
buffer = buffer_create(window->fd, width, height, (width * 4 + 15) & ~15);
|
buffer = buffer_create(window->fd, width, height, (width * 4 + 15) & ~15);
|
||||||
|
|
@ -178,15 +171,54 @@ draw_window(void *data)
|
||||||
if (window->gears == NULL)
|
if (window->gears == NULL)
|
||||||
window->gears = gears_create(0, 0, 0, 0.92);
|
window->gears = gears_create(0, 0, 0, 0.92);
|
||||||
|
|
||||||
|
window->resized = 0;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
animate_gears(gpointer data)
|
||||||
|
{
|
||||||
|
struct window *window = data;
|
||||||
|
struct buffer *buffer;
|
||||||
|
static uint32_t key;
|
||||||
|
|
||||||
|
/* Right now, resizing the window from the animation is fine,
|
||||||
|
* since the window drawing code is so slow, but once we
|
||||||
|
* implement faster resizing, this will show lag between
|
||||||
|
* pointer motion and window size even if resizing is fast.
|
||||||
|
* We need to keep processing motion events and posting new
|
||||||
|
* frames as fast as possible so when the server composites
|
||||||
|
* the next frame it will have the most recent size possible.
|
||||||
|
* In that case, we need the two ack protocol, where the first
|
||||||
|
* ack signals that the server got the request so we can free
|
||||||
|
* the buffer, to prevent us from allocating a ton of buffer
|
||||||
|
* that will never be displayed. */
|
||||||
|
if (window->resized)
|
||||||
|
draw_window(window);
|
||||||
|
|
||||||
gears_draw(window->gears, window->gears_angle);
|
gears_draw(window->gears, window->gears_angle);
|
||||||
|
|
||||||
|
buffer = window->egl_buffer;
|
||||||
wl_surface_copy(window->surface,
|
wl_surface_copy(window->surface,
|
||||||
10 + window->margin, 50 + window->margin,
|
10 + window->margin, 50 + window->margin,
|
||||||
buffer->name, buffer->stride,
|
buffer->name, buffer->stride,
|
||||||
0, 0, buffer->width, buffer->height);
|
0, 0, buffer->width, buffer->height);
|
||||||
|
|
||||||
wl_display_commit(window->display, 0);
|
/* Shouldn't need to do this here, but without proper commit
|
||||||
|
* support in the server, doing this before rendering the
|
||||||
|
* gears show the window briefly before it's fully
|
||||||
|
* rendered. */
|
||||||
|
|
||||||
window->redraw_scheduled = 0;
|
wl_surface_map(window->surface,
|
||||||
|
window->x - window->margin,
|
||||||
|
window->y - window->margin,
|
||||||
|
window->width + 2 * window->margin,
|
||||||
|
window->height + 2 * window->margin);
|
||||||
|
|
||||||
|
wl_display_commit(window->display, key++);
|
||||||
|
window->gears_angle += 1;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -221,22 +253,20 @@ event_handler(struct wl_display *display,
|
||||||
/* FIXME: Object ID 1 is the display, for anything else we
|
/* FIXME: Object ID 1 is the display, for anything else we
|
||||||
* assume it's an input device. */
|
* assume it's an input device. */
|
||||||
if (object == 1 && opcode == 3) {
|
if (object == 1 && opcode == 3) {
|
||||||
int key = p[0];
|
|
||||||
|
|
||||||
/* The acknowledge event means that the server
|
/* The acknowledge event means that the server
|
||||||
* processed our last comit request and we can now
|
* processed our last commit request and we can now
|
||||||
* safely free the buffer. key == 0 means it's an
|
* safely free the buffer. */
|
||||||
* acknowledge event for the drawing in draw_buffer,
|
if (window->buffer != NULL) {
|
||||||
* key == 1 is from animating the gears, which we
|
|
||||||
* ignore. If the window was resized in the meantime,
|
|
||||||
* schedule another redraw. */
|
|
||||||
if (key == 0) {
|
|
||||||
if (window->resized)
|
|
||||||
g_idle_add(draw_window, window);
|
|
||||||
buffer_destroy(window->buffer, window->fd);
|
buffer_destroy(window->buffer, window->fd);
|
||||||
window->buffer = NULL;
|
window->buffer = NULL;
|
||||||
window->resized = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_idle_add(animate_gears, window);
|
||||||
|
|
||||||
|
} else if (object == 1) {
|
||||||
|
fprintf(stderr, "unexpected event from display: %d\n",
|
||||||
|
opcode);
|
||||||
|
exit(-1);
|
||||||
} else if (opcode == 0) {
|
} else if (opcode == 0) {
|
||||||
int x = p[0], y = p[1];
|
int x = p[0], y = p[1];
|
||||||
|
|
||||||
|
|
@ -251,6 +281,16 @@ event_handler(struct wl_display *display,
|
||||||
window->y - window->margin,
|
window->y - window->margin,
|
||||||
window->width + 2 * window->margin,
|
window->width + 2 * window->margin,
|
||||||
window->height + 2 * window->margin);
|
window->height + 2 * window->margin);
|
||||||
|
/* FIXME: We should do this here:
|
||||||
|
*
|
||||||
|
* wl_display_commit(window->display, 1);
|
||||||
|
*
|
||||||
|
* to make sure the server processes the move,
|
||||||
|
* but that'll mess with the other commit from
|
||||||
|
* animate_gears with the current server
|
||||||
|
* implementation. Since the current server
|
||||||
|
* doesn't rely on commit anyway yet, we can
|
||||||
|
* just forget about it for now. */
|
||||||
break;
|
break;
|
||||||
case WINDOW_RESIZING_LOWER_RIGHT:
|
case WINDOW_RESIZING_LOWER_RIGHT:
|
||||||
window->width = window->drag_x + x;
|
window->width = window->drag_x + x;
|
||||||
|
|
@ -259,21 +299,7 @@ event_handler(struct wl_display *display,
|
||||||
window->width = 400;
|
window->width = 400;
|
||||||
if (window->height < 400)
|
if (window->height < 400)
|
||||||
window->height = 400;
|
window->height = 400;
|
||||||
if (!window->redraw_scheduled) {
|
|
||||||
/* If window->buffer is NULL, it means
|
|
||||||
* we got the ack for the previous
|
|
||||||
* resize, so we can just schedule a
|
|
||||||
* redraw from idle. Otherwise, we're
|
|
||||||
* still expecting an ack and we'll
|
|
||||||
* notice that the size changed in the
|
|
||||||
* ack handler and schedule a redraw
|
|
||||||
* there. */
|
|
||||||
if (window->buffer == NULL)
|
|
||||||
g_idle_add(draw_window, window);
|
|
||||||
else
|
|
||||||
window->resized = 1;
|
window->resized = 1;
|
||||||
window->redraw_scheduled = 1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (opcode == 1) {
|
} else if (opcode == 1) {
|
||||||
|
|
@ -338,6 +364,7 @@ window_create(struct wl_display *display, int fd)
|
||||||
window->state = WINDOW_STABLE;
|
window->state = WINDOW_STABLE;
|
||||||
window->fd = fd;
|
window->fd = fd;
|
||||||
window->background = cairo_pattern_create_rgba (red, green, blue, alpha);
|
window->background = cairo_pattern_create_rgba (red, green, blue, alpha);
|
||||||
|
window->resized = 1;
|
||||||
|
|
||||||
window->egl_display = eglCreateDisplayNative("/dev/dri/card0", "i965");
|
window->egl_display = eglCreateDisplayNative("/dev/dri/card0", "i965");
|
||||||
if (window->egl_display == NULL)
|
if (window->egl_display == NULL)
|
||||||
|
|
@ -354,33 +381,11 @@ window_create(struct wl_display *display, int fd)
|
||||||
if (window->context == NULL)
|
if (window->context == NULL)
|
||||||
die("failed to create context\n");
|
die("failed to create context\n");
|
||||||
|
|
||||||
draw_window(window);
|
animate_gears(window);
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
draw(gpointer data)
|
|
||||||
{
|
|
||||||
struct window *window = data;
|
|
||||||
struct buffer *buffer;
|
|
||||||
|
|
||||||
if (!window->redraw_scheduled) {
|
|
||||||
gears_draw(window->gears, window->gears_angle);
|
|
||||||
|
|
||||||
buffer = window->egl_buffer;
|
|
||||||
wl_surface_copy(window->surface,
|
|
||||||
10 + window->margin, 50 + window->margin,
|
|
||||||
buffer->name, buffer->stride,
|
|
||||||
0, 0, buffer->width, buffer->height);
|
|
||||||
wl_display_commit(window->display, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
window->gears_angle += 1;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
|
|
@ -409,8 +414,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
wl_display_set_event_handler(display, event_handler, window);
|
wl_display_set_event_handler(display, event_handler, window);
|
||||||
|
|
||||||
g_timeout_add(50, draw, window);
|
|
||||||
|
|
||||||
g_main_loop_run(loop);
|
g_main_loop_run(loop);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue