1 /*
2  * Copyright (c) 2011 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 
26 #include <sys/mman.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/ioctl.h>
30 #include <fcntl.h>
31 #ifdef ANDROID
32 #include <linux/ion.h>
33 #endif
34 #include <va/va_tpi.h>
35 #include "psb_drv_video.h"
36 #include "psb_drv_debug.h"
37 #include "psb_surface.h"
38 #include "psb_surface_attrib.h"
39 
40 
41 #define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
42 
43 #define CONFIG(id)  ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
44 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
45 #define SURFACE(id)    ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
46 #define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
47 
48 
49 /*
50  * Create surface
51  */
psb_surface_create_from_ub(psb_driver_data_p driver_data,int width,int height,int fourcc,VASurfaceAttributeTPI * graphic_buffers,psb_surface_p psb_surface,void * vaddr,unsigned flags)52 VAStatus psb_surface_create_from_ub(
53     psb_driver_data_p driver_data,
54     int width, int height, int fourcc,
55     VASurfaceAttributeTPI *graphic_buffers,
56     psb_surface_p psb_surface, /* out */
57     void *vaddr,
58     unsigned flags
59 )
60 {
61     int ret = 0;
62 
63     if ((fourcc == VA_FOURCC_NV12) || (fourcc == VA_FOURCC_YV16) || (fourcc == VA_FOURCC_IYUV) || (fourcc == VA_FOURCC_RGBA)) {
64         if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) {
65             return VA_STATUS_ERROR_ALLOCATION_FAILED;
66         }
67 
68         psb_surface->stride = graphic_buffers->luma_stride;
69         if (0) {
70             ;
71         } else if (512 == graphic_buffers->luma_stride) {
72             psb_surface->stride_mode = STRIDE_512;
73         } else if (1024 == graphic_buffers->luma_stride) {
74             psb_surface->stride_mode = STRIDE_1024;
75         } else if (1280 == graphic_buffers->luma_stride) {
76             psb_surface->stride_mode = STRIDE_1280;
77 #ifdef PSBVIDEO_MSVDX_DEC_TILING
78             if (graphic_buffers->tiling) {
79                 psb_surface->stride_mode = STRIDE_2048;
80                 psb_surface->stride = 2048;
81             }
82 #endif
83         } else if (2048 == graphic_buffers->luma_stride) {
84             psb_surface->stride_mode = STRIDE_2048;
85         } else if (4096 == graphic_buffers->luma_stride) {
86             psb_surface->stride_mode = STRIDE_4096;
87         } else {
88             psb_surface->stride_mode = STRIDE_NA;
89         }
90         if (psb_surface->stride != graphic_buffers->luma_stride) {
91             return VA_STATUS_ERROR_ALLOCATION_FAILED;
92         }
93 
94         psb_surface->luma_offset = 0;
95         psb_surface->chroma_offset = psb_surface->stride * height;
96 
97         if (VA_FOURCC_NV12 == fourcc) {
98             psb_surface->size = ((psb_surface->stride * height) * 3) / 2;
99             psb_surface->extra_info[4] = VA_FOURCC_NV12;
100         }
101         else if (VA_FOURCC_YV16 == fourcc) {
102             psb_surface->size = (psb_surface->stride * height) * 2;
103             psb_surface->extra_info[4] = VA_FOURCC_YV16;
104         }
105         else if (VA_FOURCC_IYUV == fourcc) {
106             psb_surface->size = ((psb_surface->stride * height) * 3) / 2;
107             psb_surface->extra_info[4] = VA_FOURCC_IYUV;
108         }
109 	else if (VA_FOURCC_RGBA == fourcc) {
110             psb_surface->size = (psb_surface->stride * height) * 4;
111             psb_surface->extra_info[4] = VA_FOURCC_RGBA;
112         }
113 
114         psb_surface->extra_info[8] = psb_surface->extra_info[4];
115 
116     } else {
117         return VA_STATUS_ERROR_ALLOCATION_FAILED;
118     }
119 #ifdef PSBVIDEO_MSVDX_DEC_TILING
120     if (graphic_buffers->tiling)
121         ret = psb_buffer_create_from_ub(driver_data, psb_surface->size,
122                 psb_bt_mmu_tiling, &psb_surface->buf,
123                 vaddr, 0);
124     else
125 #endif
126         ret = psb_buffer_create_from_ub(driver_data, psb_surface->size,
127                 psb_bt_surface, &psb_surface->buf,
128                 vaddr, flags);
129 
130     return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS;
131 }
132 
133 #if 0
134 VAStatus psb_CreateSurfaceFromV4L2Buf(
135     VADriverContextP ctx,
136     int v4l2_fd,         /* file descriptor of V4L2 device */
137     struct v4l2_format *v4l2_fmt,       /* format of V4L2 */
138     struct v4l2_buffer *v4l2_buf,       /* V4L2 buffer */
139     VASurfaceID *surface        /* out */
140 )
141 {
142     INIT_DRIVER_DATA;
143     VAStatus vaStatus = VA_STATUS_SUCCESS;
144     int surfaceID;
145     object_surface_p obj_surface;
146     psb_surface_p psb_surface;
147     int width, height, buf_stride, buf_offset, size;
148     unsigned long *user_ptr = NULL;
149 
150     if (IS_MRST(driver_data) == 0 && IS_MFLD(driver_data) == 0) {
151         drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaceFromV4L2Buf isn't supported on non-MRST platform\n");
152         return VA_STATUS_ERROR_UNKNOWN;
153     }
154 
155     /* Todo:
156      * sanity check if the v4l2 device on MRST is supported
157      */
158     if (V4L2_MEMORY_USERPTR == v4l2_buf->memory) {
159         unsigned long tmp = (unsigned long)(v4l2_buf->m.userptr);
160 
161         if (tmp & 0xfff) {
162             drv_debug_msg(VIDEO_DEBUG_ERROR, "The buffer address 0x%08x must be page aligned\n", tmp);
163             return VA_STATUS_ERROR_UNKNOWN;
164         }
165     }
166 
167     surfaceID = object_heap_allocate(&driver_data->surface_heap);
168     obj_surface = SURFACE(surfaceID);
169     CHECK_ALLOCATION(obj_surface);
170 
171     MEMSET_OBJECT(obj_surface, struct object_surface_s);
172 
173     width = v4l2_fmt->fmt.pix.width;
174     height = v4l2_fmt->fmt.pix.height;
175 
176     buf_stride = width; /* ? */
177     buf_offset = v4l2_buf->m.offset;
178     size = v4l2_buf->length;
179 
180     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create Surface from V4L2 buffer: %dx%d, stride=%d, buffer offset=0x%08x, size=%d\n",
181                              width, height, buf_stride, buf_offset, size);
182 
183     obj_surface->surface_id = surfaceID;
184     *surface = surfaceID;
185     obj_surface->context_id = -1;
186     obj_surface->width = width;
187     obj_surface->height = height;
188     obj_surface->subpictures = NULL;
189     obj_surface->subpic_count = 0;
190     obj_surface->derived_imgcnt = 0;
191     obj_surface->display_timestamp = 0;
192 
193     psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
194     if (NULL == psb_surface) {
195         object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
196         obj_surface->surface_id = VA_INVALID_SURFACE;
197 
198         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
199 
200         DEBUG_FAILURE;
201 
202         return vaStatus;
203     }
204 
205 #if PSB_MFLD_DUMMY_CODE
206     /* current assume it is NV12 */
207     if (IS_MRST(driver_data))
208         vaStatus = psb_surface_create_camera(driver_data, width, height, buf_stride, size, psb_surface, 1, buf_offset);
209     else {
210         if (V4L2_MEMORY_USERPTR == v4l2_buf->memory)
211             user_ptr = (unsigned long *)(v4l2_buf->m.userptr);
212         else {
213             user_ptr = mmap(NULL /* start anywhere */ ,
214                             v4l2_buf->length,
215                             PROT_READ ,
216                             MAP_SHARED /* recommended */ ,
217                             v4l2_fd, v4l2_buf->m.offset);
218         }
219 
220         if (NULL != user_ptr && MAP_FAILED != user_ptr)
221             vaStatus = psb_surface_create_camera_from_ub(driver_data, width, height,
222                        buf_stride, size, psb_surface, 1, buf_offset, user_ptr);
223         else {
224             DEBUG_FAILURE;
225             vaStatus = VA_STATUS_ERROR_UNKNOWN;
226         }
227     }
228 #else
229         vaStatus = VA_STATUS_ERROR_UNKNOWN;
230 #endif
231 
232 
233     if (VA_STATUS_SUCCESS != vaStatus) {
234         free(psb_surface);
235         object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
236         obj_surface->surface_id = VA_INVALID_SURFACE;
237 
238         DEBUG_FAILURE;
239 
240         return vaStatus;
241     }
242 
243     memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
244     psb_surface->extra_info[4] = VA_FOURCC_NV12; /* temp treat is as IYUV */
245 
246     obj_surface->psb_surface = psb_surface;
247 
248     /* Error recovery */
249     if (VA_STATUS_SUCCESS != vaStatus) {
250         object_surface_p obj_surface = SURFACE(*surface);
251         psb__destroy_surface(driver_data, obj_surface);
252         *surface = VA_INVALID_SURFACE;
253     }
254 
255     return vaStatus;
256 }
257 #endif
258 
259 
psb_CreateSurfacesForUserPtr(VADriverContextP ctx,int Width,int Height,int format,int num_surfaces,VASurfaceID * surface_list,unsigned size,unsigned int fourcc,unsigned int luma_stride,unsigned int chroma_u_stride,unsigned int chroma_v_stride,unsigned int luma_offset,unsigned int chroma_u_offset,unsigned int chroma_v_offset,unsigned int tiling)260 VAStatus psb_CreateSurfacesForUserPtr(
261     VADriverContextP ctx,
262     int Width,
263     int Height,
264     int format,
265     int num_surfaces,
266     VASurfaceID *surface_list,       /* out */
267     unsigned size, /* total buffer size need to be allocated */
268     unsigned int fourcc, /* expected fourcc */
269     unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
270     unsigned int chroma_u_stride, /* chroma stride */
271     unsigned int chroma_v_stride,
272     unsigned int luma_offset, /* could be 0 */
273     unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
274     unsigned int chroma_v_offset,
275     unsigned int tiling
276 )
277 {
278     INIT_DRIVER_DATA
279     VAStatus vaStatus = VA_STATUS_SUCCESS;
280     int i, height_origin;
281     unsigned long buffer_stride;
282 
283     /* silient compiler warning */
284     unsigned int width = (unsigned int)Width;
285     unsigned int height = (unsigned int)Height;
286 
287     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create surface: width %d, height %d, format 0x%08x"
288                              "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x"
289                              "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d"
290                              "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n",
291                              width, height, format,
292                              num_surfaces, size, fourcc,
293                              luma_stride, chroma_u_stride, chroma_v_stride,
294                              luma_offset, chroma_u_offset, chroma_v_offset);
295 
296     CHECK_INVALID_PARAM(num_surfaces <= 0);
297     CHECK_SURFACE(surface_list);
298 
299     /* We only support one format */
300     if ((VA_RT_FORMAT_YUV420 != format) && (VA_RT_FORMAT_RGB32 != format)) {
301         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
302         DEBUG_FAILURE;
303         return vaStatus;
304     }
305 
306     /* We only support NV12 */
307     if ((VA_RT_FORMAT_YUV420 == format) && (fourcc != VA_FOURCC_NV12)) {
308         drv_debug_msg(VIDEO_DEBUG_ERROR, "Only support NV12 format\n");
309         return VA_STATUS_ERROR_UNKNOWN;
310     }
311 
312     vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
313     CHECK_VASTATUS();
314 
315     if (VA_RT_FORMAT_YUV420 == format) {
316     CHECK_INVALID_PARAM((size < width * height * 1.5) ||
317         (luma_stride < width) ||
318         (chroma_u_stride * 2 < width) ||
319         (chroma_v_stride * 2 < width) ||
320         (chroma_u_offset < luma_offset + width * height) ||
321         (chroma_v_offset < luma_offset + width * height));
322     } else if (VA_RT_FORMAT_RGB32 == format) {
323     CHECK_INVALID_PARAM((size < width * height * 4) ||
324         (luma_stride < width) ||
325         (chroma_u_stride * 2 < width) ||
326         (chroma_v_stride * 2 < width) ||
327         (chroma_u_offset < luma_offset + width * height) ||
328         (chroma_v_offset < luma_offset + width * height));
329     }
330 
331     height_origin = height;
332 
333     for (i = 0; i < num_surfaces; i++) {
334         int surfaceID;
335         object_surface_p obj_surface;
336         psb_surface_p psb_surface;
337 
338         surfaceID = object_heap_allocate(&driver_data->surface_heap);
339         obj_surface = SURFACE(surfaceID);
340         if (NULL == obj_surface) {
341             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
342             DEBUG_FAILURE;
343             break;
344         }
345         MEMSET_OBJECT(obj_surface, struct object_surface_s);
346 
347         obj_surface->surface_id = surfaceID;
348         surface_list[i] = surfaceID;
349         obj_surface->context_id = -1;
350         obj_surface->width = width;
351         obj_surface->height = height;
352         obj_surface->width_r = width;
353         obj_surface->height_r = height;
354         obj_surface->height_origin = height_origin;
355 	obj_surface->is_ref_surface = 0;
356 
357         psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
358         if (NULL == psb_surface) {
359             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
360             obj_surface->surface_id = VA_INVALID_SURFACE;
361 
362             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
363 
364             DEBUG_FAILURE;
365             break;
366         }
367 
368 
369         vaStatus = psb_surface_create_for_userptr(driver_data, width, height,
370                    size,
371                    fourcc,
372                    luma_stride,
373                    chroma_u_stride,
374                    chroma_v_stride,
375                    luma_offset,
376                    chroma_u_offset,
377                    chroma_v_offset,
378                    psb_surface
379                                                  );
380 
381         if (VA_STATUS_SUCCESS != vaStatus) {
382             free(psb_surface);
383             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
384             obj_surface->surface_id = VA_INVALID_SURFACE;
385 
386             DEBUG_FAILURE;
387             break;
388         }
389         buffer_stride = psb_surface->stride;
390         /* by default, surface fourcc is NV12 */
391         memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
392         psb_surface->extra_info[4] = fourcc;
393         psb_surface->extra_info[8] = fourcc;
394 #ifdef PSBVIDEO_MSVDX_DEC_TILING
395 	psb_surface->extra_info[7] = tiling;
396 #endif
397         obj_surface->psb_surface = psb_surface;
398     }
399 
400     /* Error recovery */
401     if (VA_STATUS_SUCCESS != vaStatus) {
402         /* surface_list[i-1] was the last successful allocation */
403         for (; i--;) {
404             object_surface_p obj_surface = SURFACE(surface_list[i]);
405             psb__destroy_surface(driver_data, obj_surface);
406             surface_list[i] = VA_INVALID_SURFACE;
407         }
408     }
409 
410 
411     return vaStatus;
412 }
413 
psb_CreateSurfaceFromKBuf(VADriverContextP ctx,int _width,int _height,int format,VASurfaceID * surface,unsigned int kbuf_handle,unsigned size,unsigned int kBuf_fourcc,unsigned int luma_stride,unsigned int chroma_u_stride,unsigned int chroma_v_stride,unsigned int luma_offset,unsigned int chroma_u_offset,unsigned int chroma_v_offset,unsigned int tiling)414 VAStatus  psb_CreateSurfaceFromKBuf(
415     VADriverContextP ctx,
416     int _width,
417     int _height,
418     int format,
419     VASurfaceID *surface,       /* out */
420     unsigned int kbuf_handle, /* kernel buffer handle*/
421     unsigned size, /* kernel buffer size */
422     unsigned int kBuf_fourcc, /* expected fourcc */
423     unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
424     unsigned int chroma_u_stride, /* chroma stride */
425     unsigned int chroma_v_stride,
426     unsigned int luma_offset, /* could be 0 */
427     unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
428     unsigned int chroma_v_offset,
429     unsigned int tiling
430 )
431 {
432     INIT_DRIVER_DATA
433     VAStatus vaStatus = VA_STATUS_SUCCESS;
434     unsigned long buffer_stride;
435 
436     /* silient compiler warning */
437     unsigned int width = (unsigned int)_width;
438     unsigned int height = (unsigned int)_height;
439 
440     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create surface: width %d, height %d, format 0x%08x"
441                              "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x"
442                              "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d"
443                              "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n",
444                              width, height, format,
445                              size, kBuf_fourcc,
446                              luma_stride, chroma_u_stride, chroma_v_stride,
447                              luma_offset, chroma_u_offset, chroma_v_offset);
448 
449     CHECK_SURFACE(surface);
450 
451     /* We only support one format */
452     if (VA_RT_FORMAT_YUV420 != format) {
453         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
454         DEBUG_FAILURE;
455         return vaStatus;
456     }
457 
458     /* We only support NV12/YV12 */
459 
460     if ((VA_RT_FORMAT_YUV420 == format) && (kBuf_fourcc != VA_FOURCC_NV12)) {
461         drv_debug_msg(VIDEO_DEBUG_ERROR, "Only support NV12 format\n");
462         return VA_STATUS_ERROR_UNKNOWN;
463     }
464     /*
465     vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
466     CHECK_VASTATUS();
467     */
468 
469     CHECK_INVALID_PARAM((size < width * height * 1.5) ||
470         (luma_stride < width) ||
471         (chroma_u_stride * 2 < width) ||
472         (chroma_v_stride * 2 < width) ||
473         (chroma_u_offset < luma_offset + width * height) ||
474         (chroma_v_offset < luma_offset + width * height));
475 
476     int surfaceID;
477     object_surface_p obj_surface;
478     psb_surface_p psb_surface;
479 
480     surfaceID = object_heap_allocate(&driver_data->surface_heap);
481     obj_surface = SURFACE(surfaceID);
482     CHECK_ALLOCATION(obj_surface);
483 
484     MEMSET_OBJECT(obj_surface, struct object_surface_s);
485 
486     obj_surface->surface_id = surfaceID;
487     *surface = surfaceID;
488     obj_surface->context_id = -1;
489     obj_surface->width = width;
490     obj_surface->height = height;
491     obj_surface->width_r = width;
492     obj_surface->height_r = height;
493     obj_surface->height_origin = height;
494     obj_surface->is_ref_surface = 0;
495 
496     psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
497     if (NULL == psb_surface) {
498         object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
499         obj_surface->surface_id = VA_INVALID_SURFACE;
500 
501         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
502 
503         DEBUG_FAILURE;
504         return vaStatus;
505     }
506 
507     vaStatus = psb_surface_create_from_kbuf(driver_data, width, height,
508                                             size,
509                                             kBuf_fourcc,
510                                             kbuf_handle,
511                                             luma_stride,
512                                             chroma_u_stride,
513                                             chroma_v_stride,
514                                             luma_offset,
515                                             chroma_u_offset,
516                                             chroma_v_offset,
517                                             psb_surface);
518 
519     if (VA_STATUS_SUCCESS != vaStatus) {
520         free(psb_surface);
521         object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
522         obj_surface->surface_id = VA_INVALID_SURFACE;
523 
524         DEBUG_FAILURE;
525         return vaStatus;
526     }
527     buffer_stride = psb_surface->stride;
528     /* by default, surface fourcc is NV12 */
529     memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
530     psb_surface->extra_info[4] = kBuf_fourcc;
531     psb_surface->extra_info[8] = kBuf_fourcc;
532 #ifdef PSBVIDEO_MSVDX_DEC_TILING
533     psb_surface->extra_info[7] = tiling;
534 #endif
535     obj_surface->psb_surface = psb_surface;
536 
537     /* Error recovery */
538     if (VA_STATUS_SUCCESS != vaStatus) {
539         object_surface_p obj_surface = SURFACE(surfaceID);
540         psb__destroy_surface(driver_data, obj_surface);
541         *surface = VA_INVALID_SURFACE;
542     }
543 
544     return vaStatus;
545 }
546 
psb_CreateSurfaceFromUserspace(VADriverContextP ctx,int width,int height,int format,int num_surfaces,VASurfaceID * surface_list,VASurfaceAttributeTPI * attribute_tpi)547 VAStatus  psb_CreateSurfaceFromUserspace(
548         VADriverContextP ctx,
549         int width,
550         int height,
551         int format,
552         int num_surfaces,
553         VASurfaceID *surface_list,        /* out */
554         VASurfaceAttributeTPI *attribute_tpi
555 )
556 {
557     INIT_DRIVER_DATA;
558     VAStatus vaStatus = VA_STATUS_SUCCESS;
559 #ifdef ANDROID
560     unsigned int *vaddr;
561     unsigned long fourcc;
562     int surfaceID;
563     object_surface_p obj_surface;
564     psb_surface_p psb_surface;
565     int i;
566 
567     switch (format) {
568     case VA_RT_FORMAT_YUV422:
569         fourcc = VA_FOURCC_YV16;
570         break;
571     case VA_RT_FORMAT_YUV420:
572     default:
573         fourcc = VA_FOURCC_NV12;
574         break;
575     }
576 
577     for (i=0; i < num_surfaces; i++) {
578         vaddr = (unsigned int *)(attribute_tpi->buffers[i]);
579         surfaceID = object_heap_allocate(&driver_data->surface_heap);
580         obj_surface = SURFACE(surfaceID);
581         if (NULL == obj_surface) {
582             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
583             DEBUG_FAILURE;
584             break;
585         }
586         MEMSET_OBJECT(obj_surface, struct object_surface_s);
587 
588         obj_surface->surface_id = surfaceID;
589         surface_list[i] = surfaceID;
590         obj_surface->context_id = -1;
591         obj_surface->width = attribute_tpi->width;
592         obj_surface->height = attribute_tpi->height;
593         obj_surface->width_r = attribute_tpi->width;
594         obj_surface->height_r = attribute_tpi->height;
595 	obj_surface->is_ref_surface = 0;
596 
597         psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
598         if (NULL == psb_surface) {
599             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
600             obj_surface->surface_id = VA_INVALID_SURFACE;
601             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
602             DEBUG_FAILURE;
603             break;
604         }
605 
606         if (attribute_tpi->type == VAExternalMemoryNoneCacheUserPointer)
607             vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
608                     attribute_tpi, psb_surface, vaddr, PSB_USER_BUFFER_UNCACHED);
609         else
610             vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
611                     attribute_tpi, psb_surface, vaddr, 0);
612         obj_surface->psb_surface = psb_surface;
613 
614         if (VA_STATUS_SUCCESS != vaStatus) {
615             free(psb_surface);
616             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
617             obj_surface->surface_id = VA_INVALID_SURFACE;
618             DEBUG_FAILURE;
619             break;
620         }
621         /* by default, surface fourcc is NV12 */
622         memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
623         psb_surface->extra_info[4] = fourcc;
624         psb_surface->extra_info[8] = fourcc;
625         obj_surface->psb_surface = psb_surface;
626 
627         /* Error recovery */
628         if (VA_STATUS_SUCCESS != vaStatus) {
629             object_surface_p obj_surface = SURFACE(surfaceID);
630             psb__destroy_surface(driver_data, obj_surface);
631         }
632     }
633 #endif
634     return vaStatus;
635 }
636 
psb_CreateSurfaceFromION(VADriverContextP ctx,int width,int height,int format,int num_surfaces,VASurfaceID * surface_list,VASurfaceAttributeTPI * attribute_tpi)637 VAStatus  psb_CreateSurfaceFromION(
638         VADriverContextP ctx,
639         int width,
640         int height,
641         int format,
642         int num_surfaces,
643         VASurfaceID *surface_list,        /* out */
644         VASurfaceAttributeTPI *attribute_tpi
645 )
646 {
647     INIT_DRIVER_DATA;
648     VAStatus vaStatus = VA_STATUS_SUCCESS;
649 #ifdef ANDROID
650     unsigned int *vaddr = NULL;
651     unsigned long fourcc;
652     int surfaceID;
653     object_surface_p obj_surface;
654     psb_surface_p psb_surface;
655     int i;
656     unsigned int source_size = 0;
657     int ion_fd = 0;
658     int ion_ret = 0;
659     struct ion_fd_data ion_source_share;
660 
661     switch (format) {
662     case VA_RT_FORMAT_YUV422:
663         fourcc = VA_FOURCC_YV16;
664         break;
665     case VA_RT_FORMAT_YUV420:
666     default:
667         fourcc = VA_FOURCC_NV12;
668         break;
669     }
670 
671     ion_fd = open("/dev/ion", O_RDWR);
672     if (ion_fd < 0) {
673         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to open the ion device!\n", __FUNCTION__);
674         return VA_STATUS_ERROR_UNKNOWN;
675     }
676 
677     for (i=0; i < num_surfaces; i++) {
678         ion_source_share.handle = 0;
679         ion_source_share.fd = (int)(attribute_tpi->buffers[i]);
680         ion_ret = ioctl(ion_fd, ION_IOC_IMPORT, &ion_source_share);
681             if ((ion_ret < 0) || (0 == ion_source_share.handle)) {
682             close(ion_fd);
683             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to import the ion fd!\n", __FUNCTION__);
684             return VA_STATUS_ERROR_UNKNOWN;
685         }
686 
687         if (VA_FOURCC_NV12 == fourcc)
688             source_size = attribute_tpi->width * attribute_tpi->height * 1.5;
689         else
690             source_size = attribute_tpi->width * attribute_tpi->height * 2;
691 
692         vaddr = mmap(NULL, source_size, PROT_READ|PROT_WRITE, MAP_SHARED, ion_source_share.fd, 0);
693         if (MAP_FAILED == vaddr) {
694             close(ion_fd);
695             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to mmap the ion buffer!\n", __FUNCTION__);
696             return VA_STATUS_ERROR_UNKNOWN;
697         }
698 
699         surfaceID = object_heap_allocate(&driver_data->surface_heap);
700         obj_surface = SURFACE(surfaceID);
701         if (NULL == obj_surface) {
702             close(ion_fd);
703             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
704             DEBUG_FAILURE;
705             break;
706         }
707         MEMSET_OBJECT(obj_surface, struct object_surface_s);
708 
709         obj_surface->surface_id = surfaceID;
710         surface_list[i] = surfaceID;
711         obj_surface->context_id = -1;
712         obj_surface->width = attribute_tpi->width;
713         obj_surface->height = attribute_tpi->height;
714         obj_surface->width_r = attribute_tpi->width;
715         obj_surface->height_r = attribute_tpi->height;
716 	obj_surface->is_ref_surface = 0;
717 
718         psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
719         if (NULL == psb_surface) {
720             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
721             obj_surface->surface_id = VA_INVALID_SURFACE;
722             close(ion_fd);
723             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
724             DEBUG_FAILURE;
725             break;
726         }
727 
728         vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
729                 attribute_tpi, psb_surface, vaddr, 0);
730         obj_surface->psb_surface = psb_surface;
731 
732         if (VA_STATUS_SUCCESS != vaStatus) {
733             free(psb_surface);
734             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
735             obj_surface->surface_id = VA_INVALID_SURFACE;
736             close(ion_fd);
737             DEBUG_FAILURE;
738             break;
739         }
740         /* by default, surface fourcc is NV12 */
741         memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
742         psb_surface->extra_info[4] = fourcc;
743         psb_surface->extra_info[8] = fourcc;
744         obj_surface->psb_surface = psb_surface;
745 
746         /* Error recovery */
747         if (VA_STATUS_SUCCESS != vaStatus) {
748             object_surface_p obj_surface = SURFACE(surfaceID);
749             psb__destroy_surface(driver_data, obj_surface);
750             close(ion_fd);
751         }
752 
753         vaddr = NULL;
754     }
755 
756     close(ion_fd);
757 #endif
758     return vaStatus;
759 }
760 
psb_CreateSurfacesWithAttribute(VADriverContextP ctx,int width,int height,int format,int num_surfaces,VASurfaceID * surface_list,VASurfaceAttributeTPI * attribute_tpi)761 VAStatus psb_CreateSurfacesWithAttribute(
762     VADriverContextP ctx,
763     int width,
764     int height,
765     int format,
766     int num_surfaces,
767     VASurfaceID *surface_list,        /* out */
768     VASurfaceAttributeTPI *attribute_tpi
769 )
770 {
771     VAStatus vaStatus = VA_STATUS_SUCCESS;
772     int i;
773     int tiling;
774 
775     CHECK_INVALID_PARAM(attribute_tpi == NULL);
776 
777     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create %d surface(%dx%d) with type %d, tiling is %d\n",
778             num_surfaces, width, height, attribute_tpi->type, attribute_tpi->tiling);
779 
780     tiling = attribute_tpi->tiling;
781     switch (attribute_tpi->type) {
782     case VAExternalMemoryNULL:
783         vaStatus = psb_CreateSurfacesForUserPtr(ctx, width, height, format, num_surfaces, surface_list,
784                                      attribute_tpi->size, attribute_tpi->pixel_format,
785                                      attribute_tpi->luma_stride, attribute_tpi->chroma_u_stride,
786                                      attribute_tpi->chroma_v_stride, attribute_tpi->luma_offset,
787                                      attribute_tpi->chroma_u_offset, attribute_tpi->chroma_v_offset,
788                                      attribute_tpi->tiling);
789         return vaStatus;
790 #ifdef ANDROID
791     case VAExternalMemoryNoneCacheUserPointer:
792 #endif
793     case VAExternalMemoryUserPointer:
794         vaStatus = psb_CreateSurfaceFromUserspace(ctx, width, height,
795                                                  format, num_surfaces, surface_list,
796                                                  attribute_tpi);
797         return vaStatus;
798     case VAExternalMemoryKernelDRMBufffer:
799         for (i=0; i < num_surfaces; i++) {
800             vaStatus = psb_CreateSurfaceFromKBuf(
801                 ctx, width, height, format, &surface_list[i],
802                 attribute_tpi->buffers[i],
803                 attribute_tpi->size, attribute_tpi->pixel_format,
804                 attribute_tpi->luma_stride, attribute_tpi->chroma_u_stride,
805                 attribute_tpi->chroma_v_stride, attribute_tpi->luma_offset,
806                 attribute_tpi->chroma_u_offset, attribute_tpi->chroma_v_offset, tiling);
807             CHECK_VASTATUS();
808         }
809         return vaStatus;
810     case VAExternalMemoryAndroidGrallocBuffer:
811         vaStatus = psb_CreateSurfacesFromGralloc(ctx, width, height,
812                                                  format, num_surfaces, surface_list,
813                                                  (PsbSurfaceAttributeTPI *)attribute_tpi);
814         return vaStatus;
815 #ifdef ANDROID
816     case VAExternalMemoryIONSharedFD:
817         vaStatus = psb_CreateSurfaceFromION(ctx, width, height,
818                                                  format, num_surfaces, surface_list,
819                                                  attribute_tpi);
820         return vaStatus;
821 #endif
822     default:
823         return VA_STATUS_ERROR_INVALID_PARAMETER;
824     }
825 
826     return VA_STATUS_ERROR_INVALID_PARAMETER;
827 }
828