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 <va/va_tpi.h>
28 #include "psb_drv_video.h"
29 #include "psb_drv_debug.h"
30 #include "psb_surface.h"
31 #include "psb_surface_attrib.h"
32
33 #include <gralloc.h>
34 #include "android/psb_gralloc.h"
35 #include "android/psb_android_glue.h"
36 #ifndef BAYTRAIL
37 #include <hal/hal_public.h>
38 #endif
39 #include <wsbm/wsbm_manager.h>
40
41 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
42 #define CONFIG(id) ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
43 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
44 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
45 #define BUFFER(id) ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
46 #define SHARE_INFO_INIT_VALUE 0x12345678
47
48 static pthread_mutex_t gralloc_mutex = PTHREAD_MUTEX_INITIALIZER;
49
50 /*FIXME: include hal_public.h instead of define it here*/
51 enum {
52 GRALLOC_SUB_BUFFER0 = 0,
53 GRALLOC_SUB_BUFFER1,
54 GRALLOC_SUB_BUFFER2,
55 GRALLOC_SUB_BUFFER_MAX,
56 };
57
psb_DestroySurfaceGralloc(object_surface_p obj_surface)58 VAStatus psb_DestroySurfaceGralloc(object_surface_p obj_surface)
59 {
60 void *vaddr[GRALLOC_SUB_BUFFER_MAX];
61 int usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER;
62 buffer_handle_t handle = obj_surface->psb_surface->buf.handle;
63 VAStatus vaStatus = VA_STATUS_SUCCESS;
64
65 #ifdef PSBVIDEO_MRFL
66 usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
67 #endif
68
69 pthread_mutex_lock(&gralloc_mutex);
70 if (!gralloc_lock(handle, usage, 0, 0,
71 obj_surface->width, obj_surface->height, (void **)&vaddr[GRALLOC_SUB_BUFFER0])){
72 if (obj_surface->share_info && vaddr[GRALLOC_SUB_BUFFER1] == obj_surface->share_info) {
73 int metadata_rotate = obj_surface->share_info->metadata_rotate;
74 int surface_protected = obj_surface->share_info->surface_protected;
75 int force_output_method = obj_surface->share_info->force_output_method;
76 int bob_deinterlace = obj_surface->share_info->bob_deinterlace;
77
78 memset(obj_surface->share_info, 0, sizeof(struct psb_surface_share_info_s));
79 /* Still need to keep these info so that hwc can get them after suspend/resume cycle */
80 obj_surface->share_info->metadata_rotate = metadata_rotate;
81 obj_surface->share_info->surface_protected = surface_protected;
82 obj_surface->share_info->force_output_method = force_output_method;
83 obj_surface->share_info->bob_deinterlace = bob_deinterlace;
84 }
85 gralloc_unlock(handle);
86
87 if (gralloc_unregister(handle))
88 vaStatus = VA_STATUS_ERROR_UNKNOWN;
89 }
90 pthread_mutex_unlock(&gralloc_mutex);
91
92 return vaStatus;
93 }
94
95 #ifdef BAYTRAIL
psb_CreateSurfacesFromGralloc(VADriverContextP ctx,int width,int height,int format,int num_surfaces,VASurfaceID * surface_list,PsbSurfaceAttributeTPI * attribute_tpi)96 VAStatus psb_CreateSurfacesFromGralloc(
97 VADriverContextP ctx,
98 int width,
99 int height,
100 int format,
101 int num_surfaces,
102 VASurfaceID *surface_list, /* out */
103 PsbSurfaceAttributeTPI *attribute_tpi
104 )
105 {
106 INIT_DRIVER_DATA
107 VAStatus vaStatus = VA_STATUS_SUCCESS;
108 int i, height_origin, usage, buffer_stride = 0;
109 int protected = (VA_RT_FORMAT_PROTECTED & format);
110 unsigned long fourcc;
111 VASurfaceAttributeTPI *external_buffers = NULL;
112 unsigned long handle;
113 int size = num_surfaces * sizeof(unsigned int);
114 void *vaddr;
115
116
117 /* follow are gralloc-buffers */
118 format = format & (~VA_RT_FORMAT_PROTECTED);
119 driver_data->protected = protected;
120
121 CHECK_INVALID_PARAM(num_surfaces <= 0);
122 CHECK_SURFACE(surface_list);
123
124 external_buffers = attribute_tpi;
125
126 ALOGD("format is 0x%x, width is %d, height is %d, num_surfaces is %d.\n", format, width, height, num_surfaces);
127 /* We only support one format */
128 if ((VA_RT_FORMAT_YUV420 != format)
129 && (VA_RT_FORMAT_YUV422 != format)) {
130 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
131 DEBUG_FAILURE;
132 return vaStatus;
133 }
134
135 CHECK_INVALID_PARAM(external_buffers == NULL);
136
137 /*
138 vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
139 CHECK_VASTATUS();
140 */
141 /* Adjust height to be a multiple of 32 (height of macroblock in interlaced mode) */
142 height_origin = height;
143 height = (height + 0x1f) & ~0x1f;
144 ALOGD("external_buffers->pixel_format is 0x%x.\n", external_buffers->pixel_format);
145 /* get native window from the reserved field */
146 driver_data->native_window = (void *)external_buffers->reserved[0];
147
148 for (i = 0; i < num_surfaces; i++) {
149 int surfaceID;
150 object_surface_p obj_surface;
151 psb_surface_p psb_surface;
152
153 surfaceID = object_heap_allocate(&driver_data->surface_heap);
154 obj_surface = SURFACE(surfaceID);
155 if (NULL == obj_surface) {
156 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
157 DEBUG_FAILURE;
158 break;
159 }
160 MEMSET_OBJECT(obj_surface, struct object_surface_s);
161
162 obj_surface->surface_id = surfaceID;
163 surface_list[i] = surfaceID;
164 obj_surface->context_id = -1;
165 obj_surface->width = width;
166 obj_surface->height = height;
167 obj_surface->width_r = width;
168 obj_surface->height_r = height;
169 obj_surface->height_origin = height_origin;
170 obj_surface->is_ref_surface = 0;
171
172 psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
173 if (NULL == psb_surface) {
174 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
175 obj_surface->surface_id = VA_INVALID_SURFACE;
176
177 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
178
179 DEBUG_FAILURE;
180 break;
181 }
182
183 switch (format) {
184 case VA_RT_FORMAT_YUV422:
185 fourcc = VA_FOURCC_YV16;
186 break;
187 case VA_RT_FORMAT_YUV420:
188 default:
189 fourcc = VA_FOURCC_NV12;
190 break;
191 }
192
193 /*hard code the gralloc buffer usage*/
194 usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER;
195
196 /* usage hack for byt */
197 usage |= GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
198 /* usage hack to force pages alloc and CPU/GPU cache flush */
199 usage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
200
201 handle = (unsigned long)external_buffers->buffers[i];
202 pthread_mutex_lock(&gralloc_mutex);
203 if (gralloc_lock(handle, usage, 0, 0, width, height, (void **)&vaddr)) {
204 vaStatus = VA_STATUS_ERROR_UNKNOWN;
205 } else {
206 int cache_flag = PSB_USER_BUFFER_UNCACHED;
207 int buf_fd = gralloc_getbuffd(handle);
208
209 vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
210 external_buffers, psb_surface, vaddr, buf_fd,
211 cache_flag);
212
213 psb_surface->buf.handle = handle;
214 obj_surface->share_info = NULL;
215 gralloc_unlock(handle);
216 }
217 pthread_mutex_unlock(&gralloc_mutex);
218
219 if (VA_STATUS_SUCCESS != vaStatus) {
220 free(psb_surface);
221 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
222 obj_surface->surface_id = VA_INVALID_SURFACE;
223
224 DEBUG_FAILURE;
225 break;
226 }
227 buffer_stride = psb_surface->stride;
228 #ifdef PSBVIDEO_MSVDX_DEC_TILING
229 psb_surface->extra_info[7] = external_buffers->tiling;
230 #endif
231 /* by default, surface fourcc is NV12 */
232 psb_surface->extra_info[4] = fourcc;
233 obj_surface->psb_surface = psb_surface;
234 }
235
236 /* Error recovery */
237 if (VA_STATUS_SUCCESS != vaStatus) {
238 /* surface_list[i-1] was the last successful allocation */
239 for (; i--;) {
240 object_surface_p obj_surface = SURFACE(surface_list[i]);
241 psb__destroy_surface(driver_data, obj_surface);
242 surface_list[i] = VA_INVALID_SURFACE;
243 }
244 drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaces failed\n");
245
246 return vaStatus;
247 }
248
249 return vaStatus;
250 }
251 #else
psb_CreateSurfacesFromGralloc(VADriverContextP ctx,int width,int height,int format,int num_surfaces,VASurfaceID * surface_list,PsbSurfaceAttributeTPI * attribute_tpi)252 VAStatus psb_CreateSurfacesFromGralloc(
253 VADriverContextP ctx,
254 int width,
255 int height,
256 int format,
257 int num_surfaces,
258 VASurfaceID *surface_list, /* out */
259 PsbSurfaceAttributeTPI *attribute_tpi
260 )
261 {
262 INIT_DRIVER_DATA
263 VAStatus vaStatus = VA_STATUS_SUCCESS;
264 int i, height_origin, usage, buffer_stride = 0;
265 int protected = (VA_RT_FORMAT_PROTECTED & format);
266 unsigned long fourcc;
267 PsbSurfaceAttributeTPI *external_buffers = NULL;
268 unsigned long handle;
269 int size = num_surfaces * sizeof(unsigned int);
270 void *vaddr[GRALLOC_SUB_BUFFER_MAX];
271
272 /* follow are gralloc-buffers */
273 format = format & (~VA_RT_FORMAT_PROTECTED);
274 driver_data->protected = protected;
275
276 CHECK_INVALID_PARAM(num_surfaces <= 0);
277 CHECK_SURFACE(surface_list);
278
279 external_buffers = attribute_tpi;
280
281 /* We only support one format */
282 if ((VA_RT_FORMAT_YUV420 != format)
283 && (VA_RT_FORMAT_YUV422 != format)
284 && (VA_RT_FORMAT_RGB32 != format)) {
285 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
286 DEBUG_FAILURE;
287 return vaStatus;
288 }
289
290 CHECK_INVALID_PARAM(external_buffers == NULL);
291
292 /*
293 vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
294 CHECK_VASTATUS();
295 */
296 /* Adjust height to be a multiple of 32 (height of macroblock in interlaced mode) */
297 height_origin = height;
298
299 IMG_native_handle_t* h = (IMG_native_handle_t*)external_buffers->buffers[0];
300 int gfx_colorformat = h->iFormat;
301
302 if (gfx_colorformat != HAL_PIXEL_FORMAT_NV12 && format != VA_RT_FORMAT_RGB32)
303 height = (height + 0x1f) & ~0x1f;
304
305 /* get native window from the reserved field */
306 driver_data->native_window = (void *)external_buffers->reserved[0];
307
308 for (i = 0; i < num_surfaces; i++) {
309 int surfaceID;
310 object_surface_p obj_surface;
311 psb_surface_p psb_surface;
312
313 surfaceID = object_heap_allocate(&driver_data->surface_heap);
314 obj_surface = SURFACE(surfaceID);
315 if (NULL == obj_surface) {
316 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
317 DEBUG_FAILURE;
318 break;
319 }
320 MEMSET_OBJECT(obj_surface, struct object_surface_s);
321
322 obj_surface->surface_id = surfaceID;
323 surface_list[i] = surfaceID;
324 obj_surface->context_id = -1;
325 obj_surface->width = width;
326 obj_surface->height = height;
327 obj_surface->width_r = width;
328 obj_surface->height_r = height;
329 obj_surface->height_origin = height_origin;
330
331 psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
332 if (NULL == psb_surface) {
333 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
334 obj_surface->surface_id = VA_INVALID_SURFACE;
335
336 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
337
338 DEBUG_FAILURE;
339 break;
340 }
341
342 switch (format) {
343 case VA_RT_FORMAT_YUV422:
344 fourcc = VA_FOURCC_YV16;
345 break;
346 case VA_RT_FORMAT_RGB32:
347 fourcc = VA_FOURCC_RGBA;
348 break;
349 case VA_RT_FORMAT_YUV420:
350 default:
351 fourcc = VA_FOURCC_NV12;
352 break;
353 }
354
355 #ifndef PSBVIDEO_MSVDX_DEC_TILING
356 external_buffers->tiling = 0;
357 #endif
358 /*hard code the gralloc buffer usage*/
359 usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER;
360
361 if (gfx_colorformat == HAL_PIXEL_FORMAT_NV12)
362 usage |= GRALLOC_USAGE_SW_READ_OFTEN;
363 else {
364 // video decoder allows app to read/write the buffer
365 usage |= GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_SW_READ_RARELY;
366 }
367
368 handle = (unsigned long)external_buffers->buffers[i];
369 pthread_mutex_lock(&gralloc_mutex);
370
371 if (gralloc_register((buffer_handle_t)handle)) {
372 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
373 } else {
374 if (gralloc_lock((buffer_handle_t)handle, usage, 0, 0, width, height, (void **)&vaddr[GRALLOC_SUB_BUFFER0])) {
375 vaStatus = VA_STATUS_ERROR_UNKNOWN;
376 gralloc_unregister((buffer_handle_t)handle);
377 } else {
378 int cache_flag = PSB_USER_BUFFER_UNCACHED;
379 int buf_fd = gralloc_getbuffd((buffer_handle_t)handle);
380 #ifdef PSBVIDEO_MRFL
381 //cache_flag = 0;
382 #endif
383 vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
384 (VASurfaceAttributeTPI *)external_buffers, psb_surface,
385 vaddr[GRALLOC_SUB_BUFFER0], buf_fd, cache_flag);
386 psb_surface->buf.handle = (void *)handle;
387 obj_surface->share_info = NULL;
388
389 if ((gfx_colorformat != HAL_PIXEL_FORMAT_NV12) &&
390 (gfx_colorformat != HAL_PIXEL_FORMAT_YV12) &&
391 (format != VA_RT_FORMAT_RGB32)) {
392 unsigned int decoder_share_info = (unsigned int)external_buffers->reserved[2];
393 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s : Create graphic buffer initialized share info %d", __FUNCTION__, decoder_share_info);
394 obj_surface->share_info = (psb_surface_share_info_t *)vaddr[GRALLOC_SUB_BUFFER1];
395
396 if (obj_surface->share_info->initialized != SHARE_INFO_INIT_VALUE) {
397 memset(obj_surface->share_info, 0, sizeof(struct psb_surface_share_info_s));
398 // Set clear video the default output method as OUTPUT_FORCE_OVERLAY_FOR_SW_DECODE
399 // if the video can be decoded by HW, will reset the output method as 0 in psb_BeginPicture
400 #ifdef PSBVIDEO_MSVDX_DEC_TILING
401 obj_surface->share_info->tiling = external_buffers->tiling;
402 #endif
403 obj_surface->share_info->width = obj_surface->width;
404 obj_surface->share_info->height = obj_surface->height_origin;
405
406 obj_surface->share_info->luma_stride = psb_surface->stride;
407 obj_surface->share_info->chroma_u_stride = psb_surface->stride;
408 obj_surface->share_info->chroma_v_stride = psb_surface->stride;
409 obj_surface->share_info->format = VA_FOURCC_NV12;
410
411 obj_surface->share_info->khandle = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf)));
412
413 obj_surface->share_info->initialized = SHARE_INFO_INIT_VALUE;
414 }
415
416 if (decoder_share_info) {
417 obj_surface->share_info->force_output_method = protected ? OUTPUT_FORCE_OVERLAY : OUTPUT_FORCE_OVERLAY_FOR_SW_DECODE;
418 obj_surface->share_info->native_window = (void *)external_buffers->reserved[0];
419
420 attribute_tpi->reserved[1] = (unsigned long)obj_surface->share_info;
421
422 if (vaddr[GRALLOC_SUB_BUFFER0] == NULL) {
423 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to lock graphic buffer in psb_video");
424 } else {
425 size = psb_surface->chroma_offset;
426 // the following memset was used to work-around Bug 19197299 on L.
427 // on DDK-1.5 we didn't observe the problem so comment it out.
428 // memset((char *)vaddr[GRALLOC_SUB_BUFFER0], 0, size);
429 // memset((char *)vaddr[GRALLOC_SUB_BUFFER0] + size, 0x80, psb_surface->size - size);
430 }
431 // overlay only support BT.601 and BT.709
432 if (driver_data->load_csc_matrix == 1) {
433 obj_surface->share_info->csc_mode = (driver_data->is_BT601 == 1) ? 0 : 1;
434 } else {
435 // if csc matrix is not set, use BT601 by default
436 obj_surface->share_info->csc_mode = 0;
437 }
438
439 if (driver_data->set_video_range == 1) {
440 obj_surface->share_info->video_range = driver_data->video_range;
441 } else {
442 // if video range is not set, use limited range by default
443 obj_surface->share_info->video_range = 0;
444 }
445
446 obj_surface->share_info->surface_protected = driver_data->protected;
447 if (driver_data->render_rect.width == 0 || driver_data->render_rect.height == 0) {
448 obj_surface->share_info->crop_width = obj_surface->share_info->width;
449 obj_surface->share_info->crop_height = obj_surface->share_info->height;
450 } else {
451 obj_surface->share_info->crop_width = driver_data->render_rect.width;
452 obj_surface->share_info->crop_height = driver_data->render_rect.height;
453 }
454
455 if (obj_surface->share_info->coded_width == 0 || obj_surface->share_info->coded_height == 0) {
456 obj_surface->share_info->coded_width = (obj_surface->share_info->width + 0xf) & ~0xf;
457 obj_surface->share_info->coded_height = (obj_surface->share_info->height + 0xf) & ~0xf;
458 }
459
460 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s : Create graphic buffer success"
461 "surface_id= 0x%x, vaddr[0] (0x%x), vaddr[1] (0x%x)\n",
462 __FUNCTION__, surfaceID, vaddr[GRALLOC_SUB_BUFFER0], vaddr[GRALLOC_SUB_BUFFER1]);
463 }
464 }
465 gralloc_unlock((buffer_handle_t)handle);
466 psb_surface->buf.user_ptr = NULL;
467 }
468 }
469 pthread_mutex_unlock(&gralloc_mutex);
470
471 if (VA_STATUS_SUCCESS != vaStatus) {
472 free(psb_surface);
473 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
474 obj_surface->surface_id = VA_INVALID_SURFACE;
475
476 DEBUG_FAILURE;
477 break;
478 }
479 buffer_stride = psb_surface->stride;
480 /* by default, surface fourcc is NV12 */
481 psb_surface->extra_info[4] = fourcc;
482 /* save the pixel format set by application */
483 psb_surface->extra_info[8] = external_buffers->pixel_format;
484 #ifdef PSBVIDEO_MSVDX_DEC_TILING
485 psb_surface->extra_info[7] = external_buffers->tiling;
486 #endif
487 obj_surface->psb_surface = psb_surface;
488 }
489
490 /* Error recovery */
491 if (VA_STATUS_SUCCESS != vaStatus) {
492 /* surface_list[i-1] was the last successful allocation */
493 for (; i--;) {
494 object_surface_p obj_surface = SURFACE(surface_list[i]);
495 psb__destroy_surface(driver_data, obj_surface);
496 surface_list[i] = VA_INVALID_SURFACE;
497 }
498 drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaces failed\n");
499
500 return vaStatus;
501 }
502
503 return vaStatus;
504 }
505
506 #endif
507