static void
create_buffer(struct wl_client *client, struct wl_resource *resource,
	      uint32_t id, uint32_t name)
{
	struct wl_gdl_buffer *buffer;

	buffer = malloc(sizeof (*buffer));
	if (!buffer) {
		wl_resource_post_no_memory(resource);
		return;
	}

	if (gdl_get_surface_info(name, &buffer->surface_info) != GDL_SUCCESS) {
		wl_resource_post_error(resource, WL_GDL_ERROR_INVALID_NAME,
				       "invalid surface id %u", name);
		free(buffer);
		return;
	}

	buffer->resource =
		wl_resource_create(client, &wl_buffer_interface, 1, id);
	if (buffer->resource == NULL) {
		wl_resource_post_no_memory(resource);
		free(buffer);
		return;
	}

	wl_resource_set_implementation(buffer->resource,
				       &gdl_buffer_interface,
				       buffer, destroy_buffer);
}
示例#2
0
struct wlegl_handle *
wlegl_handle_create(struct wl_resource *parent, uint32_t id,
		    int32_t num_fds, struct wl_array *ints)
{
	struct wlegl_handle *handle;

	handle = malloc(sizeof *handle);
	if (!handle) {
		wl_resource_post_no_memory(parent);
		return;
	}
	memset(handle, 0, sizeof *handle);

	handle->resource =
		wl_resource_create(wl_resource_get_client(parent),
				   &android_wlegl_handle_interface, 1, id);
	if (!handle->resource) {
		wl_resource_post_no_memory(parent);
		free(handle);
		return;
	}
	wl_resource_set_implementation(handle->resource,
				       &wlegl_handle_implementation,
				       handle, destroy_wlegl_handle);

	wl_array_init(&handle->ints);
	wl_array_init(&handle->fds);

	wl_array_copy(&handle->ints, ints);

	handle->num_fds = num_fds;
	handle->num_ints = ints->size / sizeof(int);
}
示例#3
0
文件: drm.c 项目: daurnimator/arcan
static void create_buffer(struct wl_client *client,
	struct wl_resource *resource, uint32_t id, uint32_t name, int fd,
  int32_t width, int32_t height, uint32_t format,
	int32_t offset0, int32_t stride0, int32_t offset1, int32_t stride1,
	int32_t offset2, int32_t stride2)
{
	struct wl_drm *drm = resource->data;
	struct wl_drm_buffer *buffer;

	buffer = calloc(1, sizeof *buffer);
	if (buffer == NULL) {
		wl_resource_post_no_memory(resource);
		return;
	}

	buffer->drm = drm;
	buffer->width = width;
	buffer->height = height;
	buffer->format = format;
	buffer->fd = fd;
	buffer->offset[0] = offset0;
	buffer->stride[0] = stride0;
	buffer->offset[1] = offset1;
	buffer->stride[1] = stride1;
	buffer->offset[2] = offset2;
	buffer->stride[2] = stride2;

/*
 * these are just for hooking into the 'next' drm buffer layer
 * and thus not needed here
	drm->callbacks->reference_buffer(drm->user_data, name, fd, buffer);
	if (buffer->driver_buffer == NULL){
		wl_resource_post_error(
		resource, WL_DRM_ERROR_INVALID_NAME, "invalid name");
		return;
	}
 */

	buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id);
	if (!buffer->resource) {
		wl_resource_post_no_memory(resource);
		free(buffer);
		return;
	}

	wl_resource_set_implementation(
		buffer->resource, (void (**)(void)) &drm->buffer_interface,
		buffer, destroy_buffer
	);
}
示例#4
0
static bool subcomp_defer_handler(
	struct surface_request* req, struct arcan_shmif_cont* con)
{
	if (!con){
		trace(TRACE_SHELL, "reqfail");
		wl_resource_post_no_memory(req->target);
		return false;
	}

	struct wl_resource* subsurf = wl_resource_create(req->client->client,
		&wl_subsurface_interface, wl_resource_get_version(req->target), req->id);

