Home | History | Annotate | Download | only in src
      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  * Authors:
     25  *    Shengquan Yuan  <shengquan.yuan (at) intel.com>
     26  *    Zhaohan Ren  <zhaohan.ren (at) intel.com>
     27  *    Jason Hu <jason.hu (at) intel.com>
     28  *
     29  */
     30 
     31 #ifndef ANDROID
     32 #include <X11/Xutil.h>
     33 #include <X11/extensions/Xrandr.h>
     34 #include <va/va_dricommon.h>
     35 #include "x11/psb_x11.h"
     36 #include "x11/psb_xrandr.h"
     37 #endif
     38 #include <va/va_backend.h>
     39 #include <dlfcn.h>
     40 #include <stdlib.h>
     41 #include "psb_output.h"
     42 #include "psb_surface.h"
     43 #include "psb_buffer.h"
     44 #include "psb_surface_ext.h"
     45 #include "pnw_rotate.h"
     46 #include <stdio.h>
     47 #include <string.h>
     48 #include <stdarg.h>
     49 #include <wsbm/wsbm_manager.h>
     50 #include "psb_drv_debug.h"
     51 #include <string.h>
     52 #include <unistd.h>
     53 #include <sys/ioctl.h>
     54 
     55 #define INIT_DRIVER_DATA        psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
     56 
     57 #define SURFACE(id)     ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
     58 #define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
     59 #define IMAGE(id)  ((object_image_p) object_heap_lookup( &driver_data->image_heap, id ))
     60 #define SUBPIC(id)  ((object_subpic_p) object_heap_lookup( &driver_data->subpic_heap, id ))
     61 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
     62 
     63 
     64 /* surfaces link list associated with a subpicture */
     65 typedef struct _subpic_surface {
     66     VASurfaceID surface_id;
     67     struct _subpic_surface *next;
     68 } subpic_surface_s, *subpic_surface_p;
     69 
     70 
     71 static VAImageFormat psb__SubpicFormat[] = {
     72     psb__ImageRGBA,
     73     //psb__ImageAYUV,
     74     //psb__ImageAI44
     75 };
     76 
     77 static VAImageFormat psb__CreateImageFormat[] = {
     78     psb__ImageNV12,
     79     psb__ImageRGBA,
     80     //psb__ImageAYUV,
     81     //psb__ImageAI44,
     82     psb__ImageYV16,
     83     psb__ImageYV32
     84 };
     85 
     86 unsigned char *psb_x11_output_init(VADriverContextP ctx);
     87 VAStatus psb_x11_output_deinit(VADriverContextP ctx);
     88 unsigned char *psb_android_output_init(VADriverContextP ctx);
     89 VAStatus psb_android_output_deinit(VADriverContextP ctx);
     90 
     91 int psb_coverlay_init(VADriverContextP ctx);
     92 int psb_coverlay_deinit(VADriverContextP ctx);
     93 
     94 VAStatus psb_initOutput(VADriverContextP ctx)
     95 {
     96     INIT_DRIVER_DATA;
     97     unsigned char *ws_priv = NULL;
     98     char env_value[1024];
     99 
    100     pthread_mutex_init(&driver_data->output_mutex, NULL);
    101 
    102     if (psb_parse_config("PSB_VIDEO_PUTSURFACE_DUMMY", &env_value[0]) == 0) {
    103         drv_debug_msg(VIDEO_DEBUG_GENERAL, "vaPutSurface: dummy mode, return directly\n");
    104         driver_data->dummy_putsurface = 0;
    105 
    106         return VA_STATUS_SUCCESS;
    107     }
    108 
    109     if (psb_parse_config("PSB_VIDEO_FPS", &env_value[0]) == 0) {
    110         driver_data->fixed_fps = atoi(env_value);
    111         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Throttling at FPS=%d\n", driver_data->fixed_fps);
    112     } else
    113         driver_data->fixed_fps = 0;
    114 
    115     driver_data->outputmethod_checkinterval = 1;
    116     if (psb_parse_config("PSB_VIDEO_INTERVAL", &env_value[0]) == 0) {
    117         driver_data->outputmethod_checkinterval = atoi(env_value);
    118         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Check output method at %d frames interval\n",
    119                                  driver_data->outputmethod_checkinterval);
    120     }
    121 
    122     driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
    123     driver_data->last_displaying_surface = VA_INVALID_SURFACE;
    124 
    125     psb_InitOutLoop(ctx);
    126 
    127 #ifdef ANDROID
    128     ws_priv = psb_android_output_init(ctx);
    129     driver_data->is_android = 1;
    130 #else
    131     ws_priv = psb_x11_output_init(ctx);
    132     driver_data->is_android = 0;
    133 #endif
    134     driver_data->ws_priv = ws_priv;
    135 
    136 
    137 #if 0
    138     //use client textureblit
    139     if (driver_data->ctexture == 1) {
    140         int ret = psb_ctexture_init(ctx);
    141         if (ret != 0)
    142             driver_data->ctexture = 0;
    143     }
    144 #endif
    145 
    146     /*
    147     //use texture streaming
    148     if (driver_data->ctexstreaming == 1)
    149     psb_ctexstreaing_init(ctx);
    150     */
    151 
    152     return VA_STATUS_SUCCESS;
    153 }
    154 
    155 VAStatus psb_deinitOutput(
    156     VADriverContextP ctx
    157 )
    158 {
    159     INIT_DRIVER_DATA;
    160 
    161 #if 0
    162     //use client textureblit
    163     if (driver_data->ctexture == 1)
    164         psb_ctexture_deinit(ctx);
    165 #endif
    166 
    167     if (driver_data->coverlay_init) {
    168         psb_coverlay_deinit(ctx);
    169         driver_data->coverlay_init = 0;
    170     }
    171 
    172 #ifndef ANDROID
    173     psb_x11_output_deinit(ctx);
    174 #else
    175     psb_android_output_deinit(ctx);
    176 #endif
    177     /* free here, but allocate in window system specific */
    178     free(driver_data->ws_priv);
    179     /*
    180     //use texture streaming
    181     if (driver_data->ctexstreaming == 1)
    182         psb_ctexstreaing_deinit(ctx);
    183     */
    184     /* clean the displaying surface information in kernel */
    185 #ifndef _FOR_FPGA_
    186     psb_surface_set_displaying(driver_data, 0, 0, NULL);
    187 #endif
    188     pthread_mutex_destroy(&driver_data->output_mutex);
    189 
    190     return VA_STATUS_SUCCESS;
    191 }
    192 
    193 #ifndef VA_STATUS_ERROR_INVALID_IMAGE_FORMAT
    194 #define VA_STATUS_ERROR_INVALID_IMAGE_FORMAT VA_STATUS_ERROR_UNKNOWN
    195 #endif
    196 
    197 static VAImageFormat *psb__VAImageCheckFourCC(
    198     VAImageFormat       *src_format,
    199     VAImageFormat       *dst_format,
    200     int                 dst_num
    201 )
    202 {
    203     int i;
    204     if (NULL == src_format || dst_format == NULL) {
    205         return NULL;
    206     }
    207 
    208     /* check VAImage at first */
    209     for (i = 0; i < dst_num; i++) {
    210         if (dst_format[i].fourcc == src_format->fourcc)
    211             return &dst_format[i];
    212     }
    213 
    214     drv_debug_msg(VIDEO_DEBUG_ERROR, "Unsupport fourcc 0x%x\n", src_format->fourcc);
    215     return NULL;
    216 }
    217 
    218 static void psb__VAImageCheckRegion(
    219     object_surface_p surface,
    220     VAImage *image,
    221     int *src_x,
    222     int *src_y,
    223     int *dest_x,
    224     int *dest_y,
    225     int *width,
    226     int *height
    227 )
    228 {
    229     /* check for image */
    230     if (*src_x < 0) *src_x = 0;
    231     if (*src_x > image->width) *src_x = image->width - 1;
    232     if (*src_y < 0) *src_y = 0;
    233     if (*src_y > image->height) *src_y = image->height - 1;
    234 
    235     if (((*width) + (*src_x)) > image->width) *width = image->width - *src_x;
    236     if (((*height) + (*src_y)) > image->height) *height = image->height - *src_x;
    237 
    238     /* check for surface */
    239     if (*dest_x < 0) *dest_x = 0;
    240     if (*dest_x > surface->width) *dest_x = surface->width - 1;
    241     if (*dest_y < 0) *dest_y = 0;
    242     if (*dest_y > surface->height) *dest_y = surface->height - 1;
    243 
    244     if (((*width) + (*dest_x)) > surface->width) *width = surface->width - *dest_x;
    245     if (((*height) + (*dest_y)) > surface->height) *height = surface->height - *dest_x;
    246 }
    247 
    248 
    249 VAStatus psb_QueryImageFormats(
    250     VADriverContextP __maybe_unused ctx,
    251     VAImageFormat *format_list,        /* out */
    252     int *num_formats           /* out */
    253 )
    254 {
    255     VAStatus vaStatus = VA_STATUS_SUCCESS;
    256 
    257     CHECK_INVALID_PARAM(format_list == NULL);
    258     CHECK_INVALID_PARAM(num_formats == NULL);
    259 
    260     memcpy(format_list, psb__CreateImageFormat, sizeof(psb__CreateImageFormat));
    261     *num_formats = PSB_MAX_IMAGE_FORMATS;
    262 
    263     return VA_STATUS_SUCCESS;
    264 }
    265 
    266 inline int min_POT(int n)
    267 {
    268     if ((n & (n - 1)) == 0) /* already POT */
    269         return n;
    270 
    271     return n |= n >> 16, n |= n >> 8, n |= n >> 4, n |= n >> 2, n |= n >> 1, n + 1;
    272     /* return ((((n |= n>>16) |= n>>8) |= n>>4) |= n>>2) |= n>>1, n + 1; */
    273 }
    274 
    275 VAStatus psb_CreateImage(
    276     VADriverContextP ctx,
    277     VAImageFormat *format,
    278     int width,
    279     int height,
    280     VAImage *image     /* out */
    281 )
    282 {
    283     INIT_DRIVER_DATA;
    284     VAImageID imageID;
    285     object_image_p obj_image;
    286     VAStatus vaStatus = VA_STATUS_SUCCESS;
    287     VAImageFormat *img_fmt;
    288     int pitch_pot;
    289 
    290     (void)driver_data;
    291 
    292     img_fmt = psb__VAImageCheckFourCC(format, psb__CreateImageFormat,
    293                                       sizeof(psb__CreateImageFormat) / sizeof(VAImageFormat));
    294     if (img_fmt == NULL)
    295         return VA_STATUS_ERROR_UNKNOWN;
    296 
    297     CHECK_INVALID_PARAM(image == NULL);
    298 
    299     imageID = object_heap_allocate(&driver_data->image_heap);
    300     obj_image = IMAGE(imageID);
    301     CHECK_ALLOCATION(obj_image);
    302 
    303     MEMSET_OBJECT(obj_image, struct object_image_s);
    304 
    305     obj_image->image.image_id = imageID;
    306     obj_image->image.format = *img_fmt;
    307     obj_image->subpic_ref = 0;
    308 
    309     pitch_pot = min_POT(width);
    310 
    311     switch (format->fourcc) {
    312     case VA_FOURCC_NV12: {
    313         obj_image->image.width = width;
    314         obj_image->image.height = height;
    315         obj_image->image.data_size = pitch_pot * height /*Y*/ + 2 * (pitch_pot / 2) * (height / 2);/*UV*/
    316         obj_image->image.num_planes = 2;
    317         obj_image->image.pitches[0] = pitch_pot;
    318         obj_image->image.pitches[1] = pitch_pot;
    319         obj_image->image.offsets[0] = 0;
    320         obj_image->image.offsets[1] = pitch_pot * height;
    321         obj_image->image.num_palette_entries = 0;
    322         obj_image->image.entry_bytes = 0;
    323         obj_image->image.component_order[0] = 'Y';
    324         obj_image->image.component_order[1] = 'U';/* fixed me: packed UV packed here! */
    325         obj_image->image.component_order[2] = 'V';
    326         obj_image->image.component_order[3] = '\0';
    327         break;
    328     }
    329     case VA_FOURCC_AYUV: {
    330         obj_image->image.width = width;
    331         obj_image->image.height = height;
    332         obj_image->image.data_size = 4 * pitch_pot * height;
    333         obj_image->image.num_planes = 1;
    334         obj_image->image.pitches[0] = 4 * pitch_pot;
    335         obj_image->image.num_palette_entries = 0;
    336         obj_image->image.entry_bytes = 0;
    337         obj_image->image.component_order[0] = 'V';
    338         obj_image->image.component_order[1] = 'U';
    339         obj_image->image.component_order[2] = 'Y';
    340         obj_image->image.component_order[3] = 'A';
    341         break;
    342     }
    343     case VA_FOURCC_RGBA: {
    344         obj_image->image.width = width;
    345         obj_image->image.height = height;
    346         obj_image->image.data_size = 4 * pitch_pot * height;
    347         obj_image->image.num_planes = 1;
    348         obj_image->image.pitches[0] = 4 * pitch_pot;
    349         obj_image->image.num_palette_entries = 0;
    350         obj_image->image.entry_bytes = 0;
    351         obj_image->image.component_order[0] = 'R';
    352         obj_image->image.component_order[1] = 'G';
    353         obj_image->image.component_order[2] = 'B';
    354         obj_image->image.component_order[3] = 'A';
    355         break;
    356     }
    357     case VA_FOURCC_AI44: {
    358         obj_image->image.width = width;
    359         obj_image->image.height = height;
    360         obj_image->image.data_size = pitch_pot * height;/* one byte one element */
    361         obj_image->image.num_planes = 1;
    362         obj_image->image.pitches[0] = pitch_pot;
    363         obj_image->image.num_palette_entries = 16;
    364         obj_image->image.entry_bytes = 4; /* AYUV */
    365         obj_image->image.component_order[0] = 'I';
    366         obj_image->image.component_order[1] = 'A';
    367         obj_image->image.component_order[2] = '\0';
    368         obj_image->image.component_order[3] = '\0';
    369         break;
    370     }
    371     case VA_FOURCC_IYUV: {
    372         obj_image->image.width = width;
    373         obj_image->image.height = height;
    374         obj_image->image.data_size = pitch_pot * height /*Y*/ + 2 * (pitch_pot / 2) * (height / 2);/*UV*/
    375         obj_image->image.num_planes = 3;
    376         obj_image->image.pitches[0] = pitch_pot;
    377         obj_image->image.pitches[1] = pitch_pot / 2;
    378         obj_image->image.pitches[2] = pitch_pot / 2;
    379         obj_image->image.offsets[0] = 0;
    380         obj_image->image.offsets[1] = pitch_pot * height;
    381         obj_image->image.offsets[2] = pitch_pot * height + (pitch_pot / 2) * (height / 2);
    382         obj_image->image.num_palette_entries = 0;
    383         obj_image->image.entry_bytes = 0;
    384         obj_image->image.component_order[0] = 'Y';
    385         obj_image->image.component_order[1] = 'U';
    386         obj_image->image.component_order[2] = 'V';
    387         obj_image->image.component_order[3] = '\0';
    388         break;
    389     }
    390     case VA_FOURCC_YV32: {
    391         obj_image->image.width = width;
    392         obj_image->image.height = height;
    393         obj_image->image.data_size = 4 * pitch_pot * height;
    394         obj_image->image.num_planes = 4;
    395         obj_image->image.pitches[0] = pitch_pot;
    396         obj_image->image.pitches[1] = pitch_pot;
    397         obj_image->image.pitches[2] = pitch_pot;
    398         obj_image->image.extra_pitch = pitch_pot;
    399         obj_image->image.offsets[0] = 0;
    400         obj_image->image.offsets[1] = pitch_pot * height;
    401         obj_image->image.offsets[2] = pitch_pot * height * 2;
    402         obj_image->image.extra_offset = pitch_pot * height * 3;
    403         obj_image->image.num_palette_entries = 0;
    404         obj_image->image.entry_bytes = 0;
    405         obj_image->image.component_order[0] = 'V';
    406         obj_image->image.component_order[1] = 'U';
    407         obj_image->image.component_order[2] = 'Y';
    408         obj_image->image.component_order[3] = 'A';
    409         break;
    410     }
    411     default: {
    412         vaStatus = VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
    413         break;
    414     }
    415     }
    416 
    417     if (VA_STATUS_SUCCESS == vaStatus) {
    418         /* create the buffer */
    419         vaStatus = psb__CreateBuffer(driver_data, NULL, VAImageBufferType,
    420                                      obj_image->image.data_size, 1, NULL, &obj_image->image.buf);
    421     }
    422 
    423     obj_image->derived_surface = 0;
    424 
    425     if (VA_STATUS_SUCCESS != vaStatus) {
    426         object_heap_free(&driver_data->image_heap, (object_base_p) obj_image);
    427     } else {
    428         memcpy(image, &obj_image->image, sizeof(VAImage));
    429     }
    430 
    431     return vaStatus;
    432 }
    433 
    434 static int psb_CheckIEDStatus(VADriverContextP ctx)
    435 {
    436     INIT_DRIVER_DATA;
    437     struct drm_lnc_video_getparam_arg arg;
    438     unsigned long temp;
    439     int ret = 0;
    440 
    441     /* not settled, we get it from current HW FRAMESKIP flag */
    442     arg.key = IMG_VIDEO_IED_STATE;
    443     arg.value = (uint64_t)((unsigned long) & temp);
    444     ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
    445                               &arg, sizeof(arg));
    446     if (ret == 0) {
    447         if (temp == 1) {
    448             drv_debug_msg(VIDEO_DEBUG_ERROR, "IED is enabled, image is encrypted.\n");
    449             return 1;
    450         } else {
    451             return 0;
    452         }
    453     } else {
    454         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to call IMG_VIDEO_IED_STATE.\n");
    455         return -1;
    456     }
    457 }
    458 
    459 VAStatus psb_DeriveImage(
    460     VADriverContextP ctx,
    461     VASurfaceID surface,
    462     VAImage *image     /* out */
    463 )
    464 {
    465     INIT_DRIVER_DATA;
    466     VAStatus vaStatus = VA_STATUS_SUCCESS;
    467     VABufferID bufferID;
    468     object_buffer_p obj_buffer;
    469     VAImageID imageID;
    470     object_image_p obj_image;
    471     object_surface_p obj_surface = SURFACE(surface);
    472     unsigned int fourcc, fourcc_index = ~0, i;
    473     uint32_t srf_buf_ofs = 0;
    474 
    475     CHECK_SURFACE(obj_surface);
    476     CHECK_INVALID_PARAM(image == NULL);
    477     /* Can't derive image from reconstrued frame which is in tiled format */
    478     if (obj_surface->is_ref_surface == 1 || obj_surface->is_ref_surface == 2) {
    479 	if (getenv("PSB_VIDEO_IGNORE_TILED_FORMAT")) {
    480 	    drv_debug_msg(VIDEO_DEBUG_GENERAL, "Ignore tiled memory format" \
    481 			"of rec-frames\n");
    482 	} else {
    483 	    drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't derive reference surface" \
    484 			"which is tiled format\n");
    485 	    return VA_STATUS_ERROR_OPERATION_FAILED;
    486 	}
    487     }
    488 
    489     if (IS_MFLD(driver_data) && (psb_CheckIEDStatus(ctx) == 1)) {
    490         vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
    491         return vaStatus;
    492     }
    493 
    494     fourcc = obj_surface->psb_surface->extra_info[4];
    495     for (i = 0; i < PSB_MAX_IMAGE_FORMATS; i++) {
    496         if (psb__CreateImageFormat[i].fourcc == fourcc) {
    497             fourcc_index = i;
    498             break;
    499         }
    500     }
    501     if (i == PSB_MAX_IMAGE_FORMATS) {
    502         drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't support the Fourcc\n");
    503         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
    504         return vaStatus;
    505     }
    506 
    507     /* create the image */
    508     imageID = object_heap_allocate(&driver_data->image_heap);
    509     obj_image = IMAGE(imageID);
    510     CHECK_ALLOCATION(obj_image);
    511 
    512     MEMSET_OBJECT(obj_image, struct object_image_s);
    513 
    514     /* create a buffer to represent surface buffer */
    515     bufferID = object_heap_allocate(&driver_data->buffer_heap);
    516     obj_buffer = BUFFER(bufferID);
    517     if (NULL == obj_buffer) {
    518         object_heap_free(&driver_data->image_heap, (object_base_p) obj_image);
    519         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    520         DEBUG_FAILURE;
    521         return vaStatus;
    522     }
    523     MEMSET_OBJECT(obj_buffer, struct object_buffer_s);
    524 
    525     obj_buffer->type = VAImageBufferType;
    526     obj_buffer->buffer_data = NULL;
    527     obj_buffer->psb_buffer = &obj_surface->psb_surface->buf;
    528     obj_buffer->size = obj_surface->psb_surface->size;
    529     obj_buffer->max_num_elements = 0;
    530     obj_buffer->alloc_size = obj_buffer->size;
    531 
    532     /* fill obj_image data structure */
    533     obj_image->image.image_id = imageID;
    534     obj_image->image.format = psb__CreateImageFormat[fourcc_index];
    535     obj_image->subpic_ref = 0;
    536 
    537     obj_image->image.buf = bufferID;
    538     obj_image->image.width = obj_surface->width;
    539     obj_image->image.height = obj_surface->height;
    540     obj_image->image.data_size = obj_surface->psb_surface->size;
    541 
    542     srf_buf_ofs = obj_surface->psb_surface->buf.buffer_ofs;
    543 
    544     switch (fourcc) {
    545     case VA_FOURCC_NV12: {
    546         obj_image->image.num_planes = 2;
    547         obj_image->image.pitches[0] = obj_surface->psb_surface->stride;
    548         obj_image->image.pitches[1] = obj_surface->psb_surface->stride;
    549 
    550         obj_image->image.offsets[0] = srf_buf_ofs;
    551         obj_image->image.offsets[1] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride;
    552         obj_image->image.num_palette_entries = 0;
    553         obj_image->image.entry_bytes = 0;
    554         obj_image->image.component_order[0] = 'Y';
    555         obj_image->image.component_order[1] = 'U';/* fixed me: packed UV packed here! */
    556         obj_image->image.component_order[2] = 'V';
    557         obj_image->image.component_order[3] = '\0';
    558         break;
    559     }
    560     case VA_FOURCC_YV16: {
    561         obj_image->image.num_planes = 3;
    562         obj_image->image.pitches[0] = obj_surface->psb_surface->stride;
    563         obj_image->image.pitches[1] = obj_surface->psb_surface->stride / 2;
    564         obj_image->image.pitches[2] = obj_surface->psb_surface->stride / 2;
    565 
    566         obj_image->image.offsets[0] = srf_buf_ofs;
    567         obj_image->image.offsets[1] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride;
    568         obj_image->image.offsets[2] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride * 3 / 2;
    569         obj_image->image.num_palette_entries = 0;
    570         obj_image->image.entry_bytes = 0;
    571         obj_image->image.component_order[0] = 'Y';
    572         obj_image->image.component_order[1] = 'V';/* fixed me: packed UV packed here! */
    573         obj_image->image.component_order[2] = 'U';
    574         obj_image->image.component_order[3] = '\0';
    575         break;
    576     }
    577     case VA_FOURCC_YV32: {
    578         obj_image->image.num_planes = 3;
    579         obj_image->image.pitches[0] = obj_surface->psb_surface->stride;
    580         obj_image->image.pitches[1] = obj_surface->psb_surface->stride;
    581         obj_image->image.pitches[2] = obj_surface->psb_surface->stride;
    582 
    583         obj_image->image.offsets[0] = srf_buf_ofs;
    584         obj_image->image.offsets[1] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride;
    585         obj_image->image.offsets[2] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride * 2;
    586         obj_image->image.num_palette_entries = 0;
    587         obj_image->image.entry_bytes = 0;
    588         obj_image->image.component_order[0] = 'Y';
    589         obj_image->image.component_order[1] = 'U';/* fixed me: packed UV packed here! */
    590         obj_image->image.component_order[2] = 'V';
    591         obj_image->image.component_order[3] = '\0';
    592         break;
    593     }
    594     default:
    595         break;
    596     }
    597 
    598     obj_image->derived_surface = surface; /* this image is derived from a surface */
    599     obj_surface->derived_imgcnt++;
    600 
    601     memcpy(image, &obj_image->image, sizeof(VAImage));
    602 
    603     return vaStatus;
    604 }
    605 
    606 VAStatus psb__destroy_image(psb_driver_data_p driver_data, object_image_p obj_image)
    607 {
    608     VAStatus vaStatus = VA_STATUS_SUCCESS;
    609 
    610     if (obj_image->subpic_ref > 0) {
    611         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
    612         return vaStatus;
    613     }
    614 
    615     object_surface_p obj_surface = SURFACE(obj_image->derived_surface);
    616 
    617     if (obj_surface == NULL) { /* destroy the buffer */
    618         object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
    619         CHECK_BUFFER(obj_buffer);
    620         psb__suspend_buffer(driver_data, obj_buffer);
    621     } else {
    622         object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
    623         object_heap_free(&driver_data->buffer_heap, &obj_buffer->base);
    624         obj_surface->derived_imgcnt--;
    625     }
    626     object_heap_free(&driver_data->image_heap, (object_base_p) obj_image);
    627 
    628     return VA_STATUS_SUCCESS;
    629 }
    630 
    631 VAStatus psb_DestroyImage(
    632     VADriverContextP ctx,
    633     VAImageID image
    634 )
    635 {
    636     INIT_DRIVER_DATA
    637     VAStatus vaStatus = VA_STATUS_SUCCESS;
    638     object_image_p obj_image;
    639 
    640     obj_image = IMAGE(image);
    641     CHECK_IMAGE(obj_image);
    642     return psb__destroy_image(driver_data, obj_image);
    643 }
    644 
    645 VAStatus psb_SetImagePalette(
    646     VADriverContextP ctx,
    647     VAImageID image,
    648     /*
    649      * pointer to an array holding the palette data.  The size of the array is
    650      * num_palette_entries * entry_bytes in size.  The order of the components
    651      * in the palette is described by the component_order in VAImage struct
    652      */
    653     unsigned char *palette
    654 )
    655 {
    656     INIT_DRIVER_DATA;
    657     VAStatus vaStatus = VA_STATUS_SUCCESS;
    658 
    659     object_image_p obj_image = IMAGE(image);
    660     CHECK_IMAGE(obj_image);
    661 
    662     if (obj_image->image.format.fourcc != VA_FOURCC_AI44) {
    663         /* only support AI44 palette */
    664         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
    665         return vaStatus;
    666     }
    667 
    668     if (obj_image->image.num_palette_entries > 16) {
    669         drv_debug_msg(VIDEO_DEBUG_ERROR, "image.num_palette_entries(%d) is too big\n", obj_image->image.num_palette_entries);
    670         memcpy(obj_image->palette, palette, 16);
    671     } else
    672         memcpy(obj_image->palette, palette, obj_image->image.num_palette_entries * sizeof(unsigned int));
    673 
    674     return vaStatus;
    675 }
    676 
    677 static VAStatus lnc_unpack_topaz_rec(int src_width, int src_height,
    678                                      unsigned char *p_srcY, unsigned char *p_srcUV,
    679                                      unsigned char *p_dstY, unsigned char *p_dstU, unsigned char *p_dstV,
    680                                      int dstY_stride, int dstU_stride, int dstV_stride,
    681                                      int surface_height)
    682 {
    683     unsigned char *tmp_dstY = NULL;
    684     unsigned char *tmp_dstUV = NULL;
    685 
    686     int n, i, index;
    687 
    688     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Unpack reconstructed frame to image\n");
    689 
    690     /* do this one column at a time. */
    691     tmp_dstY = (unsigned char *)calloc(1, 16 * src_height);
    692     if (tmp_dstY == NULL)
    693         return  VA_STATUS_ERROR_ALLOCATION_FAILED;
    694 
    695     tmp_dstUV = (unsigned char*)calloc(1, 16 * src_height / 2);
    696     if (tmp_dstUV == NULL) {
    697         free(tmp_dstY);
    698         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    699     }
    700 
    701     /*  Copy Y data */
    702     for (n = 0; n < src_width / 16; n++) {
    703         memcpy((void*)tmp_dstY, p_srcY, 16 * src_height);
    704         p_srcY += (16 * surface_height);
    705         for (i = 0; i < src_height; i++) {
    706             memcpy(p_dstY + dstY_stride * i + n * 16, tmp_dstY + 16 * i, 16);
    707         }
    708     }
    709 
    710     /* Copy U/V data */
    711     for (n = 0; n < src_width / 16; n++) {
    712         memcpy((void*)tmp_dstUV, p_srcUV, 16 * src_height / 2);
    713         p_srcUV += (16 * surface_height / 2);
    714         for (i = 0; i < src_height / 2; i++) {
    715             for (index = 0; index < 8; index++) {
    716                 p_dstU[i*dstU_stride + n*8 + index] = tmp_dstUV[index*2 + i*16];
    717                 p_dstV[i*dstV_stride + n*8 + index] = tmp_dstUV[index*2 + i*16+1];
    718             }
    719         }
    720     }
    721     if (tmp_dstY)
    722         free(tmp_dstY);
    723     if (tmp_dstUV)
    724         free(tmp_dstUV);
    725 
    726     return VA_STATUS_SUCCESS;
    727 }
    728 
    729 /*
    730 * Convert the memroy format from tiled to linear
    731 */
    732 static VAStatus tng_unpack_vsp_rec(
    733     int src_width, int src_height,
    734     unsigned char *p_srcY, unsigned char *p_srcUV,
    735     unsigned char *p_dstY, unsigned char *p_dstU,
    736     int dstY_stride, int dstU_stride, int __maybe_unused dstV_stride,
    737     int __maybe_unused surface_height)
    738 {
    739     unsigned char *tmp_dstY = p_dstY;
    740     unsigned char *tmp_dstU = p_dstU;
    741 
    742     int n, t,x,y;
    743 
    744    //"	Y_address(x,y) =    Y_base + (((H            +64+63)/64) * (x/64) + (y/64))*4096 + (y%64)*64 + (x%64)
    745    //"	U_address(x,y) = UV_base + ((((H+1)/2+32+63)/64) * (x/32) + (y/64))*4096 + (y%64)*64 + (x%32)*2
    746    //"	V_address(x,y) = UV_base + ((((H+1)/2+32+63)/64) * (x/32) + (y/64))*4096 + (y%64)*64 + (x%32)*2 + 1
    747 
    748     /*  Copy Y data */
    749     for (y = 32; y < src_height + 32; y++) {
    750         for (x= 32;x < src_width + 32; x++) {
    751             * tmp_dstY++ =  *(p_srcY + (((src_height+64+63)/64) * (x/64) + (y/64))*4096 + (y%64)*64 + (x%64));
    752             }
    753             tmp_dstY += dstY_stride - src_width;
    754     }
    755 
    756     /*  Copy UV data */
    757     for (y = 16; y < 16 + ((src_height+1)>>1) ; y++) {
    758         for (x= 16;x < 16 + ( (src_width+1)>>1); x++) {
    759             * tmp_dstU++ = * (p_srcUV + ((((src_height+1)/2+32+63)/64) * (x/32) + (y/64))*4096 + (y%64)*64 + (x%32)*2);
    760             * tmp_dstU++ = * (p_srcUV + ((((src_height+1)/2+32+63)/64) * (x/32) + (y/64))*4096 + (y%64)*64 + (x%32)*2 +1);
    761             }
    762            tmp_dstU += dstU_stride - ((src_width));
    763     }
    764 
    765     return VA_STATUS_SUCCESS;
    766 }
    767 /*
    768 * Convert the memroy format from tiled to linear
    769 */
    770 static VAStatus tng_unpack_topaz_rec(
    771     int src_width, int src_height,
    772     unsigned char *p_srcY, unsigned char *p_srcUV,
    773     unsigned char *p_dstY, unsigned char *p_dstU, unsigned char *p_dstV,
    774     int dstY_stride, int __maybe_unused dstU_stride, int __maybe_unused dstV_stride,
    775     int __maybe_unused surface_height)
    776 {
    777     unsigned char *tmp_dstY = p_dstY;
    778     unsigned char *tmp_dstU = p_dstU;
    779     unsigned char *tmp_dstV = p_dstV;
    780     unsigned char *tmp_srcY = p_srcY;
    781     unsigned char *tmp_srcX = p_srcUV;
    782 
    783     int i, j, n, t;
    784     int mb_src_y_w = src_width >> 4;
    785     int mb_src_y_h = src_height >> 5;
    786     int mb_src_y_p = src_height - (mb_src_y_h << 5);
    787 
    788     /*  Copy Y data */
    789     for (j = 0; j < mb_src_y_h; j++) {
    790         tmp_dstY = p_dstY + j * dstY_stride * 32;
    791         for (i = 0; i < mb_src_y_w; i++) {
    792             for (n = 0; n < 32; n++) {
    793                 memcpy(tmp_dstY + dstY_stride * n, tmp_srcY,16);
    794                 tmp_srcY += 16;
    795             }
    796             tmp_dstY += 16;
    797         }
    798     }
    799 
    800     if(mb_src_y_p != 0) {
    801         tmp_dstY = p_dstY + j * dstY_stride * 32;
    802         for (i = 0; i < mb_src_y_w; i++) {
    803             for (n = 0; n < mb_src_y_p; n++) {
    804                 memcpy(tmp_dstY + dstY_stride * n, tmp_srcY,16);
    805                 tmp_srcY += 16;
    806             }
    807             for (; n < 32; n++) {
    808                 tmp_srcY += 16;
    809             }
    810             tmp_dstY += 16;
    811         }
    812     }
    813 
    814     for (j = 0; j < mb_src_y_h; j++) {
    815         tmp_dstU = p_dstU + j * dstY_stride * 16;
    816         for (i = 0; i < mb_src_y_w; i++) {
    817             for (n = 0; n < 16; n++) {
    818                 for (t = 0; t < 16; t++) {
    819                     tmp_dstU[(n * dstY_stride) + t] = tmp_srcX[t];
    820                 }
    821                 tmp_srcX += 16;
    822             }
    823             tmp_dstU += 16;
    824         }
    825     }
    826     mb_src_y_p >>= 1;
    827     if(mb_src_y_p != 0) {
    828         tmp_dstU = p_dstU + j * dstY_stride * 16;
    829         for (i = 0; i < mb_src_y_w; i++) {
    830             for (n = 0; n < mb_src_y_p; n++) {
    831                 for (t = 0; t < 16; t++) {
    832                    tmp_dstU[(n * dstY_stride) + t] = tmp_srcX[t];
    833                 }
    834                 tmp_srcX += 16;
    835             }
    836 
    837             for (; n < 16; n++) {
    838                 tmp_srcX += 16;
    839             }
    840 
    841             tmp_dstU += 16;
    842         }
    843     }
    844 
    845     return VA_STATUS_SUCCESS;
    846 }
    847 
    848 VAStatus psb_GetImage(
    849     VADriverContextP ctx,
    850     VASurfaceID surface,
    851     int x,     /* coordinates of the upper left source pixel */
    852     int y,
    853     unsigned int width, /* width and height of the region */
    854     unsigned int height,
    855     VAImageID image_id
    856 )
    857 {
    858     INIT_DRIVER_DATA;
    859     VAStatus vaStatus = VA_STATUS_SUCCESS;
    860     int ret, src_x = 0, src_y = 0, dest_x = 0, dest_y = 0;
    861 
    862     (void)driver_data;
    863     (void)lnc_unpack_topaz_rec;
    864 
    865     object_image_p obj_image = IMAGE(image_id);
    866     CHECK_IMAGE(obj_image);
    867 
    868     if (IS_MFLD(driver_data) && (psb_CheckIEDStatus(ctx) == 1)) {
    869         vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
    870         return vaStatus;
    871     }
    872 
    873     if (obj_image->image.format.fourcc != VA_FOURCC_NV12) {
    874         drv_debug_msg(VIDEO_DEBUG_ERROR, "target VAImage fourcc should be NV12 or IYUV\n");
    875         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
    876         return vaStatus;
    877     }
    878 
    879     object_surface_p obj_surface = SURFACE(surface);
    880     CHECK_SURFACE(obj_surface);
    881 
    882     psb__VAImageCheckRegion(obj_surface, &obj_image->image, &src_x, &src_y, &dest_x, &dest_y,
    883                             (int *)&width, (int *)&height);
    884 
    885     psb_surface_p psb_surface = obj_surface->psb_surface;
    886     unsigned char *surface_data;
    887     ret = psb_buffer_map(&psb_surface->buf, &surface_data);
    888     if (ret) {
    889         return VA_STATUS_ERROR_UNKNOWN;
    890     }
    891 
    892     object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
    893     CHECK_BUFFER(obj_buffer);
    894 
    895     unsigned char *image_data;
    896     ret = psb_buffer_map(obj_buffer->psb_buffer, &image_data);
    897     if (ret) {
    898         drv_debug_msg(VIDEO_DEBUG_ERROR, "Map buffer failed\n");
    899 
    900         psb_buffer_unmap(&psb_surface->buf);
    901         return VA_STATUS_ERROR_UNKNOWN;
    902     }
    903 
    904 
    905     image_data += obj_surface->psb_surface->buf.buffer_ofs;
    906 
    907 
    908     switch (obj_image->image.format.fourcc) {
    909     case VA_FOURCC_NV12: {
    910         unsigned char *src_y, *src_uv, *dst_y, *dst_uv;
    911 	unsigned char *dst_u, *dst_v;
    912         unsigned int i;
    913 
    914 	/*
    915 	 * For reconstructed frame, tiled to linear conversion
    916 	 * must be done.
    917 	*/
    918 	if (obj_surface->is_ref_surface == 1) {
    919 	    src_y = surface_data + y * psb_surface->stride + x;
    920 	    src_uv = surface_data + ((height + 0x1f) & (~0x1f)) * width;
    921 
    922 	    dst_y = image_data;
    923 	    dst_u = image_data + obj_image->image.offsets[1],
    924 	    dst_v = dst_u + (height * width) / 4;
    925 
    926 	    tng_unpack_topaz_rec(width, height, \
    927 				 src_y, src_uv, \
    928 			         dst_y, dst_u, dst_v, \
    929 			         obj_image->image.pitches[0], \
    930 			         obj_image->image.width / 2, \
    931 			         obj_image->image.width / 2, \
    932 			         obj_surface->height);
    933 	} else if (obj_surface->is_ref_surface == 2) {
    934 	    src_y = surface_data + y * psb_surface->stride + x;
    935 	    src_uv = surface_data + ((height + 2*32 + 63)/64*64) * ((width  + 2*32 + 63)/64*64);
    936 	    dst_y = image_data;
    937 	    dst_u = image_data +  obj_image->image.offsets[1];
    938 
    939 	    tng_unpack_vsp_rec(width, height, \
    940 				 src_y, src_uv, \
    941 			         dst_y, dst_u, \
    942 			         obj_image->image.pitches[0], \
    943 			         obj_image->image.pitches[1], \
    944 			         obj_image->image.pitches[1], \
    945 			         obj_surface->height);
    946 	} else{
    947             /* copy Y plane */
    948             dst_y = image_data;
    949             src_y = surface_data + y * psb_surface->stride + x;
    950             for (i = 0; i < height; i++)  {
    951 		memcpy(dst_y, src_y, width);
    952 		dst_y += obj_image->image.pitches[0];
    953 		src_y += psb_surface->stride;
    954             }
    955 
    956 	    /* copy UV plane */
    957 	    dst_uv = image_data + obj_image->image.offsets[1];
    958             src_uv = surface_data + psb_surface->stride * obj_surface->height + (y / 2) * psb_surface->stride + x;;
    959             for (i = 0; i < obj_image->image.height / 2; i++) {
    960 		memcpy(dst_uv, src_uv, width);
    961 		dst_uv += obj_image->image.pitches[1];
    962 		src_uv += psb_surface->stride;
    963 	    }
    964 	}
    965         break;
    966     }
    967 #if 0
    968     case VA_FOURCC_IYUV: {
    969         unsigned char *source_y, *dst_y;
    970         unsigned char *source_uv, *source_u, *source_v, *dst_u, *dst_v;
    971         unsigned int i;
    972 
    973         if (psb_surface->extra_info[4] == VA_FOURCC_IREC) {
    974             /* copy Y plane */
    975             dst_y = image_data + obj_image->image.offsets[0] + src_y * obj_image->image.pitches[0] + src_x;
    976             dst_u = image_data + obj_image->image.offsets[1] + src_y * obj_image->image.pitches[1] + src_x;
    977             dst_v = image_data + obj_image->image.offsets[2] + src_y * obj_image->image.pitches[2] + src_x;
    978 
    979             source_y = surface_data + dest_y * psb_surface->stride + dest_x;
    980             source_uv = surface_data + obj_surface->height * psb_surface->stride
    981                         + dest_y * (psb_surface->stride / 2) + dest_x;
    982 
    983             vaStatus = lnc_unpack_topaz_rec(width, height, source_y, source_uv,
    984                                             dst_y, dst_u, dst_v,
    985                                             obj_image->image.pitches[0],
    986                                             obj_image->image.pitches[1],
    987                                             obj_image->image.pitches[2],
    988                                             obj_surface->height);
    989         }
    990 
    991         break;
    992     }
    993 #endif
    994     default:
    995         break;
    996     }
    997     psb_buffer_unmap(obj_buffer->psb_buffer);
    998     psb_buffer_unmap(&psb_surface->buf);
    999 
   1000     return vaStatus;
   1001 }
   1002 
   1003 static VAStatus psb_PutImage2(
   1004     VADriverContextP ctx,
   1005     VASurfaceID surface,
   1006     VAImageID image_id,
   1007     int src_x,
   1008     int src_y,
   1009     unsigned int width,
   1010     unsigned int height,
   1011     int dest_x,
   1012     int dest_y
   1013 )
   1014 {
   1015     INIT_DRIVER_DATA;
   1016     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1017     int ret;
   1018 
   1019     object_image_p obj_image = IMAGE(image_id);
   1020     CHECK_IMAGE(obj_image);
   1021 
   1022     object_surface_p obj_surface = SURFACE(surface);
   1023     CHECK_SURFACE(obj_surface);
   1024 
   1025     if (obj_image->image.format.fourcc != VA_FOURCC_NV12) {
   1026         drv_debug_msg(VIDEO_DEBUG_ERROR, "target VAImage fourcc should be NV12 or IYUV\n");
   1027         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
   1028         return vaStatus;
   1029     }
   1030 
   1031     psb__VAImageCheckRegion(obj_surface, &obj_image->image, &src_x, &src_y, &dest_x, &dest_y,
   1032                             (int *)&width, (int *)&height);
   1033 
   1034     psb_surface_p psb_surface = obj_surface->psb_surface;
   1035     unsigned char *surface_data;
   1036     ret = psb_buffer_map(&psb_surface->buf, &surface_data);
   1037     if (ret) {
   1038         return VA_STATUS_ERROR_UNKNOWN;
   1039     }
   1040 
   1041     object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
   1042     CHECK_BUFFER(obj_buffer);
   1043 
   1044     unsigned char *image_data;
   1045     ret = psb_buffer_map(obj_buffer->psb_buffer, &image_data);
   1046     if (ret) {
   1047         psb_buffer_unmap(&psb_surface->buf);
   1048         return VA_STATUS_ERROR_UNKNOWN;
   1049     }
   1050 
   1051     image_data += obj_surface->psb_surface->buf.buffer_ofs;
   1052 
   1053     switch (obj_image->image.format.fourcc) {
   1054     case VA_FOURCC_NV12: {
   1055         unsigned char *source_y, *src_uv, *dst_y, *dst_uv;
   1056         unsigned int i;
   1057 
   1058         /* copy Y plane */
   1059         source_y = image_data + obj_image->image.offsets[0] + src_y * obj_image->image.pitches[0] + src_x;
   1060         dst_y = surface_data + dest_y * psb_surface->stride + dest_x;
   1061         for (i = 0; i < height; i++)  {
   1062             memcpy(dst_y, source_y, width);
   1063             source_y += obj_image->image.pitches[0];
   1064             dst_y += psb_surface->stride;
   1065         }
   1066 
   1067         /* copy UV plane */
   1068         src_uv = image_data + obj_image->image.offsets[1] + (src_y / 2) * obj_image->image.pitches[1] + src_x;
   1069         dst_uv = surface_data + psb_surface->stride * obj_surface->height + (dest_y / 2) * psb_surface->stride + dest_x;
   1070         for (i = 0; i < obj_image->image.height / 2; i++) {
   1071             memcpy(dst_uv, src_uv, width);
   1072             src_uv += obj_image->image.pitches[1];
   1073             dst_uv += psb_surface->stride;
   1074         }
   1075         break;
   1076     }
   1077 #if 0
   1078     case VA_FOURCC_IYUV: {
   1079         char *source_y, *dst_y;
   1080         char *source_u, *source_v, *dst_u, *dst_v;
   1081         unsigned int i;
   1082 
   1083         /* copy Y plane */
   1084         source_y = image_data + obj_image->image.offsets[0] + src_y * obj_image->image.pitches[0] + src_x;
   1085         source_u = image_data + obj_image->image.offsets[1] + src_y * obj_image->image.pitches[1] + src_x;
   1086         source_v = image_data + obj_image->image.offsets[2] + src_y * obj_image->image.pitches[2] + src_x;
   1087 
   1088         dst_y = surface_data + dest_y * psb_surface->stride + dest_x;
   1089         dst_u = surface_data + obj_surface->height * psb_surface->stride
   1090                 + dest_y * (psb_surface->stride / 2) + dest_x;
   1091         dst_v = surface_data + obj_surface->height * psb_surface->stride
   1092                 + (obj_surface->height / 2) * (psb_surface->stride / 2)
   1093                 + dest_y * (psb_surface->stride / 2) + dest_x;
   1094 
   1095         for (i = 0; i < height; i++)  {
   1096             memcpy(dst_y, source_y, width);
   1097             source_y += obj_image->image.pitches[0];
   1098             dst_y += psb_surface->stride;
   1099         }
   1100 
   1101         /* copy UV plane */
   1102         for (i = 0; i < obj_image->image.height / 2; i++) {
   1103             memcpy(dst_u, source_u, width);
   1104             memcpy(dst_v, source_v, width);
   1105 
   1106             source_u += obj_image->image.pitches[1];
   1107             source_v += obj_image->image.pitches[2];
   1108 
   1109             dst_u += psb_surface->stride / 2;
   1110             dst_v += psb_surface->stride / 2;
   1111         }
   1112         break;
   1113     }
   1114 #endif
   1115     default:
   1116         break;
   1117     }
   1118 
   1119     psb_buffer_unmap(obj_buffer->psb_buffer);
   1120     psb_buffer_unmap(&psb_surface->buf);
   1121 
   1122     return VA_STATUS_SUCCESS;
   1123 }
   1124 
   1125 
   1126 static void psb__VAImageCheckRegion2(
   1127     object_surface_p surface,
   1128     VAImage *image,
   1129     int *src_x,
   1130     int *src_y,
   1131     unsigned int *src_width,
   1132     unsigned int *src_height,
   1133     int *dest_x,
   1134     int *dest_y,
   1135     int *dest_width,
   1136     int *dest_height
   1137 )
   1138 {
   1139     /* check for image */
   1140     if (*src_x < 0) *src_x = 0;
   1141     if (*src_x > image->width) *src_x = image->width - 1;
   1142     if (*src_y < 0) *src_y = 0;
   1143     if (*src_y > image->height) *src_y = image->height - 1;
   1144 
   1145     if (((*src_width) + (*src_x)) > image->width) *src_width = image->width - *src_x;
   1146     if (((*src_height) + (*src_y)) > image->height) *src_height = image->height - *src_x;
   1147 
   1148     /* check for surface */
   1149     if (*dest_x < 0) *dest_x = 0;
   1150     if (*dest_x > surface->width) *dest_x = surface->width - 1;
   1151     if (*dest_y < 0) *dest_y = 0;
   1152     if (*dest_y > surface->height) *dest_y = surface->height - 1;
   1153 
   1154     if (((*dest_width) + (*dest_x)) > (int)surface->width) *dest_width = surface->width - *dest_x;
   1155     if (((*dest_height) + (*dest_y)) > (int)surface->height) *dest_height = surface->height - *dest_x;
   1156 }
   1157 
   1158 VAStatus psb_PutImage(
   1159     VADriverContextP ctx,
   1160     VASurfaceID surface,
   1161     VAImageID image_id,
   1162     int src_x,
   1163     int src_y,
   1164     unsigned int src_width,
   1165     unsigned int src_height,
   1166     int dest_x,
   1167     int dest_y,
   1168     unsigned int dest_width,
   1169     unsigned int dest_height
   1170 )
   1171 {
   1172     INIT_DRIVER_DATA;
   1173     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1174     int ret;
   1175     CHECK_INVALID_PARAM(((int)src_width == -1) ||
   1176                         ((int)src_height == -1) ||
   1177                         ((int)dest_width == ~0) ||
   1178                         ((int)dest_height == ~0));
   1179 
   1180     if ((src_width == dest_width) && (src_height == dest_height)) {
   1181         /* Shortcut if scaling is not required */
   1182         return psb_PutImage2(ctx, surface, image_id, src_x, src_y, src_width, src_height, dest_x, dest_y);
   1183     }
   1184 
   1185     object_image_p obj_image = IMAGE(image_id);
   1186     CHECK_IMAGE(obj_image);
   1187 
   1188     if (obj_image->image.format.fourcc != VA_FOURCC_NV12) {
   1189         /* only support NV12 getImage/putImage */
   1190         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
   1191         return vaStatus;
   1192     }
   1193 
   1194     object_surface_p obj_surface = SURFACE(surface);
   1195     CHECK_SURFACE(obj_surface);
   1196 
   1197     psb__VAImageCheckRegion2(obj_surface, &obj_image->image,
   1198                              &src_x, &src_y, &src_width, &src_height,
   1199                              &dest_x, &dest_y, (int *)&dest_width, (int *)&dest_height);
   1200 
   1201     psb_surface_p psb_surface = obj_surface->psb_surface;
   1202     unsigned char *surface_data;
   1203     ret = psb_buffer_map(&psb_surface->buf, &surface_data);
   1204     if (ret) {
   1205         return VA_STATUS_ERROR_UNKNOWN;
   1206     }
   1207 
   1208     object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
   1209     CHECK_BUFFER(obj_buffer);
   1210 
   1211     unsigned char *image_data;
   1212     ret = psb_buffer_map(obj_buffer->psb_buffer, &image_data);
   1213     if (ret) {
   1214         psb_buffer_unmap(&psb_surface->buf);
   1215         return VA_STATUS_ERROR_UNKNOWN;
   1216     }
   1217 
   1218     /* just a prototype, the algorithm is ugly and not optimized */
   1219     switch (obj_image->image.format.fourcc) {
   1220     case VA_FOURCC_NV12: {
   1221         unsigned char *source_y, *dst_y;
   1222         unsigned short *source_uv, *dst_uv;
   1223         unsigned int i, j;
   1224         float xratio = (float) src_width / dest_width;
   1225         float yratio = (float) src_height / dest_height;
   1226 
   1227         /* dst_y/dst_uv: Y/UV plane of destination */
   1228         dst_y = (unsigned char *)(surface_data + dest_y * psb_surface->stride + dest_x);
   1229         dst_uv = (unsigned short *)(surface_data + psb_surface->stride * obj_surface->height
   1230                                     + (dest_y / 2) * psb_surface->stride + dest_x);
   1231 
   1232         for (j = 0; j < dest_height; j++)  {
   1233             unsigned char *dst_y_tmp = dst_y;
   1234             unsigned short *dst_uv_tmp = dst_uv;
   1235 
   1236             for (i = 0; i < dest_width; i++)  {
   1237                 int x = (int)(i * xratio);
   1238                 int y = (int)(j * yratio);
   1239 
   1240                 source_y = image_data + obj_image->image.offsets[0]
   1241                            + (src_y + y) * obj_image->image.pitches[0]
   1242                            + (src_x + x);
   1243                 *dst_y_tmp = *source_y;
   1244                 dst_y_tmp++;
   1245 
   1246                 if (((i & 1) == 0)) {
   1247                     source_uv = (unsigned short *)(image_data + obj_image->image.offsets[1]
   1248                                                    + ((src_y + y) / 2) * obj_image->image.pitches[1])
   1249                                 + ((src_x + x) / 2);
   1250                     *dst_uv_tmp = *source_uv;
   1251                     dst_uv_tmp++;
   1252                 }
   1253             }
   1254             dst_y += psb_surface->stride;
   1255 
   1256             if (j & 1)
   1257                 dst_uv = (unsigned short *)((unsigned char *)dst_uv + psb_surface->stride);
   1258         }
   1259         break;
   1260     }
   1261     default:/* will not reach here */
   1262         break;
   1263     }
   1264 
   1265     psb_buffer_unmap(obj_buffer->psb_buffer);
   1266     psb_buffer_unmap(&psb_surface->buf);
   1267 
   1268     return VA_STATUS_SUCCESS;
   1269 }
   1270 
   1271 /*
   1272  * Link supbicture into one surface, when update is zero, not need to
   1273  * update the location information
   1274  * The image informatio and its BO of subpicture will copied to surface
   1275  * so need to update it when a vaSetSubpictureImage is called
   1276  */
   1277 static VAStatus psb__LinkSubpictIntoSurface(
   1278     psb_driver_data_p driver_data,
   1279     object_surface_p obj_surface,
   1280     object_subpic_p obj_subpic,
   1281     short src_x,
   1282     short src_y,
   1283     unsigned short src_w,
   1284     unsigned short src_h,
   1285     short dest_x,
   1286     short dest_y,
   1287     unsigned short dest_w,
   1288     unsigned short dest_h,
   1289     int update /* update subpicture location */
   1290 )
   1291 {
   1292     PsbVASurfaceRec *surface_subpic;
   1293     object_image_p obj_image = IMAGE(obj_subpic->image_id);
   1294     if (NULL == obj_image) {
   1295         return VA_STATUS_ERROR_INVALID_IMAGE;
   1296     }
   1297 
   1298     VAImage *image = &obj_image->image;
   1299     object_buffer_p obj_buffer = BUFFER(image->buf);
   1300     if (NULL == obj_buffer) {
   1301         return VA_STATUS_ERROR_INVALID_BUFFER;
   1302     }
   1303 
   1304     int found = 0;
   1305 
   1306     if (obj_surface->subpictures != NULL) {
   1307         surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures;
   1308         do {
   1309             if (surface_subpic->subpic_id == obj_subpic->subpic_id) {
   1310                 found = 1;
   1311                 break;
   1312             } else
   1313                 surface_subpic = surface_subpic->next;
   1314         } while (surface_subpic);
   1315     }
   1316 
   1317     if (found == 0) { /* new node */
   1318         if (obj_surface->subpic_count >= PSB_SUBPIC_MAX_NUM) {
   1319             drv_debug_msg(VIDEO_DEBUG_ERROR, "can't support so many sub-pictures for the surface\n");
   1320             return VA_STATUS_ERROR_UNKNOWN;
   1321         }
   1322 
   1323         surface_subpic = (PsbVASurfaceRec *)calloc(1, sizeof(*surface_subpic));
   1324         if (NULL == surface_subpic)
   1325             return VA_STATUS_ERROR_ALLOCATION_FAILED;
   1326     }
   1327 
   1328     surface_subpic->subpic_id = obj_subpic->subpic_id;
   1329     surface_subpic->fourcc = image->format.fourcc;
   1330     surface_subpic->size = image->data_size;
   1331     surface_subpic->bo = obj_buffer->psb_buffer->drm_buf;
   1332     surface_subpic->bufid = wsbmKBufHandle(wsbmKBuf(obj_buffer->psb_buffer->drm_buf));
   1333     surface_subpic->pl_flags = obj_buffer->psb_buffer->pl_flags;
   1334     surface_subpic->subpic_flags = obj_subpic->flags;
   1335 
   1336     surface_subpic->width = image->width;
   1337     surface_subpic->height = image->height;
   1338     switch (surface_subpic->fourcc) {
   1339     case VA_FOURCC_AYUV:
   1340         surface_subpic->stride = image->pitches[0] / 4;
   1341         break;
   1342     case VA_FOURCC_RGBA:
   1343         surface_subpic->stride = image->pitches[0] / 4;
   1344         break;
   1345     case VA_FOURCC_AI44:
   1346         surface_subpic->stride = image->pitches[0];
   1347         /* point to Image palette */
   1348         surface_subpic->palette_ptr = (PsbAYUVSample8 *) & obj_image->palette[0];
   1349         break;
   1350     }
   1351 
   1352     if (update) {
   1353         surface_subpic->subpic_srcx = src_x;
   1354         surface_subpic->subpic_srcy = src_y;
   1355         surface_subpic->subpic_dstx = dest_x;
   1356         surface_subpic->subpic_dsty = dest_y;
   1357         surface_subpic->subpic_srcw = src_w;
   1358         surface_subpic->subpic_srch = src_h;
   1359         surface_subpic->subpic_dstw = dest_w;
   1360         surface_subpic->subpic_dsth = dest_h;
   1361     }
   1362 
   1363     if (found == 0) { /* new node, link into the list */
   1364         if (NULL == obj_surface->subpictures) {
   1365             obj_surface->subpictures = (void *)surface_subpic;
   1366         } else { /* insert as the head */
   1367             surface_subpic->next = (PsbVASurfacePtr)obj_surface->subpictures;
   1368             obj_surface->subpictures = (void *)surface_subpic;
   1369         }
   1370         obj_surface->subpic_count++;
   1371     }
   1372 
   1373     return VA_STATUS_SUCCESS;
   1374 }
   1375 
   1376 
   1377 static VAStatus psb__LinkSurfaceIntoSubpict(
   1378     object_subpic_p obj_subpic,
   1379     VASurfaceID surface_id
   1380 )
   1381 {
   1382     subpic_surface_s *subpic_surface;
   1383     int found = 0;
   1384 
   1385     if (obj_subpic->surfaces != NULL) {
   1386         subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
   1387         do  {
   1388             if (subpic_surface->surface_id == surface_id) {
   1389                 found = 1;
   1390                 return VA_STATUS_SUCCESS; /* reture directly */
   1391             } else
   1392                 subpic_surface = subpic_surface->next;
   1393         } while (subpic_surface);
   1394     }
   1395 
   1396     /* not found */
   1397     subpic_surface = (subpic_surface_s *)calloc(1, sizeof(*subpic_surface));
   1398     if (NULL == subpic_surface)
   1399         return VA_STATUS_ERROR_ALLOCATION_FAILED;
   1400 
   1401     subpic_surface->surface_id = surface_id;
   1402     subpic_surface->next = NULL;
   1403 
   1404     if (NULL == obj_subpic->surfaces) {
   1405         obj_subpic->surfaces = (void *)subpic_surface;
   1406     } else { /* insert as the head */
   1407         subpic_surface->next = (subpic_surface_p)obj_subpic->surfaces;
   1408         obj_subpic->surfaces = (void *)subpic_surface;
   1409     }
   1410 
   1411     return VA_STATUS_SUCCESS;
   1412 }
   1413 
   1414 static VAStatus psb__DelinkSubpictFromSurface(
   1415     object_surface_p obj_surface,
   1416     VASubpictureID subpic_id
   1417 )
   1418 {
   1419     PsbVASurfaceRec *surface_subpic, *pre_surface_subpic = NULL;
   1420     int found = 0;
   1421 
   1422     if (obj_surface->subpictures != NULL) {
   1423         surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures;
   1424         do  {
   1425             if (surface_subpic->subpic_id == subpic_id) {
   1426                 found = 1;
   1427                 break;
   1428             } else {
   1429                 pre_surface_subpic = surface_subpic;
   1430                 surface_subpic = surface_subpic->next;
   1431             }
   1432         } while (surface_subpic);
   1433     }
   1434 
   1435     if (found == 1) {
   1436         if (pre_surface_subpic == NULL) { /* remove the first node */
   1437             obj_surface->subpictures = (void *)surface_subpic->next;
   1438         } else {
   1439             pre_surface_subpic->next = surface_subpic->next;
   1440         }
   1441         free(surface_subpic);
   1442         obj_surface->subpic_count--;
   1443     }
   1444 
   1445     return VA_STATUS_SUCCESS;
   1446 }
   1447 
   1448 
   1449 static VAStatus psb__DelinkSurfaceFromSubpict(
   1450     object_subpic_p obj_subpic,
   1451     VASurfaceID surface_id
   1452 )
   1453 {
   1454     subpic_surface_s *subpic_surface, *pre_subpic_surface = NULL;
   1455     int found = 0;
   1456 
   1457     if (obj_subpic->surfaces != NULL) {
   1458         subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
   1459         do {
   1460             if (subpic_surface->surface_id == surface_id) {
   1461                 found = 1;
   1462                 break;
   1463             } else {
   1464                 pre_subpic_surface = subpic_surface;
   1465                 subpic_surface = subpic_surface->next;
   1466             }
   1467         } while (subpic_surface);
   1468     }
   1469 
   1470     if (found == 1) {
   1471         if (pre_subpic_surface == NULL) { /* remove the first node */
   1472             obj_subpic->surfaces = (void *)subpic_surface->next;
   1473         } else {
   1474             pre_subpic_surface->next = subpic_surface->next;
   1475         }
   1476         free(subpic_surface);
   1477     }
   1478 
   1479     return VA_STATUS_SUCCESS;
   1480 }
   1481 
   1482 
   1483 VAStatus psb_QuerySubpictureFormats(
   1484     VADriverContextP __maybe_unused ctx,
   1485     VAImageFormat *format_list,        /* out */
   1486     unsigned int *flags,       /* out */
   1487     unsigned int *num_formats  /* out */
   1488 )
   1489 {
   1490     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1491 
   1492     CHECK_INVALID_PARAM(format_list == NULL);
   1493     CHECK_INVALID_PARAM(flags == NULL);
   1494     CHECK_INVALID_PARAM(num_formats == NULL);
   1495 
   1496     memcpy(format_list, psb__SubpicFormat, sizeof(psb__SubpicFormat));
   1497     *num_formats = PSB_MAX_SUBPIC_FORMATS;
   1498     *flags = PSB_SUPPORTED_SUBPIC_FLAGS;
   1499 
   1500     return VA_STATUS_SUCCESS;
   1501 }
   1502 
   1503 
   1504 VAStatus psb_CreateSubpicture(
   1505     VADriverContextP ctx,
   1506     VAImageID image,
   1507     VASubpictureID *subpicture   /* out */
   1508 )
   1509 {
   1510     INIT_DRIVER_DATA;
   1511     VASubpictureID subpicID;
   1512     object_subpic_p obj_subpic;
   1513     object_image_p obj_image;
   1514     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1515     VAImageFormat *img_fmt;
   1516 
   1517     obj_image = IMAGE(image);
   1518     CHECK_IMAGE(obj_image);
   1519     CHECK_SUBPICTURE(subpicture);
   1520 
   1521     img_fmt = psb__VAImageCheckFourCC(&obj_image->image.format, psb__SubpicFormat,
   1522                                       sizeof(psb__SubpicFormat) / sizeof(VAImageFormat));
   1523     if (img_fmt == NULL)
   1524         return VA_STATUS_ERROR_UNKNOWN;
   1525 
   1526     subpicID = object_heap_allocate(&driver_data->subpic_heap);
   1527     obj_subpic = SUBPIC(subpicID);
   1528     CHECK_ALLOCATION(obj_subpic);
   1529 
   1530     MEMSET_OBJECT(obj_subpic, struct object_subpic_s);
   1531 
   1532     obj_subpic->subpic_id = subpicID;
   1533     obj_subpic->image_id = obj_image->image.image_id;
   1534     obj_subpic->surfaces = NULL;
   1535     obj_subpic->global_alpha = 255;
   1536 
   1537     obj_image->subpic_ref ++;
   1538 
   1539     *subpicture = subpicID;
   1540 
   1541     return VA_STATUS_SUCCESS;
   1542 }
   1543 
   1544 
   1545 
   1546 VAStatus psb__destroy_subpicture(psb_driver_data_p driver_data, object_subpic_p obj_subpic)
   1547 {
   1548     subpic_surface_s *subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
   1549     VASubpictureID subpicture = obj_subpic->subpic_id;
   1550 
   1551     if (subpic_surface) {
   1552         do {
   1553             subpic_surface_s *tmp = subpic_surface;
   1554             object_surface_p obj_surface = SURFACE(subpic_surface->surface_id);
   1555 
   1556             if (obj_surface) { /* remove subpict from surface */
   1557                 psb__DelinkSubpictFromSurface(obj_surface, subpicture);
   1558             }
   1559             subpic_surface = subpic_surface->next;
   1560             free(tmp);
   1561         } while (subpic_surface);
   1562     }
   1563 
   1564     object_heap_free(&driver_data->subpic_heap, (object_base_p) obj_subpic);
   1565     return VA_STATUS_SUCCESS;
   1566 }
   1567 
   1568 
   1569 VAStatus psb_DestroySubpicture(
   1570     VADriverContextP ctx,
   1571     VASubpictureID subpicture
   1572 )
   1573 {
   1574     INIT_DRIVER_DATA;
   1575     object_subpic_p obj_subpic;
   1576     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1577 
   1578     obj_subpic = SUBPIC(subpicture);
   1579     CHECK_SUBPICTURE(obj_subpic);
   1580 
   1581     return psb__destroy_subpicture(driver_data, obj_subpic);
   1582 }
   1583 
   1584 VAStatus psb_SetSubpictureImage(
   1585     VADriverContextP ctx,
   1586     VASubpictureID subpicture,
   1587     VAImageID image
   1588 )
   1589 {
   1590     INIT_DRIVER_DATA;
   1591     object_subpic_p obj_subpic;
   1592     object_image_p obj_image;
   1593     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1594     subpic_surface_s *subpic_surface;
   1595     VAImageFormat *img_fmt;
   1596 
   1597     obj_image = IMAGE(image);
   1598     CHECK_IMAGE(obj_image);
   1599 
   1600     img_fmt = psb__VAImageCheckFourCC(&obj_image->image.format,
   1601                                       psb__SubpicFormat,
   1602                                       sizeof(psb__SubpicFormat) / sizeof(VAImageFormat));
   1603     CHECK_IMAGE(img_fmt);
   1604 
   1605     obj_subpic = SUBPIC(subpicture);
   1606     CHECK_SUBPICTURE(obj_subpic);
   1607 
   1608     object_image_p old_obj_image = IMAGE(obj_subpic->image_id);
   1609     if (old_obj_image) {
   1610         old_obj_image->subpic_ref--;/* decrease reference count */
   1611     }
   1612 
   1613     /* reset the image */
   1614     obj_subpic->image_id = obj_image->image.image_id;
   1615     obj_image->subpic_ref ++;
   1616 
   1617     /* relink again */
   1618     if (obj_subpic->surfaces != NULL) {
   1619         /* the subpicture already linked into surfaces
   1620          * so not check the return value of psb__LinkSubpictIntoSurface
   1621          */
   1622         subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
   1623         do {
   1624             object_surface_p obj_surface = SURFACE(subpic_surface->surface_id);
   1625             CHECK_SURFACE(obj_surface);
   1626 
   1627             psb__LinkSubpictIntoSurface(driver_data, obj_surface, obj_subpic,
   1628                                         0, 0, 0, 0, 0, 0, 0, 0,
   1629                                         0 /* not update location */
   1630                                        );
   1631             subpic_surface = subpic_surface->next;
   1632         } while (subpic_surface);
   1633     }
   1634 
   1635 
   1636     return VA_STATUS_SUCCESS;
   1637 }
   1638 
   1639 
   1640 VAStatus psb_SetSubpictureChromakey(
   1641     VADriverContextP ctx,
   1642     VASubpictureID subpicture,
   1643     unsigned int chromakey_min,
   1644     unsigned int chromakey_max,
   1645     unsigned int chromakey_mask
   1646 )
   1647 {
   1648     INIT_DRIVER_DATA;
   1649     (void)driver_data;
   1650     /* TODO */
   1651     if ((chromakey_mask < chromakey_min) || (chromakey_mask > chromakey_max)) {
   1652         drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid chromakey value %d, chromakey value should between min and max\n", chromakey_mask);
   1653         return VA_STATUS_ERROR_INVALID_PARAMETER;
   1654     }
   1655     object_subpic_p obj_subpic = SUBPIC(subpicture);
   1656     if (NULL == obj_subpic) {
   1657         drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid subpicture value %d\n", subpicture);
   1658         return VA_STATUS_ERROR_INVALID_SUBPICTURE;
   1659     }
   1660 
   1661     return VA_STATUS_SUCCESS;
   1662 }
   1663 
   1664 VAStatus psb_SetSubpictureGlobalAlpha(
   1665     VADriverContextP ctx,
   1666     VASubpictureID subpicture,
   1667     float global_alpha
   1668 )
   1669 {
   1670     INIT_DRIVER_DATA;
   1671 
   1672     if (global_alpha < 0 || global_alpha > 1) {
   1673         drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid global alpha value %07f, global alpha value should between 0 and 1\n", global_alpha);
   1674         return VA_STATUS_ERROR_INVALID_PARAMETER;
   1675     }
   1676 
   1677     object_subpic_p obj_subpic = SUBPIC(subpicture);
   1678     if (NULL == obj_subpic) {
   1679         drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid subpicture value %d\n", subpicture);
   1680         return VA_STATUS_ERROR_INVALID_SUBPICTURE;
   1681     }
   1682 
   1683     obj_subpic->global_alpha = global_alpha * 255;
   1684 
   1685     return VA_STATUS_SUCCESS;
   1686 }
   1687 
   1688 
   1689 VAStatus psb__AssociateSubpicture(
   1690     VADriverContextP ctx,
   1691     VASubpictureID subpicture,
   1692     VASurfaceID *target_surfaces,
   1693     int num_surfaces,
   1694     short src_x, /* upper left offset in subpicture */
   1695     short src_y,
   1696     unsigned short src_w,
   1697     unsigned short src_h,
   1698     short dest_x, /* upper left offset in surface */
   1699     short dest_y,
   1700     unsigned short dest_w,
   1701     unsigned short dest_h,
   1702     /*
   1703      * whether to enable chroma-keying or global-alpha
   1704      * see VA_SUBPICTURE_XXX values
   1705      */
   1706     unsigned int flags
   1707 )
   1708 {
   1709     INIT_DRIVER_DATA;
   1710 
   1711     object_subpic_p obj_subpic;
   1712     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1713     int i;
   1714 
   1715     CHECK_INVALID_PARAM(num_surfaces <= 0);
   1716 
   1717     obj_subpic = SUBPIC(subpicture);
   1718     CHECK_SUBPICTURE(obj_subpic);
   1719     CHECK_SURFACE(target_surfaces);
   1720 
   1721     if (flags & ~PSB_SUPPORTED_SUBPIC_FLAGS) {
   1722 #ifdef VA_STATUS_ERROR_FLAG_NOT_SUPPORTED
   1723         vaStatus = VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
   1724 #else
   1725         vaStatus = VA_STATUS_ERROR_UNKNOWN;
   1726 #endif
   1727         DEBUG_FAILURE;
   1728         return vaStatus;
   1729     } else {
   1730 
   1731         /* If flags are ok, copy them to the subpicture object */
   1732         obj_subpic->flags = flags;
   1733 
   1734     }
   1735 
   1736     /* Validate input params */
   1737     for (i = 0; i < num_surfaces; i++) {
   1738         object_surface_p obj_surface = SURFACE(target_surfaces[i]);
   1739         CHECK_SURFACE(obj_surface);
   1740     }
   1741 
   1742     VASurfaceID *surfaces = target_surfaces;
   1743     for (i = 0; i < num_surfaces; i++) {
   1744         object_surface_p obj_surface = SURFACE(*surfaces);
   1745         if (obj_surface) {
   1746             vaStatus = psb__LinkSubpictIntoSurface(driver_data, obj_surface, obj_subpic,
   1747                                                    src_x, src_y, src_w, src_h,
   1748                                                    dest_x, dest_y, dest_w, dest_h, 1);
   1749             if (VA_STATUS_SUCCESS == vaStatus) {
   1750                 vaStatus = psb__LinkSurfaceIntoSubpict(obj_subpic, *surfaces);
   1751             }
   1752             CHECK_VASTATUS();/* failed with malloc */
   1753         } else {
   1754             /* Should never get here */
   1755             drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid surfaces,SurfaceID=0x%x\n", *surfaces);
   1756         }
   1757 
   1758         surfaces++;
   1759     }
   1760 
   1761     return VA_STATUS_SUCCESS;
   1762 }
   1763 
   1764 
   1765 VAStatus psb_AssociateSubpicture(
   1766     VADriverContextP ctx,
   1767     VASubpictureID subpicture,
   1768     VASurfaceID *target_surfaces,
   1769     int num_surfaces,
   1770     short src_x, /* upper left offset in subpicture */
   1771     short src_y,
   1772     unsigned short src_width,
   1773     unsigned short src_height,
   1774     short dest_x, /* upper left offset in surface */
   1775     short dest_y,
   1776     unsigned short dest_width,
   1777     unsigned short dest_height,
   1778     /*
   1779      * whether to enable chroma-keying or global-alpha
   1780      * see VA_SUBPICTURE_XXX values
   1781      */
   1782     unsigned int flags
   1783 )
   1784 {
   1785     return psb__AssociateSubpicture(ctx, subpicture, target_surfaces, num_surfaces,
   1786                                     src_x, src_y, src_width, src_height,
   1787                                     dest_x, dest_y, dest_width, dest_height,
   1788                                     flags
   1789                                    );
   1790 }
   1791 
   1792 
   1793 VAStatus psb_DeassociateSubpicture(
   1794     VADriverContextP ctx,
   1795     VASubpictureID subpicture,
   1796     VASurfaceID *target_surfaces,
   1797     int num_surfaces
   1798 )
   1799 {
   1800     INIT_DRIVER_DATA;
   1801 
   1802     object_subpic_p obj_subpic;
   1803     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1804     object_image_p obj_image;
   1805     int i;
   1806 
   1807     CHECK_INVALID_PARAM(num_surfaces <= 0);
   1808 
   1809     obj_subpic = SUBPIC(subpicture);
   1810     CHECK_SUBPICTURE(obj_subpic);
   1811     CHECK_SURFACE(target_surfaces);
   1812 
   1813     VASurfaceID *surfaces = target_surfaces;
   1814     for (i = 0; i < num_surfaces; i++) {
   1815         object_surface_p obj_surface = SURFACE(*surfaces);
   1816 
   1817         if (obj_surface) {
   1818             psb__DelinkSubpictFromSurface(obj_surface, subpicture);
   1819             psb__DelinkSurfaceFromSubpict(obj_subpic, obj_surface->surface_id);
   1820         } else {
   1821             drv_debug_msg(VIDEO_DEBUG_ERROR, "vaDeassociateSubpicture: Invalid surface, VASurfaceID=0x%08x\n", *surfaces);
   1822         }
   1823 
   1824         surfaces++;
   1825     }
   1826 
   1827     obj_image = IMAGE(obj_subpic->image_id);
   1828     if (obj_image)
   1829         obj_image->subpic_ref--;/* decrease reference count */
   1830 
   1831     return VA_STATUS_SUCCESS;
   1832 }
   1833 
   1834 
   1835 void psb_SurfaceDeassociateSubpict(
   1836     psb_driver_data_p driver_data,
   1837     object_surface_p obj_surface
   1838 )
   1839 {
   1840     PsbVASurfaceRec *surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures;
   1841 
   1842     if (surface_subpic != NULL) {
   1843         do  {
   1844             PsbVASurfaceRec *tmp = surface_subpic;
   1845             object_subpic_p obj_subpic = SUBPIC(surface_subpic->subpic_id);
   1846             if (obj_subpic)
   1847                 psb__DelinkSurfaceFromSubpict(obj_subpic, obj_surface->surface_id);
   1848             surface_subpic = surface_subpic->next;
   1849             free(tmp);
   1850         } while (surface_subpic);
   1851     }
   1852 }
   1853 
   1854 
   1855 static  VADisplayAttribute psb__DisplayAttribute[] = {
   1856     {
   1857         VADisplayAttribBrightness,
   1858         BRIGHTNESS_MIN,
   1859         BRIGHTNESS_MAX,
   1860         BRIGHTNESS_DEFAULT_VALUE,
   1861         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1862     },
   1863 
   1864     {
   1865         VADisplayAttribContrast,
   1866         CONTRAST_MIN,
   1867         CONTRAST_MAX,
   1868         CONTRAST_DEFAULT_VALUE,
   1869         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1870     },
   1871 
   1872     {
   1873         VADisplayAttribHue,
   1874         HUE_MIN,
   1875         HUE_MAX,
   1876         HUE_DEFAULT_VALUE,
   1877         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1878     },
   1879 
   1880     {
   1881         VADisplayAttribSaturation,
   1882         SATURATION_MIN,
   1883         SATURATION_MAX,
   1884         SATURATION_DEFAULT_VALUE,
   1885         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1886     },
   1887     {
   1888         VADisplayAttribBackgroundColor,
   1889         0x00000000,
   1890         0xffffffff,
   1891         0x00000000,
   1892         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1893     },
   1894     {
   1895         VADisplayAttribRotation,
   1896         VA_ROTATION_NONE,
   1897         VA_ROTATION_270,
   1898         VA_ROTATION_NONE,
   1899         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1900     },
   1901     {
   1902         VADisplayAttribOutofLoopDeblock,
   1903         VA_OOL_DEBLOCKING_FALSE,
   1904         VA_OOL_DEBLOCKING_TRUE,
   1905         VA_OOL_DEBLOCKING_FALSE,
   1906         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1907     },
   1908     {
   1909         VADisplayAttribBlendColor,
   1910         0x00000000,
   1911         0xffffffff,
   1912         0x00000000,
   1913         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1914     },
   1915     {
   1916         VADisplayAttribOverlayColorKey,
   1917         0x00000000,
   1918         0xffffffff,
   1919         0x00000000,
   1920         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1921     },
   1922     {
   1923         VADisplayAttribOverlayAutoPaintColorKey,
   1924         0x00000000,
   1925         0xffffffff,
   1926         0x00000000,
   1927         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1928     },
   1929     {
   1930         VADisplayAttribCSCMatrix,
   1931         0x00000000,
   1932         0xffffffff,
   1933         0x00000000,
   1934         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1935     },
   1936     {
   1937         VADisplayAttribRenderDevice,
   1938         0x00000000,
   1939         0xffffffff,
   1940         0x00000000,
   1941         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1942     },
   1943     {
   1944         VADisplayAttribRenderMode,
   1945         0x00000000,
   1946         0xffffffff,
   1947         0x00000000,
   1948         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1949     },
   1950     {
   1951         VADisplayAttribRenderRect,
   1952         0x00000000,
   1953         0xffffffff,
   1954         0x00000000,
   1955         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
   1956     }
   1957 };
   1958 
   1959 /*
   1960  * Query display attributes
   1961  * The caller must provide a "attr_list" array that can hold at
   1962  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
   1963  * returned in "attr_list" is returned in "num_attributes".
   1964  */
   1965 VAStatus psb_QueryDisplayAttributes(
   1966     VADriverContextP __maybe_unused ctx,
   1967     VADisplayAttribute *attr_list,      /* out */
   1968     int *num_attributes         /* out */
   1969 )
   1970 {
   1971     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1972 
   1973     CHECK_INVALID_PARAM(attr_list == NULL);
   1974     CHECK_INVALID_PARAM(num_attributes == NULL);
   1975 
   1976     *num_attributes = min(*num_attributes, PSB_MAX_DISPLAY_ATTRIBUTES);
   1977     memcpy(attr_list, psb__DisplayAttribute, (*num_attributes)*sizeof(VADisplayAttribute));
   1978     return VA_STATUS_SUCCESS;
   1979 }
   1980 
   1981 /*
   1982  * Get display attributes
   1983  * This function returns the current attribute values in "attr_list".
   1984  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
   1985  * from vaQueryDisplayAttributes() can have their values retrieved.
   1986  */
   1987 VAStatus psb_GetDisplayAttributes(
   1988     VADriverContextP ctx,
   1989     VADisplayAttribute *attr_list,      /* in/out */
   1990     int num_attributes
   1991 )
   1992 {
   1993     INIT_DRIVER_DATA;
   1994     VADisplayAttribute *p = attr_list;
   1995     int i;
   1996     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1997 
   1998     CHECK_INVALID_PARAM(attr_list == NULL);
   1999     CHECK_INVALID_PARAM(num_attributes <= 0);
   2000 
   2001     for (i = 0; i < num_attributes; i++) {
   2002         switch (p->type) {
   2003         case VADisplayAttribBrightness:
   2004             /* -50*(1<<10) ~ 50*(1<<10) ==> 0~100*/
   2005             p->value = (driver_data->brightness.value / (1 << 10)) + 50;
   2006             p->min_value = 0;
   2007             p->max_value = 100;
   2008             break;
   2009         case VADisplayAttribContrast:
   2010             /* 0 ~ 2*(1<<25) ==> 0~100 */
   2011             p->value = (driver_data->contrast.value / (1 << 25)) * 50;
   2012             p->min_value = 0;
   2013             p->max_value = 100;
   2014             break;
   2015         case VADisplayAttribHue:
   2016             /* -30*(1<<25) ~ 30*(1<<25) ==> 0~100*/
   2017             p->value = ((driver_data->hue.value / (1 << 25)) + 30) * 10 / 6;
   2018             p->min_value = 0;
   2019             p->max_value = 100;
   2020             break;
   2021         case VADisplayAttribSaturation:
   2022             /* 0 ~ 2*(1<<25) ==> 0~100 */
   2023             p->value = (driver_data->saturation.value / (1 << 25)) * 50;
   2024             p->min_value = 0;
   2025             p->max_value = 100;
   2026             break;
   2027         case VADisplayAttribBackgroundColor:
   2028             p->value = driver_data->clear_color;
   2029             break;
   2030         case VADisplayAttribBlendColor:
   2031             p->value = driver_data->blend_color;
   2032             break;
   2033         case VADisplayAttribOverlayColorKey:
   2034             p->value = driver_data->color_key;
   2035             p->min_value = 0;
   2036             p->max_value = 0xFFFFFF;
   2037             break;
   2038         case VADisplayAttribOverlayAutoPaintColorKey:
   2039             p->value = driver_data->overlay_auto_paint_color_key;
   2040             p->min_value = 0;
   2041             p->max_value = 1;
   2042             break;
   2043         case VADisplayAttribRotation:
   2044             p->value = driver_data->va_rotate = p->value;
   2045             p->min_value = VA_ROTATION_NONE;
   2046             p->max_value = VA_ROTATION_270;
   2047             break;
   2048         case VADisplayAttribOutofLoopDeblock:
   2049             p->value = driver_data->is_oold = p->value;
   2050             p->min_value = VA_OOL_DEBLOCKING_FALSE;
   2051             p->max_value = VA_OOL_DEBLOCKING_TRUE;
   2052             break;
   2053         case VADisplayAttribCSCMatrix:
   2054             p->value = driver_data->load_csc_matrix = p->value;
   2055             p->min_value = 0;
   2056             p->max_value = 255;
   2057             break;
   2058         case VADisplayAttribRenderDevice:
   2059             p->value = driver_data->render_device = p->value;
   2060             p->min_value = 0;
   2061             p->max_value = 255;
   2062             break;
   2063         case VADisplayAttribRenderMode:
   2064             p->value = driver_data->render_mode = p->value;
   2065             p->min_value = 0;
   2066             p->max_value = 255;
   2067             break;
   2068         case VADisplayAttribRenderRect:
   2069             ((VARectangle *)(p->value))->x = driver_data->render_rect.x = ((VARectangle *)(p->value))->x;
   2070             ((VARectangle *)(p->value))->y = driver_data->render_rect.y = ((VARectangle *)(p->value))->y;
   2071             ((VARectangle *)(p->value))->width = driver_data->render_rect.width = ((VARectangle *)(p->value))->width;
   2072             ((VARectangle *)(p->value))->height = driver_data->render_rect.height = ((VARectangle *)(p->value))->height;
   2073             p->min_value = 0;
   2074             p->max_value = 255;
   2075             break;
   2076 
   2077         default:
   2078             break;
   2079         }
   2080         p++;
   2081     }
   2082 
   2083     return VA_STATUS_SUCCESS;
   2084 }
   2085 
   2086 /*
   2087  * Set display attributes
   2088  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
   2089  * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or
   2090  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
   2091  */
   2092 #define CLAMP_ATTR(a,max,min) (a>max?max:(a<min?min:a))
   2093 VAStatus psb_SetDisplayAttributes(
   2094     VADriverContextP ctx,
   2095     VADisplayAttribute *attr_list,
   2096     int num_attributes
   2097 )
   2098 {
   2099     INIT_DRIVER_DATA;
   2100     VAStatus vaStatus = VA_STATUS_SUCCESS;
   2101     struct psb_texture_s *texture_priv = &driver_data->ctexture_priv;
   2102     PsbPortPrivPtr overlay_priv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
   2103     int j, k;
   2104 
   2105     CHECK_INVALID_PARAM(attr_list == NULL);
   2106 
   2107     VADisplayAttribute *p = attr_list;
   2108     int i, update_coeffs = 0;
   2109     unsigned int *p_tmp;
   2110 
   2111     if (num_attributes <= 0) {
   2112         return VA_STATUS_ERROR_INVALID_PARAMETER;
   2113     }
   2114 
   2115     for (i = 0; i < num_attributes; i++) {
   2116         switch (p->type) {
   2117         case VADisplayAttribBrightness:
   2118             /* 0~100 ==> -50*(1<<10) ~ 50*(1<<10)*/
   2119             driver_data->brightness.value = (p->value - 50) * (1 << 10);
   2120             /* 0~100 ==> -50~50 */
   2121             overlay_priv->brightness.Value = texture_priv->brightness.Value = p->value - 50;
   2122             update_coeffs = 1;
   2123             break;
   2124         case VADisplayAttribContrast:
   2125             /* 0~100 ==> 0 ~ 2*(1<<25) */
   2126             driver_data->contrast.value = (p->value / 50) * (1 << 25);
   2127             /* 0~100 ==> -100~100 */
   2128             overlay_priv->contrast.Value = texture_priv->contrast.Value = p->value * 2 - 100;
   2129             update_coeffs = 1;
   2130             break;
   2131         case VADisplayAttribHue:
   2132             /* 0~100 ==> -30*(1<<25) ~ 30*(1<<25) */
   2133             driver_data->hue.value = ((p->value * 2 - 100) * 3 / 10) * (1 << 25);
   2134             /* 0~100 ==> -30~30 */
   2135             overlay_priv->hue.Value = texture_priv->hue.Value = (p->value * 2 - 100) * 3 / 10;
   2136             update_coeffs = 1;
   2137             break;
   2138         case VADisplayAttribSaturation:
   2139             /* 0~100 ==> 0 ~ 2*(1<<25) */
   2140             driver_data->contrast.value = (p->value / 50) * (1 << 25);
   2141             /* 0~100 ==> 100~200 */
   2142             overlay_priv->saturation.Value = texture_priv->saturation.Value = p->value + 100;
   2143             update_coeffs = 1;
   2144             break;
   2145         case VADisplayAttribBackgroundColor:
   2146             driver_data->clear_color = p->value;
   2147             break;
   2148         case VADisplayAttribOutofLoopDeblock:
   2149             driver_data->is_oold = p->value;
   2150             break;
   2151         case VADisplayAttribRotation:
   2152             driver_data->va_rotate = p->value;
   2153             driver_data->rotation_dirty |= PSB_NEW_VA_ROTATION;
   2154             break;
   2155 
   2156         case VADisplayAttribCSCMatrix:
   2157             driver_data->load_csc_matrix = 1;
   2158             p_tmp = (unsigned int *)p->value;
   2159             for (j = 0; j < CSC_MATRIX_Y; j++)
   2160                 for (k = 0; k < CSC_MATRIX_X; k++) {
   2161                     if (p_tmp)
   2162                         driver_data->csc_matrix[j][k] = *p_tmp;
   2163                    p_tmp++;
   2164                 }
   2165             break;
   2166 
   2167         case VADisplayAttribBlendColor:
   2168             driver_data->blend_color = p->value;
   2169             break;
   2170         case VADisplayAttribOverlayColorKey:
   2171             overlay_priv->colorKey = driver_data->color_key = p->value;
   2172             break;
   2173         case VADisplayAttribOverlayAutoPaintColorKey:
   2174             driver_data->overlay_auto_paint_color_key = p->value;
   2175             break;
   2176 
   2177         case VADisplayAttribRenderDevice:
   2178             driver_data->render_device = p->value & VA_RENDER_DEVICE_MASK;
   2179         case VADisplayAttribRenderMode:
   2180 #ifndef ANDROID
   2181             if (p->value & VA_RENDER_MODE_EXTERNAL_GPU) {
   2182                 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s:Invalid parameter.VARenderModeExternalGPU is not supported.\n", __FUNCTION__);
   2183                 return VA_STATUS_ERROR_INVALID_PARAMETER;
   2184             }
   2185             if (((p->value & VA_RENDER_MODE_LOCAL_OVERLAY) && (p->value & VA_RENDER_MODE_LOCAL_GPU)) ||
   2186                 ((p->value & VA_RENDER_MODE_EXTERNAL_OVERLAY) && (p->value & VA_RENDER_MODE_EXTERNAL_GPU))) {
   2187                 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s:Invalid parameter. Conflict setting for VADisplayAttribRenderMode.\n", __FUNCTION__);
   2188                 return VA_STATUS_ERROR_INVALID_PARAMETER;
   2189             }
   2190 #endif
   2191             driver_data->render_mode = p->value & VA_RENDER_MODE_MASK;
   2192             break;
   2193         case VADisplayAttribRenderRect:
   2194             driver_data->render_rect.x = ((VARectangle *)(p->value))->x;
   2195             driver_data->render_rect.y = ((VARectangle *)(p->value))->y;
   2196             driver_data->render_rect.width = ((VARectangle *)(p->value))->width;
   2197             driver_data->render_rect.height = ((VARectangle *)(p->value))->height;
   2198             break;
   2199 
   2200         default:
   2201             break;
   2202         }
   2203         p++;
   2204     }
   2205 
   2206     if (update_coeffs) {
   2207         /* TODO */
   2208 #ifndef ANDROID
   2209         texture_priv->update_coeffs = 1;
   2210 #endif
   2211     }
   2212 
   2213     return VA_STATUS_SUCCESS;
   2214 }
   2215 
   2216