summaryrefslogtreecommitdiff
path: root/sys/xvboimage/drm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/xvboimage/drm.c')
-rw-r--r--sys/xvboimage/drm.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/sys/xvboimage/drm.c b/sys/xvboimage/drm.c
new file mode 100644
index 00000000..d71a2206
--- /dev/null
+++ b/sys/xvboimage/drm.c
@@ -0,0 +1,231 @@
+#include <stdio.h>
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include <X11/extensions/dri2proto.h>
+#include <xf86drm.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "drm-xvimage.h"
+
+#define FALSE 0
+#define TRUE 1
+
+#define DRI2DriverDRI 0
+
+static char dri2ExtensionName[] = DRI2_NAME;
+static XExtensionInfo dri2_info_data, *dri2_info = &dri2_info_data;
+
+static XEXT_GENERATE_CLOSE_DISPLAY(DRI2CloseDisplay, dri2_info);
+
+static int DRI2Error(Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
+{
+ return xFalse;
+}
+
+static XExtensionHooks dri2ExtensionHooks = {
+ .close_display = DRI2CloseDisplay,
+ .error = DRI2Error,
+};
+
+static XEXT_GENERATE_FIND_DISPLAY(DRI2FindDisplay, dri2_info,
+ dri2ExtensionName, &dri2ExtensionHooks, 0, NULL);
+
+static int DRI2QueryExtension(Display *dpy, int *eventBase, int *errorBase)
+{
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+
+ if (XextHasExtension(info)) {
+ *eventBase = info->codes->first_event;
+ *errorBase = info->codes->first_error;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int DRI2QueryVersion(Display *dpy, int *major, int *minor)
+{
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2QueryVersionReply rep;
+ xDRI2QueryVersionReq *req;
+
+ XextCheckExtension(dpy, info, dri2ExtensionName, FALSE);
+
+ LockDisplay(dpy);
+ GetReq(DRI2QueryVersion, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2QueryVersion;
+ req->majorVersion = DRI2_MAJOR;
+ req->minorVersion = DRI2_MINOR;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return FALSE;
+ }
+ *major = rep.majorVersion;
+ *minor = rep.minorVersion;
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return TRUE;
+}
+
+static int DRI2Connect(Display *dpy, XID window, char **driverName,
+ char **deviceName)
+{
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2ConnectReply rep;
+ xDRI2ConnectReq *req;
+
+ XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+ LockDisplay(dpy);
+ GetReq(DRI2Connect, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2Connect;
+ req->window = window;
+ req->driverType = DRI2DriverDRI;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return FALSE;
+ }
+ if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return FALSE;
+ }
+ *driverName = Xmalloc(rep.driverNameLength + 1);
+ if (*driverName == NULL) {
+ _XEatData(dpy, ((rep.driverNameLength + 3) & ~3) + ((rep.deviceNameLength + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return FALSE;
+ }
+ _XReadPad(dpy, *driverName, rep.driverNameLength);
+ (*driverName)[rep.driverNameLength] = '\0';
+
+ *deviceName = Xmalloc(rep.deviceNameLength + 1);
+ if (*deviceName == NULL) {
+ Xfree(*driverName);
+ _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return FALSE;
+ }
+ _XReadPad(dpy, *deviceName, rep.deviceNameLength);
+ (*deviceName)[rep.deviceNameLength] = '\0';
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return TRUE;
+}
+
+static int DRI2Authenticate(Display *dpy, XID window, drm_magic_t magic)
+{
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2AuthenticateReq *req;
+ xDRI2AuthenticateReply rep;
+
+ XextCheckExtension(dpy, info, dri2ExtensionName, FALSE);
+
+ LockDisplay(dpy);
+ GetReq(DRI2Authenticate, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2Authenticate;
+ req->window = window;
+ req->magic = magic;
+
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return FALSE;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return rep.authenticated;
+}
+
+int drm_handle_flink(struct drm *drm, uint32_t handle, uint32_t *name)
+{
+ struct drm_gem_flink flink;
+ int ret;
+
+ memset(&flink, 0, sizeof(flink));
+ flink.handle = handle;
+
+ ret = drmIoctl(drm->fd, DRM_IOCTL_GEM_FLINK, &flink);
+ if (ret == 0)
+ *name = flink.name;
+ return ret;
+}
+
+void drm_handle_close(struct drm *drm, uint32_t handle)
+{
+ struct drm_gem_close arg;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = handle;
+ drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &arg);
+}
+
+struct drm *drm_get_and_auth(Display *dpy)
+{
+ int error_base, event_base, major, minor, fd = -1;
+ char *device_name = NULL;
+ char *driver_name = NULL;
+ struct drm *drm;
+ drm_magic_t magic;
+ XID window = DefaultRootWindow(dpy);
+
+ if (!DRI2QueryExtension(dpy, &event_base, &error_base))
+ goto err;
+
+ if (!DRI2QueryVersion(dpy, &major, &minor))
+ goto err;
+
+ if (!DRI2Connect(dpy, window, &driver_name, &device_name))
+ goto err;
+
+ fd = open(device_name, O_RDWR);
+ if (fd < 0)
+ goto err;
+
+ if (drmGetMagic(fd, &magic))
+ goto err;
+
+ if (!DRI2Authenticate(dpy, window, magic))
+ goto err;
+
+ if (device_name)
+ XFree(device_name);
+ if (driver_name)
+ XFree(driver_name);
+
+ drm = malloc(sizeof(*drm));
+ if (!drm)
+ goto err;
+
+ drm->fd = fd;
+ return drm;
+
+err:
+ if (fd >= 0)
+ close(fd);
+ if (device_name)
+ XFree(device_name);
+ if (driver_name)
+ XFree(driver_name);
+ return NULL;
+}
+
+void drm_close(struct drm *drm)
+{
+ close(drm->fd);
+ free(drm);
+}