	if (!subsurf){
		trace(TRACE_SHELL, "reqfail");
		wl_resource_post_no_memory(req->target);
		return false;
	}

	struct comp_surf* surf = wl_resource_get_user_data(req->target);
	wl_resource_set_implementation(subsurf, &subsurf_if, surf, NULL);

	if (!surf){
		trace(TRACE_SHELL, "reqfail");
		wl_resource_post_no_memory(req->target);
		return false;
	}

	surf->acon = *con;
	surf->cookie = 0xfeedface;
	surf->shell_res = subsurf;
	surf->dispatch = subsurf_shmifev_handler;
	surf->sub_parent_res = req->parent;

	snprintf(surf->tracetag, SURF_TAGLEN, "subsurf");

	if (req->parent){
		struct comp_surf* psurf = wl_resource_get_user_data(req->parent);
		if (!psurf->acon.addr){
			trace(TRACE_ALLOC, "bad subsurface, broken parent");
			return false;
		}
		surf->viewport.ext.kind = ARCAN_EVENT(VIEWPORT);
		surf->viewport.ext.viewport.parent = psurf->acon.segment_token;
		arcan_shmif_enqueue(&surf->acon, &surf->viewport);
	}

	trace(TRACE_ALLOC, "subsurface");
	return true;
}
示例#5
0
文件: drm.c 项目: ibab/swc
static void create_prime_buffer(struct wl_client * client,
                                struct wl_resource * resource, uint32_t id,
                                int32_t fd, int32_t width, int32_t height,
                                uint32_t format,
                                int32_t offset0, int32_t stride0,
                                int32_t offset1, int32_t stride1,
                                int32_t offset2, int32_t stride2)
{
    struct wld_buffer * buffer;
    struct wl_resource * buffer_resource;
    union wld_object object = { .i = fd };

    buffer = wld_import_buffer(swc.drm->context, WLD_DRM_OBJECT_PRIME_FD,
                               object, width, height, format, stride0);
    close(fd);

    if (!buffer)
        goto error0;

    buffer_resource = swc_wayland_buffer_create_resource
        (client, wl_resource_get_version(resource), id, buffer);

    if (!buffer_resource)
        goto error1;

    return;

  error1:
    wld_buffer_unreference(buffer);
  error0:
    wl_resource_post_no_memory(resource);
}
示例#6
0
static void
create_data_source(struct wl_client *client,
		   struct wl_resource *resource, uint32_t id)
{
	struct wl_data_source *source;

	source = malloc(sizeof *source);
	if (source == NULL) {
		wl_resource_post_no_memory(resource);
		return;
	}

	source->resource.destroy = destroy_data_source;
	source->resource.object.id = id;
	source->resource.object.interface = &wl_data_source_interface;
	source->resource.object.implementation =
		(void (**)(void)) &data_source_interface;
	source->resource.data = source;
	wl_list_init(&source->resource.destroy_listener_list);

	source->offer_interface = &data_offer_interface;
	source->cancel = data_source_cancel;

