vmwgfx_tex_video.c revision 34a0776d
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 */ 2834a0776dSmrg#ifdef HAVE_CONFIG_H 2934a0776dSmrg#include "config.h" 3034a0776dSmrg#endif 313bfa90b6Smrg 323bfa90b6Smrg#include "vmwgfx_driver.h" 333bfa90b6Smrg#include "vmwgfx_drmi.h" 343bfa90b6Smrg#include "vmwgfx_saa.h" 353bfa90b6Smrg 363bfa90b6Smrg#include <xf86xv.h> 373bfa90b6Smrg#include <X11/extensions/Xv.h> 383bfa90b6Smrg#include <fourcc.h> 393bfa90b6Smrg#include <xa_tracker.h> 403bfa90b6Smrg#include <xa_context.h> 413bfa90b6Smrg#include <math.h> 423bfa90b6Smrg 433bfa90b6Smrg/*XXX get these from pipe's texture limits */ 443bfa90b6Smrg#define IMAGE_MAX_WIDTH 2048 453bfa90b6Smrg#define IMAGE_MAX_HEIGHT 2048 463bfa90b6Smrg 473bfa90b6Smrg#define RES_720P_X 1280 483bfa90b6Smrg#define RES_720P_Y 720 493bfa90b6Smrg 503bfa90b6Smrg 513bfa90b6Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 523bfa90b6Smrg 533bfa90b6Smrg/* 543bfa90b6Smrg * ITU-R BT.601, BT.709 transfer matrices. 553bfa90b6Smrg * [R', G', B'] values are in the range [0, 1], Y' is in the range [0,1] 563bfa90b6Smrg * and [Pb, Pr] components are in the range [-0.5, 0.5]. 573bfa90b6Smrg * 583bfa90b6Smrg * The matrices are transposed to fit the xa conversion matrix format. 593bfa90b6Smrg */ 603bfa90b6Smrg 613bfa90b6Smrgstatic const float bt_601[] = { 623bfa90b6Smrg 1.f, 1.f, 1.f, 0.f, 633bfa90b6Smrg 0.f, -0.344136f, 1.772f, 0.f, 643bfa90b6Smrg 1.402f, -0.714136f, 0.f, 0.f 653bfa90b6Smrg}; 663bfa90b6Smrg 673bfa90b6Smrgstatic const float bt_709[] = { 683bfa90b6Smrg 1.f, 1.f, 1.f, 0.f, 693bfa90b6Smrg 0.f, -0.187324f, 1.8556f, 0.f, 703bfa90b6Smrg 1.5748f, -0.468124f, 0.f, 0.f 713bfa90b6Smrg}; 723bfa90b6Smrg 733bfa90b6Smrgstatic Atom xvBrightness, xvContrast, xvSaturation, xvHue; 743bfa90b6Smrg 753bfa90b6Smrg#define NUM_TEXTURED_ATTRIBUTES 4 7622f7e8e5Smrgstatic const XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = { 7722f7e8e5Smrg {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 7822f7e8e5Smrg {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 7922f7e8e5Smrg {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 8022f7e8e5Smrg {XvSettable | XvGettable, -1000, 1000, "XV_HUE"} 813bfa90b6Smrg}; 823bfa90b6Smrg 833bfa90b6Smrg#define NUM_FORMATS 3 843bfa90b6Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = { 853bfa90b6Smrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 863bfa90b6Smrg}; 873bfa90b6Smrg 883bfa90b6Smrgstatic XF86VideoEncodingRec DummyEncoding[1] = { 893bfa90b6Smrg { 903bfa90b6Smrg 0, 913bfa90b6Smrg "XV_IMAGE", 923bfa90b6Smrg IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 933bfa90b6Smrg {1, 1} 943bfa90b6Smrg } 953bfa90b6Smrg}; 963bfa90b6Smrg 973bfa90b6Smrg#define NUM_IMAGES 3 983bfa90b6Smrgstatic XF86ImageRec Images[NUM_IMAGES] = { 993bfa90b6Smrg XVIMAGE_UYVY, 1003bfa90b6Smrg XVIMAGE_YUY2, 1013bfa90b6Smrg XVIMAGE_YV12, 1023bfa90b6Smrg}; 1033bfa90b6Smrg 1043bfa90b6Smrgstruct xorg_xv_port_priv { 1053bfa90b6Smrg struct xa_tracker *xat; 1063bfa90b6Smrg struct xa_context *r; 1073bfa90b6Smrg struct xa_fence *fence; 1083bfa90b6Smrg 1093bfa90b6Smrg RegionRec clip; 1103bfa90b6Smrg 1113bfa90b6Smrg int brightness; 1123bfa90b6Smrg int contrast; 1133bfa90b6Smrg int saturation; 1143bfa90b6Smrg int hue; 1153bfa90b6Smrg 1163bfa90b6Smrg int current_set; 11722f7e8e5Smrg struct xa_surface *yuv[2][3]; 1183bfa90b6Smrg 11934a0776dSmrg struct xa_surface *bounce; 12034a0776dSmrg struct xa_box bounce_box; 12134a0776dSmrg struct xa_picture *src_pic; 12234a0776dSmrg struct xa_picture *dst_pic; 12334a0776dSmrg struct xa_composite *comp; 12434a0776dSmrg 1253bfa90b6Smrg int drm_fd; 1263bfa90b6Smrg 1273bfa90b6Smrg Bool hdtv; 1283bfa90b6Smrg float uv_offset; 1293bfa90b6Smrg float uv_scale; 1303bfa90b6Smrg float y_offset; 1313bfa90b6Smrg float y_scale; 1323bfa90b6Smrg float rgb_offset; 1333bfa90b6Smrg float rgb_scale; 1343bfa90b6Smrg float sinhue; 1353bfa90b6Smrg float coshue; 1363bfa90b6Smrg float cm[16]; 1373bfa90b6Smrg}; 1383bfa90b6Smrg 1393bfa90b6Smrg/* 1403bfa90b6Smrg * vmwgfx_update_conversion_matrix - Compute the effective color conversion 1413bfa90b6Smrg * matrix. 1423bfa90b6Smrg * 1433bfa90b6Smrg * Applies yuv- and resulting rgb scales and offsets to compute the correct 1443bfa90b6Smrg * color conversion matrix. These scales and offsets are properties of the 1453bfa90b6Smrg * video stream and can be adjusted using XV properties as well. 1463bfa90b6Smrg */ 1473bfa90b6Smrgstatic void 1483bfa90b6Smrgvmwgfx_update_conversion_matrix(struct xorg_xv_port_priv *priv) 1493bfa90b6Smrg{ 1503bfa90b6Smrg int i; 1513bfa90b6Smrg float *cm = priv->cm; 1523bfa90b6Smrg static const float *bt; 1533bfa90b6Smrg 1543bfa90b6Smrg bt = (priv->hdtv) ? bt_709 : bt_601; 1553bfa90b6Smrg 1563bfa90b6Smrg memcpy(cm, bt, sizeof(bt_601)); 1573bfa90b6Smrg 1583bfa90b6Smrg /* 1593bfa90b6Smrg * Apply hue rotation 1603bfa90b6Smrg */ 1613bfa90b6Smrg cm[4] = priv->coshue * bt[4] - priv->sinhue * bt[8]; 1623bfa90b6Smrg cm[8] = priv->sinhue * bt[4] + priv->coshue * bt[8]; 1633bfa90b6Smrg cm[5] = priv->coshue * bt[5] - priv->sinhue * bt[9]; 1643bfa90b6Smrg cm[9] = priv->sinhue * bt[5] + priv->coshue * bt[9]; 1653bfa90b6Smrg cm[6] = priv->coshue * bt[6] - priv->sinhue * bt[10]; 1663bfa90b6Smrg cm[10] = priv->sinhue * bt[6] + priv->coshue * bt[10]; 1673bfa90b6Smrg 1683bfa90b6Smrg /* 1693bfa90b6Smrg * Adjust for yuv scales in input and rgb scale in the converted output. 1703bfa90b6Smrg */ 1713bfa90b6Smrg for(i = 0; i < 3; ++i) { 1723bfa90b6Smrg cm[i] *= (priv->y_scale*priv->rgb_scale); 1733bfa90b6Smrg cm[i+4] *= (priv->uv_scale*priv->rgb_scale); 1743bfa90b6Smrg cm[i+8] *= (priv->uv_scale*priv->rgb_scale); 1753bfa90b6Smrg } 1763bfa90b6Smrg 1773bfa90b6Smrg /* 1783bfa90b6Smrg * Adjust for yuv offsets in input and rgb offset in the converted output. 1793bfa90b6Smrg */ 1803bfa90b6Smrg for (i = 0; i < 3; ++i) 1813bfa90b6Smrg cm[i+12] = -cm[i]*priv->y_offset - (cm[i+4] + cm[i+8])*priv->uv_offset 1823bfa90b6Smrg - priv->rgb_offset*priv->rgb_scale; 1833bfa90b6Smrg 1843bfa90b6Smrg /* 1853bfa90b6Smrg * Alpha is 1, unconditionally. 1863bfa90b6Smrg */ 1873bfa90b6Smrg cm[15] = 1.f; 1883bfa90b6Smrg} 1893bfa90b6Smrg 19034a0776dSmrg/** 19134a0776dSmrg * vmwgfx_video_free_comp - free members used for composite bounce blit 19234a0776dSmrg * 19334a0776dSmrg * @priv: Pointer to the port private 19434a0776dSmrg * 19534a0776dSmrg * Frees any port priv resources allocated for a composite bounce blit. 19634a0776dSmrg */ 19734a0776dSmrgstatic void 19834a0776dSmrgvmwgfx_video_free_comp(struct xorg_xv_port_priv *priv) 19934a0776dSmrg{ 20034a0776dSmrg if (priv->dst_pic) 20134a0776dSmrg free(priv->dst_pic); 20234a0776dSmrg if (priv->src_pic) 20334a0776dSmrg free(priv->src_pic); 20434a0776dSmrg if (priv->comp) 20534a0776dSmrg free(priv->comp); 20634a0776dSmrg 20734a0776dSmrg priv->dst_pic = NULL; 20834a0776dSmrg priv->src_pic = NULL; 20934a0776dSmrg priv->comp = NULL; 21034a0776dSmrg} 2113bfa90b6Smrg 2123bfa90b6Smrgstatic void 2133bfa90b6Smrgstop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 2143bfa90b6Smrg{ 2153bfa90b6Smrg struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 2163bfa90b6Smrg int i, j; 2173bfa90b6Smrg 2183bfa90b6Smrg REGION_EMPTY(pScrn->pScreen, &priv->clip); 2193bfa90b6Smrg if (shutdown) { 2203bfa90b6Smrg 2213bfa90b6Smrg /* 2223bfa90b6Smrg * No need to destroy the xa context or xa tracker since 2233bfa90b6Smrg * they are copied from the screen resources. 2243bfa90b6Smrg */ 2253bfa90b6Smrg 2263bfa90b6Smrg xa_fence_destroy(priv->fence); 2273bfa90b6Smrg priv->fence = NULL; 22834a0776dSmrg vmwgfx_video_free_comp(priv); 2293bfa90b6Smrg 2303bfa90b6Smrg for (i=0; i<3; ++i) { 2313bfa90b6Smrg for (j=0; j<2; ++j) { 23222f7e8e5Smrg if (priv->yuv[i]) { 23322f7e8e5Smrg xa_surface_destroy(priv->yuv[j][i]); 23422f7e8e5Smrg priv->yuv[j][i] = NULL; 2353bfa90b6Smrg } 23634a0776dSmrg if (priv->bounce) { 23734a0776dSmrg xa_surface_destroy(priv->bounce); 23834a0776dSmrg priv->bounce = NULL; 23934a0776dSmrg } 2403bfa90b6Smrg } 2413bfa90b6Smrg } 2423bfa90b6Smrg } 2433bfa90b6Smrg} 2443bfa90b6Smrg 2453bfa90b6Smrgstatic int 2463bfa90b6Smrgset_port_attribute(ScrnInfoPtr pScrn, 2473bfa90b6Smrg Atom attribute, INT32 value, pointer data) 2483bfa90b6Smrg{ 2493bfa90b6Smrg struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 2503bfa90b6Smrg 2513bfa90b6Smrg if (attribute == xvBrightness) { 2523bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2533bfa90b6Smrg return BadValue; 2543bfa90b6Smrg 2553bfa90b6Smrg priv->brightness = value; 2563bfa90b6Smrg priv->y_offset = -((float) value)/1000.f; 2573bfa90b6Smrg 2583bfa90b6Smrg } else if (attribute == xvContrast) { 2593bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2603bfa90b6Smrg return BadValue; 2613bfa90b6Smrg 2623bfa90b6Smrg priv->contrast = value; 2633bfa90b6Smrg priv->rgb_scale = ((float) value + 1000.f)/1000.f; 2643bfa90b6Smrg 2653bfa90b6Smrg } else if (attribute == xvSaturation) { 2663bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2673bfa90b6Smrg return BadValue; 2683bfa90b6Smrg 2693bfa90b6Smrg priv->saturation = value; 2703bfa90b6Smrg priv->uv_scale = ((float) value + 1000.f)/1000.f; 2713bfa90b6Smrg 2723bfa90b6Smrg } else if (attribute == xvHue) { 2733bfa90b6Smrg double hue_angle; 2743bfa90b6Smrg 2753bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2763bfa90b6Smrg return BadValue; 2773bfa90b6Smrg 2783bfa90b6Smrg priv->hue = value; 2793bfa90b6Smrg hue_angle = (double) value * M_PI / 1000.; 2803bfa90b6Smrg priv->sinhue = sin(hue_angle); 2813bfa90b6Smrg priv->coshue = cos(hue_angle); 2823bfa90b6Smrg 2833bfa90b6Smrg } else 2843bfa90b6Smrg return BadMatch; 2853bfa90b6Smrg 2863bfa90b6Smrg vmwgfx_update_conversion_matrix(priv); 2873bfa90b6Smrg return Success; 2883bfa90b6Smrg} 2893bfa90b6Smrg 2903bfa90b6Smrgstatic int 2913bfa90b6Smrgget_port_attribute(ScrnInfoPtr pScrn, 2923bfa90b6Smrg Atom attribute, INT32 * value, pointer data) 2933bfa90b6Smrg{ 2943bfa90b6Smrg struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 2953bfa90b6Smrg 2963bfa90b6Smrg if (attribute == xvBrightness) 2973bfa90b6Smrg *value = priv->brightness; 2983bfa90b6Smrg else if (attribute == xvContrast) 2993bfa90b6Smrg *value = priv->contrast; 3003bfa90b6Smrg else if (attribute == xvSaturation) 3013bfa90b6Smrg *value = priv->saturation; 3023bfa90b6Smrg else if (attribute == xvHue) 3033bfa90b6Smrg *value = priv->hue; 3043bfa90b6Smrg else 3053bfa90b6Smrg return BadMatch; 3063bfa90b6Smrg 3073bfa90b6Smrg return Success; 3083bfa90b6Smrg} 3093bfa90b6Smrg 3103bfa90b6Smrgstatic void 3113bfa90b6Smrgquery_best_size(ScrnInfoPtr pScrn, 3123bfa90b6Smrg Bool motion, 3133bfa90b6Smrg short vid_w, short vid_h, 3143bfa90b6Smrg short drw_w, short drw_h, 3153bfa90b6Smrg unsigned int *p_w, unsigned int *p_h, pointer data) 3163bfa90b6Smrg{ 3173bfa90b6Smrg if (vid_w > (drw_w << 1)) 3183bfa90b6Smrg drw_w = vid_w >> 1; 3193bfa90b6Smrg if (vid_h > (drw_h << 1)) 3203bfa90b6Smrg drw_h = vid_h >> 1; 3213bfa90b6Smrg 3223bfa90b6Smrg *p_w = drw_w; 3233bfa90b6Smrg *p_h = drw_h; 3243bfa90b6Smrg} 3253bfa90b6Smrg 3263bfa90b6Smrgstatic int 3273bfa90b6Smrgcheck_yuv_surfaces(struct xorg_xv_port_priv *priv, int id, 3283bfa90b6Smrg int width, int height) 3293bfa90b6Smrg{ 33022f7e8e5Smrg struct xa_surface **yuv = priv->yuv[priv->current_set]; 3313bfa90b6Smrg int ret = 0; 3323bfa90b6Smrg int i; 3333bfa90b6Smrg 3343bfa90b6Smrg for (i=0; i<3; ++i) { 3353bfa90b6Smrg 3363bfa90b6Smrg /* 3373bfa90b6Smrg * Adjust u,v texture size and DMA buffer to what's required by 3383bfa90b6Smrg * the format. 3393bfa90b6Smrg */ 3403bfa90b6Smrg if (i == 1) { 3413bfa90b6Smrg switch(id) { 3423bfa90b6Smrg case FOURCC_YV12: 3433bfa90b6Smrg height /= 2; 3443bfa90b6Smrg /* Fall through */ 3453bfa90b6Smrg case FOURCC_YUY2: 3463bfa90b6Smrg case FOURCC_UYVY: 3473bfa90b6Smrg width /= 2; 3483bfa90b6Smrg break; 3493bfa90b6Smrg default: 3503bfa90b6Smrg break; 3513bfa90b6Smrg } 3523bfa90b6Smrg } 3533bfa90b6Smrg 3543bfa90b6Smrg if (!yuv[i]) 3553bfa90b6Smrg yuv[i] = xa_surface_create(priv->xat, width, height, 8, 3563bfa90b6Smrg xa_type_yuv_component, 3573bfa90b6Smrg xa_format_unknown, 0); 3583bfa90b6Smrg else 3593bfa90b6Smrg ret = xa_surface_redefine(yuv[i], width, height, 8, 3603bfa90b6Smrg xa_type_yuv_component, 3613bfa90b6Smrg xa_format_unknown, 0, 0); 3623bfa90b6Smrg if (ret || !yuv[i]) 3633bfa90b6Smrg return BadAlloc; 3643bfa90b6Smrg 3653bfa90b6Smrg } 3663bfa90b6Smrg return Success; 3673bfa90b6Smrg} 3683bfa90b6Smrg 36934a0776dSmrg 37034a0776dSmrg/** 37134a0776dSmrg * vmwgfx_video_setup_comp - Set up port priv members for a composite 37234a0776dSmrg * bounce blit 37334a0776dSmrg * 37434a0776dSmrg * @priv: Pointer to the port priv. 37534a0776dSmrg * @format: XA format of the destination drawable surface. 37634a0776dSmrg * 37734a0776dSmrg * Tries to allocate and set up port priv resources to perform a composite 37834a0776dSmrg * bounce blit (except the bounce surface itself). On failure, all resources 37934a0776dSmrg * are freed. On success, TRUE is returned and @priv::comp is non-NULL. If 38034a0776dSmrg * resources are already allocated, update them for the current @format. 38134a0776dSmrg */ 38234a0776dSmrgstatic Bool 38334a0776dSmrgvmwgfx_video_setup_comp(struct xorg_xv_port_priv *priv, enum xa_formats format) 38434a0776dSmrg{ 38534a0776dSmrg const struct xa_composite_allocation *alloc; 38634a0776dSmrg struct xa_picture *pic; 38734a0776dSmrg 38834a0776dSmrg if (priv->comp) { 38934a0776dSmrg if (priv->src_pic->pict_format != format) { 39034a0776dSmrg priv->src_pic->pict_format = format; 39134a0776dSmrg priv->dst_pic->pict_format = format; 39234a0776dSmrg if (xa_composite_check_accelerated(priv->comp) != XA_ERR_NONE) { 39334a0776dSmrg vmwgfx_video_free_comp(priv); 39434a0776dSmrg return FALSE; 39534a0776dSmrg } 39634a0776dSmrg } 39734a0776dSmrg return TRUE; 39834a0776dSmrg } 39934a0776dSmrg 40034a0776dSmrg alloc = xa_composite_allocation(); 40134a0776dSmrg priv->comp = calloc(1, alloc->xa_composite_size); 40234a0776dSmrg priv->src_pic = calloc(1, alloc->xa_picture_size); 40334a0776dSmrg priv->dst_pic = calloc(1, alloc->xa_picture_size); 40434a0776dSmrg 40534a0776dSmrg if (!priv->comp || !priv->src_pic || !priv->dst_pic) { 40634a0776dSmrg vmwgfx_video_free_comp(priv); 40734a0776dSmrg return FALSE; 40834a0776dSmrg } 40934a0776dSmrg 41034a0776dSmrg pic = priv->src_pic; 41134a0776dSmrg pic->pict_format = format; 41234a0776dSmrg pic->wrap = xa_wrap_clamp_to_border; 41334a0776dSmrg pic->filter = xa_filter_linear; 41434a0776dSmrg 41534a0776dSmrg *priv->dst_pic = *pic; 41634a0776dSmrg 41734a0776dSmrg priv->comp->src = priv->src_pic; 41834a0776dSmrg priv->comp->dst = priv->dst_pic; 41934a0776dSmrg priv->comp->op = xa_op_src; 42034a0776dSmrg priv->comp->no_solid = 1; 42134a0776dSmrg 42234a0776dSmrg if (xa_composite_check_accelerated(priv->comp) != XA_ERR_NONE) { 42334a0776dSmrg vmwgfx_video_free_comp(priv); 42434a0776dSmrg return FALSE; 42534a0776dSmrg } 42634a0776dSmrg 42734a0776dSmrg return TRUE; 42834a0776dSmrg} 42934a0776dSmrg 43034a0776dSmrg/** 43134a0776dSmrg * vmwgfx_video_setup_coord_matrix - Set up a bounce - to destination 43234a0776dSmrg * transformation matrix 43334a0776dSmrg * 43434a0776dSmrg * @src_x: Upper left corner of source image as given to putImage. 43534a0776dSmrg * @src_y: Upper left corner of source image as given to putImage. 43634a0776dSmrg * @src_w: Width of source image. 43734a0776dSmrg * @src_h: Height of source image. 43834a0776dSmrg * @dst_x: Upper left corner of destination image as given to putImage. 43934a0776dSmrg * @dst_y: Upper left corner of destination image as given to putImage. 44034a0776dSmrg * @dst_w: Width of destination image. 44134a0776dSmrg * @dst_h: Height of destination image. 44234a0776dSmrg * @bounce_w: Width of bounce surface. 44334a0776dSmrg * @bounce_h: Height of bounce surface. 44434a0776dSmrg * @mat: Pointer to transformation matrix. 44534a0776dSmrg * 44634a0776dSmrg * Computes a transformation matrix that can be used by the XA composite API 44734a0776dSmrg * to transform between the destination coordinate space and the bounce 44834a0776dSmrg * surface coordinate space. Scaling and translation. 44934a0776dSmrg */ 45034a0776dSmrgstatic void 45134a0776dSmrgvmwgfx_video_setup_coord_matrix(int src_x, int src_y, int src_w, int src_h, 45234a0776dSmrg int dst_x, int dst_y, int dst_w, int dst_h, 45334a0776dSmrg int bounce_w, int bounce_h, 45434a0776dSmrg float *mat) 45534a0776dSmrg{ 45634a0776dSmrg if (dst_w == 0 || dst_h == 0 || src_w == 0 || src_h == 0) { 45734a0776dSmrg mat[0] = mat[6] = 0.; 45834a0776dSmrg mat[4] = mat[7] = 0.; 45934a0776dSmrg mat[8] = 1.f; 46034a0776dSmrg return; 46134a0776dSmrg } 46234a0776dSmrg 46334a0776dSmrg mat[0] = (float) bounce_w / (float) dst_w; 46434a0776dSmrg mat[6] = (float) src_x * (float) bounce_w / (float) src_w - 46534a0776dSmrg (float) dst_x * mat[0]; 46634a0776dSmrg mat[4] = (float) bounce_h / (float) dst_h; 46734a0776dSmrg mat[7] = (float) src_y * (float) bounce_h / (float) src_h - 46834a0776dSmrg (float) dst_y * mat[4]; 46934a0776dSmrg mat[8] = 1.f; 47034a0776dSmrg} 47134a0776dSmrg 47234a0776dSmrg/** 47334a0776dSmrg * vmwgfx_video_bounce_surface: (Re)Allocate a bounce surface if desired. 47434a0776dSmrg * 47534a0776dSmrg * @priv: Pointer to the port private. 47634a0776dSmrg * @d_with: Width of destination image. 47734a0776dSmrg * @d_height: Height of destination image. 47834a0776dSmrg * @width: Width of source video image. 47934a0776dSmrg * @height: Height of source video image. 48034a0776dSmrg * @dst_format: Format of destination drawable surface. 48134a0776dSmrg * 48234a0776dSmrg * If the destination video image is a suitable factor larger than the source 48334a0776dSmrg * video image. Allocate a bounce RGB surface that will be the target of the 48434a0776dSmrg * more expensive color conversion blit, and source of the scaling blit. 48534a0776dSmrg */ 48634a0776dSmrgstatic Bool 48734a0776dSmrgvmwgfx_video_bounce_surface(struct xorg_xv_port_priv *priv, 48834a0776dSmrg int d_width, int d_height, 48934a0776dSmrg int width, int height, 49034a0776dSmrg enum xa_formats dst_format) 49134a0776dSmrg{ 49234a0776dSmrg float bounce_area, dst_area; 49334a0776dSmrg 49434a0776dSmrg if (d_width < width) 49534a0776dSmrg width = d_width; 49634a0776dSmrg 49734a0776dSmrg if (d_height < height) 49834a0776dSmrg height = d_height; 49934a0776dSmrg 50034a0776dSmrg bounce_area = (float) width * (float) height; 50134a0776dSmrg dst_area = (float) d_width * (float) d_height; 50234a0776dSmrg 50334a0776dSmrg if (dst_area > bounce_area * 1.5f && 50434a0776dSmrg vmwgfx_video_setup_comp(priv, dst_format)) { 50534a0776dSmrg 50634a0776dSmrg if (!priv->bounce) { 50734a0776dSmrg priv->bounce = xa_surface_create(priv->xat, width, height, 50834a0776dSmrg xa_format_depth(dst_format), 50934a0776dSmrg xa_format_type(dst_format), 51034a0776dSmrg dst_format, XA_FLAG_RENDER_TARGET); 51134a0776dSmrg } else { 51234a0776dSmrg if (xa_surface_redefine(priv->bounce, width, height, 51334a0776dSmrg xa_format_depth(dst_format), 51434a0776dSmrg xa_format_type(dst_format), 51534a0776dSmrg dst_format, 51634a0776dSmrg XA_FLAG_RENDER_TARGET, 0) != XA_ERR_NONE) { 51734a0776dSmrg xa_surface_destroy(priv->bounce); 51834a0776dSmrg priv->bounce = NULL; 51934a0776dSmrg } 52034a0776dSmrg } 52134a0776dSmrg 52234a0776dSmrg } else { 52334a0776dSmrg xa_surface_destroy(priv->bounce); 52434a0776dSmrg priv->bounce = NULL; 52534a0776dSmrg } 52634a0776dSmrg 52734a0776dSmrg if (priv->bounce) { 52834a0776dSmrg priv->bounce_box.x1 = 0; 52934a0776dSmrg priv->bounce_box.x2 = width; 53034a0776dSmrg priv->bounce_box.y1 = 0; 53134a0776dSmrg priv->bounce_box.y2 = height; 53234a0776dSmrg } 53334a0776dSmrg 53434a0776dSmrg return TRUE; 53534a0776dSmrg} 53634a0776dSmrg 5373bfa90b6Smrgstatic int 5383bfa90b6Smrgquery_image_attributes(ScrnInfoPtr pScrn, 5393bfa90b6Smrg int id, 5403bfa90b6Smrg unsigned short *w, unsigned short *h, 5413bfa90b6Smrg int *pitches, int *offsets) 5423bfa90b6Smrg{ 5433bfa90b6Smrg int size, tmp; 5443bfa90b6Smrg 5453bfa90b6Smrg if (*w > IMAGE_MAX_WIDTH) 5463bfa90b6Smrg *w = IMAGE_MAX_WIDTH; 5473bfa90b6Smrg if (*h > IMAGE_MAX_HEIGHT) 5483bfa90b6Smrg *h = IMAGE_MAX_HEIGHT; 5493bfa90b6Smrg 5503bfa90b6Smrg *w = (*w + 1) & ~1; 5513bfa90b6Smrg if (offsets) 5523bfa90b6Smrg offsets[0] = 0; 5533bfa90b6Smrg 5543bfa90b6Smrg switch (id) { 5553bfa90b6Smrg case FOURCC_YV12: 5563bfa90b6Smrg *h = (*h + 1) & ~1; 5573bfa90b6Smrg size = (*w + 3) & ~3; 5583bfa90b6Smrg if (pitches) { 5593bfa90b6Smrg pitches[0] = size; 5603bfa90b6Smrg } 5613bfa90b6Smrg size *= *h; 5623bfa90b6Smrg if (offsets) { 5633bfa90b6Smrg offsets[1] = size; 5643bfa90b6Smrg } 5653bfa90b6Smrg tmp = ((*w >> 1) + 3) & ~3; 5663bfa90b6Smrg if (pitches) { 5673bfa90b6Smrg pitches[1] = pitches[2] = tmp; 5683bfa90b6Smrg } 5693bfa90b6Smrg tmp *= (*h >> 1); 5703bfa90b6Smrg size += tmp; 5713bfa90b6Smrg if (offsets) { 5723bfa90b6Smrg offsets[2] = size; 5733bfa90b6Smrg } 5743bfa90b6Smrg size += tmp; 5753bfa90b6Smrg break; 5763bfa90b6Smrg case FOURCC_UYVY: 5773bfa90b6Smrg case FOURCC_YUY2: 5783bfa90b6Smrg default: 5793bfa90b6Smrg size = *w << 1; 5803bfa90b6Smrg if (pitches) 5813bfa90b6Smrg pitches[0] = size; 5823bfa90b6Smrg size *= *h; 5833bfa90b6Smrg break; 5843bfa90b6Smrg } 5853bfa90b6Smrg 5863bfa90b6Smrg return size; 5873bfa90b6Smrg} 5883bfa90b6Smrg 5893bfa90b6Smrgstatic int 5903bfa90b6Smrgcopy_packed_data(ScrnInfoPtr pScrn, 5913bfa90b6Smrg struct xorg_xv_port_priv *port, 5923bfa90b6Smrg int id, 5933bfa90b6Smrg unsigned char *buf, 5943bfa90b6Smrg int left, 5953bfa90b6Smrg int top, 5963bfa90b6Smrg unsigned short w, unsigned short h) 5973bfa90b6Smrg{ 5983bfa90b6Smrg int i; 59922f7e8e5Smrg struct xa_surface **yuv = port->yuv[port->current_set]; 6003bfa90b6Smrg char *ymap, *vmap, *umap; 6013bfa90b6Smrg unsigned char y1, y2, u, v; 6023bfa90b6Smrg int yidx, uidx, vidx; 6033bfa90b6Smrg int y_array_size = w * h; 6043bfa90b6Smrg int ret = BadAlloc; 6053bfa90b6Smrg 60622f7e8e5Smrg ymap = xa_surface_map(port->r, yuv[0], XA_MAP_WRITE); 6073bfa90b6Smrg if (!ymap) 6083bfa90b6Smrg return BadAlloc; 60922f7e8e5Smrg umap = xa_surface_map(port->r, yuv[1], XA_MAP_WRITE); 6103bfa90b6Smrg if (!umap) 6113bfa90b6Smrg goto out_no_umap; 61222f7e8e5Smrg vmap = xa_surface_map(port->r, yuv[2], XA_MAP_WRITE); 6133bfa90b6Smrg if (!vmap) 6143bfa90b6Smrg goto out_no_vmap; 6153bfa90b6Smrg 6163bfa90b6Smrg 6173bfa90b6Smrg yidx = uidx = vidx = 0; 6183bfa90b6Smrg 6193bfa90b6Smrg switch (id) { 6203bfa90b6Smrg case FOURCC_YV12: { 6213bfa90b6Smrg int pitches[3], offsets[3]; 62222f7e8e5Smrg unsigned char *yp, *up, *vp; 6233bfa90b6Smrg query_image_attributes(pScrn, FOURCC_YV12, 6243bfa90b6Smrg &w, &h, pitches, offsets); 6253bfa90b6Smrg 62622f7e8e5Smrg yp = buf + offsets[0]; 62722f7e8e5Smrg vp = buf + offsets[1]; 62822f7e8e5Smrg up = buf + offsets[2]; 62922f7e8e5Smrg memcpy(ymap, yp, w*h); 63022f7e8e5Smrg memcpy(vmap, vp, w*h/4); 63122f7e8e5Smrg memcpy(umap, up, w*h/4); 6323bfa90b6Smrg break; 6333bfa90b6Smrg } 6343bfa90b6Smrg case FOURCC_UYVY: 6353bfa90b6Smrg for (i = 0; i < y_array_size; i +=2 ) { 6363bfa90b6Smrg /* extracting two pixels */ 6373bfa90b6Smrg u = buf[0]; 6383bfa90b6Smrg y1 = buf[1]; 6393bfa90b6Smrg v = buf[2]; 6403bfa90b6Smrg y2 = buf[3]; 6413bfa90b6Smrg buf += 4; 6423bfa90b6Smrg 6433bfa90b6Smrg ymap[yidx++] = y1; 6443bfa90b6Smrg ymap[yidx++] = y2; 6453bfa90b6Smrg umap[uidx++] = u; 6463bfa90b6Smrg vmap[vidx++] = v; 6473bfa90b6Smrg } 6483bfa90b6Smrg break; 6493bfa90b6Smrg case FOURCC_YUY2: 6503bfa90b6Smrg for (i = 0; i < y_array_size; i +=2 ) { 6513bfa90b6Smrg /* extracting two pixels */ 6523bfa90b6Smrg y1 = buf[0]; 6533bfa90b6Smrg u = buf[1]; 6543bfa90b6Smrg y2 = buf[2]; 6553bfa90b6Smrg v = buf[3]; 6563bfa90b6Smrg 6573bfa90b6Smrg buf += 4; 6583bfa90b6Smrg 6593bfa90b6Smrg ymap[yidx++] = y1; 6603bfa90b6Smrg ymap[yidx++] = y2; 6613bfa90b6Smrg umap[uidx++] = u; 6623bfa90b6Smrg vmap[vidx++] = v; 6633bfa90b6Smrg } 6643bfa90b6Smrg break; 6653bfa90b6Smrg default: 6663bfa90b6Smrg ret = BadAlloc; 6673bfa90b6Smrg break; 6683bfa90b6Smrg } 6693bfa90b6Smrg 6703bfa90b6Smrg ret = Success; 67122f7e8e5Smrg xa_surface_unmap(yuv[2]); 6723bfa90b6Smrg out_no_vmap: 67322f7e8e5Smrg xa_surface_unmap(yuv[1]); 6743bfa90b6Smrg out_no_umap: 67522f7e8e5Smrg xa_surface_unmap(yuv[0]); 6763bfa90b6Smrg 6773bfa90b6Smrg return ret; 6783bfa90b6Smrg} 6793bfa90b6Smrg 6803bfa90b6Smrg 6813bfa90b6Smrgstatic int 6823bfa90b6Smrgdisplay_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, 6833bfa90b6Smrg RegionPtr dstRegion, 6843bfa90b6Smrg int src_x, int src_y, int src_w, int src_h, 6853bfa90b6Smrg int dst_x, int dst_y, int dst_w, int dst_h, 68634a0776dSmrg int width, int height, 6873bfa90b6Smrg PixmapPtr pPixmap) 6883bfa90b6Smrg{ 6893bfa90b6Smrg struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pPixmap); 6903bfa90b6Smrg Bool hdtv; 6913bfa90b6Smrg RegionRec reg; 6923bfa90b6Smrg int ret = BadAlloc; 6933bfa90b6Smrg int blit_ret; 6943bfa90b6Smrg 6953bfa90b6Smrg REGION_NULL(pScreen, ®); 6963bfa90b6Smrg 6973bfa90b6Smrg if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, ®)) 6983bfa90b6Smrg goto out_no_dst; 6993bfa90b6Smrg 7003bfa90b6Smrg hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y)); 7013bfa90b6Smrg if (hdtv != pPriv->hdtv) { 7023bfa90b6Smrg pPriv->hdtv = hdtv; 7033bfa90b6Smrg vmwgfx_update_conversion_matrix(pPriv); 7043bfa90b6Smrg } 7053bfa90b6Smrg 7063bfa90b6Smrg#ifdef COMPOSITE 7073bfa90b6Smrg 7083bfa90b6Smrg /* 7093bfa90b6Smrg * For redirected windows, we need to fix up the destination coordinates. 7103bfa90b6Smrg */ 7113bfa90b6Smrg 7123bfa90b6Smrg REGION_TRANSLATE(pScreen, dstRegion, -pPixmap->screen_x, 7133bfa90b6Smrg -pPixmap->screen_y); 7143bfa90b6Smrg dst_x -= pPixmap->screen_x; 7153bfa90b6Smrg dst_y -= pPixmap->screen_y; 7163bfa90b6Smrg#endif 7173bfa90b6Smrg 7183bfa90b6Smrg /* 7193bfa90b6Smrg * Throttle on previous blit. 7203bfa90b6Smrg */ 7213bfa90b6Smrg 7223bfa90b6Smrg if (pPriv->fence) { 7233bfa90b6Smrg (void) xa_fence_wait(pPriv->fence, 1000000000ULL); 7243bfa90b6Smrg xa_fence_destroy(pPriv->fence); 7253bfa90b6Smrg pPriv->fence = NULL; 7263bfa90b6Smrg } 7273bfa90b6Smrg 72834a0776dSmrg (void) vmwgfx_video_bounce_surface(pPriv, dst_w, dst_h, width, height, 72934a0776dSmrg xa_surface_format(vpix->hw)); 73034a0776dSmrg 7313bfa90b6Smrg DamageRegionAppend(&pPixmap->drawable, dstRegion); 7323bfa90b6Smrg 73334a0776dSmrg if (pPriv->bounce) { 73434a0776dSmrg BoxPtr b; 73534a0776dSmrg int i; 73634a0776dSmrg 73734a0776dSmrg /* 73834a0776dSmrg * If we have a bounce buffer, First perform a (potentially down- 73934a0776dSmrg * scaling) color conversion blit with an expensive shader. 74034a0776dSmrg */ 74134a0776dSmrg blit_ret = xa_yuv_planar_blit(pPriv->r, 0, 0, src_w, src_h, 74234a0776dSmrg src_x, src_y, 74334a0776dSmrg pPriv->bounce_box.x2, 74434a0776dSmrg pPriv->bounce_box.y2, 74534a0776dSmrg &pPriv->bounce_box, 1, 74634a0776dSmrg pPriv->cm, 74734a0776dSmrg pPriv->bounce, 74834a0776dSmrg pPriv->yuv[pPriv->current_set]); 74934a0776dSmrg 75034a0776dSmrg if (blit_ret) 75134a0776dSmrg goto out_blit; 75234a0776dSmrg 75334a0776dSmrg /* 75434a0776dSmrg * Then an upscaling blit with a cheap shader. Note that we never 75534a0776dSmrg * scale up a dimenstion that was previously downscaled in the color 75634a0776dSmrg * conversion blit. 75734a0776dSmrg */ 75834a0776dSmrg pPriv->src_pic->srf = pPriv->bounce; 75934a0776dSmrg pPriv->dst_pic->srf = vpix->hw; 76034a0776dSmrg vmwgfx_video_setup_coord_matrix(src_x, src_y, src_w, src_h, 76134a0776dSmrg dst_x, dst_y, dst_w, dst_h, 76234a0776dSmrg pPriv->bounce_box.x2, 76334a0776dSmrg pPriv->bounce_box.y2, 76434a0776dSmrg pPriv->src_pic->transform); 76534a0776dSmrg pPriv->src_pic->has_transform = 1; 76634a0776dSmrg 76734a0776dSmrg if (xa_composite_prepare(pPriv->r, pPriv->comp) != XA_ERR_NONE) { 76834a0776dSmrg blit_ret = 1; 76934a0776dSmrg goto out_blit; 77034a0776dSmrg } 77134a0776dSmrg 77234a0776dSmrg b = REGION_RECTS(dstRegion); 77334a0776dSmrg for (i = 0; i < REGION_NUM_RECTS(dstRegion); ++i, ++b) { 77434a0776dSmrg xa_composite_rect(pPriv->r, b->x1, b->y1, 0, 0, 77534a0776dSmrg b->x1, b->y1, b->x2 - b->x1, 77634a0776dSmrg b->y2 - b->y1); 77734a0776dSmrg } 77834a0776dSmrg 77934a0776dSmrg xa_composite_done(pPriv->r); 78034a0776dSmrg } else { 78134a0776dSmrg /* 78234a0776dSmrg * Perform color conversion and scaling in the same blit. 78334a0776dSmrg */ 78434a0776dSmrg blit_ret = xa_yuv_planar_blit(pPriv->r, src_x, src_y, src_w, src_h, 78534a0776dSmrg dst_x, dst_y, dst_w, dst_h, 78634a0776dSmrg (struct xa_box *)REGION_RECTS(dstRegion), 78734a0776dSmrg REGION_NUM_RECTS(dstRegion), 78834a0776dSmrg pPriv->cm, 78934a0776dSmrg vpix->hw, 79034a0776dSmrg pPriv->yuv[pPriv->current_set ]); 79134a0776dSmrg } 79234a0776dSmrg 79334a0776dSmrg out_blit: 7943bfa90b6Smrg 7953bfa90b6Smrg saa_pixmap_dirty(pPixmap, TRUE, dstRegion); 7963bfa90b6Smrg DamageRegionProcessPending(&pPixmap->drawable); 7973bfa90b6Smrg ret = Success; 7983bfa90b6Smrg 7993bfa90b6Smrg if (!blit_ret) { 8003bfa90b6Smrg ret = Success; 8013bfa90b6Smrg pPriv->fence = xa_fence_get(pPriv->r); 8023bfa90b6Smrg } else 8033bfa90b6Smrg ret = BadAlloc; 8043bfa90b6Smrg 8053bfa90b6Smrg out_no_dst: 8063bfa90b6Smrg REGION_UNINIT(pScreen, ®); 8073bfa90b6Smrg return ret; 8083bfa90b6Smrg} 8093bfa90b6Smrg 8103bfa90b6Smrgstatic int 8113bfa90b6Smrgput_image(ScrnInfoPtr pScrn, 8123bfa90b6Smrg short src_x, short src_y, 8133bfa90b6Smrg short drw_x, short drw_y, 8143bfa90b6Smrg short src_w, short src_h, 8153bfa90b6Smrg short drw_w, short drw_h, 8163bfa90b6Smrg int id, unsigned char *buf, 8173bfa90b6Smrg short width, short height, 8183bfa90b6Smrg Bool sync, RegionPtr clipBoxes, pointer data, 8193bfa90b6Smrg DrawablePtr pDraw) 8203bfa90b6Smrg{ 8213bfa90b6Smrg struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data; 8223bfa90b6Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 8233bfa90b6Smrg PixmapPtr pPixmap; 8243bfa90b6Smrg INT32 x1, x2, y1, y2; 8253bfa90b6Smrg BoxRec dstBox; 8263bfa90b6Smrg int ret; 8273bfa90b6Smrg 8283bfa90b6Smrg /* Clip */ 8293bfa90b6Smrg x1 = src_x; 8303bfa90b6Smrg x2 = src_x + src_w; 8313bfa90b6Smrg y1 = src_y; 8323bfa90b6Smrg y2 = src_y + src_h; 8333bfa90b6Smrg 8343bfa90b6Smrg dstBox.x1 = drw_x; 8353bfa90b6Smrg dstBox.x2 = drw_x + drw_w; 8363bfa90b6Smrg dstBox.y1 = drw_y; 8373bfa90b6Smrg dstBox.y2 = drw_y + drw_h; 8383bfa90b6Smrg 8393bfa90b6Smrg if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 8403bfa90b6Smrg width, height)) 8413bfa90b6Smrg return Success; 8423bfa90b6Smrg 8433bfa90b6Smrg ret = check_yuv_surfaces(pPriv, id, width, height); 8443bfa90b6Smrg if (ret) 8453bfa90b6Smrg return ret; 8463bfa90b6Smrg 8473bfa90b6Smrg ret = copy_packed_data(pScrn, pPriv, id, buf, 8483bfa90b6Smrg src_x, src_y, width, height); 8493bfa90b6Smrg if (ret) 8503bfa90b6Smrg return ret; 8513bfa90b6Smrg 8523bfa90b6Smrg if (pDraw->type == DRAWABLE_WINDOW) { 8533bfa90b6Smrg pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); 8543bfa90b6Smrg } else { 8553bfa90b6Smrg pPixmap = (PixmapPtr)pDraw; 8563bfa90b6Smrg } 8573bfa90b6Smrg 8583bfa90b6Smrg display_video(pScrn->pScreen, pPriv, id, clipBoxes, 8593bfa90b6Smrg src_x, src_y, src_w, src_h, 8603bfa90b6Smrg drw_x, drw_y, 86134a0776dSmrg drw_w, drw_h, 86234a0776dSmrg width, height, pPixmap); 8633bfa90b6Smrg 8643bfa90b6Smrg pPriv->current_set = (pPriv->current_set + 1) & 1; 8653bfa90b6Smrg return Success; 8663bfa90b6Smrg} 8673bfa90b6Smrg 8683bfa90b6Smrgstatic struct xorg_xv_port_priv * 8693bfa90b6Smrgport_priv_create(struct xa_tracker *xat, struct xa_context *r, 8703bfa90b6Smrg int drm_fd) 8713bfa90b6Smrg{ 8723bfa90b6Smrg struct xorg_xv_port_priv *priv = NULL; 8733bfa90b6Smrg 8743bfa90b6Smrg priv = calloc(1, sizeof(struct xorg_xv_port_priv)); 8753bfa90b6Smrg 8763bfa90b6Smrg if (!priv) 8773bfa90b6Smrg return NULL; 8783bfa90b6Smrg 8793bfa90b6Smrg priv->r = r; 8803bfa90b6Smrg priv->xat = xat; 8813bfa90b6Smrg priv->drm_fd = drm_fd; 8823bfa90b6Smrg REGION_NULL(pScreen, &priv->clip); 8833bfa90b6Smrg priv->hdtv = FALSE; 8843bfa90b6Smrg priv->uv_offset = 0.5f; 8853bfa90b6Smrg priv->uv_scale = 1.f; 8863bfa90b6Smrg priv->y_offset = 0.f; 8873bfa90b6Smrg priv->y_scale = 1.f; 8883bfa90b6Smrg priv->rgb_offset = 0.f; 8893bfa90b6Smrg priv->rgb_scale = 1.f; 8903bfa90b6Smrg priv->sinhue = 0.f; 8913bfa90b6Smrg priv->coshue = 1.f; 8923bfa90b6Smrg 8933bfa90b6Smrg vmwgfx_update_conversion_matrix(priv); 8943bfa90b6Smrg 8953bfa90b6Smrg return priv; 8963bfa90b6Smrg} 8973bfa90b6Smrg 8983bfa90b6Smrgstatic void 8993bfa90b6Smrgvmwgfx_free_textured_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports) 9003bfa90b6Smrg{ 9013bfa90b6Smrg if (free_ports) { 9023bfa90b6Smrg int i; 9033bfa90b6Smrg 9043bfa90b6Smrg for(i=0; i<adaptor->nPorts; ++i) { 9053bfa90b6Smrg free(adaptor->pPortPrivates[i].ptr); 9063bfa90b6Smrg } 9073bfa90b6Smrg } 9083bfa90b6Smrg 9093bfa90b6Smrg free(adaptor->pAttributes); 9103bfa90b6Smrg free(adaptor->pPortPrivates); 9113bfa90b6Smrg xf86XVFreeVideoAdaptorRec(adaptor); 9123bfa90b6Smrg} 9133bfa90b6Smrg 9143bfa90b6Smrgstatic XF86VideoAdaptorPtr 9153bfa90b6Smrgxorg_setup_textured_adapter(ScreenPtr pScreen) 9163bfa90b6Smrg{ 9173bfa90b6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 9183bfa90b6Smrg modesettingPtr ms = modesettingPTR(pScrn); 9193bfa90b6Smrg XF86VideoAdaptorPtr adapt; 9203bfa90b6Smrg XF86AttributePtr attrs; 9213bfa90b6Smrg DevUnion *dev_unions; 9223bfa90b6Smrg int nports = 16, i; 9233bfa90b6Smrg int nattributes; 9243bfa90b6Smrg struct xa_context *xar; 9253bfa90b6Smrg 9263bfa90b6Smrg /* 9273bfa90b6Smrg * Use the XA default context since we don't expect the X server 9283bfa90b6Smrg * to render from multiple threads. 9293bfa90b6Smrg */ 9303bfa90b6Smrg 9313bfa90b6Smrg xar = xa_context_default(ms->xat); 9323bfa90b6Smrg nattributes = NUM_TEXTURED_ATTRIBUTES; 9333bfa90b6Smrg 9343bfa90b6Smrg adapt = calloc(1, sizeof(XF86VideoAdaptorRec)); 9353bfa90b6Smrg dev_unions = calloc(nports, sizeof(DevUnion)); 9363bfa90b6Smrg attrs = calloc(nattributes, sizeof(XF86AttributeRec)); 9373bfa90b6Smrg if (adapt == NULL || dev_unions == NULL || attrs == NULL) { 9383bfa90b6Smrg free(adapt); 9393bfa90b6Smrg free(dev_unions); 9403bfa90b6Smrg free(attrs); 9413bfa90b6Smrg return NULL; 9423bfa90b6Smrg } 9433bfa90b6Smrg 9443bfa90b6Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 9453bfa90b6Smrg adapt->flags = 0; 9463bfa90b6Smrg adapt->name = "XA G3D Textured Video"; 9473bfa90b6Smrg adapt->nEncodings = 1; 9483bfa90b6Smrg adapt->pEncodings = DummyEncoding; 9493bfa90b6Smrg adapt->nFormats = NUM_FORMATS; 9503bfa90b6Smrg adapt->pFormats = Formats; 9513bfa90b6Smrg adapt->nPorts = 0; 9523bfa90b6Smrg adapt->pPortPrivates = dev_unions; 9533bfa90b6Smrg adapt->nAttributes = nattributes; 9543bfa90b6Smrg adapt->pAttributes = attrs; 9553bfa90b6Smrg memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec)); 9563bfa90b6Smrg adapt->nImages = NUM_IMAGES; 9573bfa90b6Smrg adapt->pImages = Images; 9583bfa90b6Smrg adapt->PutVideo = NULL; 9593bfa90b6Smrg adapt->PutStill = NULL; 9603bfa90b6Smrg adapt->GetVideo = NULL; 9613bfa90b6Smrg adapt->GetStill = NULL; 9623bfa90b6Smrg adapt->StopVideo = stop_video; 9633bfa90b6Smrg adapt->SetPortAttribute = set_port_attribute; 9643bfa90b6Smrg adapt->GetPortAttribute = get_port_attribute; 9653bfa90b6Smrg adapt->QueryBestSize = query_best_size; 9663bfa90b6Smrg adapt->PutImage = put_image; 9673bfa90b6Smrg adapt->QueryImageAttributes = query_image_attributes; 9683bfa90b6Smrg 9693bfa90b6Smrg 9703bfa90b6Smrg for (i = 0; i < nports; i++) { 9713bfa90b6Smrg struct xorg_xv_port_priv *priv = 9723bfa90b6Smrg port_priv_create(ms->xat, xar, ms->fd); 9733bfa90b6Smrg 9743bfa90b6Smrg adapt->pPortPrivates[i].ptr = (pointer) (priv); 9753bfa90b6Smrg adapt->nPorts++; 9763bfa90b6Smrg } 9773bfa90b6Smrg 9783bfa90b6Smrg return adapt; 9793bfa90b6Smrg} 9803bfa90b6Smrg 9813bfa90b6Smrgvoid 9823bfa90b6Smrgxorg_xv_init(ScreenPtr pScreen) 9833bfa90b6Smrg{ 9843bfa90b6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 9853bfa90b6Smrg modesettingPtr ms = modesettingPTR(pScrn); 9863bfa90b6Smrg XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL; 9873bfa90b6Smrg XF86VideoAdaptorPtr textured_adapter = NULL, overlay_adaptor = NULL; 9883bfa90b6Smrg int num_adaptors; 9893bfa90b6Smrg 9903bfa90b6Smrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 9913bfa90b6Smrg new_adaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); 9923bfa90b6Smrg if (new_adaptors == NULL) 9933bfa90b6Smrg return; 9943bfa90b6Smrg 9953bfa90b6Smrg memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); 9963bfa90b6Smrg adaptors = new_adaptors; 9973bfa90b6Smrg 9983bfa90b6Smrg /* Add the adaptors supported by our hardware. First, set up the atoms 9993bfa90b6Smrg * that will be used by both output adaptors. 10003bfa90b6Smrg */ 10013bfa90b6Smrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 10023bfa90b6Smrg xvContrast = MAKE_ATOM("XV_CONTRAST"); 10033bfa90b6Smrg xvSaturation = MAKE_ATOM("XV_SATURATION"); 10043bfa90b6Smrg xvHue = MAKE_ATOM("XV_HUE"); 10053bfa90b6Smrg 10063bfa90b6Smrg if (ms->xat) { 10073bfa90b6Smrg textured_adapter = xorg_setup_textured_adapter(pScreen); 10083bfa90b6Smrg if (textured_adapter) 10093bfa90b6Smrg adaptors[num_adaptors++] = textured_adapter; 10103bfa90b6Smrg } else { 10113bfa90b6Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 10123bfa90b6Smrg "No 3D acceleration. Not setting up textured video.\n"); 10133bfa90b6Smrg } 10143bfa90b6Smrg 10153bfa90b6Smrg overlay_adaptor = vmw_video_init_adaptor(pScrn); 10163bfa90b6Smrg if (overlay_adaptor) 10173bfa90b6Smrg adaptors[num_adaptors++] = overlay_adaptor; 10183bfa90b6Smrg 10193bfa90b6Smrg if (num_adaptors) { 10203bfa90b6Smrg Bool ret; 10213bfa90b6Smrg ret = xf86XVScreenInit(pScreen, adaptors, num_adaptors); 10223bfa90b6Smrg if (textured_adapter) 10233bfa90b6Smrg vmwgfx_free_textured_adaptor(textured_adapter, !ret); 10243bfa90b6Smrg if (overlay_adaptor) 10253bfa90b6Smrg vmw_video_free_adaptor(overlay_adaptor, !ret); 10263bfa90b6Smrg if (!ret) 10273bfa90b6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 10283bfa90b6Smrg "Failed to initialize Xv.\n"); 10293bfa90b6Smrg } else { 10303bfa90b6Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 10313bfa90b6Smrg "Disabling Xv because no adaptors could be initialized.\n"); 10323bfa90b6Smrg } 10333bfa90b6Smrg} 1034