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" 3525dbecb6Smrg#include "../src/common_compat.h" 363bfa90b6Smrg 373bfa90b6Smrg#include <xf86xv.h> 383bfa90b6Smrg#include <X11/extensions/Xv.h> 393bfa90b6Smrg#include <fourcc.h> 403bfa90b6Smrg#include <xa_tracker.h> 413bfa90b6Smrg#include <xa_context.h> 423bfa90b6Smrg#include <math.h> 433bfa90b6Smrg 4425dbecb6Smrgstatic CONST_ABI_16_0 char xv_adapt_name[] = "XA G3D Textured Video"; 4525dbecb6Smrg 4625dbecb6Smrg/*Xxx get these from pipe's texture limits */ 473bfa90b6Smrg#define IMAGE_MAX_WIDTH 2048 483bfa90b6Smrg#define IMAGE_MAX_HEIGHT 2048 493bfa90b6Smrg 503bfa90b6Smrg#define RES_720P_X 1280 513bfa90b6Smrg#define RES_720P_Y 720 523bfa90b6Smrg 533bfa90b6Smrg 543bfa90b6Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 553bfa90b6Smrg 563bfa90b6Smrg/* 573bfa90b6Smrg * ITU-R BT.601, BT.709 transfer matrices. 583bfa90b6Smrg * [R', G', B'] values are in the range [0, 1], Y' is in the range [0,1] 593bfa90b6Smrg * and [Pb, Pr] components are in the range [-0.5, 0.5]. 603bfa90b6Smrg * 613bfa90b6Smrg * The matrices are transposed to fit the xa conversion matrix format. 623bfa90b6Smrg */ 633bfa90b6Smrg 643bfa90b6Smrgstatic const float bt_601[] = { 653bfa90b6Smrg 1.f, 1.f, 1.f, 0.f, 663bfa90b6Smrg 0.f, -0.344136f, 1.772f, 0.f, 673bfa90b6Smrg 1.402f, -0.714136f, 0.f, 0.f 683bfa90b6Smrg}; 693bfa90b6Smrg 703bfa90b6Smrgstatic const float bt_709[] = { 713bfa90b6Smrg 1.f, 1.f, 1.f, 0.f, 723bfa90b6Smrg 0.f, -0.187324f, 1.8556f, 0.f, 733bfa90b6Smrg 1.5748f, -0.468124f, 0.f, 0.f 743bfa90b6Smrg}; 753bfa90b6Smrg 763bfa90b6Smrgstatic Atom xvBrightness, xvContrast, xvSaturation, xvHue; 7725dbecb6Smrgstatic CONST_ABI_16_TO_19 char xv_brightness_name[] = "XV_BRIGHTNESS"; 7825dbecb6Smrgstatic CONST_ABI_16_TO_19 char xv_contrast_name[] = "XV_CONTRAST"; 7925dbecb6Smrgstatic CONST_ABI_16_TO_19 char xv_saturation_name[] = "XV_SATURATION"; 8025dbecb6Smrgstatic CONST_ABI_16_TO_19 char xv_hue_name[] = "XV_HUE"; 8125dbecb6Smrgstatic CONST_ABI_16_TO_19 char xv_image_name[] = "XV_IMAGE"; 823bfa90b6Smrg 833bfa90b6Smrg#define NUM_TEXTURED_ATTRIBUTES 4 8422f7e8e5Smrgstatic const XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = { 8525dbecb6Smrg {XvSettable | XvGettable, -1000, 1000, xv_brightness_name}, 8625dbecb6Smrg {XvSettable | XvGettable, -1000, 1000, xv_contrast_name}, 8725dbecb6Smrg {XvSettable | XvGettable, -1000, 1000, xv_saturation_name}, 8825dbecb6Smrg {XvSettable | XvGettable, -1000, 1000, xv_hue_name} 893bfa90b6Smrg}; 903bfa90b6Smrg 913bfa90b6Smrg#define NUM_FORMATS 3 923bfa90b6Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = { 933bfa90b6Smrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 943bfa90b6Smrg}; 953bfa90b6Smrg 963bfa90b6Smrgstatic XF86VideoEncodingRec DummyEncoding[1] = { 973bfa90b6Smrg { 983bfa90b6Smrg 0, 9925dbecb6Smrg xv_image_name, 1003bfa90b6Smrg IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 1013bfa90b6Smrg {1, 1} 1023bfa90b6Smrg } 1033bfa90b6Smrg}; 1043bfa90b6Smrg 1053bfa90b6Smrg#define NUM_IMAGES 3 1063bfa90b6Smrgstatic XF86ImageRec Images[NUM_IMAGES] = { 1073bfa90b6Smrg XVIMAGE_UYVY, 1083bfa90b6Smrg XVIMAGE_YUY2, 1093bfa90b6Smrg XVIMAGE_YV12, 1103bfa90b6Smrg}; 1113bfa90b6Smrg 1123bfa90b6Smrgstruct xorg_xv_port_priv { 1133bfa90b6Smrg struct xa_tracker *xat; 1143bfa90b6Smrg struct xa_context *r; 1153bfa90b6Smrg struct xa_fence *fence; 1163bfa90b6Smrg 1173bfa90b6Smrg RegionRec clip; 1183bfa90b6Smrg 1193bfa90b6Smrg int brightness; 1203bfa90b6Smrg int contrast; 1213bfa90b6Smrg int saturation; 1223bfa90b6Smrg int hue; 1233bfa90b6Smrg 1243bfa90b6Smrg int current_set; 12522f7e8e5Smrg struct xa_surface *yuv[2][3]; 1263bfa90b6Smrg 12734a0776dSmrg struct xa_surface *bounce; 12834a0776dSmrg struct xa_box bounce_box; 12934a0776dSmrg struct xa_picture *src_pic; 13034a0776dSmrg struct xa_picture *dst_pic; 13134a0776dSmrg struct xa_composite *comp; 13234a0776dSmrg 1333bfa90b6Smrg int drm_fd; 1343bfa90b6Smrg 1353bfa90b6Smrg Bool hdtv; 1363bfa90b6Smrg float uv_offset; 1373bfa90b6Smrg float uv_scale; 1383bfa90b6Smrg float y_offset; 1393bfa90b6Smrg float y_scale; 1403bfa90b6Smrg float rgb_offset; 1413bfa90b6Smrg float rgb_scale; 1423bfa90b6Smrg float sinhue; 1433bfa90b6Smrg float coshue; 1443bfa90b6Smrg float cm[16]; 1453bfa90b6Smrg}; 1463bfa90b6Smrg 1473bfa90b6Smrg/* 1483bfa90b6Smrg * vmwgfx_update_conversion_matrix - Compute the effective color conversion 1493bfa90b6Smrg * matrix. 1503bfa90b6Smrg * 1513bfa90b6Smrg * Applies yuv- and resulting rgb scales and offsets to compute the correct 1523bfa90b6Smrg * color conversion matrix. These scales and offsets are properties of the 1533bfa90b6Smrg * video stream and can be adjusted using XV properties as well. 1543bfa90b6Smrg */ 1553bfa90b6Smrgstatic void 1563bfa90b6Smrgvmwgfx_update_conversion_matrix(struct xorg_xv_port_priv *priv) 1573bfa90b6Smrg{ 1583bfa90b6Smrg int i; 1593bfa90b6Smrg float *cm = priv->cm; 1603bfa90b6Smrg static const float *bt; 1613bfa90b6Smrg 1623bfa90b6Smrg bt = (priv->hdtv) ? bt_709 : bt_601; 1633bfa90b6Smrg 1643bfa90b6Smrg memcpy(cm, bt, sizeof(bt_601)); 1653bfa90b6Smrg 1663bfa90b6Smrg /* 1673bfa90b6Smrg * Apply hue rotation 1683bfa90b6Smrg */ 1693bfa90b6Smrg cm[4] = priv->coshue * bt[4] - priv->sinhue * bt[8]; 1703bfa90b6Smrg cm[8] = priv->sinhue * bt[4] + priv->coshue * bt[8]; 1713bfa90b6Smrg cm[5] = priv->coshue * bt[5] - priv->sinhue * bt[9]; 1723bfa90b6Smrg cm[9] = priv->sinhue * bt[5] + priv->coshue * bt[9]; 1733bfa90b6Smrg cm[6] = priv->coshue * bt[6] - priv->sinhue * bt[10]; 1743bfa90b6Smrg cm[10] = priv->sinhue * bt[6] + priv->coshue * bt[10]; 1753bfa90b6Smrg 1763bfa90b6Smrg /* 1773bfa90b6Smrg * Adjust for yuv scales in input and rgb scale in the converted output. 1783bfa90b6Smrg */ 1793bfa90b6Smrg for(i = 0; i < 3; ++i) { 1803bfa90b6Smrg cm[i] *= (priv->y_scale*priv->rgb_scale); 1813bfa90b6Smrg cm[i+4] *= (priv->uv_scale*priv->rgb_scale); 1823bfa90b6Smrg cm[i+8] *= (priv->uv_scale*priv->rgb_scale); 1833bfa90b6Smrg } 1843bfa90b6Smrg 1853bfa90b6Smrg /* 1863bfa90b6Smrg * Adjust for yuv offsets in input and rgb offset in the converted output. 1873bfa90b6Smrg */ 1883bfa90b6Smrg for (i = 0; i < 3; ++i) 1893bfa90b6Smrg cm[i+12] = -cm[i]*priv->y_offset - (cm[i+4] + cm[i+8])*priv->uv_offset 1903bfa90b6Smrg - priv->rgb_offset*priv->rgb_scale; 1913bfa90b6Smrg 1923bfa90b6Smrg /* 1933bfa90b6Smrg * Alpha is 1, unconditionally. 1943bfa90b6Smrg */ 1953bfa90b6Smrg cm[15] = 1.f; 1963bfa90b6Smrg} 1973bfa90b6Smrg 19834a0776dSmrg/** 19934a0776dSmrg * vmwgfx_video_free_comp - free members used for composite bounce blit 20034a0776dSmrg * 20134a0776dSmrg * @priv: Pointer to the port private 20234a0776dSmrg * 20334a0776dSmrg * Frees any port priv resources allocated for a composite bounce blit. 20434a0776dSmrg */ 20534a0776dSmrgstatic void 20634a0776dSmrgvmwgfx_video_free_comp(struct xorg_xv_port_priv *priv) 20734a0776dSmrg{ 20834a0776dSmrg if (priv->dst_pic) 20934a0776dSmrg free(priv->dst_pic); 21034a0776dSmrg if (priv->src_pic) 21134a0776dSmrg free(priv->src_pic); 21234a0776dSmrg if (priv->comp) 21334a0776dSmrg free(priv->comp); 21434a0776dSmrg 21534a0776dSmrg priv->dst_pic = NULL; 21634a0776dSmrg priv->src_pic = NULL; 21734a0776dSmrg priv->comp = NULL; 21834a0776dSmrg} 2193bfa90b6Smrg 2203bfa90b6Smrgstatic void 2213bfa90b6Smrgstop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 2223bfa90b6Smrg{ 2233bfa90b6Smrg struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 2243bfa90b6Smrg int i, j; 2253bfa90b6Smrg 2263bfa90b6Smrg REGION_EMPTY(pScrn->pScreen, &priv->clip); 2273bfa90b6Smrg if (shutdown) { 2283bfa90b6Smrg 2293bfa90b6Smrg /* 2303bfa90b6Smrg * No need to destroy the xa context or xa tracker since 2313bfa90b6Smrg * they are copied from the screen resources. 2323bfa90b6Smrg */ 2333bfa90b6Smrg 2343bfa90b6Smrg xa_fence_destroy(priv->fence); 2353bfa90b6Smrg priv->fence = NULL; 23634a0776dSmrg vmwgfx_video_free_comp(priv); 2373bfa90b6Smrg 2383bfa90b6Smrg for (i=0; i<3; ++i) { 2393bfa90b6Smrg for (j=0; j<2; ++j) { 24025dbecb6Smrg if (priv->yuv[j][i]) { 24122f7e8e5Smrg xa_surface_destroy(priv->yuv[j][i]); 24222f7e8e5Smrg priv->yuv[j][i] = NULL; 2433bfa90b6Smrg } 24434a0776dSmrg if (priv->bounce) { 24534a0776dSmrg xa_surface_destroy(priv->bounce); 24634a0776dSmrg priv->bounce = NULL; 24734a0776dSmrg } 2483bfa90b6Smrg } 2493bfa90b6Smrg } 2503bfa90b6Smrg } 2513bfa90b6Smrg} 2523bfa90b6Smrg 2533bfa90b6Smrgstatic int 2543bfa90b6Smrgset_port_attribute(ScrnInfoPtr pScrn, 2553bfa90b6Smrg Atom attribute, INT32 value, pointer data) 2563bfa90b6Smrg{ 2573bfa90b6Smrg struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 2583bfa90b6Smrg 2593bfa90b6Smrg if (attribute == xvBrightness) { 2603bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2613bfa90b6Smrg return BadValue; 2623bfa90b6Smrg 2633bfa90b6Smrg priv->brightness = value; 2643bfa90b6Smrg priv->y_offset = -((float) value)/1000.f; 2653bfa90b6Smrg 2663bfa90b6Smrg } else if (attribute == xvContrast) { 2673bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2683bfa90b6Smrg return BadValue; 2693bfa90b6Smrg 2703bfa90b6Smrg priv->contrast = value; 2713bfa90b6Smrg priv->rgb_scale = ((float) value + 1000.f)/1000.f; 2723bfa90b6Smrg 2733bfa90b6Smrg } else if (attribute == xvSaturation) { 2743bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2753bfa90b6Smrg return BadValue; 2763bfa90b6Smrg 2773bfa90b6Smrg priv->saturation = value; 2783bfa90b6Smrg priv->uv_scale = ((float) value + 1000.f)/1000.f; 2793bfa90b6Smrg 2803bfa90b6Smrg } else if (attribute == xvHue) { 2813bfa90b6Smrg double hue_angle; 2823bfa90b6Smrg 2833bfa90b6Smrg if ((value < -1000) || (value > 1000)) 2843bfa90b6Smrg return BadValue; 2853bfa90b6Smrg 2863bfa90b6Smrg priv->hue = value; 2873bfa90b6Smrg hue_angle = (double) value * M_PI / 1000.; 2883bfa90b6Smrg priv->sinhue = sin(hue_angle); 2893bfa90b6Smrg priv->coshue = cos(hue_angle); 2903bfa90b6Smrg 2913bfa90b6Smrg } else 2923bfa90b6Smrg return BadMatch; 2933bfa90b6Smrg 2943bfa90b6Smrg vmwgfx_update_conversion_matrix(priv); 2953bfa90b6Smrg return Success; 2963bfa90b6Smrg} 2973bfa90b6Smrg 2983bfa90b6Smrgstatic int 2993bfa90b6Smrgget_port_attribute(ScrnInfoPtr pScrn, 3003bfa90b6Smrg Atom attribute, INT32 * value, pointer data) 3013bfa90b6Smrg{ 3023bfa90b6Smrg struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 3033bfa90b6Smrg 3043bfa90b6Smrg if (attribute == xvBrightness) 3053bfa90b6Smrg *value = priv->brightness; 3063bfa90b6Smrg else if (attribute == xvContrast) 3073bfa90b6Smrg *value = priv->contrast; 3083bfa90b6Smrg else if (attribute == xvSaturation) 3093bfa90b6Smrg *value = priv->saturation; 3103bfa90b6Smrg else if (attribute == xvHue) 3113bfa90b6Smrg *value = priv->hue; 3123bfa90b6Smrg else 3133bfa90b6Smrg return BadMatch; 3143bfa90b6Smrg 3153bfa90b6Smrg return Success; 3163bfa90b6Smrg} 3173bfa90b6Smrg 3183bfa90b6Smrgstatic void 3193bfa90b6Smrgquery_best_size(ScrnInfoPtr pScrn, 3203bfa90b6Smrg Bool motion, 3213bfa90b6Smrg short vid_w, short vid_h, 3223bfa90b6Smrg short drw_w, short drw_h, 3233bfa90b6Smrg unsigned int *p_w, unsigned int *p_h, pointer data) 3243bfa90b6Smrg{ 3253bfa90b6Smrg if (vid_w > (drw_w << 1)) 3263bfa90b6Smrg drw_w = vid_w >> 1; 3273bfa90b6Smrg if (vid_h > (drw_h << 1)) 3283bfa90b6Smrg drw_h = vid_h >> 1; 3293bfa90b6Smrg 3303bfa90b6Smrg *p_w = drw_w; 3313bfa90b6Smrg *p_h = drw_h; 3323bfa90b6Smrg} 3333bfa90b6Smrg 3343bfa90b6Smrgstatic int 3353bfa90b6Smrgcheck_yuv_surfaces(struct xorg_xv_port_priv *priv, int id, 3363bfa90b6Smrg int width, int height) 3373bfa90b6Smrg{ 33822f7e8e5Smrg struct xa_surface **yuv = priv->yuv[priv->current_set]; 3393bfa90b6Smrg int ret = 0; 3403bfa90b6Smrg int i; 3413bfa90b6Smrg 3423bfa90b6Smrg for (i=0; i<3; ++i) { 3433bfa90b6Smrg 3443bfa90b6Smrg /* 3453bfa90b6Smrg * Adjust u,v texture size and DMA buffer to what's required by 3463bfa90b6Smrg * the format. 3473bfa90b6Smrg */ 3483bfa90b6Smrg if (i == 1) { 3493bfa90b6Smrg switch(id) { 3503bfa90b6Smrg case FOURCC_YV12: 3513bfa90b6Smrg height /= 2; 3523bfa90b6Smrg /* Fall through */ 3533bfa90b6Smrg case FOURCC_YUY2: 3543bfa90b6Smrg case FOURCC_UYVY: 3553bfa90b6Smrg width /= 2; 3563bfa90b6Smrg break; 3573bfa90b6Smrg default: 3583bfa90b6Smrg break; 3593bfa90b6Smrg } 3603bfa90b6Smrg } 3613bfa90b6Smrg 3623bfa90b6Smrg if (!yuv[i]) 3633bfa90b6Smrg yuv[i] = xa_surface_create(priv->xat, width, height, 8, 3643bfa90b6Smrg xa_type_yuv_component, 3653bfa90b6Smrg xa_format_unknown, 0); 3663bfa90b6Smrg else 3673bfa90b6Smrg ret = xa_surface_redefine(yuv[i], width, height, 8, 3683bfa90b6Smrg xa_type_yuv_component, 3693bfa90b6Smrg xa_format_unknown, 0, 0); 3703bfa90b6Smrg if (ret || !yuv[i]) 3713bfa90b6Smrg return BadAlloc; 3723bfa90b6Smrg 3733bfa90b6Smrg } 3743bfa90b6Smrg return Success; 3753bfa90b6Smrg} 3763bfa90b6Smrg 37734a0776dSmrg 37834a0776dSmrg/** 37934a0776dSmrg * vmwgfx_video_setup_comp - Set up port priv members for a composite 38034a0776dSmrg * bounce blit 38134a0776dSmrg * 38234a0776dSmrg * @priv: Pointer to the port priv. 38334a0776dSmrg * @format: XA format of the destination drawable surface. 38434a0776dSmrg * 38534a0776dSmrg * Tries to allocate and set up port priv resources to perform a composite 38634a0776dSmrg * bounce blit (except the bounce surface itself). On failure, all resources 38734a0776dSmrg * are freed. On success, TRUE is returned and @priv::comp is non-NULL. If 38834a0776dSmrg * resources are already allocated, update them for the current @format. 38934a0776dSmrg */ 39034a0776dSmrgstatic Bool 39134a0776dSmrgvmwgfx_video_setup_comp(struct xorg_xv_port_priv *priv, enum xa_formats format) 39234a0776dSmrg{ 39334a0776dSmrg const struct xa_composite_allocation *alloc; 39434a0776dSmrg struct xa_picture *pic; 39534a0776dSmrg 39634a0776dSmrg if (priv->comp) { 39734a0776dSmrg if (priv->src_pic->pict_format != format) { 39834a0776dSmrg priv->src_pic->pict_format = format; 39934a0776dSmrg priv->dst_pic->pict_format = format; 40034a0776dSmrg if (xa_composite_check_accelerated(priv->comp) != XA_ERR_NONE) { 40134a0776dSmrg vmwgfx_video_free_comp(priv); 40234a0776dSmrg return FALSE; 40334a0776dSmrg } 40434a0776dSmrg } 40534a0776dSmrg return TRUE; 40634a0776dSmrg } 40734a0776dSmrg 40834a0776dSmrg alloc = xa_composite_allocation(); 40934a0776dSmrg priv->comp = calloc(1, alloc->xa_composite_size); 41034a0776dSmrg priv->src_pic = calloc(1, alloc->xa_picture_size); 41134a0776dSmrg priv->dst_pic = calloc(1, alloc->xa_picture_size); 41234a0776dSmrg 41334a0776dSmrg if (!priv->comp || !priv->src_pic || !priv->dst_pic) { 41434a0776dSmrg vmwgfx_video_free_comp(priv); 41534a0776dSmrg return FALSE; 41634a0776dSmrg } 41734a0776dSmrg 41834a0776dSmrg pic = priv->src_pic; 41934a0776dSmrg pic->pict_format = format; 42034a0776dSmrg pic->wrap = xa_wrap_clamp_to_border; 42134a0776dSmrg pic->filter = xa_filter_linear; 42234a0776dSmrg 42334a0776dSmrg *priv->dst_pic = *pic; 42434a0776dSmrg 42534a0776dSmrg priv->comp->src = priv->src_pic; 42634a0776dSmrg priv->comp->dst = priv->dst_pic; 42734a0776dSmrg priv->comp->op = xa_op_src; 42834a0776dSmrg priv->comp->no_solid = 1; 42934a0776dSmrg 43034a0776dSmrg if (xa_composite_check_accelerated(priv->comp) != XA_ERR_NONE) { 43134a0776dSmrg vmwgfx_video_free_comp(priv); 43234a0776dSmrg return FALSE; 43334a0776dSmrg } 43434a0776dSmrg 43534a0776dSmrg return TRUE; 43634a0776dSmrg} 43734a0776dSmrg 43834a0776dSmrg/** 43934a0776dSmrg * vmwgfx_video_setup_coord_matrix - Set up a bounce - to destination 44034a0776dSmrg * transformation matrix 44134a0776dSmrg * 44234a0776dSmrg * @src_x: Upper left corner of source image as given to putImage. 44334a0776dSmrg * @src_y: Upper left corner of source image as given to putImage. 44434a0776dSmrg * @src_w: Width of source image. 44534a0776dSmrg * @src_h: Height of source image. 44634a0776dSmrg * @dst_x: Upper left corner of destination image as given to putImage. 44734a0776dSmrg * @dst_y: Upper left corner of destination image as given to putImage. 44834a0776dSmrg * @dst_w: Width of destination image. 44934a0776dSmrg * @dst_h: Height of destination image. 45034a0776dSmrg * @bounce_w: Width of bounce surface. 45134a0776dSmrg * @bounce_h: Height of bounce surface. 45234a0776dSmrg * @mat: Pointer to transformation matrix. 45334a0776dSmrg * 45434a0776dSmrg * Computes a transformation matrix that can be used by the XA composite API 45534a0776dSmrg * to transform between the destination coordinate space and the bounce 45634a0776dSmrg * surface coordinate space. Scaling and translation. 45734a0776dSmrg */ 45834a0776dSmrgstatic void 45934a0776dSmrgvmwgfx_video_setup_coord_matrix(int src_x, int src_y, int src_w, int src_h, 46034a0776dSmrg int dst_x, int dst_y, int dst_w, int dst_h, 46134a0776dSmrg int bounce_w, int bounce_h, 46234a0776dSmrg float *mat) 46334a0776dSmrg{ 46434a0776dSmrg if (dst_w == 0 || dst_h == 0 || src_w == 0 || src_h == 0) { 46534a0776dSmrg mat[0] = mat[6] = 0.; 46634a0776dSmrg mat[4] = mat[7] = 0.; 46734a0776dSmrg mat[8] = 1.f; 46834a0776dSmrg return; 46934a0776dSmrg } 47034a0776dSmrg 47134a0776dSmrg mat[0] = (float) bounce_w / (float) dst_w; 47234a0776dSmrg mat[6] = (float) src_x * (float) bounce_w / (float) src_w - 47334a0776dSmrg (float) dst_x * mat[0]; 47434a0776dSmrg mat[4] = (float) bounce_h / (float) dst_h; 47534a0776dSmrg mat[7] = (float) src_y * (float) bounce_h / (float) src_h - 47634a0776dSmrg (float) dst_y * mat[4]; 47734a0776dSmrg mat[8] = 1.f; 47834a0776dSmrg} 47934a0776dSmrg 48034a0776dSmrg/** 48134a0776dSmrg * vmwgfx_video_bounce_surface: (Re)Allocate a bounce surface if desired. 48234a0776dSmrg * 48334a0776dSmrg * @priv: Pointer to the port private. 48434a0776dSmrg * @d_with: Width of destination image. 48534a0776dSmrg * @d_height: Height of destination image. 48634a0776dSmrg * @width: Width of source video image. 48734a0776dSmrg * @height: Height of source video image. 48834a0776dSmrg * @dst_format: Format of destination drawable surface. 48934a0776dSmrg * 49034a0776dSmrg * If the destination video image is a suitable factor larger than the source 49134a0776dSmrg * video image. Allocate a bounce RGB surface that will be the target of the 49234a0776dSmrg * more expensive color conversion blit, and source of the scaling blit. 49334a0776dSmrg */ 49434a0776dSmrgstatic Bool 49534a0776dSmrgvmwgfx_video_bounce_surface(struct xorg_xv_port_priv *priv, 49634a0776dSmrg int d_width, int d_height, 49734a0776dSmrg int width, int height, 49834a0776dSmrg enum xa_formats dst_format) 49934a0776dSmrg{ 50034a0776dSmrg float bounce_area, dst_area; 50134a0776dSmrg 50234a0776dSmrg if (d_width < width) 50334a0776dSmrg width = d_width; 50434a0776dSmrg 50534a0776dSmrg if (d_height < height) 50634a0776dSmrg height = d_height; 50734a0776dSmrg 50834a0776dSmrg bounce_area = (float) width * (float) height; 50934a0776dSmrg dst_area = (float) d_width * (float) d_height; 51034a0776dSmrg 51134a0776dSmrg if (dst_area > bounce_area * 1.5f && 51234a0776dSmrg vmwgfx_video_setup_comp(priv, dst_format)) { 51334a0776dSmrg 51434a0776dSmrg if (!priv->bounce) { 51534a0776dSmrg priv->bounce = xa_surface_create(priv->xat, width, height, 51634a0776dSmrg xa_format_depth(dst_format), 51734a0776dSmrg xa_format_type(dst_format), 51834a0776dSmrg dst_format, XA_FLAG_RENDER_TARGET); 51934a0776dSmrg } else { 52034a0776dSmrg if (xa_surface_redefine(priv->bounce, width, height, 52134a0776dSmrg xa_format_depth(dst_format), 52234a0776dSmrg xa_format_type(dst_format), 52334a0776dSmrg dst_format, 52434a0776dSmrg XA_FLAG_RENDER_TARGET, 0) != XA_ERR_NONE) { 52534a0776dSmrg xa_surface_destroy(priv->bounce); 52634a0776dSmrg priv->bounce = NULL; 52734a0776dSmrg } 52834a0776dSmrg } 52934a0776dSmrg 53034a0776dSmrg } else { 53134a0776dSmrg xa_surface_destroy(priv->bounce); 53234a0776dSmrg priv->bounce = NULL; 53334a0776dSmrg } 53434a0776dSmrg 53534a0776dSmrg if (priv->bounce) { 53634a0776dSmrg priv->bounce_box.x1 = 0; 53734a0776dSmrg priv->bounce_box.x2 = width; 53834a0776dSmrg priv->bounce_box.y1 = 0; 53934a0776dSmrg priv->bounce_box.y2 = height; 54034a0776dSmrg } 54134a0776dSmrg 54234a0776dSmrg return TRUE; 54334a0776dSmrg} 54434a0776dSmrg 5453bfa90b6Smrgstatic int 5463bfa90b6Smrgquery_image_attributes(ScrnInfoPtr pScrn, 5473bfa90b6Smrg int id, 5483bfa90b6Smrg unsigned short *w, unsigned short *h, 5493bfa90b6Smrg int *pitches, int *offsets) 5503bfa90b6Smrg{ 5513bfa90b6Smrg int size, tmp; 5523bfa90b6Smrg 5533bfa90b6Smrg if (*w > IMAGE_MAX_WIDTH) 5543bfa90b6Smrg *w = IMAGE_MAX_WIDTH; 5553bfa90b6Smrg if (*h > IMAGE_MAX_HEIGHT) 5563bfa90b6Smrg *h = IMAGE_MAX_HEIGHT; 5573bfa90b6Smrg 5583bfa90b6Smrg *w = (*w + 1) & ~1; 5593bfa90b6Smrg if (offsets) 5603bfa90b6Smrg offsets[0] = 0; 5613bfa90b6Smrg 5623bfa90b6Smrg switch (id) { 5633bfa90b6Smrg case FOURCC_YV12: 5643bfa90b6Smrg *h = (*h + 1) & ~1; 5653bfa90b6Smrg size = (*w + 3) & ~3; 5663bfa90b6Smrg if (pitches) { 5673bfa90b6Smrg pitches[0] = size; 5683bfa90b6Smrg } 5693bfa90b6Smrg size *= *h; 5703bfa90b6Smrg if (offsets) { 5713bfa90b6Smrg offsets[1] = size; 5723bfa90b6Smrg } 5733bfa90b6Smrg tmp = ((*w >> 1) + 3) & ~3; 5743bfa90b6Smrg if (pitches) { 5753bfa90b6Smrg pitches[1] = pitches[2] = tmp; 5763bfa90b6Smrg } 5773bfa90b6Smrg tmp *= (*h >> 1); 5783bfa90b6Smrg size += tmp; 5793bfa90b6Smrg if (offsets) { 5803bfa90b6Smrg offsets[2] = size; 5813bfa90b6Smrg } 5823bfa90b6Smrg size += tmp; 5833bfa90b6Smrg break; 5843bfa90b6Smrg case FOURCC_UYVY: 5853bfa90b6Smrg case FOURCC_YUY2: 5863bfa90b6Smrg default: 5873bfa90b6Smrg size = *w << 1; 5883bfa90b6Smrg if (pitches) 5893bfa90b6Smrg pitches[0] = size; 5903bfa90b6Smrg size *= *h; 5913bfa90b6Smrg break; 5923bfa90b6Smrg } 5933bfa90b6Smrg 5943bfa90b6Smrg return size; 5953bfa90b6Smrg} 5963bfa90b6Smrg 5973bfa90b6Smrgstatic int 5983bfa90b6Smrgcopy_packed_data(ScrnInfoPtr pScrn, 5993bfa90b6Smrg struct xorg_xv_port_priv *port, 6003bfa90b6Smrg int id, 6013bfa90b6Smrg unsigned char *buf, 6023bfa90b6Smrg int left, 6033bfa90b6Smrg int top, 6043bfa90b6Smrg unsigned short w, unsigned short h) 6053bfa90b6Smrg{ 6063bfa90b6Smrg int i; 60722f7e8e5Smrg struct xa_surface **yuv = port->yuv[port->current_set]; 6083bfa90b6Smrg char *ymap, *vmap, *umap; 60925dbecb6Smrg unsigned char _y1, _y2, u, v; 6103bfa90b6Smrg int yidx, uidx, vidx; 6113bfa90b6Smrg int y_array_size = w * h; 6123bfa90b6Smrg int ret = BadAlloc; 6133bfa90b6Smrg 61422f7e8e5Smrg ymap = xa_surface_map(port->r, yuv[0], XA_MAP_WRITE); 6153bfa90b6Smrg if (!ymap) 6163bfa90b6Smrg return BadAlloc; 61722f7e8e5Smrg umap = xa_surface_map(port->r, yuv[1], XA_MAP_WRITE); 6183bfa90b6Smrg if (!umap) 6193bfa90b6Smrg goto out_no_umap; 62022f7e8e5Smrg vmap = xa_surface_map(port->r, yuv[2], XA_MAP_WRITE); 6213bfa90b6Smrg if (!vmap) 6223bfa90b6Smrg goto out_no_vmap; 6233bfa90b6Smrg 6243bfa90b6Smrg 6253bfa90b6Smrg yidx = uidx = vidx = 0; 6263bfa90b6Smrg 6273bfa90b6Smrg switch (id) { 6283bfa90b6Smrg case FOURCC_YV12: { 6293bfa90b6Smrg int pitches[3], offsets[3]; 63022f7e8e5Smrg unsigned char *yp, *up, *vp; 6313bfa90b6Smrg query_image_attributes(pScrn, FOURCC_YV12, 6323bfa90b6Smrg &w, &h, pitches, offsets); 6333bfa90b6Smrg 63422f7e8e5Smrg yp = buf + offsets[0]; 63522f7e8e5Smrg vp = buf + offsets[1]; 63622f7e8e5Smrg up = buf + offsets[2]; 63725dbecb6Smrg for (i = 0; i < h; ++i) { 63825dbecb6Smrg memcpy(ymap + w * i, yp, w); 63925dbecb6Smrg yp += pitches[0]; 64025dbecb6Smrg } 64125dbecb6Smrg for (i = 0; i < h / 2; ++i) { 64225dbecb6Smrg memcpy(vmap + w * i / 2, vp, w / 2); 64325dbecb6Smrg memcpy(umap + w * i / 2, up, w / 2); 64425dbecb6Smrg vp += pitches[1]; 64525dbecb6Smrg up += pitches[2]; 64625dbecb6Smrg } 6473bfa90b6Smrg break; 6483bfa90b6Smrg } 6493bfa90b6Smrg case FOURCC_UYVY: 6503bfa90b6Smrg for (i = 0; i < y_array_size; i +=2 ) { 6513bfa90b6Smrg /* extracting two pixels */ 6523bfa90b6Smrg u = buf[0]; 65325dbecb6Smrg _y1 = buf[1]; 6543bfa90b6Smrg v = buf[2]; 65525dbecb6Smrg _y2 = buf[3]; 6563bfa90b6Smrg buf += 4; 6573bfa90b6Smrg 65825dbecb6Smrg ymap[yidx++] = _y1; 65925dbecb6Smrg ymap[yidx++] = _y2; 6603bfa90b6Smrg umap[uidx++] = u; 6613bfa90b6Smrg vmap[vidx++] = v; 6623bfa90b6Smrg } 6633bfa90b6Smrg break; 6643bfa90b6Smrg case FOURCC_YUY2: 6653bfa90b6Smrg for (i = 0; i < y_array_size; i +=2 ) { 6663bfa90b6Smrg /* extracting two pixels */ 66725dbecb6Smrg _y1 = buf[0]; 6683bfa90b6Smrg u = buf[1]; 66925dbecb6Smrg _y2 = buf[2]; 6703bfa90b6Smrg v = buf[3]; 6713bfa90b6Smrg 6723bfa90b6Smrg buf += 4; 6733bfa90b6Smrg 67425dbecb6Smrg ymap[yidx++] = _y1; 67525dbecb6Smrg ymap[yidx++] = _y2; 6763bfa90b6Smrg umap[uidx++] = u; 6773bfa90b6Smrg vmap[vidx++] = v; 6783bfa90b6Smrg } 6793bfa90b6Smrg break; 6803bfa90b6Smrg default: 6813bfa90b6Smrg ret = BadAlloc; 6823bfa90b6Smrg break; 6833bfa90b6Smrg } 6843bfa90b6Smrg 6853bfa90b6Smrg ret = Success; 68622f7e8e5Smrg xa_surface_unmap(yuv[2]); 6873bfa90b6Smrg out_no_vmap: 68822f7e8e5Smrg xa_surface_unmap(yuv[1]); 6893bfa90b6Smrg out_no_umap: 69022f7e8e5Smrg xa_surface_unmap(yuv[0]); 6913bfa90b6Smrg 6923bfa90b6Smrg return ret; 6933bfa90b6Smrg} 6943bfa90b6Smrg 6953bfa90b6Smrg 6963bfa90b6Smrgstatic int 6973bfa90b6Smrgdisplay_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, 6983bfa90b6Smrg RegionPtr dstRegion, 6993bfa90b6Smrg int src_x, int src_y, int src_w, int src_h, 7003bfa90b6Smrg int dst_x, int dst_y, int dst_w, int dst_h, 70134a0776dSmrg int width, int height, 7023bfa90b6Smrg PixmapPtr pPixmap) 7033bfa90b6Smrg{ 7043bfa90b6Smrg struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pPixmap); 7053bfa90b6Smrg Bool hdtv; 7063bfa90b6Smrg RegionRec reg; 7073bfa90b6Smrg int ret = BadAlloc; 7083bfa90b6Smrg int blit_ret; 7093bfa90b6Smrg 7103bfa90b6Smrg REGION_NULL(pScreen, ®); 7113bfa90b6Smrg 7123bfa90b6Smrg if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, ®)) 7133bfa90b6Smrg goto out_no_dst; 7143bfa90b6Smrg 7153bfa90b6Smrg hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y)); 7163bfa90b6Smrg if (hdtv != pPriv->hdtv) { 7173bfa90b6Smrg pPriv->hdtv = hdtv; 7183bfa90b6Smrg vmwgfx_update_conversion_matrix(pPriv); 7193bfa90b6Smrg } 7203bfa90b6Smrg 7213bfa90b6Smrg#ifdef COMPOSITE 7223bfa90b6Smrg 7233bfa90b6Smrg /* 7243bfa90b6Smrg * For redirected windows, we need to fix up the destination coordinates. 7253bfa90b6Smrg */ 7263bfa90b6Smrg 7273bfa90b6Smrg REGION_TRANSLATE(pScreen, dstRegion, -pPixmap->screen_x, 7283bfa90b6Smrg -pPixmap->screen_y); 7293bfa90b6Smrg dst_x -= pPixmap->screen_x; 7303bfa90b6Smrg dst_y -= pPixmap->screen_y; 7313bfa90b6Smrg#endif 7323bfa90b6Smrg 7333bfa90b6Smrg /* 7343bfa90b6Smrg * Throttle on previous blit. 7353bfa90b6Smrg */ 7363bfa90b6Smrg 7373bfa90b6Smrg if (pPriv->fence) { 7383bfa90b6Smrg (void) xa_fence_wait(pPriv->fence, 1000000000ULL); 7393bfa90b6Smrg xa_fence_destroy(pPriv->fence); 7403bfa90b6Smrg pPriv->fence = NULL; 7413bfa90b6Smrg } 7423bfa90b6Smrg 74334a0776dSmrg (void) vmwgfx_video_bounce_surface(pPriv, dst_w, dst_h, width, height, 74434a0776dSmrg xa_surface_format(vpix->hw)); 74534a0776dSmrg 7463bfa90b6Smrg DamageRegionAppend(&pPixmap->drawable, dstRegion); 7473bfa90b6Smrg 74834a0776dSmrg if (pPriv->bounce) { 74934a0776dSmrg BoxPtr b; 75034a0776dSmrg int i; 75134a0776dSmrg 75234a0776dSmrg /* 75334a0776dSmrg * If we have a bounce buffer, First perform a (potentially down- 75434a0776dSmrg * scaling) color conversion blit with an expensive shader. 75534a0776dSmrg */ 75634a0776dSmrg blit_ret = xa_yuv_planar_blit(pPriv->r, 0, 0, src_w, src_h, 75734a0776dSmrg src_x, src_y, 75834a0776dSmrg pPriv->bounce_box.x2, 75934a0776dSmrg pPriv->bounce_box.y2, 76034a0776dSmrg &pPriv->bounce_box, 1, 76134a0776dSmrg pPriv->cm, 76234a0776dSmrg pPriv->bounce, 76334a0776dSmrg pPriv->yuv[pPriv->current_set]); 76434a0776dSmrg 76534a0776dSmrg if (blit_ret) 76634a0776dSmrg goto out_blit; 76734a0776dSmrg 76834a0776dSmrg /* 76934a0776dSmrg * Then an upscaling blit with a cheap shader. Note that we never 77034a0776dSmrg * scale up a dimenstion that was previously downscaled in the color 77134a0776dSmrg * conversion blit. 77234a0776dSmrg */ 77334a0776dSmrg pPriv->src_pic->srf = pPriv->bounce; 77434a0776dSmrg pPriv->dst_pic->srf = vpix->hw; 77534a0776dSmrg vmwgfx_video_setup_coord_matrix(src_x, src_y, src_w, src_h, 77634a0776dSmrg dst_x, dst_y, dst_w, dst_h, 77734a0776dSmrg pPriv->bounce_box.x2, 77834a0776dSmrg pPriv->bounce_box.y2, 77934a0776dSmrg pPriv->src_pic->transform); 78034a0776dSmrg pPriv->src_pic->has_transform = 1; 78134a0776dSmrg 78234a0776dSmrg if (xa_composite_prepare(pPriv->r, pPriv->comp) != XA_ERR_NONE) { 78334a0776dSmrg blit_ret = 1; 78434a0776dSmrg goto out_blit; 78534a0776dSmrg } 78634a0776dSmrg 78734a0776dSmrg b = REGION_RECTS(dstRegion); 78834a0776dSmrg for (i = 0; i < REGION_NUM_RECTS(dstRegion); ++i, ++b) { 78934a0776dSmrg xa_composite_rect(pPriv->r, b->x1, b->y1, 0, 0, 79034a0776dSmrg b->x1, b->y1, b->x2 - b->x1, 79134a0776dSmrg b->y2 - b->y1); 79234a0776dSmrg } 79334a0776dSmrg 79434a0776dSmrg xa_composite_done(pPriv->r); 79534a0776dSmrg } else { 79634a0776dSmrg /* 79734a0776dSmrg * Perform color conversion and scaling in the same blit. 79834a0776dSmrg */ 79934a0776dSmrg blit_ret = xa_yuv_planar_blit(pPriv->r, src_x, src_y, src_w, src_h, 80034a0776dSmrg dst_x, dst_y, dst_w, dst_h, 80134a0776dSmrg (struct xa_box *)REGION_RECTS(dstRegion), 80234a0776dSmrg REGION_NUM_RECTS(dstRegion), 80334a0776dSmrg pPriv->cm, 80434a0776dSmrg vpix->hw, 80534a0776dSmrg pPriv->yuv[pPriv->current_set ]); 80634a0776dSmrg } 80734a0776dSmrg 80834a0776dSmrg out_blit: 8093bfa90b6Smrg 8103bfa90b6Smrg saa_pixmap_dirty(pPixmap, TRUE, dstRegion); 8113bfa90b6Smrg DamageRegionProcessPending(&pPixmap->drawable); 8123bfa90b6Smrg ret = Success; 8133bfa90b6Smrg 8143bfa90b6Smrg if (!blit_ret) { 8153bfa90b6Smrg ret = Success; 8163bfa90b6Smrg pPriv->fence = xa_fence_get(pPriv->r); 8173bfa90b6Smrg } else 8183bfa90b6Smrg ret = BadAlloc; 8193bfa90b6Smrg 8203bfa90b6Smrg out_no_dst: 8213bfa90b6Smrg REGION_UNINIT(pScreen, ®); 8223bfa90b6Smrg return ret; 8233bfa90b6Smrg} 8243bfa90b6Smrg 8253bfa90b6Smrgstatic int 8263bfa90b6Smrgput_image(ScrnInfoPtr pScrn, 8273bfa90b6Smrg short src_x, short src_y, 8283bfa90b6Smrg short drw_x, short drw_y, 8293bfa90b6Smrg short src_w, short src_h, 8303bfa90b6Smrg short drw_w, short drw_h, 8313bfa90b6Smrg int id, unsigned char *buf, 8323bfa90b6Smrg short width, short height, 8333bfa90b6Smrg Bool sync, RegionPtr clipBoxes, pointer data, 8343bfa90b6Smrg DrawablePtr pDraw) 8353bfa90b6Smrg{ 8363bfa90b6Smrg struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data; 8373bfa90b6Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 8383bfa90b6Smrg PixmapPtr pPixmap; 83925dbecb6Smrg INT32 x1, x2, _y1, _y2; 8403bfa90b6Smrg BoxRec dstBox; 8413bfa90b6Smrg int ret; 8423bfa90b6Smrg 8433bfa90b6Smrg /* Clip */ 8443bfa90b6Smrg x1 = src_x; 8453bfa90b6Smrg x2 = src_x + src_w; 84625dbecb6Smrg _y1 = src_y; 84725dbecb6Smrg _y2 = src_y + src_h; 8483bfa90b6Smrg 8493bfa90b6Smrg dstBox.x1 = drw_x; 8503bfa90b6Smrg dstBox.x2 = drw_x + drw_w; 8513bfa90b6Smrg dstBox.y1 = drw_y; 8523bfa90b6Smrg dstBox.y2 = drw_y + drw_h; 8533bfa90b6Smrg 85425dbecb6Smrg if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &_y1, &_y2, clipBoxes, 8553bfa90b6Smrg width, height)) 8563bfa90b6Smrg return Success; 8573bfa90b6Smrg 8583bfa90b6Smrg ret = check_yuv_surfaces(pPriv, id, width, height); 8593bfa90b6Smrg if (ret) 8603bfa90b6Smrg return ret; 8613bfa90b6Smrg 8623bfa90b6Smrg ret = copy_packed_data(pScrn, pPriv, id, buf, 8633bfa90b6Smrg src_x, src_y, width, height); 8643bfa90b6Smrg if (ret) 8653bfa90b6Smrg return ret; 8663bfa90b6Smrg 8673bfa90b6Smrg if (pDraw->type == DRAWABLE_WINDOW) { 8683bfa90b6Smrg pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); 8693bfa90b6Smrg } else { 8703bfa90b6Smrg pPixmap = (PixmapPtr)pDraw; 8713bfa90b6Smrg } 8723bfa90b6Smrg 8733bfa90b6Smrg display_video(pScrn->pScreen, pPriv, id, clipBoxes, 8743bfa90b6Smrg src_x, src_y, src_w, src_h, 8753bfa90b6Smrg drw_x, drw_y, 87634a0776dSmrg drw_w, drw_h, 87734a0776dSmrg width, height, pPixmap); 8783bfa90b6Smrg 8793bfa90b6Smrg pPriv->current_set = (pPriv->current_set + 1) & 1; 8803bfa90b6Smrg return Success; 8813bfa90b6Smrg} 8823bfa90b6Smrg 8833bfa90b6Smrgstatic struct xorg_xv_port_priv * 8843bfa90b6Smrgport_priv_create(struct xa_tracker *xat, struct xa_context *r, 8853bfa90b6Smrg int drm_fd) 8863bfa90b6Smrg{ 8873bfa90b6Smrg struct xorg_xv_port_priv *priv = NULL; 8883bfa90b6Smrg 8893bfa90b6Smrg priv = calloc(1, sizeof(struct xorg_xv_port_priv)); 8903bfa90b6Smrg 8913bfa90b6Smrg if (!priv) 8923bfa90b6Smrg return NULL; 8933bfa90b6Smrg 8943bfa90b6Smrg priv->r = r; 8953bfa90b6Smrg priv->xat = xat; 8963bfa90b6Smrg priv->drm_fd = drm_fd; 8973bfa90b6Smrg REGION_NULL(pScreen, &priv->clip); 8983bfa90b6Smrg priv->hdtv = FALSE; 8993bfa90b6Smrg priv->uv_offset = 0.5f; 9003bfa90b6Smrg priv->uv_scale = 1.f; 9013bfa90b6Smrg priv->y_offset = 0.f; 9023bfa90b6Smrg priv->y_scale = 1.f; 9033bfa90b6Smrg priv->rgb_offset = 0.f; 9043bfa90b6Smrg priv->rgb_scale = 1.f; 9053bfa90b6Smrg priv->sinhue = 0.f; 9063bfa90b6Smrg priv->coshue = 1.f; 9073bfa90b6Smrg 9083bfa90b6Smrg vmwgfx_update_conversion_matrix(priv); 9093bfa90b6Smrg 9103bfa90b6Smrg return priv; 9113bfa90b6Smrg} 9123bfa90b6Smrg 9133bfa90b6Smrgstatic void 91425dbecb6Smrgvmwgfx_free_textured_adaptor(XF86VideoAdaptorPtr adaptor) 9153bfa90b6Smrg{ 91625dbecb6Smrg int i; 9173bfa90b6Smrg 91825dbecb6Smrg for (i = 0; i < adaptor->nPorts; ++i) 91925dbecb6Smrg free(adaptor->pPortPrivates[i].ptr); 9203bfa90b6Smrg 9213bfa90b6Smrg free(adaptor->pAttributes); 9223bfa90b6Smrg free(adaptor->pPortPrivates); 9233bfa90b6Smrg xf86XVFreeVideoAdaptorRec(adaptor); 9243bfa90b6Smrg} 9253bfa90b6Smrg 9263bfa90b6Smrgstatic XF86VideoAdaptorPtr 9273bfa90b6Smrgxorg_setup_textured_adapter(ScreenPtr pScreen) 9283bfa90b6Smrg{ 9293bfa90b6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 9303bfa90b6Smrg modesettingPtr ms = modesettingPTR(pScrn); 9313bfa90b6Smrg XF86VideoAdaptorPtr adapt; 9323bfa90b6Smrg XF86AttributePtr attrs; 9333bfa90b6Smrg DevUnion *dev_unions; 9343bfa90b6Smrg int nports = 16, i; 9353bfa90b6Smrg int nattributes; 9363bfa90b6Smrg struct xa_context *xar; 9373bfa90b6Smrg 9383bfa90b6Smrg /* 9393bfa90b6Smrg * Use the XA default context since we don't expect the X server 9403bfa90b6Smrg * to render from multiple threads. 9413bfa90b6Smrg */ 9423bfa90b6Smrg 9433bfa90b6Smrg xar = xa_context_default(ms->xat); 9443bfa90b6Smrg nattributes = NUM_TEXTURED_ATTRIBUTES; 9453bfa90b6Smrg 9463bfa90b6Smrg adapt = calloc(1, sizeof(XF86VideoAdaptorRec)); 9473bfa90b6Smrg dev_unions = calloc(nports, sizeof(DevUnion)); 9483bfa90b6Smrg attrs = calloc(nattributes, sizeof(XF86AttributeRec)); 9493bfa90b6Smrg if (adapt == NULL || dev_unions == NULL || attrs == NULL) { 9503bfa90b6Smrg free(adapt); 9513bfa90b6Smrg free(dev_unions); 9523bfa90b6Smrg free(attrs); 9533bfa90b6Smrg return NULL; 9543bfa90b6Smrg } 9553bfa90b6Smrg 9563bfa90b6Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 9573bfa90b6Smrg adapt->flags = 0; 95825dbecb6Smrg adapt->name = xv_adapt_name; 9593bfa90b6Smrg adapt->nEncodings = 1; 9603bfa90b6Smrg adapt->pEncodings = DummyEncoding; 9613bfa90b6Smrg adapt->nFormats = NUM_FORMATS; 9623bfa90b6Smrg adapt->pFormats = Formats; 9633bfa90b6Smrg adapt->nPorts = 0; 9643bfa90b6Smrg adapt->pPortPrivates = dev_unions; 9653bfa90b6Smrg adapt->nAttributes = nattributes; 9663bfa90b6Smrg adapt->pAttributes = attrs; 9673bfa90b6Smrg memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec)); 9683bfa90b6Smrg adapt->nImages = NUM_IMAGES; 9693bfa90b6Smrg adapt->pImages = Images; 9703bfa90b6Smrg adapt->PutVideo = NULL; 9713bfa90b6Smrg adapt->PutStill = NULL; 9723bfa90b6Smrg adapt->GetVideo = NULL; 9733bfa90b6Smrg adapt->GetStill = NULL; 9743bfa90b6Smrg adapt->StopVideo = stop_video; 9753bfa90b6Smrg adapt->SetPortAttribute = set_port_attribute; 9763bfa90b6Smrg adapt->GetPortAttribute = get_port_attribute; 9773bfa90b6Smrg adapt->QueryBestSize = query_best_size; 9783bfa90b6Smrg adapt->PutImage = put_image; 9793bfa90b6Smrg adapt->QueryImageAttributes = query_image_attributes; 9803bfa90b6Smrg 9813bfa90b6Smrg 9823bfa90b6Smrg for (i = 0; i < nports; i++) { 9833bfa90b6Smrg struct xorg_xv_port_priv *priv = 9843bfa90b6Smrg port_priv_create(ms->xat, xar, ms->fd); 9853bfa90b6Smrg 9863bfa90b6Smrg adapt->pPortPrivates[i].ptr = (pointer) (priv); 9873bfa90b6Smrg adapt->nPorts++; 9883bfa90b6Smrg } 9893bfa90b6Smrg 9903bfa90b6Smrg return adapt; 9913bfa90b6Smrg} 9923bfa90b6Smrg 99325dbecb6Smrgvoid 99425dbecb6Smrgvmw_xv_close(ScreenPtr pScreen) 99525dbecb6Smrg{ 99625dbecb6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 99725dbecb6Smrg modesettingPtr ms = modesettingPTR(pScrn); 99825dbecb6Smrg 99925dbecb6Smrg if (ms->overlay) { 100025dbecb6Smrg vmw_video_free_adaptor(ms->overlay); 100125dbecb6Smrg ms->overlay = NULL; 100225dbecb6Smrg } 100325dbecb6Smrg 100425dbecb6Smrg if (ms->textured) { 100525dbecb6Smrg vmwgfx_free_textured_adaptor(ms->textured); 100625dbecb6Smrg ms->textured = NULL; 100725dbecb6Smrg } 100825dbecb6Smrg} 100925dbecb6Smrg 10103bfa90b6Smrgvoid 10113bfa90b6Smrgxorg_xv_init(ScreenPtr pScreen) 10123bfa90b6Smrg{ 10133bfa90b6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 10143bfa90b6Smrg modesettingPtr ms = modesettingPTR(pScrn); 10153bfa90b6Smrg XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL; 10163bfa90b6Smrg XF86VideoAdaptorPtr textured_adapter = NULL, overlay_adaptor = NULL; 10173bfa90b6Smrg int num_adaptors; 10183bfa90b6Smrg 10193bfa90b6Smrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 10203bfa90b6Smrg new_adaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); 10213bfa90b6Smrg if (new_adaptors == NULL) 10223bfa90b6Smrg return; 10233bfa90b6Smrg 10243bfa90b6Smrg memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); 10253bfa90b6Smrg adaptors = new_adaptors; 10263bfa90b6Smrg 10273bfa90b6Smrg /* Add the adaptors supported by our hardware. First, set up the atoms 10283bfa90b6Smrg * that will be used by both output adaptors. 10293bfa90b6Smrg */ 10303bfa90b6Smrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 10313bfa90b6Smrg xvContrast = MAKE_ATOM("XV_CONTRAST"); 10323bfa90b6Smrg xvSaturation = MAKE_ATOM("XV_SATURATION"); 10333bfa90b6Smrg xvHue = MAKE_ATOM("XV_HUE"); 10343bfa90b6Smrg 10353bfa90b6Smrg if (ms->xat) { 10363bfa90b6Smrg textured_adapter = xorg_setup_textured_adapter(pScreen); 10373bfa90b6Smrg if (textured_adapter) 10383bfa90b6Smrg adaptors[num_adaptors++] = textured_adapter; 10393bfa90b6Smrg } else { 10403bfa90b6Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 10413bfa90b6Smrg "No 3D acceleration. Not setting up textured video.\n"); 10423bfa90b6Smrg } 10433bfa90b6Smrg 10443bfa90b6Smrg overlay_adaptor = vmw_video_init_adaptor(pScrn); 10453bfa90b6Smrg if (overlay_adaptor) 10463bfa90b6Smrg adaptors[num_adaptors++] = overlay_adaptor; 10473bfa90b6Smrg 10483bfa90b6Smrg if (num_adaptors) { 104925dbecb6Smrg if (xf86XVScreenInit(pScreen, adaptors, num_adaptors)) { 105025dbecb6Smrg ms->overlay = overlay_adaptor; 105125dbecb6Smrg ms->textured = textured_adapter; 105225dbecb6Smrg } else { 105325dbecb6Smrg ms->overlay = NULL; 105425dbecb6Smrg ms->textured = NULL; 10553bfa90b6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 10563bfa90b6Smrg "Failed to initialize Xv.\n"); 105725dbecb6Smrg } 10583bfa90b6Smrg } else { 10593bfa90b6Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 10603bfa90b6Smrg "Disabling Xv because no adaptors could be initialized.\n"); 10613bfa90b6Smrg } 106225dbecb6Smrg 106325dbecb6Smrg free(new_adaptors); 10643bfa90b6Smrg} 1065