	wl_array_init(&source->mime_types);
	wl_client_add_resource(client, &source->resource);
}
示例#7
0
void Screenshooter::shoot(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *outputResource, wl_resource *bufferResource)
{
    weston_output *output = static_cast<weston_output *>(wl_resource_get_user_data(outputResource));
    weston_buffer *buffer = weston_buffer_from_resource(bufferResource);

    if (!buffer) {
        wl_resource_post_no_memory(resource);
        return;
    }

    struct Screenshot
    {
        static void done(void *data, weston_screenshooter_outcome outcome)
        {
            Screenshot *ss = static_cast<Screenshot *>(data);

            switch (outcome) {
                case WESTON_SCREENSHOOTER_SUCCESS:
                    orbital_screenshot_send_done(ss->resource);
                    break;
                case WESTON_SCREENSHOOTER_NO_MEMORY:
                    wl_resource_post_no_memory(ss->resource);
                    break;
                case WESTON_SCREENSHOOTER_BAD_BUFFER:
                    orbital_screenshot_send_failed(ss->resource);
                    break;
            }

            wl_resource_destroy(ss->resource);
            delete ss;
        }

        wl_resource *resource;
    };

    auto res = wl_resource_create(client, &orbital_screenshot_interface, 1, id);
    if (!res) {
        wl_resource_post_no_memory(resource);
        return;
    }

    Screenshot *ss = new Screenshot { res };
    weston_screenshooter_shoot(output, buffer, Screenshot::done, ss);
}
示例#8
0
文件: shm.c 项目: C0DEHERO/swc
static void create_pool(struct wl_client * client,
                        struct wl_resource * resource, uint32_t id,
                        int32_t fd, int32_t size)
{
    struct pool * pool;

    if (!(pool = malloc(sizeof *pool)))
    {
        wl_resource_post_no_memory(resource);
        return;
    }

    pool->resource = wl_resource_create(client, &wl_shm_pool_interface,
                                        wl_resource_get_version(resource), id);

    if (!pool->resource)
    {
        wl_resource_post_no_memory(resource);
        goto error0;
    }

    wl_resource_set_implementation(pool->resource, &shm_pool_implementation,
                                   pool, &destroy_pool_resource);
    pool->data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);

    if (pool->data == MAP_FAILED)
    {
        wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD,
                               "mmap failed: %s", strerror(errno));
        goto error1;
    }

    pool->size = size;
    pool->references = 1;

    return;

  error1:
    wl_resource_destroy(pool->resource);
  error0:
    free(pool);
}
示例#9
0
void CompositorInterface::Private::createRegion(wl_client *client, wl_resource *resource, uint32_t id)
{
    RegionInterface *region = new RegionInterface(q, resource);
    region->create(display->getConnection(client), wl_resource_get_version(resource), id);
    if (!region->resource()) {
        wl_resource_post_no_memory(resource);
        delete region;
        return;
    }
    emit q->regionCreated(region);
}
示例#10
0
文件: xdg_shell.c 项目: N8Fear/swc
static void
get_xdg_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
{
	struct surface *surface = wl_resource_get_user_data(surface_resource);
	struct xdg_surface *xdg_surface;

	xdg_surface = xdg_surface_new(client, wl_resource_get_version(resource), id, surface);

	if (!xdg_surface)
		wl_resource_post_no_memory(resource);
}
示例#11
0
static void create_data_source(struct wl_client * client,
                               struct wl_resource * resource, uint32_t id)
{
    struct wl_resource * data_source;

    data_source = data_source_new(client,
                                  wl_resource_get_version(resource), id);

    if (!data_source)
        wl_resource_post_no_memory(resource);
}
示例#12
0
void CompositorInterface::Private::createSurface(wl_client *client, wl_resource *resource, uint32_t id)
{
    SurfaceInterface *surface = new SurfaceInterface(q, resource);
    surface->create(display->getConnection(client), wl_resource_get_version(resource), id);
    if (!surface->resource()) {
        wl_resource_post_no_memory(resource);
        delete surface;
        return;
    }
    emit q->surfaceCreated(surface);
}
示例#13
0
文件: shell.c 项目: dapus/swc
static void get_shell_surface(struct wl_client * client,
                              struct wl_resource * resource, uint32_t id,
                              struct wl_resource * surface_resource)
{
    struct swc_surface * surface = wl_resource_get_user_data(surface_resource);
    struct swc_shell_surface * shell_surface;

    shell_surface = swc_shell_surface_new(client, id, surface);

