예제 #1
0
static GstFlowReturn
gst_wayland_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
    GstBufferPoolAcquireParams * params)
{
  GstWaylandBufferPool *self = GST_WAYLAND_BUFFER_POOL_CAST (pool);
  gint width, height, stride;
  gsize size;
  enum wl_shm_format format;
  gint offset;
  void *data;
  GstWlMeta *meta;

  width = GST_VIDEO_INFO_WIDTH (&self->info);
  height = GST_VIDEO_INFO_HEIGHT (&self->info);
  stride = GST_VIDEO_INFO_PLANE_STRIDE (&self->info, 0);
  size = GST_VIDEO_INFO_SIZE (&self->info);
  format =
      gst_video_format_to_wayland_format (GST_VIDEO_INFO_FORMAT (&self->info));

  GST_DEBUG_OBJECT (self, "Allocating buffer of size %" G_GSSIZE_FORMAT
      " (%d x %d, stride %d), format %s", size, width, height, stride,
      gst_wayland_format_to_string (format));

  /* try to reserve another memory block from the shm pool */
  if (self->used + size > self->size)
    goto no_buffer;

  offset = self->used;
  self->used += size;
  data = ((gchar *) self->data) + offset;

  /* create buffer and its metadata object */
  *buffer = gst_buffer_new ();
  meta = (GstWlMeta *) gst_buffer_add_meta (*buffer, GST_WL_META_INFO, NULL);
  meta->pool = self;
  meta->wbuffer = wl_shm_pool_create_buffer (self->wl_pool, offset,
      width, height, stride, format);
  meta->used_by_compositor = FALSE;

  /* configure listening to wl_buffer.release */
  g_mutex_lock (&self->buffers_map_mutex);
  g_hash_table_insert (self->buffers_map, meta->wbuffer, *buffer);
  g_mutex_unlock (&self->buffers_map_mutex);

  wl_buffer_add_listener (meta->wbuffer, &buffer_listener, self);

  /* add the allocated memory on the GstBuffer */
  gst_buffer_append_memory (*buffer,
      gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, data,
          size, 0, size, NULL, NULL));

  return GST_FLOW_OK;

  /* ERROR */
