void WaylandNativeWindowBuffer::wlbuffer_from_native_handle(struct android_wlegl *android_wlegl, struct wl_display *display, struct wl_event_queue *queue) { struct wl_array ints; int *ints_data; struct android_wlegl_handle *wlegl_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(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]); } wlbuffer = android_wlegl_create_buffer(android_wlegl, width, height, stride, format, usage, wlegl_handle); wl_proxy_set_queue((struct wl_proxy *) wlbuffer, queue); android_wlegl_handle_destroy(wlegl_handle); creation_callback = wl_display_sync(display); wl_callback_add_listener(creation_callback, &buffer_create_sync_listener, &creation_callback); wl_proxy_set_queue((struct wl_proxy *)creation_callback, queue); }
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 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 gboolean gst_vaapi_window_wayland_create (GstVaapiWindow * window, guint * width, guint * height) { GstVaapiWindowWaylandPrivate *const priv = GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window); GstVaapiDisplayWaylandPrivate *const priv_display = GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (GST_VAAPI_OBJECT_DISPLAY (window)); GST_DEBUG ("create window, size %ux%u", *width, *height); g_return_val_if_fail (priv_display->compositor != NULL, FALSE); g_return_val_if_fail (priv_display->shell != NULL, FALSE); GST_VAAPI_OBJECT_LOCK_DISPLAY (window); priv->event_queue = wl_display_create_queue (priv_display->wl_display); GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window); if (!priv->event_queue) return FALSE; GST_VAAPI_OBJECT_LOCK_DISPLAY (window); priv->surface = wl_compositor_create_surface (priv_display->compositor); GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window); if (!priv->surface) return FALSE; wl_proxy_set_queue ((struct wl_proxy *) priv->surface, priv->event_queue); GST_VAAPI_OBJECT_LOCK_DISPLAY (window); priv->shell_surface = wl_shell_get_shell_surface (priv_display->shell, priv->surface); GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window); if (!priv->shell_surface) return FALSE; wl_proxy_set_queue ((struct wl_proxy *) priv->shell_surface, priv->event_queue); wl_shell_surface_add_listener (priv->shell_surface, &shell_surface_listener, priv); wl_shell_surface_set_toplevel (priv->shell_surface); priv->poll = gst_poll_new (TRUE); gst_poll_fd_init (&priv->pollfd); if (priv->fullscreen_on_show) gst_vaapi_window_wayland_set_fullscreen (window, TRUE); priv->surface_format = GST_VIDEO_FORMAT_ENCODED; priv->use_vpp = GST_VAAPI_DISPLAY_HAS_VPP (GST_VAAPI_OBJECT_DISPLAY (window)); priv->is_shown = TRUE; return TRUE; }
WaylandNativeWindow::WaylandNativeWindow(struct wl_egl_window *window, struct wl_display *display, const gralloc_module_t* gralloc, alloc_device_t* alloc_device) { int wayland_ok; HYBRIS_TRACE_BEGIN("wayland-platform", "create_window", ""); this->m_window = window; this->m_window->nativewindow = (void *) this; this->m_display = display; this->m_width = window->width; this->m_height = window->height; this->m_defaultWidth = window->width; this->m_defaultHeight = window->height; this->m_window->resize_callback = resize_callback; this->m_format = 1; this->wl_queue = wl_display_create_queue(display); this->frame_callback = NULL; this->registry = wl_display_get_registry(display); wl_proxy_set_queue((struct wl_proxy *) this->registry, this->wl_queue); wl_registry_add_listener(this->registry, ®istry_listener, this); wayland_ok = wayland_roundtrip(this); assert(wayland_ok >= 0); assert(this->m_android_wlegl != NULL); this->m_gralloc = gralloc; this->m_alloc = alloc_device; m_usage=GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); m_freeBufs = 0; setBufferCount(3); HYBRIS_TRACE_END("wayland-platform", "create_window", ""); }
WaylandNativeWindow::WaylandNativeWindow(struct wl_egl_window *window, struct wl_display *display, const gralloc_module_t* gralloc, alloc_device_t* alloc_device) { int i; this->m_window = window; this->m_display = display; this->m_width = window->width; this->m_height = window->height; this->m_defaultWidth = window->width; this->m_defaultHeight = window->height; this->m_format = 1; this->wl_queue = wl_display_create_queue(display); this->frame_callback = NULL; this->registry = wl_display_get_registry(display); wl_proxy_set_queue((struct wl_proxy *) this->registry, this->wl_queue); wl_registry_add_listener(this->registry, ®istry_listener, this); assert(wayland_roundtrip(this) >= 0); assert(this->m_android_wlegl != NULL); this->m_gralloc = gralloc; this->m_alloc = alloc_device; m_usage=GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; pthread_mutex_init(&mutex, NULL); TRACE("WaylandNativeWindow created in %p", pthread_self()); }
extern "C" _EGLDisplay *waylandws_GetDisplay(EGLNativeDisplayType display) { WaylandDisplay *wdpy = new WaylandDisplay; wdpy->wl_dpy = (wl_display *)display; wdpy->wlegl = NULL; wdpy->queue = wl_display_create_queue(wdpy->wl_dpy); wdpy->registry = wl_display_get_registry(wdpy->wl_dpy); wl_proxy_set_queue((wl_proxy *) wdpy->registry, wdpy->queue); wl_registry_add_listener(wdpy->registry, ®istry_listener, wdpy); wl_callback *cb = wl_display_sync(wdpy->wl_dpy); wl_proxy_set_queue((wl_proxy *) cb, wdpy->queue); wl_callback_add_listener(cb, &callback_listener, wdpy); return &wdpy->base; }
static GstWlWindow * gst_wl_window_new_internal (GstWlDisplay * display, GMutex * render_lock) { GstWlWindow *window; struct wl_region *region; window = g_object_new (GST_TYPE_WL_WINDOW, NULL); window->display = g_object_ref (display); window->render_lock = render_lock; window->area_surface = wl_compositor_create_surface (display->compositor); window->video_surface = wl_compositor_create_surface (display->compositor); window->area_surface_wrapper = wl_proxy_create_wrapper (window->area_surface); window->video_surface_wrapper = wl_proxy_create_wrapper (window->video_surface); wl_proxy_set_queue ((struct wl_proxy *) window->area_surface_wrapper, display->queue); wl_proxy_set_queue ((struct wl_proxy *) window->video_surface_wrapper, display->queue); /* embed video_surface in area_surface */ window->video_subsurface = wl_subcompositor_get_subsurface (display->subcompositor, window->video_surface, window->area_surface); wl_subsurface_set_desync (window->video_subsurface); if (display->viewporter) { window->area_viewport = wp_viewporter_get_viewport (display->viewporter, window->area_surface); window->video_viewport = wp_viewporter_get_viewport (display->viewporter, window->video_surface); } /* do not accept input */ region = wl_compositor_create_region (display->compositor); wl_surface_set_input_region (window->area_surface, region); wl_region_destroy (region); region = wl_compositor_create_region (display->compositor); wl_surface_set_input_region (window->video_surface, region); wl_region_destroy (region); return window; }
GstWlDisplay * gst_wl_display_new_existing (struct wl_display * display, gboolean take_ownership, GError ** error) { GstWlDisplay *self; GError *err = NULL; gint i; g_return_val_if_fail (display != NULL, NULL); self = g_object_new (GST_TYPE_WL_DISPLAY, NULL); self->display = display; self->own_display = take_ownership; self->queue = wl_display_create_queue (self->display); self->registry = wl_display_get_registry (self->display); wl_proxy_set_queue ((struct wl_proxy *) self->registry, self->queue); wl_registry_add_listener (self->registry, ®istry_listener, self); /* we need exactly 2 roundtrips to discover global objects and their state */ for (i = 0; i < 2; i++) { if (gst_wl_display_roundtrip (self) < 0) { *error = g_error_new (g_quark_from_static_string ("GstWlDisplay"), 0, "Error communicating with the wayland display"); g_object_unref (self); return NULL; } } /* verify we got all the required interfaces */ #define VERIFY_INTERFACE_EXISTS(var, interface) \ if (!self->var) { \ g_set_error (error, g_quark_from_static_string ("GstWlDisplay"), 0, \ "Could not bind to " interface ". Either it is not implemented in " \ "the compositor, or the implemented version doesn't match"); \ g_object_unref (self); \ return NULL; \ } VERIFY_INTERFACE_EXISTS (compositor, "wl_compositor"); VERIFY_INTERFACE_EXISTS (subcompositor, "wl_subcompositor"); VERIFY_INTERFACE_EXISTS (shell, "wl_shell"); VERIFY_INTERFACE_EXISTS (shm, "wl_shm"); VERIFY_INTERFACE_EXISTS (scaler, "wl_scaler"); #undef VERIFY_INTERFACE_EXISTS self->thread = g_thread_try_new ("GstWlDisplay", gst_wl_display_thread_run, self, &err); if (err) { g_propagate_prefixed_error (error, err, "Failed to start thread for the display's events"); g_object_unref (self); return NULL; } return self; }
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; }
QWaylandDisplay::QWaylandDisplay() : mLastKeyboardFocusInputDevice(0) , mDndSelectionHandler(0) , mWindowExtension(0) , mSubSurfaceExtension(0) , mOutputExtension(0) , mTouchExtension(0) , mQtKeyExtension(0) { display = this; qRegisterMetaType<uint32_t>("uint32_t"); mEventThreadObject = new QWaylandEventThread(0); mEventThread = new QThread(this); mEventThreadObject->moveToThread(mEventThread); mEventThread->start(); mEventThreadObject->displayConnect(); mDisplay = mEventThreadObject->display(); //blocks until display is available //Create a new even queue for the QtGui thread mEventQueue = wl_display_create_queue(mDisplay); struct ::wl_registry *registry = wl_display_get_registry(mDisplay); wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue); init(registry); QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(flushRequests())); connect(mEventThreadObject, SIGNAL(newEventsRead()), this, SLOT(flushRequests())); #ifdef QT_WAYLAND_GL_SUPPORT mEglIntegration = QWaylandGLIntegration::createGLIntegration(this); #endif mWindowManagerIntegration = new QWaylandWindowManagerIntegration(this); blockingReadEvents(); #ifdef QT_WAYLAND_GL_SUPPORT mEglIntegration->initialize(); flushRequests(); while (mEglIntegration->waitingForEvents()) blockingReadEvents(); #endif waitForScreens(); }
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; }
/* 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 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; }
ServerWaylandBuffer::ServerWaylandBuffer(unsigned int w, unsigned int h, int f, int u, gralloc_module_t *gralloc, android_wlegl *android_wlegl, struct wl_event_queue *queue) : WaylandNativeWindowBuffer() , m_buf(0) { ANativeWindowBuffer::width = w; ANativeWindowBuffer::height = h; m_gralloc = gralloc; usage = u; wl_array_init(&ints); wl_array_init(&fds); android_wlegl_server_buffer_handle *ssb = android_wlegl_get_server_buffer_handle(android_wlegl, width, height, f, u); wl_proxy_set_queue((struct wl_proxy *) ssb, queue); android_wlegl_server_buffer_handle_add_listener(ssb, &server_handle_listener, this); }
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; }
WaylandNativeWindow::WaylandNativeWindow(struct wl_egl_window *window, struct wl_display *display, alloc_device_t* alloc_device) : m_android_wlegl(NULL) { int wayland_ok; HYBRIS_TRACE_BEGIN("wayland-platform", "create_window", ""); this->m_window = window; this->m_window->nativewindow = (void *) this; this->m_display = display; this->m_width = window->width; this->m_height = window->height; this->m_defaultWidth = window->width; this->m_defaultHeight = window->height; this->m_window->resize_callback = resize_callback; this->m_window->free_callback = free_callback; this->m_format = 1; this->frame_callback = NULL; this->wl_queue = wl_display_create_queue(display); this->registry = wl_display_get_registry(display); this->m_android_wlegl = NULL; wl_proxy_set_queue((struct wl_proxy *) this->registry, this->wl_queue); wl_registry_add_listener(this->registry, ®istry_listener, this); const_cast<int&>(ANativeWindow::minSwapInterval) = 0; const_cast<int&>(ANativeWindow::maxSwapInterval) = 1; // This is the default as per the EGL documentation this->m_swap_interval = 1; wayland_ok = wayland_roundtrip(this); assert(wayland_ok >= 0); assert(this->m_android_wlegl != NULL); this->m_alloc = alloc_device; m_usage=GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); m_queueReads = 0; m_freeBufs = 0; m_damage_rects = NULL; m_damage_n_rects = 0; m_lastBuffer = 0; setBufferCount(3); HYBRIS_TRACE_END("wayland-platform", "create_window", ""); }
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; }
static void wayland_window_surface_handle_resize(struct wayland_surface *surface) { struct wayland_display *display = surface->display; struct pipe_resource *front_resource; const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT; int i; front_resource = resource_surface_get_single_resource(surface->rsurf, front_natt); if (resource_surface_set_size(surface->rsurf, surface->win->width, surface->win->height)) { if (surface->pending_resource) wayland_roundtrip(display); if (front_resource) { struct wl_callback *callback; surface->pending_resource = front_resource; front_resource = NULL; callback = wl_display_sync(display->dpy); wl_callback_add_listener(callback, &release_buffer_listener, surface); wl_proxy_set_queue((struct wl_proxy *) callback, display->queue); } for (i = 0; i < WL_BUFFER_COUNT; ++i) { if (surface->buffer[i]) wl_buffer_destroy(surface->buffer[i]); surface->buffer[i] = NULL; } surface->dx = surface->win->dx; surface->dy = surface->win->dy; } pipe_resource_reference(&front_resource, NULL); }
static GstWlWindow * gst_wl_window_new_internal (GstWlDisplay * display, struct wl_surface *surface) { GstWlWindow *window; struct wl_region *region; g_return_val_if_fail (surface != NULL, NULL); window = g_object_new (GST_TYPE_WL_WINDOW, NULL); window->display = g_object_ref (display); window->surface = surface; /* make sure the surface runs on our local queue */ wl_proxy_set_queue ((struct wl_proxy *) surface, display->queue); window->viewport = wl_scaler_get_viewport (display->scaler, window->surface); /* do not accept input */ region = wl_compositor_create_region (display->compositor); wl_surface_set_input_region (surface, region); wl_region_destroy (region); return window; }
static gboolean gst_mfx_window_wayland_create (GstMfxWindow * window, guint * width, guint * height) { GstMfxWindowWaylandPrivate *const priv = GST_MFX_WINDOW_WAYLAND_GET_PRIVATE (window); GstMfxDisplayWaylandPrivate *const priv_display = GST_MFX_DISPLAY_WAYLAND_GET_PRIVATE (GST_MFX_WINDOW_DISPLAY (window)); struct wl_display *const wl_display = GST_MFX_DISPLAY_HANDLE (GST_MFX_WINDOW_DISPLAY (window)); GError *err = NULL; GST_DEBUG ("create window, size %ux%u", *width, *height); g_return_val_if_fail (priv_display->compositor != NULL, FALSE); g_return_val_if_fail (priv_display->shell != NULL, FALSE); GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window)); priv->event_queue = wl_display_create_queue (wl_display); GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window)); if (!priv->event_queue) return FALSE; GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window)); priv->surface = wl_compositor_create_surface (priv_display->compositor); GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window)); if (!priv->surface) return FALSE; wl_proxy_set_queue ((struct wl_proxy *) priv->surface, priv->event_queue); GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window)); priv->shell_surface = wl_shell_get_shell_surface (priv_display->shell, priv->surface); GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window)); if (!priv->shell_surface) return FALSE; wl_proxy_set_queue ((struct wl_proxy *) priv->shell_surface, priv->event_queue); wl_shell_surface_add_listener (priv->shell_surface, &shell_surface_listener, window); wl_shell_surface_set_toplevel (priv->shell_surface); #ifdef USE_WESTON_4_0 if (priv_display->viewporter) { GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window)); priv->wp_viewport = wp_viewporter_get_viewport (priv_display->viewporter, priv->surface); GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window)); } #else if (priv_display->scaler) { GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window)); priv->viewport = wl_scaler_get_viewport (priv_display->scaler, priv->surface); GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window)); } #endif priv->poll = gst_poll_new (TRUE); gst_poll_fd_init (&priv->pollfd); if (priv->fullscreen_on_show) gst_mfx_window_wayland_set_fullscreen (window, TRUE); #ifdef USE_EGL if (gst_mfx_display_has_opengl (GST_MFX_WINDOW_DISPLAY (window))) { priv->egl_window = wl_egl_window_create (priv->surface, *width, *height); if (!priv->egl_window) return FALSE; GST_MFX_WINDOW_ID (window) = GPOINTER_TO_INT(priv->egl_window); } #endif priv->thread = g_thread_try_new ("wayland-thread", gst_mfx_window_wayland_thread_run, window, &err); if (err) return FALSE; priv->is_shown = TRUE; 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; } }
static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg, video_format_t *fmtp, vlc_video_context *context) { if (cfg->window->type != VOUT_WINDOW_TYPE_WAYLAND) return VLC_EGENERIC; vout_display_sys_t *sys = malloc(sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; vd->sys = sys; sys->embed = NULL; sys->eventq = NULL; sys->shm = NULL; sys->viewporter = NULL; sys->active_buffers = 0; sys->display_width = cfg->display.width; sys->display_height = cfg->display.height; sys->use_buffer_transform = false; /* Get window */ sys->embed = cfg->window; assert(sys->embed != NULL); struct wl_display *display = sys->embed->display.wl; sys->eventq = wl_display_create_queue(display); if (sys->eventq == NULL) goto error; struct wl_registry *registry = wl_display_get_registry(display); if (registry == NULL) goto error; wl_proxy_set_queue((struct wl_proxy *)registry, sys->eventq); wl_registry_add_listener(registry, ®istry_cbs, vd); wl_display_roundtrip_queue(display, sys->eventq); wl_registry_destroy(registry); if (sys->shm == NULL) goto error; wl_shm_add_listener(sys->shm, &shm_cbs, vd); wl_display_roundtrip_queue(display, sys->eventq); struct wl_surface *surface = sys->embed->handle.wl; if (sys->viewporter != NULL) sys->viewport = wp_viewporter_get_viewport(sys->viewporter, surface); else sys->viewport = NULL; /* Determine our pixel format */ static const enum wl_output_transform transforms[8] = { [ORIENT_TOP_LEFT] = WL_OUTPUT_TRANSFORM_NORMAL, [ORIENT_TOP_RIGHT] = WL_OUTPUT_TRANSFORM_FLIPPED, [ORIENT_BOTTOM_LEFT] = WL_OUTPUT_TRANSFORM_FLIPPED_180, [ORIENT_BOTTOM_RIGHT] = WL_OUTPUT_TRANSFORM_180, [ORIENT_LEFT_TOP] = WL_OUTPUT_TRANSFORM_FLIPPED_270, [ORIENT_LEFT_BOTTOM] = WL_OUTPUT_TRANSFORM_90, [ORIENT_RIGHT_TOP] = WL_OUTPUT_TRANSFORM_270, [ORIENT_RIGHT_BOTTOM] = WL_OUTPUT_TRANSFORM_FLIPPED_90, };
static void create_surfaces (GstGLWindowWaylandEGL * window_egl) { GstGLDisplayWayland *display = GST_GL_DISPLAY_WAYLAND (GST_GL_WINDOW (window_egl)->display); gint width, height; if (!window_egl->window.surface) { window_egl->window.surface = wl_compositor_create_surface (display->compositor); if (window_egl->window.queue) wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.surface, window_egl->window.queue); } if (window_egl->window.foreign_surface) { /* (re)parent */ if (!display->subcompositor) { GST_ERROR_OBJECT (window_egl, "Wayland server does not support subsurfaces"); window_egl->window.foreign_surface = NULL; goto shell_window; } if (!window_egl->window.subsurface) { window_egl->window.subsurface = wl_subcompositor_get_subsurface (display->subcompositor, window_egl->window.surface, window_egl->window.foreign_surface); if (window_egl->window.queue) wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.subsurface, window_egl->window.queue); wl_subsurface_set_position (window_egl->window.subsurface, window_egl->window.window_x, window_egl->window.window_y); wl_subsurface_set_desync (window_egl->window.subsurface); } } else { shell_window: if (!window_egl->window.shell_surface) { window_egl->window.shell_surface = wl_shell_get_shell_surface (display->shell, window_egl->window.surface); if (window_egl->window.queue) wl_proxy_set_queue ((struct wl_proxy *) window_egl->window. shell_surface, window_egl->window.queue); wl_shell_surface_add_listener (window_egl->window.shell_surface, &shell_surface_listener, window_egl); wl_shell_surface_set_title (window_egl->window.shell_surface, "OpenGL Renderer"); wl_shell_surface_set_toplevel (window_egl->window.shell_surface); } } if (window_egl->window.window_width > 0) width = window_egl->window.window_width; else width = 320; window_egl->window.window_width = width; if (window_egl->window.window_height > 0) height = window_egl->window.window_height; else height = 240; window_egl->window.window_height = height; if (!window_egl->window.native) { gst_gl_window_resize (GST_GL_WINDOW (window_egl), width, height); window_egl->window.native = wl_egl_window_create (window_egl->window.surface, width, height); if (window_egl->window.queue) wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.native, window_egl->window.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; }
GstWlDisplay * gst_wl_display_new_existing (struct wl_display * display, gboolean take_ownership, GError ** error) { GstWlDisplay *self; GError *err = NULL; gint i; g_return_val_if_fail (display != NULL, NULL); self = g_object_new (GST_TYPE_WL_DISPLAY, NULL); self->display = display; self->own_display = take_ownership; self->queue = wl_display_create_queue (self->display); self->registry = wl_display_get_registry (self->display); wl_proxy_set_queue ((struct wl_proxy *) self->registry, self->queue); wl_registry_add_listener (self->registry, ®istry_listener, self); /* we need exactly 2 roundtrips to discover global objects and their state */ for (i = 0; i < 2; i++) { if (gst_wl_display_roundtrip (self) < 0) { *error = g_error_new (g_quark_from_static_string ("GstWlDisplay"), 0, "Error communicating with the wayland display"); g_object_unref (self); return NULL; } } /* verify we got all the required interfaces */ #define VERIFY_INTERFACE_EXISTS(var, interface) \ if (!self->var) { \ g_set_error (error, g_quark_from_static_string ("GstWlDisplay"), 0, \ "Could not bind to " interface ". Either it is not implemented in " \ "the compositor, or the implemented version doesn't match"); \ g_object_unref (self); \ return NULL; \ } VERIFY_INTERFACE_EXISTS (compositor, "wl_compositor"); VERIFY_INTERFACE_EXISTS (subcompositor, "wl_subcompositor"); VERIFY_INTERFACE_EXISTS (shell, "wl_shell"); VERIFY_INTERFACE_EXISTS (shm, "wl_shm"); #undef VERIFY_INTERFACE_EXISTS /* We make the viewporter optional even though it may cause bad display. * This is so one can test wayland display on older compositor or on * compositor that don't implement this extension. */ if (!self->viewporter) { g_warning ("Wayland compositor is missing the ability to scale, video " "display may not work properly."); } if (!self->dmabuf) { g_warning ("Could not bind to zwp_linux_dmabuf_v1"); } self->thread = g_thread_try_new ("GstWlDisplay", gst_wl_display_thread_run, self, &err); if (err) { g_propagate_prefixed_error (error, err, "Failed to start thread for the display's events"); g_object_unref (self); return NULL; } return self; }
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; }
/* 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; }
/* Initialize a native display for use with WSEGL */ static WSEGLError wseglInitializeDisplay (NativeDisplayType nativeDisplay, WSEGLDisplayHandle *display, const WSEGLCaps **caps, WSEGLConfig **configs) { struct wl_egl_display *egldisplay = wl_egl_display_create((struct wl_display *) nativeDisplay); if (wseglFetchContext(egldisplay) != 1) { wl_egl_display_destroy(egldisplay); return WSEGL_OUT_OF_MEMORY; } /* If it is a framebuffer */ if (egldisplay->display == NULL) { wsegl_info("wayland-wsegl: Initializing framebuffer"); int fd; WSEGLPixelFormat format; /* Open the framebuffer and fetch its properties */ fd = open("/dev/fb0", O_RDWR, 0); if (fd < 0) { perror("/dev/fb0"); wseglReleaseContext(egldisplay); wl_egl_display_destroy(egldisplay); return WSEGL_CANNOT_INITIALISE; } if (ioctl(fd, FBIOGET_VSCREENINFO, &egldisplay->var) < 0) { perror("FBIOGET_VSCREENINFO"); wseglReleaseContext(egldisplay); wl_egl_display_destroy(egldisplay); close(fd); return WSEGL_CANNOT_INITIALISE; } if (ioctl(fd, FBIOGET_FSCREENINFO, &egldisplay->fix) < 0) { perror("FBIOGET_FSCREENINFO"); wseglReleaseContext(egldisplay); wl_egl_display_destroy(egldisplay); close(fd); return WSEGL_CANNOT_INITIALISE; } egldisplay->fd = fd; format = getwseglPixelFormat(egldisplay); egldisplay->wseglDisplayConfigs[0].ePixelFormat = format; egldisplay->wseglDisplayConfigs[1].ePixelFormat = format; } else { egldisplay->queue = wl_display_create_queue(nativeDisplay); egldisplay->frame_callback = NULL; egldisplay->registry = wl_display_get_registry(nativeDisplay); wl_proxy_set_queue(egldisplay->registry, egldisplay->queue); wl_registry_add_listener(egldisplay->registry, ®istry_listener, egldisplay); assert(wayland_roundtrip(egldisplay) >= 0); assert(egldisplay->sgx_wlegl); } *display = (WSEGLDisplayHandle)egldisplay; *caps = wseglDisplayCaps; *configs = egldisplay->wseglDisplayConfigs; return WSEGL_SUCCESS; }