Fix va_DisplayContextGetDriverName() to check for LIBVA_DRIVER_NAME first.
[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 *driver_name_env;
210
211     if (driver_name)
212         *driver_name = NULL;
213
214     if ((driver_name_env = getenv("LIBVA_DRIVER_NAME")) != NULL
215         && geteuid() == getuid())
216     {
217         /* don't allow setuid apps to use LIBVA_DRIVER_NAME */
218         *driver_name = strdup(driver_name_env);
219         return VA_STATUS_SUCCESS;
220     }
221
222     vaStatus = va_DRI2GetDriverName(pDisplayContext, driver_name);
223     if (vaStatus != VA_STATUS_SUCCESS)
224         vaStatus = va_DRIGetDriverName(pDisplayContext, driver_name);
225    
226     return vaStatus;
227 }
228
229 int vaDisplayIsValid(VADisplay dpy)
230 {
231   VADisplayContextP tmp=NULL;
232   VADisplayContextP pDisplayContext = pDisplayContexts;
233
234   while (pDisplayContext)
235   {
236       if (pDisplayContext == (VADisplayContextP)dpy)
237       {
238           tmp = (VADisplay)pDisplayContext;
239           break;
240       }
241       pDisplayContext = pDisplayContext->pNext;
242   }
243
244   if (!tmp)
245       return 0;
246   
247   return tmp->vaIsValid(pDisplayContext);
248 }
249
250
251 VADisplay vaGetDisplay (
252     Display *native_dpy /* implementation specific */
253 )
254 {
255   VADisplay dpy = NULL;
256   VADisplayContextP pDisplayContext = pDisplayContexts;
257
258   if (!native_dpy)
259       return NULL;
260
261   while (pDisplayContext)
262   {
263       if (pDisplayContext->pDriverContext &&
264           pDisplayContext->pDriverContext->x11_dpy == native_dpy)
265       {
266           dpy = (VADisplay)pDisplayContext;
267           break;
268       }
269       pDisplayContext = pDisplayContext->pNext;
270   }
271
272   if (!dpy)
273   {
274       /* create new entry */
275       VADriverContextP pDriverContext;
276       pDisplayContext = calloc(1, sizeof(*pDisplayContext));
277       pDriverContext  = calloc(1, sizeof(*pDriverContext));
278       if (pDisplayContext && pDriverContext)
279       {
280           pDriverContext->old_pNext        = (void *)(unsigned long)0xdeadbeef;
281           pDriverContext->x11_dpy          = native_dpy;
282           pDisplayContext->pNext           = pDisplayContexts;
283           pDisplayContext->pDriverContext  = pDriverContext;
284           pDisplayContext->vaIsValid       = va_DisplayContextIsValid;
285           pDisplayContext->vaDestroy       = va_DisplayContextDestroy;
286           pDisplayContext->vaGetDriverName = va_DisplayContextGetDriverName;
287           pDisplayContexts                 = pDisplayContext;
288           pDriverContext->dri_state        = calloc(1, sizeof(struct dri_state));
289           dpy                              = (VADisplay)pDisplayContext;
290       }
291       else
292       {
293           if (pDisplayContext)
294               free(pDisplayContext);
295           if (pDriverContext)
296               free(pDriverContext);
297       }
298   }
299   
300   return dpy;
301 }