no_buffer:
  {
    GST_WARNING_OBJECT (pool, "can't create buffer");
    return GST_FLOW_ERROR;
  }
}
예제 #2
0
void Buffer::Setup(const SharedMemoryPool &pool,
                   int32_t width,
                   int32_t height,
                   int32_t stride,
                   uint32_t format,
                   int offset) {
  Destroy();

  int size = stride * height;
  if ((offset + size) > pool.size()) {
    throw std::runtime_error("Error! Trying to allocate buffer on small SHM pool.");
  }

  p_->wl_buffer = wl_shm_pool_create_buffer(pool.wl_shm_pool_,
                                            offset,
                                            width,
                                            height,
                                            stride,
                                            format);
  wl_buffer_add_listener(p_->wl_buffer, &Private::kListener, this);
  p_->size.width = width;
  p_->size.height = height;
  p_->stride = stride;
  p_->format = format;
  p_->offset = offset;
  p_->data = (char *) pool.data() + offset;
}
예제 #3
0
파일: util.cpp 프로젝트: nyorain/ny
void ShmBuffer::create()
{
	destroy();
	if(!size_.x || !size_.y) throw std::runtime_error("ny::wayland::ShmBuffer invalid size");
	if(!stride_) throw std::runtime_error("ny::wayland::ShmBuffer invalid stride");

    auto* shm = appContext_->wlShm();
    if(!shm) throw std::runtime_error("ny::wayland::ShmBuffer: wlAC has no wl_shm");

    auto vecSize = stride_ * size_.y;
    shmSize_ = std::max(vecSize, shmSize_);

    auto fd = osCreateAnonymousFile(shmSize_);
    if (fd < 0) throw std::runtime_error("ny::wayland::ShmBuffer: could not create shm file");

	//the fd is not needed here anymore AFTER the pool was created
	//our access to the file is represented by the pool
	auto fdGuard = nytl::makeScopeGuard([&]{ close(fd); });

    auto ptr = mmap(nullptr, shmSize_, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(ptr == MAP_FAILED) throw std::runtime_error("ny::wayland::ShmBuffer: could not mmap file");

	data_ = reinterpret_cast<std::uint8_t*>(ptr);
    pool_ = wl_shm_create_pool(shm, fd, shmSize_);
    buffer_ = wl_shm_pool_create_buffer(pool_, 0, size_.x, size_.y, stride_, format_);

	static constexpr wl_buffer_listener listener
	{
		memberCallback<decltype(&ShmBuffer::released), &ShmBuffer::released, void(wl_buffer*)>
	};

    wl_buffer_add_listener(buffer_, &listener, this);
}
예제 #4
0
파일: wlf_window.c 프로젝트: AMV007/FreeRDP
static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t time)
{
	wlfWindow* window = data;
	wlfBuffer* buffer;
	struct wl_shm_pool* shm_pool;
	void* shm_data;
	void* free_data;
	int fd;
	int fdt;

	if (!window->buffers[0].busy)
		buffer = &window->buffers[0];
	else if (!window->buffers[1].busy)
		buffer = &window->buffers[1];
	else
		return;

	if (!buffer->buffer) {
		fd = shm_open("/wlfreerdp_shm", O_CREAT | O_RDWR, 0666);
		fdt = ftruncate(fd, window->width * window->height * 4);
		if (fdt != 0)
		{
			WLog_ERR(TAG, "window_redraw: could not allocate memory");
			close(fd);
			return;
		}

		shm_data = mmap(NULL, window->width * window->height * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
		if (shm_data == MAP_FAILED)
		{
			WLog_ERR(TAG, "window_redraw: failed to memory map buffer");
			close(fd);
			return;
		}

		shm_pool = wl_shm_create_pool(window->display->shm, fd, window->width * window->height * 4);
		buffer->buffer = wl_shm_pool_create_buffer(shm_pool, 0, window->width, window->height, window->width* 4, WL_SHM_FORMAT_XRGB8888);
		wl_buffer_add_listener(buffer->buffer, &wl_buffer_listener, buffer);
		wl_shm_pool_destroy(shm_pool);
		shm_unlink("/wlfreerdp_shm");
		close(fd);

		free_data = buffer->shm_data;
		buffer->shm_data = shm_data;
		munmap(free_data, window->width * window->height * 4);
	}

	 /* this is the real surface data */
	memcpy(buffer->shm_data, (void*) window->data, window->width * window->height * 4);
	wl_surface_attach(window->surface, buffer->buffer, 0, 0);
	wl_surface_damage(window->surface, 0, 0, window->width, window->height);

	if (callback) wl_callback_destroy(callback);
	window->callback = wl_surface_frame(window->surface);
	wl_callback_add_listener(window->callback, &wl_callback_listener, window);
	wl_surface_commit(window->surface);

	buffer->busy = TRUE;
}
예제 #5
0
void WaylandNativeWindow::finishSwap()
{
    int ret = 0;
    lock();

    WaylandNativeWindowBuffer *wnb = queue.front();
    if (!wnb) {
        wnb = m_lastBuffer;
    } else {
        queue.pop_front();
    }
    assert(wnb);
    m_lastBuffer = wnb;
    wnb->busy = 1;

    ret = readQueue(false);
    if (this->frame_callback) {
        do {
            ret = readQueue(true);
        } while (this->frame_callback && ret != -1);
    }
    if (ret < 0) {
        HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb);
        return;
    }

    if (wnb->wlbuffer == NULL)
    {
        wnb->wlbuffer_from_native_handle(m_android_wlegl, m_display, wl_queue);
        TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer);
        wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this);
        wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue);
    }

    if (m_swap_interval > 0) {
        this->frame_callback = wl_surface_frame(m_window->surface);
        wl_callback_add_listener(this->frame_callback, &frame_listener, this);
        wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue);
    }

    wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0);
    wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height);
    wl_surface_commit(m_window->surface);
    // Some compositors, namely Weston, queue buffer release events instead
    // of sending them immediately.  If a frame event is used, this should
    // not be a problem.  Without a frame event, we need to send a sync
    // request to ensure that they get flushed.
    wl_callback_destroy(wl_display_sync(m_display));
    wl_display_flush(m_display);
    fronted.push_back(wnb);

    m_window->attached_width = wnb->width;
    m_window->attached_height = wnb->height;

    m_damage_rects = NULL;
    m_damage_n_rects = 0;
    unlock();
}
예제 #6
0
int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32_t width,
                              uint32_t height, enum wl_shm_format format)
{
	int ret = UWAC_SUCCESS;
	UwacBuffer* newBuffers;
	int i, fd;
	void* data;
	struct wl_shm_pool* pool;
	newBuffers = realloc(w->buffers, (w->nbuffers + nbuffers) * sizeof(UwacBuffer));

	if (!newBuffers)
		return UWAC_ERROR_NOMEMORY;

	w->buffers = newBuffers;
	memset(w->buffers + w->nbuffers, 0, sizeof(UwacBuffer) * nbuffers);
	fd = uwac_create_anonymous_file(allocSize * nbuffers);

	if (fd < 0)
	{
		return UWAC_ERROR_INTERNAL;
	}

	data = mmap(NULL, allocSize * nbuffers, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

	if (data == MAP_FAILED)
	{
		ret = UWAC_ERROR_NOMEMORY;
		goto error_mmap;
	}

	pool = wl_shm_create_pool(w->display->shm, fd, allocSize * nbuffers);

	if (!pool)
	{
		ret = UWAC_ERROR_NOMEMORY;
		goto error_mmap;
	}

	for (i = 0; i < nbuffers; i++)
	{
		UwacBuffer* buffer = &w->buffers[w->nbuffers + i];
#ifdef HAVE_PIXMAN_REGION
		pixman_region32_init(&buffer->damage);
#else
		region16_init(&buffer->damage);
#endif
		buffer->data = data + (allocSize * i);
		buffer->wayland_buffer = wl_shm_pool_create_buffer(pool, allocSize * i, width, height, w->stride,
		                         format);
		wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, buffer);
	}

	wl_shm_pool_destroy(pool);
	w->nbuffers += nbuffers;
error_mmap:
	close(fd);
	return ret;
}
예제 #7
0
파일: shm.c 프로젝트: videolan/vlc
static void Prepare(vout_display_t *vd, picture_t *pic, subpicture_t *subpic,
                    vlc_tick_t date)
{
    VLC_UNUSED(date);
    vout_display_sys_t *sys = vd->sys;
    struct wl_display *display = sys->embed->display.wl;
    struct wl_surface *surface = sys->embed->handle.wl;
    struct picture_buffer_t *picbuf = pic->p_sys;

    if (picbuf->fd == -1)
        return;

    struct buffer_data *d = malloc(sizeof (*d));
    if (unlikely(d == NULL))
        return;

    d->picture = pic;
    d->counter = &sys->active_buffers;

    off_t offset = picbuf->offset;
    const size_t stride = pic->p->i_pitch;
    const size_t size = pic->p->i_lines * stride;
    struct wl_shm_pool *pool;
    struct wl_buffer *buf;

    pool = wl_shm_create_pool(sys->shm, picbuf->fd, offset + size);
    if (pool == NULL)
    {
        free(d);
        return;
    }

    if (sys->viewport == NULL) /* Poor man's crop */
        offset += 4 * vd->fmt.i_x_offset
                  + pic->p->i_pitch * vd->fmt.i_y_offset;

    buf = wl_shm_pool_create_buffer(pool, offset, vd->fmt.i_visible_width,
                                    vd->fmt.i_visible_height, stride,
                                    WL_SHM_FORMAT_XRGB8888);
    wl_shm_pool_destroy(pool);
    if (buf == NULL)
    {
        free(d);
        return;
    }

    picture_Hold(pic);

    wl_buffer_add_listener(buf, &buffer_cbs, d);
    wl_surface_attach(surface, buf, 0, 0);
    wl_surface_damage(surface, 0, 0, sys->display_width, sys->display_height);
    wl_display_flush(display);

    sys->active_buffers++;

    (void) subpic;
}
예제 #8
0
int WaylandNativeWindow::postBuffer(ANativeWindowBuffer* buffer)
{
    TRACE("");
    WaylandNativeWindowBuffer *wnb = NULL;

    lock();
    std::list<WaylandNativeWindowBuffer *>::iterator it = post_registered.begin();
    for (; it != post_registered.end(); it++)
    {
        if ((*it)->other == buffer)
        {
            wnb = (*it);
            break;
        }
    }
    unlock();
    if (!wnb)
    {
        wnb = new WaylandNativeWindowBuffer(buffer);

        wnb->common.incRef(&wnb->common);
        buffer->common.incRef(&buffer->common);
    }

    int ret = 0;

    lock();
    wnb->busy = 1;
    ret = readQueue(false);
    unlock();

    if (ret < 0) {
        return ret;
    }

    lock();

    if (wnb->wlbuffer == NULL)
    {
        wnb->wlbuffer_from_native_handle(m_android_wlegl, m_display, wl_queue);
        TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer);
        wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this);
        wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue);
        post_registered.push_back(wnb);
    }
    TRACE("%p DAMAGE AREA: %dx%d", wnb, wnb->width, wnb->height);
    wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0);
    wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height);
    wl_surface_commit(m_window->surface);
    wl_display_flush(m_display);

    posted.push_back(wnb);
    unlock();

    return NO_ERROR;
}
예제 #9
0
int WaylandNativeWindow::queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd){
    WaylandNativeWindowBuffer *backbuf = (WaylandNativeWindowBuffer *) buffer;
    int ret = 0;
    lock();
    backbuf->busy = 2;
    unlock();
    while (this->frame_callback && ret != -1)
     	ret = wl_display_dispatch_queue(m_display, this->wl_queue);
    
    if (ret < 0)
	return ret;

    lock();
    this->frame_callback = wl_surface_frame(m_window->surface);
    wl_callback_add_listener(this->frame_callback, &frame_listener, this);
    wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue);

    if (backbuf->wlbuffer == NULL)	
    {
	    struct wl_array ints;
	    int *ints_data;
	    struct android_wlegl_handle *wlegl_handle;
	    buffer_handle_t handle;
		
	    handle = backbuf->handle;

	    wl_array_init(&ints);
	    ints_data = (int*) wl_array_add(&ints, handle->numInts*sizeof(int));
	    memcpy(ints_data, handle->data + handle->numFds, handle->numInts*sizeof(int));
	    wlegl_handle = android_wlegl_create_handle(m_android_wlegl, handle->numFds, &ints);
	    wl_array_release(&ints);
	    for (int i = 0; i < handle->numFds; i++) {
		android_wlegl_handle_add_fd(wlegl_handle, handle->data[i]);
	    }

	    backbuf->wlbuffer = android_wlegl_create_buffer(m_android_wlegl,
			backbuf->width, backbuf->height, backbuf->stride,
			backbuf->format, backbuf->usage, wlegl_handle);

	    android_wlegl_handle_destroy(wlegl_handle);
	    backbuf->common.incRef(&backbuf->common);

	    TRACE("Add listener for %p with %p inside", backbuf, backbuf->wlbuffer);
	    wl_buffer_add_listener(backbuf->wlbuffer, &wl_buffer_listener, this);
	    wl_proxy_set_queue((struct wl_proxy *) backbuf->wlbuffer,
				this->wl_queue);
    }
    wl_surface_attach(m_window->surface, backbuf->wlbuffer, 0, 0); 
    wl_surface_damage(m_window->surface, 0, 0, backbuf->width, backbuf->height);
    wl_surface_commit(m_window->surface);
    fronted.push_back(backbuf);   
 
    unlock();
    return NO_ERROR;
}
예제 #10
0
static void
create_succeeded(void *data,
		 struct zwp_linux_buffer_params_v1 *params,
		 struct wl_buffer *new_buffer)
{
	struct buffer *buffer = data;

