diff --git a/client.c b/client.c index 5c8e8ed4..2fb1484c 100644 --- a/client.c +++ b/client.c @@ -112,7 +112,7 @@ int main(int argc, char *argv[]) { struct wl_display *display; struct wl_surface *surface; - const int x = 200, y = 100, width = 300, height = 300; + const int x = 200, y = 200, width = 200, height = 200; int fd, i, ret; uint32_t name, mask; cairo_surface_t *s; @@ -141,11 +141,11 @@ int main(int argc, char *argv[]) cairo_image_surface_get_stride(s)); i = 0; - while (ret = poll(p, 1, 20), ret >= 0) { + while (ret = poll(p, 1, 200), ret >= 0) { if (ret == 0) { wl_surface_map(surface, - x + cos(i / 10.0) * 50, - y + sin(i / 10.0) * 50, + x + cos(i / 10.0) * 150, + y + sin(i / 10.0) * 150, width, height); i++; continue; diff --git a/egl-compositor.c b/egl-compositor.c index a12d4820..fd39216e 100644 --- a/egl-compositor.c +++ b/egl-compositor.c @@ -21,6 +21,7 @@ struct egl_compositor { EGLDisplay display; EGLSurface surface; EGLContext context; + struct wl_display *wl_display; int gem_fd; }; @@ -28,6 +29,7 @@ struct surface_data { uint32_t handle; int32_t width, height, stride; GLuint texture; + struct wl_map map; }; void notify_surface_create(struct wl_compositor *compositor, @@ -134,48 +136,74 @@ void notify_surface_attach(struct wl_compositor *compositor, free(data); } +static void +repaint(struct egl_compositor *ec) +{ + struct wl_surface_iterator *iterator; + struct wl_surface *surface; + struct surface_data *sd; + GLint vertices[12]; + GLint tex_coords[8] = { 1, 0, 1, 1, 0, 1, 0, 0 }; + GLuint indices[4] = { 0, 1, 2, 3 }; + + /* This part is where we actually copy the buffer to screen. + * Needs to be part of the repaint loop, not called from the + * notify_map handler. */ + + glClear(GL_COLOR_BUFFER_BIT); + + iterator = wl_surface_iterator_create(ec->wl_display, 0); + while (wl_surface_iterator_next(iterator, &surface)) { + sd = wl_surface_get_data(surface); + if (sd == NULL) + continue; + + vertices[0] = sd->map.x; + vertices[1] = sd->map.y; + vertices[2] = 0; + + vertices[3] = sd->map.x; + vertices[4] = sd->map.y + sd->map.height; + vertices[5] = 0; + + vertices[6] = sd->map.x + sd->map.width; + vertices[7] = sd->map.y + sd->map.height; + vertices[8] = 0; + + vertices[9] = sd->map.x + sd->map.width; + vertices[10] = sd->map.y; + vertices[11] = 0; + + glBindTexture(GL_TEXTURE_2D, sd->texture); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(3, GL_INT, 0, vertices); + glTexCoordPointer(2, GL_INT, 0, tex_coords); + glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, indices); + } + wl_surface_iterator_destroy(iterator); + + glFlush(); + + eglSwapBuffers(ec->display, ec->surface); +} + void notify_surface_map(struct wl_compositor *compositor, struct wl_surface *surface, struct wl_map *map) { struct egl_compositor *ec = (struct egl_compositor *) compositor; struct surface_data *sd; - GLint vertices[12] = { - map->x, map->y, 0.0, - map->x, map->y + map->height, 0.0, - map->x + map->width, map->y + map->height, 0.0, - map->x + map->width, map->y, 0.0 - }; - GLint tex_coords[8] = { - 1, 0, - 1, 1, - 0, 1, - 0, 0 - }; - GLuint indices[4] = { 0, 1, 2, 3 }; - - /* This part is where we actually copy the buffer to screen. - * Needs to be part of the repaint loop, not in the notify_map - * handler. */ sd = wl_surface_get_data(surface); if (sd == NULL) return; - glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, sd->texture); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(3, GL_INT, 0, vertices); - glTexCoordPointer(2, GL_INT, 0, tex_coords); - glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, indices); - - glFlush(); - - eglSwapBuffers(ec->display, ec->surface); + sd->map = *map; + repaint(ec); } struct wl_compositor_interface interface = { @@ -188,7 +216,7 @@ struct wl_compositor_interface interface = { static const char gem_device[] = "/dev/dri/card0"; struct wl_compositor * -wl_compositor_create(void) +wl_compositor_create(struct wl_display *display) { EGLConfig configs[64]; EGLint major, minor, count; @@ -200,6 +228,7 @@ wl_compositor_create(void) return NULL; ec->base.interface = &interface; + ec->wl_display = display; ec->display = eglCreateDisplay(gem_device, "i965"); if (ec->display == NULL) { diff --git a/wayland-client.c b/wayland-client.c index 025f69ce..6b55f1ce 100644 --- a/wayland-client.c +++ b/wayland-client.c @@ -51,7 +51,6 @@ wl_display_create(const char *address, return NULL; memset(display, 0, sizeof *display); - display->id = 256; /* Need to get our id-range. */ display->fd = socket(PF_LOCAL, SOCK_STREAM, 0); if (display->fd < 0) { free(display); @@ -69,6 +68,10 @@ wl_display_create(const char *address, return NULL; } + /* FIXME: We'll need a protocol for getting a new range, I + * guess... */ + read(display->fd, &display->id, sizeof display->id); + /* FIXME: actually discover advertised objects here. */ read(display->fd, &id, sizeof id); read(display->fd, &length, sizeof length); diff --git a/wayland.c b/wayland.c index 6bad7183..8604bba7 100644 --- a/wayland.c +++ b/wayland.c @@ -14,9 +14,33 @@ #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) -struct wl_region { +struct wl_list { + struct wl_list *prev; + struct wl_list *next; }; +void wl_list_init(struct wl_list *list) +{ + list->prev = list; + list->next = list; +} + +void +wl_list_insert(struct wl_list *list, struct wl_list *elm) +{ + elm->prev = list; + elm->next = list->next; + list->next = elm; + elm->next->prev = elm; +} + +void +wl_list_remove(struct wl_list *elm) +{ + elm->prev->next = elm->next; + elm->next->prev = elm->prev; +} + struct wl_client { struct wl_connection *connection; struct wl_event_source *source; @@ -30,6 +54,9 @@ struct wl_display { struct wl_compositor *compositor; struct wl_compositor_interface *compositor_interface; + + struct wl_list surface_list; + uint32_t client_id_range; }; struct wl_surface { @@ -41,6 +68,7 @@ struct wl_surface { int stride; struct wl_map map; + struct wl_list link; /* how to convert buffer contents to pixels in screen format; * yuv->rgb, indexed->rgb, svg->rgb, but mostly just rgb->rgb. */ @@ -58,7 +86,9 @@ wl_surface_destroy(struct wl_client *client, struct wl_compositor_interface *interface; interface = client->display->compositor->interface; - interface->notify_surface_destroy(client->display->compositor, surface); + interface->notify_surface_destroy(client->display->compositor, + surface); + wl_list_remove(&surface->link); } static void @@ -134,6 +164,8 @@ wl_surface_create(struct wl_display *display, uint32_t id) surface->base.id = id; surface->base.interface = &surface_interface; + wl_list_insert(display->surface_list.prev, &surface->link); + interface = display->compositor->interface; interface->notify_surface_create(display->compositor, surface); @@ -238,11 +270,8 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target, static void wl_client_event(struct wl_client *client, struct wl_object *object, uint32_t event) { - const struct wl_interface *interface; uint32_t p[2]; - interface = object->interface; - p[0] = object->id; p[1] = event | (8 << 16); wl_connection_write(client->connection, p, sizeof p); @@ -355,6 +384,11 @@ wl_client_create(struct wl_display *display, int fd) wl_client_connection_update, client); + wl_connection_write(client->connection, + &display->client_id_range, + sizeof display->client_id_range); + display->client_id_range += 256; + advertise_object(client, &display->base); return client; @@ -421,6 +455,9 @@ wl_display_create(void) display->base.id = 0; display->base.interface = &display_interface; wl_hash_insert(&display->objects, &display->base); + wl_list_init(&display->surface_list); + + display->client_id_range = 256; /* Gah, arbitrary... */ return display; } @@ -489,6 +526,53 @@ wl_display_add_socket(struct wl_display *display) } +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +struct wl_surface_iterator { + struct wl_list *head; + struct wl_surface *surface; + uint32_t mask; +}; + +struct wl_surface_iterator * +wl_surface_iterator_create(struct wl_display *display, uint32_t mask) +{ + struct wl_surface_iterator *iterator; + + iterator = malloc(sizeof *iterator); + if (iterator == NULL) + return NULL; + + iterator->head = &display->surface_list; + iterator->surface = container_of(display->surface_list.next, + struct wl_surface, link); + iterator->mask = mask; + + return iterator; +} + +int +wl_surface_iterator_next(struct wl_surface_iterator *iterator, + struct wl_surface **surface) +{ + if (&iterator->surface->link == iterator->head) + return 0; + + *surface = iterator->surface; + iterator->surface = container_of(iterator->surface->link.next, + struct wl_surface, link); + + return 1; +} + +void +wl_surface_iterator_destroy(struct wl_surface_iterator *iterator) +{ + free(iterator); +} + int main(int argc, char *argv[]) { struct wl_display *display; @@ -501,7 +585,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - compositor = wl_compositor_create(); + compositor = wl_compositor_create(display); wl_display_set_compositor(display, compositor); printf("wayland online, display is %p\n", display); diff --git a/wayland.h b/wayland.h index fc8f0fc5..2865cfe1 100644 --- a/wayland.h +++ b/wayland.h @@ -84,6 +84,13 @@ struct wl_map { void wl_surface_set_data(struct wl_surface *surface, void *data); void *wl_surface_get_data(struct wl_surface *surface); +struct wl_surface_iterator; +struct wl_surface_iterator * +wl_surface_iterator_create(struct wl_display *display, uint32_t mask); +int wl_surface_iterator_next(struct wl_surface_iterator *iterator, + struct wl_surface **surface); +void wl_surface_iterator_destroy(struct wl_surface_iterator *iterator); + struct wl_compositor { struct wl_compositor_interface *interface; }; @@ -100,7 +107,7 @@ struct wl_compositor_interface { struct wl_surface *surface, struct wl_map *map); }; -struct wl_compositor *wl_compositor_create(void); +struct wl_compositor *wl_compositor_create(struct wl_display *display); void wl_display_set_compositor(struct wl_display *display, struct wl_compositor *compositor);