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
48static pthread_mutex_t gralloc_mutex = PTHREAD_MUTEX_INITIALIZER;
49
50/*FIXME: include hal_public.h instead of define it here*/
51enum {
52    GRALLOC_SUB_BUFFER0 = 0,
53    GRALLOC_SUB_BUFFER1,
54    GRALLOC_SUB_BUFFER2,
55    GRALLOC_SUB_BUFFER_MAX,
56};
57
58VAStatus 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
92VAStatus 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            int buf_fd = gralloc_getbuffd(handle);
204
205            vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
206                    external_buffers, psb_surface, vaddr, buf_fd,
207                    cache_flag);
208
209            psb_surface->buf.handle = handle;
210            obj_surface->share_info = NULL;
211            gralloc_unlock(handle);
212        }
213        pthread_mutex_unlock(&gralloc_mutex);
214
215        if (VA_STATUS_SUCCESS != vaStatus) {
216            free(psb_surface);
217            object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
218            obj_surface->surface_id = VA_INVALID_SURFACE;
219
220            DEBUG_FAILURE;
221            break;
222        }
223        buffer_stride = psb_surface->stride;
224#ifdef PSBVIDEO_MSVDX_DEC_TILING
225        psb_surface->extra_info[7] = external_buffers->tiling;
226#endif
227        /* by default, surface fourcc is NV12 */
228        psb_surface->extra_info[4] = fourcc;
229        obj_surface->psb_surface = psb_surface;
230    }
231
232    /* Error recovery */
233    if (VA_STATUS_SUCCESS != vaStatus) {
234        /* surface_list[i-1] was the last successful allocation */
235        for (; i--;) {
236            object_surface_p obj_surface = SURFACE(surface_list[i]);
237            psb__destroy_surface(driver_data, obj_surface);
238            surface_list[i] = VA_INVALID_SURFACE;
239        }
240        drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaces failed\n");
241
242        return vaStatus;
243    }
244
245    return vaStatus;
246}
247#else
248VAStatus psb_CreateSurfacesFromGralloc(
249    VADriverContextP ctx,
250    int width,
251    int height,
252    int format,
253    int num_surfaces,
254    VASurfaceID *surface_list,        /* out */
255    PsbSurfaceAttributeTPI *attribute_tpi
256)
257{
258    INIT_DRIVER_DATA
259    VAStatus vaStatus = VA_STATUS_SUCCESS;
260    int i, height_origin, usage, buffer_stride = 0;
261    int protected = (VA_RT_FORMAT_PROTECTED & format);
262    unsigned long fourcc;
263    PsbSurfaceAttributeTPI *external_buffers = NULL;
264    unsigned long handle;
265    int size = num_surfaces * sizeof(unsigned int);
266    void *vaddr[GRALLOC_SUB_BUFFER_MAX];
267
268    /* follow are gralloc-buffers */
269    format = format & (~VA_RT_FORMAT_PROTECTED);
270    driver_data->protected = protected;
271
272    CHECK_INVALID_PARAM(num_surfaces <= 0);
273    CHECK_SURFACE(surface_list);
274
275    external_buffers = attribute_tpi;
276
277    /* We only support one format */
278    if ((VA_RT_FORMAT_YUV420 != format)
279        && (VA_RT_FORMAT_YUV422 != format)
280        && (VA_RT_FORMAT_RGB32 != format)) {
281        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
282        DEBUG_FAILURE;
283        return vaStatus;
284    }
285
286    CHECK_INVALID_PARAM(external_buffers == NULL);
287
288    /*
289    vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
290    CHECK_VASTATUS();
291    */
292    /* Adjust height to be a multiple of 32 (height of macroblock in interlaced mode) */
293    height_origin = height;
294
295    IMG_native_handle_t* h = (IMG_native_handle_t*)external_buffers->buffers[0];
296    int gfx_colorformat = h->iFormat;
297
298    if (gfx_colorformat != HAL_PIXEL_FORMAT_NV12 && format != VA_RT_FORMAT_RGB32)
299        height = (height + 0x1f) & ~0x1f;
300
301    /* get native window from the reserved field */
302    driver_data->native_window = (void *)external_buffers->reserved[0];
303
304    for (i = 0; i < num_surfaces; i++) {
305        int surfaceID;
306        object_surface_p obj_surface;
307        psb_surface_p psb_surface;
308
309        surfaceID = object_heap_allocate(&driver_data->surface_heap);
310        obj_surface = SURFACE(surfaceID);
311        if (NULL == obj_surface) {
312            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
313            DEBUG_FAILURE;
314            break;
315        }
316        MEMSET_OBJECT(obj_surface, struct object_surface_s);
317
318        obj_surface->surface_id = surfaceID;
319        surface_list[i] = surfaceID;
320        obj_surface->context_id = -1;
321        obj_surface->width = width;
322        obj_surface->height = height;
323        obj_surface->width_r = width;
324        obj_surface->height_r = height;
325        obj_surface->height_origin = height_origin;
326
327        psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
328        if (NULL == psb_surface) {
329            object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
330            obj_surface->surface_id = VA_INVALID_SURFACE;
331
332            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
333
334            DEBUG_FAILURE;
335            break;
336        }
337
338        switch (format) {
339        case VA_RT_FORMAT_YUV422:
340            fourcc = VA_FOURCC_YV16;
341            break;
342        case VA_RT_FORMAT_RGB32:
343            fourcc = VA_FOURCC_RGBA;
344            break;
345        case VA_RT_FORMAT_YUV420:
346        default:
347            fourcc = VA_FOURCC_NV12;
348            break;
349        }
350
351#ifndef PSBVIDEO_MSVDX_DEC_TILING
352        external_buffers->tiling = 0;
353#endif
354        /*hard code the gralloc buffer usage*/
355        usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER;
356
357        if (gfx_colorformat == HAL_PIXEL_FORMAT_NV12)
358            usage |= GRALLOC_USAGE_SW_READ_OFTEN;
359        else {
360            // video decoder allows app to read/write the buffer
361            usage |= GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_SW_READ_RARELY;
362        }
363
364        handle = (unsigned long)external_buffers->buffers[i];
365        pthread_mutex_lock(&gralloc_mutex);
366
367        if (gralloc_lock((buffer_handle_t)handle, usage, 0, 0, width, height, (void **)&vaddr[GRALLOC_SUB_BUFFER0])) {
368            vaStatus = VA_STATUS_ERROR_UNKNOWN;
369        } else {
370            int cache_flag = PSB_USER_BUFFER_UNCACHED;
371            int buf_fd = gralloc_getbuffd((buffer_handle_t)handle);
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], buf_fd, 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                    if (vaddr[GRALLOC_SUB_BUFFER0] == NULL) {
416                        drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to lock graphic buffer in psb_video");
417                    }
418                    else {
419                        size = psb_surface->chroma_offset;
420                        // the following memset was used to work-around Bug 19197299 on L.
421                        // on DDK-1.5 we didn't observe the problem so comment it out.
422                        // memset((char *)vaddr[GRALLOC_SUB_BUFFER0], 0, size);
423                        // memset((char *)vaddr[GRALLOC_SUB_BUFFER0] + size, 0x80, psb_surface->size - size);
424                    }
425                    // overlay only support BT.601 and BT.709
426                    if (driver_data->load_csc_matrix == 1) {
427                        obj_surface->share_info->csc_mode = (driver_data->is_BT601 == 1) ? 0 : 1;
428                    } else {
429                        // if csc matrix is not set, use BT601 by default
430                        obj_surface->share_info->csc_mode = 0;
431                    }
432
433                    if (driver_data->set_video_range == 1) {
434                        obj_surface->share_info->video_range = driver_data->video_range;
435                    } else {
436                        // if video range is not set, use limited range by default
437                        obj_surface->share_info->video_range = 0;
438                    }
439
440                    obj_surface->share_info->surface_protected = driver_data->protected;
441                    if (driver_data->render_rect.width == 0 || driver_data->render_rect.height == 0) {
442                        obj_surface->share_info->crop_width = obj_surface->share_info->width;
443                        obj_surface->share_info->crop_height = obj_surface->share_info->height;
444                    } else {
445                        obj_surface->share_info->crop_width = driver_data->render_rect.width;
446                        obj_surface->share_info->crop_height = driver_data->render_rect.height;
447                    }
448
449                    if (obj_surface->share_info->coded_width == 0 || obj_surface->share_info->coded_height == 0) {
450                        obj_surface->share_info->coded_width = (obj_surface->share_info->width + 0xf) & ~0xf;
451                        obj_surface->share_info->coded_height = (obj_surface->share_info->height + 0xf) & ~0xf;
452                    }
453
454                    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s : Create graphic buffer success"
455                            "surface_id= 0x%x, vaddr[0] (0x%x), vaddr[1] (0x%x)\n",
456                            __FUNCTION__, surfaceID, vaddr[GRALLOC_SUB_BUFFER0], vaddr[GRALLOC_SUB_BUFFER1]);
457                }
458            }
459            gralloc_unlock((buffer_handle_t)handle);
460            psb_surface->buf.user_ptr = NULL;
461        }
462        pthread_mutex_unlock(&gralloc_mutex);
463
464        if (VA_STATUS_SUCCESS != vaStatus) {
465            free(psb_surface);
466            object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
467            obj_surface->surface_id = VA_INVALID_SURFACE;
468
469            DEBUG_FAILURE;
470            break;
471        }
472        buffer_stride = psb_surface->stride;
473        /* by default, surface fourcc is NV12 */
474        psb_surface->extra_info[4] = fourcc;
475        /* save the pixel format set by application */
476        psb_surface->extra_info[8] = external_buffers->pixel_format;
477#ifdef PSBVIDEO_MSVDX_DEC_TILING
478        psb_surface->extra_info[7] = external_buffers->tiling;
479#endif
480        obj_surface->psb_surface = psb_surface;
481    }
482
483    /* Error recovery */
484    if (VA_STATUS_SUCCESS != vaStatus) {
485        /* surface_list[i-1] was the last successful allocation */
486        for (; i--;) {
487            object_surface_p obj_surface = SURFACE(surface_list[i]);
488            psb__destroy_surface(driver_data, obj_surface);
489            surface_list[i] = VA_INVALID_SURFACE;
490        }
491        drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaces failed\n");
492
493        return vaStatus;
494    }
495
496    return vaStatus;
497}
498
499#endif
500