diff options
Diffstat (limited to 'EGL/x11/yagl_x11_display.c')
-rw-r--r-- | EGL/x11/yagl_x11_display.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/EGL/x11/yagl_x11_display.c b/EGL/x11/yagl_x11_display.c new file mode 100644 index 0000000..6c067f3 --- /dev/null +++ b/EGL/x11/yagl_x11_display.c @@ -0,0 +1,235 @@ +#include "yagl_x11_display.h" +#include "yagl_x11_drawable.h" +#include "yagl_x11_image.h" +#include "yagl_log.h" +#include "yagl_malloc.h" +#include "yagl_dri2.h" +#include <X11/Xutil.h> +#include <X11/extensions/XShm.h> +#include <sys/fcntl.h> +#include <stdio.h> +#include <stdlib.h> + +static int yagl_x11_display_dri2_init(Display *x_dpy) +{ + int ret; + int event_base, error_base; + int dri_major, dri_minor; + char *dri_driver = NULL; + char *dri_device = NULL; + int drm_fd = -1; + drm_magic_t magic; + + YAGL_LOG_FUNC_SET(eglGetDisplay); + + if (!yagl_DRI2QueryExtension(x_dpy, &event_base, &error_base)) { + fprintf(stderr, "Critical error! Failed to DRI2QueryExtension on YaGL display, DRI2 not enabled ?\n"); + goto fail; + } + + YAGL_LOG_TRACE("DRI2QueryExtension returned %d %d", + event_base, error_base); + + if (!yagl_DRI2QueryVersion(x_dpy, &dri_major, &dri_minor)) { + fprintf(stderr, "Critical error! Failed to DRI2QueryVersion on YaGL display, DRI2 not enabled ?\n"); + goto fail; + } + + YAGL_LOG_TRACE("DRI2QueryVersion returned %d %d", + dri_major, dri_minor); + + if (!yagl_DRI2Connect(x_dpy, + RootWindow(x_dpy, DefaultScreen(x_dpy)), + &dri_driver, + &dri_device)) { + fprintf(stderr, "Critical error! Failed to DRI2Connect on YaGL display, DRI2 not enabled ?\n"); + goto fail; + } + + YAGL_LOG_TRACE("DRI2Connect returned %s %s", + dri_driver, dri_device); + + drm_fd = open(dri_device, O_RDWR); + + if (drm_fd < 0) { + fprintf(stderr, "Critical error! Failed to open(\"%s\"): %s\n", dri_device, strerror(errno)); + goto fail; + } + + memset(&magic, 0, sizeof(magic)); + + ret = drmGetMagic(drm_fd, &magic); + + if (ret != 0) { + fprintf(stderr, "Critical error! drmGetMagic failed: %s\n", strerror(-ret)); + goto fail; + } + + if (!yagl_DRI2Authenticate(x_dpy, + RootWindow(x_dpy, DefaultScreen(x_dpy)), + magic)) { + fprintf(stderr, "Critical error! Failed to DRI2Authenticate on YaGL display, DRI2 not enabled ?\n"); + goto fail; + } + + goto out; + +fail: + if (drm_fd >= 0) { + close(drm_fd); + drm_fd = -1; + } +out: + if (dri_driver) { + Xfree(dri_driver); + } + if (dri_device) { + Xfree(dri_device); + } + + return drm_fd; +} + +static struct yagl_native_drawable + *yagl_x11_display_wrap_window(struct yagl_native_display *dpy, + yagl_os_window os_window) +{ + return yagl_x11_drawable_create(dpy, os_window, 0, 0); +} + +static struct yagl_native_drawable + *yagl_x11_display_wrap_pixmap(struct yagl_native_display *dpy, + yagl_os_pixmap os_pixmap) +{ + return yagl_x11_drawable_create(dpy, os_pixmap, 0, 1); +} + +static struct yagl_native_drawable + *yagl_x11_display_create_pixmap(struct yagl_native_display *dpy, + uint32_t width, + uint32_t height, + uint32_t depth) +{ + struct yagl_native_drawable *drawable; + Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy); + Pixmap x_pixmap = XCreatePixmap(x_dpy, + RootWindow(x_dpy, DefaultScreen(x_dpy)), + width, height, depth); + + if (!x_pixmap) { + return NULL; + } + + drawable = yagl_x11_drawable_create(dpy, (yagl_os_pixmap)x_pixmap, 1, 1); + + if (!drawable) { + XFreePixmap(x_dpy, x_pixmap); + return NULL; + } + + return drawable; +} + +static struct yagl_native_image + *yagl_x11_display_create_image(struct yagl_native_display *dpy, + uint32_t width, + uint32_t height, + uint32_t depth) +{ + return yagl_x11_image_create(dpy, width, height, depth); +} + +static int yagl_x11_display_get_visual(struct yagl_native_display *dpy, + int *visual_id, + int *visual_type) +{ + Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy); + int screen; + XVisualInfo vi; + + screen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(x_dpy)); + + /* + * 24-bit is the highest supported by soft framebuffer. + */ + if (!XMatchVisualInfo(x_dpy, screen, 24, TrueColor, &vi)) { + return 0; + } + + *visual_id = XVisualIDFromVisual(vi.visual); + *visual_type = TrueColor; + + return 1; +} + +static void yagl_x11_display_destroy(struct yagl_native_display *dpy) +{ + struct yagl_x11_display *x11_dpy = (struct yagl_x11_display*)dpy; + Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy); + + if (x11_dpy->own_dpy) { + XCloseDisplay(x_dpy); + } + + if (dpy->drm_fd >= 0) { + close(dpy->drm_fd); + } + + yagl_native_display_cleanup(dpy); + + yagl_free(x11_dpy); +} + +struct yagl_native_display *yagl_x11_display_create(struct yagl_native_platform *platform, + yagl_os_display os_dpy, + int own_dpy, + int enable_drm) +{ + Display *x_dpy = YAGL_X11_DPY(os_dpy); + struct yagl_x11_display *dpy; + int xmajor; + int xminor; + Bool pixmaps; + int drm_fd = -1; + + YAGL_LOG_FUNC_SET(eglGetDisplay); + + dpy = yagl_malloc0(sizeof(*dpy)); + + dpy->own_dpy = own_dpy; + + dpy->xshm_images_supported = XShmQueryVersion(x_dpy, + &xmajor, + &xminor, + &pixmaps); + dpy->xshm_pixmaps_supported = pixmaps; + + YAGL_LOG_DEBUG("XShm images are%s supported, version %d, %d (pixmaps = %d)", + (dpy->xshm_images_supported ? "" : " NOT"), + xmajor, + xminor, + pixmaps); + + if (enable_drm) { + drm_fd = yagl_x11_display_dri2_init(x_dpy); + + if (drm_fd < 0) { + yagl_free(dpy); + return NULL; + } + } + + yagl_native_display_init(&dpy->base, + platform, + os_dpy, + drm_fd); + + dpy->base.wrap_window = &yagl_x11_display_wrap_window; + dpy->base.wrap_pixmap = &yagl_x11_display_wrap_pixmap; + dpy->base.create_pixmap = &yagl_x11_display_create_pixmap; + dpy->base.create_image = &yagl_x11_display_create_image; + dpy->base.get_visual = &yagl_x11_display_get_visual; + dpy->base.destroy = &yagl_x11_display_destroy; + + return &dpy->base; +} |