1e5340122cbaed05e449835bc5156ac8e1b56976
[profile/ivi/libva.git] / src / x11 / va_x11.c
1 /*
2  * Copyright (c) 2007 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
25 #define _GNU_SOURCE 1
26 #include "config.h"
27 #include "va.h"
28 #include "va_backend.h"
29 #include "va_x11.h"
30 #include "va_dri.h"
31 #include "va_dri2.h"
32 #include "va_dricommon.h"
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <errno.h>
41
42 static VADisplayContextP pDisplayContexts = NULL;
43
44 static void va_errorMessage(const char *msg, ...)
45 {
46     va_list args;
47
48     fprintf(stderr, "libva error: ");
49     va_start(args, msg);
50     vfprintf(stderr, msg, args);
51     va_end(args);
52 }
53
54 static void va_infoMessage(const char *msg, ...)
55 {
56     va_list args;
57
58     fprintf(stderr, "libva: ");
59     va_start(args, msg);
60     vfprintf(stderr, msg, args);
61     va_end(args);
62 }
63
64 static int va_DisplayContextIsValid (
65     VADisplayContextP pDisplayContext
66 )
67 {
68     VADisplayContextP ctx = pDisplayContexts;
69
70     while (ctx)
71     {
72         if (ctx == pDisplayContext && pDisplayContext->pDriverContext)
73             return 1;
74         ctx = ctx->pNext;
75     }
76     return 0;
77 }
78
79 static void va_DisplayContextDestroy (
80     VADisplayContextP pDisplayContext
81 )
82 {
83     VADisplayContextP *ctx = &pDisplayContexts;
84
85     /* Throw away pDisplayContext */
86     while (*ctx)
87     {
88         if (*ctx == pDisplayContext)
89         {
90             *ctx = pDisplayContext->pNext;
91             pDisplayContext->pNext = NULL;
92             break;
93         }
94         ctx = &((*ctx)->pNext);
95     }
96     free(pDisplayContext->pDriverContext);
97     free(pDisplayContext);
98 }
99
100
101 static VAStatus va_DRI2GetDriverName (
102     VADisplayContextP pDisplayContext,
103     char **driver_name
104 )
105 {
106     VADriverContextP ctx = pDisplayContext->pDriverContext;
107     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
108     int eventBase, errorBase;
109     char *device_name;
110     int driver_major;
111     int driver_minor;
112     int driver_patch;
113     Bool result = True;
114
115     if (!VA_DRI2QueryExtension(ctx->x11_dpy, &eventBase, &errorBase)) {
116         va_infoMessage("DRI2 extension isn't present\n");
117         return VA_STATUS_ERROR_UNKNOWN;
118     }
119
120     if (!VA_DRI2QueryVersion(ctx->x11_dpy, &driver_major, &driver_minor)) {
121         va_errorMessage("VA_DRI2QueryVersion failed\n");
122         return VA_STATUS_ERROR_UNKNOWN;
123     }
124     
125     if (!VA_DRI2Connect(ctx->x11_dpy, RootWindow(ctx->x11_dpy, ctx->x11_screen),
126                      driver_name, &device_name)) {
127         va_infoMessage("DRI2 isn't enabled, fallback to DRI1\n");
128         return VA_STATUS_ERROR_UNKNOWN;
129     }
130
131     va_infoMessage("VA_DRI2Connect: %d.%d.%d %s (screen %d)\n",
132                    driver_major, driver_minor, driver_patch, *driver_name, ctx->x11_screen);
133     ctx->dri2 = 1;
134     
135     return VA_STATUS_SUCCESS;
136 }
137
138 static VAStatus va_DRIGetDriverName (
139     VADisplayContextP pDisplayContext,
140     char **driver_name
141 )
142 {
143     VADriverContextP ctx = pDisplayContext->pDriverContext;
144     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
145     int eventBase, errorBase;
146     int direct_capable;
147     int driver_major;
148     int driver_minor;
149     int driver_patch;
150     Bool result = True;
151     char *x_driver_name = NULL;
152
153     if (!VA_DRIQueryExtension(ctx->x11_dpy, &eventBase, &errorBase)) {
154         va_errorMessage("VA_DRIQueryExtension failed\n");
155         return VA_STATUS_ERROR_UNKNOWN;
156     }
157     
158     if (result)
159     {
160         result = VA_DRIQueryDirectRenderingCapable(ctx->x11_dpy, ctx->x11_screen, &direct_capable);
161         if (!result)
162         {
163             va_errorMessage("VA_DRIQueryDirectRenderingCapable failed\n");
164         }
165     }
166     if (result)
167     {
168         result = direct_capable;
169         if (!result)
170         {
171             va_errorMessage("VA_DRIQueryDirectRenderingCapable returned false\n");
172         }
173     }
174     if (result)
175     {
176         result = VA_DRIGetClientDriverName(ctx->x11_dpy, ctx->x11_screen, &driver_major, &driver_minor,
177                                             &driver_patch, &x_driver_name);
178         if (!result)
179         {
180             va_errorMessage("VA_DRIGetClientDriverName returned false\n");
181         }
182     }
183     if (result)
184     {
185         vaStatus = VA_STATUS_SUCCESS;
186         va_infoMessage("VA_DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
187              driver_major, driver_minor, driver_patch, x_driver_name, ctx->x11_screen);
188         if (driver_name)
189             *driver_name = strdup(x_driver_name);
190     }
191     if (x_driver_name)
192         XFree(x_driver_name);
193
194     return vaStatus;
195 }
196
197 static VAStatus va_DisplayContextGetDriverName (
198     VADisplayContextP pDisplayContext,
199     char **driver_name
200 )
201 {
202     VADriverContextP ctx = pDisplayContext->pDriverContext;
203     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
204     int direct_capable;
205     int driver_major;
206     int driver_minor;
207     int driver_patch;
208     Bool result = True;
209     char *x_driver_name = NULL;
210
211     if (driver_name)
212         *driver_name = NULL;
213     
214     vaStatus = va_DRI2GetDriverName(pDisplayContext, driver_name);
215     if (vaStatus != VA_STATUS_SUCCESS)
216         vaStatus = va_DRIGetDriverName(pDisplayContext, driver_name);
217
218     if ((vaStatus == VA_STATUS_SUCCESS)
219         && geteuid() == getuid())
220     {
221         /* don't allow setuid apps to use LIBVA_DRIVER_NAME */
222         if (getenv("LIBVA_DRIVER_NAME"))
223         {
224             /* For easier debugging */
225             if (*driver_name)
226                 XFree(*driver_name);
227             
228             *driver_name = strdup(getenv("LIBVA_DRIVER_NAME"));
229             return VA_STATUS_SUCCESS;
230         }
231     }
232     
233     return vaStatus;
234 }
235
236 int vaDisplayIsValid(VADisplay dpy)
237 {
238   VADisplayContextP tmp=NULL;
239   VADisplayContextP pDisplayContext = pDisplayContexts;
240
241   while (pDisplayContext)
242   {
243       if (pDisplayContext == (VADisplayContextP)dpy)
244       {
245           tmp = (VADisplay)pDisplayContext;
246           break;
247       }
248       pDisplayContext = pDisplayContext->pNext;
249   }
250
251   if (!tmp)
252       return 0;
253   
254   return tmp->vaIsValid(pDisplayContext);
255 }
256
257
258 VADisplay vaGetDisplay (
259     Display *native_dpy /* implementation specific */
260 )
261 {
262   VADisplay dpy = NULL;
263   VADisplayContextP pDisplayContext = pDisplayContexts;
264
265   if (!native_dpy)
266       return NULL;
267
268   while (pDisplayContext)
269   {
270       if (pDisplayContext->pDriverContext &&
271           pDisplayContext->pDriverContext->x11_dpy == native_dpy)
272       {
273           dpy = (VADisplay)pDisplayContext;
274           break;
275       }
276       pDisplayContext = pDisplayContext->pNext;
277   }
278
279   if (!dpy)
280   {
281       /* create new entry */
282       VADriverContextP pDriverContext;
283       pDisplayContext = calloc(1, sizeof(*pDisplayContext));
284       pDriverContext  = calloc(1, sizeof(*pDriverContext));
285       if (pDisplayContext && pDriverContext)
286       {
287           pDriverContext->old_pNext        = (void *)(unsigned long)0xdeadbeef;
288           pDriverContext->x11_dpy          = native_dpy;
289           pDisplayContext->pNext           = pDisplayContexts;
290           pDisplayContext->pDriverContext  = pDriverContext;
291           pDisplayContext->vaIsValid       = va_DisplayContextIsValid;
292           pDisplayContext->vaDestroy       = va_DisplayContextDestroy;
293           pDisplayContext->vaGetDriverName = va_DisplayContextGetDriverName;
294           pDisplayContexts                 = pDisplayContext;
295           pDriverContext->dri_state        = calloc(1, sizeof(struct dri_state));
296           dpy                              = (VADisplay)pDisplayContext;
297       }
298       else
299       {
300           if (pDisplayContext)
301               free(pDisplayContext);
302           if (pDriverContext)
303               free(pDriverContext);
304       }
305   }
306   
307   return dpy;
308 }