	buffer->buffer = new_buffer;
	wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);

	zwp_linux_buffer_params_v1_destroy(params);
}
예제 #11
0
static Eina_Bool 
_evas_swapper_buffer_new(Wl_Swapper *ws, Wl_Buffer *wb)
{
   unsigned int format = WL_SHM_FORMAT_XRGB8888;
   size_t size;

   LOGFN(__FILE__, __LINE__, __FUNCTION__);

   /* make sure swapper has a shm */
   if (!ws->shm) return EINA_FALSE;

   wb->w = ws->w;
   wb->h = ws->h;

   /* calculate new required size */
   size = ((wb->w * sizeof(int)) * wb->h);

   /* check pool size to see if we need to realloc the pool */
   if (ws->used_size + size > ws->pool_size) 
     {
        size_t newsize;

        /* calculate new required size */
        newsize = (ws->pool_size + size);

        /* resize the shm pool */
        wl_shm_pool_resize(ws->pool, newsize);

        ws->pool_size = newsize;
     }

   /* check if this buffer needs argb and set format */
   if (ws->alpha) format = WL_SHM_FORMAT_ARGB8888;

   /* create actual wl_buffer */
   wb->buffer = 
     wl_shm_pool_create_buffer(ws->pool, ws->used_size, wb->w, wb->h, 
                               (wb->w * sizeof(int)), format);

   /* add wayland buffer listener */
   wl_buffer_add_listener(wb->buffer, &_evas_swapper_buffer_listener, wb);

   wb->data = (char *)ws->data + ws->used_size;
   wb->size = size;

   ws->used_size += size;

   wb->ws = ws;

   /* return allocated buffer */
   return EINA_TRUE;
}
예제 #12
0
static void
draw_initial_frame(struct wayland_output *output)
{
	struct wayland_compositor *c =
		(struct wayland_compositor *) output->base.compositor;
	struct wl_shm *shm = c->parent.shm;
	struct wl_surface *surface = output->parent.surface;
	struct wl_shm_pool *pool;
	struct wl_buffer *buffer;

	int width, height, stride;
	int size;
	int fd;
	void *data;

	width = output->mode.width + c->border.left + c->border.right;
	height = output->mode.height + c->border.top + c->border.bottom;
	stride = width * 4;
	size = height * stride;

	fd = os_create_anonymous_file(size);
	if (fd < 0) {
		perror("os_create_anonymous_file");
		return;
	}

	data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (data == MAP_FAILED) {
		perror("mmap");
		close(fd);
		return;
	}

	pool = wl_shm_create_pool(shm, fd, size);

	buffer = wl_shm_pool_create_buffer(pool, 0,
					   width, height,
					   stride,
					   WL_SHM_FORMAT_ARGB8888);
	wl_buffer_add_listener(buffer, &buffer_listener, buffer);
	wl_shm_pool_destroy(pool);
	close(fd);

	memset(data, 0, size);

	wl_surface_attach(surface, buffer, 0, 0);

	/* We only need to damage some part, as its only transparant
	 * pixels anyway. */
	wl_surface_damage(surface, 0, 0, 1, 1);
}
예제 #13
0
static struct wl_buffer *
wayland_create_buffer(struct dri2_egl_surface *dri2_surf,
                      __DRIbuffer *buffer)
{
   struct dri2_egl_display *dri2_dpy =
      dri2_egl_display(dri2_surf->base.Resource.Display);
   struct wl_buffer *buf;

   buf = wl_drm_create_buffer(dri2_dpy->wl_drm, buffer->name,
                              dri2_surf->base.Width, dri2_surf->base.Height,
                              buffer->pitch, dri2_surf->format);
   wl_buffer_add_listener(buf, &wl_buffer_listener, dri2_surf);

   return buf;
}
예제 #14
0
static BufferData *
_create_buffer (gint width,
                gint height)
{
  MechBackendWayland *backend;
  BufferData *buffer;
  gint stride, fd;

  buffer = g_new0 (BufferData, 1);

  backend = _mech_backend_wayland_get ();
  stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width);
  buffer->data_len = stride * height;

  fd = _create_temporary_file (buffer->data_len);
  buffer->data = mmap (NULL, buffer->data_len,
                       PROT_READ | PROT_WRITE, MAP_SHARED,
                       fd, 0);

  if (buffer->data == MAP_FAILED)
    {
      g_critical ("Failed to mmap SHM region: %m");
      g_free (buffer);
      close(fd);
      return NULL;
    }

  buffer->wl_pool = wl_shm_create_pool (backend->wl_shm, fd, buffer->data_len);
  close (fd);

  buffer->wl_buffer = wl_shm_pool_create_buffer (buffer->wl_pool, 0,
                                                 width, height, stride,
                                                 WL_SHM_FORMAT_ARGB8888);
  wl_buffer_add_listener (buffer->wl_buffer, &buffer_listener_funcs, buffer);

  buffer->surface = cairo_image_surface_create_for_data (buffer->data,
                                                         CAIRO_FORMAT_ARGB32,
                                                         width, height, stride);
  buffer->blank = TRUE;
  buffer->released = TRUE;

  return buffer;
}
예제 #15
0
파일: buffer.c 프로젝트: 0x0all/mpv
int shm_buffer_resize(shm_buffer_t *buffer, uint32_t width, uint32_t height)
{
    uint32_t new_stride = SHM_BUFFER_STRIDE(width, buffer->bytes);
    uint32_t new_size = new_stride * height;

    if (SHM_BUFFER_IS_BUSY(buffer)) {
        SHM_BUFFER_SET_PNDNG_RSZ(buffer);
        buffer->pending_width = width;
        buffer->pending_height = height;
        return SHM_BUFFER_BUSY;
    }

    SHM_BUFFER_CLEAR_PNDNG_RSZ(buffer);

    if (new_size > buffer->pool_size) {
        munmap(buffer->data, buffer->pool_size);
        ftruncate(buffer->fd, new_size);

        buffer->data = mmap(NULL, new_size, PROT_READ | PROT_WRITE,
                            MAP_SHARED, buffer->fd, 0);

        // TODO: the buffer should be destroyed when -1 is return
        if (buffer->data == MAP_FAILED)
            return -1;

        wl_shm_pool_resize(buffer->shm_pool, new_size);
        buffer->pool_size = new_size;
    }

    const void *listener = wl_proxy_get_listener((struct wl_proxy*)buffer->buffer);

    wl_buffer_destroy(buffer->buffer);
    buffer->buffer = wl_shm_pool_create_buffer(buffer->shm_pool,
                                               0, width, height, new_stride,
                                               buffer->format.wl_format);

    wl_buffer_add_listener(buffer->buffer, listener, buffer);

    buffer->height = height;
    buffer->stride = new_stride;

    return 0;
}
예제 #16
0
파일: buffer.c 프로젝트: 0x0all/mpv
shm_buffer_t* shm_buffer_create(uint32_t width,
                                uint32_t height,
                                format_t fmt,
                                struct wl_shm *shm,
                                const struct wl_buffer_listener *listener)
{
    int8_t bytes = format_get_bytes(&fmt);
    uint32_t stride = SHM_BUFFER_STRIDE(width, bytes);
    uint32_t size = stride * height;

    shm_buffer_t *buffer = calloc(1, sizeof(shm_buffer_t));
    int fd = memfile_create(size);

    if (fd < 0)
        return NULL;

    buffer->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    if (buffer->data == MAP_FAILED) {
        close(fd);
        return NULL;
    }

    buffer->shm_pool = wl_shm_create_pool(shm, fd, size);
    buffer->buffer = wl_shm_pool_create_buffer(buffer->shm_pool,
                                               0, width, height, stride,
                                               fmt.wl_format);

    wl_buffer_add_listener(buffer->buffer, listener, buffer);

    buffer->fd = fd;
    buffer->height = height;
    buffer->stride = stride;
    buffer->format = fmt;
    buffer->bytes = bytes;
    buffer->pool_size = size;
    buffer->pending_height = 0;
    buffer->pending_width = 0;

    return buffer;
}
    QWaylandBrcmBuffer(QWaylandDisplay *display,
                       struct qt_brcm *brcm,
                       const QSize &size,
                       EGLint *data,
                       int count)
        : m_size(size)
        , m_released(true)
        , m_display(display)
    {
        wl_array_init(&m_array);
        m_data = static_cast<EGLint *>(wl_array_add(&m_array, count * sizeof(EGLint)));

        for (int i = 0; i < count; ++i)
            m_data[i] = data[i];

        mBuffer = qt_brcm_create_buffer(brcm, size.width(), size.height(), &m_array);

        static const struct wl_buffer_listener buffer_listener = {
            QWaylandBrcmBuffer::buffer_release
        };

        wl_buffer_add_listener(mBuffer, &buffer_listener, this);
    }
