aboutsummaryrefslogtreecommitdiffstats
path: root/drmtools-egl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drmtools-egl.c')
-rw-r--r--drmtools-egl.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/drmtools-egl.c b/drmtools-egl.c
new file mode 100644
index 0000000..8c91c0f
--- /dev/null
+++ b/drmtools-egl.c
@@ -0,0 +1,195 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getopt.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <gbm.h>
+#include <epoxy/gl.h>
+#include <epoxy/egl.h>
+
+#include "gfx.h"
+#include "drmtools.h"
+
+/* ------------------------------------------------------------------ */
+
+static struct gbm_device *gbm_dev;
+static struct gbm_surface *gbm_surface;
+static EGLDisplay dpy;
+static EGLConfig cfg;
+static EGLContext ctx;
+static EGLSurface surface;
+
+/* ------------------------------------------------------------------ */
+
+static int drm_setup_egl(void)
+{
+ static const EGLint conf_att[] = {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RED_SIZE, 5,
+ EGL_GREEN_SIZE, 5,
+ EGL_BLUE_SIZE, 5,
+ EGL_ALPHA_SIZE, 0,
+ EGL_NONE,
+ };
+ static const EGLint ctx_att[] = {
+ EGL_NONE
+ };
+ EGLint major, minor;
+ EGLBoolean b;
+ EGLint n;
+
+ gbm_dev = gbm_create_device(drm_fd);
+ if (!gbm_dev) {
+ fprintf(stderr, "egl: gbm_create_device failed\n");
+ return -1;
+ }
+
+ gbm_surface = gbm_surface_create(gbm_dev,
+ drm_mode->hdisplay,
+ drm_mode->vdisplay,
+ GBM_FORMAT_XRGB8888,
+ GBM_BO_USE_RENDERING);
+ if (!gbm_surface) {
+ fprintf(stderr, "egl: gbm_create_surface failed\n");
+ return -1;
+ }
+
+ dpy = eglGetDisplay(gbm_dev);
+ if (dpy == EGL_NO_DISPLAY) {
+ fprintf(stderr, "egl: eglGetDisplay failed\n");
+ return -1;
+ }
+
+ b = eglInitialize(dpy, &major, &minor);
+ if (b == EGL_FALSE) {
+ fprintf(stderr, "egl: eglInitialize failed\n");
+ return -1;
+ }
+
+ b = eglBindAPI(EGL_OPENGL_API);
+ if (b == EGL_FALSE) {
+ fprintf(stderr, "egl: eglBindAPI failed\n");
+ return -1;
+ }
+
+ b = eglChooseConfig(dpy, conf_att, &cfg, 1, &n);
+ if (b == EGL_FALSE || n != 1) {
+ fprintf(stderr, "egl: eglChooseConfig failed\n");
+ return -1;
+ }
+
+ ctx = eglCreateContext(dpy, cfg, EGL_NO_CONTEXT, ctx_att);
+ if (ctx == EGL_NO_CONTEXT) {
+ fprintf(stderr, "egl: eglCreateContext failed\n");
+ return -1;
+ }
+
+ b = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx);
+ if (b == EGL_FALSE) {
+ fprintf(stderr, "egl: eglMakeCurrent(EGL_NO_SURFACE) failed\n");
+ return -1;
+ }
+
+ surface = eglCreateWindowSurface(dpy, cfg,
+ (EGLNativeWindowType)gbm_surface,
+ NULL);
+ if (!surface) {
+ fprintf(stderr, "egl: eglCreateWindowSurface failed\n");
+ return -1;
+ }
+
+ b = eglMakeCurrent(dpy, surface, surface, ctx);
+ if (b == EGL_FALSE) {
+ fprintf(stderr, "egl: eglMakeCurrent(surface) failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+static void drm_egl_restore_display(void)
+{
+ /* FIXME */
+}
+
+static int fbid;
+static struct gbm_bo *bo;
+
+/* called after cairo_gl_surface_swapbuffers(); */
+static void drm_egl_flush_display(bool second)
+{
+ uint32_t handle, stride, newfb;
+ struct gbm_bo *newbo;
+ int rc;
+
+ newbo = gbm_surface_lock_front_buffer(gbm_surface);
+ if (!newbo) {
+ fprintf(stderr, "egl: gbm_surface_lock_front_buffer failed\n");
+ return;
+ }
+ handle = gbm_bo_get_handle(newbo).u32;
+ stride = gbm_bo_get_stride(newbo);
+
+ drmModeAddFB(drm_fd, drm_mode->hdisplay, drm_mode->vdisplay, 24, 32,
+ stride, handle, &newfb);
+ rc = drmModeSetCrtc(drm_fd, drm_enc->crtc_id, newfb, 0, 0,
+ &drm_conn->connector_id, 1,
+ &drm_conn->modes[0]);
+ if (rc < 0) {
+ fprintf(stderr, "egl: drmModeSetCrtc() failed\n");
+ return;
+ }
+
+ if (fbid) {
+ drmModeRmFB(drm_fd, fbid);
+ }
+ fbid = newfb;
+
+ if (bo) {
+ gbm_surface_release_buffer(gbm_surface, bo);
+ }
+ bo = newbo;
+}
+
+gfxstate *drm_init_egl(const char *device, const char *output)
+{
+ gfxstate *gfx;
+ char dev[64];
+
+ if (device) {
+ snprintf(dev, sizeof(dev), "%s", device);
+ } else {
+ snprintf(dev, sizeof(dev), DRM_DEV_NAME, DRM_DIR_NAME, 0);
+ }
+ fprintf(stderr, "trying drm/egl: %s ...\n", dev);
+
+ if (drm_init_dev(dev, output) < 0)
+ return NULL;
+ if (drm_setup_egl() < 0)
+ return NULL;
+
+ /* prepare gfx */
+ gfx = malloc(sizeof(*gfx));
+ memset(gfx, 0, sizeof(*gfx));
+
+ gfx->hdisplay = drm_mode->hdisplay;
+ gfx->vdisplay = drm_mode->vdisplay;
+
+ gfx->dpy = dpy;
+ gfx->ctx = ctx;
+ gfx->surface = surface;
+
+ gfx->restore_display = drm_egl_restore_display;
+ gfx->cleanup_display = drm_cleanup_display;
+ gfx->flush_display = drm_egl_flush_display;
+
+ return gfx;
+}