OSDN Git Service

4fddf3704aecc25eeae94daf0aca0ea06951fdeb
[android-x86/hardware-intel-common-libva.git] / va / x11 / dri2_util.c
1 /*
2  * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include <stdlib.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <assert.h>
28
29 #include <xf86drm.h>
30
31 #include <X11/Xlibint.h>
32 #include <X11/Xlib.h>
33 #include "va.h"
34 #include "va_backend.h"
35
36 #include "va_dri2.h"
37 #include "va_dri2tokens.h"
38 #include "va_dricommon.h"
39
40 #define __DRI_BUFFER_FRONT_LEFT         0
41 #define __DRI_BUFFER_BACK_LEFT          1
42 #define __DRI_BUFFER_FRONT_RIGHT        2
43 #define __DRI_BUFFER_BACK_RIGHT         3
44 #define __DRI_BUFFER_DEPTH              4
45 #define __DRI_BUFFER_STENCIL            5
46 #define __DRI_BUFFER_ACCUM              6
47 #define __DRI_BUFFER_FAKE_FRONT_LEFT    7
48 #define __DRI_BUFFER_FAKE_FRONT_RIGHT   8
49
50 struct dri2_drawable 
51 {
52     struct dri_drawable base;
53     union dri_buffer buffers[5];
54     int width;
55     int height;
56     int has_backbuffer;
57     int back_index;
58     int front_index;
59 };
60
61 static int gsDRI2SwapAvailable;
62
63 static struct dri_drawable * 
64 dri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
65 {
66     struct dri2_drawable *dri2_drawable;
67
68     dri2_drawable = calloc(1, sizeof(*dri2_drawable));
69
70     if (!dri2_drawable)
71         return NULL;
72
73     dri2_drawable->base.x_drawable = x_drawable;
74     dri2_drawable->base.x = 0;
75     dri2_drawable->base.y = 0;
76     VA_DRI2CreateDrawable(ctx->native_dpy, x_drawable);
77
78     return &dri2_drawable->base;
79 }
80
81 static void 
82 dri2DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
83 {
84     VA_DRI2DestroyDrawable(ctx->native_dpy, dri_drawable->x_drawable);
85     free(dri_drawable);
86 }
87
88 static void 
89 dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
90 {
91     struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
92     XRectangle xrect;
93     XserverRegion region;
94
95     if (dri2_drawable->has_backbuffer) {
96         if (gsDRI2SwapAvailable) {
97             CARD64 ret;
98             VA_DRI2SwapBuffers(ctx->native_dpy, dri_drawable->x_drawable,
99                                0, 1, 0,
100                                &ret);
101         } else {
102             xrect.x = 0;
103             xrect.y = 0;
104             xrect.width = dri2_drawable->width;
105             xrect.height = dri2_drawable->height;
106
107             region = XFixesCreateRegion(ctx->native_dpy, &xrect, 1);
108             VA_DRI2CopyRegion(ctx->native_dpy, dri_drawable->x_drawable, region,
109                               DRI2BufferFrontLeft, DRI2BufferBackLeft);
110             XFixesDestroyRegion(ctx->native_dpy, region);
111         }
112     }
113 }
114
115 static union dri_buffer *
116 dri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
117 {
118     struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
119     int i;
120     int count;
121     unsigned int attachments[5];
122     VA_DRI2Buffer *buffers;
123     
124     i = 0;
125     if (dri_drawable->is_window)
126         attachments[i++] = __DRI_BUFFER_BACK_LEFT;
127     else
128         attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
129
130     buffers = VA_DRI2GetBuffers(ctx->native_dpy, dri_drawable->x_drawable,
131                              &dri2_drawable->width, &dri2_drawable->height, 
132                              attachments, i, &count);
133     assert(buffers);
134     if (buffers == NULL)
135         return NULL;
136
137     dri2_drawable->has_backbuffer = 0;
138
139     for (i = 0; i < count; i++) {
140         dri2_drawable->buffers[i].dri2.attachment = buffers[i].attachment;
141         dri2_drawable->buffers[i].dri2.name = buffers[i].name;
142         dri2_drawable->buffers[i].dri2.pitch = buffers[i].pitch;
143         dri2_drawable->buffers[i].dri2.cpp = buffers[i].cpp;
144         dri2_drawable->buffers[i].dri2.flags = buffers[i].flags;
145         
146         if (buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) {
147             dri2_drawable->has_backbuffer = 1;
148             dri2_drawable->back_index = i;
149         }
150
151         if (buffers[i].attachment == __DRI_BUFFER_FRONT_LEFT)
152             dri2_drawable->front_index = i;
153     }
154     
155     dri_drawable->width = dri2_drawable->width;
156     dri_drawable->height = dri2_drawable->height;
157     Xfree(buffers);
158
159     if (dri2_drawable->has_backbuffer)
160         return &dri2_drawable->buffers[dri2_drawable->back_index];
161
162     return &dri2_drawable->buffers[dri2_drawable->front_index];
163 }
164
165 static void
166 dri2Close(VADriverContextP ctx)
167 {
168     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
169
170     free_drawable_hashtable(ctx);
171
172     if (dri_state->base.fd >= 0)
173         close(dri_state->base.fd);
174 }
175
176 Bool 
177 isDRI2Connected(VADriverContextP ctx, char **driver_name)
178 {
179     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
180     int major, minor;
181     int error_base;
182     int event_base;
183     char *device_name = NULL;
184     drm_magic_t magic;        
185     *driver_name = NULL;
186     dri_state->base.fd = -1;
187     dri_state->base.auth_type = VA_NONE;
188     if (!VA_DRI2QueryExtension(ctx->native_dpy, &event_base, &error_base))
189         goto err_out;
190
191     if (!VA_DRI2QueryVersion(ctx->native_dpy, &major, &minor))
192         goto err_out;
193
194
195     if (!VA_DRI2Connect(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
196                      driver_name, &device_name))
197         goto err_out;
198
199     dri_state->base.fd = open(device_name, O_RDWR);
200
201     if (dri_state->base.fd < 0)
202         goto err_out;
203
204     if (drmGetMagic(dri_state->base.fd, &magic))
205         goto err_out;
206
207     if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
208                           magic))
209         goto err_out;
210
211     dri_state->base.auth_type = VA_DRI2;
212     dri_state->createDrawable = dri2CreateDrawable;
213     dri_state->destroyDrawable = dri2DestroyDrawable;
214     dri_state->swapBuffer = dri2SwapBuffer;
215     dri_state->getRenderingBuffer = dri2GetRenderingBuffer;
216     dri_state->close = dri2Close;
217     gsDRI2SwapAvailable = (minor >= 2);
218
219     if (device_name)
220         Xfree(device_name);
221
222     return True;
223
224 err_out:
225     if (device_name)
226         Xfree(device_name);
227
228     if (*driver_name)
229         Xfree(*driver_name);
230
231     if (dri_state->base.fd >= 0)
232         close(dri_state->base.fd);
233
234     *driver_name = NULL;
235     dri_state->base.fd = -1;
236     
237     return False;
238 }
239