1 #include <stdlib.h>
2 #include <fcntl.h>
3 #include <unistd.h>
4 #include <sys/mman.h>
5 #include <assert.h>
6 
7 #include <xf86drm.h>
8 
9 #include "X11/Xlib.h"
10 #include "va.h"
11 #include "va_backend.h"
12 
13 #include "va_dri.h"
14 #include "va_dricommon.h"
15 
16 struct dri1_drawable
17 {
18     struct dri_drawable base;
19     union dri_buffer buffer;
20     int width;
21     int height;
22 };
23 
24 static struct dri_drawable *
dri1CreateDrawable(VADriverContextP ctx,XID x_drawable)25 dri1CreateDrawable(VADriverContextP ctx, XID x_drawable)
26 {
27     struct dri1_drawable *dri1_drawable;
28 
29     dri1_drawable = calloc(1, sizeof(*dri1_drawable));
30 
31     if (!dri1_drawable)
32         return NULL;
33 
34     dri1_drawable->base.x_drawable = x_drawable;
35 
36     return &dri1_drawable->base;
37 }
38 
39 static void
dri1DestroyDrawable(VADriverContextP ctx,struct dri_drawable * dri_drawable)40 dri1DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
41 {
42     free(dri_drawable);
43 }
44 
45 static void
dri1SwapBuffer(VADriverContextP ctx,struct dri_drawable * dri_drawable)46 dri1SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
47 {
48 
49 }
50 
51 static union dri_buffer *
dri1GetRenderingBuffer(VADriverContextP ctx,struct dri_drawable * dri_drawable)52 dri1GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
53 {
54     struct dri1_drawable *dri1_drawable = (struct dri1_drawable *)dri_drawable;
55 
56     return &dri1_drawable->buffer;
57 }
58 
59 static void
dri1Close(VADriverContextP ctx)60 dri1Close(VADriverContextP ctx)
61 {
62     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
63 
64     free_drawable_hashtable(ctx);
65     VA_DRIDestroyContext(ctx->native_dpy, ctx->x11_screen, dri_state->hwContextID);
66     assert(dri_state->pSAREA != MAP_FAILED);
67     drmUnmap(dri_state->pSAREA, SAREA_MAX);
68     assert(dri_state->base.fd >= 0);
69     drmCloseOnce(dri_state->base.fd);
70     VA_DRICloseConnection(ctx->native_dpy, ctx->x11_screen);
71 }
72 
73 Bool
isDRI1Connected(VADriverContextP ctx,char ** driver_name)74 isDRI1Connected(VADriverContextP ctx, char **driver_name)
75 {
76     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
77     int direct_capable;
78     int driver_major;
79     int driver_minor;
80     int driver_patch;
81     int newlyopened;
82     char *BusID;
83     drm_magic_t magic;
84 
85     *driver_name = NULL;
86     dri_state->base.fd = -1;
87     dri_state->pSAREA = MAP_FAILED;
88     dri_state->base.auth_type = VA_NONE;
89 
90     if (!VA_DRIQueryDirectRenderingCapable(ctx->native_dpy,
91                                            ctx->x11_screen,
92                                            &direct_capable))
93         goto err_out0;
94 
95     if (!direct_capable)
96         goto err_out0;
97 
98     if (!VA_DRIGetClientDriverName(ctx->native_dpy, ctx->x11_screen,
99                                    &driver_major, &driver_minor,
100                                    &driver_patch, driver_name))
101         goto err_out0;
102 
103     if (!VA_DRIOpenConnection(ctx->native_dpy, ctx->x11_screen,
104                               &dri_state->hSAREA, &BusID))
105         goto err_out0;
106 
107 
108     dri_state->base.fd = drmOpenOnce(NULL, BusID, &newlyopened);
109     XFree(BusID);
110 
111     if (dri_state->base.fd < 0)
112         goto err_out1;
113 
114 
115     if (drmGetMagic(dri_state->base.fd, &magic))
116         goto err_out1;
117 
118     if (newlyopened && !VA_DRIAuthConnection(ctx->native_dpy, ctx->x11_screen, magic))
119         goto err_out1;
120 
121     if (drmMap(dri_state->base.fd, dri_state->hSAREA, SAREA_MAX, &dri_state->pSAREA))
122         goto err_out1;
123 
124     if (!VA_DRICreateContext(ctx->native_dpy, ctx->x11_screen,
125                              DefaultVisual(ctx->native_dpy, ctx->x11_screen),
126                              &dri_state->hwContextID, &dri_state->hwContext))
127         goto err_out1;
128 
129     dri_state->base.auth_type = VA_DRI1;
130     dri_state->createDrawable = dri1CreateDrawable;
131     dri_state->destroyDrawable = dri1DestroyDrawable;
132     dri_state->swapBuffer = dri1SwapBuffer;
133     dri_state->getRenderingBuffer = dri1GetRenderingBuffer;
134     dri_state->close = dri1Close;
135 
136     return True;
137 
138 err_out1:
139     if (dri_state->pSAREA != MAP_FAILED)
140         drmUnmap(dri_state->pSAREA, SAREA_MAX);
141 
142     if (dri_state->base.fd >= 0)
143         drmCloseOnce(dri_state->base.fd);
144 
145     VA_DRICloseConnection(ctx->native_dpy, ctx->x11_screen);
146 
147 err_out0:
148     if (*driver_name)
149         XFree(*driver_name);
150 
151     dri_state->pSAREA = MAP_FAILED;
152     dri_state->base.fd = -1;
153     *driver_name = NULL;
154 
155     return False;
156 }
157 
158