diff options
Diffstat (limited to 'sys/xvboimage/drm.c')
-rw-r--r-- | sys/xvboimage/drm.c | 231 |
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); +} |