static void bind_output (struct wl_client *client, void *data, guint32 version, guint32 id) { MetaWaylandOutput *wayland_output = data; MetaOutput *output = wayland_output->output; struct wl_resource *resource; guint mode_flags; resource = wl_resource_create (client, &wl_output_interface, MIN (META_WL_OUTPUT_VERSION, version), id); wayland_output->resources = g_list_prepend (wayland_output->resources, resource); wl_resource_set_user_data (resource, wayland_output); wl_resource_set_destructor (resource, output_resource_destroy); meta_verbose ("Binding output %p/%s (%u, %u, %u, %u) x %f\n", output, output->name, output->crtc->rect.x, output->crtc->rect.y, output->crtc->rect.width, output->crtc->rect.height, output->crtc->current_mode->refresh_rate); wl_resource_post_event (resource, WL_OUTPUT_GEOMETRY, (int)output->crtc->rect.x, (int)output->crtc->rect.y, output->width_mm, output->height_mm, /* Cogl values reflect XRandR values, and so does wayland */ output->subpixel_order, output->vendor, output->product, output->crtc->transform); g_assert (output->crtc->current_mode != NULL); mode_flags = WL_OUTPUT_MODE_CURRENT; if (output->crtc->current_mode == output->preferred_mode) mode_flags |= WL_OUTPUT_MODE_PREFERRED; wl_resource_post_event (resource, WL_OUTPUT_MODE, mode_flags, (int)output->crtc->current_mode->width, (int)output->crtc->current_mode->height, (int)output->crtc->current_mode->refresh_rate); output->scale = compute_scale (output); if (version >= WL_OUTPUT_SCALE_SINCE_VERSION) wl_resource_post_event (resource, WL_OUTPUT_SCALE, output->scale); if (version >= WL_OUTPUT_DONE_SINCE_VERSION) wl_resource_post_event (resource, WL_OUTPUT_DONE); }
static void bind_output (struct wl_client *client, void *data, guint32 version, guint32 id) { MetaWaylandOutput *wayland_output = data; MetaMonitorInfo *monitor_info = wayland_output->monitor_info; struct wl_resource *resource; MetaOutput *output = monitor_info->outputs[0]; resource = wl_resource_create (client, &wl_output_interface, version, id); wayland_output->resources = g_list_prepend (wayland_output->resources, resource); wl_resource_set_user_data (resource, wayland_output); wl_resource_set_destructor (resource, output_resource_destroy); meta_verbose ("Binding monitor %p/%s (%u, %u, %u, %u) x %f\n", monitor_info, output->name, monitor_info->rect.x, monitor_info->rect.y, monitor_info->rect.width, monitor_info->rect.height, monitor_info->refresh_rate); send_output_events (resource, wayland_output, monitor_info, TRUE); }
static void meta_wayland_output_finalize (GObject *object) { MetaWaylandOutput *wayland_output = META_WAYLAND_OUTPUT (object); GList *l; wl_global_destroy (wayland_output->global); /* Make sure the wl_output destructor doesn't try to access MetaWaylandOutput * after we have freed it. */ for (l = wayland_output->resources; l; l = l->next) { struct wl_resource *output_resource = l->data; wl_resource_set_user_data (output_resource, NULL); } g_list_free (wayland_output->resources); G_OBJECT_CLASS (meta_wayland_output_parent_class)->finalize (object); }
static void on_surface_destroyed (MetaWaylandSurface *surface) { wl_resource_set_user_data (surface->viewport.resource, NULL); }
static void params_create(struct wl_client *client, struct wl_resource *params_resource, int32_t width, int32_t height, uint32_t format, uint32_t flags) { struct linux_dmabuf_buffer *buffer; int i; buffer = wl_resource_get_user_data(params_resource); if (!buffer) { wl_resource_post_error(params_resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "params was already used to create a wl_buffer"); return; } assert(buffer->params_resource == params_resource); assert(!buffer->buffer_resource); /* Switch the linux_dmabuf_buffer object from params resource to * eventually wl_buffer resource. */ wl_resource_set_user_data(buffer->params_resource, NULL); buffer->params_resource = NULL; if (!buffer->attributes.n_planes) { wl_resource_post_error(params_resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "no dmabuf has been added to the params"); goto err_out; } /* Check for holes in the dmabufs set (e.g. [0, 1, 3]) */ for (i = 0; i < buffer->attributes.n_planes; i++) { if (buffer->attributes.fd[i] == -1) { wl_resource_post_error(params_resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "no dmabuf has been added for plane %i", i); goto err_out; } } buffer->attributes.width = width; buffer->attributes.height = height; buffer->attributes.format = format; buffer->attributes.flags = flags; if (width < 1 || height < 1) { wl_resource_post_error(params_resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS, "invalid width %d or height %d", width, height); goto err_out; } for (i = 0; i < buffer->attributes.n_planes; i++) { off_t size; if ((uint64_t) buffer->attributes.offset[i] + buffer->attributes.stride[i] > UINT32_MAX) { wl_resource_post_error(params_resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, "size overflow for plane %i", i); goto err_out; } if (i == 0 && (uint64_t) buffer->attributes.offset[i] + (uint64_t) buffer->attributes.stride[i] * height > UINT32_MAX) { wl_resource_post_error(params_resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, "size overflow for plane %i", i); goto err_out; } /* Don't report an error as it might be caused * by the kernel not supporting seeking on dmabuf */ size = lseek(buffer->attributes.fd[i], 0, SEEK_END); if (size == -1) break; if (buffer->attributes.offset[i] >= size) { wl_resource_post_error(params_resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, "invalid offset %i for plane %i", buffer->attributes.offset[i], i); goto err_out; } if (buffer->attributes.offset[i] + buffer->attributes.stride[i] > size) { wl_resource_post_error(params_resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, "invalid stride %i for plane %i", buffer->attributes.stride[i], i); goto err_out; } /* Only valid for first plane as other planes might be * sub-sampled according to fourcc format */ if (i == 0 && buffer->attributes.offset[i] + buffer->attributes.stride[i] * height > size) { wl_resource_post_error(params_resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, "invalid buffer stride or height for plane %i", i); goto err_out; } } /* XXX: Some additional sanity checks could be done with respect * to the fourcc format. A centralized collection (kernel or * libdrm) would be useful to avoid code duplication for these * checks (e.g. drm_format_num_planes). */ if (!weston_compositor_import_dmabuf(buffer->compositor, buffer)) goto err_failed; buffer->buffer_resource = wl_resource_create(client, &wl_buffer_interface, 1, 0); if (!buffer->buffer_resource) { wl_resource_post_no_memory(params_resource); goto err_buffer; } wl_resource_set_implementation(buffer->buffer_resource, &linux_dmabuf_buffer_implementation, buffer, destroy_linux_dmabuf_wl_buffer); zwp_linux_buffer_params_v1_send_created(params_resource, buffer->buffer_resource); return; err_buffer: if (buffer->user_data_destroy_func) buffer->user_data_destroy_func(buffer); err_failed: zwp_linux_buffer_params_v1_send_failed(params_resource); err_out: linux_dmabuf_buffer_destroy(buffer); }