    if (!shell_surface)
        wl_resource_post_no_memory(resource);
}
示例#14
0
static void
drm_create_buffer(struct wl_client *client, struct wl_resource *resource,
		  uint32_t id, uint32_t name, int32_t width, int32_t height,
		  uint32_t stride, uint32_t format)
{
	struct wl_drm *drm = resource->data;
	struct wl_drm_buffer *buffer;

	switch (format) {
	case WL_DRM_FORMAT_ARGB8888:
	case WL_DRM_FORMAT_XRGB8888:
		break;
	default:
		wl_resource_post_error(resource,
				       WL_DRM_ERROR_INVALID_FORMAT,
				       "invalid format");
		return;
	}

	buffer = calloc(1, sizeof *buffer);
	if (buffer == NULL) {
		wl_resource_post_no_memory(resource);
		return;
	}

	buffer->drm = drm;
	buffer->buffer.width = width;
	buffer->buffer.height = height;
	buffer->format = format;

	buffer->driver_buffer =
		drm->callbacks->reference_buffer(drm->user_data, name,
						 width, height,
						 stride, format);

	if (buffer->driver_buffer == NULL) {
		wl_resource_post_error(resource,
				       WL_DRM_ERROR_INVALID_NAME,
				       "invalid name");
		return;
	}

	buffer->buffer.resource.object.id = id;
	buffer->buffer.resource.object.interface = &wl_buffer_interface;
	buffer->buffer.resource.object.implementation =
		(void (**)(void)) &drm_buffer_interface;
	buffer->buffer.resource.data = buffer;

	buffer->buffer.resource.destroy = destroy_buffer;
	buffer->buffer.resource.client = resource->client;

	wl_client_add_resource(resource->client, &buffer->buffer.resource);
}
示例#15
0
static void
data_source_offer (struct wl_client *client,
                   struct wl_resource *resource, const char *type)
{
  MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
  char **p;

  p = wl_array_add (&source->mime_types, sizeof *p);
  if (p)
    *p = strdup (type);
  if (!p || !*p)
    wl_resource_post_no_memory (resource);
}
示例#16
0
文件: xdg_shell.c 项目: N8Fear/swc
static void
get_xdg_popup(struct wl_client *client, struct wl_resource *resource,
              uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource,
              struct wl_resource *seat_resource, uint32_t serial, int32_t x, int32_t y)
{
	struct surface *surface = wl_resource_get_user_data(surface_resource);
	struct surface *parent = wl_resource_get_user_data(parent_resource);
	struct xdg_popup *popup;

	popup = xdg_popup_new(client, wl_resource_get_version(resource), id, surface, parent, x, y);

