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