예제 #18
0
static int
create_shm_buffer(struct display *display, struct buffer *buffer,
		  int width, int height, uint32_t format)
{
	struct wl_shm_pool *pool;
	int fd, size, pitch;
	void *data;

	pitch = width * 4;
	size = pitch * height;

	fd = os_create_anonymous_file(size);
	if (fd < 0) {
		fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
			size);
		return -1;
	}

	data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (data == MAP_FAILED) {
		fprintf(stderr, "mmap failed: %m\n");
		close(fd);
		return -1;
	}

	pool = wl_shm_create_pool(display->shm, fd, size);
	buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
						   width, height,
						   pitch, format);
	wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
	wl_shm_pool_destroy(pool);
	close(fd);

	buffer->shm_data = data;

	return 0;
}
예제 #19
0
int WaylandNativeWindow::postBuffer(ANativeWindowBuffer* buffer)
{
    TRACE("");
    WaylandNativeWindowBuffer *wnb = NULL;

    lock();
    std::list<WaylandNativeWindowBuffer *>::iterator it = post_registered.begin();
    for (; it != post_registered.end(); it++)
    {
        if ((*it)->other == buffer)
        {
            wnb = (*it);
            break;
        }
    }
    unlock();
    if (!wnb)
    {
        wnb = new WaylandNativeWindowBuffer(buffer);

        wnb->common.incRef(&wnb->common);
        buffer->common.incRef(&buffer->common);
    }

    int ret = 0;

    lock();
    wnb->busy = 1;
    unlock();
    /* XXX locking/something is a bit fishy here */
    while (this->frame_callback && ret != -1) {
        ret = wl_display_dispatch_queue(m_display, this->wl_queue);
    }

    if (ret < 0) {
        TRACE("wl_display_dispatch_queue returned an error:%i", ret);
        check_fatal_error(m_display);
        return ret;
    }

    lock();
    this->frame_callback = wl_surface_frame(m_window->surface);
    wl_callback_add_listener(this->frame_callback, &frame_listener, this);
    wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue);

    if (wnb->wlbuffer == NULL)
    {
        wnb->wlbuffer_from_native_handle(m_android_wlegl);
        TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer);
        wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this);
        wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue);
        post_registered.push_back(wnb);
    }
    TRACE("%p DAMAGE AREA: %dx%d", wnb, wnb->width, wnb->height);
    wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0);
    wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height);
    wl_surface_commit(m_window->surface);
    //--m_freeBufs;
    //pthread_cond_signal(&cond);
    posted.push_back(wnb);
    unlock();

    return NO_ERROR;
}
static gboolean
gst_vaapi_window_wayland_render (GstVaapiWindow * window,
                                 GstVaapiSurface * surface,
                                 const GstVaapiRectangle * src_rect,
                                 const GstVaapiRectangle * dst_rect, guint flags)
{
    GstVaapiWindowWaylandPrivate *const priv =
        GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window);
    GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (window);
    struct wl_display *const wl_display =
        GST_VAAPI_OBJECT_NATIVE_DISPLAY (window);
    struct wl_buffer *buffer;
    FrameState *frame;
    guint width, height, va_flags;
    VAStatus status;
    gboolean need_vpp = FALSE;

    /* Check that we don't need to crop source VA surface */
    gst_vaapi_surface_get_size (surface, &width, &height);
    if (src_rect->x != 0 || src_rect->y != 0)
        need_vpp = TRUE;
    if (src_rect->width != width || src_rect->height != height)
        need_vpp = TRUE;

    /* Check that we don't render to a subregion of this window */
    if (dst_rect->x != 0 || dst_rect->y != 0)
        need_vpp = TRUE;
    if (dst_rect->width != window->width || dst_rect->height != window->height)
        need_vpp = TRUE;

    /* Try to construct a Wayland buffer from VA surface as is (without VPP) */
    if (!need_vpp) {
        GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
        va_flags = from_GstVaapiSurfaceRenderFlags (flags);
        status = vaGetSurfaceBufferWl (GST_VAAPI_DISPLAY_VADISPLAY (display),
                                       GST_VAAPI_OBJECT_ID (surface),
                                       va_flags & (VA_TOP_FIELD | VA_BOTTOM_FIELD), &buffer);
        GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
        if (status == VA_STATUS_ERROR_FLAG_NOT_SUPPORTED)
            need_vpp = TRUE;
        else if (!vaapi_check_status (status, "vaGetSurfaceBufferWl()"))
            return FALSE;
    }

    /* Try to construct a Wayland buffer with VPP */
    if (need_vpp) {
        if (priv->use_vpp) {
            GstVaapiSurface *const vpp_surface =
                vpp_convert (window, surface, src_rect, dst_rect, flags);
            if (G_UNLIKELY (!vpp_surface))
                need_vpp = FALSE;
            else {
                surface = vpp_surface;
                width = window->width;
                height = window->height;
            }
        }

        GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
        status = vaGetSurfaceBufferWl (GST_VAAPI_DISPLAY_VADISPLAY (display),
                                       GST_VAAPI_OBJECT_ID (surface), VA_FRAME_PICTURE, &buffer);
        GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
        if (!vaapi_check_status (status, "vaGetSurfaceBufferWl()"))
            return FALSE;
    }

    /* Wait for the previous frame to complete redraw */
    if (!gst_vaapi_window_wayland_sync (window)) {
        wl_buffer_destroy (buffer);
        return !priv->sync_failed;
    }

    frame = frame_state_new (window);
    if (!frame)
        return FALSE;
    g_atomic_pointer_set (&priv->last_frame, frame);
    g_atomic_int_inc (&priv->num_frames_pending);

    if (need_vpp && priv->use_vpp) {
        frame->surface = surface;
        frame->surface_pool = gst_vaapi_video_pool_ref (priv->surface_pool);
    }

    /* XXX: attach to the specified target rectangle */
    GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
    wl_surface_attach (priv->surface, buffer, 0, 0);
    wl_surface_damage (priv->surface, 0, 0, width, height);

    if (priv->opaque_region) {
        wl_surface_set_opaque_region (priv->surface, priv->opaque_region);
        wl_region_destroy (priv->opaque_region);
        priv->opaque_region = NULL;
    }

    wl_proxy_set_queue ((struct wl_proxy *) buffer, priv->event_queue);
    wl_buffer_add_listener (buffer, &frame_buffer_listener, frame);

    frame->callback = wl_surface_frame (priv->surface);
    wl_callback_add_listener (frame->callback, &frame_callback_listener, frame);

    wl_surface_commit (priv->surface);
    wl_display_flush (wl_display);
    GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
    return TRUE;
}
예제 #21
0
 WaylandBuffer(wl_shm* shm, uint32_t width, uint32_t height) {
     mBufferListener.release = hookBufferRelease;
     mBuffer = createShmBuffer(shm, width, height);
     wl_buffer_add_listener(mBuffer, &mBufferListener, this);
     mReadyToDraw = true;
 }
