#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <assert.h>
#include <xf86drm.h>
#include "X11/Xlib.h"
#include "va.h"
#include "va_backend.h"
#include "va_dri.h"
#include "va_dricommon.h"
struct dri1_drawable
{
struct dri_drawable base;
union dri_buffer buffer;
int width;
int height;
};
static struct dri_drawable *
dri1CreateDrawable(VADriverContextP ctx, XID x_drawable)
{
struct dri1_drawable *dri1_drawable;
dri1_drawable = calloc(1, sizeof(*dri1_drawable));
if (!dri1_drawable)
return NULL;
dri1_drawable->base.x_drawable = x_drawable;
return &dri1_drawable->base;
}
static void
dri1DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
{
free(dri_drawable);
}
static void
dri1SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
{
}
static union dri_buffer *
dri1GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
{
struct dri1_drawable *dri1_drawable = (struct dri1_drawable *)dri_drawable;
return &dri1_drawable->buffer;
}
static void
dri1Close(VADriverContextP ctx)
{
struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
free_drawable_hashtable(ctx);
VA_DRIDestroyContext(ctx->native_dpy, ctx->x11_screen, dri_state->hwContextID);
assert(dri_state->pSAREA != MAP_FAILED);
drmUnmap(dri_state->pSAREA, SAREA_MAX);
assert(dri_state->base.fd >= 0);
drmCloseOnce(dri_state->base.fd);
VA_DRICloseConnection(ctx->native_dpy, ctx->x11_screen);
}
Bool
isDRI1Connected(VADriverContextP ctx, char **driver_name)
{
struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
int direct_capable;
int driver_major;
int driver_minor;
int driver_patch;
int newlyopened;
char *BusID;
drm_magic_t magic;
*driver_name = NULL;
dri_state->base.fd = -1;
dri_state->pSAREA = MAP_FAILED;
dri_state->base.auth_type = VA_NONE;
if (!VA_DRIQueryDirectRenderingCapable(ctx->native_dpy,
ctx->x11_screen,
&direct_capable))
goto err_out0;
if (!direct_capable)
goto err_out0;
if (!VA_DRIGetClientDriverName(ctx->native_dpy, ctx->x11_screen,
&driver_major, &driver_minor,
&driver_patch, driver_name))
goto err_out0;
if (!VA_DRIOpenConnection(ctx->native_dpy, ctx->x11_screen,
&dri_state->hSAREA, &BusID))
goto err_out0;
dri_state->base.fd = drmOpenOnce(NULL, BusID, &newlyopened);
XFree(BusID);
if (dri_state->base.fd < 0)
goto err_out1;
if (drmGetMagic(dri_state->base.fd, &magic))
goto err_out1;
if (newlyopened && !VA_DRIAuthConnection(ctx->native_dpy, ctx->x11_screen, magic))
goto err_out1;
if (drmMap(dri_state->base.fd, dri_state->hSAREA, SAREA_MAX, &dri_state->pSAREA))
goto err_out1;
if (!VA_DRICreateContext(ctx->native_dpy, ctx->x11_screen,
DefaultVisual(ctx->native_dpy, ctx->x11_screen),
&dri_state->hwContextID, &dri_state->hwContext))
goto err_out1;
dri_state->base.auth_type = VA_DRI1;
dri_state->createDrawable = dri1CreateDrawable;
dri_state->destroyDrawable = dri1DestroyDrawable;
dri_state->swapBuffer = dri1SwapBuffer;
dri_state->getRenderingBuffer = dri1GetRenderingBuffer;
dri_state->close = dri1Close;
return True;
err_out1:
if (dri_state->pSAREA != MAP_FAILED)
drmUnmap(dri_state->pSAREA, SAREA_MAX);
if (dri_state->base.fd >= 0)
drmCloseOnce(dri_state->base.fd);
VA_DRICloseConnection(ctx->native_dpy, ctx->x11_screen);
err_out0:
if (*driver_name)
XFree(*driver_name);
dri_state->pSAREA = MAP_FAILED;
dri_state->base.fd = -1;
*driver_name = NULL;
return False;
}