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);
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #5
0
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);
}