예제 #22
0
static gboolean
_eventd_nd_wl_create_buffer(EventdNdSurface *self)
{
    struct wl_shm_pool *pool;
    struct wl_buffer *buffer;
    gint fd;
    gpointer data;
    gint width, height, stride;
    gsize size;

    width = self->width * self->context->scale;
    height = self->height * self->context->scale;
    stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
    size = stride * height;

    gchar *filename;
    filename = g_build_filename(g_get_user_runtime_dir(), PACKAGE_NAME G_DIR_SEPARATOR_S "wayland-surface", NULL);
    fd = g_open(filename, O_CREAT | O_RDWR | O_CLOEXEC, 0);
    g_unlink(filename);
    g_free(filename);
    if ( fd < 0 )
    {
        g_warning("creating a buffer file for %zu B failed: %s\n", size, g_strerror(errno));
        return FALSE;
    }
    if ( ftruncate(fd, size) < 0 )
    {
        close(fd);
        return FALSE;
    }

    data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if ( data == MAP_FAILED )
    {
        g_warning("mmap failed: %s\n", g_strerror(errno));
        close(fd);
        return FALSE;
    }

    cairo_surface_t *cairo_surface;
    cairo_surface = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, 4 * width);
    cairo_surface_set_device_scale(cairo_surface, self->context->scale, self->context->scale);
    self->context->nd->notification_draw(self->notification, cairo_surface, TRUE);
    cairo_surface_destroy(cairo_surface);

    munmap(data, size);

    pool = wl_shm_create_pool(self->context->shm, fd, size);
    buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
    wl_shm_pool_destroy(pool);
    close(fd);

    if ( self->buffer != NULL )
        _eventd_nd_wl_buffer_release(self->buffer, self->buffer->buffer);

    self->buffer = g_new0(EventdNdWlBuffer, 1);
    self->buffer->buffer = buffer;
    self->buffer->data = data;
    self->buffer->size = size;

    wl_buffer_add_listener(buffer, &_eventd_nd_wl_buffer_listener, self->buffer);

    wl_surface_damage(self->surface, 0, 0, self->width, self->height);
    wl_surface_attach(self->surface, self->buffer->buffer, 0, 0);
    if ( wl_surface_get_version(self->surface) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION )
        wl_surface_set_buffer_scale(self->surface, self->context->scale);
    wl_surface_commit(self->surface);

    return TRUE;
}
static gboolean
gst_mfx_window_wayland_render (GstMfxWindow * window,
    GstMfxSurface * surface,
    const GstMfxRectangle * src_rect, const GstMfxRectangle * dst_rect)
{
  GstMfxWindowWaylandPrivate *const priv =
      GST_MFX_WINDOW_WAYLAND_GET_PRIVATE (window);
  GstMfxDisplayWaylandPrivate *const display_priv =
      GST_MFX_DISPLAY_WAYLAND_GET_PRIVATE (GST_MFX_WINDOW_DISPLAY (window));
  struct wl_display *const display =
      GST_MFX_DISPLAY_HANDLE (GST_MFX_WINDOW_DISPLAY (window));
  GstMfxPrimeBufferProxy *buffer_proxy;
  struct wl_buffer *buffer;
  FrameState *frame;
  guintptr fd = 0;
  guint32 drm_format = 0;
  gint offsets[3] = { 0 }, pitches[3] = { 0 }, num_planes = 0, i = 0;
  VaapiImage *vaapi_image;

  buffer_proxy = gst_mfx_prime_buffer_proxy_new_from_surface (surface);
  if (!buffer_proxy)
    return FALSE;

  fd = GST_MFX_PRIME_BUFFER_PROXY_HANDLE (buffer_proxy);
  vaapi_image = gst_mfx_prime_buffer_proxy_get_vaapi_image (buffer_proxy);
  num_planes = vaapi_image_get_plane_count (vaapi_image);

  if ((dst_rect->height != src_rect->height)
      || (dst_rect->width != src_rect->width)) {
#ifdef USE_WESTON_4_0
    if (priv->wp_viewport) {
      wp_viewport_set_destination (priv->wp_viewport,
          dst_rect->width, dst_rect->height);
    }
#else
    if (priv->viewport) {
      wl_viewport_set_destination (priv->viewport,
          dst_rect->width, dst_rect->height);
    }
#endif
  }

  for (i = 0; i < num_planes; i++) {
    offsets[i] = vaapi_image_get_offset (vaapi_image, i);
    pitches[i] = vaapi_image_get_pitch (vaapi_image, i);
  }

  if (GST_VIDEO_FORMAT_NV12 == vaapi_image_get_format (vaapi_image)) {
    drm_format = WL_DRM_FORMAT_NV12;
  } else if (GST_VIDEO_FORMAT_BGRA == vaapi_image_get_format (vaapi_image)) {
    drm_format = WL_DRM_FORMAT_ARGB8888;
  }

  if (!drm_format)
    goto error;

  if (!display_priv->drm)
    goto error;

  GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window));
  buffer =
      wl_drm_create_prime_buffer (display_priv->drm, fd,
          src_rect->width, src_rect->height, drm_format,
          offsets[0], pitches[0],
          offsets[1], pitches[1],
          offsets[2], pitches[2]);
  GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window));
  if (!buffer) {
    GST_ERROR ("No wl_buffer created\n");
    goto error;
  }

  frame = frame_state_new (window);
  if (!frame)
    goto error;

  g_atomic_pointer_set (&priv->last_frame, frame);
  g_atomic_int_inc (&priv->num_frames_pending);

  GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window));
  wl_surface_attach (priv->surface, buffer, 0, 0);

  wl_surface_damage (priv->surface, 0, 0, dst_rect->width, dst_rect->height);

  if (priv->opaque_region) {
    wl_surface_set_opaque_region (priv->surface, priv->opaque_region);
    wl_region_destroy (priv->opaque_region);
    priv->opaque_region = NULL;
  }
  wl_proxy_set_queue ((struct wl_proxy *) buffer, priv->event_queue);
  wl_buffer_add_listener (buffer, &frame_buffer_listener, frame);

  frame->callback = wl_surface_frame (priv->surface);
  wl_callback_add_listener (frame->callback, &frame_callback_listener, frame);

  wl_surface_commit (priv->surface);
  wl_display_flush (display);

  GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window));

  vaapi_image_unref (vaapi_image);
  gst_mfx_prime_buffer_proxy_unref (buffer_proxy);

  return TRUE;