	if (!popup)
		wl_resource_post_no_memory(resource);
}
示例#17
0
文件: shm.c 项目: Kinokoio/swc
static void create_buffer(struct wl_client * client,
                          struct wl_resource * resource, uint32_t id,
                          int32_t offset, int32_t width, int32_t height,
                          int32_t stride, uint32_t format)
{
    struct pool * pool = wl_resource_get_user_data(resource);
    struct pool_reference * reference;
    struct wld_buffer * buffer;
    struct wl_resource * buffer_resource;
    union wld_object object;

    if (offset > pool->size || offset < 0)
    {
        wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_STRIDE,
                               "offset is too big or negative");
        return;
    }

    object.ptr = (void *)((uintptr_t) pool->data + offset);
    buffer = wld_import_buffer(swc.shm->context, WLD_OBJECT_DATA, object,
                               width, height, format_shm_to_wld(format),
                               stride);

    if (!buffer)
        goto error0;

    buffer_resource = wayland_buffer_create_resource
        (client, wl_resource_get_version(resource), id, buffer);

    if (!buffer_resource)
        goto error1;

    if (!(reference = malloc(sizeof *reference)))
        goto error2;

    reference->pool = pool;
    reference->destructor.destroy = &handle_buffer_destroy;
    wld_buffer_add_destructor(buffer, &reference->destructor);
    ++pool->references;

    return;

  error2:
    wl_resource_destroy(buffer_resource);
  error1:
    wld_buffer_unreference(buffer);
  error0:
    wl_resource_post_no_memory(resource);
}
示例#18
0
void DpmsManagerInterface::Private::getDpmsCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *output)
{
    auto p = Private::cast(resource);
    auto c = p->display->getConnection(client);
    OutputInterface *o = OutputInterface::get(output);
    DpmsInterface *dpms = new DpmsInterface(o, resource, p->q);
    dpms->create(c, wl_resource_get_version(resource), id);
    if (!dpms->resource()) {
        wl_resource_post_no_memory(resource);
        return;
    }
    dpms->sendSupported();
    dpms->sendMode();
    dpms->sendDone();
}
示例#19
0
static void
create_buffer(struct wl_client *client, struct wl_resource *resource,
              uint32_t id, uint32_t name, int fd,
              int32_t width, int32_t height,
              uint32_t format,
              int32_t offset0, int32_t stride0,
              int32_t offset1, int32_t stride1,
              int32_t offset2, int32_t stride2)
{
	struct wl_drm *drm = resource->data;
	struct wl_drm_buffer *buffer;

	buffer = calloc(1, sizeof *buffer);
	if (buffer == NULL) {
		wl_resource_post_no_memory(resource);
		return;
	}

	buffer->drm = drm;
	buffer->buffer.width = width;
	buffer->buffer.height = height;
	buffer->format = format;
	buffer->offset[0] = offset0;
	buffer->stride[0] = stride0;
	buffer->offset[1] = offset1;
	buffer->stride[1] = stride1;
	buffer->offset[2] = offset2;
	buffer->stride[2] = stride2;

        drm->callbacks->reference_buffer(drm->user_data, name, fd, buffer);
	if (buffer->driver_buffer == NULL) {
		wl_resource_post_error(resource,
				       WL_DRM_ERROR_INVALID_NAME,
				       "invalid name");
		return;
	}

	buffer->buffer.resource.object.id = id;
	buffer->buffer.resource.object.interface = &wl_buffer_interface;
	buffer->buffer.resource.object.implementation =
		(void (**)(void)) &drm_buffer_interface;
	buffer->buffer.resource.data = buffer;

	buffer->buffer.resource.destroy = destroy_buffer;
	buffer->buffer.resource.client = resource->client;

	wl_client_add_resource(resource->client, &buffer->buffer.resource);
}
示例#20
0
static void
data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
		       struct wl_resource *source_resource,
		       struct wl_resource *origin_resource,
		       struct wl_resource *icon_resource, uint32_t serial)
{
	struct weston_seat *seat = wl_resource_get_user_data(resource);
	struct weston_data_source *source = NULL;
	struct weston_surface *icon = NULL;
	int32_t ret = 0;

	if ((seat->pointer->button_count == 0 ||
	    seat->pointer->grab_serial != serial ||
	    !seat->pointer->focus ||
	    seat->pointer->focus->surface != wl_resource_get_user_data(origin_resource)) &&
		(seat->touch->grab_serial != serial ||
		!seat->touch->focus ||
		seat->touch->focus->surface != wl_resource_get_user_data(origin_resource)))
		return;

	/* FIXME: Check that the data source type array isn't empty. */

	if (source_resource)
		source = wl_resource_get_user_data(source_resource);
	if (icon_resource)
		icon = wl_resource_get_user_data(icon_resource);
	if (icon && icon->configure) {
		wl_resource_post_error(icon_resource,
				       WL_DISPLAY_ERROR_INVALID_OBJECT,
				       "surface->configure already set");
		return;
	}

	if (seat->pointer->button_count == 1 &&
		seat->pointer->grab_serial == serial &&
		seat->pointer->focus &&
		seat->pointer->focus->surface == wl_resource_get_user_data(origin_resource))
		ret = weston_pointer_start_drag(seat->pointer, source, icon, client);
	else if (seat->touch->grab_serial != serial ||
		seat->touch->focus ||
		seat->touch->focus->surface != wl_resource_get_user_data(origin_resource))
		ret = weston_touch_start_drag(seat->touch, source, icon, client);

