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