summaryrefslogtreecommitdiff
path: root/src/x11/dri2_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/x11/dri2_util.c')
-rw-r--r--src/x11/dri2_util.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/x11/dri2_util.c b/src/x11/dri2_util.c
new file mode 100644
index 0000000..ebe7a2c
--- /dev/null
+++ b/src/x11/dri2_util.c
@@ -0,0 +1,200 @@
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <xf86drm.h>
+
+#include <X11/Xlibint.h>
+#include <X11/Xlib.h>
+#include "va.h"
+#include "va_backend.h"
+
+#include "va_dri2.h"
+#include "va_dri2tokens.h"
+#include "va_dricommon.h"
+
+#define __DRI_BUFFER_FRONT_LEFT 0
+#define __DRI_BUFFER_BACK_LEFT 1
+#define __DRI_BUFFER_FRONT_RIGHT 2
+#define __DRI_BUFFER_BACK_RIGHT 3
+#define __DRI_BUFFER_DEPTH 4
+#define __DRI_BUFFER_STENCIL 5
+#define __DRI_BUFFER_ACCUM 6
+#define __DRI_BUFFER_FAKE_FRONT_LEFT 7
+#define __DRI_BUFFER_FAKE_FRONT_RIGHT 8
+
+struct dri2_drawable
+{
+ struct dri_drawable base;
+ union dri_buffer buffers[5];
+ int width;
+ int height;
+ int has_backbuffer;
+ int back_index;
+ int front_index;
+};
+
+static struct dri_drawable *
+dri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
+{
+ struct dri2_drawable *dri2_drawable;
+
+ dri2_drawable = calloc(1, sizeof(*dri2_drawable));
+
+ if (!dri2_drawable)
+ return NULL;
+
+ dri2_drawable->base.x_drawable = x_drawable;
+ dri2_drawable->base.x = 0;
+ dri2_drawable->base.y = 0;
+ VA_DRI2CreateDrawable(ctx->x11_dpy, x_drawable);
+
+ return &dri2_drawable->base;
+}
+
+static void
+dri2DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
+{
+ VA_DRI2DestroyDrawable(ctx->x11_dpy, dri_drawable->x_drawable);
+ free(dri_drawable);
+}
+
+static void
+dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
+{
+ struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
+ XRectangle xrect;
+ XserverRegion region;
+
+ if (dri2_drawable->has_backbuffer) {
+ xrect.x = 0;
+ xrect.y = 0;
+ xrect.width = dri2_drawable->width;
+ xrect.height = dri2_drawable->height;
+
+ region = XFixesCreateRegion(ctx->x11_dpy, &xrect, 1);
+ VA_DRI2CopyRegion(ctx->x11_dpy, dri_drawable->x_drawable, region,
+ DRI2BufferFrontLeft, DRI2BufferBackLeft);
+ XFixesDestroyRegion(ctx->x11_dpy, region);
+ }
+}
+
+static union dri_buffer *
+dri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
+{
+ struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
+ int i;
+ int count;
+ unsigned int attachments[5];
+ VA_DRI2Buffer *buffers;
+
+ i = 0;
+ attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+ attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+ buffers = VA_DRI2GetBuffers(ctx->x11_dpy, dri_drawable->x_drawable,
+ &dri2_drawable->width, &dri2_drawable->height,
+ attachments, i, &count);
+ assert(buffers);
+ if (buffers == NULL)
+ return NULL;
+
+ dri2_drawable->has_backbuffer = 0;
+
+ for (i = 0; i < count; i++) {
+ dri2_drawable->buffers[i].dri2.attachment = buffers[i].attachment;
+ dri2_drawable->buffers[i].dri2.name = buffers[i].name;
+ dri2_drawable->buffers[i].dri2.pitch = buffers[i].pitch;
+ dri2_drawable->buffers[i].dri2.cpp = buffers[i].cpp;
+ dri2_drawable->buffers[i].dri2.flags = buffers[i].flags;
+
+ if (buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) {
+ dri2_drawable->has_backbuffer = 1;
+ dri2_drawable->back_index = i;
+ }
+
+ if (buffers[i].attachment == __DRI_BUFFER_FRONT_LEFT)
+ dri2_drawable->front_index = i;
+ }
+
+ dri_drawable->width = dri2_drawable->width;
+ dri_drawable->height = dri2_drawable->height;
+ Xfree(buffers);
+
+ if (dri2_drawable->has_backbuffer)
+ return &dri2_drawable->buffers[dri2_drawable->back_index];
+
+ return &dri2_drawable->buffers[dri2_drawable->front_index];
+}
+
+static void
+dri2Close(VADriverContextP ctx)
+{
+ struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
+
+ free_drawable_hashtable(ctx);
+ assert(dri_state->fd >= 0);
+ close(dri_state->fd);
+}
+
+Bool
+isDRI2Connected(VADriverContextP ctx, char **driver_name)
+{
+ struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
+ int major, minor;
+ int error_base;
+ int event_base;
+ char *device_name = NULL;
+ drm_magic_t magic;
+ *driver_name = NULL;
+ dri_state->fd = -1;
+ dri_state->driConnectedFlag = VA_NONE;
+ if (!VA_DRI2QueryExtension(ctx->x11_dpy, &event_base, &error_base))
+ goto err_out;
+
+ if (!VA_DRI2QueryVersion(ctx->x11_dpy, &major, &minor))
+ goto err_out;
+
+
+ if (!VA_DRI2Connect(ctx->x11_dpy, RootWindow(ctx->x11_dpy, ctx->x11_screen),
+ driver_name, &device_name))
+ goto err_out;
+
+ dri_state->fd = open(device_name, O_RDWR);
+ assert(dri_state->fd >= 0);
+
+ if (dri_state->fd < 0)
+ goto err_out;
+
+ if (drmGetMagic(dri_state->fd, &magic))
+ goto err_out;
+
+ if (!VA_DRI2Authenticate(ctx->x11_dpy, RootWindow(ctx->x11_dpy, ctx->x11_screen),
+ magic))
+ goto err_out;
+
+ dri_state->driConnectedFlag = VA_DRI2;
+ dri_state->createDrawable = dri2CreateDrawable;
+ dri_state->destroyDrawable = dri2DestroyDrawable;
+ dri_state->swapBuffer = dri2SwapBuffer;
+ dri_state->getRenderingBuffer = dri2GetRenderingBuffer;
+ dri_state->close = dri2Close;
+
+ return True;
+
+err_out:
+ if (device_name)
+ Xfree(device_name);
+
+ if (*driver_name)
+ Xfree(*driver_name);
+
+ if (dri_state->fd >= 0)
+ close(dri_state->fd);
+
+ *driver_name = NULL;
+ dri_state->fd = -1;
+
+ return False;
+}
+