OLD | NEW |
(Empty) | |
| 1 #include <stdlib.h> |
| 2 #include <fcntl.h> |
| 3 #include <unistd.h> |
| 4 #include <assert.h> |
| 5 |
| 6 #include <xf86drm.h> |
| 7 |
| 8 #include <X11/Xlibint.h> |
| 9 #include <X11/Xlib.h> |
| 10 #include "va.h" |
| 11 #include "va_backend.h" |
| 12 |
| 13 #include "va_dri2.h" |
| 14 #include "va_dri2tokens.h" |
| 15 #include "va_dricommon.h" |
| 16 |
| 17 #define __DRI_BUFFER_FRONT_LEFT 0 |
| 18 #define __DRI_BUFFER_BACK_LEFT 1 |
| 19 #define __DRI_BUFFER_FRONT_RIGHT 2 |
| 20 #define __DRI_BUFFER_BACK_RIGHT 3 |
| 21 #define __DRI_BUFFER_DEPTH 4 |
| 22 #define __DRI_BUFFER_STENCIL 5 |
| 23 #define __DRI_BUFFER_ACCUM 6 |
| 24 #define __DRI_BUFFER_FAKE_FRONT_LEFT 7 |
| 25 #define __DRI_BUFFER_FAKE_FRONT_RIGHT 8 |
| 26 |
| 27 struct dri2_drawable |
| 28 { |
| 29 struct dri_drawable base; |
| 30 union dri_buffer buffers[5]; |
| 31 int width; |
| 32 int height; |
| 33 int has_backbuffer; |
| 34 int back_index; |
| 35 int front_index; |
| 36 }; |
| 37 |
| 38 static int gsDRI2SwapAvailable; |
| 39 |
| 40 static struct dri_drawable * |
| 41 dri2CreateDrawable(VADriverContextP ctx, XID x_drawable) |
| 42 { |
| 43 struct dri2_drawable *dri2_drawable; |
| 44 |
| 45 dri2_drawable = calloc(1, sizeof(*dri2_drawable)); |
| 46 |
| 47 if (!dri2_drawable) |
| 48 return NULL; |
| 49 |
| 50 dri2_drawable->base.x_drawable = x_drawable; |
| 51 dri2_drawable->base.x = 0; |
| 52 dri2_drawable->base.y = 0; |
| 53 VA_DRI2CreateDrawable(ctx->native_dpy, x_drawable); |
| 54 |
| 55 return &dri2_drawable->base; |
| 56 } |
| 57 |
| 58 static void |
| 59 dri2DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable) |
| 60 { |
| 61 VA_DRI2DestroyDrawable(ctx->native_dpy, dri_drawable->x_drawable); |
| 62 free(dri_drawable); |
| 63 } |
| 64 |
| 65 static void |
| 66 dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable) |
| 67 { |
| 68 struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable; |
| 69 XRectangle xrect; |
| 70 XserverRegion region; |
| 71 |
| 72 if (dri2_drawable->has_backbuffer) { |
| 73 if (gsDRI2SwapAvailable) { |
| 74 CARD64 ret; |
| 75 VA_DRI2SwapBuffers(ctx->native_dpy, dri_drawable->x_drawable, 0, 0, |
| 76 0, &ret); |
| 77 } else { |
| 78 xrect.x = 0; |
| 79 xrect.y = 0; |
| 80 xrect.width = dri2_drawable->width; |
| 81 xrect.height = dri2_drawable->height; |
| 82 |
| 83 region = XFixesCreateRegion(ctx->native_dpy, &xrect, 1); |
| 84 VA_DRI2CopyRegion(ctx->native_dpy, dri_drawable->x_drawable, region, |
| 85 DRI2BufferFrontLeft, DRI2BufferBackLeft); |
| 86 XFixesDestroyRegion(ctx->native_dpy, region); |
| 87 } |
| 88 } |
| 89 } |
| 90 |
| 91 static union dri_buffer * |
| 92 dri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable) |
| 93 { |
| 94 struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable; |
| 95 int i; |
| 96 int count; |
| 97 unsigned int attachments[5]; |
| 98 VA_DRI2Buffer *buffers; |
| 99 |
| 100 i = 0; |
| 101 if (dri_drawable->is_window) |
| 102 attachments[i++] = __DRI_BUFFER_BACK_LEFT; |
| 103 else |
| 104 attachments[i++] = __DRI_BUFFER_FRONT_LEFT; |
| 105 |
| 106 buffers = VA_DRI2GetBuffers(ctx->native_dpy, dri_drawable->x_drawable, |
| 107 &dri2_drawable->width, &dri2_drawable->height, |
| 108 attachments, i, &count); |
| 109 assert(buffers); |
| 110 if (buffers == NULL) |
| 111 return NULL; |
| 112 |
| 113 dri2_drawable->has_backbuffer = 0; |
| 114 |
| 115 for (i = 0; i < count; i++) { |
| 116 dri2_drawable->buffers[i].dri2.attachment = buffers[i].attachment; |
| 117 dri2_drawable->buffers[i].dri2.name = buffers[i].name; |
| 118 dri2_drawable->buffers[i].dri2.pitch = buffers[i].pitch; |
| 119 dri2_drawable->buffers[i].dri2.cpp = buffers[i].cpp; |
| 120 dri2_drawable->buffers[i].dri2.flags = buffers[i].flags; |
| 121 |
| 122 if (buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) { |
| 123 dri2_drawable->has_backbuffer = 1; |
| 124 dri2_drawable->back_index = i; |
| 125 } |
| 126 |
| 127 if (buffers[i].attachment == __DRI_BUFFER_FRONT_LEFT) |
| 128 dri2_drawable->front_index = i; |
| 129 } |
| 130 |
| 131 dri_drawable->width = dri2_drawable->width; |
| 132 dri_drawable->height = dri2_drawable->height; |
| 133 Xfree(buffers); |
| 134 |
| 135 if (dri2_drawable->has_backbuffer) |
| 136 return &dri2_drawable->buffers[dri2_drawable->back_index]; |
| 137 |
| 138 return &dri2_drawable->buffers[dri2_drawable->front_index]; |
| 139 } |
| 140 |
| 141 void |
| 142 dri2Close(VADriverContextP ctx) |
| 143 { |
| 144 struct dri_state *dri_state = (struct dri_state *)ctx->dri_state; |
| 145 |
| 146 free_drawable_hashtable(ctx); |
| 147 |
| 148 if (dri_state->fd >= 0); |
| 149 close(dri_state->fd); |
| 150 } |
| 151 |
| 152 Bool |
| 153 isDRI2Connected(VADriverContextP ctx, char **driver_name) |
| 154 { |
| 155 struct dri_state *dri_state = (struct dri_state *)ctx->dri_state; |
| 156 int major, minor; |
| 157 int error_base; |
| 158 int event_base; |
| 159 char *device_name = NULL; |
| 160 drm_magic_t magic; |
| 161 *driver_name = NULL; |
| 162 dri_state->fd = -1; |
| 163 dri_state->driConnectedFlag = VA_NONE; |
| 164 if (!VA_DRI2QueryExtension(ctx->native_dpy, &event_base, &error_base)) |
| 165 goto err_out; |
| 166 |
| 167 if (!VA_DRI2QueryVersion(ctx->native_dpy, &major, &minor)) |
| 168 goto err_out; |
| 169 |
| 170 |
| 171 if (!VA_DRI2Connect(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_sc
reen), |
| 172 driver_name, &device_name)) |
| 173 goto err_out; |
| 174 |
| 175 dri_state->fd = open(device_name, O_RDWR); |
| 176 assert(dri_state->fd >= 0); |
| 177 |
| 178 if (dri_state->fd < 0) |
| 179 goto err_out; |
| 180 |
| 181 if (drmGetMagic(dri_state->fd, &magic)) |
| 182 goto err_out; |
| 183 |
| 184 if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x
11_screen), |
| 185 magic)) |
| 186 goto err_out; |
| 187 |
| 188 dri_state->driConnectedFlag = VA_DRI2; |
| 189 dri_state->createDrawable = dri2CreateDrawable; |
| 190 dri_state->destroyDrawable = dri2DestroyDrawable; |
| 191 dri_state->swapBuffer = dri2SwapBuffer; |
| 192 dri_state->getRenderingBuffer = dri2GetRenderingBuffer; |
| 193 dri_state->close = dri2Close; |
| 194 gsDRI2SwapAvailable = (minor >= 2); |
| 195 |
| 196 if (device_name) |
| 197 Xfree(device_name); |
| 198 |
| 199 return True; |
| 200 |
| 201 err_out: |
| 202 if (device_name) |
| 203 Xfree(device_name); |
| 204 |
| 205 if (*driver_name) |
| 206 Xfree(*driver_name); |
| 207 |
| 208 if (dri_state->fd >= 0) |
| 209 close(dri_state->fd); |
| 210 |
| 211 *driver_name = NULL; |
| 212 dri_state->fd = -1; |
| 213 |
| 214 return False; |
| 215 } |
| 216 |
OLD | NEW |