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