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; } }
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; }
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); }
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; }
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(); }
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; }
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; }
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; }
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; }
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); }
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; }
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); }
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; }
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; }
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; }
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); }
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; }
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; }
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; }
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; } }
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; }