	if (ret < 0)
		wl_resource_post_no_memory(resource);
}
示例#21
0
        static void done(void *data, weston_screenshooter_outcome outcome)
        {
            Screenshot *ss = static_cast<Screenshot *>(data);

            switch (outcome) {
                case WESTON_SCREENSHOOTER_SUCCESS:
                    orbital_screenshot_send_done(ss->resource);
                    break;
                case WESTON_SCREENSHOOTER_NO_MEMORY:
                    wl_resource_post_no_memory(ss->resource);
                    break;
                case WESTON_SCREENSHOOTER_BAD_BUFFER:
                    orbital_screenshot_send_failed(ss->resource);
                    break;
            }

            wl_resource_destroy(ss->resource);
            delete ss;
        }
示例#22
0
static void
get_data_device(struct wl_client *client,
		struct wl_resource *manager_resource,
		uint32_t id, struct wl_resource *seat_resource)
{
	struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
	struct wl_resource *resource;

	resource = wl_resource_create(client,
				      &wl_data_device_interface, 1, id);
	if (resource == NULL) {
		wl_resource_post_no_memory(manager_resource);
		return;
	}

	wl_list_insert(&seat->drag_resource_list,
		       wl_resource_get_link(resource));
	wl_resource_set_implementation(resource, &data_device_interface,
				       seat, unbind_data_device);
}
示例#23
0
static void
linux_dmabuf_create_params(struct wl_client *client,
			   struct wl_resource *linux_dmabuf_resource,
			   uint32_t params_id)
{
	struct weston_compositor *compositor;
	struct linux_dmabuf_buffer *buffer;
	uint32_t version;
	int i;

	version = wl_resource_get_version(linux_dmabuf_resource);
	compositor = wl_resource_get_user_data(linux_dmabuf_resource);

	buffer = zalloc(sizeof *buffer);
	if (!buffer)
		goto err_out;

	for (i = 0; i < MAX_DMABUF_PLANES; i++)
		buffer->attributes.fd[i] = -1;

	buffer->compositor = compositor;
	buffer->params_resource =
		wl_resource_create(client,
				   &zwp_linux_buffer_params_v1_interface,
				   version, params_id);
	if (!buffer->params_resource)
		goto err_dealloc;

	wl_resource_set_implementation(buffer->params_resource,
				       &zwp_linux_buffer_params_implementation,
				       buffer, destroy_params);

	return;

err_dealloc:
	free(buffer);

err_out:
	wl_resource_post_no_memory(linux_dmabuf_resource);
}
示例#24
0
static void
wlegl_handle_add_fd(struct wl_client *client, struct wl_resource *resource,
		    int32_t fd)
{
	struct wlegl_handle *handle = wl_resource_get_user_data(resource);
	int *next_fd;

	if (handle->fds.size >= handle->num_fds * sizeof(int)) {
		wl_resource_post_error(handle->resource,
				       ANDROID_WLEGL_HANDLE_ERROR_TOO_MANY_FDS,
				       "too many file descriptors");
		close(fd);
		return;
	}

	next_fd = wl_array_add(&handle->fds, sizeof(int));
	if (!next_fd) {
		wl_resource_post_no_memory(resource);
		return;
	}

	*next_fd = fd;
}
示例#25
0
static void
create_data_source(struct wl_client *client,
		   struct wl_resource *resource, uint32_t id)
{
	struct weston_data_source *source;

	source = malloc(sizeof *source);
	if (source == NULL) {
		wl_resource_post_no_memory(resource);
		return;
	}

	wl_signal_init(&source->destroy_signal);
	source->accept = client_source_accept;
	source->send = client_source_send;
	source->cancel = client_source_cancel;

	wl_array_init(&source->mime_types);

	source->resource =
		wl_resource_create(client, &wl_data_source_interface, 1, id);
	wl_resource_set_implementation(source->resource, &data_source_interface,
				       source, destroy_data_source);
}
示例#26
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);
}