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