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