OSDN Git Service

a00df7b8b854e9b10917635703e2fc20878f7f49
[android-x86/hardware-intel-common-libva.git] / va / x11 / dri2_util.c
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_screen),
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->x11_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