error:
  {
    vaapi_image_unref (vaapi_image);
    gst_mfx_prime_buffer_proxy_unref (buffer_proxy);
    return FALSE;
  }
}
예제 #24
0
int WaylandNativeWindow::queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd)
{
    WaylandNativeWindowBuffer *wnb = (WaylandNativeWindowBuffer*) buffer;
    int ret = 0;

    HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer", "-%p", wnb);
    lock();
    wnb->busy = 1;
    unlock();
    /* XXX locking/something is a bit fishy here */
    HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb);

    while (this->frame_callback && ret != -1) {
        ret = wl_display_dispatch_queue(m_display, this->wl_queue);
    }


    if (ret < 0) {
        TRACE("wl_display_dispatch_queue returned an error");
        HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb);
        check_fatal_error(m_display);
        return ret;
    }

    HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb);


    lock();

    if (debugenvchecked == 0)
    {
        if (getenv("HYBRIS_WAYLAND_DUMP_BUFFERS") != NULL)
            debugenvchecked = 2;
        else
            debugenvchecked = 1;
    }
    if (debugenvchecked == 2)
    {
        HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_dumping_buffer", "-%p", wnb);
        hybris_dump_buffer_to_file(wnb->getNativeBuffer());
        HYBRIS_TRACE_END("wayland-platform", "queueBuffer_dumping_buffer", "-%p", wnb);

    }

