1 /* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * Copyright (c) Imagination Technologies Limited, UK 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Binglin Chen <binglin.chen (at) intel.com> 27 * Zhaohan Ren <zhaohan.ren (at) intel.com> 28 * Shengquan Yuan <shengquan.yuan (at) intel.com> 29 */ 30 31 #include <stdio.h> 32 #include <unistd.h> 33 #include <math.h> 34 35 #ifdef ANDROID 36 #include <drm/ttm/ttm_placement.h> 37 #include <linux/psb_drm.h> 38 #else 39 #include <psb_drm.h> 40 #endif 41 42 #include <va/va_backend.h> 43 #include <va/va_drmcommon.h> 44 #include "psb_drv_debug.h" 45 46 #include <wsbm/wsbm_manager.h> 47 48 #ifndef ANDROID 49 #include <X11/Xlib.h> 50 #include "x11/psb_xrandr.h" 51 #include "x11/psb_x11.h" 52 #endif 53 54 #include "mrst/pvr2d.h" 55 56 #include "psb_drv_video.h" 57 #include "psb_output.h" 58 #include "psb_surface_ext.h" 59 60 #include "psb_texture.h" 61 62 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; 63 #define INIT_OUTPUT_PRIV psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv) 64 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id )) 65 #define SUBPIC(id) ((object_subpic_p) object_heap_lookup( &driver_data->subpic_heap, id )) 66 67 #define Degree (2*PI / 360.0) 68 #define PI 3.1415927 69 70 #define OV_HUE_DEFAULT_VALUE 0 71 #define OV_HUE_MIN -30 72 #define OV_HUE_MAX 30 73 74 #define OV_BRIGHTNESS_DEFAULT_VALUE 0 75 #define OV_BRIGHTNESS_MIN -50 76 #define OV_BRIGHTNESS_MAX 50 77 78 #define OV_CONTRAST_DEFAULT_VALUE 0 79 #define OV_CONTRAST_MIN -100 80 #define OV_CONTRAST_MAX 100 81 82 #define OV_SATURATION_DEFAULT_VALUE 100 83 #define OV_SATURATION_MIN 0 84 #define OV_SATURATION_MAX 200 85 86 typedef struct _psb_transform_coeffs_ { 87 double rY, rCb, rCr; 88 double gY, gCb, gCr; 89 double bY, bCb, bCr; 90 } psb_transform_coeffs; 91 92 typedef enum _psb_videotransfermatrix { 93 PSB_VideoTransferMatrixMask = 0x07, 94 PSB_VideoTransferMatrix_Unknown = 0, 95 PSB_VideoTransferMatrix_BT709 = 1, 96 PSB_VideoTransferMatrix_BT601 = 2, 97 PSB_VideoTransferMatrix_SMPTE240M = 3 98 } psb_videotransfermatrix; 99 100 typedef enum _psb_nominalrange { 101 PSB_NominalRangeMask = 0x07, 102 PSB_NominalRange_Unknown = 0, 103 PSB_NominalRange_Normal = 1, 104 PSB_NominalRange_Wide = 2, 105 /* explicit range forms */ 106 PSB_NominalRange_0_255 = 1, 107 PSB_NominalRange_16_235 = 2, 108 PSB_NominalRange_48_208 = 3 109 } psb_nominalrange; 110 111 /* 112 * ITU-R BT.601, BT.709 and SMPTE 240M transfer matrices from VA 2.0 113 * Video Color Field definitions Design Spec(Version 0.03). 114 * [R', G', B'] values are in the range [0, 1], Y' is in the range [0,1] 115 * and [Pb, Pr] components are in the range [-0.5, 0.5]. 116 */ 117 static psb_transform_coeffs s601 = { 118 1, -0.000001, 1.402, 119 1, -0.344136, -0.714136, 120 1, 1.772, 0 121 }; 122 123 static psb_transform_coeffs s709 = { 124 1, 0, 1.5748, 125 1, -0.187324, -0.468124, 126 1, 1.8556, 0 127 }; 128 129 static psb_transform_coeffs s240M = { 130 1, -0.000657, 1.575848, 131 1, -0.226418, -0.476529, 132 1, 1.825958, 0.000378 133 }; 134 135 static void psb_setup_coeffs(struct psb_texture_s * pPriv); 136 static void psb_scale_transfermatrix(psb_transform_coeffs * transfer_matrix, 137 double YColumScale, double CbColumScale, 138 double CrColumnScale); 139 static void psb_select_transfermatrix(struct psb_texture_s * pPriv, 140 psb_transform_coeffs * transfer_matrix, 141 double *Y_offset, double *CbCr_offset, 142 double *RGB_offset); 143 static void psb_create_coeffs(double yOff, double uOff, double vOff, double rgbOff, 144 double yScale, double uScale, double vScale, 145 double brightness, double contrast, 146 double *pYCoeff, double *pUCoeff, double *pVCoeff, 147 double *pConstant); 148 static void psb_convert_coeffs(double Ycoeff, double Ucoeff, double Vcoeff, 149 double ConstantTerm, signed char *pY, signed char *pU, 150 signed char *pV, signed short *constant, 151 unsigned char *pShift); 152 static int psb_check_coeffs(double Ycoeff, double Ucoeff, double Vcoeff, 153 double ConstantTerm, signed char byShift); 154 static void 155 psb_transform_sathuecoeffs(psb_transform_coeffs * dest, 156 const psb_transform_coeffs * const source, 157 double fHue, double fSat); 158 159 static unsigned long PVRCalculateStride(unsigned long widthInPixels, unsigned int bitsPerPixel, unsigned int stride_alignment) 160 { 161 int ulActiveLinelenInPixels = (widthInPixels + (stride_alignment - 1)) & ~(stride_alignment - 1); 162 return ((ulActiveLinelenInPixels * bitsPerPixel) + 7) >> 3; 163 } 164 165 static int pvr_context_create(unsigned char **pvr_ctx) 166 { 167 #ifdef _FOR_FPGA_ 168 return PVR2D_OK; 169 #endif 170 int ret = 0; 171 int pvr_devices = PVR2DEnumerateDevices(0); 172 PVR2DDEVICEINFO *pvr_devs = NULL; 173 174 if ((pvr_devices < PVR2D_OK) || (pvr_devices == 0)) { 175 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s(): PowerVR device not found", __func__); 176 goto out; 177 } 178 179 pvr_devs = calloc(1, pvr_devices * sizeof(*pvr_devs)); 180 if (!pvr_devs) { 181 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s(): not enough memory", __func__); 182 goto out; 183 } 184 185 ret = PVR2DEnumerateDevices(pvr_devs); 186 if (ret != PVR2D_OK) { 187 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s(): PVR2DEnumerateDevices() failed(%d)", __func__, 188 ret); 189 goto out; 190 } 191 192 /* Choose the first display device */ 193 ret = PVR2DCreateDeviceContext(pvr_devs[0].ulDevID, (PVR2DCONTEXTHANDLE *)pvr_ctx, 0); 194 if (ret != PVR2D_OK) { 195 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s(): PVR2DCreateDeviceContext() failed(%d)", __func__, 196 ret); 197 goto out; 198 } 199 200 out: 201 if (pvr_devs) 202 free(pvr_devs); 203 204 return ret; 205 } 206 207 void psb_fix_drmfd_closesequence(psb_driver_data_p driver_data) 208 { 209 driver_data->dup_drm_fd = dup(driver_data->drm_fd); 210 } 211 212 213 int psb_ctexture_init(VADriverContextP ctx) 214 { 215 INIT_DRIVER_DATA; 216 217 struct psb_texture_s *texture_priv = &driver_data->ctexture_priv; 218 int i, ret; 219 220 ret = pvr_context_create(&driver_data->hPVR2DContext); 221 if (ret != PVR2D_OK) { 222 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s(): null PVR context!!", __func__); 223 return ret; 224 } 225 226 texture_priv->video_transfermatrix = PSB_VideoTransferMatrix_BT709; 227 texture_priv->src_nominalrange = PSB_NominalRange_0_255; 228 texture_priv->dst_nominalrange = PSB_NominalRange_0_255; 229 230 texture_priv->brightness.Value = OV_BRIGHTNESS_DEFAULT_VALUE; 231 texture_priv->brightness.Fraction = 0; 232 texture_priv->contrast.Value = OV_CONTRAST_DEFAULT_VALUE; 233 texture_priv->contrast.Fraction = 0; 234 texture_priv->hue.Value = OV_HUE_DEFAULT_VALUE; 235 texture_priv->hue.Fraction = 0; 236 texture_priv->saturation.Value = OV_SATURATION_DEFAULT_VALUE; 237 texture_priv->saturation.Fraction = 0; 238 239 texture_priv->gamma5 = 0xc0c0c0; 240 texture_priv->gamma4 = 0x808080; 241 texture_priv->gamma3 = 0x404040; 242 texture_priv->gamma2 = 0x202020; 243 texture_priv->gamma1 = 0x101010; 244 texture_priv->gamma0 = 0x080808; 245 246 texture_priv->dri_init_flag = 0; 247 texture_priv->drawable_update_flag = 0; 248 texture_priv->extend_dri_init_flag = 0; 249 texture_priv->current_blt_buffer = 0; 250 texture_priv->extend_current_blt_buffer = 0; 251 texture_priv->adjust_window_flag = 0; 252 texture_priv->destw_save = 0; 253 texture_priv->desth_save = 0; 254 texture_priv->local_rotation_save = -1; 255 texture_priv->extend_rotation_save = -1; 256 texture_priv->dri_drawable = NULL; 257 texture_priv->extend_dri_drawable = NULL; 258 259 for (i = 0; i < DRI2_BLIT_BUFFERS_NUM; i++) { 260 texture_priv->blt_meminfo[i] = NULL; 261 texture_priv->extend_blt_meminfo[i] = NULL; 262 } 263 264 for (i = 0; i < DRI2_FLIP_BUFFERS_NUM; i++) 265 texture_priv->flip_meminfo[i] = NULL; 266 267 texture_priv->blt_meminfo_pixmap = NULL; 268 269 for (i = 0; i < 6; i++) 270 texture_priv->pal_meminfo[i] = NULL; 271 272 psb_setup_coeffs(texture_priv); 273 psb_fix_drmfd_closesequence(driver_data); 274 275 return 0; 276 } 277 278 void psb_ctexture_deinit(VADriverContextP ctx) 279 { 280 INIT_DRIVER_DATA; 281 PVR2DERROR ePVR2DStatus; 282 int i; 283 284 struct psb_texture_s *texture_priv = &driver_data->ctexture_priv; 285 286 if (texture_priv->blt_meminfo_pixmap) { 287 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->blt_meminfo_pixmap); 288 if (ePVR2DStatus != PVR2D_OK) 289 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 290 } 291 292 for (i = 0; i < DRI2_BLIT_BUFFERS_NUM; i++) { 293 if (texture_priv->blt_meminfo[i]) { 294 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->blt_meminfo[i]); 295 if (ePVR2DStatus != PVR2D_OK) 296 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 297 texture_priv->blt_meminfo[i] = NULL; 298 } 299 } 300 301 for (i = 0; i < DRI2_FLIP_BUFFERS_NUM; i++) { 302 if (texture_priv->flip_meminfo[i]) { 303 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->flip_meminfo[i]); 304 if (ePVR2DStatus != PVR2D_OK) 305 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 306 texture_priv->flip_meminfo[i] = NULL; 307 } 308 } 309 310 for (i = 0; i < DRI2_BLIT_BUFFERS_NUM; i++) { 311 if (texture_priv->extend_blt_meminfo[i]) { 312 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->extend_blt_meminfo[i]); 313 if (ePVR2DStatus != PVR2D_OK) 314 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 315 texture_priv->extend_blt_meminfo[i] = NULL; 316 } 317 } 318 319 320 for (i = 0; i < 6; i++) { 321 if (texture_priv->pal_meminfo[i]) { 322 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->pal_meminfo[i]); 323 if (ePVR2DStatus != PVR2D_OK) 324 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 325 texture_priv->pal_meminfo[i] = NULL; 326 } 327 } 328 329 if (driver_data->hPVR2DContext) { 330 ePVR2DStatus = PVR2DDestroyDeviceContext(driver_data->hPVR2DContext); 331 if (ePVR2DStatus != PVR2D_OK) 332 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 333 driver_data->hPVR2DContext = NULL; 334 } 335 336 if (driver_data->dup_drm_fd) 337 close(driver_data->dup_drm_fd); 338 } 339 340 /* calculate subpicture size according to the downscale situation of both main and subpicture bitstream */ 341 static void psb_calculate_subpic_size(int surf_width, int surf_height, int dst_w, int dst_h, PsbVASurfaceRec *surface_subpic) 342 { 343 float src_h_ratio, src_v_ratio; 344 float subpic_h_ratio, subpic_v_ratio; 345 float subpic_h_dest_ratio, subpic_v_dest_ratio; 346 347 src_h_ratio = (float)surf_width / dst_w; 348 src_v_ratio = (float)surf_height / dst_h; 349 350 subpic_h_ratio = (float)surface_subpic->subpic_srcw / surface_subpic->subpic_dstw; 351 subpic_v_ratio = (float)surface_subpic->subpic_srch / surface_subpic->subpic_dsth; 352 353 subpic_h_dest_ratio = (float)dst_w / surface_subpic->subpic_dstw; 354 subpic_v_dest_ratio = (float)dst_h / surface_subpic->subpic_dsth; 355 356 if (!(surface_subpic->subpic_flags & VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD)) { 357 /* If coordinates are video relative then scale subpicture with video */ 358 surface_subpic->subpic_dstx /= src_h_ratio; 359 surface_subpic->subpic_dsty /= src_v_ratio; 360 surface_subpic->subpic_dstx /= subpic_h_ratio; 361 surface_subpic->subpic_dsty /= subpic_v_ratio; 362 363 surface_subpic->subpic_dstw /= src_h_ratio; 364 surface_subpic->subpic_dsth /= src_v_ratio; 365 surface_subpic->subpic_dstw /= subpic_h_ratio; 366 surface_subpic->subpic_dsth /= subpic_v_ratio; 367 } 368 } 369 370 static PPVR2DMEMINFO psb_check_subpic_buffer(psb_driver_data_p driver_data, PsbVASurfaceRec* surface_subpic) 371 { 372 unsigned int i, j; 373 unsigned char* tmp_buffer; 374 unsigned char tmp; 375 PVR2DERROR ePVR2DStatus; 376 377 /* Find and return the wrapped buffer index */ 378 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 379 if (driver_data->wrapped_subpic_id[i] == surface_subpic->subpic_id && driver_data->subpicBuf[i]) { 380 return driver_data->subpicBuf[i]; 381 } 382 } 383 384 /* Wrap a un-wrapped buffer and return */ 385 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 386 if (driver_data->wrapped_subpic_id[i] == VA_INVALID_ID) { 387 tmp_buffer = NULL; 388 tmp_buffer = wsbmBOMap(surface_subpic->bo, WSBM_ACCESS_READ | WSBM_ACCESS_WRITE); 389 if (NULL == tmp_buffer) { 390 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d: wsbmBOMap failed!", 391 __FUNCTION__, __LINE__); 392 return NULL; 393 } 394 for (j = 0; j < surface_subpic->size; j = j + 4096) { 395 tmp = *(tmp_buffer + j); 396 if (tmp == 0) 397 *(tmp_buffer + j) = 0; 398 } 399 400 ePVR2DStatus = PVR2DMemWrap(driver_data->hPVR2DContext, 401 tmp_buffer, 402 0, 403 surface_subpic->size, 404 NULL, 405 &driver_data->subpicBuf[i]); 406 if (ePVR2DStatus != PVR2D_OK) { 407 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemWrap error %d\n", __FUNCTION__, ePVR2DStatus); 408 return NULL; 409 } 410 411 driver_data->wrapped_subpic_id[i] = surface_subpic->subpic_id; 412 return driver_data->subpicBuf[i]; 413 } 414 } 415 416 if (i == VIDEO_BUFFER_NUM - 1) { 417 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Out of warpped subpic buffer memory\n", __FUNCTION__); 418 return NULL; 419 } 420 421 return NULL; 422 } 423 424 425 void psb_init_surface_pvr2dbuf(psb_driver_data_p driver_data) 426 { 427 int i; 428 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 429 driver_data->videoBuf[i] = NULL; 430 driver_data->subpicBuf[i] = NULL; 431 driver_data->wrapped_surface_id[i] = VA_INVALID_ID; 432 driver_data->wrapped_subpic_id[i] = VA_INVALID_ID; 433 } 434 435 } 436 437 void psb_free_surface_pvr2dbuf(psb_driver_data_p driver_data) 438 { 439 int i; 440 PVR2DERROR ePVR2DStatus; 441 442 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 443 if ((driver_data->wrapped_surface_id[i] != VA_INVALID_ID) && driver_data->videoBuf[i]) { 444 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, driver_data->videoBuf[i]); 445 if (ePVR2DStatus != PVR2D_OK) 446 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 447 } 448 449 if ((driver_data->wrapped_subpic_id[i] != VA_INVALID_ID) && driver_data->subpicBuf[i]) { 450 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, driver_data->subpicBuf[i]); 451 if (ePVR2DStatus != PVR2D_OK) 452 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 453 } 454 455 driver_data->wrapped_surface_id[i] = VA_INVALID_ID; 456 driver_data->wrapped_subpic_id[i] = -1; 457 458 driver_data->videoBuf[i] = NULL; 459 driver_data->subpicBuf[i] = NULL; 460 } 461 } 462 463 464 static PPVR2DMEMINFO psb_wrap_surface_pvr2dbuf(psb_driver_data_p driver_data, VASurfaceID surface) 465 { 466 int i, j; 467 unsigned char* tmp_buffer; 468 unsigned char tmp; 469 object_surface_p obj_surface = SURFACE(surface); 470 psb_surface_p psb_surface; 471 VAStatus vaStatus = VA_STATUS_SUCCESS; 472 PVR2DERROR ePVR2DStatus; 473 474 CHECK_SURFACE(obj_surface); 475 psb_surface = obj_surface->psb_surface; 476 477 /* Find and return the wrapped buffer index */ 478 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 479 if (driver_data->wrapped_surface_id[i] == surface && driver_data->videoBuf[i]) { 480 return driver_data->videoBuf[i]; 481 } 482 } 483 484 /* Wrap a un-wrapped buffer and return */ 485 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 486 if (driver_data->wrapped_surface_id[i] == VA_INVALID_ID) { 487 tmp_buffer = NULL; 488 tmp_buffer = wsbmBOMap(psb_surface->buf.drm_buf, WSBM_ACCESS_READ | WSBM_ACCESS_WRITE); 489 if (NULL == tmp_buffer) { 490 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d: wsbmBOMap failed!", 491 __FUNCTION__, __LINE__); 492 return NULL; 493 } 494 for (j = 0; j < psb_surface->size; j = j + 4096) { 495 tmp = *(tmp_buffer + j); 496 if (tmp == 0) 497 *(tmp_buffer + j) = 0; 498 } 499 500 ePVR2DStatus = PVR2DMemWrap(driver_data->hPVR2DContext, 501 tmp_buffer, 502 0, 503 psb_surface->size, 504 NULL, 505 &driver_data->videoBuf[i]); 506 if (ePVR2DStatus != PVR2D_OK) { 507 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemWrap error %d\n", __FUNCTION__, ePVR2DStatus); 508 } 509 510 driver_data->wrapped_surface_id[i] = surface; 511 return driver_data->videoBuf[i]; 512 } 513 } 514 515 if (i == VIDEO_BUFFER_NUM - 1) { 516 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Out of warpped buffer memory\n", __FUNCTION__); 517 return NULL; 518 } 519 520 return NULL; 521 } 522 523 #if 0 524 void psb_putsurface_textureblit( 525 VADriverContextP ctx, unsigned char *dst, VASurfaceID surface, int src_x, int src_y, int src_w, 526 int src_h, int dst_x, int dst_y, int dst_w, int dst_h, unsigned int subtitle, 527 int width, int height, 528 int src_pitch, struct _WsbmBufferObject * src_buf, 529 unsigned int placement, int wrap_dst) 530 { 531 INIT_DRIVER_DATA; 532 unsigned int i; 533 unsigned char *tmp_palette; 534 struct psb_texture_s *texture_priv = &driver_data->ctexture_priv; 535 object_surface_p obj_surface; 536 PsbVASurfaceRec *surface_subpic = NULL; 537 VAStatus vaStatus = VA_STATUS_SUCCESS; 538 obj_surface = SURFACE(surface); 539 540 PVR2D_VPBLT sBltVP; 541 PVR2DERROR ePVR2DStatus; 542 PPVR2DMEMINFO pVaVideoSubpicMemInfo; 543 PPVR2DMEMINFO pVaVideoMemInfo; 544 PPVR2DMEMINFO pDstMeminfo; 545 546 src_pitch = (src_pitch + 0x3) & ~0x3; 547 548 if (NULL == obj_surface) { 549 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Invalid surface ID 0x%08x!\n", __func__, surface); 550 return; 551 } 552 surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures; 553 /* check whether we need to update coeffs */ 554 if ((height > 576) && 555 (texture_priv->video_transfermatrix != PSB_VideoTransferMatrix_BT709)) { 556 texture_priv->video_transfermatrix = PSB_VideoTransferMatrix_BT709; 557 texture_priv->update_coeffs = 1; 558 } else if ((height <= 576) && 559 (texture_priv->video_transfermatrix != PSB_VideoTransferMatrix_BT601)) { 560 texture_priv->video_transfermatrix = PSB_VideoTransferMatrix_BT601; 561 texture_priv->update_coeffs = 1; 562 } 563 564 /* prepare coeffs if needed */ 565 memset(&sBltVP, 0, sizeof(PVR2D_VPBLT)); 566 if (texture_priv->update_coeffs == 1) { 567 psb_setup_coeffs(texture_priv); 568 sBltVP.psYUVCoeffs = (PPVR2D_YUVCOEFFS) & texture_priv->coeffs; 569 /* FIXME: is it right? */ 570 sBltVP.bCoeffsGiven = 1; 571 } 572 573 pVaVideoMemInfo = psb_wrap_surface_pvr2dbuf(driver_data, surface); 574 if (!pVaVideoMemInfo) { 575 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get source PVR2DMEMINFO!\n", __func__); 576 return; 577 } 578 579 /* wrap the dest source */ 580 /* FIXME: this is wrap for rgb565 */ 581 if (wrap_dst == 0) { 582 /* comment out for rebasing to staging 583 pDstMeminfo = (PPVR2DMEMINFO)dst; 584 if (IS_MFLD(driver_data)) 585 sBltVP.sDst.Stride = PVRCalculateStride(((struct dri_drawable*)texture_priv->dri_drawable)->width, 32, 8); 586 sBltVP.sDst.Format = PVR2D_ARGB8888; 587 */ 588 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Not support ARGB8888!\n", __func__); 589 return; 590 } else { 591 ePVR2DStatus = PVR2DMemWrap(driver_data->hPVR2DContext, 592 dst, 593 0, 594 (dst_w * dst_h * 2), 595 NULL, 596 &pDstMeminfo); 597 if (ePVR2DStatus != PVR2D_OK) { 598 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemWrap error %d\n", __FUNCTION__, ePVR2DStatus); 599 return; 600 } 601 602 /* FIXME: this wrong, how to get system pitch */ 603 sBltVP.sDst.Stride = dst_w * 2;//align_to(dst_w, 64); 604 sBltVP.sDst.Format = PVR2D_RGB565; 605 } 606 sBltVP.sDst.pSurfMemInfo = pDstMeminfo; 607 sBltVP.sDst.SurfOffset = 0; 608 sBltVP.sDst.SurfWidth = dst_w; 609 sBltVP.sDst.SurfHeight = dst_h; 610 611 /* Y plane UV plane */ 612 sBltVP.uiNumLayers = 1; 613 sBltVP.sSrc->Stride = src_pitch; 614 sBltVP.sSrc->Format = VA_FOURCC_NV12; 615 sBltVP.sSrc->SurfWidth = width; 616 sBltVP.sSrc->SurfHeight = height; 617 sBltVP.sSrc[0].pSurfMemInfo = pVaVideoMemInfo; 618 619 /* FIXME: check for top-bottom */ 620 sBltVP.sSrc->SurfOffset = 0; 621 622 /* FIXME: check rotation setting */ 623 /* FIXME: use PVR define */ 624 sBltVP.RotationValue = 1; 625 626 /* clip box */ 627 sBltVP.rcDest.left = dst_x; 628 sBltVP.rcDest.right = dst_x + dst_w; 629 sBltVP.rcDest.top = dst_y; 630 sBltVP.rcDest.bottom = dst_y + dst_h; 631 632 sBltVP.rcSource->left = src_x; 633 sBltVP.rcSource->right = src_x + src_w; 634 sBltVP.rcSource->top = src_y; 635 sBltVP.rcSource->bottom = src_y + src_h; 636 637 if (subtitle == 1 && obj_surface->subpic_count) { 638 for (i = 0; i < obj_surface->subpic_count; i++) { 639 sBltVP.uiNumLayers += 1; 640 641 psb_calculate_subpic_size(obj_surface->width, obj_surface->height, dst_w, dst_h, surface_subpic); 642 643 pVaVideoSubpicMemInfo = psb_check_subpic_buffer(driver_data, surface_subpic); 644 if (!pVaVideoSubpicMemInfo) { 645 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get subpic PVR2DMEMINFO!\n", __func__); 646 return; 647 } 648 649 object_subpic_p obj_subpic = SUBPIC(surface_subpic->subpic_id); 650 CHECK_SURFACE(obj_subpic); 651 // sBltVP.AlphaBlendingFunc = PVR2D_ALPHA_OP_GLOBAL; 652 sBltVP.AlphaBlendingFunc = 3; 653 sBltVP.subpicGlobalAlpha[i] = obj_subpic->global_alpha; 654 655 sBltVP.sSrcSubpic[i].pSurfMemInfo = pVaVideoSubpicMemInfo; 656 sBltVP.sSrcSubpic[i].SurfOffset = 0; 657 sBltVP.sSrcSubpic[i].Stride = surface_subpic->stride; 658 659 if (surface_subpic->fourcc == VA_FOURCC_AI44) 660 sBltVP.sSrcSubpic[i].Format = MAKEFOURCC('A', 'I' , '4', '4'); 661 else 662 sBltVP.sSrcSubpic[i].Format = surface_subpic->fourcc; 663 664 sBltVP.sSrcSubpic[i].SurfWidth = surface_subpic->subpic_srcw; 665 sBltVP.sSrcSubpic[i].SurfHeight = surface_subpic->subpic_srch; 666 667 sBltVP.rcSubpicSource[i].left = surface_subpic->subpic_srcx; 668 sBltVP.rcSubpicSource[i].right = surface_subpic->subpic_srcx + surface_subpic->subpic_srcw; 669 sBltVP.rcSubpicSource[i].top = surface_subpic->subpic_srcy; 670 sBltVP.rcSubpicSource[i].bottom = surface_subpic->subpic_srcy + surface_subpic->subpic_srch; 671 672 sBltVP.rcSubpicDest[i].left = surface_subpic->subpic_dstx; 673 sBltVP.rcSubpicDest[i].right = surface_subpic->subpic_dstx + surface_subpic->subpic_dstw; 674 sBltVP.rcSubpicDest[i].top = surface_subpic->subpic_dsty; 675 sBltVP.rcSubpicDest[i].bottom = surface_subpic->subpic_dsty + surface_subpic->subpic_dsth; 676 677 //only allocate memory once for palette 678 if (surface_subpic->fourcc == VA_FOURCC_AI44) { 679 if (!texture_priv->pal_meminfo[i]) { 680 ePVR2DStatus = PVR2DMemAlloc(driver_data->hPVR2DContext, 16 * sizeof(unsigned int), 0, 0, &texture_priv->pal_meminfo[i]); 681 if (ePVR2DStatus != PVR2D_OK) { 682 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemAlloc error %d\n", __FUNCTION__, ePVR2DStatus); 683 return; 684 } 685 } 686 687 sBltVP.pPalMemInfo[i] = texture_priv->pal_meminfo[i]; 688 tmp_palette = sBltVP.pPalMemInfo[i]->pBase; 689 memcpy(tmp_palette, surface_subpic->palette_ptr, 16 * sizeof(unsigned int)); 690 sBltVP.PalOffset[i] = 0; 691 } 692 surface_subpic = surface_subpic->next; 693 } 694 } 695 696 //#ifndef ANDROID /* MRST Android not enable this API, uncomment for MRST */ 697 ePVR2DStatus = PVR2DBltVideo(driver_data->hPVR2DContext, &sBltVP); 698 //#endif 699 700 if (ePVR2DStatus != PVR2D_OK) 701 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: failed to do PVR2DBltVideo with error code %d\n", 702 __FUNCTION__, ePVR2DStatus); 703 704 if (wrap_dst) { 705 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, pDstMeminfo); 706 if (ePVR2DStatus != PVR2D_OK) 707 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 708 } 709 710 driver_data->cur_displaying_surface = VA_INVALID_SURFACE; 711 driver_data->last_displaying_surface = VA_INVALID_SURFACE; 712 obj_surface->display_timestamp = 0; 713 } 714 #endif 715 716 static void 717 psb_setup_coeffs(struct psb_texture_s * pPriv) 718 { 719 double yCoeff, uCoeff, vCoeff, Constant; 720 double fContrast; 721 double Y_offset, CbCr_offset, RGB_offset; 722 int bright_off = 0; 723 psb_transform_coeffs coeffs, transfer_matrix; 724 memset(&coeffs, 0, sizeof(psb_transform_coeffs)); 725 memset(&transfer_matrix, 0, sizeof(psb_transform_coeffs)); 726 727 /* Offsets in the input and output ranges are 728 * included in the constant of the transform equation 729 */ 730 psb_select_transfermatrix(pPriv, &transfer_matrix, 731 &Y_offset, &CbCr_offset, &RGB_offset); 732 733 /* 734 * It is at this point we should adjust the parameters for the procamp: 735 * - Brightness is handled as an offset of the Y parameter. 736 * - Contrast is an adjustment of the Y scale. 737 * - Saturation is a scaling of the U anc V parameters. 738 * - Hue is a rotation of the U and V parameters. 739 */ 740 741 bright_off = pPriv->brightness.Value; 742 fContrast = (pPriv->contrast.Value + 100) / 100.0; 743 744 /* Apply hue and saturation correction to transfer matrix */ 745 psb_transform_sathuecoeffs(&coeffs, 746 &transfer_matrix, 747 pPriv->hue.Value * Degree, 748 pPriv->saturation.Value / 100.0); 749 750 /* Create coefficients to get component R 751 * (including brightness and contrast correction) 752 */ 753 psb_create_coeffs(-1 * Y_offset, -1 * CbCr_offset, -1 * CbCr_offset, 754 RGB_offset, coeffs.rY, coeffs.rCb, coeffs.rCr, 755 bright_off, fContrast, &yCoeff, &uCoeff, &vCoeff, 756 &Constant); 757 758 /* Convert transform operation from floating point to fixed point */ 759 psb_convert_coeffs(yCoeff, uCoeff, vCoeff, Constant, /* input coefficients */ 760 &pPriv->coeffs.rY, &pPriv->coeffs.rU, 761 &pPriv->coeffs.rV, &pPriv->coeffs.rConst, 762 &pPriv->coeffs.rShift); 763 764 /* Create coefficients to get component G 765 * (including brightness and contrast correction) 766 */ 767 psb_create_coeffs(-1 * Y_offset, -1 * CbCr_offset, -1 * CbCr_offset, 768 RGB_offset, coeffs.gY, coeffs.gCb, coeffs.gCr, 769 bright_off, fContrast, &yCoeff, &uCoeff, &vCoeff, 770 &Constant); 771 772 /* Convert transform operation from floating point to fixed point */ 773 psb_convert_coeffs(yCoeff, uCoeff, vCoeff, Constant, 774 /* tranfer matrix coefficients for G */ 775 &pPriv->coeffs.gY, &pPriv->coeffs.gU, 776 &pPriv->coeffs.gV, &pPriv->coeffs.gConst, 777 &pPriv->coeffs.gShift); 778 779 /* Create coefficients to get component B 780 * (including brightness and contrast correction) 781 */ 782 psb_create_coeffs(-1 * Y_offset, -1 * CbCr_offset, -1 * CbCr_offset, 783 RGB_offset, coeffs.bY, coeffs.bCb, coeffs.bCr, 784 bright_off, fContrast, &yCoeff, &uCoeff, &vCoeff, 785 &Constant); 786 787 /* Convert transform operation from floating point to fixed point */ 788 psb_convert_coeffs(yCoeff, uCoeff, vCoeff, Constant, 789 /* tranfer matrix coefficients for B */ 790 &pPriv->coeffs.bY, &pPriv->coeffs.bU, 791 &pPriv->coeffs.bV, &pPriv->coeffs.bConst, 792 &pPriv->coeffs.bShift); 793 } 794 795 /* 796 These are the corresponding matrices when using NominalRange_16_235 797 for the input surface and NominalRange_0_255 for the outpur surface: 798 799 static const psb_transform_coeffs s601 = { 800 1.164, 0, 1.596, 801 1.164, -0.391, -0.813, 802 1.164, 2.018, 0 803 }; 804 805 static const psb_transform_coeffs s709 = { 806 1.164, 0, 1.793, 807 1.164, -0.213, -0.534, 808 1.164, 2.115, 0 809 }; 810 811 static const psb_transform_coeffs s240M = { 812 1.164, -0.0007, 1.793, 813 1.164, -0.257, -0.542, 814 1.164, 2.078, 0.0004 815 }; 816 */ 817 818 /** 819 * Select which transfer matrix to use in the YUV->RGB conversion. 820 */ 821 static void 822 psb_select_transfermatrix(struct psb_texture_s * pPriv, 823 psb_transform_coeffs * transfer_matrix, 824 double *Y_offset, double *CbCr_offset, 825 double *RGB_offset) 826 { 827 double RGB_scale, Y_scale, Cb_scale, Cr_scale; 828 829 /* 830 * Depending on the nominal ranges of the input YUV surface and the output RGB 831 * surface, it might be needed to perform some scaling on the transfer matrix. 832 * The excursion in the YUV values implies that the first column of the matrix 833 * must be divided by the Y excursion, and the second and third columns be 834 * divided by the U and V excursions respectively. The offset does not affect 835 * the values of the matrix. 836 * The excursion in the RGB values implies that all the values in the transfer 837 * matrix must be multiplied by the value of the excursion. 838 * 839 * Example: Conversion of the SMPTE 240M transfer matrix. 840 * 841 * Conversion from [Y', Pb, Pr] to [R', G', B'] in the range of [0, 1]. Y' is in 842 * the range of [0, 1] and Pb and Pr in the range of [-0.5, 0.5]. 843 * 844 * R' 1 -0.000657 1.575848 Y' 845 * G' = 1 -0.226418 -0.476529 * Pb 846 * B' 1 1.825958 0.000378 Pr 847 * 848 * Conversion from [Y', Cb, Cr] to {R', G', B'] in the range of [0, 1]. Y' has an 849 * excursion of 219 and an offset of +16, and CB and CR have excursions of +/-112 850 * and offset of +128, for a range of 16 through 240 inclusive. 851 * 852 * R' 1/219 -0.000657/224 1.575848/224 Y' 16 853 * G' = 1/219 -0.226418/224 -0.476529/224 * Cb - 128 854 * B' 1/219 1.825958/224 0.000378/224 Cr 128 855 * 856 * Conversion from [Y', Cb, Cr] to R'G'B' in the range [0, 255]. 857 * 858 * R' 1/219 -0.000657/224 1.575848/224 Y' 16 859 * G' = 255 * 1/219 -0.226418/224 -0.476529/224 * Cb - 128 860 * B' 1/219 1.825958/224 0.000378/224 Cr 128 861 */ 862 863 switch (pPriv->src_nominalrange) { 864 case PSB_NominalRange_0_255: 865 /* Y has a range of [0, 255], U and V have a range of [0, 255] */ 866 { 867 double tmp = 0.0; 868 869 (void)tmp; 870 } /* workaroud for float point bug? */ 871 Y_scale = 255.0; 872 *Y_offset = 0; 873 Cb_scale = Cr_scale = 255; 874 *CbCr_offset = 128; 875 break; 876 case PSB_NominalRange_16_235: 877 case PSB_NominalRange_Unknown: 878 /* Y has a range of [16, 235] and Cb, Cr have a range of [16, 240] */ 879 Y_scale = 219; 880 *Y_offset = 16; 881 Cb_scale = Cr_scale = 224; 882 *CbCr_offset = 128; 883 break; 884 case PSB_NominalRange_48_208: 885 /* Y has a range of [48, 208] and Cb, Cr have a range of [48, 208] */ 886 Y_scale = 160; 887 *Y_offset = 48; 888 Cb_scale = Cr_scale = 160; 889 *CbCr_offset = 128; 890 break; 891 892 default: 893 /* Y has a range of [0, 1], U and V have a range of [-0.5, 0.5] */ 894 Y_scale = 1; 895 *Y_offset = 0; 896 Cb_scale = Cr_scale = 1; 897 *CbCr_offset = 0; 898 break; 899 } 900 901 /* 902 * 8-bit computer RGB, also known as sRGB or "full-scale" RGB, and studio 903 * video RGB, or "RGB with head-room and toe-room." These are defined as follows: 904 * 905 * - Computer RGB uses 8 bits for each sample of red, green, and blue. Black 906 * is represented by R = G = B = 0, and white is represented by R = G = B = 255. 907 * - Studio video RGB uses some number of bits N for each sample of red, green, 908 * and blue, where N is 8 or more. Studio video RGB uses a different scaling 909 * factor than computer RGB, and it has an offset. Black is represented by 910 * R = G = B = 16*2^(N-8), and white is represented by R = G = B = 235*2^(N-8). 911 * However, actual values may fall outside this range. 912 */ 913 switch (pPriv->dst_nominalrange) { 914 case PSB_NominalRange_0_255: // for sRGB 915 case PSB_NominalRange_Unknown: 916 /* R, G and B have a range of [0, 255] */ 917 RGB_scale = 255; 918 *RGB_offset = 0; 919 break; 920 case PSB_NominalRange_16_235: // for stRGB 921 /* R, G and B have a range of [16, 235] */ 922 RGB_scale = 219; 923 *RGB_offset = 16; 924 break; 925 case PSB_NominalRange_48_208: // for Bt.1361 RGB 926 /* R, G and B have a range of [48, 208] */ 927 RGB_scale = 160; 928 *RGB_offset = 48; 929 break; 930 default: 931 /* R, G and B have a range of [0, 1] */ 932 RGB_scale = 1; 933 *RGB_offset = 0; 934 break; 935 } 936 937 switch (pPriv->video_transfermatrix) { 938 case PSB_VideoTransferMatrix_BT709: 939 memcpy(transfer_matrix, &s709, sizeof(psb_transform_coeffs)); 940 break; 941 case PSB_VideoTransferMatrix_BT601: 942 memcpy(transfer_matrix, &s601, sizeof(psb_transform_coeffs)); 943 break; 944 case PSB_VideoTransferMatrix_SMPTE240M: 945 memcpy(transfer_matrix, &s240M, sizeof(psb_transform_coeffs)); 946 break; 947 case PSB_VideoTransferMatrix_Unknown: 948 /* 949 * Specifies that the video transfer matrix is not specified. 950 * The default value is BT601 for standard definition (SD) video and BT709 951 * for high definition (HD) video. 952 */ 953 if (1 /*pPriv->sVideoDesc.SampleWidth < 720 */) { /* TODO, width selection */ 954 memcpy(transfer_matrix, &s601, sizeof(psb_transform_coeffs)); 955 } else { 956 memcpy(transfer_matrix, &s709, sizeof(psb_transform_coeffs)); 957 } 958 break; 959 default: 960 break; 961 } 962 963 if (Y_scale != 1 || Cb_scale != 1 || Cr_scale != 1) { 964 /* Each column of the transfer matrix has to 965 * be scaled by the excursion of each component 966 */ 967 psb_scale_transfermatrix(transfer_matrix, 1 / Y_scale, 1 / Cb_scale, 968 1 / Cr_scale); 969 } 970 if (RGB_scale != 1) { 971 /* All the values in the transfer matrix have to be multiplied 972 * by the excursion of the RGB components 973 */ 974 psb_scale_transfermatrix(transfer_matrix, RGB_scale, RGB_scale, 975 RGB_scale); 976 } 977 } 978 979 static void 980 psb_scale_transfermatrix(psb_transform_coeffs * transfer_matrix, 981 double YColumScale, double CbColumScale, 982 double CrColumnScale) 983 { 984 /* First column of the transfer matrix */ 985 transfer_matrix->rY *= YColumScale; 986 transfer_matrix->gY *= YColumScale; 987 transfer_matrix->bY *= YColumScale; 988 989 /* Second column of the transfer matrix */ 990 transfer_matrix->rCb *= CbColumScale; 991 transfer_matrix->gCb *= CbColumScale; 992 transfer_matrix->bCb *= CbColumScale; 993 994 /* Third column of the transfer matrix */ 995 transfer_matrix->rCr *= CrColumnScale; 996 transfer_matrix->gCr *= CrColumnScale; 997 transfer_matrix->bCr *= CrColumnScale; 998 } 999 1000 /* 1001 * Calculates the coefficintes of a YUV->RGB conversion based on 1002 * the provided basis coefficients (already had HUe and Satu applied). 1003 * Performs brightness and contrast adjustment as well as the required 1004 * offsets to put into correct range for hardware conversion. 1005 */ 1006 static void 1007 psb_create_coeffs(double yOff, double uOff, double vOff, double rgbOff, 1008 double yScale, double uScale, double vScale, 1009 double brightness, double contrast, 1010 double *pYCoeff, double *pUCoeff, double *pVCoeff, 1011 double *pConstant) 1012 { 1013 *pYCoeff = yScale * contrast; 1014 *pUCoeff = uScale * contrast; 1015 *pVCoeff = vScale * contrast; 1016 1017 *pConstant = (((yOff + brightness) * yScale) 1018 + (uOff * uScale) + (vOff * vScale)) * contrast + rgbOff; 1019 } 1020 1021 /* 1022 * Converts a floating point function in the form 1023 * a*yCoeff + b*uCoeff + c * vCoeff + d 1024 * Into a fixed point function of the forrm 1025 * (a*pY + b * pU + c * pV + constant)>>pShift 1026 */ 1027 static void 1028 psb_convert_coeffs(double Ycoeff, double Ucoeff, double Vcoeff, 1029 double ConstantTerm, signed char *pY, signed char *pU, 1030 signed char *pV, signed short *constant, 1031 unsigned char *pShift) 1032 { 1033 *pShift = 0; 1034 1035 Ycoeff *= 256; 1036 Ucoeff *= 256; 1037 Vcoeff *= 256; 1038 ConstantTerm *= 256; 1039 *pShift = 8; 1040 1041 /* 1042 * What we want to do is scale up the coefficients so that they just fit into their 1043 * allowed bits, so we are using signed maths giving us coefficients can be between +-128. 1044 * The constant can be between =- 32767. 1045 * The divide can be between 0 and 256 (on powers of two only). 1046 * A mathematical approach would be nice, but for simplicity do an iterative compare 1047 * and divide. Until something fits. 1048 */ 1049 while (psb_check_coeffs(Ycoeff, Ucoeff, Vcoeff, ConstantTerm, *pShift)) { 1050 Ycoeff /= 2; 1051 Ucoeff /= 2; 1052 Vcoeff /= 2; 1053 ConstantTerm /= 2; 1054 (*pShift)--; 1055 } 1056 *pY = (signed char)(Ycoeff + 0.5); 1057 *pU = (signed char)(Ucoeff + 0.5); 1058 *pV = (signed char)(Vcoeff + 0.5); 1059 *constant = (signed short)(ConstantTerm + 0.5); 1060 } 1061 1062 /** 1063 * Checks if the specified coefficients are within the ranges required 1064 * and returns true if they are else false. 1065 */ 1066 static int 1067 psb_check_coeffs(double Ycoeff, double Ucoeff, double Vcoeff, 1068 double ConstantTerm, signed char byShift) 1069 { 1070 if ((Ycoeff > 127) || (Ycoeff < -128)) { 1071 return 1; 1072 } 1073 if ((Ucoeff > 127) || (Ucoeff < -128)) { 1074 return 1; 1075 } 1076 if ((Vcoeff > 127) || (Vcoeff < -128)) { 1077 return 1; 1078 } 1079 if ((ConstantTerm > 32766) || (ConstantTerm < -32767)) { 1080 return 1; 1081 } 1082 return 0; 1083 } 1084 1085 static void 1086 psb_transform_sathuecoeffs(psb_transform_coeffs * dest, 1087 const psb_transform_coeffs * const source, 1088 double fHue, double fSat) 1089 { 1090 double fHueSatSin, fHueSatCos; 1091 1092 fHueSatSin = sin(fHue) * fSat; 1093 fHueSatCos = cos(fHue) * fSat; 1094 1095 dest->rY = source->rY; 1096 dest->rCb = source->rCb * fHueSatCos - source->rCr * fHueSatSin; 1097 dest->rCr = source->rCr * fHueSatCos + source->rCb * fHueSatSin; 1098 1099 dest->gY = source->gY; 1100 dest->gCb = source->gCb * fHueSatCos - source->gCr * fHueSatSin; 1101 dest->gCr = source->gCr * fHueSatCos + source->gCb * fHueSatSin; 1102 1103 dest->bY = source->bY; 1104 dest->bCb = source->bCb * fHueSatCos - source->bCr * fHueSatSin; 1105 dest->bCr = source->bCr * fHueSatCos + source->bCb * fHueSatSin; 1106 } 1107 1108