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