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