OSDN Git Service

45966570ad663f2ebe7245397060985eb6f71a20
[android-x86/hardware-intel-common-libva.git] / va / android / va_android.cpp
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 "va.h"
27 #include "va_backend.h"
28 #include "va_android.h"
29 #include "va_dricommon.h" /* needs some helper functions from this file */
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <dlfcn.h>
39 #include <errno.h>
40 #ifndef ANDROID
41 #include <libudev.h>
42 #include "drmtest.h"
43 #endif
44
45 #define CHECK_SYMBOL(func) { if (!func) printf("func %s not found\n", #func); return VA_STATUS_ERROR_UNKNOWN; }
46 #define DEVICE_NAME "/dev/card0"
47
48 static VADisplayContextP pDisplayContexts = NULL;
49
50 static int open_device (char *dev_name)
51 {
52   struct stat st;
53   int fd;
54
55   if (-1 == stat (dev_name, &st))
56     {
57       printf ("Cannot identify '%s': %d, %s\n",
58                dev_name, errno, strerror (errno));
59       return -1;
60     }
61
62   if (!S_ISCHR (st.st_mode))
63     {
64       printf ("%s is no device\n", dev_name);
65       return -1;
66     }
67
68   fd = open (dev_name, O_RDWR);
69
70   if (-1 == fd)
71     {
72       fprintf (stderr, "Cannot open '%s': %d, %s\n",
73                dev_name, errno, strerror (errno));
74       return -1;
75     }
76
77   return fd;
78 }
79
80 static int va_DisplayContextIsValid (
81     VADisplayContextP pDisplayContext
82 )
83 {
84     VADisplayContextP ctx = pDisplayContexts;
85
86     while (ctx)
87     {
88         if (ctx == pDisplayContext && pDisplayContext->pDriverContext)
89             return 1;
90         ctx = ctx->pNext;
91     }
92     return 0;
93 }
94
95 static void va_DisplayContextDestroy (
96     VADisplayContextP pDisplayContext
97 )
98 {
99     VADisplayContextP *ctx = &pDisplayContexts;
100
101     /* Throw away pDisplayContext */
102     while (*ctx)
103     {
104         if (*ctx == pDisplayContext)
105         {
106             *ctx = pDisplayContext->pNext;
107             pDisplayContext->pNext = NULL;
108             break;
109         }
110         ctx = &((*ctx)->pNext);
111     }
112     free(pDisplayContext->pDriverContext->dri_state);
113     free(pDisplayContext->pDriverContext);
114     free(pDisplayContext);
115 }
116
117 #ifdef ANDROID
118 static VAStatus va_DisplayContextGetDriverName (
119     VADisplayContextP pDisplayContext,
120     char **driver_name
121 )
122 {
123     VADriverContextP ctx = pDisplayContext->pDriverContext;
124     struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
125     char *driver_name_env;
126     int vendor_id, device_id;
127     
128     struct {
129         int vendor_id;
130         int device_id;
131         char driver_name[64];
132     } devices[] = {
133         { 0x8086, 0x4100, "pvr" },
134         { 0x8086, 0x0130, "pvr" },
135         { 0x0,    0x0,    "\0" },
136     };
137
138     memset(dri_state, 0, sizeof(*dri_state));
139     dri_state->fd = open_device(DEVICE_NAME);
140     
141     if (dri_state->fd < 0) {
142         fprintf(stderr,"can't open DRM devices\n");
143         return VA_STATUS_ERROR_UNKNOWN;
144     }
145
146     if ((driver_name_env = getenv("LIBVA_DRIVER_NAME")) != NULL
147         && geteuid() == getuid()) {
148         /* don't allow setuid apps to use LIBVA_DRIVER_NAME */
149         *driver_name = strdup(driver_name_env);
150         return VA_STATUS_SUCCESS;
151     } else { /* TBD: other vendor driver names */
152         vendor_id = devices[0].vendor_id;
153         device_id = devices[0].device_id;
154         *driver_name = strdup(devices[0].driver_name);
155     }
156
157     dri_state->driConnectedFlag = VA_DUMMY;
158     
159     return VA_STATUS_SUCCESS;
160 }
161 #else
162 static VAStatus va_DisplayContextGetDriverName (
163     VADisplayContextP pDisplayContext,
164     char **driver_name
165 )
166 {
167     VADriverContextP ctx = pDisplayContext->pDriverContext;
168     struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
169     char *driver_name_env;
170     int vendor_id, device_id;
171     
172     struct {
173         int vendor_id;
174         int device_id;
175         char driver_name[64];
176     } devices[] = {
177         { 0x8086, 0x4100, "pvr" },
178         { 0x8086, 0x0130, "pvr" },
179         { 0x0,    0x0,    "\0" },
180     };
181
182     memset(dri_state, 0, sizeof(*dri_state));
183     dri_state->fd = drm_open_any(&vendor_id, &device_id);
184     
185     if (dri_state->fd < 0) {
186         fprintf(stderr,"can't open DRM devices\n");
187         return VA_STATUS_ERROR_UNKNOWN;
188     }
189     
190     if ((driver_name_env = getenv("LIBVA_DRIVER_NAME")) != NULL
191         && geteuid() == getuid()) {
192         /* don't allow setuid apps to use LIBVA_DRIVER_NAME */
193         *driver_name = strdup(driver_name_env);
194         return VA_STATUS_SUCCESS;
195     } else { /* TBD: other vendor driver names */
196         int i = 0;
197
198         while (devices[i].device_id != 0) {
199             if ((devices[i].vendor_id == vendor_id) &&
200                 (devices[i].device_id == device_id))
201                 break;
202             i++;
203         }
204
205         if (devices[i].device_id != 0)
206             *driver_name = strdup(devices[i].driver_name);
207         else {
208             fprintf(stderr,"device (0x%04x:0x%04x) is not supported\n",
209                     vendor_id, device_id);
210             
211             return VA_STATUS_ERROR_UNKNOWN;
212         }            
213     }
214
215     printf("DRM device is opened, loading driver %s for device 0x%04x:0x%04x\n",
216            driver_name, vendor_id, device_id);
217     
218     dri_state->driConnectedFlag = VA_DUMMY;
219     
220     return VA_STATUS_SUCCESS;
221 }
222 #endif
223
224 VADisplay vaGetDisplay (
225     void *native_dpy /* implementation specific */
226 )
227 {
228   VADisplay dpy = NULL;
229   VADisplayContextP pDisplayContext = pDisplayContexts;
230
231   if (!native_dpy)
232       return NULL;
233
234   while (pDisplayContext)
235   {
236       if (pDisplayContext->pDriverContext &&
237           pDisplayContext->pDriverContext->native_dpy == (void *)native_dpy)
238       {
239           dpy = (VADisplay)pDisplayContext;
240           break;
241       }
242       pDisplayContext = pDisplayContext->pNext;
243   }
244
245
246   if (!dpy)
247   {
248       /* create new entry */
249       VADriverContextP pDriverContext;
250       struct dri_state *dri_state;
251       pDisplayContext = (VADisplayContextP)calloc(1, sizeof(*pDisplayContext));
252       pDriverContext  = (VADriverContextP)calloc(1, sizeof(*pDriverContext));
253       dri_state       = (struct dri_state*)calloc(1, sizeof(*dri_state));
254       if (pDisplayContext && pDriverContext && dri_state)
255       {
256           pDisplayContext->vadpy_magic = VA_DISPLAY_MAGIC;          
257
258           pDriverContext->native_dpy       = (void *)native_dpy;
259           pDisplayContext->pNext           = pDisplayContexts;
260           pDisplayContext->pDriverContext  = pDriverContext;
261           pDisplayContext->vaIsValid       = va_DisplayContextIsValid;
262           pDisplayContext->vaDestroy       = va_DisplayContextDestroy;
263           pDisplayContext->vaGetDriverName = va_DisplayContextGetDriverName;
264           pDisplayContexts                 = pDisplayContext;
265           pDriverContext->dri_state        = dri_state;
266           dpy                              = (VADisplay)pDisplayContext;
267       }
268       else
269       {
270           if (pDisplayContext)
271               free(pDisplayContext);
272           if (pDriverContext)
273               free(pDriverContext);
274           if (dri_state)
275               free(dri_state);
276       }
277   }
278   
279   return dpy;
280 }
281
282 #define CTX(dpy) (((VADisplayContextP)dpy)->pDriverContext)
283 #define CHECK_DISPLAY(dpy) if( !vaDisplayIsValid(dpy) ) { return VA_STATUS_ERROR_INVALID_DISPLAY; }
284
285
286 #ifdef ANDROID
287 VAStatus vaPutSurface (
288     VADisplay dpy,
289     VASurfaceID surface,
290     sp<Surface> draw, /* Android Surface/Window */
291     short srcx,
292     short srcy,
293     unsigned short srcw,
294     unsigned short srch,
295     short destx,
296     short desty,
297     unsigned short destw,
298     unsigned short desth,
299     VARectangle *cliprects, /* client supplied clip list */
300     unsigned int number_cliprects, /* number of clip rects in the clip list */
301     unsigned int flags /* de-interlacing flags */
302 )
303 {
304   VADriverContextP ctx;
305
306   CHECK_DISPLAY(dpy);
307   ctx = CTX(dpy);
308   return ctx->vtable.vaPutSurface( ctx, surface, static_cast<void*>(&draw), srcx, srcy, srcw, srch, 
309                                    destx, desty, destw, desth,
310                                    cliprects, number_cliprects, flags );
311 }
312 #endif