vmwgfx_tex_video.c revision 22f7e8e5
13bfa90b6Smrg/* 23bfa90b6Smrg * Copyright 2009-2011 VMWare, Inc. 33bfa90b6Smrg * All Rights Reserved. 43bfa90b6Smrg * 53bfa90b6Smrg * Permission is hereby granted, free of charge, to any person obtaining a 63bfa90b6Smrg * copy of this software and associated documentation files (the 73bfa90b6Smrg * "Software"), to deal in the Software without restriction, including 83bfa90b6Smrg * without limitation the rights to use, copy, modify, merge, publish, 93bfa90b6Smrg * distribute, sub license, and/or sell copies of the Software, and to 103bfa90b6Smrg * permit persons to whom the Software is furnished to do so, subject to 113bfa90b6Smrg * the following conditions: 123bfa90b6Smrg * 133bfa90b6Smrg * The above copyright notice and this permission notice (including the 143bfa90b6Smrg * next paragraph) shall be included in all copies or substantial portions 153bfa90b6Smrg * of the Software. 163bfa90b6Smrg * 173bfa90b6Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 183bfa90b6Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 193bfa90b6Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 203bfa90b6Smrg * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 213bfa90b6Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 223bfa90b6Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 233bfa90b6Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 243bfa90b6Smrg * 253bfa90b6Smrg * Author: Thomas Hellstrom <thellstrom@vmware.com> 263bfa90b6Smrg * Author: Zack Rusin <zackr@vmware.com> 273bfa90b6Smrg */ 283bfa90b6Smrg 293bfa90b6Smrg#include "vmwgfx_driver.h" 303bfa90b6Smrg#include "vmwgfx_drmi.h" 313bfa90b6Smrg#include "vmwgfx_saa.h" 323bfa90b6Smrg 333bfa90b6Smrg#include <xf86xv.h> 343bfa90b6Smrg#include <X11/extensions/Xv.h> 353bfa90b6Smrg#include <fourcc.h> 363bfa90b6Smrg#include <xa_tracker.h> 373bfa90b6Smrg#include <xa_context.h> 383bfa90b6Smrg#include <math.h> 393bfa90b6Smrg 403bfa90b6Smrg/*XXX get these from pipe's texture limits */ 413bfa90b6Smrg#define IMAGE_MAX_WIDTH 2048 423bfa90b6Smrg#define IMAGE_MAX_HEIGHT 2048 433bfa90b6Smrg 443bfa90b6Smrg#define RES_720P_X 1280 453bfa90b6Smrg#define RES_720P_Y 720 463bfa90b6Smrg 473bfa90b6Smrg 483bfa90b6Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 493bfa90b6Smrg 503bfa90b6Smrg/* 513bfa90b6Smrg * ITU-R BT.601, BT.709 transfer matrices. 523bfa90b6Smrg * [R', G', B'] values are in the range [0, 1], Y' is in the range [0,1] 533bfa90b6Smrg * and [Pb, Pr] components are in the range [-0.5, 0.5]. 543bfa90b6Smrg * 553bfa90b6Smrg * The matrices are transposed to fit the xa conversion matrix format. 563bfa90b6Smrg */ 573bfa90b6Smrg 583bfa90b6Smrgstatic const float bt_601[] = { 593bfa90b6Smrg 1.f, 1.f, 1.f, 0.f, 603bfa90b6Smrg 0.f, -0.344136f, 1.772f, 0.f, 613bfa90b6Smrg 1.402f, -0.714136f, 0.f, 0.f 623bfa90b6Smrg}; 633bfa90b6Smrg 643bfa90b6Smrgstatic const float bt_709[] = { 653bfa90b6Smrg 1.f, 1.f, 1.f, 0.f, 663bfa90b6Smrg 0.f, -0.187324f, 1.8556f, 0.f, 673bfa90b6Smrg 1.5748f, -0.468124f, 0.f, 0.f 683bfa90b6Smrg}; 693bfa90b6Smrg 703bfa90b6Smrgstatic Atom xvBrightness, xvContrast, xvSaturation, xvHue; 713bfa90b6Smrg 723bfa90b6Smrg#define NUM_TEXTURED_ATTRIBUTES 4 7322f7e8e5Smrgstatic const XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = { 7422f7e8e5Smrg {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 7522f7e8e5Smrg {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 7622f7e8e5Smrg {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 7722f7e8e5Smrg {XvSettable | XvGettable, -1000, 1000, "XV_HUE"} 783bfa90b6Smrg}; 793bfa90b6Smrg 803bfa90b6Smrg#define NUM_FORMATS 3 813bfa90b6Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = { 823bfa90b6Smrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 833bfa90b6Smrg}; 843bfa90b6Smrg 853bfa90b6Smrgstatic XF86VideoEncodingRec DummyEncoding[1] = { 863bfa90b6Smrg { 873bfa90b6Smrg 0, 883bfa90b6Smrg "XV_IMAGE", 893bfa90b6Smrg IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 903bfa90b6Smrg {1, 1} 913bfa90b6Smrg } 923bfa90b6Smrg}; 933bfa90b6Smrg 943bfa90b6Smrg#define NUM_IMAGES 3 953bfa90b6Smrgstatic XF86ImageRec Images[NUM_IMAGES] = { 963bfa90b6Smrg XVIMAGE_UYVY, 973bfa90b6Smrg XVIMAGE_YUY2, 983bfa90b6Smrg XVIMAGE_YV12, 993bfa90b6Smrg}; 1003bfa90b6Smrg 1013bfa90b6Smrgstruct xorg_xv_port_priv { 1023bfa90b6Smrg struct xa_tracker *xat; 1033bfa90b6Smrg struct xa_context *r; 1043bfa90b6Smrg struct xa_fence *fence; 1053bfa90b6Smrg 1063bfa90b6Smrg RegionRec clip; 1073bfa90b6Smrg 1083bfa90b6Smrg int brightness; 1093bfa90b6Smrg int contrast; 1103bfa90b6Smrg int saturation; 1113bfa90b6Smrg int hue; 1123bfa90b6Smrg 1133bfa90b6Smrg int current_set; 11422f7e8e5Smrg struct xa_surface *yuv[2][3]; 1153bfa90b6Smrg 1163bfa90b6Smrg int drm_fd; 1173bfa90b6Smrg 1183bfa90b6Smrg Bool hdtv; 1193bfa90b6Smrg float uv_offset; 1203bfa90b6Smrg float uv_scale; 1213bfa90b6Smrg float y_offset; 1223bfa90b6Smrg float y_scale; 1233bfa90b6Smrg float rgb_offset; 1243bfa90b6Smrg float rgb_scale; 1253bfa90b6Smrg float sinhue; 1263bfa90b6Smrg float coshue; 1273bfa90b6Smrg float cm[16]; 1283bfa90b6Smrg}; 1293bfa90b6Smrg 1303bfa90b6Smrg/* 1313bfa90b6Smrg * vmwgfx_update_conversion_matrix - Compute the effective color conversion 1323bfa90b6Smrg * matrix. 1333bfa90b6Smrg * 1343bfa90b6Smrg * Applies yuv- and resulting rgb scales and offsets to compute the correct 1353bfa90b6Smrg * color conversion matrix. These scales and offsets are properties of the 1363bfa90b6Smrg * video stream and can be adjusted using XV properties as well. 1373bfa90b6Smrg */ 1383bfa90b6Smrgstatic void 1393bfa90b6Smrgvmwgfx_update_conversion_matrix(struct xorg_xv_port_priv *priv) 1403bfa90b6Smrg{ 1413bfa90b6Smrg int i; 1423bfa90b6Smrg float *cm = priv->cm; 1433bfa90b6Smrg static const float *bt; 1443bfa90b6Smrg 1453bfa90b6Smrg bt = (priv->hdtv) ? bt_709 : bt_601; 1463bfa90b6Smrg 1473bfa90b6Smrg memcpy(cm, bt, sizeof(bt_601)); 1483bfa90b6Smrg 1493bfa90b6Smrg /* 1503bfa90b6Smrg * Apply hue rotation 1513bfa90b6Smrg */ 1523bfa90b6Smrg cm[4] = priv->coshue * bt[4] - priv->sinhue * bt[8]; 1533bfa90b6Smrg cm[8] = priv->sinhue * bt[4] + priv->coshue * bt[8]; 1543bfa90b6Smrg cm[5] = priv->coshue * bt[5] - priv->sinhue * bt[9]; 1553bfa90b6Smrg cm[9] = priv->sinhue * bt[5] + priv->coshue * bt[9]; 1563bfa90b6Smrg cm[6] = priv->coshue * bt[6] - priv->sinhue * bt[10]; 1573bfa90b6Smrg cm[10] = priv->sinhue * bt[6] + priv->coshue * bt[10]; 1583bfa90b6Smrg 1593bfa90b6Smrg /* 1603bfa90b6Smrg * Adjust for yuv scales in input and rgb scale in the converted output. 1613bfa90b6Smrg */ 1623bfa90b6Smrg for(i = 0; i < 3; ++i) { 1633bfa90b6Smrg cm[i] *= (priv->y_scale*priv->rgb_scale); 1643bfa90b6Smrg cm[i+4] *= (priv->uv_scale*priv->rgb_scale); 1653bfa90b6Smrg cm[i+8] *= (priv->uv_scale*priv->rgb_scale); 1663bfa90b6Smrg } 1673bfa90b6Smrg 1683bfa90b6Smrg /* 1693bfa90b6Smrg * Adjust for yuv offsets in input and rgb offset in the converted output. 1703bfa90b6Smrg */ 1713bfa90b6Smrg for (i = 0; i < 3; ++i) 1723bfa90b6Smrg cm[i+12] = -cm[i]*priv->y_offset - (cm[i+4] + cm[i+8])*priv->uv_offset 1733bfa90b6Smrg - priv->rgb_offset*priv->rgb_scale; 1743bfa90b6Smrg 1753bfa90b6Smrg /* 1763bfa90b6Smrg * Alpha is 1, unconditionally. 1773bfa90b6Smrg */ 1783bfa90b6Smrg cm[15] = 1.f; 1793bfa90b6Smrg} 1803bfa90b6Smrg 1813bfa90b6Smrg 1823bfa90b6Smrgstatic void 1833bfa90b6Smrgstop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 1843bfa90b6Smrg{ 1853bfa90b6Smrg struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 1863bfa90b6Smrg int i, j; 1873bfa90b6Smrg 1883bfa90b6Smrg REGION_EMPTY(pScrn->pScreen, &priv->clip); 1893bfa90b6Smrg if (shutdown) { 1903bfa90b6Smrg 1913bfa90b6Smrg /* 1923bfa90b6Smrg * No need to destroy the xa context or xa tracker since 1933bfa90b6Smrg * they are copied from the screen resources. 1943bfa90b6Smrg */ 1953bfa90b6Smrg 1963bfa90b6Smrg xa_fence_destroy(priv->fence); 1973bfa90b6Smrg priv->fence = NULL; 1983bfa90b6Smrg 1993bfa90b6Smrg for (i=0; i<3; ++i) { 2003bfa90b6Smrg for (j=0; j<2; ++j) { 20122f7e8e5Smrg if (priv->yuv[i]) { 20222f7e8e5Smrg xa_surface_destroy(priv->yuv[j][i]); 20322f7e8e5Smrg priv->yuv[j][i] = NULL; 2043bfa90b6Smrg } 2053bfa90b6Smrg } 2063bfa90b6Smrg } 2073bfa90b6Smrg } 2083bfa90b6Smrg} 2093bfa90b6Smrg 2103bfa90b6Smrgstatic int 2113bfa90b6Smrgset_port_attribute(ScrnInfoPtr pScrn, 2123bfa90b6Smrg Atom attribute, INT32 value, pointer data) 2133bfa90b6Smrg{ 2143bfa90b6Smrg struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 2153bfa90b6Smrg 2163bfa90b6Smrg if (attribute == xvBrightness) { 2173bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2183bfa90b6Smrg return BadValue; 2193bfa90b6Smrg 2203bfa90b6Smrg priv->brightness = value; 2213bfa90b6Smrg priv->y_offset = -((float) value)/1000.f; 2223bfa90b6Smrg 2233bfa90b6Smrg } else if (attribute == xvContrast) { 2243bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2253bfa90b6Smrg return BadValue; 2263bfa90b6Smrg 2273bfa90b6Smrg priv->contrast = value; 2283bfa90b6Smrg priv->rgb_scale = ((float) value + 1000.f)/1000.f; 2293bfa90b6Smrg 2303bfa90b6Smrg } else if (attribute == xvSaturation) { 2313bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2323bfa90b6Smrg return BadValue; 2333bfa90b6Smrg 2343bfa90b6Smrg priv->saturation = value; 2353bfa90b6Smrg priv->uv_scale = ((float) value + 1000.f)/1000.f; 2363bfa90b6Smrg 2373bfa90b6Smrg } else if (attribute == xvHue) { 2383bfa90b6Smrg double hue_angle; 2393bfa90b6Smrg 2403bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2413bfa90b6Smrg return BadValue; 2423bfa90b6Smrg 2433bfa90b6Smrg priv->hue = value; 2443bfa90b6Smrg hue_angle = (double) value * M_PI / 1000.; 2453bfa90b6Smrg priv->sinhue = sin(hue_angle); 2463bfa90b6Smrg priv->coshue = cos(hue_angle); 2473bfa90b6Smrg 2483bfa90b6Smrg } else 2493bfa90b6Smrg return BadMatch; 2503bfa90b6Smrg 2513bfa90b6Smrg vmwgfx_update_conversion_matrix(priv); 2523bfa90b6Smrg return Success; 2533bfa90b6Smrg} 2543bfa90b6Smrg 2553bfa90b6Smrgstatic int 2563bfa90b6Smrgget_port_attribute(ScrnInfoPtr pScrn, 2573bfa90b6Smrg Atom attribute, INT32 * value, pointer data) 2583bfa90b6Smrg{ 2593bfa90b6Smrg struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 2603bfa90b6Smrg 2613bfa90b6Smrg if (attribute == xvBrightness) 2623bfa90b6Smrg *value = priv->brightness; 2633bfa90b6Smrg else if (attribute == xvContrast) 2643bfa90b6Smrg *value = priv->contrast; 2653bfa90b6Smrg else if (attribute == xvSaturation) 2663bfa90b6Smrg *value = priv->saturation; 2673bfa90b6Smrg else if (attribute == xvHue) 2683bfa90b6Smrg *value = priv->hue; 2693bfa90b6Smrg else 2703bfa90b6Smrg return BadMatch; 2713bfa90b6Smrg 2723bfa90b6Smrg return Success; 2733bfa90b6Smrg} 2743bfa90b6Smrg 2753bfa90b6Smrgstatic void 2763bfa90b6Smrgquery_best_size(ScrnInfoPtr pScrn, 2773bfa90b6Smrg Bool motion, 2783bfa90b6Smrg short vid_w, short vid_h, 2793bfa90b6Smrg short drw_w, short drw_h, 2803bfa90b6Smrg unsigned int *p_w, unsigned int *p_h, pointer data) 2813bfa90b6Smrg{ 2823bfa90b6Smrg if (vid_w > (drw_w << 1)) 2833bfa90b6Smrg drw_w = vid_w >> 1; 2843bfa90b6Smrg if (vid_h > (drw_h << 1)) 2853bfa90b6Smrg drw_h = vid_h >> 1; 2863bfa90b6Smrg 2873bfa90b6Smrg *p_w = drw_w; 2883bfa90b6Smrg *p_h = drw_h; 2893bfa90b6Smrg} 2903bfa90b6Smrg 2913bfa90b6Smrgstatic int 2923bfa90b6Smrgcheck_yuv_surfaces(struct xorg_xv_port_priv *priv, int id, 2933bfa90b6Smrg int width, int height) 2943bfa90b6Smrg{ 29522f7e8e5Smrg struct xa_surface **yuv = priv->yuv[priv->current_set]; 2963bfa90b6Smrg int ret = 0; 2973bfa90b6Smrg int i; 2983bfa90b6Smrg 2993bfa90b6Smrg for (i=0; i<3; ++i) { 3003bfa90b6Smrg 3013bfa90b6Smrg /* 3023bfa90b6Smrg * Adjust u,v texture size and DMA buffer to what's required by 3033bfa90b6Smrg * the format. 3043bfa90b6Smrg */ 3053bfa90b6Smrg if (i == 1) { 3063bfa90b6Smrg switch(id) { 3073bfa90b6Smrg case FOURCC_YV12: 3083bfa90b6Smrg height /= 2; 3093bfa90b6Smrg /* Fall through */ 3103bfa90b6Smrg case FOURCC_YUY2: 3113bfa90b6Smrg case FOURCC_UYVY: 3123bfa90b6Smrg width /= 2; 3133bfa90b6Smrg break; 3143bfa90b6Smrg default: 3153bfa90b6Smrg break; 3163bfa90b6Smrg } 3173bfa90b6Smrg } 3183bfa90b6Smrg 3193bfa90b6Smrg if (!yuv[i]) 3203bfa90b6Smrg yuv[i] = xa_surface_create(priv->xat, width, height, 8, 3213bfa90b6Smrg xa_type_yuv_component, 3223bfa90b6Smrg xa_format_unknown, 0); 3233bfa90b6Smrg else 3243bfa90b6Smrg ret = xa_surface_redefine(yuv[i], width, height, 8, 3253bfa90b6Smrg xa_type_yuv_component, 3263bfa90b6Smrg xa_format_unknown, 0, 0); 3273bfa90b6Smrg if (ret || !yuv[i]) 3283bfa90b6Smrg return BadAlloc; 3293bfa90b6Smrg 3303bfa90b6Smrg } 3313bfa90b6Smrg return Success; 3323bfa90b6Smrg} 3333bfa90b6Smrg 3343bfa90b6Smrgstatic int 3353bfa90b6Smrgquery_image_attributes(ScrnInfoPtr pScrn, 3363bfa90b6Smrg int id, 3373bfa90b6Smrg unsigned short *w, unsigned short *h, 3383bfa90b6Smrg int *pitches, int *offsets) 3393bfa90b6Smrg{ 3403bfa90b6Smrg int size, tmp; 3413bfa90b6Smrg 3423bfa90b6Smrg if (*w > IMAGE_MAX_WIDTH) 3433bfa90b6Smrg *w = IMAGE_MAX_WIDTH; 3443bfa90b6Smrg if (*h > IMAGE_MAX_HEIGHT) 3453bfa90b6Smrg *h = IMAGE_MAX_HEIGHT; 3463bfa90b6Smrg 3473bfa90b6Smrg *w = (*w + 1) & ~1; 3483bfa90b6Smrg if (offsets) 3493bfa90b6Smrg offsets[0] = 0; 3503bfa90b6Smrg 3513bfa90b6Smrg switch (id) { 3523bfa90b6Smrg case FOURCC_YV12: 3533bfa90b6Smrg *h = (*h + 1) & ~1; 3543bfa90b6Smrg size = (*w + 3) & ~3; 3553bfa90b6Smrg if (pitches) { 3563bfa90b6Smrg pitches[0] = size; 3573bfa90b6Smrg } 3583bfa90b6Smrg size *= *h; 3593bfa90b6Smrg if (offsets) { 3603bfa90b6Smrg offsets[1] = size; 3613bfa90b6Smrg } 3623bfa90b6Smrg tmp = ((*w >> 1) + 3) & ~3; 3633bfa90b6Smrg if (pitches) { 3643bfa90b6Smrg pitches[1] = pitches[2] = tmp; 3653bfa90b6Smrg } 3663bfa90b6Smrg tmp *= (*h >> 1); 3673bfa90b6Smrg size += tmp; 3683bfa90b6Smrg if (offsets) { 3693bfa90b6Smrg offsets[2] = size; 3703bfa90b6Smrg } 3713bfa90b6Smrg size += tmp; 3723bfa90b6Smrg break; 3733bfa90b6Smrg case FOURCC_UYVY: 3743bfa90b6Smrg case FOURCC_YUY2: 3753bfa90b6Smrg default: 3763bfa90b6Smrg size = *w << 1; 3773bfa90b6Smrg if (pitches) 3783bfa90b6Smrg pitches[0] = size; 3793bfa90b6Smrg size *= *h; 3803bfa90b6Smrg break; 3813bfa90b6Smrg } 3823bfa90b6Smrg 3833bfa90b6Smrg return size; 3843bfa90b6Smrg} 3853bfa90b6Smrg 3863bfa90b6Smrgstatic int 3873bfa90b6Smrgcopy_packed_data(ScrnInfoPtr pScrn, 3883bfa90b6Smrg struct xorg_xv_port_priv *port, 3893bfa90b6Smrg int id, 3903bfa90b6Smrg unsigned char *buf, 3913bfa90b6Smrg int left, 3923bfa90b6Smrg int top, 3933bfa90b6Smrg unsigned short w, unsigned short h) 3943bfa90b6Smrg{ 3953bfa90b6Smrg int i; 39622f7e8e5Smrg struct xa_surface **yuv = port->yuv[port->current_set]; 3973bfa90b6Smrg char *ymap, *vmap, *umap; 3983bfa90b6Smrg unsigned char y1, y2, u, v; 3993bfa90b6Smrg int yidx, uidx, vidx; 4003bfa90b6Smrg int y_array_size = w * h; 4013bfa90b6Smrg int ret = BadAlloc; 4023bfa90b6Smrg 40322f7e8e5Smrg ymap = xa_surface_map(port->r, yuv[0], XA_MAP_WRITE); 4043bfa90b6Smrg if (!ymap) 4053bfa90b6Smrg return BadAlloc; 40622f7e8e5Smrg umap = xa_surface_map(port->r, yuv[1], XA_MAP_WRITE); 4073bfa90b6Smrg if (!umap) 4083bfa90b6Smrg goto out_no_umap; 40922f7e8e5Smrg vmap = xa_surface_map(port->r, yuv[2], XA_MAP_WRITE); 4103bfa90b6Smrg if (!vmap) 4113bfa90b6Smrg goto out_no_vmap; 4123bfa90b6Smrg 4133bfa90b6Smrg 4143bfa90b6Smrg yidx = uidx = vidx = 0; 4153bfa90b6Smrg 4163bfa90b6Smrg switch (id) { 4173bfa90b6Smrg case FOURCC_YV12: { 4183bfa90b6Smrg int pitches[3], offsets[3]; 41922f7e8e5Smrg unsigned char *yp, *up, *vp; 4203bfa90b6Smrg query_image_attributes(pScrn, FOURCC_YV12, 4213bfa90b6Smrg &w, &h, pitches, offsets); 4223bfa90b6Smrg 42322f7e8e5Smrg yp = buf + offsets[0]; 42422f7e8e5Smrg vp = buf + offsets[1]; 42522f7e8e5Smrg up = buf + offsets[2]; 42622f7e8e5Smrg memcpy(ymap, yp, w*h); 42722f7e8e5Smrg memcpy(vmap, vp, w*h/4); 42822f7e8e5Smrg memcpy(umap, up, w*h/4); 4293bfa90b6Smrg break; 4303bfa90b6Smrg } 4313bfa90b6Smrg case FOURCC_UYVY: 4323bfa90b6Smrg for (i = 0; i < y_array_size; i +=2 ) { 4333bfa90b6Smrg /* extracting two pixels */ 4343bfa90b6Smrg u = buf[0]; 4353bfa90b6Smrg y1 = buf[1]; 4363bfa90b6Smrg v = buf[2]; 4373bfa90b6Smrg y2 = buf[3]; 4383bfa90b6Smrg buf += 4; 4393bfa90b6Smrg 4403bfa90b6Smrg ymap[yidx++] = y1; 4413bfa90b6Smrg ymap[yidx++] = y2; 4423bfa90b6Smrg umap[uidx++] = u; 4433bfa90b6Smrg vmap[vidx++] = v; 4443bfa90b6Smrg } 4453bfa90b6Smrg break; 4463bfa90b6Smrg case FOURCC_YUY2: 4473bfa90b6Smrg for (i = 0; i < y_array_size; i +=2 ) { 4483bfa90b6Smrg /* extracting two pixels */ 4493bfa90b6Smrg y1 = buf[0]; 4503bfa90b6Smrg u = buf[1]; 4513bfa90b6Smrg y2 = buf[2]; 4523bfa90b6Smrg v = buf[3]; 4533bfa90b6Smrg 4543bfa90b6Smrg buf += 4; 4553bfa90b6Smrg 4563bfa90b6Smrg ymap[yidx++] = y1; 4573bfa90b6Smrg ymap[yidx++] = y2; 4583bfa90b6Smrg umap[uidx++] = u; 4593bfa90b6Smrg vmap[vidx++] = v; 4603bfa90b6Smrg } 4613bfa90b6Smrg break; 4623bfa90b6Smrg default: 4633bfa90b6Smrg ret = BadAlloc; 4643bfa90b6Smrg break; 4653bfa90b6Smrg } 4663bfa90b6Smrg 4673bfa90b6Smrg ret = Success; 46822f7e8e5Smrg xa_surface_unmap(yuv[2]); 4693bfa90b6Smrg out_no_vmap: 47022f7e8e5Smrg xa_surface_unmap(yuv[1]); 4713bfa90b6Smrg out_no_umap: 47222f7e8e5Smrg xa_surface_unmap(yuv[0]); 4733bfa90b6Smrg 4743bfa90b6Smrg return ret; 4753bfa90b6Smrg} 4763bfa90b6Smrg 4773bfa90b6Smrg 4783bfa90b6Smrgstatic int 4793bfa90b6Smrgdisplay_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, 4803bfa90b6Smrg RegionPtr dstRegion, 4813bfa90b6Smrg int src_x, int src_y, int src_w, int src_h, 4823bfa90b6Smrg int dst_x, int dst_y, int dst_w, int dst_h, 4833bfa90b6Smrg PixmapPtr pPixmap) 4843bfa90b6Smrg{ 4853bfa90b6Smrg struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pPixmap); 4863bfa90b6Smrg Bool hdtv; 4873bfa90b6Smrg RegionRec reg; 4883bfa90b6Smrg int ret = BadAlloc; 4893bfa90b6Smrg int blit_ret; 4903bfa90b6Smrg 4913bfa90b6Smrg REGION_NULL(pScreen, ®); 4923bfa90b6Smrg 4933bfa90b6Smrg if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, ®)) 4943bfa90b6Smrg goto out_no_dst; 4953bfa90b6Smrg 4963bfa90b6Smrg hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y)); 4973bfa90b6Smrg if (hdtv != pPriv->hdtv) { 4983bfa90b6Smrg pPriv->hdtv = hdtv; 4993bfa90b6Smrg vmwgfx_update_conversion_matrix(pPriv); 5003bfa90b6Smrg } 5013bfa90b6Smrg 5023bfa90b6Smrg#ifdef COMPOSITE 5033bfa90b6Smrg 5043bfa90b6Smrg /* 5053bfa90b6Smrg * For redirected windows, we need to fix up the destination coordinates. 5063bfa90b6Smrg */ 5073bfa90b6Smrg 5083bfa90b6Smrg REGION_TRANSLATE(pScreen, dstRegion, -pPixmap->screen_x, 5093bfa90b6Smrg -pPixmap->screen_y); 5103bfa90b6Smrg dst_x -= pPixmap->screen_x; 5113bfa90b6Smrg dst_y -= pPixmap->screen_y; 5123bfa90b6Smrg#endif 5133bfa90b6Smrg 5143bfa90b6Smrg /* 5153bfa90b6Smrg * Throttle on previous blit. 5163bfa90b6Smrg */ 5173bfa90b6Smrg 5183bfa90b6Smrg if (pPriv->fence) { 5193bfa90b6Smrg (void) xa_fence_wait(pPriv->fence, 1000000000ULL); 5203bfa90b6Smrg xa_fence_destroy(pPriv->fence); 5213bfa90b6Smrg pPriv->fence = NULL; 5223bfa90b6Smrg } 5233bfa90b6Smrg 5243bfa90b6Smrg DamageRegionAppend(&pPixmap->drawable, dstRegion); 5253bfa90b6Smrg 5263bfa90b6Smrg blit_ret = xa_yuv_planar_blit(pPriv->r, src_x, src_y, src_w, src_h, 5273bfa90b6Smrg dst_x, dst_y, dst_w, dst_h, 5283bfa90b6Smrg (struct xa_box *)REGION_RECTS(dstRegion), 5293bfa90b6Smrg REGION_NUM_RECTS(dstRegion), 5303bfa90b6Smrg pPriv->cm, 53122f7e8e5Smrg vpix->hw, 53222f7e8e5Smrg pPriv->yuv[pPriv->current_set ]); 5333bfa90b6Smrg 5343bfa90b6Smrg saa_pixmap_dirty(pPixmap, TRUE, dstRegion); 5353bfa90b6Smrg DamageRegionProcessPending(&pPixmap->drawable); 5363bfa90b6Smrg ret = Success; 5373bfa90b6Smrg 5383bfa90b6Smrg if (!blit_ret) { 5393bfa90b6Smrg ret = Success; 5403bfa90b6Smrg pPriv->fence = xa_fence_get(pPriv->r); 5413bfa90b6Smrg } else 5423bfa90b6Smrg ret = BadAlloc; 5433bfa90b6Smrg 5443bfa90b6Smrg out_no_dst: 5453bfa90b6Smrg REGION_UNINIT(pScreen, ®); 5463bfa90b6Smrg return ret; 5473bfa90b6Smrg} 5483bfa90b6Smrg 5493bfa90b6Smrgstatic int 5503bfa90b6Smrgput_image(ScrnInfoPtr pScrn, 5513bfa90b6Smrg short src_x, short src_y, 5523bfa90b6Smrg short drw_x, short drw_y, 5533bfa90b6Smrg short src_w, short src_h, 5543bfa90b6Smrg short drw_w, short drw_h, 5553bfa90b6Smrg int id, unsigned char *buf, 5563bfa90b6Smrg short width, short height, 5573bfa90b6Smrg Bool sync, RegionPtr clipBoxes, pointer data, 5583bfa90b6Smrg DrawablePtr pDraw) 5593bfa90b6Smrg{ 5603bfa90b6Smrg struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data; 5613bfa90b6Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 5623bfa90b6Smrg PixmapPtr pPixmap; 5633bfa90b6Smrg INT32 x1, x2, y1, y2; 5643bfa90b6Smrg BoxRec dstBox; 5653bfa90b6Smrg int ret; 5663bfa90b6Smrg 5673bfa90b6Smrg /* Clip */ 5683bfa90b6Smrg x1 = src_x; 5693bfa90b6Smrg x2 = src_x + src_w; 5703bfa90b6Smrg y1 = src_y; 5713bfa90b6Smrg y2 = src_y + src_h; 5723bfa90b6Smrg 5733bfa90b6Smrg dstBox.x1 = drw_x; 5743bfa90b6Smrg dstBox.x2 = drw_x + drw_w; 5753bfa90b6Smrg dstBox.y1 = drw_y; 5763bfa90b6Smrg dstBox.y2 = drw_y + drw_h; 5773bfa90b6Smrg 5783bfa90b6Smrg if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 5793bfa90b6Smrg width, height)) 5803bfa90b6Smrg return Success; 5813bfa90b6Smrg 5823bfa90b6Smrg ret = check_yuv_surfaces(pPriv, id, width, height); 5833bfa90b6Smrg if (ret) 5843bfa90b6Smrg return ret; 5853bfa90b6Smrg 5863bfa90b6Smrg ret = copy_packed_data(pScrn, pPriv, id, buf, 5873bfa90b6Smrg src_x, src_y, width, height); 5883bfa90b6Smrg if (ret) 5893bfa90b6Smrg return ret; 5903bfa90b6Smrg 5913bfa90b6Smrg if (pDraw->type == DRAWABLE_WINDOW) { 5923bfa90b6Smrg pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); 5933bfa90b6Smrg } else { 5943bfa90b6Smrg pPixmap = (PixmapPtr)pDraw; 5953bfa90b6Smrg } 5963bfa90b6Smrg 5973bfa90b6Smrg display_video(pScrn->pScreen, pPriv, id, clipBoxes, 5983bfa90b6Smrg src_x, src_y, src_w, src_h, 5993bfa90b6Smrg drw_x, drw_y, 6003bfa90b6Smrg drw_w, drw_h, pPixmap); 6013bfa90b6Smrg 6023bfa90b6Smrg pPriv->current_set = (pPriv->current_set + 1) & 1; 6033bfa90b6Smrg return Success; 6043bfa90b6Smrg} 6053bfa90b6Smrg 6063bfa90b6Smrgstatic struct xorg_xv_port_priv * 6073bfa90b6Smrgport_priv_create(struct xa_tracker *xat, struct xa_context *r, 6083bfa90b6Smrg int drm_fd) 6093bfa90b6Smrg{ 6103bfa90b6Smrg struct xorg_xv_port_priv *priv = NULL; 6113bfa90b6Smrg 6123bfa90b6Smrg priv = calloc(1, sizeof(struct xorg_xv_port_priv)); 6133bfa90b6Smrg 6143bfa90b6Smrg if (!priv) 6153bfa90b6Smrg return NULL; 6163bfa90b6Smrg 6173bfa90b6Smrg priv->r = r; 6183bfa90b6Smrg priv->xat = xat; 6193bfa90b6Smrg priv->drm_fd = drm_fd; 6203bfa90b6Smrg REGION_NULL(pScreen, &priv->clip); 6213bfa90b6Smrg priv->hdtv = FALSE; 6223bfa90b6Smrg priv->uv_offset = 0.5f; 6233bfa90b6Smrg priv->uv_scale = 1.f; 6243bfa90b6Smrg priv->y_offset = 0.f; 6253bfa90b6Smrg priv->y_scale = 1.f; 6263bfa90b6Smrg priv->rgb_offset = 0.f; 6273bfa90b6Smrg priv->rgb_scale = 1.f; 6283bfa90b6Smrg priv->sinhue = 0.f; 6293bfa90b6Smrg priv->coshue = 1.f; 6303bfa90b6Smrg 6313bfa90b6Smrg vmwgfx_update_conversion_matrix(priv); 6323bfa90b6Smrg 6333bfa90b6Smrg return priv; 6343bfa90b6Smrg} 6353bfa90b6Smrg 6363bfa90b6Smrgstatic void 6373bfa90b6Smrgvmwgfx_free_textured_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports) 6383bfa90b6Smrg{ 6393bfa90b6Smrg if (free_ports) { 6403bfa90b6Smrg int i; 6413bfa90b6Smrg 6423bfa90b6Smrg for(i=0; i<adaptor->nPorts; ++i) { 6433bfa90b6Smrg free(adaptor->pPortPrivates[i].ptr); 6443bfa90b6Smrg } 6453bfa90b6Smrg } 6463bfa90b6Smrg 6473bfa90b6Smrg free(adaptor->pAttributes); 6483bfa90b6Smrg free(adaptor->pPortPrivates); 6493bfa90b6Smrg xf86XVFreeVideoAdaptorRec(adaptor); 6503bfa90b6Smrg} 6513bfa90b6Smrg 6523bfa90b6Smrgstatic XF86VideoAdaptorPtr 6533bfa90b6Smrgxorg_setup_textured_adapter(ScreenPtr pScreen) 6543bfa90b6Smrg{ 6553bfa90b6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 6563bfa90b6Smrg modesettingPtr ms = modesettingPTR(pScrn); 6573bfa90b6Smrg XF86VideoAdaptorPtr adapt; 6583bfa90b6Smrg XF86AttributePtr attrs; 6593bfa90b6Smrg DevUnion *dev_unions; 6603bfa90b6Smrg int nports = 16, i; 6613bfa90b6Smrg int nattributes; 6623bfa90b6Smrg struct xa_context *xar; 6633bfa90b6Smrg 6643bfa90b6Smrg /* 6653bfa90b6Smrg * Use the XA default context since we don't expect the X server 6663bfa90b6Smrg * to render from multiple threads. 6673bfa90b6Smrg */ 6683bfa90b6Smrg 6693bfa90b6Smrg xar = xa_context_default(ms->xat); 6703bfa90b6Smrg nattributes = NUM_TEXTURED_ATTRIBUTES; 6713bfa90b6Smrg 6723bfa90b6Smrg adapt = calloc(1, sizeof(XF86VideoAdaptorRec)); 6733bfa90b6Smrg dev_unions = calloc(nports, sizeof(DevUnion)); 6743bfa90b6Smrg attrs = calloc(nattributes, sizeof(XF86AttributeRec)); 6753bfa90b6Smrg if (adapt == NULL || dev_unions == NULL || attrs == NULL) { 6763bfa90b6Smrg free(adapt); 6773bfa90b6Smrg free(dev_unions); 6783bfa90b6Smrg free(attrs); 6793bfa90b6Smrg return NULL; 6803bfa90b6Smrg } 6813bfa90b6Smrg 6823bfa90b6Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 6833bfa90b6Smrg adapt->flags = 0; 6843bfa90b6Smrg adapt->name = "XA G3D Textured Video"; 6853bfa90b6Smrg adapt->nEncodings = 1; 6863bfa90b6Smrg adapt->pEncodings = DummyEncoding; 6873bfa90b6Smrg adapt->nFormats = NUM_FORMATS; 6883bfa90b6Smrg adapt->pFormats = Formats; 6893bfa90b6Smrg adapt->nPorts = 0; 6903bfa90b6Smrg adapt->pPortPrivates = dev_unions; 6913bfa90b6Smrg adapt->nAttributes = nattributes; 6923bfa90b6Smrg adapt->pAttributes = attrs; 6933bfa90b6Smrg memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec)); 6943bfa90b6Smrg adapt->nImages = NUM_IMAGES; 6953bfa90b6Smrg adapt->pImages = Images; 6963bfa90b6Smrg adapt->PutVideo = NULL; 6973bfa90b6Smrg adapt->PutStill = NULL; 6983bfa90b6Smrg adapt->GetVideo = NULL; 6993bfa90b6Smrg adapt->GetStill = NULL; 7003bfa90b6Smrg adapt->StopVideo = stop_video; 7013bfa90b6Smrg adapt->SetPortAttribute = set_port_attribute; 7023bfa90b6Smrg adapt->GetPortAttribute = get_port_attribute; 7033bfa90b6Smrg adapt->QueryBestSize = query_best_size; 7043bfa90b6Smrg adapt->PutImage = put_image; 7053bfa90b6Smrg adapt->QueryImageAttributes = query_image_attributes; 7063bfa90b6Smrg 7073bfa90b6Smrg 7083bfa90b6Smrg for (i = 0; i < nports; i++) { 7093bfa90b6Smrg struct xorg_xv_port_priv *priv = 7103bfa90b6Smrg port_priv_create(ms->xat, xar, ms->fd); 7113bfa90b6Smrg 7123bfa90b6Smrg adapt->pPortPrivates[i].ptr = (pointer) (priv); 7133bfa90b6Smrg adapt->nPorts++; 7143bfa90b6Smrg } 7153bfa90b6Smrg 7163bfa90b6Smrg return adapt; 7173bfa90b6Smrg} 7183bfa90b6Smrg 7193bfa90b6Smrgvoid 7203bfa90b6Smrgxorg_xv_init(ScreenPtr pScreen) 7213bfa90b6Smrg{ 7223bfa90b6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 7233bfa90b6Smrg modesettingPtr ms = modesettingPTR(pScrn); 7243bfa90b6Smrg XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL; 7253bfa90b6Smrg XF86VideoAdaptorPtr textured_adapter = NULL, overlay_adaptor = NULL; 7263bfa90b6Smrg int num_adaptors; 7273bfa90b6Smrg 7283bfa90b6Smrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 7293bfa90b6Smrg new_adaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); 7303bfa90b6Smrg if (new_adaptors == NULL) 7313bfa90b6Smrg return; 7323bfa90b6Smrg 7333bfa90b6Smrg memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); 7343bfa90b6Smrg adaptors = new_adaptors; 7353bfa90b6Smrg 7363bfa90b6Smrg /* Add the adaptors supported by our hardware. First, set up the atoms 7373bfa90b6Smrg * that will be used by both output adaptors. 7383bfa90b6Smrg */ 7393bfa90b6Smrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 7403bfa90b6Smrg xvContrast = MAKE_ATOM("XV_CONTRAST"); 7413bfa90b6Smrg xvSaturation = MAKE_ATOM("XV_SATURATION"); 7423bfa90b6Smrg xvHue = MAKE_ATOM("XV_HUE"); 7433bfa90b6Smrg 7443bfa90b6Smrg if (ms->xat) { 7453bfa90b6Smrg textured_adapter = xorg_setup_textured_adapter(pScreen); 7463bfa90b6Smrg if (textured_adapter) 7473bfa90b6Smrg adaptors[num_adaptors++] = textured_adapter; 7483bfa90b6Smrg } else { 7493bfa90b6Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7503bfa90b6Smrg "No 3D acceleration. Not setting up textured video.\n"); 7513bfa90b6Smrg } 7523bfa90b6Smrg 7533bfa90b6Smrg overlay_adaptor = vmw_video_init_adaptor(pScrn); 7543bfa90b6Smrg if (overlay_adaptor) 7553bfa90b6Smrg adaptors[num_adaptors++] = overlay_adaptor; 7563bfa90b6Smrg 7573bfa90b6Smrg if (num_adaptors) { 7583bfa90b6Smrg Bool ret; 7593bfa90b6Smrg ret = xf86XVScreenInit(pScreen, adaptors, num_adaptors); 7603bfa90b6Smrg if (textured_adapter) 7613bfa90b6Smrg vmwgfx_free_textured_adaptor(textured_adapter, !ret); 7623bfa90b6Smrg if (overlay_adaptor) 7633bfa90b6Smrg vmw_video_free_adaptor(overlay_adaptor, !ret); 7643bfa90b6Smrg if (!ret) 7653bfa90b6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 7663bfa90b6Smrg "Failed to initialize Xv.\n"); 7673bfa90b6Smrg } else { 7683bfa90b6Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 7693bfa90b6Smrg "Disabling Xv because no adaptors could be initialized.\n"); 7703bfa90b6Smrg } 7713bfa90b6Smrg} 772