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