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