int WaylandNativeWindow::readQueue(bool block) { int ret = 0; if (++m_queueReads == 1) { if (block) { ret = wl_display_dispatch_queue(m_display, wl_queue); } else { ret = wl_display_dispatch_queue_pending(m_display, wl_queue); } // all threads waiting on the false branch will wake and return now, so we // can safely set m_queueReads to 0 here instead of relying on every thread // to decrement it. This prevents a race condition when a thread enters readQueue() // before the one in this thread returns. // The new thread would go in the false branch, and there would be no thread in the // true branch, blocking the new thread and any other that will call readQueue in // the future. m_queueReads = 0; pthread_cond_broadcast(&cond); if (ret < 0) { TRACE("wl_display_dispatch_queue returned an error"); check_fatal_error(m_display); return ret; } } else if (block) { while (m_queueReads > 0) { pthread_cond_wait(&cond, &mutex); } } return ret; }
extern "C" EGLNativeWindowType waylandws_CreateWindow(EGLNativeWindowType win, _EGLDisplay *display) { struct wl_egl_window *wl_window = (struct wl_egl_window*) win; struct wl_display *wl_display = (struct wl_display*) display; if (wl_window == 0 || wl_display == 0) { HYBRIS_ERROR("Running with EGL_PLATFORM=wayland without setup wayland environment is not possible"); HYBRIS_ERROR("If you want to run a standlone EGL client do it like this:"); HYBRIS_ERROR(" $ export EGL_PLATFORM=null"); HYBRIS_ERROR(" $ test_glevs2"); abort(); } WaylandDisplay *wdpy = (WaylandDisplay *)display; int ret = 0; while (ret == 0 && !wdpy->wlegl) { ret = wl_display_dispatch_queue(wdpy->wl_dpy, wdpy->queue); } assert(ret >= 0); WaylandNativeWindow *window = new WaylandNativeWindow((struct wl_egl_window *) win, wdpy->wl_dpy, wdpy->wlegl, alloc, gralloc); window->common.incRef(&window->common); return (EGLNativeWindowType) static_cast<struct ANativeWindow *>(window); }
void QWaylandDisplay::blockingReadEvents() { int ret = wl_display_dispatch_queue(mDisplay, mEventQueue); if (ret < 0) { qWarning("The wayland connection broke (error %d). Did the wayland compositor die?", errno); exit(1); } }
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; }
int wayland_roundtrip(struct wl_egl_display *display) { struct wl_callback *callback; int done = 0, ret = 0; wl_display_dispatch_queue_pending(display->display, display->queue); callback = wl_display_sync(display->display); wl_callback_add_listener(callback, &roundtrip_listener, &done); wl_proxy_set_queue((struct wl_proxy *)callback, display->queue); while (ret == 0 && !done) ret = wl_display_dispatch_queue(display->display, display->queue); return ret; }
extern "C" void waylandws_Terminate(_EGLDisplay *dpy) { WaylandDisplay *wdpy = (WaylandDisplay *)dpy; int ret = 0; // We still have the sync callback on flight, wait for it to arrive while (ret == 0 && !wdpy->wlegl) { ret = wl_display_dispatch_queue(wdpy->wl_dpy, wdpy->queue); } assert(ret >= 0); android_wlegl_destroy(wdpy->wlegl); wl_registry_destroy(wdpy->registry); wl_event_queue_destroy(wdpy->queue); delete wdpy; }
int WaylandNativeWindow::wayland_roundtrip(WaylandNativeWindow *display) { struct wl_callback *callback; int done = 0, ret = 0; wl_display_dispatch_queue_pending(display->m_display, display->wl_queue); callback = wl_display_sync(display->m_display); wl_callback_add_listener(callback, &sync_listener, &done); wl_proxy_set_queue((struct wl_proxy *) callback, display->wl_queue); while (ret == 0 && !done) ret = wl_display_dispatch_queue(display->m_display, display->wl_queue); return ret; }
int wayland_roundtrip(struct wayland_display *display) { struct wl_callback *callback; int done = 0, ret = 0; callback = wl_display_sync(display->dpy); wl_callback_add_listener(callback, &sync_listener, &done); wl_proxy_set_queue((struct wl_proxy *) callback, display->queue); while (ret != -1 && !done) ret = wl_display_dispatch_queue(display->dpy, display->queue); if (!done) wl_callback_destroy(callback); return ret; }
static boolean wayland_surface_swap_buffers(struct native_surface *nsurf) { struct wayland_surface *surface = wayland_surface(nsurf); struct wayland_display *display = surface->display; int ret = 0; while (surface->frame_callback && ret != -1) ret = wl_display_dispatch_queue(display->dpy, display->queue); if (ret == -1) return EGL_FALSE; surface->frame_callback = wl_surface_frame(surface->win->surface); wl_callback_add_listener(surface->frame_callback, &frame_listener, surface); wl_proxy_set_queue((struct wl_proxy *) surface->frame_callback, display->queue); if (surface->type == WL_WINDOW_SURFACE) { resource_surface_swap_buffers(surface->rsurf, NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE); wayland_buffers_swap(surface->buffer, WL_BUFFER_FRONT, WL_BUFFER_BACK); if (surface->buffer[WL_BUFFER_FRONT] == NULL) surface->buffer[WL_BUFFER_FRONT] = display->create_buffer(display, surface, NATIVE_ATTACHMENT_FRONT_LEFT); wl_surface_attach(surface->win->surface, surface->buffer[WL_BUFFER_FRONT], surface->dx, surface->dy); resource_surface_get_size(surface->rsurf, (uint *) &surface->win->attached_width, (uint *) &surface->win->attached_height); surface->dx = 0; surface->dy = 0; } surface->sequence_number++; wayland_event_handler->invalid_surface(&display->base, &surface->base, surface->sequence_number); return TRUE; }
static gint gst_wl_display_roundtrip (GstWlDisplay * self) { struct wl_callback *callback; gint ret = 0; gboolean done = FALSE; g_return_val_if_fail (self != NULL, -1); /* We don't own the display, process only our queue */ callback = wl_display_sync (self->display); wl_callback_add_listener (callback, &sync_listener, &done); wl_proxy_set_queue ((struct wl_proxy *) callback, self->queue); while (ret != -1 && !done) ret = wl_display_dispatch_queue (self->display, self->queue); wl_callback_destroy (callback); return ret; }
void WaylandNativeWindow::destroyBuffer(WaylandNativeWindowBuffer* wnb) { TRACE("wnb:%p", wnb); assert(wnb != NULL); int ret = 0; while (ret != -1 && wnb->creation_callback) ret = wl_display_dispatch_queue(m_display, wl_queue); if (wnb->creation_callback) { wl_callback_destroy(wnb->creation_callback); wnb->creation_callback = NULL; } if (wnb->wlbuffer) wl_buffer_destroy(wnb->wlbuffer); wnb->wlbuffer = NULL; wnb->common.decRef(&wnb->common); m_freeBufs--; }
/* Test that when receiving the first of two synchronization * callback events, destroying the second one doesn't cause any * errors even if the delete_id event is handled out of order. */ static int client_test_multiple_queues(void) { struct wl_event_queue *queue; struct wl_callback *callback1; struct multiple_queues_state state; int ret = 0; state.display = wl_display_connect(SOCKET_NAME); client_assert(state.display); /* Make the current thread the display thread. This is because * wl_display_dispatch_queue() will only read the display fd if * the main display thread has been set. */ wl_display_dispatch_pending(state.display); queue = wl_display_create_queue(state.display); client_assert(queue); state.done = false; callback1 = wl_display_sync(state.display); wl_callback_add_listener(callback1, &sync_listener, &state); wl_proxy_set_queue((struct wl_proxy *) callback1, queue); state.callback2 = wl_display_sync(state.display); wl_callback_add_listener(state.callback2, &sync_listener, NULL); wl_proxy_set_queue((struct wl_proxy *) state.callback2, queue); wl_display_flush(state.display); while (!state.done && !ret) ret = wl_display_dispatch_queue(state.display, queue); wl_display_disconnect(state.display); return ret == -1 ? -1 : 0; }
int DispatchQueue(struct wl_event_queue *queue){ return wl_display_dispatch_queue(cobj, queue); }
/* Swap the contents of a drawable to the screen */ static WSEGLError wseglSwapDrawable (WSEGLDrawableHandle _drawable, unsigned long data) { struct wl_egl_window *drawable = (struct wl_egl_window *) _drawable; struct wl_callback *callback; if (drawable->numFlipBuffers) { // wsegl_info("PRESENT FLIP"); PVR2DPresentFlip(drawable->display->context, drawable->flipChain, drawable->backBuffers[drawable->currentBackBuffer], 0); } else if (drawable->display->display) { //wsegl_info("wseglSwapDrawable for wayland, %d %p", drawable->currentBackBuffer, drawable->drmbuffers[drawable->currentBackBuffer]); int ret = 0; while (drawable->display->frame_callback && ret != -1) ret = wl_display_dispatch_queue(drawable->display->display, drawable->display->queue); drawable->display->frame_callback = wl_surface_frame(drawable->surface); wl_callback_add_listener(drawable->display->frame_callback, &frame_listener, drawable); wl_proxy_set_queue((struct wl_proxy *)drawable->display->frame_callback, drawable->display->queue); if (!drawable->drmbuffers[drawable->currentBackBuffer]) { int32_t handle; struct wl_resource *wlbuf; handle = drawable->exporthandles[drawable->currentBackBuffer]; wlbuf = sgx_wlegl_create_buffer(drawable->display->sgx_wlegl, drawable->width, drawable->height, drawable->strideBytes, drawable->format, handle); drawable->drmbuffers[drawable->currentBackBuffer] = wlbuf; wsegl_info("sgx_wlegl_create_buffer for %d", drawable->currentBackBuffer); wsegl_info("Add listener for %p with %p (buf %d) inside", drawable, wlbuf, drawable->currentBackBuffer); // TODO: listen for release wl_proxy_set_queue((struct wl_proxy *)wlbuf, drawable->display->queue); } struct wl_resource *wlbuf = drawable->drmbuffers[drawable->currentBackBuffer]; wl_surface_attach(drawable->surface, wlbuf, 0, 0); wl_surface_damage(drawable->surface, 0, 0, drawable->width, drawable->height); wl_surface_commit(drawable->surface); } else { PVR2DBLTINFO blit; memset(&blit, 0, sizeof(blit)); blit.CopyCode = PVR2DROPcopy; blit.BlitFlags = PVR2D_BLIT_DISABLE_ALL; blit.pSrcMemInfo = drawable->backBuffers[drawable->currentBackBuffer]; blit.SrcStride = drawable->strideBytes; blit.SrcX = 0; blit.SrcY = 0; blit.SizeX = drawable->width; blit.SizeY = drawable->height; blit.SrcFormat = wsegl2pvr2dformat(drawable->format); blit.pDstMemInfo = drawable->frontBufferPVRMEM; blit.DstStride = drawable->strideBytes; blit.DstX = 0; blit.DstY = 0; blit.DSizeX = drawable->width; blit.DSizeY = drawable->height; blit.DstFormat = wsegl2pvr2dformat(drawable->format); PVR2DBlt(drawable->display->context, &blit); PVR2DQueryBlitsComplete (drawable->display->context, drawable->frontBufferPVRMEM, 1); assert (drawable->display->fd >= 0); struct omapfb_update_window update_window; update_window.x = update_window.out_x = 0; update_window.y = update_window.out_y = 0; update_window.width = update_window.out_width = drawable->width; update_window.height = update_window.out_height = drawable->height; update_window.format = 0; assert(ioctl(drawable->display->fd, OMAPFB_UPDATE_WINDOW, &update_window) == 0); } drawable->currentBackBuffer = (drawable->currentBackBuffer + 1) % WAYLANDWSEGL_MAX_BACK_BUFFERS; return WSEGL_SUCCESS; }
/** Process incoming events * * \param display The display context object * \return The number of dispatched events on success or -1 on failure * * Dispatch the display's main event queue. * * If the main event queue is empty, this function blocks until there are * events to be read from the display fd. Events are read and queued on * the appropriate event queues. Finally, events on the main event queue * are dispatched. * * \note It is not possible to check if there are events on the main queue * or not. For dispatching main queue events without blocking, see \ref * wl_display_dispatch_pending(). * * \note Calling this will release the display file descriptor if this * thread acquired it using wl_display_acquire_fd(). * * \sa wl_display_dispatch_pending(), wl_display_dispatch_queue() * * \memberof wl_display */ WL_EXPORT int wl_display_dispatch(struct wl_display *display) { return wl_display_dispatch_queue(display, &display->queue); }
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; }
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; }