1/* 2 * Copyright 2007 Arthur Huillet 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#include "xorg-config.h" 28#include "xf86xv.h" 29#include <X11/extensions/Xv.h> 30#include "exa.h" 31#include "damage.h" 32#include "dixstruct.h" 33#include "fourcc.h" 34 35#include "nv_include.h" 36#include "nv_dma.h" 37 38extern Atom xvBrightness, xvContrast, xvColorKey, xvSaturation; 39extern Atom xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer; 40extern Atom xvITURBT709, xvSyncToVBlank, xvOnCRTCNb; 41 42/** 43 * NV10PutOverlayImage 44 * program hardware to overlay image into front buffer 45 * 46 * @param pScrn screen 47 * @param offset card offset to the pixel data 48 * @param id format of image 49 * @param dstPitch pitch of the pixel data in VRAM 50 * @param dstBox destination box 51 * @param x1 first source point - x 52 * @param y1 first source point - y 53 * @param x2 second source point - x 54 * @param y2 second source point - y 55 * @param width width of the source image = x2 - x1 56 * @param height height 57 * @param src_w width of the image data in VRAM 58 * @param src_h height 59 * @param drw_w width of the image to draw to screen 60 * @param drw_h height 61 * @param clipBoxes ??? 62 */ 63void 64NV10PutOverlayImage(ScrnInfoPtr pScrn, 65 struct nouveau_bo *src, int offset, int uvoffset, int id, 66 int dstPitch, BoxPtr dstBox, int x1, int y1, int x2, int y2, 67 short width, short height, short src_w, short src_h, 68 short drw_w, short drw_h, RegionPtr clipBoxes) 69{ 70 NVPtr pNv = NVPTR(pScrn); 71 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 72#ifdef NVOVL_SUPPORT 73 int buffer = pPriv->currentBuffer; 74 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 75 xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC]; 76 77 if (crtc->mode.Flags & V_DBLSCAN) { 78 dstBox->y1 <<= 1; 79 dstBox->y2 <<= 1; 80 drw_h <<= 1; 81 } 82 83 /* paint the color key */ 84 if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L || 85 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) { 86 /* we always paint V4L's color key */ 87 if (!pPriv->grabbedByV4L) 88 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 89 { 90 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 91 } 92 } 93 94 //xf86DrvMsg(0, X_INFO, "SIZE_IN h %d w %d, POINT_IN x %d y %d, DS_DX %d DT_DY %d, POINT_OUT x %d y %d SIZE_OUT h %d w %d\n", height, width, x1 >> 95 //16,y1>>16, (src_w << 20) / drw_w, (src_h << 20) / drw_h, (dstBox->x1),(dstBox->y1), (dstBox->y2 - dstBox->y1), (dstBox->x2 - dstBox->x1)); 96 97 nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer) , 0); 98 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer), 99 src->offset + offset); 100 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer) , (height << 16) | width); 101 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) , 102 ((y1 << 4) & 0xffff0000) | (x1 >> 12)); 103 nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer) , (src_w << 20) / drw_w); 104 nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer) , (src_h << 20) / drw_h); 105 nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer), 106 (dstBox->y1 << 16) | dstBox->x1); 107 nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) , 108 ((dstBox->y2 - dstBox->y1) << 16) | 109 (dstBox->x2 - dstBox->x1)); 110 111 dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; /* use color key */ 112 if(id != FOURCC_UYVY) 113 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8; 114 if(pPriv->iturbt_709) 115 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; 116 117 if( id == FOURCC_YV12 || id == FOURCC_I420 ) 118 dstPitch |= NV_PVIDEO_FORMAT_PLANAR; 119 120 /* Those are important only for planar formats (NV12) */ 121 if (uvoffset) { 122 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0); 123 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), 124 src->offset + uvoffset); 125 } 126 127 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch); 128 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0); 129 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1); 130#endif 131 132 pPriv->videoStatus = CLIENT_VIDEO_ON; 133} 134 135/** 136 * NV10SetOverlayPortAttribute 137 * sets the attribute "attribute" of port "data" to value "value" 138 * calls NVResetVideo(pScrn) to apply changes to hardware 139 * 140 * @param pScrenInfo 141 * @param attribute attribute to set 142 * @param value value to which attribute is to be set 143 * @param data port from which the attribute is to be set 144 * 145 * @return Success, if setting is successful 146 * BadValue/BadMatch, if value/attribute are invalid 147 * @see NVResetVideo(ScrnInfoPtr pScrn) 148 */ 149int 150NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute, 151 INT32 value, pointer data) 152{ 153 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 154 155 if (attribute == xvBrightness) { 156 if ((value < -512) || (value > 512)) 157 return BadValue; 158 pPriv->brightness = value; 159 } else 160 if (attribute == xvDoubleBuffer) { 161 if ((value < 0) || (value > 1)) 162 return BadValue; 163 pPriv->doubleBuffer = value; 164 } else 165 if (attribute == xvContrast) { 166 if ((value < 0) || (value > 8191)) 167 return BadValue; 168 pPriv->contrast = value; 169 } else 170 if (attribute == xvHue) { 171 value %= 360; 172 if (value < 0) 173 value += 360; 174 pPriv->hue = value; 175 } else 176 if (attribute == xvSaturation) { 177 if ((value < 0) || (value > 8191)) 178 return BadValue; 179 pPriv->saturation = value; 180 } else 181 if (attribute == xvColorKey) { 182 pPriv->colorKey = value; 183 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 184 } else 185 if (attribute == xvAutopaintColorKey) { 186 if ((value < 0) || (value > 1)) 187 return BadValue; 188 pPriv->autopaintColorKey = value; 189 } else 190 if (attribute == xvITURBT709) { 191 if ((value < 0) || (value > 1)) 192 return BadValue; 193 pPriv->iturbt_709 = value; 194 } else 195 if (attribute == xvSetDefaults) { 196 NVSetPortDefaults(pScrn, pPriv); 197 } else 198#ifdef NVOVL_SUPPORT 199 if ( attribute == xvOnCRTCNb) { 200 NVPtr pNv = NVPTR(pScrn); 201 202 if ((value < 0) || (value > 1)) 203 return BadValue; 204 pPriv->overlayCRTC = value; 205 NVWriteCRTC(pNv, value, NV_PCRTC_ENGINE_CTRL, 206 NVReadCRTC(pNv, value, NV_PCRTC_ENGINE_CTRL) | NV_CRTC_FSEL_OVERLAY); 207 NVWriteCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL, 208 NVReadCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL) & ~NV_CRTC_FSEL_OVERLAY); 209 } else 210#endif 211 return BadMatch; 212 213 NV10WriteOverlayParameters(pScrn); 214 215 return Success; 216} 217 218/** 219 * NV10GetOverlayPortAttribute 220 * 221 * @param pScrn unused 222 * @param attribute attribute to be read 223 * @param value value of attribute will be stored in this pointer 224 * @param data port from which attribute will be read 225 * @return Success, if queried attribute exists 226 */ 227int 228NV10GetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute, 229 INT32 *value, pointer data) 230{ 231 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 232 233 if (attribute == xvBrightness) 234 *value = pPriv->brightness; 235 else if (attribute == xvDoubleBuffer) 236 *value = (pPriv->doubleBuffer) ? 1 : 0; 237 else if (attribute == xvContrast) 238 *value = pPriv->contrast; 239 else if (attribute == xvSaturation) 240 *value = pPriv->saturation; 241 else if (attribute == xvHue) 242 *value = pPriv->hue; 243 else if (attribute == xvColorKey) 244 *value = pPriv->colorKey; 245 else if (attribute == xvAutopaintColorKey) 246 *value = (pPriv->autopaintColorKey) ? 1 : 0; 247 else if (attribute == xvITURBT709) 248 *value = (pPriv->iturbt_709) ? 1 : 0; 249 else if (attribute == xvOnCRTCNb) 250 *value = (pPriv->overlayCRTC) ? 1 : 0; 251 else 252 return BadMatch; 253 254 return Success; 255} 256 257/** 258 * NV10StopOverlay 259 * Tell the hardware to stop the overlay 260 */ 261void 262NV10StopOverlay (ScrnInfoPtr pScrn) 263{ 264#ifdef NVOVL_SUPPORT 265 NVPtr pNv = NVPTR(pScrn); 266 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1); 267#endif 268} 269 270/** 271 * NV10WriteOverlayParameters 272 * Tell the hardware about parameters that are too expensive to be set 273 * on every frame 274 */ 275void 276NV10WriteOverlayParameters (ScrnInfoPtr pScrn) 277{ 278 NVPtr pNv = NVPTR(pScrn); 279 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 280 int satSine, satCosine; 281 double angle; 282 283 angle = (double)pPriv->hue * 3.1415927 / 180.0; 284 285 satSine = pPriv->saturation * sin(angle); 286 if (satSine < -1024) 287 satSine = -1024; 288 satCosine = pPriv->saturation * cos(angle); 289 if (satCosine < -1024) 290 satCosine = -1024; 291 292#ifdef NVOVL_SUPPORT 293 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) | 294 pPriv->contrast); 295 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) | 296 pPriv->contrast); 297 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) | 298 (satCosine & 0xffff)); 299 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) | 300 (satCosine & 0xffff)); 301 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey); 302#endif 303} 304 305