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