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