psb_texture.c revision 54752e65b02b1a84c491e3f9c964046faeea306e
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 texture_priv->dri_drawable= NULL; 247 texture_priv->extend_dri_drawable= NULL; 248 249 for (i = 0; i < DRI2_BLIT_BUFFERS_NUM; i++) { 250 texture_priv->blt_meminfo[i] = NULL; 251 texture_priv->extend_blt_meminfo[i] = NULL; 252 } 253 254 for (i = 0; i < DRI2_FLIP_BUFFERS_NUM; i++) 255 texture_priv->flip_meminfo[i] = NULL; 256 257 texture_priv->blt_meminfo_pixmap = NULL; 258 259 for (i = 0; i < 6; i++) 260 texture_priv->pal_meminfo[i] = NULL; 261 262 psb_setup_coeffs(texture_priv); 263 psb_fix_drmfd_closesequence(driver_data); 264} 265 266void psb_ctexture_deinit(VADriverContextP ctx) 267{ 268 INIT_DRIVER_DATA; 269 PVR2DERROR ePVR2DStatus; 270 int i; 271 272 struct psb_texture_s *texture_priv = &driver_data->ctexture_priv; 273 274 if (texture_priv->blt_meminfo_pixmap) { 275 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->blt_meminfo_pixmap); 276 if (ePVR2DStatus != PVR2D_OK) 277 psb__error_message("%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 278 } 279 280 for (i = 0; i < DRI2_BLIT_BUFFERS_NUM; i++) { 281 if (texture_priv->blt_meminfo[i]) { 282 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->blt_meminfo[i]); 283 if (ePVR2DStatus != PVR2D_OK) 284 psb__error_message("%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 285 texture_priv->blt_meminfo[i] = NULL; 286 } 287 } 288 289 for (i = 0; i < DRI2_FLIP_BUFFERS_NUM; i++) { 290 if (texture_priv->flip_meminfo[i]) { 291 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->flip_meminfo[i]); 292 if (ePVR2DStatus != PVR2D_OK) 293 psb__error_message("%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 294 texture_priv->flip_meminfo[i] = NULL; 295 } 296 } 297 298 for (i = 0; i < DRI2_BLIT_BUFFERS_NUM; i++) { 299 if (texture_priv->extend_blt_meminfo[i]) { 300 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->extend_blt_meminfo[i]); 301 if (ePVR2DStatus != PVR2D_OK) 302 psb__error_message("%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 303 texture_priv->extend_blt_meminfo[i] = NULL; 304 } 305 } 306 307 308 for (i = 0; i < 6; i++) { 309 if (texture_priv->pal_meminfo[i]) { 310 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, texture_priv->pal_meminfo[i]); 311 if (ePVR2DStatus != PVR2D_OK) 312 psb__error_message("%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 313 texture_priv->pal_meminfo[i] = NULL; 314 } 315 } 316 317 /* release all dri drawable buffer */ 318 //free_drawable_hashtable(ctx); 319 320 if (driver_data->hPVR2DContext) { 321 ePVR2DStatus = PVR2DDestroyDeviceContext(driver_data->hPVR2DContext); 322 if (ePVR2DStatus != PVR2D_OK) 323 psb__error_message("%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 324 driver_data->hPVR2DContext = NULL; 325 } 326 327 if (driver_data->dup_drm_fd) 328 close(driver_data->dup_drm_fd); 329} 330 331/* calculate subpicture size according to the downscale situation of both main and subpicture bitstream */ 332static void psb_calculate_subpic_size(int surf_width, int surf_height, int dst_w, int dst_h, PsbVASurfaceRec *surface_subpic) 333{ 334 float src_h_ratio, src_v_ratio; 335 float subpic_h_ratio, subpic_v_ratio; 336 float subpic_h_dest_ratio, subpic_v_dest_ratio; 337 338 src_h_ratio = (float)surf_width / dst_w; 339 src_v_ratio = (float)surf_height / dst_h; 340 341 subpic_h_ratio = (float)surface_subpic->subpic_srcw / surface_subpic->subpic_dstw; 342 subpic_v_ratio = (float)surface_subpic->subpic_srch / surface_subpic->subpic_dsth; 343 344 subpic_h_dest_ratio = (float)dst_w / surface_subpic->subpic_dstw; 345 subpic_v_dest_ratio = (float)dst_h / surface_subpic->subpic_dsth; 346 347 if (!(surface_subpic->subpic_flags & VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD)) { 348 /* If coordinates are video relative then scale subpicture with video */ 349 surface_subpic->subpic_dstx /= src_h_ratio; 350 surface_subpic->subpic_dsty /= src_v_ratio; 351 surface_subpic->subpic_dstx /= subpic_h_ratio; 352 surface_subpic->subpic_dsty /= subpic_v_ratio; 353 354 surface_subpic->subpic_dstw /= src_h_ratio; 355 surface_subpic->subpic_dsth /= src_v_ratio; 356 surface_subpic->subpic_dstw /= subpic_h_ratio; 357 surface_subpic->subpic_dsth /= subpic_v_ratio; 358 } 359} 360 361static PPVR2DMEMINFO psb_check_subpic_buffer(psb_driver_data_p driver_data, PsbVASurfaceRec* surface_subpic) 362{ 363 int i, j; 364 unsigned char* tmp_buffer; 365 unsigned char tmp; 366 PVR2DERROR ePVR2DStatus; 367 368 /* Find and return the wrapped buffer index */ 369 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 370 if (driver_data->wrapped_subpic_id[i] == surface_subpic->subpic_id && driver_data->subpicBuf[i]) { 371 return driver_data->subpicBuf[i]; 372 } 373 } 374 375 /* Wrap a un-wrapped buffer and return */ 376 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 377 if (driver_data->wrapped_subpic_id[i] == -1) { 378 tmp_buffer = NULL; 379 tmp_buffer = wsbmBOMap(surface_subpic->bo, WSBM_ACCESS_READ | WSBM_ACCESS_WRITE); 380 for (j = 0; j < surface_subpic->size; j = j + 4096) { 381 tmp = *(tmp_buffer + j); 382 if (tmp == 0) 383 *(tmp_buffer + j) = 0; 384 } 385 386 ePVR2DStatus = PVR2DMemWrap(driver_data->hPVR2DContext, 387 tmp_buffer, 388 0, 389 surface_subpic->size, 390 NULL, 391 &driver_data->subpicBuf[i]); 392 if (ePVR2DStatus != PVR2D_OK) { 393 psb__error_message("%s: PVR2DMemWrap error %d\n", __FUNCTION__, ePVR2DStatus); 394 return NULL; 395 } 396 397 driver_data->wrapped_subpic_id[i] = surface_subpic->subpic_id; 398 return driver_data->subpicBuf[i]; 399 } 400 } 401 402 if (i == VIDEO_BUFFER_NUM - 1) { 403 psb__error_message("%s: Out of warpped subpic buffer memory\n", __FUNCTION__); 404 return NULL; 405 } 406 407 return NULL; 408} 409 410 411void psb_init_surface_pvr2dbuf(psb_driver_data_p driver_data) 412{ 413 int i; 414 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 415 driver_data->videoBuf[i] = NULL; 416 driver_data->subpicBuf[i] = NULL; 417 driver_data->wrapped_surface_id[i] = -1; 418 driver_data->wrapped_subpic_id[i] = -1; 419 } 420 421} 422 423void psb_free_surface_pvr2dbuf(psb_driver_data_p driver_data) 424{ 425 int i; 426 PVR2DERROR ePVR2DStatus; 427 428 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 429 if ((driver_data->wrapped_surface_id[i] != -1) && driver_data->videoBuf[i]) { 430 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, driver_data->videoBuf[i]); 431 if (ePVR2DStatus != PVR2D_OK) 432 psb__error_message("%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 433 } 434 435 if ((driver_data->wrapped_subpic_id[i] != -1) && driver_data->subpicBuf[i]) { 436 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, driver_data->subpicBuf[i]); 437 if (ePVR2DStatus != PVR2D_OK) 438 psb__error_message("%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 439 } 440 441 driver_data->wrapped_surface_id[i] = -1; 442 driver_data->wrapped_subpic_id[i] = -1; 443 444 driver_data->videoBuf[i] = NULL; 445 driver_data->subpicBuf[i] = NULL; 446 } 447} 448 449 450static PPVR2DMEMINFO psb_wrap_surface_pvr2dbuf(psb_driver_data_p driver_data, VASurfaceID surface) 451{ 452 int i, j; 453 unsigned char* tmp_buffer; 454 unsigned char tmp; 455 object_surface_p obj_surface = SURFACE(surface); 456 psb_surface_p psb_surface = obj_surface->psb_surface; 457 PVR2DERROR ePVR2DStatus; 458 459 /* Find and return the wrapped buffer index */ 460 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 461 if (driver_data->wrapped_surface_id[i] == surface && driver_data->videoBuf[i]) { 462 return driver_data->videoBuf[i]; 463 } 464 } 465 466 /* Wrap a un-wrapped buffer and return */ 467 for (i = 0; i < VIDEO_BUFFER_NUM; i++) { 468 if (driver_data->wrapped_surface_id[i] == -1) { 469 tmp_buffer = NULL; 470 tmp_buffer = wsbmBOMap(psb_surface->buf.drm_buf, WSBM_ACCESS_READ | WSBM_ACCESS_WRITE); 471 for (j = 0; j < psb_surface->size; j = j + 4096) { 472 tmp = *(tmp_buffer + j); 473 if (tmp == 0) 474 *(tmp_buffer + j) = 0; 475 } 476 477 ePVR2DStatus = PVR2DMemWrap(driver_data->hPVR2DContext, 478 tmp_buffer, 479 0, 480 psb_surface->size, 481 NULL, 482 &driver_data->videoBuf[i]); 483 if (ePVR2DStatus != PVR2D_OK) { 484 psb__error_message("%s: PVR2DMemWrap error %d\n", __FUNCTION__, ePVR2DStatus); 485 } 486 487 driver_data->wrapped_surface_id[i] = surface; 488 return driver_data->videoBuf[i]; 489 } 490 } 491 492 if (i == VIDEO_BUFFER_NUM - 1) { 493 psb__error_message("%s: Out of warpped buffer memory\n", __FUNCTION__); 494 return NULL; 495 } 496 497 return NULL; 498} 499 500void psb_putsurface_textureblit( 501 VADriverContextP ctx, unsigned char *dst, VASurfaceID surface, int src_x, int src_y, int src_w, 502 int src_h, int dst_x, int dst_y, int dst_w, int dst_h, unsigned int subtitle, 503 int width, int height, 504 int src_pitch, struct _WsbmBufferObject * src_buf, 505 unsigned int placement, int wrap_dst) 506{ 507 INIT_DRIVER_DATA; 508 int i; 509 unsigned char *tmp_palette; 510 struct psb_texture_s *texture_priv = &driver_data->ctexture_priv; 511 object_surface_p obj_surface; 512 PsbVASurfaceRec *surface_subpic = NULL; 513 obj_surface = SURFACE(surface); 514 515 PVR2D_VPBLT sBltVP; 516 PVR2DERROR ePVR2DStatus; 517 PPVR2DMEMINFO pVaVideoSubpicMemInfo; 518 PPVR2DMEMINFO pVaVideoMemInfo; 519 PPVR2DMEMINFO pDstMeminfo; 520 521 src_pitch = (src_pitch + 0x3) & ~0x3; 522 523 if (NULL == obj_surface) { 524 psb__error_message("%s: Invalid surface ID 0x%08x!\n", __func__, surface); 525 return; 526 } 527 surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures; 528 /* check whether we need to update coeffs */ 529 if ((height > 576) && 530 (texture_priv->video_transfermatrix != PSB_VideoTransferMatrix_BT709)) { 531 texture_priv->video_transfermatrix = PSB_VideoTransferMatrix_BT709; 532 texture_priv->update_coeffs = 1; 533 } else if ((height <= 576) && 534 (texture_priv->video_transfermatrix != PSB_VideoTransferMatrix_BT601)) { 535 texture_priv->video_transfermatrix = PSB_VideoTransferMatrix_BT601; 536 texture_priv->update_coeffs = 1; 537 } 538 539 /* prepare coeffs if needed */ 540 memset(&sBltVP, 0, sizeof(PVR2D_VPBLT)); 541 if (texture_priv->update_coeffs == 1) { 542 psb_setup_coeffs(texture_priv); 543 sBltVP.psYUVCoeffs = (PPVR2D_YUVCOEFFS) & texture_priv->coeffs; 544 /* FIXME: is it right? */ 545 sBltVP.bCoeffsGiven = 1; 546 } 547 548 pVaVideoMemInfo = psb_wrap_surface_pvr2dbuf(driver_data, surface); 549 if (!pVaVideoMemInfo) { 550 psb__error_message("%s: Failed to get source PVR2DMEMINFO!\n", __func__); 551 return; 552 } 553 554 /* wrap the dest source */ 555 /* FIXME: this is wrap for rgb565 */ 556 if (wrap_dst == 0) { 557 558 pDstMeminfo = (PPVR2DMEMINFO)dst; 559 sBltVP.sDst.Stride = PVRCalculateStride(((struct dri_drawable*)texture_priv->dri_drawable)->width, 32, 8); 560 sBltVP.sDst.Format = PVR2D_ARGB8888; 561 562 } else { 563 ePVR2DStatus = PVR2DMemWrap(driver_data->hPVR2DContext, 564 dst, 565 0, 566 (dst_w * dst_h * 2), 567 NULL, 568 &pDstMeminfo); 569 if (ePVR2DStatus != PVR2D_OK) { 570 psb__error_message("%s: PVR2DMemWrap error %d\n", __FUNCTION__, ePVR2DStatus); 571 return; 572 } 573 574 /* FIXME: this wrong, how to get system pitch */ 575 sBltVP.sDst.Stride = dst_w * 2;//align_to(dst_w, 64); 576 sBltVP.sDst.Format = PVR2D_RGB565; 577 } 578 sBltVP.sDst.pSurfMemInfo = pDstMeminfo; 579 sBltVP.sDst.SurfOffset = 0; 580 sBltVP.sDst.SurfWidth = dst_w; 581 sBltVP.sDst.SurfHeight = dst_h; 582 583 /* Y plane UV plane */ 584 sBltVP.uiNumLayers = 1; 585 sBltVP.sSrc->Stride = src_pitch; 586 sBltVP.sSrc->Format = VA_FOURCC_NV12; 587 sBltVP.sSrc->SurfWidth = width; 588 sBltVP.sSrc->SurfHeight = height; 589 sBltVP.sSrc[0].pSurfMemInfo = pVaVideoMemInfo; 590 591 /* FIXME: check for top-bottom */ 592 sBltVP.sSrc->SurfOffset = 0; 593 594 /* FIXME: check rotation setting */ 595 /* FIXME: use PVR define */ 596 sBltVP.RotationValue = 1; 597 598 /* clip box */ 599 sBltVP.rcDest.left = dst_x; 600 sBltVP.rcDest.right = dst_x + dst_w; 601 sBltVP.rcDest.top = dst_y; 602 sBltVP.rcDest.bottom = dst_y + dst_h; 603 604 sBltVP.rcSource->left = src_x; 605 sBltVP.rcSource->right = src_x + src_w; 606 sBltVP.rcSource->top = src_y; 607 sBltVP.rcSource->bottom = src_y + src_h; 608 609 if (subtitle == 1 && obj_surface->subpic_count) { 610 for (i = 0; i < obj_surface->subpic_count; i++) { 611 sBltVP.uiNumLayers += 1; 612 613 psb_calculate_subpic_size(obj_surface->width, obj_surface->height, dst_w, dst_h, surface_subpic); 614 615 pVaVideoSubpicMemInfo = psb_check_subpic_buffer(driver_data, surface_subpic); 616 if (!pVaVideoSubpicMemInfo) { 617 psb__error_message("%s: Failed to get subpic PVR2DMEMINFO!\n", __func__); 618 return; 619 } 620 621 object_subpic_p obj_subpic = SUBPIC(surface_subpic->subpic_id); 622 sBltVP.AlphaBlendingFunc = PVR2D_ALPHA_OP_GLOBAL; 623 sBltVP.subpicGlobalAlpha[i] = obj_subpic->global_alpha; 624 625 sBltVP.sSrcSubpic[i].pSurfMemInfo = pVaVideoSubpicMemInfo; 626 sBltVP.sSrcSubpic[i].SurfOffset = 0; 627 sBltVP.sSrcSubpic[i].Stride = surface_subpic->stride; 628 629 if (surface_subpic->fourcc == VA_FOURCC_AI44) 630 sBltVP.sSrcSubpic[i].Format = MAKEFOURCC('A', 'I' , '4', '4'); 631 else 632 sBltVP.sSrcSubpic[i].Format = surface_subpic->fourcc; 633 634 sBltVP.sSrcSubpic[i].SurfWidth = surface_subpic->subpic_srcw; 635 sBltVP.sSrcSubpic[i].SurfHeight = surface_subpic->subpic_srch; 636 637 sBltVP.rcSubpicSource[i].left = surface_subpic->subpic_srcx; 638 sBltVP.rcSubpicSource[i].right = surface_subpic->subpic_srcx + surface_subpic->subpic_srcw; 639 sBltVP.rcSubpicSource[i].top = surface_subpic->subpic_srcy; 640 sBltVP.rcSubpicSource[i].bottom = surface_subpic->subpic_srcy + surface_subpic->subpic_srch; 641 642 sBltVP.rcSubpicDest[i].left = surface_subpic->subpic_dstx; 643 sBltVP.rcSubpicDest[i].right = surface_subpic->subpic_dstx + surface_subpic->subpic_dstw; 644 sBltVP.rcSubpicDest[i].top = surface_subpic->subpic_dsty; 645 sBltVP.rcSubpicDest[i].bottom = surface_subpic->subpic_dsty + surface_subpic->subpic_dsth; 646 647 //only allocate memory once for palette 648 if (surface_subpic->fourcc == VA_FOURCC_AI44) { 649 if (!texture_priv->pal_meminfo[i]) { 650 ePVR2DStatus = PVR2DMemAlloc(driver_data->hPVR2DContext, 16 * sizeof(unsigned int), 0, 0, &texture_priv->pal_meminfo[i]); 651 if (ePVR2DStatus != PVR2D_OK) { 652 psb__error_message("%s: PVR2DMemAlloc error %d\n", __FUNCTION__, ePVR2DStatus); 653 return; 654 } 655 } 656 657 sBltVP.pPalMemInfo[i] = texture_priv->pal_meminfo[i]; 658 tmp_palette = sBltVP.pPalMemInfo[i]->pBase; 659 memcpy(tmp_palette, surface_subpic->palette_ptr, 16 * sizeof(unsigned int)); 660 sBltVP.PalOffset[i] = 0; 661 } 662 surface_subpic = surface_subpic->next; 663 } 664 } 665 666//#ifndef ANDROID /* MRST Android not enable this API, uncomment for MRST */ 667 ePVR2DStatus = PVR2DBltVideo(driver_data->hPVR2DContext, &sBltVP); 668//#endif 669 670 if (ePVR2DStatus != PVR2D_OK) 671 psb__error_message("%s: failed to do PVR2DBltVideo with error code %d\n", 672 __FUNCTION__, ePVR2DStatus); 673 674 if (wrap_dst) { 675 ePVR2DStatus = PVR2DMemFree(driver_data->hPVR2DContext, pDstMeminfo); 676 if (ePVR2DStatus != PVR2D_OK) 677 psb__error_message("%s: PVR2DMemFree error %d\n", __FUNCTION__, ePVR2DStatus); 678 } 679} 680 681static void 682psb_setup_coeffs(struct psb_texture_s * pPriv) 683{ 684 double yCoeff, uCoeff, vCoeff, Constant; 685 double fContrast; 686 double Y_offset, CbCr_offset, RGB_offset; 687 int bright_off = 0; 688 psb_transform_coeffs coeffs, transfer_matrix; 689 memset(&coeffs, 0, sizeof(psb_transform_coeffs)); 690 memset(&transfer_matrix, 0, sizeof(psb_transform_coeffs)); 691 692 /* Offsets in the input and output ranges are 693 * included in the constant of the transform equation 694 */ 695 psb_select_transfermatrix(pPriv, &transfer_matrix, 696 &Y_offset, &CbCr_offset, &RGB_offset); 697 698 /* 699 * It is at this point we should adjust the parameters for the procamp: 700 * - Brightness is handled as an offset of the Y parameter. 701 * - Contrast is an adjustment of the Y scale. 702 * - Saturation is a scaling of the U anc V parameters. 703 * - Hue is a rotation of the U and V parameters. 704 */ 705 706 bright_off = pPriv->brightness.Value; 707 fContrast = (pPriv->contrast.Value + 100) / 100.0; 708 709 /* Apply hue and saturation correction to transfer matrix */ 710 psb_transform_sathuecoeffs(&coeffs, 711 &transfer_matrix, 712 pPriv->hue.Value * Degree, 713 pPriv->saturation.Value / 100.0); 714 715 /* Create coefficients to get component R 716 * (including brightness and contrast correction) 717 */ 718 psb_create_coeffs(-1 * Y_offset, -1 * CbCr_offset, -1 * CbCr_offset, 719 RGB_offset, coeffs.rY, coeffs.rCb, coeffs.rCr, 720 bright_off, fContrast, &yCoeff, &uCoeff, &vCoeff, 721 &Constant); 722 723 /* Convert transform operation from floating point to fixed point */ 724 psb_convert_coeffs(yCoeff, uCoeff, vCoeff, Constant, /* input coefficients */ 725 &pPriv->coeffs.rY, &pPriv->coeffs.rU, 726 &pPriv->coeffs.rV, &pPriv->coeffs.rConst, 727 &pPriv->coeffs.rShift); 728 729 /* Create coefficients to get component G 730 * (including brightness and contrast correction) 731 */ 732 psb_create_coeffs(-1 * Y_offset, -1 * CbCr_offset, -1 * CbCr_offset, 733 RGB_offset, coeffs.gY, coeffs.gCb, coeffs.gCr, 734 bright_off, fContrast, &yCoeff, &uCoeff, &vCoeff, 735 &Constant); 736 737 /* Convert transform operation from floating point to fixed point */ 738 psb_convert_coeffs(yCoeff, uCoeff, vCoeff, Constant, 739 /* tranfer matrix coefficients for G */ 740 &pPriv->coeffs.gY, &pPriv->coeffs.gU, 741 &pPriv->coeffs.gV, &pPriv->coeffs.gConst, 742 &pPriv->coeffs.gShift); 743 744 /* Create coefficients to get component B 745 * (including brightness and contrast correction) 746 */ 747 psb_create_coeffs(-1 * Y_offset, -1 * CbCr_offset, -1 * CbCr_offset, 748 RGB_offset, coeffs.bY, coeffs.bCb, coeffs.bCr, 749 bright_off, fContrast, &yCoeff, &uCoeff, &vCoeff, 750 &Constant); 751 752 /* Convert transform operation from floating point to fixed point */ 753 psb_convert_coeffs(yCoeff, uCoeff, vCoeff, Constant, 754 /* tranfer matrix coefficients for B */ 755 &pPriv->coeffs.bY, &pPriv->coeffs.bU, 756 &pPriv->coeffs.bV, &pPriv->coeffs.bConst, 757 &pPriv->coeffs.bShift); 758} 759 760/* 761 These are the corresponding matrices when using NominalRange_16_235 762 for the input surface and NominalRange_0_255 for the outpur surface: 763 764 static const psb_transform_coeffs s601 = { 765 1.164, 0, 1.596, 766 1.164, -0.391, -0.813, 767 1.164, 2.018, 0 768 }; 769 770 static const psb_transform_coeffs s709 = { 771 1.164, 0, 1.793, 772 1.164, -0.213, -0.534, 773 1.164, 2.115, 0 774 }; 775 776 static const psb_transform_coeffs s240M = { 777 1.164, -0.0007, 1.793, 778 1.164, -0.257, -0.542, 779 1.164, 2.078, 0.0004 780 }; 781*/ 782 783/** 784 * Select which transfer matrix to use in the YUV->RGB conversion. 785 */ 786static void 787psb_select_transfermatrix(struct psb_texture_s * pPriv, 788 psb_transform_coeffs * transfer_matrix, 789 double *Y_offset, double *CbCr_offset, 790 double *RGB_offset) 791{ 792 double RGB_scale, Y_scale, Cb_scale, Cr_scale; 793 794 /* 795 * Depending on the nominal ranges of the input YUV surface and the output RGB 796 * surface, it might be needed to perform some scaling on the transfer matrix. 797 * The excursion in the YUV values implies that the first column of the matrix 798 * must be divided by the Y excursion, and the second and third columns be 799 * divided by the U and V excursions respectively. The offset does not affect 800 * the values of the matrix. 801 * The excursion in the RGB values implies that all the values in the transfer 802 * matrix must be multiplied by the value of the excursion. 803 * 804 * Example: Conversion of the SMPTE 240M transfer matrix. 805 * 806 * Conversion from [Y', Pb, Pr] to [R', G', B'] in the range of [0, 1]. Y' is in 807 * the range of [0, 1] and Pb and Pr in the range of [-0.5, 0.5]. 808 * 809 * R' 1 -0.000657 1.575848 Y' 810 * G' = 1 -0.226418 -0.476529 * Pb 811 * B' 1 1.825958 0.000378 Pr 812 * 813 * Conversion from [Y', Cb, Cr] to {R', G', B'] in the range of [0, 1]. Y' has an 814 * excursion of 219 and an offset of +16, and CB and CR have excursions of +/-112 815 * and offset of +128, for a range of 16 through 240 inclusive. 816 * 817 * R' 1/219 -0.000657/224 1.575848/224 Y' 16 818 * G' = 1/219 -0.226418/224 -0.476529/224 * Cb - 128 819 * B' 1/219 1.825958/224 0.000378/224 Cr 128 820 * 821 * Conversion from [Y', Cb, Cr] to R'G'B' in the range [0, 255]. 822 * 823 * R' 1/219 -0.000657/224 1.575848/224 Y' 16 824 * G' = 255 * 1/219 -0.226418/224 -0.476529/224 * Cb - 128 825 * B' 1/219 1.825958/224 0.000378/224 Cr 128 826 */ 827 828 switch (pPriv->src_nominalrange) { 829 case PSB_NominalRange_0_255: 830 /* Y has a range of [0, 255], U and V have a range of [0, 255] */ 831 { 832 double tmp = 0.0; 833 834 (void)tmp; 835 } /* workaroud for float point bug? */ 836 Y_scale = 255.0; 837 *Y_offset = 0; 838 Cb_scale = Cr_scale = 255; 839 *CbCr_offset = 128; 840 break; 841 case PSB_NominalRange_16_235: 842 case PSB_NominalRange_Unknown: 843 /* Y has a range of [16, 235] and Cb, Cr have a range of [16, 240] */ 844 Y_scale = 219; 845 *Y_offset = 16; 846 Cb_scale = Cr_scale = 224; 847 *CbCr_offset = 128; 848 break; 849 case PSB_NominalRange_48_208: 850 /* Y has a range of [48, 208] and Cb, Cr have a range of [48, 208] */ 851 Y_scale = 160; 852 *Y_offset = 48; 853 Cb_scale = Cr_scale = 160; 854 *CbCr_offset = 128; 855 break; 856 857 default: 858 /* Y has a range of [0, 1], U and V have a range of [-0.5, 0.5] */ 859 Y_scale = 1; 860 *Y_offset = 0; 861 Cb_scale = Cr_scale = 1; 862 *CbCr_offset = 0; 863 break; 864 } 865 866 /* 867 * 8-bit computer RGB, also known as sRGB or "full-scale" RGB, and studio 868 * video RGB, or "RGB with head-room and toe-room." These are defined as follows: 869 * 870 * - Computer RGB uses 8 bits for each sample of red, green, and blue. Black 871 * is represented by R = G = B = 0, and white is represented by R = G = B = 255. 872 * - Studio video RGB uses some number of bits N for each sample of red, green, 873 * and blue, where N is 8 or more. Studio video RGB uses a different scaling 874 * factor than computer RGB, and it has an offset. Black is represented by 875 * R = G = B = 16*2^(N-8), and white is represented by R = G = B = 235*2^(N-8). 876 * However, actual values may fall outside this range. 877 */ 878 switch (pPriv->dst_nominalrange) { 879 case PSB_NominalRange_0_255: // for sRGB 880 case PSB_NominalRange_Unknown: 881 /* R, G and B have a range of [0, 255] */ 882 RGB_scale = 255; 883 *RGB_offset = 0; 884 break; 885 case PSB_NominalRange_16_235: // for stRGB 886 /* R, G and B have a range of [16, 235] */ 887 RGB_scale = 219; 888 *RGB_offset = 16; 889 break; 890 case PSB_NominalRange_48_208: // for Bt.1361 RGB 891 /* R, G and B have a range of [48, 208] */ 892 RGB_scale = 160; 893 *RGB_offset = 48; 894 break; 895 default: 896 /* R, G and B have a range of [0, 1] */ 897 RGB_scale = 1; 898 *RGB_offset = 0; 899 break; 900 } 901 902 switch (pPriv->video_transfermatrix) { 903 case PSB_VideoTransferMatrix_BT709: 904 memcpy(transfer_matrix, &s709, sizeof(psb_transform_coeffs)); 905 break; 906 case PSB_VideoTransferMatrix_BT601: 907 memcpy(transfer_matrix, &s601, sizeof(psb_transform_coeffs)); 908 break; 909 case PSB_VideoTransferMatrix_SMPTE240M: 910 memcpy(transfer_matrix, &s240M, sizeof(psb_transform_coeffs)); 911 break; 912 case PSB_VideoTransferMatrix_Unknown: 913 /* 914 * Specifies that the video transfer matrix is not specified. 915 * The default value is BT601 for standard definition (SD) video and BT709 916 * for high definition (HD) video. 917 */ 918 if (1 /*pPriv->sVideoDesc.SampleWidth < 720 */) { /* TODO, width selection */ 919 memcpy(transfer_matrix, &s601, sizeof(psb_transform_coeffs)); 920 } else { 921 memcpy(transfer_matrix, &s709, sizeof(psb_transform_coeffs)); 922 } 923 break; 924 default: 925 break; 926 } 927 928 if (Y_scale != 1 || Cb_scale != 1 || Cr_scale != 1) { 929 /* Each column of the transfer matrix has to 930 * be scaled by the excursion of each component 931 */ 932 psb_scale_transfermatrix(transfer_matrix, 1 / Y_scale, 1 / Cb_scale, 933 1 / Cr_scale); 934 } 935 if (RGB_scale != 1) { 936 /* All the values in the transfer matrix have to be multiplied 937 * by the excursion of the RGB components 938 */ 939 psb_scale_transfermatrix(transfer_matrix, RGB_scale, RGB_scale, 940 RGB_scale); 941 } 942} 943 944static void 945psb_scale_transfermatrix(psb_transform_coeffs * transfer_matrix, 946 double YColumScale, double CbColumScale, 947 double CrColumnScale) 948{ 949 /* First column of the transfer matrix */ 950 transfer_matrix->rY *= YColumScale; 951 transfer_matrix->gY *= YColumScale; 952 transfer_matrix->bY *= YColumScale; 953 954 /* Second column of the transfer matrix */ 955 transfer_matrix->rCb *= CbColumScale; 956 transfer_matrix->gCb *= CbColumScale; 957 transfer_matrix->bCb *= CbColumScale; 958 959 /* Third column of the transfer matrix */ 960 transfer_matrix->rCr *= CrColumnScale; 961 transfer_matrix->gCr *= CrColumnScale; 962 transfer_matrix->bCr *= CrColumnScale; 963} 964 965/* 966 * Calculates the coefficintes of a YUV->RGB conversion based on 967 * the provided basis coefficients (already had HUe and Satu applied). 968 * Performs brightness and contrast adjustment as well as the required 969 * offsets to put into correct range for hardware conversion. 970 */ 971static void 972psb_create_coeffs(double yOff, double uOff, double vOff, double rgbOff, 973 double yScale, double uScale, double vScale, 974 double brightness, double contrast, 975 double *pYCoeff, double *pUCoeff, double *pVCoeff, 976 double *pConstant) 977{ 978 *pYCoeff = yScale * contrast; 979 *pUCoeff = uScale * contrast; 980 *pVCoeff = vScale * contrast; 981 982 *pConstant = (((yOff + brightness) * yScale) 983 + (uOff * uScale) + (vOff * vScale)) * contrast + rgbOff; 984} 985 986/* 987 * Converts a floating point function in the form 988 * a*yCoeff + b*uCoeff + c * vCoeff + d 989 * Into a fixed point function of the forrm 990 * (a*pY + b * pU + c * pV + constant)>>pShift 991 */ 992static void 993psb_convert_coeffs(double Ycoeff, double Ucoeff, double Vcoeff, 994 double ConstantTerm, signed char *pY, signed char *pU, 995 signed char *pV, signed short *constant, 996 unsigned char *pShift) 997{ 998 *pShift = 0; 999 1000 Ycoeff *= 256; 1001 Ucoeff *= 256; 1002 Vcoeff *= 256; 1003 ConstantTerm *= 256; 1004 *pShift = 8; 1005 1006 /* 1007 * What we want to do is scale up the coefficients so that they just fit into their 1008 * allowed bits, so we are using signed maths giving us coefficients can be between +-128. 1009 * The constant can be between =- 32767. 1010 * The divide can be between 0 and 256 (on powers of two only). 1011 * A mathematical approach would be nice, but for simplicity do an iterative compare 1012 * and divide. Until something fits. 1013 */ 1014 while (psb_check_coeffs(Ycoeff, Ucoeff, Vcoeff, ConstantTerm, *pShift)) { 1015 Ycoeff /= 2; 1016 Ucoeff /= 2; 1017 Vcoeff /= 2; 1018 ConstantTerm /= 2; 1019 (*pShift)--; 1020 } 1021 *pY = (signed char)(Ycoeff + 0.5); 1022 *pU = (signed char)(Ucoeff + 0.5); 1023 *pV = (signed char)(Vcoeff + 0.5); 1024 *constant = (signed short)(ConstantTerm + 0.5); 1025} 1026 1027/** 1028 * Checks if the specified coefficients are within the ranges required 1029 * and returns true if they are else false. 1030 */ 1031static int 1032psb_check_coeffs(double Ycoeff, double Ucoeff, double Vcoeff, 1033 double ConstantTerm, signed char byShift) 1034{ 1035 if ((Ycoeff > 127) || (Ycoeff < -128)) { 1036 return 1; 1037 } 1038 if ((Ucoeff > 127) || (Ucoeff < -128)) { 1039 return 1; 1040 } 1041 if ((Vcoeff > 127) || (Vcoeff < -128)) { 1042 return 1; 1043 } 1044 if ((ConstantTerm > 32766) || (ConstantTerm < -32767)) { 1045 return 1; 1046 } 1047 return 0; 1048} 1049 1050static void 1051psb_transform_sathuecoeffs(psb_transform_coeffs * dest, 1052 const psb_transform_coeffs * const source, 1053 double fHue, double fSat) 1054{ 1055 double fHueSatSin, fHueSatCos; 1056 1057 fHueSatSin = sin(fHue) * fSat; 1058 fHueSatCos = cos(fHue) * fSat; 1059 1060 dest->rY = source->rY; 1061 dest->rCb = source->rCb * fHueSatCos - source->rCr * fHueSatSin; 1062 dest->rCr = source->rCr * fHueSatCos + source->rCb * fHueSatSin; 1063 1064 dest->gY = source->gY; 1065 dest->gCb = source->gCb * fHueSatCos - source->gCr * fHueSatSin; 1066 dest->gCr = source->gCr * fHueSatCos + source->gCb * fHueSatSin; 1067 1068 dest->bY = source->bY; 1069 dest->bCb = source->bCb * fHueSatCos - source->bCr * fHueSatSin; 1070 dest->bCr = source->bCr * fHueSatCos + source->bCb * fHueSatSin; 1071} 1072 1073