1fda9279dSmrg/* 2fda9279dSmrg * Copyright 2007 Arthur Huillet 3fda9279dSmrg * 4fda9279dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5fda9279dSmrg * copy of this software and associated documentation files (the "Software"), 6fda9279dSmrg * to deal in the Software without restriction, including without limitation 7fda9279dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8fda9279dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9fda9279dSmrg * Software is furnished to do so, subject to the following conditions: 10fda9279dSmrg * 11fda9279dSmrg * The above copyright notice and this permission notice shall be included in 12fda9279dSmrg * all copies or substantial portions of the Software. 13fda9279dSmrg * 14fda9279dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15fda9279dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16fda9279dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17fda9279dSmrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18fda9279dSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19fda9279dSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20fda9279dSmrg * SOFTWARE. 21fda9279dSmrg */ 22fda9279dSmrg 23fda9279dSmrg 24fda9279dSmrg#ifdef HAVE_CONFIG_H 25fda9279dSmrg#include "config.h" 26fda9279dSmrg#endif 27fda9279dSmrg 28fda9279dSmrg#ifdef __SSE2__ 29fda9279dSmrg#include <immintrin.h> 30fda9279dSmrg#endif 31fda9279dSmrg 32479f40c1Smrg#include "xorg-config.h" 33fda9279dSmrg#include "xf86xv.h" 34fda9279dSmrg#include <X11/extensions/Xv.h> 35fda9279dSmrg#include "exa.h" 36fda9279dSmrg#include "damage.h" 37fda9279dSmrg#include "dixstruct.h" 38fda9279dSmrg#include "fourcc.h" 39fda9279dSmrg 40fda9279dSmrg#include "nv_include.h" 41fda9279dSmrg#include "nv_dma.h" 42fda9279dSmrg 43fda9279dSmrg#include "vl_hwmc.h" 44fda9279dSmrg 45fda9279dSmrg#include "hwdefs/nv_m2mf.xml.h" 46fda9279dSmrg 47fda9279dSmrg#define IMAGE_MAX_W 2046 48fda9279dSmrg#define IMAGE_MAX_H 2046 49fda9279dSmrg 50fda9279dSmrg#define TEX_IMAGE_MAX_W 4096 51fda9279dSmrg#define TEX_IMAGE_MAX_H 4096 52fda9279dSmrg 53fda9279dSmrg#define OFF_DELAY 500 /* milliseconds */ 54fda9279dSmrg#define FREE_DELAY 5000 55fda9279dSmrg 56fda9279dSmrg#define NUM_BLIT_PORTS 16 57fda9279dSmrg#define NUM_TEXTURE_PORTS 32 58fda9279dSmrg 59fda9279dSmrg 60fda9279dSmrg#define NVStopOverlay(X) (((pNv->Architecture == NV_ARCH_04) ? NV04StopOverlay(X) : NV10StopOverlay(X))) 61fda9279dSmrg 62fda9279dSmrg/* Value taken by pPriv -> currentHostBuffer when we failed to allocate the two private buffers in TT memory, so that we can catch this case 63fda9279dSmrgand attempt no other allocation afterwards (performance reasons) */ 64fda9279dSmrg#define NO_PRIV_HOST_BUFFER_AVAILABLE 9999 65fda9279dSmrg 66fda9279dSmrg/* NVPutImage action flags */ 67fda9279dSmrgenum { 68fda9279dSmrg IS_YV12 = 1, 69fda9279dSmrg IS_YUY2 = 2, 70fda9279dSmrg CONVERT_TO_YUY2=4, 71fda9279dSmrg USE_OVERLAY=8, 72fda9279dSmrg USE_TEXTURE=16, 73fda9279dSmrg SWAP_UV=32, 74fda9279dSmrg IS_RGB=64, //I am not sure how long we will support it 75fda9279dSmrg}; 76fda9279dSmrg 77fda9279dSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 78fda9279dSmrg 79fda9279dSmrgAtom xvBrightness, xvContrast, xvColorKey, xvSaturation; 80fda9279dSmrgAtom xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer; 81fda9279dSmrgAtom xvITURBT709, xvSyncToVBlank, xvOnCRTCNb; 82fda9279dSmrg 83fda9279dSmrg/* client libraries expect an encoding */ 84fda9279dSmrgstatic XF86VideoEncodingRec DummyEncoding = 85fda9279dSmrg{ 86fda9279dSmrg 0, 87fda9279dSmrg "XV_IMAGE", 88fda9279dSmrg IMAGE_MAX_W, IMAGE_MAX_H, 89fda9279dSmrg {1, 1} 90fda9279dSmrg}; 91fda9279dSmrg 92fda9279dSmrgstatic XF86VideoEncodingRec DummyEncodingTex = 93fda9279dSmrg{ 94fda9279dSmrg 0, 95fda9279dSmrg "XV_IMAGE", 96fda9279dSmrg TEX_IMAGE_MAX_W, TEX_IMAGE_MAX_H, 97fda9279dSmrg {1, 1} 98fda9279dSmrg}; 99fda9279dSmrg 100fda9279dSmrgstatic XF86VideoEncodingRec DummyEncodingNV50 = 101fda9279dSmrg{ 102fda9279dSmrg 0, 103fda9279dSmrg "XV_IMAGE", 104fda9279dSmrg 8192, 8192, 105fda9279dSmrg {1, 1} 106fda9279dSmrg}; 107fda9279dSmrg 108fda9279dSmrg#define NUM_FORMATS_ALL 6 109fda9279dSmrg 110fda9279dSmrgXF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] = 111fda9279dSmrg{ 112fda9279dSmrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, 113fda9279dSmrg {15, DirectColor}, {16, DirectColor}, {24, DirectColor} 114fda9279dSmrg}; 115fda9279dSmrg 11622d74663Smrg#define NUM_FORMATS_NV50 8 11722d74663SmrgXF86VideoFormatRec NV50Formats[NUM_FORMATS_NV50] = 11822d74663Smrg{ 11922d74663Smrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, {30, TrueColor}, 12022d74663Smrg {15, DirectColor}, {16, DirectColor}, {24, DirectColor}, {30, DirectColor} 12122d74663Smrg}; 12222d74663Smrg 123fda9279dSmrg#define NUM_NV04_OVERLAY_ATTRIBUTES 4 124fda9279dSmrgXF86AttributeRec NV04OverlayAttributes[NUM_NV04_OVERLAY_ATTRIBUTES] = 125fda9279dSmrg{ 126fda9279dSmrg {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"}, 127fda9279dSmrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 128fda9279dSmrg {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, 129fda9279dSmrg {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, 130fda9279dSmrg}; 131fda9279dSmrg 132fda9279dSmrg 133fda9279dSmrg#define NUM_NV10_OVERLAY_ATTRIBUTES 10 134fda9279dSmrgXF86AttributeRec NV10OverlayAttributes[NUM_NV10_OVERLAY_ATTRIBUTES] = 135fda9279dSmrg{ 136fda9279dSmrg {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, 137fda9279dSmrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 138fda9279dSmrg {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, 139fda9279dSmrg {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, 140fda9279dSmrg {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"}, 141fda9279dSmrg {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"}, 142fda9279dSmrg {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"}, 143fda9279dSmrg {XvSettable | XvGettable, 0, 360, "XV_HUE"}, 144fda9279dSmrg {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}, 145fda9279dSmrg {XvSettable | XvGettable, 0, 1, "XV_ON_CRTC_NB"}, 146fda9279dSmrg}; 147fda9279dSmrg 148fda9279dSmrg#define NUM_BLIT_ATTRIBUTES 2 149fda9279dSmrgXF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] = 150fda9279dSmrg{ 151fda9279dSmrg {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, 152fda9279dSmrg {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"} 153fda9279dSmrg}; 154fda9279dSmrg 155fda9279dSmrg#define NUM_TEXTURED_ATTRIBUTES 2 156fda9279dSmrgXF86AttributeRec NVTexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = 157fda9279dSmrg{ 158fda9279dSmrg {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, 159fda9279dSmrg {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"} 160fda9279dSmrg}; 161fda9279dSmrg 162fda9279dSmrg#define NUM_TEXTURED_ATTRIBUTES_NV50 7 163fda9279dSmrgXF86AttributeRec NVTexturedAttributesNV50[NUM_TEXTURED_ATTRIBUTES_NV50] = 164fda9279dSmrg{ 165fda9279dSmrg { XvSettable , 0, 0, "XV_SET_DEFAULTS" }, 166fda9279dSmrg { XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK" }, 167fda9279dSmrg { XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS" }, 168fda9279dSmrg { XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST" }, 169fda9279dSmrg { XvSettable | XvGettable, -1000, 1000, "XV_SATURATION" }, 170fda9279dSmrg { XvSettable | XvGettable, -1000, 1000, "XV_HUE" }, 171fda9279dSmrg { XvSettable | XvGettable, 0, 1, "XV_ITURBT_709" } 172fda9279dSmrg}; 173fda9279dSmrg 174fda9279dSmrg#define NUM_IMAGES_YUV 4 175fda9279dSmrg#define NUM_IMAGES_ALL 5 176fda9279dSmrg 177fda9279dSmrg#define FOURCC_RGB 0x0000003 178fda9279dSmrg#define XVIMAGE_RGB \ 179fda9279dSmrg { \ 180fda9279dSmrg FOURCC_RGB, \ 181fda9279dSmrg XvRGB, \ 182fda9279dSmrg LSBFirst, \ 183fda9279dSmrg { 0x03, 0x00, 0x00, 0x00, \ 184fda9279dSmrg 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ 185fda9279dSmrg 32, \ 186fda9279dSmrg XvPacked, \ 187fda9279dSmrg 1, \ 188fda9279dSmrg 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \ 189fda9279dSmrg 0, 0, 0, \ 190fda9279dSmrg 0, 0, 0, \ 191fda9279dSmrg 0, 0, 0, \ 192fda9279dSmrg {'B','G','R','X',\ 193fda9279dSmrg 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ 194fda9279dSmrg XvTopToBottom \ 195fda9279dSmrg } 196fda9279dSmrg 197fda9279dSmrgstatic XF86ImageRec NVImages[NUM_IMAGES_ALL] = 198fda9279dSmrg{ 199fda9279dSmrg XVIMAGE_YUY2, 200fda9279dSmrg XVIMAGE_YV12, 201fda9279dSmrg XVIMAGE_UYVY, 202fda9279dSmrg XVIMAGE_I420, 203fda9279dSmrg XVIMAGE_RGB 204fda9279dSmrg}; 205fda9279dSmrg 206fda9279dSmrgstatic void 207a5560a61Smrgbox_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) 208fda9279dSmrg{ 209a5560a61Smrg dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; 210a5560a61Smrg dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; 211a5560a61Smrg if (dest->x1 >= dest->x2) { 212a5560a61Smrg dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; 213a5560a61Smrg return; 214a5560a61Smrg } 215a5560a61Smrg 216a5560a61Smrg dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; 217a5560a61Smrg dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; 218a5560a61Smrg if (dest->y1 >= dest->y2) 219a5560a61Smrg dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; 220a5560a61Smrg} 221fda9279dSmrg 222a5560a61Smrgstatic int 223a5560a61Smrgbox_area(BoxPtr box) 224a5560a61Smrg{ 225a5560a61Smrg return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); 226fda9279dSmrg} 227fda9279dSmrg 228fda9279dSmrgstatic void 229a5560a61Smrgrr_crtc_box(RRCrtcPtr crtc, BoxPtr crtc_box) 230fda9279dSmrg{ 231a5560a61Smrg if (crtc->mode) { 232a5560a61Smrg crtc_box->x1 = crtc->x; 233a5560a61Smrg crtc_box->y1 = crtc->y; 234a5560a61Smrg switch (crtc->rotation) { 235a5560a61Smrg case RR_Rotate_0: 236a5560a61Smrg case RR_Rotate_180: 237a5560a61Smrg default: 238a5560a61Smrg crtc_box->x2 = crtc->x + crtc->mode->mode.width; 239a5560a61Smrg crtc_box->y2 = crtc->y + crtc->mode->mode.height; 240a5560a61Smrg break; 241a5560a61Smrg case RR_Rotate_90: 242a5560a61Smrg case RR_Rotate_270: 243a5560a61Smrg crtc_box->x2 = crtc->x + crtc->mode->mode.height; 244a5560a61Smrg crtc_box->y2 = crtc->y + crtc->mode->mode.width; 245a5560a61Smrg break; 246a5560a61Smrg } 247a5560a61Smrg } else 248a5560a61Smrg crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; 249fda9279dSmrg} 250fda9279dSmrg 251a5560a61Smrgstatic Bool 252a5560a61Smrgrr_crtc_on(RRCrtcPtr crtc, Bool crtc_is_xf86_hint) 253fda9279dSmrg{ 254a5560a61Smrg if (!crtc) { 255a5560a61Smrg return FALSE; 256a5560a61Smrg } 257a5560a61Smrg if (crtc_is_xf86_hint && crtc->devPrivate) { 258a5560a61Smrg return xf86_crtc_on(crtc->devPrivate); 259a5560a61Smrg } else { 260a5560a61Smrg return !!crtc->mode; 261a5560a61Smrg } 262a5560a61Smrg} 263a5560a61Smrg 264a5560a61Smrg/* 265a5560a61Smrg * Return the crtc covering 'box'. If two crtcs cover a portion of 266a5560a61Smrg * 'box', then prefer the crtc with greater coverage. 267a5560a61Smrg */ 268a5560a61Smrgstatic RRCrtcPtr 269a5560a61Smrgrr_crtc_covering_box(ScreenPtr pScreen, BoxPtr box, Bool screen_is_xf86_hint) 270a5560a61Smrg{ 271a5560a61Smrg rrScrPrivPtr pScrPriv; 272a5560a61Smrg RRCrtcPtr crtc, best_crtc, primary_crtc; 273a5560a61Smrg int coverage, best_coverage; 274a5560a61Smrg int c; 275a5560a61Smrg BoxRec crtc_box, cover_box; 276a5560a61Smrg RROutputPtr primary_output; 277a5560a61Smrg 278a5560a61Smrg best_crtc = NULL; 279a5560a61Smrg best_coverage = 0; 280a5560a61Smrg primary_crtc = NULL; 281a5560a61Smrg primary_output = NULL; 282a5560a61Smrg 283a5560a61Smrg if (!dixPrivateKeyRegistered(rrPrivKey)) 284a5560a61Smrg return NULL; 285a5560a61Smrg 286a5560a61Smrg pScrPriv = rrGetScrPriv(pScreen); 287a5560a61Smrg 288a5560a61Smrg if (!pScrPriv) 289a5560a61Smrg return NULL; 290a5560a61Smrg 291a5560a61Smrg primary_output = RRFirstOutput(pScreen); 292a5560a61Smrg if (primary_output && primary_output->crtc) 293a5560a61Smrg primary_crtc = primary_output->crtc->devPrivate; 294a5560a61Smrg 295a5560a61Smrg for (c = 0; c < pScrPriv->numCrtcs; c++) { 296a5560a61Smrg crtc = pScrPriv->crtcs[c]; 297a5560a61Smrg 298a5560a61Smrg /* If the CRTC is off, treat it as not covering */ 299a5560a61Smrg if (!rr_crtc_on(crtc, screen_is_xf86_hint)) 300a5560a61Smrg continue; 301a5560a61Smrg 302a5560a61Smrg rr_crtc_box(crtc, &crtc_box); 303a5560a61Smrg box_intersect(&cover_box, &crtc_box, box); 304a5560a61Smrg coverage = box_area(&cover_box); 305a5560a61Smrg if (coverage > best_coverage || 306a5560a61Smrg (crtc == primary_crtc && coverage == best_coverage)) { 307a5560a61Smrg best_crtc = crtc; 308a5560a61Smrg best_coverage = coverage; 309a5560a61Smrg } 310a5560a61Smrg } 311a5560a61Smrg 312a5560a61Smrg return best_crtc; 313a5560a61Smrg} 314a5560a61Smrg 315a5560a61Smrg#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0) 316a5560a61Smrgstatic RRCrtcPtr 317a5560a61Smrgrr_crtc_covering_box_on_secondary(ScreenPtr pScreen, BoxPtr box) 318a5560a61Smrg{ 319a5560a61Smrg if (!pScreen->isGPU) { 320a5560a61Smrg ScreenPtr secondary; 321a5560a61Smrg RRCrtcPtr crtc = NULL; 322a5560a61Smrg 323a5560a61Smrg xorg_list_for_each_entry(secondary, &pScreen->secondary_list, secondary_head) { 324a5560a61Smrg if (!secondary->is_output_secondary) 325a5560a61Smrg continue; 326a5560a61Smrg 327a5560a61Smrg crtc = rr_crtc_covering_box(secondary, box, FALSE); 328a5560a61Smrg if (crtc) 329a5560a61Smrg return crtc; 330a5560a61Smrg } 331a5560a61Smrg } 332a5560a61Smrg 333a5560a61Smrg return NULL; 334a5560a61Smrg} 335a5560a61Smrg#endif 336a5560a61Smrg 337a5560a61SmrgRRCrtcPtr 338a5560a61Smrgrandr_crtc_covering_drawable(DrawablePtr pDraw) 339a5560a61Smrg{ 340a5560a61Smrg ScreenPtr pScreen = pDraw->pScreen; 341a5560a61Smrg RRCrtcPtr crtc = NULL; 342a5560a61Smrg BoxRec box; 343a5560a61Smrg 344a5560a61Smrg box.x1 = pDraw->x; 345a5560a61Smrg box.y1 = pDraw->y; 346a5560a61Smrg box.x2 = box.x1 + pDraw->width; 347a5560a61Smrg box.y2 = box.y1 + pDraw->height; 348a5560a61Smrg 349a5560a61Smrg crtc = rr_crtc_covering_box(pScreen, &box, TRUE); 350a5560a61Smrg#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0) 351a5560a61Smrg if (!crtc) { 352a5560a61Smrg crtc = rr_crtc_covering_box_on_secondary(pScreen, &box); 353a5560a61Smrg } 354a5560a61Smrg#endif 355a5560a61Smrg return crtc; 356fda9279dSmrg} 357fda9279dSmrg 358fda9279dSmrgxf86CrtcPtr 359a5560a61Smrgnouveau_pick_best_crtc(ScrnInfoPtr pScrn, 360fda9279dSmrg int x, int y, int w, int h) 361fda9279dSmrg{ 362a5560a61Smrg ScreenPtr pScreen = pScrn->pScreen; 363a5560a61Smrg RRCrtcPtr crtc = NULL; 364a5560a61Smrg BoxRec box; 365fda9279dSmrg 366fda9279dSmrg if (!pScrn->vtSema) 367fda9279dSmrg return NULL; 368fda9279dSmrg 369fda9279dSmrg box.x1 = x; 370fda9279dSmrg box.x2 = x + w; 371fda9279dSmrg box.y1 = y; 372fda9279dSmrg box.y2 = y + h; 373fda9279dSmrg 374a5560a61Smrg crtc = rr_crtc_covering_box(pScreen, &box, TRUE); 375a5560a61Smrg if (crtc) { 376a5560a61Smrg return crtc->devPrivate; 377fda9279dSmrg } 378a5560a61Smrg return NULL; 379fda9279dSmrg} 380fda9279dSmrg 381fda9279dSmrgunsigned int 382fda9279dSmrgnv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h) 383fda9279dSmrg{ 384fda9279dSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 385fda9279dSmrg unsigned int mask = 0; 386fda9279dSmrg int i; 387fda9279dSmrg 388fda9279dSmrg for (i = 0; i < xf86_config->num_crtc; i++) { 389fda9279dSmrg xf86CrtcPtr crtc = xf86_config->crtc[i]; 390fda9279dSmrg 391a5560a61Smrg if (!xf86_crtc_on(crtc)) 392fda9279dSmrg continue; 393fda9279dSmrg 394fda9279dSmrg if ((x < (crtc->x + crtc->mode.HDisplay)) && 395fda9279dSmrg (y < (crtc->y + crtc->mode.VDisplay)) && 396fda9279dSmrg ((x + w) > crtc->x) && 397fda9279dSmrg ((y + h) > crtc->y)) 398fda9279dSmrg mask |= 1 << i; 399fda9279dSmrg } 400fda9279dSmrg 401fda9279dSmrg return mask; 402fda9279dSmrg} 403fda9279dSmrg 404fda9279dSmrg/** 405fda9279dSmrg * NVSetPortDefaults 406fda9279dSmrg * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults 407fda9279dSmrg * this function does not care about the kind of adapter the port is for 408fda9279dSmrg * 409fda9279dSmrg * @param pScrn screen to get the default colorKey from 410fda9279dSmrg * @param pPriv port to reset to defaults 411fda9279dSmrg */ 412fda9279dSmrgvoid 413fda9279dSmrgNVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv) 414fda9279dSmrg{ 415fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 416fda9279dSmrg 417fda9279dSmrg pPriv->brightness = 0; 418fda9279dSmrg pPriv->contrast = 4096; 419fda9279dSmrg pPriv->saturation = 4096; 420fda9279dSmrg pPriv->hue = 0; 421fda9279dSmrg pPriv->colorKey = pNv->videoKey; 422fda9279dSmrg pPriv->autopaintColorKey = TRUE; 423fda9279dSmrg pPriv->doubleBuffer = pNv->Architecture != NV_ARCH_04; 424fda9279dSmrg pPriv->iturbt_709 = FALSE; 425fda9279dSmrg pPriv->currentHostBuffer = 0; 426fda9279dSmrg} 427fda9279dSmrg 428fda9279dSmrgstatic int 429fda9279dSmrgnouveau_xv_bo_realloc(ScrnInfoPtr pScrn, unsigned flags, unsigned size, 430fda9279dSmrg struct nouveau_bo **pbo) 431fda9279dSmrg{ 432fda9279dSmrg union nouveau_bo_config config = {}; 433fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 434fda9279dSmrg 435fda9279dSmrg if (*pbo) { 436fda9279dSmrg if ((*pbo)->size >= size) 437fda9279dSmrg return 0; 438fda9279dSmrg nouveau_bo_ref(NULL, pbo); 439fda9279dSmrg } 440fda9279dSmrg 441fda9279dSmrg if (flags & NOUVEAU_BO_VRAM) { 442fda9279dSmrg if (pNv->Architecture == NV_TESLA) 443fda9279dSmrg config.nv50.memtype = 0x70; 444fda9279dSmrg else 445fda9279dSmrg if (pNv->Architecture >= NV_FERMI) 446fda9279dSmrg config.nvc0.memtype = 0xfe; 447fda9279dSmrg } 448fda9279dSmrg flags |= NOUVEAU_BO_MAP; 449fda9279dSmrg 450fda9279dSmrg return nouveau_bo_new(pNv->dev, flags, 0, size, &config, pbo); 451fda9279dSmrg} 452fda9279dSmrg 453fda9279dSmrg/** 454fda9279dSmrg * NVFreePortMemory 455fda9279dSmrg * frees memory held by a given port 456fda9279dSmrg * 457fda9279dSmrg * @param pScrn screen whose port wants to free memory 458fda9279dSmrg * @param pPriv port to free memory of 459fda9279dSmrg */ 460fda9279dSmrgstatic void 461fda9279dSmrgNVFreePortMemory(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv) 462fda9279dSmrg{ 463fda9279dSmrg nouveau_bo_ref(NULL, &pPriv->video_mem); 464fda9279dSmrg nouveau_bo_ref(NULL, &pPriv->TT_mem_chunk[0]); 465fda9279dSmrg nouveau_bo_ref(NULL, &pPriv->TT_mem_chunk[1]); 466fda9279dSmrg} 467fda9279dSmrg 468fda9279dSmrg/** 469fda9279dSmrg * NVFreeOverlayMemory 470fda9279dSmrg * frees memory held by the overlay port 471fda9279dSmrg * 472fda9279dSmrg * @param pScrn screen whose overlay port wants to free memory 473fda9279dSmrg */ 474fda9279dSmrgstatic void 475fda9279dSmrgNVFreeOverlayMemory(ScrnInfoPtr pScrn) 476fda9279dSmrg{ 477fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 478fda9279dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 479fda9279dSmrg 480fda9279dSmrg NVFreePortMemory(pScrn, pPriv); 481fda9279dSmrg#if NVOVL_SUPPORT 482fda9279dSmrg /* "power cycle" the overlay */ 483fda9279dSmrg nvWriteMC(pNv, NV_PMC_ENABLE, 484fda9279dSmrg (nvReadMC(pNv, NV_PMC_ENABLE) & 0xEFFFFFFF)); 485fda9279dSmrg nvWriteMC(pNv, NV_PMC_ENABLE, 486fda9279dSmrg (nvReadMC(pNv, NV_PMC_ENABLE) | 0x10000000)); 487fda9279dSmrg#endif 488fda9279dSmrg} 489fda9279dSmrg 490fda9279dSmrg/** 491fda9279dSmrg * NVFreeBlitMemory 492fda9279dSmrg * frees memory held by the blit port 493fda9279dSmrg * 494fda9279dSmrg * @param pScrn screen whose blit port wants to free memory 495fda9279dSmrg */ 496fda9279dSmrgstatic void 497fda9279dSmrgNVFreeBlitMemory(ScrnInfoPtr pScrn) 498fda9279dSmrg{ 499fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 500fda9279dSmrg NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv); 501fda9279dSmrg 502fda9279dSmrg NVFreePortMemory(pScrn, pPriv); 503fda9279dSmrg} 504fda9279dSmrg 505fda9279dSmrg/** 506fda9279dSmrg * NVVideoTimerCallback 507fda9279dSmrg * callback function which perform cleanup tasks (stop overlay, free memory). 508fda9279dSmrg * within the driver 509fda9279dSmrg * purpose and use is unknown 510fda9279dSmrg */ 511fda9279dSmrgvoid 512fda9279dSmrgNVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime) 513fda9279dSmrg{ 514fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 515fda9279dSmrg NVPortPrivPtr pOverPriv = NULL; 516fda9279dSmrg NVPortPrivPtr pBlitPriv = NULL; 517fda9279dSmrg Bool needCallback = FALSE; 518fda9279dSmrg 519fda9279dSmrg if (!pScrn->vtSema) 520fda9279dSmrg return; 521fda9279dSmrg 522fda9279dSmrg if (pNv->overlayAdaptor) { 523fda9279dSmrg pOverPriv = GET_OVERLAY_PRIVATE(pNv); 524fda9279dSmrg if (!pOverPriv->videoStatus) 525fda9279dSmrg pOverPriv = NULL; 526fda9279dSmrg } 527fda9279dSmrg 528fda9279dSmrg if (pNv->blitAdaptor) { 529fda9279dSmrg pBlitPriv = GET_BLIT_PRIVATE(pNv); 530fda9279dSmrg if (!pBlitPriv->videoStatus) 531fda9279dSmrg pBlitPriv = NULL; 532fda9279dSmrg } 533fda9279dSmrg 534fda9279dSmrg if (pOverPriv) { 535fda9279dSmrg if (pOverPriv->videoTime < currentTime) { 536fda9279dSmrg if (pOverPriv->videoStatus & OFF_TIMER) { 537fda9279dSmrg NVStopOverlay(pScrn); 538fda9279dSmrg pOverPriv->videoStatus = FREE_TIMER; 539fda9279dSmrg pOverPriv->videoTime = currentTime + FREE_DELAY; 540fda9279dSmrg needCallback = TRUE; 541fda9279dSmrg } else 542fda9279dSmrg if (pOverPriv->videoStatus & FREE_TIMER) { 543fda9279dSmrg NVFreeOverlayMemory(pScrn); 544fda9279dSmrg pOverPriv->videoStatus = 0; 545fda9279dSmrg } 546fda9279dSmrg } else { 547fda9279dSmrg needCallback = TRUE; 548fda9279dSmrg } 549fda9279dSmrg } 550fda9279dSmrg 551fda9279dSmrg if (pBlitPriv) { 552fda9279dSmrg if (pBlitPriv->videoTime < currentTime) { 553fda9279dSmrg NVFreeBlitMemory(pScrn); 554fda9279dSmrg pBlitPriv->videoStatus = 0; 555fda9279dSmrg } else { 556fda9279dSmrg needCallback = TRUE; 557fda9279dSmrg } 558fda9279dSmrg } 559fda9279dSmrg 560fda9279dSmrg pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL; 561fda9279dSmrg} 562fda9279dSmrg 563fda9279dSmrg#ifndef ExaOffscreenMarkUsed 564fda9279dSmrgextern void ExaOffscreenMarkUsed(PixmapPtr); 565fda9279dSmrg#endif 566fda9279dSmrg 567fda9279dSmrg/* 568fda9279dSmrg * StopVideo 569fda9279dSmrg */ 570fda9279dSmrgstatic void 571fda9279dSmrgNVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit) 572fda9279dSmrg{ 573fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 574fda9279dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 575fda9279dSmrg 576fda9279dSmrg if (pPriv->grabbedByV4L) 577fda9279dSmrg return; 578fda9279dSmrg 579fda9279dSmrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 580fda9279dSmrg 581fda9279dSmrg if(Exit) { 582fda9279dSmrg if (pPriv->videoStatus & CLIENT_VIDEO_ON) 583fda9279dSmrg NVStopOverlay(pScrn); 584fda9279dSmrg NVFreeOverlayMemory(pScrn); 585fda9279dSmrg pPriv->videoStatus = 0; 586fda9279dSmrg } else { 587fda9279dSmrg if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 588fda9279dSmrg pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; 589fda9279dSmrg pPriv->videoTime = currentTime.milliseconds + OFF_DELAY; 590fda9279dSmrg pNv->VideoTimerCallback = NVVideoTimerCallback; 591fda9279dSmrg } 592fda9279dSmrg } 593fda9279dSmrg} 594fda9279dSmrg 595fda9279dSmrg/** 596fda9279dSmrg * QueryBestSize 597fda9279dSmrg * used by client applications to ask the driver: 598fda9279dSmrg * how would you actually scale a video of dimensions 599fda9279dSmrg * vid_w, vid_h, if i wanted you to scale it to dimensions 600fda9279dSmrg * drw_w, drw_h? 601fda9279dSmrg * function stores actual scaling size in pointers p_w, p_h. 602fda9279dSmrg * 603fda9279dSmrg * 604fda9279dSmrg * @param pScrn unused 605fda9279dSmrg * @param motion unused 606fda9279dSmrg * @param vid_w width of source video 607fda9279dSmrg * @param vid_h height of source video 608fda9279dSmrg * @param drw_w desired scaled width as requested by client 609fda9279dSmrg * @param drw_h desired scaled height as requested by client 610fda9279dSmrg * @param p_w actual scaled width as the driver is capable of 611fda9279dSmrg * @param p_h actual scaled height as the driver is capable of 612fda9279dSmrg * @param data unused 613fda9279dSmrg */ 614fda9279dSmrgstatic void 615fda9279dSmrgNVQueryBestSize(ScrnInfoPtr pScrn, Bool motion, 616fda9279dSmrg short vid_w, short vid_h, 617fda9279dSmrg short drw_w, short drw_h, 618fda9279dSmrg unsigned int *p_w, unsigned int *p_h, 619fda9279dSmrg pointer data) 620fda9279dSmrg{ 621fda9279dSmrg if(vid_w > (drw_w << 3)) 622fda9279dSmrg drw_w = vid_w >> 3; 623fda9279dSmrg if(vid_h > (drw_h << 3)) 624fda9279dSmrg drw_h = vid_h >> 3; 625fda9279dSmrg 626fda9279dSmrg *p_w = drw_w; 627fda9279dSmrg *p_h = drw_h; 628fda9279dSmrg} 629fda9279dSmrg 630fda9279dSmrg/** 631fda9279dSmrg * NVCopyData420 632fda9279dSmrg * used to convert YV12 to YUY2 for the blitter and NV04 overlay. 633fda9279dSmrg * The U and V samples generated are linearly interpolated on the vertical 634fda9279dSmrg * axis for better quality 635fda9279dSmrg * 636fda9279dSmrg * @param src1 source buffer of luma 637fda9279dSmrg * @param src2 source buffer of chroma1 638fda9279dSmrg * @param src3 source buffer of chroma2 639fda9279dSmrg * @param dst1 destination buffer 640fda9279dSmrg * @param srcPitch pitch of src1 641fda9279dSmrg * @param srcPitch2 pitch of src2, src3 642fda9279dSmrg * @param dstPitch pitch of dst1 643fda9279dSmrg * @param h number of lines to copy 644fda9279dSmrg * @param w length of lines to copy 645fda9279dSmrg */ 646fda9279dSmrgstatic inline void 647fda9279dSmrgNVCopyData420(unsigned char *src1, unsigned char *src2, unsigned char *src3, 648fda9279dSmrg unsigned char *dst1, int srcPitch, int srcPitch2, int dstPitch, 649fda9279dSmrg int h, int w) 650fda9279dSmrg{ 651fda9279dSmrg CARD32 *dst; 652fda9279dSmrg CARD8 *s1, *s2, *s3; 653fda9279dSmrg int i, j; 654fda9279dSmrg 655fda9279dSmrg#define su(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s2[X] + \ 656fda9279dSmrg (signed int)(s2 + srcPitch2)[X]) / 2) : (s2[X])) 657fda9279dSmrg#define sv(X) (((j & 1) && j < (h-1)) ? ((unsigned)((signed int)s3[X] + \ 658fda9279dSmrg (signed int)(s3 + srcPitch2)[X]) / 2) : (s3[X])) 659fda9279dSmrg 660fda9279dSmrg w >>= 1; 661fda9279dSmrg 662fda9279dSmrg for (j = 0; j < h; j++) { 663fda9279dSmrg dst = (CARD32*)dst1; 664fda9279dSmrg s1 = src1; s2 = src2; s3 = src3; 665fda9279dSmrg i = w; 666fda9279dSmrg 667fda9279dSmrg while (i > 4) { 668fda9279dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 669fda9279dSmrg dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0); 670fda9279dSmrg dst[1] = (s1[2] << 24) | (s1[3] << 8) | (sv(1) << 16) | su(1); 671fda9279dSmrg dst[2] = (s1[4] << 24) | (s1[5] << 8) | (sv(2) << 16) | su(2); 672fda9279dSmrg dst[3] = (s1[6] << 24) | (s1[7] << 8) | (sv(3) << 16) | su(3); 673fda9279dSmrg#else 674fda9279dSmrg dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24); 675fda9279dSmrg dst[1] = s1[2] | (s1[3] << 16) | (sv(1) << 8) | (su(1) << 24); 676fda9279dSmrg dst[2] = s1[4] | (s1[5] << 16) | (sv(2) << 8) | (su(2) << 24); 677fda9279dSmrg dst[3] = s1[6] | (s1[7] << 16) | (sv(3) << 8) | (su(3) << 24); 678fda9279dSmrg#endif 679fda9279dSmrg dst += 4; s2 += 4; s3 += 4; s1 += 8; 680fda9279dSmrg i -= 4; 681fda9279dSmrg } 682fda9279dSmrg 683fda9279dSmrg while (i--) { 684fda9279dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 685fda9279dSmrg dst[0] = (s1[0] << 24) | (s1[1] << 8) | (sv(0) << 16) | su(0); 686fda9279dSmrg#else 687fda9279dSmrg dst[0] = s1[0] | (s1[1] << 16) | (sv(0) << 8) | (su(0) << 24); 688fda9279dSmrg#endif 689fda9279dSmrg dst++; s2++; s3++; 690fda9279dSmrg s1 += 2; 691fda9279dSmrg } 692fda9279dSmrg 693fda9279dSmrg dst1 += dstPitch; 694fda9279dSmrg src1 += srcPitch; 695fda9279dSmrg if (j & 1) { 696fda9279dSmrg src2 += srcPitch2; 697fda9279dSmrg src3 += srcPitch2; 698fda9279dSmrg } 699fda9279dSmrg } 700fda9279dSmrg} 701fda9279dSmrg 702fda9279dSmrg/** 703fda9279dSmrg * NVCopyNV12ColorPlanes 704fda9279dSmrg * Used to convert YV12 color planes to NV12 (interleaved UV) for the overlay 705fda9279dSmrg * 706fda9279dSmrg * @param src1 source buffer of chroma1 707fda9279dSmrg * @param dst1 destination buffer 708fda9279dSmrg * @param h number of lines to copy 709fda9279dSmrg * @param w length of lines to copy 710fda9279dSmrg * @param id source pixel format (YV12 or I420) 711fda9279dSmrg */ 712fda9279dSmrgstatic inline void 713fda9279dSmrgNVCopyNV12ColorPlanes(unsigned char *src1, unsigned char *src2, 714fda9279dSmrg unsigned char *dst, int dstPitch, int srcPitch2, 715fda9279dSmrg int h, int w) 716fda9279dSmrg{ 717fda9279dSmrg int i, j, l, e; 718fda9279dSmrg 719fda9279dSmrg w >>= 1; 720fda9279dSmrg h >>= 1; 721fda9279dSmrg#ifdef __SSE2__ 722fda9279dSmrg l = w >> 3; 723fda9279dSmrg e = w & 7; 724fda9279dSmrg#else 725fda9279dSmrg l = w >> 1; 726fda9279dSmrg e = w & 1; 727fda9279dSmrg#endif 728fda9279dSmrg 729fda9279dSmrg for (j = 0; j < h; j++) { 730fda9279dSmrg unsigned char *us = src1; 731fda9279dSmrg unsigned char *vs = src2; 732fda9279dSmrg unsigned int *vuvud = (unsigned int *) dst; 733fda9279dSmrg unsigned short *vud; 734fda9279dSmrg 735fda9279dSmrg for (i = 0; i < l; i++) { 736fda9279dSmrg#ifdef __SSE2__ 737fda9279dSmrg _mm_storeu_si128( 738fda9279dSmrg (void*)vuvud, 739fda9279dSmrg _mm_unpacklo_epi8( 740fda9279dSmrg _mm_loadl_epi64((void*)vs), 741fda9279dSmrg _mm_loadl_epi64((void*)us))); 742fda9279dSmrg vuvud+=4; 743fda9279dSmrg us+=8; 744fda9279dSmrg vs+=8; 745fda9279dSmrg#else /* __SSE2__ */ 746fda9279dSmrg# if X_BYTE_ORDER == X_BIG_ENDIAN 747fda9279dSmrg *vuvud++ = (vs[0]<<24) | (us[0]<<16) | (vs[1]<<8) | us[1]; 748fda9279dSmrg# else 749fda9279dSmrg *vuvud++ = vs[0] | (us[0]<<8) | (vs[1]<<16) | (us[1]<<24); 750fda9279dSmrg# endif 751fda9279dSmrg us+=2; 752fda9279dSmrg vs+=2; 753fda9279dSmrg#endif /* __SSE2__ */ 754fda9279dSmrg } 755fda9279dSmrg 756fda9279dSmrg vud = (unsigned short *)vuvud; 757fda9279dSmrg for (i = 0; i < e; i++) { 758fda9279dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 759fda9279dSmrg vud[i] = us[i] | (vs[i]<<8); 760fda9279dSmrg#else 761fda9279dSmrg vud[i] = vs[i] | (us[i]<<8); 762fda9279dSmrg#endif 763fda9279dSmrg } 764fda9279dSmrg 765fda9279dSmrg dst += dstPitch; 766fda9279dSmrg src1 += srcPitch2; 767fda9279dSmrg src2 += srcPitch2; 768fda9279dSmrg } 769fda9279dSmrg 770fda9279dSmrg} 771fda9279dSmrg 772fda9279dSmrg 773fda9279dSmrgstatic int 774fda9279dSmrgNV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 *xa, INT32 *xb, 775fda9279dSmrg INT32 *ya, INT32 *yb, short *src_x, short *src_y, 776fda9279dSmrg short *src_w, short *src_h, short *drw_x, short *drw_y, 777fda9279dSmrg short *drw_w, short *drw_h, int *left, int *top, int *right, 778fda9279dSmrg int *bottom, BoxRec *dstBox, int *npixels, int *nlines, 779fda9279dSmrg RegionPtr clipBoxes, short width, short height) 780fda9279dSmrg{ 781fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 782fda9279dSmrg 783fda9279dSmrg if (action_flags & USE_OVERLAY) { 784fda9279dSmrg switch (pNv->Architecture) { 785fda9279dSmrg case NV_ARCH_04: 786fda9279dSmrg /* NV0x overlay can't scale down. at all. */ 787fda9279dSmrg if (*drw_w < *src_w) 788fda9279dSmrg *drw_w = *src_w; 789fda9279dSmrg if (*drw_h < *src_h) 790fda9279dSmrg *drw_h = *src_h; 791fda9279dSmrg break; 792fda9279dSmrg case NV_ARCH_30: 793fda9279dSmrg /* According to DirectFB, NV3x can't scale down by 794fda9279dSmrg * a ratio > 2 795fda9279dSmrg */ 796fda9279dSmrg if (*drw_w < (*src_w) >> 1) 797fda9279dSmrg *drw_w = *src_w; 798fda9279dSmrg if (*drw_h < (*src_h) >> 1) 799fda9279dSmrg *drw_h = *src_h; 800fda9279dSmrg break; 801fda9279dSmrg default: /*NV10, NV20*/ 802fda9279dSmrg /* NV1x overlay can't scale down by a ratio > 8 */ 803fda9279dSmrg if (*drw_w < (*src_w) >> 3) 804fda9279dSmrg *drw_w = *src_w >> 3; 805fda9279dSmrg if (*drw_h < (*src_h >> 3)) 806fda9279dSmrg *drw_h = *src_h >> 3; 807fda9279dSmrg } 808fda9279dSmrg } 809fda9279dSmrg 810fda9279dSmrg /* Clip */ 811fda9279dSmrg *xa = *src_x; 812fda9279dSmrg *xb = *src_x + *src_w; 813fda9279dSmrg *ya = *src_y; 814fda9279dSmrg *yb = *src_y + *src_h; 815fda9279dSmrg 816fda9279dSmrg dstBox->x1 = *drw_x; 817fda9279dSmrg dstBox->x2 = *drw_x + *drw_w; 818fda9279dSmrg dstBox->y1 = *drw_y; 819fda9279dSmrg dstBox->y2 = *drw_y + *drw_h; 820fda9279dSmrg 821fda9279dSmrg /* In randr 1.2 mode VIDEO_CLIP_TO_VIEWPORT is broken (hence it is not 822fda9279dSmrg * set in the overlay adapter flags) since pScrn->frame{X,Y}1 do not get 823fda9279dSmrg * updated. Hence manual clipping against the CRTC dimensions 824fda9279dSmrg */ 825fda9279dSmrg if (action_flags & USE_OVERLAY) { 826fda9279dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 827fda9279dSmrg unsigned id = pPriv->overlayCRTC; 828fda9279dSmrg xf86CrtcPtr crtc = XF86_CRTC_CONFIG_PTR(pScrn)->crtc[id]; 829fda9279dSmrg RegionRec VPReg; 830fda9279dSmrg BoxRec VPBox; 831fda9279dSmrg 832fda9279dSmrg VPBox.x1 = crtc->x; 833fda9279dSmrg VPBox.y1 = crtc->y; 834fda9279dSmrg VPBox.x2 = crtc->x + crtc->mode.HDisplay; 835fda9279dSmrg VPBox.y2 = crtc->y + crtc->mode.VDisplay; 836fda9279dSmrg 837fda9279dSmrg REGION_INIT(pScreen, &VPReg, &VPBox, 1); 838fda9279dSmrg REGION_INTERSECT(pScreen, clipBoxes, clipBoxes, &VPReg); 839fda9279dSmrg REGION_UNINIT(pScreen, &VPReg); 840fda9279dSmrg } 841fda9279dSmrg 842fda9279dSmrg if (!xf86XVClipVideoHelper(dstBox, xa, xb, ya, yb, clipBoxes, 843fda9279dSmrg width, height)) 844fda9279dSmrg return -1; 845fda9279dSmrg 846fda9279dSmrg if (action_flags & USE_OVERLAY) { 847fda9279dSmrg xf86CrtcConfigPtr xf86_config = 848fda9279dSmrg XF86_CRTC_CONFIG_PTR(pScrn); 849fda9279dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 850fda9279dSmrg 851fda9279dSmrg dstBox->x1 -= xf86_config->crtc[pPriv->overlayCRTC]->x; 852fda9279dSmrg dstBox->x2 -= xf86_config->crtc[pPriv->overlayCRTC]->x; 853fda9279dSmrg dstBox->y1 -= xf86_config->crtc[pPriv->overlayCRTC]->y; 854fda9279dSmrg dstBox->y2 -= xf86_config->crtc[pPriv->overlayCRTC]->y; 855fda9279dSmrg } 856fda9279dSmrg 857fda9279dSmrg /* Convert fixed point to integer, as xf86XVClipVideoHelper probably 858fda9279dSmrg * turns its parameter into fixed point values 859fda9279dSmrg */ 860fda9279dSmrg *left = (*xa) >> 16; 861fda9279dSmrg if (*left < 0) 862fda9279dSmrg *left = 0; 863fda9279dSmrg 864fda9279dSmrg *top = (*ya) >> 16; 865fda9279dSmrg if (*top < 0) 866fda9279dSmrg *top = 0; 867fda9279dSmrg 868fda9279dSmrg *right = (*xb) >> 16; 869fda9279dSmrg if (*right > width) 870fda9279dSmrg *right = width; 871fda9279dSmrg 872fda9279dSmrg *bottom = (*yb) >> 16; 873fda9279dSmrg if (*bottom > height) 874fda9279dSmrg *bottom = height; 875fda9279dSmrg 876fda9279dSmrg if (action_flags & IS_YV12) { 877fda9279dSmrg /* even "left", even "top", even number of pixels per line 878fda9279dSmrg * and even number of lines 879fda9279dSmrg */ 880fda9279dSmrg *left &= ~1; 881fda9279dSmrg *npixels = ((*right + 1) & ~1) - *left; 882fda9279dSmrg *top &= ~1; 883fda9279dSmrg *nlines = ((*bottom + 1) & ~1) - *top; 884fda9279dSmrg } else 885fda9279dSmrg if (action_flags & IS_YUY2) { 886fda9279dSmrg /* even "left" */ 887fda9279dSmrg *left &= ~1; 888fda9279dSmrg /* even number of pixels per line */ 889fda9279dSmrg *npixels = ((*right + 1) & ~1) - *left; 890fda9279dSmrg *nlines = *bottom - *top; 891fda9279dSmrg /* 16bpp */ 892fda9279dSmrg *left <<= 1; 893fda9279dSmrg } else 894fda9279dSmrg if (action_flags & IS_RGB) { 895fda9279dSmrg *npixels = *right - *left; 896fda9279dSmrg *nlines = *bottom - *top; 897fda9279dSmrg /* 32bpp */ 898fda9279dSmrg *left <<= 2; 899fda9279dSmrg } 900fda9279dSmrg 901fda9279dSmrg return 0; 902fda9279dSmrg} 903fda9279dSmrg 904fda9279dSmrgstatic int 905fda9279dSmrgNV_calculate_pitches_and_mem_size(NVPtr pNv, int action_flags, int *srcPitch, 906fda9279dSmrg int *srcPitch2, int *dstPitch, int *s2offset, 907fda9279dSmrg int *s3offset, int *uv_offset, 908fda9279dSmrg int *newFBSize, int *newTTSize, 909fda9279dSmrg int *line_len, int npixels, int nlines, 910fda9279dSmrg int width, int height) 911fda9279dSmrg{ 912fda9279dSmrg int tmp; 913fda9279dSmrg 914fda9279dSmrg if (pNv->Architecture >= NV_TESLA) { 915fda9279dSmrg npixels = (npixels + 7) & ~7; 916fda9279dSmrg nlines = (nlines + 7) & ~7; 917fda9279dSmrg } 918fda9279dSmrg 919fda9279dSmrg if (action_flags & IS_YV12) { 920fda9279dSmrg *srcPitch = (width + 3) & ~3; /* of luma */ 921fda9279dSmrg *s2offset = *srcPitch * height; 922fda9279dSmrg *srcPitch2 = ((width >> 1) + 3) & ~3; /*of chroma*/ 923fda9279dSmrg *s3offset = (*srcPitch2 * (height >> 1)) + *s2offset; 924fda9279dSmrg *dstPitch = (npixels + 63) & ~63; /*luma and chroma pitch*/ 925fda9279dSmrg *line_len = npixels; 926fda9279dSmrg *uv_offset = nlines * *dstPitch; 927fda9279dSmrg *newFBSize = *uv_offset + (nlines >> 1) * *dstPitch; 928fda9279dSmrg *newTTSize = *uv_offset + (nlines >> 1) * *dstPitch; 929fda9279dSmrg } else 930fda9279dSmrg if (action_flags & IS_YUY2) { 931fda9279dSmrg *srcPitch = width << 1; /* one luma, one chroma per pixel */ 932fda9279dSmrg *dstPitch = ((npixels << 1) + 63) & ~63; 933fda9279dSmrg *line_len = npixels << 1; 934fda9279dSmrg *newFBSize = nlines * *dstPitch; 935fda9279dSmrg *newTTSize = nlines * *line_len; 936fda9279dSmrg } else 937fda9279dSmrg if (action_flags & IS_RGB) { 938fda9279dSmrg /* one R, one G, one B, one X per pixel */ 939fda9279dSmrg *srcPitch = width << 2; 940fda9279dSmrg *dstPitch = ((npixels << 2) + 63) & ~63; 941fda9279dSmrg *line_len = npixels << 2; 942fda9279dSmrg *newFBSize = nlines * *dstPitch; 943fda9279dSmrg *newTTSize = nlines * *dstPitch; 944fda9279dSmrg } 945fda9279dSmrg 946fda9279dSmrg if (action_flags & CONVERT_TO_YUY2) { 947fda9279dSmrg *dstPitch = ((npixels << 1) + 63) & ~63; 948fda9279dSmrg *line_len = npixels << 1; 949fda9279dSmrg *newFBSize = nlines * *dstPitch; 950fda9279dSmrg *newTTSize = nlines * *line_len; 951fda9279dSmrg *uv_offset = 0; 952fda9279dSmrg } 953fda9279dSmrg 954fda9279dSmrg if (action_flags & SWAP_UV) { 955fda9279dSmrg /* I420 swaps U and V */ 956fda9279dSmrg tmp = *s2offset; 957fda9279dSmrg *s2offset = *s3offset; 958fda9279dSmrg *s3offset = tmp; 959fda9279dSmrg } 960fda9279dSmrg 961fda9279dSmrg /* Overlay double buffering... */ 962fda9279dSmrg if (action_flags & USE_OVERLAY) 963fda9279dSmrg (*newFBSize) <<= 1; 964fda9279dSmrg 965fda9279dSmrg return 0; 966fda9279dSmrg} 967fda9279dSmrg 968fda9279dSmrg 969fda9279dSmrg/** 970fda9279dSmrg * NV_set_action_flags 971fda9279dSmrg * This function computes the action flags from the input image, 972fda9279dSmrg * that is, it decides what NVPutImage and its helpers must do. 973fda9279dSmrg * This eases readability by avoiding lots of switch-case statements in the 974fda9279dSmrg * core NVPutImage 975fda9279dSmrg */ 976fda9279dSmrgstatic void 977fda9279dSmrgNV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, 978fda9279dSmrg int id, short drw_x, short drw_y, short drw_w, short drw_h, 979fda9279dSmrg int *action_flags) 980fda9279dSmrg{ 981fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 982fda9279dSmrg 983fda9279dSmrg#define USING_OVERLAY (*action_flags & USE_OVERLAY) 984fda9279dSmrg#define USING_TEXTURE (*action_flags & USE_TEXTURE) 985fda9279dSmrg#define USING_BLITTER ((!(*action_flags & USE_OVERLAY)) && \ 986fda9279dSmrg (!(*action_flags & USE_TEXTURE))) 987fda9279dSmrg 988fda9279dSmrg *action_flags = 0; 989fda9279dSmrg 990fda9279dSmrg /* Pixel format-related bits */ 991fda9279dSmrg if (id == FOURCC_YUY2 || id == FOURCC_UYVY) 992fda9279dSmrg *action_flags |= IS_YUY2; 993fda9279dSmrg 994fda9279dSmrg if (id == FOURCC_YV12 || id == FOURCC_I420) 995fda9279dSmrg *action_flags |= IS_YV12; 996fda9279dSmrg 997fda9279dSmrg if (id == FOURCC_RGB) /*How long will we support it?*/ 998fda9279dSmrg *action_flags |= IS_RGB; 999fda9279dSmrg 1000fda9279dSmrg if (id == FOURCC_I420) /* I420 is YV12 with swapped UV */ 1001fda9279dSmrg *action_flags |= SWAP_UV; 1002fda9279dSmrg 1003fda9279dSmrg /* Desired adapter */ 1004fda9279dSmrg if (!pPriv->blitter && !pPriv->texture) 1005fda9279dSmrg *action_flags |= USE_OVERLAY; 1006fda9279dSmrg 1007fda9279dSmrg if (!pPriv->blitter && pPriv->texture) 1008fda9279dSmrg *action_flags |= USE_TEXTURE; 1009fda9279dSmrg 1010fda9279dSmrg /* Adapter fallbacks (when the desired one can't be used)*/ 1011fda9279dSmrg#ifdef COMPOSITE 1012fda9279dSmrg { 1013fda9279dSmrg PixmapPtr ppix = NVGetDrawablePixmap(pDraw); 1014fda9279dSmrg 1015fda9279dSmrg /* this is whether ppix is in the viewable fb, not related to 1016fda9279dSmrg the EXA "offscreen" stuff */ 1017fda9279dSmrg if (!nouveau_exa_pixmap_is_onscreen(ppix)) 1018fda9279dSmrg *action_flags &= ~USE_OVERLAY; 1019fda9279dSmrg } 1020fda9279dSmrg#endif 1021fda9279dSmrg 1022fda9279dSmrg#ifdef NVOVL_SUPPORT 1023fda9279dSmrg if (USING_OVERLAY) { 1024fda9279dSmrg char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y, 1025fda9279dSmrg drw_w, drw_h); 1026fda9279dSmrg 1027fda9279dSmrg if ((crtc & (1 << 0)) && (crtc & (1 << 1))) { 1028fda9279dSmrg /* The overlay cannot be used on two CRTCs at a time, 1029fda9279dSmrg * so we need to fallback on the blitter 1030fda9279dSmrg */ 1031fda9279dSmrg *action_flags &= ~USE_OVERLAY; 1032fda9279dSmrg } else 1033fda9279dSmrg if ((crtc & (1 << 0))) { 1034fda9279dSmrg /* We need to put the overlay on CRTC0 - if it's not 1035fda9279dSmrg * already here 1036fda9279dSmrg */ 1037fda9279dSmrg if (pPriv->overlayCRTC == 1) { 1038fda9279dSmrg NVWriteCRTC(pNv, 0, NV_PCRTC_ENGINE_CTRL, 1039fda9279dSmrg NVReadCRTC(pNv, 0, NV_PCRTC_ENGINE_CTRL) | 1040fda9279dSmrg NV_CRTC_FSEL_OVERLAY); 1041fda9279dSmrg NVWriteCRTC(pNv, 1, NV_PCRTC_ENGINE_CTRL, 1042fda9279dSmrg NVReadCRTC(pNv, 1, NV_PCRTC_ENGINE_CTRL) & 1043fda9279dSmrg ~NV_CRTC_FSEL_OVERLAY); 1044fda9279dSmrg pPriv->overlayCRTC = 0; 1045fda9279dSmrg } 1046fda9279dSmrg } else 1047fda9279dSmrg if ((crtc & (1 << 1))) { 1048fda9279dSmrg if (pPriv->overlayCRTC == 0) { 1049fda9279dSmrg NVWriteCRTC(pNv, 1, NV_PCRTC_ENGINE_CTRL, 1050fda9279dSmrg NVReadCRTC(pNv, 1, NV_PCRTC_ENGINE_CTRL) | 1051fda9279dSmrg NV_CRTC_FSEL_OVERLAY); 1052fda9279dSmrg NVWriteCRTC(pNv, 0, NV_PCRTC_ENGINE_CTRL, 1053fda9279dSmrg NVReadCRTC(pNv, 0, NV_PCRTC_ENGINE_CTRL) & 1054fda9279dSmrg ~NV_CRTC_FSEL_OVERLAY); 1055fda9279dSmrg pPriv->overlayCRTC = 1; 1056fda9279dSmrg } 1057fda9279dSmrg } 1058fda9279dSmrg 1059fda9279dSmrg if (XF86_CRTC_CONFIG_PTR(pScrn)->crtc[pPriv->overlayCRTC] 1060fda9279dSmrg ->rotation != RR_Rotate_0) 1061fda9279dSmrg *action_flags &= ~USE_OVERLAY; 1062fda9279dSmrg } 1063fda9279dSmrg#endif 1064fda9279dSmrg 1065fda9279dSmrg /* At this point the adapter we're going to use is _known_. 1066fda9279dSmrg * You cannot change it now. 1067fda9279dSmrg */ 1068fda9279dSmrg 1069fda9279dSmrg /* Card/adapter format restrictions */ 1070fda9279dSmrg if (USING_BLITTER) { 1071fda9279dSmrg /* The blitter does not handle YV12 natively */ 1072fda9279dSmrg if (id == FOURCC_YV12 || id == FOURCC_I420) 1073fda9279dSmrg *action_flags |= CONVERT_TO_YUY2; 1074fda9279dSmrg } 1075fda9279dSmrg 1076fda9279dSmrg if (USING_OVERLAY && (pNv->Architecture == NV_ARCH_04)) { 1077fda9279dSmrg /* NV04-05 don't support YV12, only YUY2 and ITU-R BT.601 */ 1078fda9279dSmrg if (*action_flags & IS_YV12) 1079fda9279dSmrg *action_flags |= CONVERT_TO_YUY2; 1080fda9279dSmrg } 1081fda9279dSmrg 1082fda9279dSmrg if (USING_OVERLAY && (pNv->Architecture == NV_ARCH_10 || 1083fda9279dSmrg pNv->Architecture == NV_ARCH_20)) { 1084fda9279dSmrg /* No YV12 overlay on NV10, 11, 15, 20, NFORCE */ 1085fda9279dSmrg switch (pNv->dev->chipset) { 1086fda9279dSmrg case 0x10: 1087fda9279dSmrg case 0x11: 1088fda9279dSmrg case 0x15: 1089fda9279dSmrg case 0x1a: /*XXX: unsure about nforce */ 1090fda9279dSmrg case 0x20: 1091fda9279dSmrg *action_flags |= CONVERT_TO_YUY2; 1092fda9279dSmrg break; 1093fda9279dSmrg default: 1094fda9279dSmrg break; 1095fda9279dSmrg } 1096fda9279dSmrg } 1097fda9279dSmrg} 1098fda9279dSmrg 1099fda9279dSmrg 1100fda9279dSmrg/** 1101fda9279dSmrg * NVPutImage 1102fda9279dSmrg * PutImage is "the" important function of the Xv extension. 1103fda9279dSmrg * a client (e.g. video player) calls this function for every 1104fda9279dSmrg * image (of the video) to be displayed. this function then 1105fda9279dSmrg * scales and displays the image. 1106fda9279dSmrg * 1107fda9279dSmrg * @param pScrn screen which hold the port where the image is put 1108fda9279dSmrg * @param src_x source point in the source image to start displaying from 1109fda9279dSmrg * @param src_y see above 1110fda9279dSmrg * @param src_w width of the source image to display 1111fda9279dSmrg * @param src_h see above 1112fda9279dSmrg * @param drw_x screen point to display to 1113fda9279dSmrg * @param drw_y 1114fda9279dSmrg * @param drw_w width of the screen drawable 1115fda9279dSmrg * @param drw_h 1116fda9279dSmrg * @param id pixel format of image 1117fda9279dSmrg * @param buf pointer to buffer containing the source image 1118fda9279dSmrg * @param width total width of the source image we are passed 1119fda9279dSmrg * @param height 1120fda9279dSmrg * @param Sync unused 1121fda9279dSmrg * @param clipBoxes ?? 1122fda9279dSmrg * @param data pointer to port 1123fda9279dSmrg * @param pDraw drawable pointer 1124fda9279dSmrg */ 1125fda9279dSmrgstatic int 1126fda9279dSmrgNVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, 1127fda9279dSmrg short drw_y, short src_w, short src_h, short drw_w, short drw_h, 1128fda9279dSmrg int id, unsigned char *buf, short width, short height, 1129fda9279dSmrg Bool Sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 1130fda9279dSmrg{ 1131fda9279dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 1132fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1133fda9279dSmrg PixmapPtr ppix; 1134fda9279dSmrg /* source box */ 1135fda9279dSmrg INT32 xa = 0, xb = 0, ya = 0, yb = 0; 1136fda9279dSmrg /* size to allocate in VRAM and in GART respectively */ 1137fda9279dSmrg int newFBSize = 0, newTTSize = 0; 1138fda9279dSmrg /* card VRAM offsets, source offsets for U and V planes */ 1139fda9279dSmrg int offset = 0, uv_offset = 0, s2offset = 0, s3offset = 0; 1140fda9279dSmrg /* source pitch, source pitch of U and V planes in case of YV12, 1141fda9279dSmrg * VRAM destination pitch 1142fda9279dSmrg */ 1143fda9279dSmrg int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; 1144fda9279dSmrg /* position of the given source data (using src_*), number of pixels 1145fda9279dSmrg * and lines we are interested in 1146fda9279dSmrg */ 1147fda9279dSmrg int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0; 1148fda9279dSmrg Bool skip = FALSE; 1149fda9279dSmrg BoxRec dstBox; 1150fda9279dSmrg CARD32 tmp = 0; 1151fda9279dSmrg int line_len = 0; /* length of a line, like npixels, but in bytes */ 1152fda9279dSmrg struct nouveau_bo *destination_buffer = NULL; 1153fda9279dSmrg int action_flags; /* what shall we do? */ 1154fda9279dSmrg unsigned char *map; 1155fda9279dSmrg int ret, i; 1156fda9279dSmrg 1157fda9279dSmrg if (pPriv->grabbedByV4L) 1158fda9279dSmrg return Success; 1159fda9279dSmrg 116016ee1e9aSmrg if (width > pPriv->max_image_dim || height > pPriv->max_image_dim) 116116ee1e9aSmrg return BadMatch; 1162fda9279dSmrg 1163fda9279dSmrg NV_set_action_flags(pScrn, pDraw, pPriv, id, drw_x, drw_y, drw_w, 1164fda9279dSmrg drw_h, &action_flags); 1165fda9279dSmrg 1166fda9279dSmrg if (NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb, 1167fda9279dSmrg &src_x, &src_y, &src_w, &src_h, 1168fda9279dSmrg &drw_x, &drw_y, &drw_w, &drw_h, 1169fda9279dSmrg &left, &top, &right, &bottom, &dstBox, 1170fda9279dSmrg &npixels, &nlines, clipBoxes, width, height)) 1171fda9279dSmrg return Success; 1172fda9279dSmrg 1173fda9279dSmrg if (NV_calculate_pitches_and_mem_size(pNv, action_flags, &srcPitch, 1174fda9279dSmrg &srcPitch2, &dstPitch, &s2offset, 1175fda9279dSmrg &s3offset, &uv_offset, 1176fda9279dSmrg &newFBSize, &newTTSize, 1177fda9279dSmrg &line_len, npixels, nlines, 1178fda9279dSmrg width, height)) 1179fda9279dSmrg return BadImplementation; 1180fda9279dSmrg 1181fda9279dSmrg /* There are some cases (tvtime with overscan for example) where the 1182fda9279dSmrg * input image is larger (width/height) than the source rectangle for 1183fda9279dSmrg * the overlay (src_w, src_h). In those cases, we try to do something 1184fda9279dSmrg * optimal by uploading only the necessary data. 1185fda9279dSmrg */ 1186fda9279dSmrg if (action_flags & IS_YUY2 || action_flags & IS_RGB) 1187fda9279dSmrg buf += (top * srcPitch) + left; 1188fda9279dSmrg 1189fda9279dSmrg if (action_flags & IS_YV12) { 1190fda9279dSmrg tmp = ((top >> 1) * srcPitch2) + (left >> 1); 1191fda9279dSmrg s2offset += tmp; 1192fda9279dSmrg s3offset += tmp; 1193fda9279dSmrg } 1194fda9279dSmrg 1195fda9279dSmrg ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, newFBSize, 1196fda9279dSmrg &pPriv->video_mem); 1197fda9279dSmrg if (ret) 1198fda9279dSmrg return BadAlloc; 1199fda9279dSmrg 1200fda9279dSmrg#ifdef NVOVL_SUPPORT 1201fda9279dSmrg if (action_flags & USE_OVERLAY) { 1202fda9279dSmrg ret = nouveau_bo_pin(pPriv->video_mem, NOUVEAU_BO_VRAM); 1203fda9279dSmrg if (ret) { 1204fda9279dSmrg nouveau_bo_ref(NULL, &pPriv->video_mem); 1205fda9279dSmrg return BadAlloc; 1206fda9279dSmrg } 1207fda9279dSmrg } 1208fda9279dSmrg#endif 1209fda9279dSmrg 1210fda9279dSmrg /* The overlay supports hardware double buffering. We handle this here*/ 1211fda9279dSmrg offset = 0; 1212fda9279dSmrg#ifdef NVOVL_SUPPORT 1213fda9279dSmrg if (pPriv->doubleBuffer) { 1214fda9279dSmrg int mask = 1 << (pPriv->currentBuffer << 2); 1215fda9279dSmrg 1216fda9279dSmrg /* overwrite the newest buffer if there's not one free */ 1217fda9279dSmrg if (nvReadVIDEO(pNv, NV_PVIDEO_BUFFER) & mask) { 1218fda9279dSmrg if (!pPriv->currentBuffer) 1219fda9279dSmrg offset += newFBSize >> 1; 1220fda9279dSmrg skip = TRUE; 1221fda9279dSmrg } else { 1222fda9279dSmrg if (pPriv->currentBuffer) 1223fda9279dSmrg offset += newFBSize >> 1; 1224fda9279dSmrg } 1225fda9279dSmrg } 1226fda9279dSmrg#endif 1227fda9279dSmrg 1228fda9279dSmrg /* Now we take a decision regarding the way we send the data to the 1229fda9279dSmrg * card. 1230fda9279dSmrg * 1231fda9279dSmrg * Either we use double buffering of "private" TT memory 1232fda9279dSmrg * Either we rely on X's GARTScratch 1233fda9279dSmrg * Either we fallback on CPU copy 1234fda9279dSmrg */ 1235fda9279dSmrg 1236fda9279dSmrg /* Try to allocate host-side double buffers, unless we have already 1237fda9279dSmrg * failed 1238fda9279dSmrg */ 1239fda9279dSmrg 1240fda9279dSmrg /* We take only nlines * line_len bytes - that is, only the pixel 1241fda9279dSmrg * data we are interested in - because the stuff in the GART is 1242fda9279dSmrg * written contiguously 1243fda9279dSmrg */ 1244fda9279dSmrg if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) { 1245fda9279dSmrg ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_GART, newTTSize, 1246fda9279dSmrg &pPriv->TT_mem_chunk[0]); 1247fda9279dSmrg if (ret == 0) { 1248fda9279dSmrg ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_GART, 1249fda9279dSmrg newTTSize, 1250fda9279dSmrg &pPriv->TT_mem_chunk[1]); 1251fda9279dSmrg if (ret) { 1252fda9279dSmrg nouveau_bo_ref(NULL, &pPriv->TT_mem_chunk[0]); 1253fda9279dSmrg pPriv->currentHostBuffer = 1254fda9279dSmrg NO_PRIV_HOST_BUFFER_AVAILABLE; 1255fda9279dSmrg } 1256fda9279dSmrg } else { 1257fda9279dSmrg pPriv->currentHostBuffer = 1258fda9279dSmrg NO_PRIV_HOST_BUFFER_AVAILABLE; 1259fda9279dSmrg } 1260fda9279dSmrg } 1261fda9279dSmrg 1262fda9279dSmrg if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) { 1263fda9279dSmrg destination_buffer = 1264fda9279dSmrg pPriv->TT_mem_chunk[pPriv->currentHostBuffer]; 1265fda9279dSmrg } 1266fda9279dSmrg if (!destination_buffer) { 1267fda9279dSmrg if (pNv->Architecture >= NV_TESLA) { 1268fda9279dSmrg NOUVEAU_ERR("No scratch buffer for tiled upload\n"); 1269fda9279dSmrg return BadAlloc; 1270fda9279dSmrg } 1271fda9279dSmrg 1272fda9279dSmrg goto CPU_copy; 1273fda9279dSmrg } 1274fda9279dSmrg 1275fda9279dSmrg if (newTTSize <= destination_buffer->size) { 1276fda9279dSmrg unsigned char *dst; 1277fda9279dSmrg 1278fda9279dSmrg /* Upload to GART */ 1279fda9279dSmrg nouveau_bo_map(destination_buffer, NOUVEAU_BO_WR, pNv->client); 1280fda9279dSmrg dst = destination_buffer->map; 1281fda9279dSmrg 1282fda9279dSmrg if (action_flags & IS_YV12) { 1283fda9279dSmrg if (action_flags & CONVERT_TO_YUY2) { 1284fda9279dSmrg NVCopyData420(buf + (top * srcPitch) + left, 1285fda9279dSmrg buf + s2offset, buf + s3offset, 1286fda9279dSmrg dst, srcPitch, srcPitch2, 1287fda9279dSmrg line_len, nlines, npixels); 1288fda9279dSmrg } else { 1289fda9279dSmrg /* Native YV12 */ 1290fda9279dSmrg unsigned char *tbuf = buf + top * 1291fda9279dSmrg srcPitch + left; 1292fda9279dSmrg unsigned char *tdst = dst; 1293fda9279dSmrg 1294fda9279dSmrg /* luma upload */ 1295fda9279dSmrg for (i = 0; i < nlines; i++) { 1296fda9279dSmrg memcpy(tdst, tbuf, line_len); 1297fda9279dSmrg tdst += line_len; 1298fda9279dSmrg tbuf += srcPitch; 1299fda9279dSmrg } 1300fda9279dSmrg dst += line_len * nlines; 1301fda9279dSmrg 1302fda9279dSmrg NVCopyNV12ColorPlanes(buf + s2offset, 1303fda9279dSmrg buf + s3offset, dst, 1304fda9279dSmrg line_len, srcPitch2, 1305fda9279dSmrg nlines, npixels); 1306fda9279dSmrg } 1307fda9279dSmrg } else { 1308fda9279dSmrg for (i = 0; i < nlines; i++) { 1309fda9279dSmrg memcpy(dst, buf, line_len); 1310fda9279dSmrg dst += line_len; 1311fda9279dSmrg buf += srcPitch; 1312fda9279dSmrg } 1313fda9279dSmrg } 1314fda9279dSmrg 1315fda9279dSmrg if (uv_offset) { 1316fda9279dSmrg NVAccelM2MF(pNv, line_len, nlines / 2, 1, 1317fda9279dSmrg line_len * nlines, uv_offset, 1318fda9279dSmrg destination_buffer, NOUVEAU_BO_GART, 1319fda9279dSmrg line_len, nlines >> 1, 0, 0, 1320fda9279dSmrg pPriv->video_mem, NOUVEAU_BO_VRAM, 1321fda9279dSmrg dstPitch, nlines >> 1, 0, 0); 1322fda9279dSmrg } 1323fda9279dSmrg 1324fda9279dSmrg NVAccelM2MF(pNv, line_len, nlines, 1, 0, 0, 1325fda9279dSmrg destination_buffer, NOUVEAU_BO_GART, 1326fda9279dSmrg line_len, nlines, 0, 0, 1327fda9279dSmrg pPriv->video_mem, NOUVEAU_BO_VRAM, 1328fda9279dSmrg dstPitch, nlines, 0, 0); 1329fda9279dSmrg 1330fda9279dSmrg } else { 1331fda9279dSmrgCPU_copy: 1332fda9279dSmrg nouveau_bo_map(pPriv->video_mem, NOUVEAU_BO_WR, pNv->client); 1333fda9279dSmrg map = pPriv->video_mem->map + offset; 1334fda9279dSmrg 1335fda9279dSmrg if (action_flags & IS_YV12) { 1336fda9279dSmrg if (action_flags & CONVERT_TO_YUY2) { 1337fda9279dSmrg NVCopyData420(buf + (top * srcPitch) + left, 1338fda9279dSmrg buf + s2offset, buf + s3offset, 1339fda9279dSmrg map, srcPitch, srcPitch2, 1340fda9279dSmrg dstPitch, nlines, npixels); 1341fda9279dSmrg } else { 1342fda9279dSmrg unsigned char *tbuf = 1343fda9279dSmrg buf + left + top * srcPitch; 1344fda9279dSmrg 1345fda9279dSmrg for (i = 0; i < nlines; i++) { 1346fda9279dSmrg int dwords = npixels << 1; 1347fda9279dSmrg 1348fda9279dSmrg while (dwords & ~0x03) { 1349fda9279dSmrg *map = *tbuf; 1350fda9279dSmrg *(map + 1) = *(tbuf + 1); 1351fda9279dSmrg *(map + 2) = *(tbuf + 2); 1352fda9279dSmrg *(map + 3) = *(tbuf + 3); 1353fda9279dSmrg map += 4; 1354fda9279dSmrg tbuf += 4; 1355fda9279dSmrg dwords -= 4; 1356fda9279dSmrg } 1357fda9279dSmrg 1358fda9279dSmrg switch (dwords) { 1359fda9279dSmrg case 3: *(map + 2) = *(tbuf + 2); 1360fda9279dSmrg case 2: *(map + 1) = *(tbuf + 1); 1361fda9279dSmrg case 1: *map = *tbuf; 1362fda9279dSmrg } 1363fda9279dSmrg 1364fda9279dSmrg map += dstPitch - (npixels << 1); 1365fda9279dSmrg tbuf += srcPitch - (npixels << 1); 1366fda9279dSmrg } 1367fda9279dSmrg 1368fda9279dSmrg NVCopyNV12ColorPlanes(buf + s2offset, 1369fda9279dSmrg buf + s3offset, 1370fda9279dSmrg map, dstPitch, srcPitch2, 1371fda9279dSmrg nlines, npixels); 1372fda9279dSmrg } 1373fda9279dSmrg } else { 1374fda9279dSmrg /* YUY2 and RGB */ 1375fda9279dSmrg for (i = 0; i < nlines; i++) { 1376fda9279dSmrg int dwords = npixels << 1; 1377fda9279dSmrg 1378fda9279dSmrg while (dwords & ~0x03) { 1379fda9279dSmrg *map = *buf; 1380fda9279dSmrg *(map + 1) = *(buf + 1); 1381fda9279dSmrg *(map + 2) = *(buf + 2); 1382fda9279dSmrg *(map + 3) = *(buf + 3); 1383fda9279dSmrg map += 4; 1384fda9279dSmrg buf += 4; 1385fda9279dSmrg dwords -= 4; 1386fda9279dSmrg } 1387fda9279dSmrg 1388fda9279dSmrg switch (dwords) { 1389fda9279dSmrg case 3: *(map + 2) = *(buf + 2); 1390fda9279dSmrg case 2: *(map + 1) = *(buf + 1); 1391fda9279dSmrg case 1: *map = *buf; 1392fda9279dSmrg } 1393fda9279dSmrg 1394fda9279dSmrg map += dstPitch - (npixels << 1); 1395fda9279dSmrg buf += srcPitch - (npixels << 1); 1396fda9279dSmrg } 1397fda9279dSmrg } 1398fda9279dSmrg } 1399fda9279dSmrg 1400fda9279dSmrg if (skip) 1401fda9279dSmrg return Success; 1402fda9279dSmrg 1403fda9279dSmrg if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) 1404fda9279dSmrg pPriv->currentHostBuffer ^= 1; 1405fda9279dSmrg 1406fda9279dSmrg /* If we're not using the hw overlay, we're rendering into a pixmap 1407fda9279dSmrg * and need to take a couple of additional steps... 1408fda9279dSmrg */ 1409fda9279dSmrg if (!(action_flags & USE_OVERLAY)) { 1410fda9279dSmrg ppix = NVGetDrawablePixmap(pDraw); 1411fda9279dSmrg 1412fda9279dSmrg /* Ensure pixmap is in offscreen memory */ 1413fda9279dSmrg pNv->exa_force_cp = TRUE; 1414fda9279dSmrg exaMoveInPixmap(ppix); 1415fda9279dSmrg pNv->exa_force_cp = FALSE; 1416fda9279dSmrg 1417fda9279dSmrg if (!exaGetPixmapDriverPrivate(ppix)) 1418fda9279dSmrg return BadAlloc; 1419fda9279dSmrg 1420fda9279dSmrg#ifdef COMPOSITE 1421fda9279dSmrg /* Convert screen coords to pixmap coords */ 1422fda9279dSmrg if (ppix->screen_x || ppix->screen_y) { 1423fda9279dSmrg REGION_TRANSLATE(pScrn->pScreen, clipBoxes, 1424fda9279dSmrg -ppix->screen_x, -ppix->screen_y); 1425fda9279dSmrg dstBox.x1 -= ppix->screen_x; 1426fda9279dSmrg dstBox.x2 -= ppix->screen_x; 1427fda9279dSmrg dstBox.y1 -= ppix->screen_y; 1428fda9279dSmrg dstBox.y2 -= ppix->screen_y; 1429fda9279dSmrg } 1430fda9279dSmrg#endif 1431fda9279dSmrg } 1432fda9279dSmrg 1433fda9279dSmrg if (action_flags & USE_OVERLAY) { 1434fda9279dSmrg if (pNv->Architecture == NV_ARCH_04) { 1435fda9279dSmrg NV04PutOverlayImage(pScrn, pPriv->video_mem, offset, 1436fda9279dSmrg id, dstPitch, &dstBox, 0, 0, 1437fda9279dSmrg xb, yb, npixels, nlines, 1438fda9279dSmrg src_w, src_h, drw_w, drw_h, 1439fda9279dSmrg clipBoxes); 1440fda9279dSmrg } else { 1441fda9279dSmrg NV10PutOverlayImage(pScrn, pPriv->video_mem, offset, 1442fda9279dSmrg uv_offset, id, dstPitch, &dstBox, 1443fda9279dSmrg 0, 0, xb, yb, 1444fda9279dSmrg npixels, nlines, src_w, src_h, 1445fda9279dSmrg drw_w, drw_h, clipBoxes); 1446fda9279dSmrg } 1447fda9279dSmrg 1448fda9279dSmrg pPriv->currentBuffer ^= 1; 1449fda9279dSmrg } else 1450fda9279dSmrg if (action_flags & USE_TEXTURE) { 145122d74663Smrg ret = BadImplementation; 1452fda9279dSmrg 1453fda9279dSmrg if (pNv->Architecture == NV_ARCH_30) { 1454fda9279dSmrg ret = NV30PutTextureImage(pScrn, pPriv->video_mem, 1455fda9279dSmrg offset, uv_offset, 1456fda9279dSmrg id, dstPitch, &dstBox, 0, 0, 1457fda9279dSmrg xb, yb, npixels, nlines, 1458fda9279dSmrg src_w, src_h, drw_w, drw_h, 1459fda9279dSmrg clipBoxes, ppix, pPriv); 1460fda9279dSmrg } else 1461fda9279dSmrg if (pNv->Architecture == NV_ARCH_40) { 1462fda9279dSmrg ret = NV40PutTextureImage(pScrn, pPriv->video_mem, 1463fda9279dSmrg offset, uv_offset, 1464fda9279dSmrg id, dstPitch, &dstBox, 0, 0, 1465fda9279dSmrg xb, yb, npixels, nlines, 1466fda9279dSmrg src_w, src_h, drw_w, drw_h, 1467fda9279dSmrg clipBoxes, ppix, pPriv); 1468fda9279dSmrg } else 1469fda9279dSmrg if (pNv->Architecture == NV_TESLA) { 1470fda9279dSmrg ret = nv50_xv_image_put(pScrn, pPriv->video_mem, 1471fda9279dSmrg offset, uv_offset, 1472fda9279dSmrg id, dstPitch, &dstBox, 0, 0, 1473fda9279dSmrg xb, yb, npixels, nlines, 1474fda9279dSmrg src_w, src_h, drw_w, drw_h, 1475fda9279dSmrg clipBoxes, ppix, pPriv); 1476fda9279dSmrg } else { 1477fda9279dSmrg ret = nvc0_xv_image_put(pScrn, pPriv->video_mem, 1478fda9279dSmrg offset, uv_offset, 1479fda9279dSmrg id, dstPitch, &dstBox, 0, 0, 1480fda9279dSmrg xb, yb, npixels, nlines, 1481fda9279dSmrg src_w, src_h, drw_w, drw_h, 1482fda9279dSmrg clipBoxes, ppix, pPriv); 1483fda9279dSmrg } 1484fda9279dSmrg 1485fda9279dSmrg if (ret != Success) 1486fda9279dSmrg return ret; 1487fda9279dSmrg } else { 1488fda9279dSmrg ret = NVPutBlitImage(pScrn, pPriv->video_mem, offset, id, 1489fda9279dSmrg dstPitch, &dstBox, 0, 0, xb, yb, npixels, 1490fda9279dSmrg nlines, src_w, src_h, drw_w, drw_h, 1491fda9279dSmrg clipBoxes, ppix); 1492fda9279dSmrg if (ret != Success) 1493fda9279dSmrg return ret; 1494fda9279dSmrg } 1495fda9279dSmrg 1496fda9279dSmrg#ifdef COMPOSITE 1497fda9279dSmrg /* Damage tracking */ 1498fda9279dSmrg if (!(action_flags & USE_OVERLAY)) 1499fda9279dSmrg DamageDamageRegion(&ppix->drawable, clipBoxes); 1500fda9279dSmrg#endif 1501fda9279dSmrg 1502fda9279dSmrg return Success; 1503fda9279dSmrg} 1504fda9279dSmrg 1505fda9279dSmrg/** 1506fda9279dSmrg * QueryImageAttributes 1507fda9279dSmrg * 1508fda9279dSmrg * calculates 1509fda9279dSmrg * - size (memory required to store image), 1510fda9279dSmrg * - pitches, 1511fda9279dSmrg * - offsets 1512fda9279dSmrg * of image 1513fda9279dSmrg * depending on colorspace (id) and dimensions (w,h) of image 1514fda9279dSmrg * values of 1515fda9279dSmrg * - w, 1516fda9279dSmrg * - h 1517fda9279dSmrg * may be adjusted as needed 1518fda9279dSmrg * 1519fda9279dSmrg * @param pScrn unused 1520fda9279dSmrg * @param id colorspace of image 1521fda9279dSmrg * @param w pointer to width of image 1522fda9279dSmrg * @param h pointer to height of image 1523fda9279dSmrg * @param pitches pitches[i] = length of a scanline in plane[i] 1524fda9279dSmrg * @param offsets offsets[i] = offset of plane i from the beginning of the image 1525fda9279dSmrg * @return size of the memory required for the XvImage queried 1526fda9279dSmrg */ 1527fda9279dSmrgstatic int 1528fda9279dSmrgNVQueryImageAttributes(ScrnInfoPtr pScrn, int id, 1529fda9279dSmrg unsigned short *w, unsigned short *h, 1530fda9279dSmrg int *pitches, int *offsets) 1531fda9279dSmrg{ 1532fda9279dSmrg int size, tmp; 1533fda9279dSmrg 1534fda9279dSmrg *w = (*w + 1) & ~1; // width rounded up to an even number 1535fda9279dSmrg if (offsets) 1536fda9279dSmrg offsets[0] = 0; 1537fda9279dSmrg 1538fda9279dSmrg switch (id) { 1539fda9279dSmrg case FOURCC_YV12: 1540fda9279dSmrg case FOURCC_I420: 1541fda9279dSmrg *h = (*h + 1) & ~1; // height rounded up to an even number 1542fda9279dSmrg size = (*w + 3) & ~3; // width rounded up to a multiple of 4 1543fda9279dSmrg if (pitches) 1544fda9279dSmrg pitches[0] = size; // width rounded up to a multiple of 4 1545fda9279dSmrg size *= *h; 1546fda9279dSmrg if (offsets) 1547fda9279dSmrg offsets[1] = size; // number of pixels in "rounded up" image 1548fda9279dSmrg tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4 1549fda9279dSmrg if (pitches) 1550fda9279dSmrg pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4 1551fda9279dSmrg tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image 1552fda9279dSmrg size += tmp; // 5/4*number of pixels in "rounded up" image 1553fda9279dSmrg if (offsets) 1554fda9279dSmrg offsets[2] = size; // 5/4*number of pixels in "rounded up" image 1555fda9279dSmrg size += tmp; // = 3/2*number of pixels in "rounded up" image 1556fda9279dSmrg break; 1557fda9279dSmrg case FOURCC_UYVY: 1558fda9279dSmrg case FOURCC_YUY2: 1559fda9279dSmrg size = *w << 1; // 2*width 1560fda9279dSmrg if (pitches) 1561fda9279dSmrg pitches[0] = size; // 2*width 1562fda9279dSmrg size *= *h; // 2*width*height 1563fda9279dSmrg break; 1564fda9279dSmrg case FOURCC_RGB: 1565fda9279dSmrg size = *w << 2; // 4*width (32 bit per pixel) 1566fda9279dSmrg if (pitches) 1567fda9279dSmrg pitches[0] = size; // 4*width 1568fda9279dSmrg size *= *h; // 4*width*height 1569fda9279dSmrg break; 1570fda9279dSmrg case FOURCC_AI44: 1571fda9279dSmrg case FOURCC_IA44: 1572fda9279dSmrg size = *w; // width 1573fda9279dSmrg if (pitches) 1574fda9279dSmrg pitches[0] = size; // width 1575fda9279dSmrg size *= *h; // width*height 1576fda9279dSmrg break; 1577fda9279dSmrg default: 1578fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown colorspace: %x\n", id); 1579fda9279dSmrg *w = *h = size = 0; 1580fda9279dSmrg break; 1581fda9279dSmrg } 1582fda9279dSmrg 1583fda9279dSmrg return size; 1584fda9279dSmrg} 1585fda9279dSmrg 1586fda9279dSmrg/***** Exported offscreen surface stuff ****/ 1587fda9279dSmrg 1588fda9279dSmrg 1589fda9279dSmrgstatic int 1590fda9279dSmrgNVAllocSurface(ScrnInfoPtr pScrn, int id, 1591fda9279dSmrg unsigned short w, unsigned short h, 1592fda9279dSmrg XF86SurfacePtr surface) 1593fda9279dSmrg{ 1594fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1595fda9279dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 1596fda9279dSmrg int size, bpp, ret; 1597fda9279dSmrg 1598fda9279dSmrg bpp = pScrn->bitsPerPixel >> 3; 1599fda9279dSmrg 1600fda9279dSmrg if (pPriv->grabbedByV4L) 1601fda9279dSmrg return BadAlloc; 1602fda9279dSmrg 1603fda9279dSmrg if ((w > IMAGE_MAX_W) || (h > IMAGE_MAX_H)) 1604fda9279dSmrg return BadValue; 1605fda9279dSmrg 1606fda9279dSmrg w = (w + 1) & ~1; 1607fda9279dSmrg pPriv->pitch = ((w << 1) + 63) & ~63; 1608fda9279dSmrg size = h * pPriv->pitch / bpp; 1609fda9279dSmrg 1610fda9279dSmrg ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, size, 1611fda9279dSmrg &pPriv->video_mem); 1612fda9279dSmrg if (ret) 1613fda9279dSmrg return BadAlloc; 1614fda9279dSmrg pPriv->offset = 0; 1615fda9279dSmrg 1616fda9279dSmrg surface->width = w; 1617fda9279dSmrg surface->height = h; 1618fda9279dSmrg surface->pScrn = pScrn; 1619fda9279dSmrg surface->pitches = &pPriv->pitch; 1620fda9279dSmrg surface->offsets = &pPriv->offset; 1621fda9279dSmrg surface->devPrivate.ptr = (pointer)pPriv; 1622fda9279dSmrg surface->id = id; 1623fda9279dSmrg 1624fda9279dSmrg /* grab the video */ 1625fda9279dSmrg NVStopOverlay(pScrn); 1626fda9279dSmrg pPriv->videoStatus = 0; 1627fda9279dSmrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 1628fda9279dSmrg pPriv->grabbedByV4L = TRUE; 1629fda9279dSmrg 1630fda9279dSmrg return Success; 1631fda9279dSmrg} 1632fda9279dSmrg 1633fda9279dSmrgstatic int 1634fda9279dSmrgNVStopSurface(XF86SurfacePtr surface) 1635fda9279dSmrg{ 1636fda9279dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); 1637fda9279dSmrg 1638fda9279dSmrg if (pPriv->grabbedByV4L && pPriv->videoStatus) { 1639fda9279dSmrg NV10StopOverlay(surface->pScrn); 1640fda9279dSmrg pPriv->videoStatus = 0; 1641fda9279dSmrg } 1642fda9279dSmrg 1643fda9279dSmrg return Success; 1644fda9279dSmrg} 1645fda9279dSmrg 1646fda9279dSmrgstatic int 1647fda9279dSmrgNVFreeSurface(XF86SurfacePtr surface) 1648fda9279dSmrg{ 1649fda9279dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); 1650fda9279dSmrg 1651fda9279dSmrg if (pPriv->grabbedByV4L) { 1652fda9279dSmrg NVStopSurface(surface); 1653fda9279dSmrg NVFreeOverlayMemory(surface->pScrn); 1654fda9279dSmrg pPriv->grabbedByV4L = FALSE; 1655fda9279dSmrg } 1656fda9279dSmrg 1657fda9279dSmrg return Success; 1658fda9279dSmrg} 1659fda9279dSmrg 1660fda9279dSmrgstatic int 1661fda9279dSmrgNVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value) 1662fda9279dSmrg{ 1663fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1664fda9279dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 1665fda9279dSmrg 1666fda9279dSmrg return NV10GetOverlayPortAttribute(pScrn, attribute, 1667fda9279dSmrg value, (pointer)pPriv); 1668fda9279dSmrg} 1669fda9279dSmrg 1670fda9279dSmrgstatic int 1671fda9279dSmrgNVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value) 1672fda9279dSmrg{ 1673fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1674fda9279dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 1675fda9279dSmrg 1676fda9279dSmrg return NV10SetOverlayPortAttribute(pScrn, attribute, 1677fda9279dSmrg value, (pointer)pPriv); 1678fda9279dSmrg} 1679fda9279dSmrg 1680fda9279dSmrgstatic int 1681fda9279dSmrgNVDisplaySurface(XF86SurfacePtr surface, 1682fda9279dSmrg short src_x, short src_y, 1683fda9279dSmrg short drw_x, short drw_y, 1684fda9279dSmrg short src_w, short src_h, 1685fda9279dSmrg short drw_w, short drw_h, 1686fda9279dSmrg RegionPtr clipBoxes) 1687fda9279dSmrg{ 1688fda9279dSmrg ScrnInfoPtr pScrn = surface->pScrn; 1689fda9279dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); 1690fda9279dSmrg INT32 xa, xb, ya, yb; 1691fda9279dSmrg BoxRec dstBox; 1692fda9279dSmrg 1693fda9279dSmrg if (!pPriv->grabbedByV4L) 1694fda9279dSmrg return Success; 1695fda9279dSmrg 1696fda9279dSmrg if (src_w > (drw_w << 3)) 1697fda9279dSmrg drw_w = src_w >> 3; 1698fda9279dSmrg if (src_h > (drw_h << 3)) 1699fda9279dSmrg drw_h = src_h >> 3; 1700fda9279dSmrg 1701fda9279dSmrg /* Clip */ 1702fda9279dSmrg xa = src_x; 1703fda9279dSmrg xb = src_x + src_w; 1704fda9279dSmrg ya = src_y; 1705fda9279dSmrg yb = src_y + src_h; 1706fda9279dSmrg 1707fda9279dSmrg dstBox.x1 = drw_x; 1708fda9279dSmrg dstBox.x2 = drw_x + drw_w; 1709fda9279dSmrg dstBox.y1 = drw_y; 1710fda9279dSmrg dstBox.y2 = drw_y + drw_h; 1711fda9279dSmrg 1712fda9279dSmrg if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, 1713fda9279dSmrg surface->width, surface->height)) 1714fda9279dSmrg return Success; 1715fda9279dSmrg 1716fda9279dSmrg dstBox.x1 -= pScrn->frameX0; 1717fda9279dSmrg dstBox.x2 -= pScrn->frameX0; 1718fda9279dSmrg dstBox.y1 -= pScrn->frameY0; 1719fda9279dSmrg dstBox.y2 -= pScrn->frameY0; 1720fda9279dSmrg 1721fda9279dSmrg pPriv->currentBuffer = 0; 1722fda9279dSmrg 1723fda9279dSmrg NV10PutOverlayImage(pScrn, pPriv->video_mem, surface->offsets[0], 1724fda9279dSmrg 0, surface->id, surface->pitches[0], &dstBox, 1725fda9279dSmrg xa, ya, xb, yb, surface->width, surface->height, 1726fda9279dSmrg src_w, src_h, drw_w, drw_h, clipBoxes); 1727fda9279dSmrg 1728fda9279dSmrg return Success; 1729fda9279dSmrg} 1730fda9279dSmrg 1731fda9279dSmrg/** 1732fda9279dSmrg * NVSetupBlitVideo 1733fda9279dSmrg * this function does all the work setting up a blit port 1734fda9279dSmrg * 1735fda9279dSmrg * @return blit port 1736fda9279dSmrg */ 1737fda9279dSmrgstatic XF86VideoAdaptorPtr 1738fda9279dSmrgNVSetupBlitVideo (ScreenPtr pScreen) 1739fda9279dSmrg{ 1740fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1741fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1742fda9279dSmrg XF86VideoAdaptorPtr adapt; 1743fda9279dSmrg NVPortPrivPtr pPriv; 1744fda9279dSmrg int i; 1745fda9279dSmrg 1746fda9279dSmrg if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 1747fda9279dSmrg sizeof(NVPortPrivRec) + 1748fda9279dSmrg (sizeof(DevUnion) * NUM_BLIT_PORTS)))) { 1749fda9279dSmrg return NULL; 1750fda9279dSmrg } 1751fda9279dSmrg 1752fda9279dSmrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 1753fda9279dSmrg adapt->flags = 0; 1754fda9279dSmrg adapt->name = "NV Video Blitter"; 1755fda9279dSmrg adapt->nEncodings = 1; 1756fda9279dSmrg adapt->pEncodings = &DummyEncoding; 1757fda9279dSmrg adapt->nFormats = NUM_FORMATS_ALL; 1758fda9279dSmrg adapt->pFormats = NVFormats; 1759fda9279dSmrg adapt->nPorts = NUM_BLIT_PORTS; 1760fda9279dSmrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 1761fda9279dSmrg 1762fda9279dSmrg pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]); 1763fda9279dSmrg for(i = 0; i < NUM_BLIT_PORTS; i++) 1764fda9279dSmrg adapt->pPortPrivates[i].ptr = (pointer)(pPriv); 1765fda9279dSmrg 1766fda9279dSmrg if (pNv->dev->chipset >= 0x11) { 1767fda9279dSmrg adapt->pAttributes = NVBlitAttributes; 1768fda9279dSmrg adapt->nAttributes = NUM_BLIT_ATTRIBUTES; 1769fda9279dSmrg } else { 1770fda9279dSmrg adapt->pAttributes = NULL; 1771fda9279dSmrg adapt->nAttributes = 0; 1772fda9279dSmrg } 1773fda9279dSmrg 1774fda9279dSmrg adapt->pImages = NVImages; 1775fda9279dSmrg adapt->nImages = NUM_IMAGES_ALL; 1776fda9279dSmrg adapt->PutVideo = NULL; 1777fda9279dSmrg adapt->PutStill = NULL; 1778fda9279dSmrg adapt->GetVideo = NULL; 1779fda9279dSmrg adapt->GetStill = NULL; 1780fda9279dSmrg adapt->StopVideo = NVStopBlitVideo; 1781fda9279dSmrg adapt->SetPortAttribute = NVSetBlitPortAttribute; 1782fda9279dSmrg adapt->GetPortAttribute = NVGetBlitPortAttribute; 1783fda9279dSmrg adapt->QueryBestSize = NVQueryBestSize; 1784fda9279dSmrg adapt->PutImage = NVPutImage; 1785fda9279dSmrg adapt->QueryImageAttributes = NVQueryImageAttributes; 1786fda9279dSmrg 1787fda9279dSmrg pPriv->videoStatus = 0; 1788fda9279dSmrg pPriv->grabbedByV4L = FALSE; 1789fda9279dSmrg pPriv->blitter = TRUE; 1790fda9279dSmrg pPriv->texture = FALSE; 1791fda9279dSmrg pPriv->bicubic = FALSE; 1792fda9279dSmrg pPriv->doubleBuffer = FALSE; 1793fda9279dSmrg pPriv->SyncToVBlank = (pNv->dev->chipset >= 0x11); 179416ee1e9aSmrg pPriv->max_image_dim = 2048; 1795fda9279dSmrg 1796fda9279dSmrg pNv->blitAdaptor = adapt; 1797fda9279dSmrg 1798fda9279dSmrg return adapt; 1799fda9279dSmrg} 1800fda9279dSmrg 1801fda9279dSmrg/** 1802fda9279dSmrg * NVSetupOverlayVideo 1803fda9279dSmrg * this function does all the work setting up an overlay port 1804fda9279dSmrg * 1805fda9279dSmrg * @return overlay port 1806fda9279dSmrg */ 1807fda9279dSmrgstatic XF86VideoAdaptorPtr 1808fda9279dSmrgNVSetupOverlayVideoAdapter(ScreenPtr pScreen) 1809fda9279dSmrg{ 1810fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1811fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1812fda9279dSmrg XF86VideoAdaptorPtr adapt; 1813fda9279dSmrg NVPortPrivPtr pPriv; 1814fda9279dSmrg 1815fda9279dSmrg if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 1816fda9279dSmrg sizeof(NVPortPrivRec) + 1817fda9279dSmrg sizeof(DevUnion)))) { 1818fda9279dSmrg return NULL; 1819fda9279dSmrg } 1820fda9279dSmrg 1821fda9279dSmrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 1822fda9279dSmrg adapt->flags = VIDEO_OVERLAID_IMAGES; 1823fda9279dSmrg adapt->name = "NV Video Overlay"; 1824fda9279dSmrg adapt->nEncodings = 1; 1825fda9279dSmrg adapt->pEncodings = &DummyEncoding; 1826fda9279dSmrg adapt->nFormats = NUM_FORMATS_ALL; 1827fda9279dSmrg adapt->pFormats = NVFormats; 1828fda9279dSmrg adapt->nPorts = 1; 1829fda9279dSmrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 1830fda9279dSmrg 1831fda9279dSmrg pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]); 1832fda9279dSmrg adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 1833fda9279dSmrg 1834fda9279dSmrg adapt->pAttributes = (pNv->Architecture != NV_ARCH_04) ? NV10OverlayAttributes : NV04OverlayAttributes; 1835fda9279dSmrg adapt->nAttributes = (pNv->Architecture != NV_ARCH_04) ? NUM_NV10_OVERLAY_ATTRIBUTES : NUM_NV04_OVERLAY_ATTRIBUTES; 1836fda9279dSmrg adapt->pImages = NVImages; 1837fda9279dSmrg adapt->nImages = NUM_IMAGES_YUV; 1838fda9279dSmrg adapt->PutVideo = NULL; 1839fda9279dSmrg adapt->PutStill = NULL; 1840fda9279dSmrg adapt->GetVideo = NULL; 1841fda9279dSmrg adapt->GetStill = NULL; 1842fda9279dSmrg adapt->StopVideo = NVStopOverlayVideo; 1843fda9279dSmrg adapt->SetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10SetOverlayPortAttribute : NV04SetOverlayPortAttribute; 1844fda9279dSmrg adapt->GetPortAttribute = (pNv->Architecture != NV_ARCH_04) ? NV10GetOverlayPortAttribute : NV04GetOverlayPortAttribute; 1845fda9279dSmrg adapt->QueryBestSize = NVQueryBestSize; 1846fda9279dSmrg adapt->PutImage = NVPutImage; 1847fda9279dSmrg adapt->QueryImageAttributes = NVQueryImageAttributes; 1848fda9279dSmrg 1849fda9279dSmrg pPriv->videoStatus = 0; 1850fda9279dSmrg pPriv->currentBuffer = 0; 1851fda9279dSmrg pPriv->grabbedByV4L = FALSE; 1852fda9279dSmrg pPriv->blitter = FALSE; 1853fda9279dSmrg pPriv->texture = FALSE; 1854fda9279dSmrg pPriv->bicubic = FALSE; 185516ee1e9aSmrg pPriv->max_image_dim = 2048; 1856fda9279dSmrg 1857fda9279dSmrg NVSetPortDefaults (pScrn, pPriv); 1858fda9279dSmrg 1859fda9279dSmrg /* gotta uninit this someplace */ 1860fda9279dSmrg REGION_NULL(pScreen, &pPriv->clip); 1861fda9279dSmrg 1862fda9279dSmrg pNv->overlayAdaptor = adapt; 1863fda9279dSmrg 1864fda9279dSmrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 1865fda9279dSmrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 1866fda9279dSmrg xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); 1867fda9279dSmrg xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); 1868fda9279dSmrg 1869fda9279dSmrg if ( pNv->Architecture != NV_ARCH_04 ) 1870fda9279dSmrg { 1871fda9279dSmrg xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); 1872fda9279dSmrg xvContrast = MAKE_ATOM("XV_CONTRAST"); 1873fda9279dSmrg xvSaturation = MAKE_ATOM("XV_SATURATION"); 1874fda9279dSmrg xvHue = MAKE_ATOM("XV_HUE"); 1875fda9279dSmrg xvITURBT709 = MAKE_ATOM("XV_ITURBT_709"); 1876fda9279dSmrg xvOnCRTCNb = MAKE_ATOM("XV_ON_CRTC_NB"); 1877fda9279dSmrg NV10WriteOverlayParameters(pScrn); 1878fda9279dSmrg } 1879fda9279dSmrg 1880fda9279dSmrg return adapt; 1881fda9279dSmrg} 1882fda9279dSmrg 1883fda9279dSmrg 1884fda9279dSmrgXF86OffscreenImageRec NVOffscreenImages[2] = { 1885fda9279dSmrg { 1886fda9279dSmrg &NVImages[0], 1887fda9279dSmrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 1888fda9279dSmrg NVAllocSurface, 1889fda9279dSmrg NVFreeSurface, 1890fda9279dSmrg NVDisplaySurface, 1891fda9279dSmrg NVStopSurface, 1892fda9279dSmrg NVGetSurfaceAttribute, 1893fda9279dSmrg NVSetSurfaceAttribute, 1894fda9279dSmrg IMAGE_MAX_W, IMAGE_MAX_H, 1895fda9279dSmrg NUM_NV10_OVERLAY_ATTRIBUTES - 1, 1896fda9279dSmrg &NV10OverlayAttributes[1] 1897fda9279dSmrg }, 1898fda9279dSmrg { 1899fda9279dSmrg &NVImages[2], 1900fda9279dSmrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 1901fda9279dSmrg NVAllocSurface, 1902fda9279dSmrg NVFreeSurface, 1903fda9279dSmrg NVDisplaySurface, 1904fda9279dSmrg NVStopSurface, 1905fda9279dSmrg NVGetSurfaceAttribute, 1906fda9279dSmrg NVSetSurfaceAttribute, 1907fda9279dSmrg IMAGE_MAX_W, IMAGE_MAX_H, 1908fda9279dSmrg NUM_NV10_OVERLAY_ATTRIBUTES - 1, 1909fda9279dSmrg &NV10OverlayAttributes[1] 1910fda9279dSmrg } 1911fda9279dSmrg}; 1912fda9279dSmrg 1913fda9279dSmrgstatic void 1914fda9279dSmrgNVInitOffscreenImages (ScreenPtr pScreen) 1915fda9279dSmrg{ 1916fda9279dSmrg xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2); 1917fda9279dSmrg} 1918fda9279dSmrg 1919fda9279dSmrg/** 1920fda9279dSmrg * NVChipsetHasOverlay 1921fda9279dSmrg * 1922fda9279dSmrg * newer chips don't support overlay anymore. 1923fda9279dSmrg * overlay feature is emulated via textures. 1924fda9279dSmrg * 1925fda9279dSmrg * @param pNv 1926fda9279dSmrg * @return true, if chipset supports overlay 1927fda9279dSmrg */ 1928fda9279dSmrgstatic Bool 1929fda9279dSmrgNVChipsetHasOverlay(NVPtr pNv) 1930fda9279dSmrg{ 1931fda9279dSmrg switch (pNv->Architecture) { 1932fda9279dSmrg case NV_ARCH_04: /*NV04 has a different overlay than NV10+*/ 1933fda9279dSmrg case NV_ARCH_10: 1934fda9279dSmrg case NV_ARCH_20: 1935fda9279dSmrg case NV_ARCH_30: 1936fda9279dSmrg return TRUE; 1937fda9279dSmrg case NV_ARCH_40: 1938fda9279dSmrg if (pNv->dev->chipset == 0x40) 1939fda9279dSmrg return TRUE; 1940fda9279dSmrg break; 1941fda9279dSmrg default: 1942fda9279dSmrg break; 1943fda9279dSmrg } 1944fda9279dSmrg 1945fda9279dSmrg return FALSE; 1946fda9279dSmrg} 1947fda9279dSmrg 1948fda9279dSmrg/** 1949fda9279dSmrg * NVSetupOverlayVideo 1950fda9279dSmrg * check if chipset supports Overla 1951fda9279dSmrg * if so, setup overlay port 1952fda9279dSmrg * 1953fda9279dSmrg * @return overlay port 1954fda9279dSmrg * @see NVChipsetHasOverlay(NVPtr pNv) 1955fda9279dSmrg * @see NV10SetupOverlayVideo(ScreenPtr pScreen) 1956fda9279dSmrg * @see NVInitOffscreenImages(ScreenPtr pScreen) 1957fda9279dSmrg */ 1958fda9279dSmrgstatic XF86VideoAdaptorPtr 1959fda9279dSmrgNVSetupOverlayVideo(ScreenPtr pScreen) 1960fda9279dSmrg{ 1961fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1962fda9279dSmrg XF86VideoAdaptorPtr overlayAdaptor = NULL; 1963fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 1964fda9279dSmrg 1965fda9279dSmrg if (1 /*pNv->kms_enable*/ || !NVChipsetHasOverlay(pNv)) 1966fda9279dSmrg return NULL; 1967fda9279dSmrg 1968fda9279dSmrg overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen); 1969fda9279dSmrg /* I am not sure what this call does. */ 1970fda9279dSmrg if (overlayAdaptor && pNv->Architecture != NV_ARCH_04 ) 1971fda9279dSmrg NVInitOffscreenImages(pScreen); 1972fda9279dSmrg 1973fda9279dSmrg #ifdef COMPOSITE 1974fda9279dSmrg if (!noCompositeExtension) { 1975fda9279dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1976fda9279dSmrg "Xv: Composite is enabled, enabling overlay with " 1977fda9279dSmrg "smart blitter fallback\n"); 1978fda9279dSmrg overlayAdaptor->name = "NV Video Overlay with Composite"; 1979fda9279dSmrg } 1980fda9279dSmrg #endif 1981fda9279dSmrg 1982fda9279dSmrg return overlayAdaptor; 1983fda9279dSmrg} 1984fda9279dSmrg 1985fda9279dSmrg/** 1986fda9279dSmrg * NV30 texture adapter. 1987fda9279dSmrg */ 1988fda9279dSmrg 1989fda9279dSmrg#define NUM_FORMAT_TEXTURED 2 1990fda9279dSmrg 1991fda9279dSmrgstatic XF86ImageRec NV30TexturedImages[NUM_FORMAT_TEXTURED] = 1992fda9279dSmrg{ 1993fda9279dSmrg XVIMAGE_YV12, 1994fda9279dSmrg XVIMAGE_I420, 1995fda9279dSmrg}; 1996fda9279dSmrg 1997fda9279dSmrg/** 1998fda9279dSmrg * NV30SetupTexturedVideo 1999fda9279dSmrg * this function does all the work setting up textured video port 2000fda9279dSmrg * 2001fda9279dSmrg * @return texture port 2002fda9279dSmrg */ 2003fda9279dSmrgstatic XF86VideoAdaptorPtr 2004fda9279dSmrgNV30SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic) 2005fda9279dSmrg{ 2006fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2007fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 2008fda9279dSmrg XF86VideoAdaptorPtr adapt; 2009fda9279dSmrg NVPortPrivPtr pPriv; 2010fda9279dSmrg int i; 2011fda9279dSmrg 2012fda9279dSmrg if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 2013fda9279dSmrg sizeof(NVPortPrivRec) + 2014fda9279dSmrg (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) { 2015fda9279dSmrg return NULL; 2016fda9279dSmrg } 2017fda9279dSmrg 2018fda9279dSmrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 2019fda9279dSmrg adapt->flags = 0; 2020fda9279dSmrg if (bicubic) 2021fda9279dSmrg adapt->name = "NV30 high quality adapter"; 2022fda9279dSmrg else 2023fda9279dSmrg adapt->name = "NV30 texture adapter"; 2024fda9279dSmrg adapt->nEncodings = 1; 2025fda9279dSmrg adapt->pEncodings = &DummyEncodingTex; 2026fda9279dSmrg adapt->nFormats = NUM_FORMATS_ALL; 2027fda9279dSmrg adapt->pFormats = NVFormats; 2028fda9279dSmrg adapt->nPorts = NUM_TEXTURE_PORTS; 2029fda9279dSmrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 2030fda9279dSmrg 2031fda9279dSmrg pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]); 2032fda9279dSmrg for(i = 0; i < NUM_TEXTURE_PORTS; i++) 2033fda9279dSmrg adapt->pPortPrivates[i].ptr = (pointer)(pPriv); 2034fda9279dSmrg 2035fda9279dSmrg adapt->pAttributes = NVTexturedAttributes; 2036fda9279dSmrg adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES; 2037fda9279dSmrg adapt->pImages = NV30TexturedImages; 2038fda9279dSmrg adapt->nImages = NUM_FORMAT_TEXTURED; 2039fda9279dSmrg adapt->PutVideo = NULL; 2040fda9279dSmrg adapt->PutStill = NULL; 2041fda9279dSmrg adapt->GetVideo = NULL; 2042fda9279dSmrg adapt->GetStill = NULL; 2043fda9279dSmrg adapt->StopVideo = NV30StopTexturedVideo; 2044fda9279dSmrg adapt->SetPortAttribute = NV30SetTexturePortAttribute; 2045fda9279dSmrg adapt->GetPortAttribute = NV30GetTexturePortAttribute; 2046fda9279dSmrg adapt->QueryBestSize = NVQueryBestSize; 2047fda9279dSmrg adapt->PutImage = NVPutImage; 2048fda9279dSmrg adapt->QueryImageAttributes = NVQueryImageAttributes; 2049fda9279dSmrg 2050fda9279dSmrg pPriv->videoStatus = 0; 2051fda9279dSmrg pPriv->grabbedByV4L = FALSE; 2052fda9279dSmrg pPriv->blitter = FALSE; 2053fda9279dSmrg pPriv->texture = TRUE; 2054fda9279dSmrg pPriv->bicubic = bicubic; 2055fda9279dSmrg pPriv->doubleBuffer = FALSE; 2056fda9279dSmrg pPriv->SyncToVBlank = TRUE; 205716ee1e9aSmrg pPriv->max_image_dim = 4096; 2058fda9279dSmrg 2059fda9279dSmrg if (bicubic) 2060fda9279dSmrg pNv->textureAdaptor[1] = adapt; 2061fda9279dSmrg else 2062fda9279dSmrg pNv->textureAdaptor[0] = adapt; 2063fda9279dSmrg 2064fda9279dSmrg return adapt; 2065fda9279dSmrg} 2066fda9279dSmrg 2067fda9279dSmrg/** 2068fda9279dSmrg * NV40 texture adapter. 2069fda9279dSmrg */ 2070fda9279dSmrg 2071fda9279dSmrg#define NUM_FORMAT_TEXTURED 2 2072fda9279dSmrg 2073fda9279dSmrgstatic XF86ImageRec NV40TexturedImages[NUM_FORMAT_TEXTURED] = 2074fda9279dSmrg{ 2075fda9279dSmrg XVIMAGE_YV12, 2076fda9279dSmrg XVIMAGE_I420, 2077fda9279dSmrg}; 2078fda9279dSmrg 2079fda9279dSmrg/** 2080fda9279dSmrg * NV40SetupTexturedVideo 2081fda9279dSmrg * this function does all the work setting up textured video port 2082fda9279dSmrg * 2083fda9279dSmrg * @return texture port 2084fda9279dSmrg */ 2085fda9279dSmrgstatic XF86VideoAdaptorPtr 2086fda9279dSmrgNV40SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic) 2087fda9279dSmrg{ 2088fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2089fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 2090fda9279dSmrg XF86VideoAdaptorPtr adapt; 2091fda9279dSmrg NVPortPrivPtr pPriv; 2092fda9279dSmrg int i; 2093fda9279dSmrg 2094fda9279dSmrg if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 2095fda9279dSmrg sizeof(NVPortPrivRec) + 2096fda9279dSmrg (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) { 2097fda9279dSmrg return NULL; 2098fda9279dSmrg } 2099fda9279dSmrg 2100fda9279dSmrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 2101fda9279dSmrg adapt->flags = 0; 2102fda9279dSmrg if (bicubic) 2103fda9279dSmrg adapt->name = "NV40 high quality adapter"; 2104fda9279dSmrg else 2105fda9279dSmrg adapt->name = "NV40 texture adapter"; 2106fda9279dSmrg adapt->nEncodings = 1; 2107fda9279dSmrg adapt->pEncodings = &DummyEncodingTex; 2108fda9279dSmrg adapt->nFormats = NUM_FORMATS_ALL; 2109fda9279dSmrg adapt->pFormats = NVFormats; 2110fda9279dSmrg adapt->nPorts = NUM_TEXTURE_PORTS; 2111fda9279dSmrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 2112fda9279dSmrg 2113fda9279dSmrg pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]); 2114fda9279dSmrg for(i = 0; i < NUM_TEXTURE_PORTS; i++) 2115fda9279dSmrg adapt->pPortPrivates[i].ptr = (pointer)(pPriv); 2116fda9279dSmrg 2117fda9279dSmrg adapt->pAttributes = NVTexturedAttributes; 2118fda9279dSmrg adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES; 2119fda9279dSmrg adapt->pImages = NV40TexturedImages; 2120fda9279dSmrg adapt->nImages = NUM_FORMAT_TEXTURED; 2121fda9279dSmrg adapt->PutVideo = NULL; 2122fda9279dSmrg adapt->PutStill = NULL; 2123fda9279dSmrg adapt->GetVideo = NULL; 2124fda9279dSmrg adapt->GetStill = NULL; 2125fda9279dSmrg adapt->StopVideo = NV40StopTexturedVideo; 2126fda9279dSmrg adapt->SetPortAttribute = NV40SetTexturePortAttribute; 2127fda9279dSmrg adapt->GetPortAttribute = NV40GetTexturePortAttribute; 2128fda9279dSmrg adapt->QueryBestSize = NVQueryBestSize; 2129fda9279dSmrg adapt->PutImage = NVPutImage; 2130fda9279dSmrg adapt->QueryImageAttributes = NVQueryImageAttributes; 2131fda9279dSmrg 2132fda9279dSmrg pPriv->videoStatus = 0; 2133fda9279dSmrg pPriv->grabbedByV4L = FALSE; 2134fda9279dSmrg pPriv->blitter = FALSE; 2135fda9279dSmrg pPriv->texture = TRUE; 2136fda9279dSmrg pPriv->bicubic = bicubic; 2137fda9279dSmrg pPriv->doubleBuffer = FALSE; 2138fda9279dSmrg pPriv->SyncToVBlank = TRUE; 213916ee1e9aSmrg pPriv->max_image_dim = 4096; 2140fda9279dSmrg 2141fda9279dSmrg if (bicubic) 2142fda9279dSmrg pNv->textureAdaptor[1] = adapt; 2143fda9279dSmrg else 2144fda9279dSmrg pNv->textureAdaptor[0] = adapt; 2145fda9279dSmrg 2146fda9279dSmrg return adapt; 2147fda9279dSmrg} 2148fda9279dSmrg 2149fda9279dSmrgstatic XF86ImageRec 2150fda9279dSmrgNV50TexturedImages[] = 2151fda9279dSmrg{ 2152fda9279dSmrg XVIMAGE_YV12, 2153fda9279dSmrg XVIMAGE_I420, 2154fda9279dSmrg XVIMAGE_YUY2, 2155fda9279dSmrg XVIMAGE_UYVY 2156fda9279dSmrg}; 2157fda9279dSmrg 2158fda9279dSmrgstatic XF86VideoAdaptorPtr 2159fda9279dSmrgNV50SetupTexturedVideo (ScreenPtr pScreen) 2160fda9279dSmrg{ 2161fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2162fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 2163fda9279dSmrg XF86VideoAdaptorPtr adapt; 2164fda9279dSmrg NVPortPrivPtr pPriv; 2165fda9279dSmrg int i; 2166fda9279dSmrg 2167fda9279dSmrg if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 2168fda9279dSmrg sizeof(NVPortPrivRec) + 2169fda9279dSmrg (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) { 2170fda9279dSmrg return NULL; 2171fda9279dSmrg } 2172fda9279dSmrg 2173fda9279dSmrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 2174fda9279dSmrg adapt->flags = 0; 2175fda9279dSmrg adapt->name = "Nouveau GeForce 8/9 Textured Video"; 2176fda9279dSmrg adapt->nEncodings = 1; 2177fda9279dSmrg adapt->pEncodings = &DummyEncodingNV50; 217822d74663Smrg adapt->nFormats = NUM_FORMATS_NV50; 217922d74663Smrg adapt->pFormats = NV50Formats; 2180fda9279dSmrg adapt->nPorts = NUM_TEXTURE_PORTS; 2181fda9279dSmrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 2182fda9279dSmrg 2183fda9279dSmrg pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]); 2184fda9279dSmrg for(i = 0; i < NUM_TEXTURE_PORTS; i++) 2185fda9279dSmrg adapt->pPortPrivates[i].ptr = (pointer)(pPriv); 2186fda9279dSmrg 2187fda9279dSmrg adapt->pAttributes = NVTexturedAttributesNV50; 2188fda9279dSmrg adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES_NV50; 2189fda9279dSmrg adapt->pImages = NV50TexturedImages; 2190fda9279dSmrg adapt->nImages = sizeof(NV50TexturedImages) / 2191fda9279dSmrg sizeof(NV50TexturedImages[0]); 2192fda9279dSmrg adapt->PutVideo = NULL; 2193fda9279dSmrg adapt->PutStill = NULL; 2194fda9279dSmrg adapt->GetVideo = NULL; 2195fda9279dSmrg adapt->GetStill = NULL; 2196fda9279dSmrg adapt->StopVideo = nv50_xv_video_stop; 2197fda9279dSmrg adapt->SetPortAttribute = nv50_xv_port_attribute_set; 2198fda9279dSmrg adapt->GetPortAttribute = nv50_xv_port_attribute_get; 2199fda9279dSmrg adapt->QueryBestSize = NVQueryBestSize; 2200fda9279dSmrg adapt->PutImage = NVPutImage; 2201fda9279dSmrg adapt->QueryImageAttributes = NVQueryImageAttributes; 2202fda9279dSmrg 2203fda9279dSmrg pNv->textureAdaptor[0] = adapt; 2204fda9279dSmrg 2205fda9279dSmrg nv50_xv_set_port_defaults(pScrn, pPriv); 2206fda9279dSmrg nv50_xv_csc_update(pScrn, pPriv); 2207fda9279dSmrg 2208fda9279dSmrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 2209fda9279dSmrg xvContrast = MAKE_ATOM("XV_CONTRAST"); 2210fda9279dSmrg xvSaturation = MAKE_ATOM("XV_SATURATION"); 2211fda9279dSmrg xvHue = MAKE_ATOM("XV_HUE"); 2212fda9279dSmrg xvITURBT709 = MAKE_ATOM("XV_ITURBT_709"); 2213fda9279dSmrg return adapt; 2214fda9279dSmrg} 2215fda9279dSmrg 221622d74663Smrgstatic void 2217fda9279dSmrgNVSetupTexturedVideo (ScreenPtr pScreen, XF86VideoAdaptorPtr *textureAdaptor) 2218fda9279dSmrg{ 2219fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2220fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 2221fda9279dSmrg 2222fda9279dSmrg if (!pNv->Nv3D) 2223fda9279dSmrg return; 2224fda9279dSmrg 2225fda9279dSmrg if (pNv->Architecture == NV_ARCH_30) { 2226fda9279dSmrg textureAdaptor[0] = NV30SetupTexturedVideo(pScreen, FALSE); 2227fda9279dSmrg textureAdaptor[1] = NV30SetupTexturedVideo(pScreen, TRUE); 2228fda9279dSmrg } else 2229fda9279dSmrg if (pNv->Architecture == NV_ARCH_40) { 2230fda9279dSmrg textureAdaptor[0] = NV40SetupTexturedVideo(pScreen, FALSE); 2231fda9279dSmrg textureAdaptor[1] = NV40SetupTexturedVideo(pScreen, TRUE); 2232fda9279dSmrg } else 22331090d90aSmrg if (pNv->Architecture >= NV_TESLA) { 2234fda9279dSmrg textureAdaptor[0] = NV50SetupTexturedVideo(pScreen); 2235fda9279dSmrg } 2236fda9279dSmrg} 2237fda9279dSmrg 2238fda9279dSmrg/** 2239fda9279dSmrg * NVInitVideo 2240fda9279dSmrg * tries to initialize the various supported adapters 2241fda9279dSmrg * and add them to the list of ports on screen "pScreen". 2242fda9279dSmrg * 2243fda9279dSmrg * @param pScreen 2244fda9279dSmrg * @see NVSetupOverlayVideo(ScreenPtr pScreen) 2245fda9279dSmrg * @see NVSetupBlitVideo(ScreenPtr pScreen) 2246fda9279dSmrg */ 2247fda9279dSmrgvoid 2248fda9279dSmrgNVInitVideo(ScreenPtr pScreen) 2249fda9279dSmrg{ 2250fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2251fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 2252fda9279dSmrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 2253fda9279dSmrg XF86VideoAdaptorPtr overlayAdaptor = NULL; 2254fda9279dSmrg XF86VideoAdaptorPtr blitAdaptor = NULL; 2255fda9279dSmrg XF86VideoAdaptorPtr textureAdaptor[2] = {NULL, NULL}; 2256fda9279dSmrg int num_adaptors; 2257fda9279dSmrg 2258fda9279dSmrg /* 2259fda9279dSmrg * Driving the blitter requires the DMA FIFO. Using the FIFO 2260fda9279dSmrg * without accel causes DMA errors. While the overlay might 2261fda9279dSmrg * might work without accel, we also disable it for now when 2262fda9279dSmrg * acceleration is disabled: 2263fda9279dSmrg */ 2264fda9279dSmrg if (pScrn->bitsPerPixel != 8 && pNv->AccelMethod == EXA) { 2265fda9279dSmrg xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK"); 2266fda9279dSmrg 2267fda9279dSmrg if (pNv->Architecture < NV_TESLA) { 2268fda9279dSmrg overlayAdaptor = NVSetupOverlayVideo(pScreen); 2269fda9279dSmrg blitAdaptor = NVSetupBlitVideo(pScreen); 2270fda9279dSmrg } 2271fda9279dSmrg 2272fda9279dSmrg NVSetupTexturedVideo(pScreen, textureAdaptor); 2273fda9279dSmrg } 2274fda9279dSmrg 2275fda9279dSmrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 2276fda9279dSmrg if (blitAdaptor || overlayAdaptor || textureAdaptor[0]) { 2277fda9279dSmrg int size = num_adaptors; 2278fda9279dSmrg 2279fda9279dSmrg if(overlayAdaptor) size++; 2280fda9279dSmrg if(blitAdaptor) size++; 2281fda9279dSmrg if(textureAdaptor[0]) size++; 2282fda9279dSmrg if(textureAdaptor[1]) size++; 2283fda9279dSmrg 2284fda9279dSmrg newAdaptors = malloc(size * sizeof(XF86VideoAdaptorPtr *)); 2285fda9279dSmrg if(newAdaptors) { 2286fda9279dSmrg if(num_adaptors) { 2287fda9279dSmrg memcpy(newAdaptors, adaptors, num_adaptors * 2288fda9279dSmrg sizeof(XF86VideoAdaptorPtr)); 2289fda9279dSmrg } 2290fda9279dSmrg 2291fda9279dSmrg if(overlayAdaptor) { 2292fda9279dSmrg newAdaptors[num_adaptors] = overlayAdaptor; 2293fda9279dSmrg num_adaptors++; 2294fda9279dSmrg } 2295fda9279dSmrg 2296fda9279dSmrg if (textureAdaptor[0]) { /* bilinear */ 2297fda9279dSmrg newAdaptors[num_adaptors] = textureAdaptor[0]; 2298fda9279dSmrg num_adaptors++; 2299fda9279dSmrg } 2300fda9279dSmrg 2301fda9279dSmrg if (textureAdaptor[1]) { /* bicubic */ 2302fda9279dSmrg newAdaptors[num_adaptors] = textureAdaptor[1]; 2303fda9279dSmrg num_adaptors++; 2304fda9279dSmrg } 2305fda9279dSmrg 2306fda9279dSmrg if(blitAdaptor) { 2307fda9279dSmrg newAdaptors[num_adaptors] = blitAdaptor; 2308fda9279dSmrg num_adaptors++; 2309fda9279dSmrg } 2310fda9279dSmrg 2311fda9279dSmrg adaptors = newAdaptors; 2312fda9279dSmrg } 2313fda9279dSmrg } 2314fda9279dSmrg 2315fda9279dSmrg if (num_adaptors) 2316fda9279dSmrg xf86XVScreenInit(pScreen, adaptors, num_adaptors); 2317fda9279dSmrg if (newAdaptors) 2318fda9279dSmrg free(newAdaptors); 2319fda9279dSmrg 2320fda9279dSmrg /* 2321fda9279dSmrg * For now we associate with the plain texture adapter since it is logical, but we can 2322fda9279dSmrg * associate with any/all adapters since VL doesn't depend on Xv for color conversion. 2323fda9279dSmrg */ 2324fda9279dSmrg if (textureAdaptor[0]) { 2325fda9279dSmrg XF86MCAdaptorPtr *adaptorsXvMC = malloc(sizeof(XF86MCAdaptorPtr)); 2326fda9279dSmrg 2327fda9279dSmrg if (adaptorsXvMC) { 232822d74663Smrg adaptorsXvMC[0] = vlCreateAdaptorXvMC(pScreen, (char *)textureAdaptor[0]->name); 2329fda9279dSmrg 2330fda9279dSmrg if (adaptorsXvMC[0]) { 2331fda9279dSmrg vlInitXvMC(pScreen, 1, adaptorsXvMC); 2332fda9279dSmrg vlDestroyAdaptorXvMC(adaptorsXvMC[0]); 2333fda9279dSmrg } 2334fda9279dSmrg 2335fda9279dSmrg free(adaptorsXvMC); 2336fda9279dSmrg } 2337fda9279dSmrg } 2338fda9279dSmrg} 2339fda9279dSmrg 2340fda9279dSmrgvoid 2341fda9279dSmrgNVTakedownVideo(ScrnInfoPtr pScrn) 2342fda9279dSmrg{ 2343fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 2344fda9279dSmrg 2345fda9279dSmrg if (pNv->blitAdaptor) 2346fda9279dSmrg NVFreePortMemory(pScrn, GET_BLIT_PRIVATE(pNv)); 2347fda9279dSmrg if (pNv->textureAdaptor[0]) { 2348fda9279dSmrg NVFreePortMemory(pScrn, 2349fda9279dSmrg pNv->textureAdaptor[0]->pPortPrivates[0].ptr); 2350fda9279dSmrg } 2351fda9279dSmrg if (pNv->textureAdaptor[1]) { 2352fda9279dSmrg NVFreePortMemory(pScrn, 2353fda9279dSmrg pNv->textureAdaptor[1]->pPortPrivates[0].ptr); 2354fda9279dSmrg } 2355fda9279dSmrg} 2356fda9279dSmrg 2357fda9279dSmrg/* The filtering function used for video scaling. We use a cubic filter as 2358fda9279dSmrg * defined in "Reconstruction Filters in Computer Graphics" Mitchell & 2359fda9279dSmrg * Netravali in SIGGRAPH '88 2360fda9279dSmrg */ 2361fda9279dSmrgstatic float filter_func(float x) 2362fda9279dSmrg{ 2363fda9279dSmrg const double B=0.75; 2364fda9279dSmrg const double C=(1.0-B)/2.0; 2365fda9279dSmrg double x1=fabs(x); 2366fda9279dSmrg double x2=fabs(x)*x1; 2367fda9279dSmrg double x3=fabs(x)*x2; 2368fda9279dSmrg 2369fda9279dSmrg if (fabs(x)<1.0) 2370fda9279dSmrg return ( (12.0-9.0*B-6.0*C)*x3+(-18.0+12.0*B+6.0*C)*x2+(6.0-2.0*B) )/6.0; 2371fda9279dSmrg else 2372fda9279dSmrg return ( (-B-6.0*C)*x3+(6.0*B+30.0*C)*x2+(-12.0*B-48.0*C)*x1+(8.0*B+24.0*C) )/6.0; 2373fda9279dSmrg} 2374fda9279dSmrg 2375fda9279dSmrgstatic int8_t f32tosb8(float v) 2376fda9279dSmrg{ 2377fda9279dSmrg return (int8_t)(v*127.0); 2378fda9279dSmrg} 2379fda9279dSmrg 2380fda9279dSmrgvoid 2381fda9279dSmrgNVXVComputeBicubicFilter(struct nouveau_bo *bo, unsigned offset, unsigned size) 2382fda9279dSmrg{ 2383fda9279dSmrg int8_t *t = (int8_t *)(bo->map + offset); 2384fda9279dSmrg int i; 2385fda9279dSmrg 2386fda9279dSmrg for(i = 0; i < size; i++) { 2387fda9279dSmrg float x = (i + 0.5) / size; 2388fda9279dSmrg float w0 = filter_func(x+1.0); 2389fda9279dSmrg float w1 = filter_func(x); 2390fda9279dSmrg float w2 = filter_func(x-1.0); 2391fda9279dSmrg float w3 = filter_func(x-2.0); 2392fda9279dSmrg 2393fda9279dSmrg t[4*i+2]=f32tosb8(1.0+x-w1/(w0+w1)); 2394fda9279dSmrg t[4*i+1]=f32tosb8(1.0-x+w3/(w2+w3)); 2395fda9279dSmrg t[4*i+0]=f32tosb8(w0+w1); 2396fda9279dSmrg t[4*i+3]=f32tosb8(0.0); 2397fda9279dSmrg } 2398fda9279dSmrg} 2399