static int init_drm(struct display *d) { EGLint major, minor; int fd; drm_magic_t magic; fd = open(d->device_name, O_RDWR); if (fd < 0) { fprintf(stderr, "drm open failed: %m\n"); return -1; } if (drmGetMagic(fd, &magic)) { fprintf(stderr, "DRI2: failed to get drm magic"); return -1; } /* Wait for authenticated event */ wl_drm_authenticate(d->drm, magic); wl_display_iterate(d->display, WL_DISPLAY_WRITABLE); while (!d->authenticated) wl_display_iterate(d->display, WL_DISPLAY_READABLE); d->dpy = eglGetDRMDisplayMESA(fd); if (!eglInitialize(d->dpy, &major, &minor)) { fprintf(stderr, "failed to initialize display\n"); return -1; } if (!eglBindAPI(EGL_OPENGL_API)) { fprintf(stderr, "failed to bind api EGL_OPENGL_API\n"); return -1; } d->ctx = eglCreateContext(d->dpy, NULL, EGL_NO_CONTEXT, NULL); if (d->ctx == NULL) { fprintf(stderr, "failed to create context\n"); return -1; } if (!eglMakeCurrent(d->dpy, NULL, NULL, d->ctx)) { fprintf(stderr, "faile to make context current\n"); return -1; } #ifdef HAVE_CAIRO_EGL d->device = cairo_egl_device_create(d->dpy, d->ctx); if (d->device == NULL) { fprintf(stderr, "failed to get cairo drm device\n"); return -1; } #endif return 0; }
int main(int argc, char **argv) { struct sigaction sigint; struct display display = { 0 }; struct window window = { 0 }; window.display = &display; window.geometry.width = 250; window.geometry.height = 250; display.display = wl_display_connect(NULL); assert(display.display); wl_display_add_global_listener(display.display, display_handle_global, &display); wl_display_get_fd(display.display, event_mask_update, &display); wl_display_iterate(display.display, WL_DISPLAY_READABLE); init_egl(&display); create_surface(&window); init_gl(&window); sigint.sa_handler = signal_int; sigemptyset(&sigint.sa_mask); sigint.sa_flags = SA_RESETHAND; sigaction(SIGINT, &sigint, NULL); redraw(&window, NULL, 0); while (running) wl_display_iterate(display.display, display.mask); fprintf(stderr, "simple-egl exiting\n"); destroy_surface(&window); fini_egl(&display); if (display.shell) wl_shell_destroy(display.shell); if (display.compositor) wl_compositor_destroy(display.compositor); wl_display_flush(display.display); wl_display_disconnect(display.display); return 0; }
static void gdk_wayland_display_sync (GdkDisplay *display) { GdkDisplayWayland *display_wayland; gboolean done; g_return_if_fail (GDK_IS_DISPLAY (display)); display_wayland = GDK_DISPLAY_WAYLAND (display); wl_display_sync_callback(display_wayland->wl_display, sync_callback, &done); wl_display_iterate(display_wayland->wl_display, WL_DISPLAY_WRITABLE); while (!done) wl_display_iterate(display_wayland->wl_display, WL_DISPLAY_READABLE); }
int main(int argc, char **argv) { struct sigaction sigint; struct display *display; struct window *window; display = create_display(); window = create_window(display, 250, 250); if (!window) return 1; sigint.sa_handler = signal_int; sigemptyset(&sigint.sa_mask); sigint.sa_flags = SA_RESETHAND; sigaction(SIGINT, &sigint, NULL); redraw(window, NULL, 0); while (running) wl_display_iterate(display->display, display->mask); fprintf(stderr, "simple-shm exiting\n"); destroy_window(window); destroy_display(display); return 0; }
static gboolean clutter_event_source_wayland_dispatch (GSource *base, GSourceFunc callback, gpointer data) { ClutterEventSourceWayland *source = (ClutterEventSourceWayland *) base; ClutterEvent *event; clutter_threads_enter (); if (source->pfd.revents) { wl_display_iterate (source->display, WL_DISPLAY_READABLE); source->pfd.revents = 0; } event = clutter_event_get (); if (event) { /* forward the event into clutter for emission etc. */ clutter_do_event (event); clutter_event_free (event); } clutter_threads_leave (); 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) { PVR2DPresentFlip(drawable->display->context, drawable->flipChain, drawable->backBuffers[drawable->currentBackBuffer], 0); } else if (drawable->display->display) { while (drawable->block_swap_buffers == 1) wl_display_iterate(drawable->display->display, WL_DISPLAY_READABLE); drawable->block_swap_buffers = 1; callback = wl_display_sync(drawable->display->display); wl_callback_add_listener(callback, &sync_listener, drawable); wl_buffer_damage(drawable->drmbuffers[drawable->currentBackBuffer], 0, 0, drawable->width, drawable->height); wl_surface_attach(drawable->surface, drawable->drmbuffers[drawable->currentBackBuffer], 0, 0); wl_surface_damage(drawable->surface, 0, 0, drawable->width, drawable->height); } 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); } drawable->currentBackBuffer = (drawable->currentBackBuffer + 1) % WAYLANDWSEGL_MAX_BACK_BUFFERS; return WSEGL_SUCCESS; }
void _gdk_wayland_display_flush (GdkDisplay *display, GSource *source) { GdkWaylandEventSource *wayland_source = (GdkWaylandEventSource *) source; while (wayland_source->mask & WL_DISPLAY_WRITABLE) wl_display_iterate(GDK_DISPLAY_WAYLAND (display)->wl_display, WL_DISPLAY_WRITABLE); }
void _gdk_wayland_display_queue_events (GdkDisplay *display) { GdkDisplayWayland *display_wayland; GdkWaylandEventSource *source; display_wayland = GDK_DISPLAY_WAYLAND (display); source = (GdkWaylandEventSource *) display_wayland->event_source; if (source->pfd.revents) { wl_display_iterate(display_wayland->wl_display, WL_DISPLAY_READABLE); source->pfd.revents = 0; } }
static boolean wayland_surface_swap_buffers(struct native_surface *nsurf) { struct wayland_surface *surface = wayland_surface(nsurf); struct wayland_display *display = surface->display; struct wl_callback *callback; while (surface->block_swap_buffers) wl_display_iterate(display->dpy, WL_DISPLAY_READABLE); surface->block_swap_buffers = TRUE; callback = wl_surface_frame(surface->win->surface); wl_callback_add_listener(callback, &frame_listener, surface); 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 gboolean gdk_event_source_prepare(GSource *base, gint *timeout) { GdkWaylandEventSource *source = (GdkWaylandEventSource *) base; GdkDisplayWayland *display = (GdkDisplayWayland *) source->display; *timeout = -1; /* We have to add/remove the GPollFD if we want to update our * poll event mask dynamically. Instead, let's just flush all * write on idle instead, which is what this amounts to. */ if (_gdk_event_queue_find_first (source->display) != NULL) return TRUE; while (source->mask & WL_DISPLAY_WRITABLE) wl_display_iterate(display->wl_display, WL_DISPLAY_WRITABLE); return FALSE; }
void QWaylandDisplay::readEvents() { // verify that there is still data on the socket fd_set fds; FD_ZERO(&fds); FD_SET(mFd, &fds); fd_set nds; FD_ZERO(&nds); fd_set rs = fds; fd_set ws = nds; fd_set es = nds; timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; int ret = ::select(mFd+1, &rs, &ws, &es, &timeout ); if (ret <= 0) { //qDebug("QWaylandDisplay::readEvents() No data... blocking avoided"); return; } wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); }
static struct display * create_display(void) { struct display *display; display = malloc(sizeof *display); display->display = wl_display_connect(NULL); assert(display->display); display->formats = 0; wl_display_add_global_listener(display->display, display_handle_global, display); wl_display_iterate(display->display, WL_DISPLAY_READABLE); wl_display_roundtrip(display->display); if (!(display->formats & (1 << WL_SHM_FORMAT_XRGB8888))) { fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n"); exit(1); } wl_display_get_fd(display->display, event_mask_update, display); return display; }
void QWaylandDisplay::blockingReadEvents() { wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); }
void QWaylandDisplay::flushRequests() { if (mSocketMask & WL_DISPLAY_WRITABLE) wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); }
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(window)->priv; GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(window); struct wl_display * const wl_display = GST_VAAPI_OBJECT_WL_DISPLAY(window); struct wl_buffer *buffer; struct wl_callback *callback; guint width, height, va_flags; VASurfaceID surface_id; VAStatus status; /* XXX: use VPP to support unusual source and destination rectangles */ gst_vaapi_surface_get_size(surface, &width, &height); if (src_rect->x != 0 || src_rect->y != 0 || src_rect->width != width || src_rect->height != height) { GST_ERROR("unsupported source rectangle for rendering"); return FALSE; } if (0 && (dst_rect->width != width || dst_rect->height != height)) { GST_ERROR("unsupported target rectangle for rendering"); return FALSE; } surface_id = GST_VAAPI_OBJECT_ID(surface); if (surface_id == VA_INVALID_ID) return FALSE; GST_VAAPI_OBJECT_LOCK_DISPLAY(window); /* Wait for the previous frame to complete redraw */ if (priv->redraw_pending) wl_display_iterate(wl_display, WL_DISPLAY_READABLE); /* XXX: use VA/VPP for other filters */ va_flags = from_GstVaapiSurfaceRenderFlags(flags); status = vaGetSurfaceBufferWl( GST_VAAPI_DISPLAY_VADISPLAY(display), surface_id, va_flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD), &buffer ); if (status == VA_STATUS_ERROR_FLAG_NOT_SUPPORTED) { /* XXX: de-interlacing flags not supported, try with VPP? */ status = vaGetSurfaceBufferWl( GST_VAAPI_DISPLAY_VADISPLAY(display), surface_id, VA_FRAME_PICTURE, &buffer ); } if (!vaapi_check_status(status, "vaGetSurfaceBufferWl()")) return FALSE; /* XXX: attach to the specified target rectangle */ wl_surface_attach(priv->surface, buffer, 0, 0); wl_surface_damage(priv->surface, 0, 0, width, height); wl_display_iterate(wl_display, WL_DISPLAY_WRITABLE); priv->redraw_pending = TRUE; priv->buffer = buffer; callback = wl_surface_frame(priv->surface); wl_callback_add_listener(callback, &frame_callback_listener, priv); GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window); return TRUE; }
/** * Called via eglSwapBuffers(), drv->API.SwapBuffers(). */ static EGLBoolean dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); struct wl_callback *callback; if (dri2_surf->block_swap_buffers) { wl_display_flush(dri2_dpy->wl_dpy); while (dri2_surf->block_swap_buffers) wl_display_iterate(dri2_dpy->wl_dpy, WL_DISPLAY_READABLE); } dri2_surf->block_swap_buffers = EGL_TRUE; callback = wl_surface_frame(dri2_surf->wl_win->surface); wl_callback_add_listener(callback, &frame_listener, dri2_surf); if (dri2_surf->base.Type == EGL_WINDOW_BIT) { pointer_swap( (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT], (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]); dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]->attachment = __DRI_BUFFER_FRONT_LEFT; dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment = __DRI_BUFFER_BACK_LEFT; swap_wl_buffers(dri2_surf, WL_BUFFER_FRONT, WL_BUFFER_BACK); if (!dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT]) dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT] = wayland_create_buffer(dri2_surf, dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]); wl_buffer_damage(dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], 0, 0, dri2_surf->base.Width, dri2_surf->base.Height); wl_surface_attach(dri2_surf->wl_win->surface, dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], dri2_surf->dx, dri2_surf->dy); dri2_surf->wl_buffer_lock[WL_BUFFER_FRONT] = 1; dri2_surf->wl_win->attached_width = dri2_surf->base.Width; dri2_surf->wl_win->attached_height = dri2_surf->base.Height; /* reset resize growing parameters */ dri2_surf->dx = 0; dri2_surf->dy = 0; wl_surface_damage(dri2_surf->wl_win->surface, 0, 0, dri2_surf->base.Width, dri2_surf->base.Height); } _EGLContext *ctx; if (dri2_drv->glFlush) { ctx = _eglGetCurrentContext(); if (ctx && ctx->DrawSurface == &dri2_surf->base) dri2_drv->glFlush(); } (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); return EGL_TRUE; }
static gboolean clutter_backend_wayland_post_parse (ClutterBackend *backend, GError **error) { ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); EGLBoolean status; g_atexit (clutter_backend_at_exit); /* TODO: expose environment variable/commandline option for this... */ backend_wayland->wayland_display = wl_display_connect (NULL); if (!backend_wayland->wayland_display) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Failed to open Wayland display socket"); return FALSE; } backend_wayland->wayland_source = _clutter_event_source_wayland_new (backend_wayland->wayland_display); g_source_attach (backend_wayland->wayland_source, NULL); /* Set up listener so we'll catch all events. */ wl_display_add_global_listener (backend_wayland->wayland_display, display_handle_global, backend_wayland); /* Process connection events. */ wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); if (!try_get_display(backend_wayland, error)) return FALSE; status = eglInitialize (backend_wayland->edpy, &backend_wayland->egl_version_major, &backend_wayland->egl_version_minor); if (status != EGL_TRUE) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Unable to Initialize EGL"); return FALSE; } CLUTTER_NOTE (BACKEND, "EGL Reports version %i.%i", backend_wayland->egl_version_major, backend_wayland->egl_version_minor); backend_wayland->drm_enabled = try_enable_drm(backend_wayland, error); if (!backend_wayland->drm_enabled) { if (backend_wayland->wayland_shm == NULL) return FALSE; g_debug("Could not enable DRM buffers, falling back to SHM buffers"); g_clear_error(error); } return TRUE; }
struct display * display_create(int *argc, char **argv[], const GOptionEntry *option_entries) { struct display *d; GOptionContext *context; GOptionGroup *xkb_option_group; GError *error; g_type_init(); context = g_option_context_new(NULL); if (option_entries) g_option_context_add_main_entries(context, option_entries, "Wayland View"); xkb_option_group = g_option_group_new("xkb", "Keyboard options", "Show all XKB options", NULL, NULL); g_option_group_add_entries(xkb_option_group, xkb_option_entries); g_option_context_add_group (context, xkb_option_group); if (!g_option_context_parse(context, argc, argv, &error)) { fprintf(stderr, "option parsing failed: %s\n", error->message); exit(EXIT_FAILURE); } d = malloc(sizeof *d); if (d == NULL) return NULL; d->display = wl_display_connect(NULL); if (d->display == NULL) { fprintf(stderr, "failed to create display: %m\n"); return NULL; } wl_list_init(&d->input_list); /* Set up listener so we'll catch all events. */ wl_display_add_global_listener(d->display, display_handle_global, d); /* Process connection events. */ wl_display_iterate(d->display, WL_DISPLAY_READABLE); if (d->device_name && init_drm(d) < 0) return NULL; create_pointer_surfaces(d); display_render_frame(d); d->loop = g_main_loop_new(NULL, FALSE); d->source = wl_glib_source_new(d->display); g_source_attach(d->source, NULL); wl_list_init(&d->window_list); init_xkb(d); return d; }
static gboolean try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error) { drm_magic_t magic; const gchar *exts, *glexts; if (backend_wayland->drm_fd < 0) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Failed to open drm device"); return FALSE; } glexts = glGetString(GL_EXTENSIONS); exts = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS); if (!_cogl_check_extension ("EGL_KHR_image_base", exts) || !_cogl_check_extension ("EGL_MESA_drm_image", exts) || !_cogl_check_extension ("GL_OES_EGL_image", glexts)) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Missing EGL extensions"); return FALSE; } backend_wayland->create_drm_image = (PFNEGLCREATEDRMIMAGEMESA) eglGetProcAddress ("eglCreateDRMImageMESA"); backend_wayland->destroy_image = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR"); backend_wayland->export_drm_image = (PFNEGLEXPORTDRMIMAGEMESA) eglGetProcAddress ("eglExportDRMImageMESA"); backend_wayland->image_target_texture_2d = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES"); if (backend_wayland->create_drm_image == NULL || backend_wayland->destroy_image == NULL || backend_wayland->export_drm_image == NULL || backend_wayland->image_target_texture_2d == NULL) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Missing EGL extensions"); return FALSE; } if (drmGetMagic (backend_wayland->drm_fd, &magic)) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Failed to get drm magic"); return FALSE; } wl_drm_authenticate (backend_wayland->wayland_drm, magic); wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE); while (!backend_wayland->authenticated) wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); return TRUE; };