diff --git a/src/compositor-drm.c b/src/compositor-drm.c index c4f9cf64..e704c9f2 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -371,7 +371,7 @@ err_free: } static void -drm_fb_set_buffer(struct drm_fb *fb, struct wl_buffer *buffer) +drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer) { assert(fb->buffer_ref.buffer == NULL); @@ -437,7 +437,7 @@ drm_output_prepare_scanout_surface(struct weston_output *_output, struct drm_output *output = (struct drm_output *) _output; struct drm_compositor *c = (struct drm_compositor *) output->base.compositor; - struct wl_buffer *buffer = es->buffer_ref.buffer; + struct weston_buffer *buffer = es->buffer_ref.buffer; struct gbm_bo *bo; uint32_t format; @@ -791,7 +791,7 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base, if (es->alpha != 1.0f) return NULL; - if (wl_buffer_is_shm(es->buffer_ref.buffer)) + if (wl_shm_buffer_get(es->buffer_ref.buffer->resource)) return NULL; if (!drm_surface_transform_supported(es)) @@ -915,7 +915,7 @@ drm_output_prepare_cursor_surface(struct weston_output *output_base, if (c->cursors_are_broken) return NULL; if (es->buffer_ref.buffer == NULL || - !wl_buffer_is_shm(es->buffer_ref.buffer) || + !wl_shm_buffer_get(es->buffer_ref.buffer->resource) || es->geometry.width > 64 || es->geometry.height > 64) return NULL; @@ -949,8 +949,8 @@ drm_output_set_cursor(struct drm_output *output) output->current_cursor ^= 1; bo = output->cursor_bo[output->current_cursor]; memset(buf, 0, sizeof buf); - stride = wl_shm_buffer_get_stride(es->buffer_ref.buffer); - s = wl_shm_buffer_get_data(es->buffer_ref.buffer); + stride = wl_shm_buffer_get_stride(es->buffer_ref.buffer->shm_buffer); + s = wl_shm_buffer_get_data(es->buffer_ref.buffer->shm_buffer); for (i = 0; i < es->geometry.height; i++) memcpy(buf + i * 64, s + i * stride, es->geometry.width * 4); @@ -1008,7 +1008,7 @@ drm_assign_planes(struct weston_output *output) * non-shm, or small enough to be a cursor */ if ((es->buffer_ref.buffer && - !wl_buffer_is_shm(es->buffer_ref.buffer)) || + !wl_shm_buffer_get(es->buffer_ref.buffer->resource)) || (es->geometry.width <= 64 && es->geometry.height <= 64)) es->keep_buffer = 1; else diff --git a/src/compositor.c b/src/compositor.c index 5c82413b..af273b98 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -1052,6 +1052,42 @@ destroy_surface(struct wl_resource *resource) weston_surface_destroy(surface); } +static void +weston_buffer_destroy_handler(struct wl_listener *listener, void *data) +{ + struct weston_buffer *buffer = + container_of(listener, struct weston_buffer, destroy_listener); + + wl_signal_emit(&buffer->destroy_signal, buffer); + free(buffer); +} + +struct weston_buffer * +weston_buffer_from_resource(struct wl_resource *resource) +{ + struct weston_buffer *buffer; + struct wl_listener *listener; + + listener = wl_resource_get_destroy_listener(resource, + weston_buffer_destroy_handler); + + if (listener) { + buffer = container_of(listener, struct weston_buffer, + destroy_listener); + } else { + buffer = malloc(sizeof *buffer); + memset(buffer, 0, sizeof *buffer); + + buffer->resource = resource; + wl_signal_init(&buffer->destroy_signal); + buffer->destroy_listener.notify = weston_buffer_destroy_handler; + wl_resource_add_destroy_listener(resource, + &buffer->destroy_listener); + } + + return buffer; +} + static void weston_buffer_reference_handle_destroy(struct wl_listener *listener, void *data) @@ -1060,19 +1096,19 @@ weston_buffer_reference_handle_destroy(struct wl_listener *listener, container_of(listener, struct weston_buffer_reference, destroy_listener); - assert((struct wl_buffer *)data == ref->buffer); + assert((struct weston_buffer *)data == ref->buffer); ref->buffer = NULL; } WL_EXPORT void weston_buffer_reference(struct weston_buffer_reference *ref, - struct wl_buffer *buffer) + struct weston_buffer *buffer) { if (ref->buffer && buffer != ref->buffer) { ref->buffer->busy_count--; if (ref->buffer->busy_count == 0) { - assert(ref->buffer->resource.client != NULL); - wl_resource_queue_event(&ref->buffer->resource, + assert(wl_resource_get_client(ref->buffer->resource)); + wl_resource_queue_event(ref->buffer->resource, WL_BUFFER_RELEASE); } wl_list_remove(&ref->destroy_listener.link); @@ -1080,7 +1116,7 @@ weston_buffer_reference(struct weston_buffer_reference *ref, if (buffer && buffer != ref->buffer) { buffer->busy_count++; - wl_signal_add(&buffer->resource.destroy_signal, + wl_signal_add(&buffer->destroy_signal, &ref->destroy_listener); } @@ -1089,7 +1125,8 @@ weston_buffer_reference(struct weston_buffer_reference *ref, } static void -weston_surface_attach(struct weston_surface *surface, struct wl_buffer *buffer) +weston_surface_attach(struct weston_surface *surface, + struct weston_buffer *buffer) { weston_buffer_reference(&surface->buffer_ref, buffer); @@ -1135,7 +1172,7 @@ surface_accumulate_damage(struct weston_surface *surface, pixman_region32_t *opaque) { if (surface->buffer_ref.buffer && - wl_buffer_is_shm(surface->buffer_ref.buffer)) + wl_shm_buffer_get(surface->buffer_ref.buffer->resource)) surface->compositor->renderer->flush_damage(surface); if (surface->transform.enabled) { @@ -1398,10 +1435,10 @@ surface_attach(struct wl_client *client, struct wl_resource *buffer_resource, int32_t sx, int32_t sy) { struct weston_surface *surface = wl_resource_get_user_data(resource); - struct wl_buffer *buffer = NULL; + struct weston_buffer *buffer = NULL; if (buffer_resource) - buffer = buffer_resource->data; + buffer = weston_buffer_from_resource(buffer_resource); /* Attach, attach, without commit in between does not send * wl_buffer.release. */ @@ -1413,7 +1450,7 @@ surface_attach(struct wl_client *client, surface->pending.buffer = buffer; surface->pending.newly_attached = 1; if (buffer) { - wl_signal_add(&buffer->resource.destroy_signal, + wl_signal_add(&buffer->destroy_signal, &surface->pending.buffer_destroy_listener); } } diff --git a/src/compositor.h b/src/compositor.h index 297f9715..3206e450 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -48,6 +48,7 @@ struct weston_transform { }; struct weston_surface; +struct weston_buffer; struct shell_surface; struct weston_seat; struct weston_output; @@ -489,7 +490,7 @@ struct weston_renderer { void (*repaint_output)(struct weston_output *output, pixman_region32_t *output_damage); void (*flush_damage)(struct weston_surface *surface); - void (*attach)(struct weston_surface *es, struct wl_buffer *buffer); + void (*attach)(struct weston_surface *es, struct weston_buffer *buffer); int (*create_surface)(struct weston_surface *surface); void (*surface_set_color)(struct weston_surface *surface, float red, float green, @@ -574,8 +575,21 @@ struct weston_compositor { struct weston_xkb_info xkb_info; }; +struct weston_buffer { + struct wl_resource *resource; + struct wl_signal destroy_signal; + struct wl_listener destroy_listener; + + union { + struct wl_shm_buffer *shm_buffer; + struct wl_buffer *legacy_buffer; + }; + int32_t width, height; + uint32_t busy_count; +}; + struct weston_buffer_reference { - struct wl_buffer *buffer; + struct weston_buffer *buffer; struct wl_listener destroy_listener; }; @@ -740,7 +754,7 @@ struct weston_surface { struct { /* wl_surface.attach */ int newly_attached; - struct wl_buffer *buffer; + struct weston_buffer *buffer; struct wl_listener buffer_destroy_listener; int32_t sx; int32_t sy; @@ -1017,9 +1031,12 @@ weston_surface_unmap(struct weston_surface *surface); struct weston_surface * weston_surface_get_main_surface(struct weston_surface *surface); +struct weston_buffer * +weston_buffer_from_resource(struct wl_resource *resource); + void weston_buffer_reference(struct weston_buffer_reference *ref, - struct wl_buffer *buffer); + struct weston_buffer *buffer); uint32_t weston_compositor_get_time(void); diff --git a/src/gl-renderer.c b/src/gl-renderer.c index 7d27a97d..f0ae3450 100644 --- a/src/gl-renderer.c +++ b/src/gl-renderer.c @@ -1100,7 +1100,7 @@ gl_renderer_flush_damage(struct weston_surface *surface) { struct gl_renderer *gr = get_renderer(surface->compositor); struct gl_surface_state *gs = get_surface_state(surface); - struct wl_buffer *buffer = gs->buffer_ref.buffer; + struct weston_buffer *buffer = gs->buffer_ref.buffer; #ifdef GL_UNPACK_ROW_LENGTH pixman_box32_t *rectangles; @@ -1131,7 +1131,7 @@ gl_renderer_flush_damage(struct weston_surface *surface) glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, gs->pitch, buffer->height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, - wl_shm_buffer_get_data(buffer)); + wl_shm_buffer_get_data(buffer->shm_buffer)); goto done; } @@ -1139,7 +1139,7 @@ gl_renderer_flush_damage(struct weston_surface *surface) #ifdef GL_UNPACK_ROW_LENGTH /* Mesa does not define GL_EXT_unpack_subimage */ glPixelStorei(GL_UNPACK_ROW_LENGTH, gs->pitch); - data = wl_shm_buffer_get_data(buffer); + data = wl_shm_buffer_get_data(buffer->shm_buffer); rectangles = pixman_region32_rectangles(&gs->texture_damage, &n); for (i = 0; i < n; i++) { pixman_box32_t r; @@ -1182,11 +1182,12 @@ ensure_textures(struct gl_surface_state *gs, int num_textures) } static void -gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) +gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) { struct weston_compositor *ec = es->compositor; struct gl_renderer *gr = get_renderer(ec); struct gl_surface_state *gs = get_surface_state(es); + struct wl_shm_buffer *shm_buffer; EGLint attribs[3], format; int i, num_planes; @@ -1203,16 +1204,21 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) return; } - if (wl_buffer_is_shm(buffer)) { + shm_buffer = wl_shm_buffer_get(buffer->resource); + if (shm_buffer) { + buffer->shm_buffer = shm_buffer; + buffer->width = wl_shm_buffer_get_width(shm_buffer); + buffer->height = wl_shm_buffer_get_height(shm_buffer); + /* Only allocate a texture if it doesn't match existing one. * If gs->num_images is not 0, then a switch from DRM allocated * buffer to a SHM buffer is happening, and we need to allocate * a new texture buffer. */ - if (wl_shm_buffer_get_stride(buffer) / 4 != gs->pitch || - wl_shm_buffer_get_height(buffer) != gs->height || + if (wl_shm_buffer_get_stride(shm_buffer) / 4 != gs->pitch || + buffer->height != gs->height || gs->num_images > 0) { - gs->pitch = wl_shm_buffer_get_stride(buffer) / 4; - gs->height = wl_shm_buffer_get_height(buffer); + gs->pitch = wl_shm_buffer_get_stride(shm_buffer) / 4; + gs->height = buffer->height; gs->target = GL_TEXTURE_2D; ensure_textures(gs, 1); @@ -1227,12 +1233,17 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) gs->height / es->buffer_scale); } - if (wl_shm_buffer_get_format(buffer) == WL_SHM_FORMAT_XRGB8888) + if (wl_shm_buffer_get_format(shm_buffer) == WL_SHM_FORMAT_XRGB8888) gs->shader = &gr->texture_shader_rgbx; else gs->shader = &gr->texture_shader_rgba; - } else if (gr->query_buffer(gr->egl_display, buffer, + } else if (gr->query_buffer(gr->egl_display, + (struct wl_buffer *)buffer->resource, EGL_TEXTURE_FORMAT, &format)) { + buffer->legacy_buffer = (struct wl_buffer *)buffer->resource; + buffer->width = buffer->legacy_buffer->width; + buffer->height = buffer->legacy_buffer->height; + for (i = 0; i < gs->num_images; i++) gr->destroy_image(gr->egl_display, gs->images[i]); gs->num_images = 0; @@ -1271,7 +1282,8 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) gs->images[i] = gr->create_image(gr->egl_display, NULL, EGL_WAYLAND_BUFFER_WL, - buffer, attribs); + buffer->legacy_buffer, + attribs); if (!gs->images[i]) { weston_log("failed to create img for plane %d\n", i); continue; diff --git a/src/noop-renderer.c b/src/noop-renderer.c index c0765f26..91659f58 100644 --- a/src/noop-renderer.c +++ b/src/noop-renderer.c @@ -47,7 +47,7 @@ noop_renderer_flush_damage(struct weston_surface *surface) } static void -noop_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) +noop_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) { } diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c index 0bae1a48..25bffbe2 100644 --- a/src/pixman-renderer.c +++ b/src/pixman-renderer.c @@ -529,9 +529,10 @@ pixman_renderer_flush_damage(struct weston_surface *surface) } static void -pixman_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) +pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) { struct pixman_surface_state *ps = get_surface_state(es); + struct wl_shm_buffer *shm_buffer; pixman_format_code_t pixman_format; weston_buffer_reference(&ps->buffer_ref, buffer); @@ -543,14 +544,16 @@ pixman_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) if (!buffer) return; + + shm_buffer = wl_shm_buffer_get(buffer->resource); - if (!wl_buffer_is_shm(buffer)) { + if (! shm_buffer) { weston_log("Pixman renderer supports only SHM buffers\n"); weston_buffer_reference(&ps->buffer_ref, NULL); return; } - switch (wl_shm_buffer_get_format(buffer)) { + switch (wl_shm_buffer_get_format(shm_buffer)) { case WL_SHM_FORMAT_XRGB8888: pixman_format = PIXMAN_x8r8g8b8; break; @@ -563,11 +566,15 @@ pixman_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) return; break; } + + buffer->shm_buffer = shm_buffer; + buffer->width = wl_shm_buffer_get_width(shm_buffer); + buffer->height = wl_shm_buffer_get_height(shm_buffer); + ps->image = pixman_image_create_bits(pixman_format, - wl_shm_buffer_get_width(buffer), - wl_shm_buffer_get_height(buffer), - wl_shm_buffer_get_data(buffer), - wl_shm_buffer_get_stride(buffer)); + buffer->width, buffer->height, + wl_shm_buffer_get_data(shm_buffer), + wl_shm_buffer_get_stride(shm_buffer)); } static int diff --git a/src/rpi-renderer.c b/src/rpi-renderer.c index c3611854..919ecc55 100644 --- a/src/rpi-renderer.c +++ b/src/rpi-renderer.c @@ -226,7 +226,7 @@ rpi_resource_realloc(struct rpi_resource *resource, VC_IMAGE_TYPE_T ifmt, #define PREMULT_ALPHA_FLAG (1 << 31) static VC_IMAGE_TYPE_T -shm_buffer_get_vc_format(struct wl_buffer *buffer) +shm_buffer_get_vc_format(struct wl_shm_buffer *buffer) { switch (wl_shm_buffer_get_format(buffer)) { case WL_SHM_FORMAT_XRGB8888: @@ -240,7 +240,7 @@ shm_buffer_get_vc_format(struct wl_buffer *buffer) } static int -rpi_resource_update(struct rpi_resource *resource, struct wl_buffer *buffer, +rpi_resource_update(struct rpi_resource *resource, struct weston_buffer *buffer, pixman_region32_t *region) { pixman_region32_t write_region; @@ -259,11 +259,11 @@ rpi_resource_update(struct rpi_resource *resource, struct wl_buffer *buffer, if (!buffer) return -1; - ifmt = shm_buffer_get_vc_format(buffer); - width = wl_shm_buffer_get_width(buffer); - height = wl_shm_buffer_get_height(buffer); - stride = wl_shm_buffer_get_stride(buffer); - pixels = wl_shm_buffer_get_data(buffer); + ifmt = shm_buffer_get_vc_format(buffer->shm_buffer); + width = wl_shm_buffer_get_width(buffer->shm_buffer); + height = wl_shm_buffer_get_height(buffer->shm_buffer); + stride = wl_shm_buffer_get_stride(buffer->shm_buffer); + pixels = wl_shm_buffer_get_data(buffer->shm_buffer); ret = rpi_resource_realloc(resource, ifmt & ~PREMULT_ALPHA_FLAG, width, height, stride, height); @@ -356,7 +356,7 @@ rpir_surface_destroy(struct rpir_surface *surface) } static int -rpir_surface_damage(struct rpir_surface *surface, struct wl_buffer *buffer, +rpir_surface_damage(struct rpir_surface *surface, struct weston_buffer *buffer, pixman_region32_t *damage) { pixman_region32_t upload; @@ -1113,11 +1113,11 @@ rpi_renderer_flush_damage(struct weston_surface *base) * having an shm buffer. */ struct rpir_surface *surface = to_rpir_surface(base); - struct wl_buffer *buffer = surface->buffer_ref.buffer; + struct weston_buffer *buffer = surface->buffer_ref.buffer; int ret; assert(buffer); - assert(wl_buffer_is_shm(buffer)); + assert(wl_shm_buffer_get(buffer->resource)); ret = rpir_surface_damage(surface, buffer, &base->damage); if (ret) @@ -1128,7 +1128,7 @@ rpi_renderer_flush_damage(struct weston_surface *base) } static void -rpi_renderer_attach(struct weston_surface *base, struct wl_buffer *buffer) +rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer) { /* Called every time a client commits an attach. */ static int warned; @@ -1138,12 +1138,18 @@ rpi_renderer_attach(struct weston_surface *base, struct wl_buffer *buffer) if (!surface) return; - if (buffer && !wl_buffer_is_shm(buffer) && !warned) { + if (buffer && !wl_shm_buffer_get(buffer->resource) && !warned) { weston_log("Error: non-wl_shm buffers not supported.\n"); warned = 1; return; } + if (wl_shm_buffer_get(buffer->resource)) { + buffer->shm_buffer = wl_shm_buffer_get(buffer->resource); + buffer->width = wl_shm_buffer_get_width(buffer->shm_buffer); + buffer->height = wl_shm_buffer_get_height(buffer->shm_buffer); + } + weston_buffer_reference(&surface->buffer_ref, buffer); /* XXX: need to check if in middle of update diff --git a/src/screenshooter.c b/src/screenshooter.c index 1fdfc9a0..be2e34fd 100644 --- a/src/screenshooter.c +++ b/src/screenshooter.c @@ -46,7 +46,7 @@ struct screenshooter { struct screenshooter_frame_listener { struct wl_listener listener; - struct wl_buffer *buffer; + struct weston_buffer *buffer; struct wl_resource *resource; }; @@ -140,9 +140,9 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data) 0, 0, output->current->width, output->current->height); - stride = wl_shm_buffer_get_stride(l->buffer); + stride = wl_shm_buffer_get_stride(l->buffer->shm_buffer); - d = wl_shm_buffer_get_data(l->buffer); + d = wl_shm_buffer_get_data(l->buffer->shm_buffer); s = pixels + stride * (l->buffer->height - 1); switch (compositor->read_format) { @@ -178,10 +178,15 @@ screenshooter_shoot(struct wl_client *client, struct weston_output *output = wl_resource_get_user_data(output_resource); struct screenshooter_frame_listener *l; - struct wl_buffer *buffer = buffer_resource->data; + struct weston_buffer *buffer = + weston_buffer_from_resource(buffer_resource); - if (!wl_buffer_is_shm(buffer)) + if (!wl_shm_buffer_get(buffer->resource)) return; + + buffer->shm_buffer = wl_shm_buffer_get(buffer->resource); + buffer->width = wl_shm_buffer_get_width(buffer->shm_buffer); + buffer->height = wl_shm_buffer_get_height(buffer->shm_buffer); if (buffer->width < output->current->width || buffer->height < output->current->height)