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