#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2
    HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_waiting_for_fence", "-%p", wnb);
    sync_wait(fenceFd, -1);
    close(fenceFd);
    HYBRIS_TRACE_END("wayland-platform", "queueBuffer_waiting_for_fence", "-%p", wnb);
#endif

    this->frame_callback = wl_surface_frame(m_window->surface);
    wl_callback_add_listener(this->frame_callback, &frame_listener, this);
    wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue);

    if (wnb->wlbuffer == NULL)
    {
        wnb->wlbuffer_from_native_handle(m_android_wlegl);
        TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer);
        wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this);
        wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue);
    }
    TRACE("%p DAMAGE AREA: %dx%d", wnb, wnb->width, wnb->height);
    HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_attachdamagecommit", "-resource@%i", wl_proxy_get_id((struct wl_proxy *) wnb->wlbuffer));

    wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0);
    wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height);
    wl_surface_commit(m_window->surface);
    wl_display_flush(m_display);
    HYBRIS_TRACE_END("wayland-platform", "queueBuffer_attachdamagecommit", "-resource@%i", wl_proxy_get_id((struct wl_proxy *) wnb->wlbuffer));

    //--m_freeBufs;
    //pthread_cond_signal(&cond);
    fronted.push_back(wnb);
    HYBRIS_TRACE_COUNTER("wayland-platform", "fronted.size", "%i", fronted.size());

    if (fronted.size() == m_bufList.size())
    {
        HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_wait_for_nonfronted_buffer", "-%p", wnb);

        /* We have fronted all our buffers, let's wait for one of them to be free */
        do {
            unlock();
            ret = wl_display_dispatch_queue(m_display, this->wl_queue);
            lock();
            if (ret == -1)
            {
                check_fatal_error(m_display);
                break;
            }
            HYBRIS_TRACE_COUNTER("wayland-platform", "fronted.size", "%i", fronted.size());

            if (fronted.size() != m_bufList.size())
                break;
        } while (1);
        HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_nonfronted_buffer", "-%p", wnb);
    }
    HYBRIS_TRACE_END("wayland-platform", "queueBuffer", "-%p", wnb);
    unlock();

    return NO_ERROR;
}