1/* 2 * Copyright (c) 2004 The Unichrome Project. All rights reserved. 3 * Copyright (c) 2000 Intel Corporation. All rights reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include "xf86.h" 29#include "xf86_OSproc.h" 30 31#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 32#include "xf86Resources.h" 33#endif 34 35#include "compiler.h" 36#include "xf86Pci.h" 37#include "regionstr.h" 38 39#ifdef HAVE_DRI 40 41#include "via_drmclient.h" 42#include "via_drm.h" 43#include "via_dri.h" 44#include "via_driver.h" 45 46#include "xf86xv.h" 47#include "fourcc.h" 48 49#if defined(X_NEED_XVPRIV_H) || defined (_XF86_FOURCC_H_) 50#include "xf86xvpriv.h" 51#endif 52 53#include "xf86xvmc.h" 54#include <X11/extensions/Xv.h> 55#include <X11/extensions/XvMC.h> 56#include "dixstruct.h" 57#include "via_xvmc.h" 58#include "dristruct.h" 59#include "dri.h" 60#include "via_xvpriv.h" 61#include "via_xv.h" 62 63#define MAKE_ATOM(a) MakeAtom(a, strlen(a), TRUE) 64 65 66/* 67 * List of attributes for the XvMC extension to handle. 68 * As long as the attribute is supported by the Xv adaptor, it needs only 69 * to be added here to be supported also by XvMC. 70 * Currently, only colorkey seems to be supported by Xv for Putimage. 71 */ 72static char *attrXvMC[VIA_NUM_XVMC_ATTRIBUTES] = { "XV_COLORKEY", 73 "XV_AUTOPAINT_COLORKEY", 74 "XV_BRIGHTNESS", 75 "XV_CONTRAST", 76 "XV_SATURATION", 77 "XV_HUE" 78}; 79static Atom attrAtoms[VIA_NUM_XVMC_ATTRIBUTES]; 80 81/* 82 * Xv Port private structure for XvMC. 83 */ 84typedef struct 85{ 86 unsigned ctxDisplaying; 87 int xvmc_port; 88 ViaXvMCAttrHolder xvAttr; 89 int newAttribute; 90 91 SetPortAttributeFuncPtr SetPortAttribute; 92 GetPortAttributeFuncPtr GetPortAttribute; 93 PutImageFuncPtr PutImage; 94} ViaXvMCXVPriv; 95 96/* Proposed XvMC VIA driver extension. */ 97#define XVMC_VLD 0x0020000 98 99 100/* Function declarations. */ 101static int ViaXvMCCreateContext(ScrnInfoPtr pScrn, XvMCContextPtr pContext, 102 int *num_priv, INT32 ** priv); 103static void ViaXvMCDestroyContext(ScrnInfoPtr pScrn, XvMCContextPtr pContext); 104static int ViaXvMCCreateSurface(ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf, 105 int *num_priv, INT32 ** priv); 106static void ViaXvMCDestroySurface(ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf); 107static int ViaXvMCCreateSubpicture(ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf, 108 int *num_priv, INT32 ** priv); 109static void ViaXvMCDestroySubpicture(ScrnInfoPtr pScrn, 110 XvMCSubpicturePtr pSubp); 111static int viaXvMCInterceptXvAttribute(ScrnInfoPtr pScrn, Atom attribute, 112 INT32 value, pointer data); 113static int viaXvMCInterceptPutImage(ScrnInfoPtr, short, short, short, short, 114 short, short, short, short, int, 115 unsigned char *, short, short, Bool, 116 RegionPtr, pointer, DrawablePtr); 117static int viaXvMCInterceptXvGetAttribute(ScrnInfoPtr pScrn, Atom attribute, 118 INT32 * value, pointer data); 119 120 121/* 122 * Initialize and clean up the screen private parts of XvMC. 123 */ 124static void 125initViaXvMC(ViaXvMCPtr vXvMC) 126{ 127 unsigned i; 128 129 for (i = 0; i < VIA_XVMC_MAX_CONTEXTS; ++i) { 130 vXvMC->contexts[i] = 0; 131 vXvMC->cPrivs[i] = 0; 132 } 133 134 for (i = 0; i < VIA_XVMC_MAX_SURFACES; ++i) { 135 vXvMC->surfaces[i] = 0; 136 vXvMC->sPrivs[i] = 0; 137 } 138} 139 140static void 141cleanupViaXvMC(ViaXvMCPtr vXvMC, XF86VideoAdaptorPtr * XvAdaptors, 142 int XvAdaptorCount) 143{ 144 unsigned i; 145 146 for (i = 0; i < VIA_XVMC_MAX_CONTEXTS; ++i) { 147 vXvMC->contexts[i] = 0; 148 if (vXvMC->cPrivs[i]) { 149 free(vXvMC->cPrivs[i]); 150 vXvMC->cPrivs[i] = 0; 151 } 152 } 153 154 for (i = 0; i < VIA_XVMC_MAX_SURFACES; ++i) { 155 vXvMC->surfaces[i] = 0; 156 if (vXvMC->sPrivs[i]) { 157 free(vXvMC->sPrivs[i]); 158 vXvMC->sPrivs[i] = 0; 159 } 160 } 161} 162 163static unsigned 164stride(int w) 165{ 166 return (w + 31) & ~31; 167} 168 169static unsigned long 170size_yuv420(int w, int h) 171{ 172 unsigned yPitch = stride(w); 173 174 return h * (yPitch + (yPitch >> 1)); 175} 176 177static unsigned long 178size_xx44(int w, int h) 179{ 180 return h * stride(w); 181} 182 183 184static int yv12_subpicture_index_list[2] = { 185 FOURCC_IA44, 186 FOURCC_AI44 187}; 188 189static XF86MCImageIDList yv12_subpicture_list = { 190 2, 191 yv12_subpicture_index_list 192}; 193 194static XF86MCSurfaceInfoRec Via_YV12_mpg2_surface = { 195 FOURCC_YV12, 196 XVMC_CHROMA_FORMAT_420, 197 0, 198 1024, 199 1024, 200 1024, 201 1024, 202 XVMC_MPEG_2 | XVMC_VLD, 203 XVMC_OVERLAID_SURFACE | XVMC_BACKEND_SUBPICTURE, 204 &yv12_subpicture_list 205}; 206 207static XF86MCSurfaceInfoRec Via_pga_mpg2_surface = { 208 FOURCC_YV12, 209 XVMC_CHROMA_FORMAT_420, 210 0, 211 2048, 212 2048, 213 2048, 214 2048, 215 XVMC_MPEG_2 | XVMC_VLD, 216 XVMC_OVERLAID_SURFACE | XVMC_BACKEND_SUBPICTURE, 217 &yv12_subpicture_list 218}; 219 220static XF86MCSurfaceInfoRec Via_YV12_mpg1_surface = { 221 FOURCC_YV12, 222 XVMC_CHROMA_FORMAT_420, 223 0, 224 1024, 225 1024, 226 1024, 227 1024, 228 XVMC_MPEG_1 | XVMC_VLD, 229 XVMC_OVERLAID_SURFACE | XVMC_BACKEND_SUBPICTURE, 230 &yv12_subpicture_list 231}; 232 233static XF86MCSurfaceInfoRec Via_pga_mpg1_surface = { 234 FOURCC_YV12, 235 XVMC_CHROMA_FORMAT_420, 236 0, 237 2048, 238 2048, 239 2048, 240 2048, 241 XVMC_MPEG_1 | XVMC_VLD, 242 XVMC_OVERLAID_SURFACE | XVMC_BACKEND_SUBPICTURE, 243 &yv12_subpicture_list 244}; 245 246static XF86MCSurfaceInfoPtr ppSI[2] = { 247 (XF86MCSurfaceInfoPtr) & Via_YV12_mpg2_surface, 248 (XF86MCSurfaceInfoPtr) & Via_YV12_mpg1_surface 249}; 250 251static XF86MCSurfaceInfoPtr ppSI_pga[2] = { 252 (XF86MCSurfaceInfoPtr) & Via_pga_mpg2_surface, 253 (XF86MCSurfaceInfoPtr) & Via_pga_mpg1_surface 254}; 255 256/* List of supported subpicture types. */ 257static XF86ImageRec ia44_subpicture = XVIMAGE_IA44; 258static XF86ImageRec ai44_subpicture = XVIMAGE_AI44; 259 260static XF86ImagePtr Via_subpicture_list[2] = { 261 (XF86ImagePtr) & ia44_subpicture, 262 (XF86ImagePtr) & ai44_subpicture 263}; 264 265/* 266 * Filling in the device dependent adaptor record. 267 * This is named "VIA Video Overlay" because this code falls under the 268 * XV extension, the name must match or it won't be used. 269 * 270 * For surface and subpicture, see above. 271 * The function pointers point to functions below. 272 */ 273static XF86MCAdaptorRec pAdapt = { 274 "XV_SWOV", /* name */ 275 2, /* num_surfaces */ 276 ppSI, /* surfaces */ 277 2, /* num_subpictures */ 278 Via_subpicture_list, /* subpictures */ 279 (xf86XvMCCreateContextProcPtr) ViaXvMCCreateContext, 280 (xf86XvMCDestroyContextProcPtr) ViaXvMCDestroyContext, 281 (xf86XvMCCreateSurfaceProcPtr) ViaXvMCCreateSurface, 282 (xf86XvMCDestroySurfaceProcPtr) ViaXvMCDestroySurface, 283 (xf86XvMCCreateSubpictureProcPtr) ViaXvMCCreateSubpicture, 284 (xf86XvMCDestroySubpictureProcPtr) ViaXvMCDestroySubpicture 285}; 286 287static XF86MCAdaptorRec pAdapt_pga = { 288 "XV_SWOV", /* name */ 289 2, /* num_surfaces */ 290 ppSI_pga, /* surfaces */ 291 2, /* num_subpictures */ 292 Via_subpicture_list, /* subpictures */ 293 (xf86XvMCCreateContextProcPtr) ViaXvMCCreateContext, 294 (xf86XvMCDestroyContextProcPtr) ViaXvMCDestroyContext, 295 (xf86XvMCCreateSurfaceProcPtr) ViaXvMCCreateSurface, 296 (xf86XvMCDestroySurfaceProcPtr) ViaXvMCDestroySurface, 297 (xf86XvMCCreateSubpictureProcPtr) ViaXvMCCreateSubpicture, 298 (xf86XvMCDestroySubpictureProcPtr) ViaXvMCDestroySubpicture 299}; 300 301static XF86MCAdaptorPtr ppAdapt[1] = { (XF86MCAdaptorPtr) & pAdapt }; 302static XF86MCAdaptorPtr ppAdapt_pga[1] = { (XF86MCAdaptorPtr) & pAdapt_pga }; 303 304 305static void 306mpegDisable(VIAPtr pVia, CARD32 val) 307{ 308 MPGOutD(0x0c, MPGInD(0x0c) & (val ^ 0xffffffff)); 309} 310 311void 312ViaInitXVMC(ScreenPtr pScreen) 313{ 314 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 315 VIAPtr pVia = VIAPTR(pScrn); 316 ViaXvMCPtr vXvMC = &(pVia->xvmc); 317 volatile ViaXvMCSAreaPriv *saPriv; 318 319 pVia->XvMCEnabled = 0; 320 321 if ((pVia->Chipset == VIA_KM400) || 322 (pVia->Chipset == VIA_CX700) || 323 (pVia->Chipset == VIA_K8M890) || 324 (pVia->Chipset == VIA_P4M900) || 325 (pVia->Chipset == VIA_VX800) || 326 (pVia->Chipset == VIA_VX855) || 327 (pVia->Chipset == VIA_VX900)) { 328 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 329 "[XvMC] XvMC is not supported on this chipset.\n"); 330 return; 331 } 332 333 if (!pVia->directRenderingType) { 334 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 335 "[XvMC] Cannot use XvMC without DRI!\n"); 336 return; 337 } 338 339 if (((pVia->drmVerMajor <= 2) && (pVia->drmVerMinor < 4))) { 340 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 341 "[XvMC] Kernel drm is not compatible with XvMC.\n"); 342 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 343 "[XvMC] Kernel drm version is %d.%d.%d; " 344 "at least version 2.4.0 is needed.\n", 345 pVia->drmVerMajor, pVia->drmVerMinor, pVia->drmVerPL); 346 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 347 "[XvMC] Please update. Disabling XvMC.\n"); 348 return; 349 } 350 351 vXvMC->mmioBase = pVia->registerHandle; 352 353 if (drmAddMap(pVia->drmmode.fd, 354 (drm_handle_t) pVia->FrameBufferBase, 355 pVia->videoRambytes, DRM_FRAME_BUFFER, 0, 356 &(vXvMC->fbBase)) < 0) { 357 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 358 "[XvMC] drmAddMap(FB) failed. Disabling XvMC.\n"); 359 return; 360 } 361 362 initViaXvMC(vXvMC); 363 364 if (!xf86XvMCScreenInit(pScreen, 1, ((pVia->Chipset == VIA_PM800) 365 ? ppAdapt_pga : ppAdapt))) { 366 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 367 "[XvMC] XvMCScreenInit failed. Disabling XvMC.\n"); 368 drmRmMap(pVia->drmmode.fd, vXvMC->fbBase); 369 return; 370 } 371#if (XvMCVersion > 1) || (XvMCRevision > 0) 372 { 373 DRIInfoPtr pDRIInfo = pVia->pDRIInfo; 374 375 if (pVia->ChipId != PCI_CHIP_VT3259 && 376 pVia->ChipId != PCI_CHIP_VT3364) { 377 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 378 "[XvMC] Registering chromeXvMC.\n"); 379 xf86XvMCRegisterDRInfo(pScreen, "chromeXvMC", pDRIInfo->busIdString, 380 VIAXVMC_MAJOR, VIAXVMC_MINOR, VIAXVMC_PL); 381 } else { 382 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 383 "[XvMC] Registering chromeXvMCPro.\n"); 384 xf86XvMCRegisterDRInfo(pScreen, "chromeXvMCPro", 385 pDRIInfo->busIdString, VIAXVMC_MAJOR, 386 VIAXVMC_MINOR, VIAXVMC_PL); 387 } 388 } 389#endif 390 391 vXvMC->activePorts = 0; 392 saPriv = (ViaXvMCSAreaPriv *) DRIGetSAREAPrivate(pScreen); 393 saPriv->XvMCCtxNoGrabbed = ~0; 394 395 XVMCLOCKPTR(saPriv, UNICHROME_LOCK_DECODER1)->lock = 0; 396 397 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 398 "[XvMC] Initialized XvMC extension.\n"); 399 pVia->XvMCEnabled = 1; 400} 401 402void 403ViaCleanupXVMC(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr * XvAdaptors, 404 int XvAdaptorCount) 405{ 406 VIAPtr pVia = VIAPTR(pScrn); 407 ViaXvMCPtr vXvMC = &(pVia->xvmc); 408 int i, j; 409 410 if (pVia->XvMCEnabled) { 411 mpegDisable(pVia, 0); 412 drmRmMap(pVia->drmmode.fd, vXvMC->mmioBase); 413 cleanupViaXvMC(vXvMC, XvAdaptors, XvAdaptorCount); 414 } 415 for (i = 0; i < XvAdaptorCount; ++i) { 416 if (!XvAdaptors[i]) 417 continue; 418 419 for (j = 0; j < XvAdaptors[i]->nPorts; ++j) { 420 viaPortPrivPtr pPriv = XvAdaptors[i]->pPortPrivates[j].ptr; 421 422 if (pPriv->xvmc_priv) 423 free(pPriv->xvmc_priv); 424 } 425 } 426 pVia->XvMCEnabled = 0; 427} 428 429static int 430ViaXvMCCreateContext(ScrnInfoPtr pScrn, XvMCContextPtr pContext, 431 int *num_priv, INT32 ** priv) 432{ 433 VIAPtr pVia = VIAPTR(pScrn); 434 ViaXvMCPtr vXvMC = &(pVia->xvmc); 435 DRIInfoPtr pDRIInfo = pVia->pDRIInfo; 436 VIADRIPtr pViaDRI = pDRIInfo->devPrivate; 437 ViaXvMCCreateContextRec *contextRec; 438 unsigned ctxNo; 439 ViaXvMCContextPriv *cPriv; 440 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) pContext->port_priv; 441 viaPortPrivPtr pPriv = (viaPortPrivPtr) portPriv->DevPriv.ptr; 442 ViaXvMCXVPriv *vx = (ViaXvMCXVPriv *) pPriv->xvmc_priv; 443 volatile ViaXvMCSAreaPriv *sAPriv; 444 445 sAPriv = (ViaXvMCSAreaPriv *) DRIGetSAREAPrivate(pScrn->pScreen); 446 447 if (-1 == vx->xvmc_port) { 448 vx->xvmc_port = (vXvMC->activePorts++); 449 sAPriv->XvMCSubPicOn[vx->xvmc_port] = 0; 450 sAPriv->XvMCDisplaying[vx->xvmc_port] = 0; 451 } 452 453 if (vXvMC->nContexts >= VIA_XVMC_MAX_CONTEXTS) { 454 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 455 "[XvMC] ViaXvMCCreateContext: Out of contexts.\n"); 456 return BadAlloc; 457 } 458 459 *priv = calloc(1, sizeof(ViaXvMCCreateContextRec)); 460 contextRec = (ViaXvMCCreateContextRec *) * priv; 461 462 if (!*priv) { 463 *num_priv = 0; 464 return BadAlloc; 465 } 466 467 *num_priv = sizeof(ViaXvMCCreateContextRec) >> 2; 468 469 for (ctxNo = 0; ctxNo < VIA_XVMC_MAX_CONTEXTS; ++ctxNo) { 470 if (0 == vXvMC->contexts[ctxNo]) 471 break; 472 } 473 474 cPriv = (ViaXvMCContextPriv *) calloc(1, sizeof(ViaXvMCContextPriv)); 475 476 if (!cPriv) { 477 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 478 "[XvMC] ViaXvMCCreateContext: Unable to allocate memory!\n"); 479 free(*priv); 480 *num_priv = 0; 481 return BadAlloc; 482 } 483 484 /* Export framebuffer and mmio to non-root clients. */ 485 contextRec->ctxNo = ctxNo; 486 contextRec->xvmc_port = vx->xvmc_port; 487 contextRec->fbOffset = vXvMC->fbBase; 488 contextRec->fbSize = pVia->videoRambytes; 489 contextRec->mmioOffset = vXvMC->mmioBase; 490 contextRec->mmioSize = VIA_MMIO_REGSIZE; 491 contextRec->sAreaSize = pDRIInfo->SAREASize; 492 contextRec->sAreaPrivOffset = sizeof(XF86DRISAREARec); 493 contextRec->major = VIAXVMC_MAJOR; 494 contextRec->minor = VIAXVMC_MINOR; 495 contextRec->pl = VIAXVMC_PL; 496 contextRec->initAttrs = vx->xvAttr; 497 contextRec->useAGP = (pViaDRI->ringBufActive && 498 ((pVia->Chipset == VIA_CLE266) || 499 (pVia->Chipset == VIA_KM400) || 500 (pVia->Chipset == VIA_PM800) || 501 (pVia->Chipset == VIA_P4M900))); 502 contextRec->chipId = pVia->ChipId; 503 contextRec->screen = pScrn->scrnIndex; 504 contextRec->depth = pScrn->bitsPerPixel; 505 contextRec->stride = pVia->Bpp * pScrn->virtualX; 506 507 vXvMC->nContexts++; 508 vXvMC->contexts[ctxNo] = pContext->context_id; 509 vXvMC->cPrivs[ctxNo] = cPriv; 510 511 return Success; 512} 513 514static int 515ViaXvMCCreateSurface(ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf, 516 int *num_priv, INT32 ** priv) 517{ 518 VIAPtr pVia = VIAPTR(pScrn); 519 ViaXvMCPtr vXvMC = &(pVia->xvmc); 520 unsigned srfNo, numBuffers, i; 521 ViaXvMCSurfacePriv *sPriv; 522 XvMCContextPtr ctx; 523 unsigned bufSize, yBufSize; 524 void *buf; 525 526 if (VIA_XVMC_MAX_SURFACES == vXvMC->nSurfaces) { 527 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 528 "[XvMC] ViaXvMCCreateSurface: Too many surfaces !\n"); 529 return BadAlloc; 530 } 531 532 sPriv = (ViaXvMCSurfacePriv *) calloc(1, sizeof(ViaXvMCSurfacePriv)); 533 534 if (!sPriv) { 535 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 536 "[XvMC] ViaXvMCCreateSurface: Unable to allocate memory!\n"); 537 *num_priv = 0; 538 return BadAlloc; 539 } 540 541 numBuffers = 1; 542 543 /* 544 * Some chips require more than one buffer per surface (and a special 545 * flipping procedure; See Ivor Hewitt's ddmpeg.c version 1.6). The client 546 * lib will detect the number of buffers allocated and determine the 547 * flipping method from that. 548 */ 549#if 0 /* Not enabled yet. */ 550 switch (pVia->ChipSet) { 551 case VIA_CLE266: 552 switch (pVia->ChipRev) { 553 case 0x10: /* CLE266 C0 only? Or all C? */ 554 numBuffers = 2; 555 break; 556 default: 557 break; 558 } 559 break; 560 default: 561 break; 562 } 563#endif 564 *num_priv = numBuffers + 2; 565 566 *priv = (INT32 *) calloc(*num_priv, sizeof(INT32)); 567 568 if (!*priv) { 569 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 570 "[XvMC] ViaXvMCCreateSurface: Unable to allocate memory!\n"); 571 *num_priv = 0; 572 free(sPriv); 573 return BadAlloc; 574 } 575 576 for (srfNo = 0; srfNo < VIA_XVMC_MAX_SURFACES; ++srfNo) { 577 if (0 == vXvMC->sPrivs[srfNo]) 578 break; 579 } 580 581 (*priv)[0] = srfNo; 582 583 ctx = pSurf->context; 584 bufSize = size_yuv420(ctx->width, ctx->height); 585 sPriv->memory_ref = drm_bo_alloc(pScrn, numBuffers * bufSize, 586 32, TTM_PL_FLAG_VRAM); 587 if (!sPriv->memory_ref) { 588 free(*priv); 589 free(sPriv); 590 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSurface: " 591 "Unable to allocate frambuffer memory!\n"); 592 return BadAlloc; 593 } 594 buf = drm_bo_map(pScrn, sPriv->memory_ref); 595 596 (*priv)[1] = numBuffers; 597 (*priv)[2] = sPriv->offsets[0] = sPriv->memory_ref->offset; 598 for (i = 1; i < numBuffers; ++i) { 599 (*priv)[i + 2] = sPriv->offsets[i] = sPriv->offsets[i - 1] + bufSize; 600 } 601 602 yBufSize = stride(ctx->width) * ctx->height; 603 for (i = 0; i < numBuffers; ++i) { 604 memset(buf, 0, yBufSize); 605 memset(buf + yBufSize, 0x80, yBufSize >> 1); 606 buf += bufSize; 607 } 608 drm_bo_unmap(pScrn, sPriv->memory_ref); 609 610 vXvMC->sPrivs[srfNo] = sPriv; 611 vXvMC->surfaces[srfNo] = pSurf->surface_id; 612 vXvMC->nSurfaces++; 613 return Success; 614} 615 616static int 617ViaXvMCCreateSubpicture(ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp, 618 int *num_priv, INT32 ** priv) 619{ 620 VIAPtr pVia = VIAPTR(pScrn); 621 ViaXvMCPtr vXvMC = &(pVia->xvmc); 622 unsigned srfNo; 623 ViaXvMCSurfacePriv *sPriv; 624 XvMCContextPtr ctx; 625 unsigned bufSize; 626 627 if (VIA_XVMC_MAX_SURFACES == vXvMC->nSurfaces) { 628 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 629 "[XvMC] ViaXvMCCreateSubpicture: Too many surfaces !\n"); 630 return BadAlloc; 631 } 632 633 sPriv = (ViaXvMCSurfacePriv *) calloc(1, sizeof(ViaXvMCSurfacePriv)); 634 635 if (!sPriv) { 636 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSubpicture:" 637 " Unable to allocate memory!\n"); 638 *num_priv = 0; 639 return BadAlloc; 640 } 641 642 *priv = (INT32 *) calloc(3, sizeof(INT32)); 643 644 if (!*priv) { 645 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSubpicture:" 646 " Unable to allocate memory!\n"); 647 *num_priv = 0; 648 free(sPriv); 649 return BadAlloc; 650 } 651 652 *num_priv = 2; 653 654 for (srfNo = 0; srfNo < VIA_XVMC_MAX_SURFACES; ++srfNo) { 655 if (0 == vXvMC->sPrivs[srfNo]) 656 break; 657 } 658 659 (*priv)[0] = srfNo; 660 661 ctx = pSubp->context; 662 bufSize = size_xx44(ctx->width, ctx->height); 663 sPriv->memory_ref = drm_bo_alloc(pScrn, 1 * bufSize, 32, TTM_PL_FLAG_VRAM); 664 if (!sPriv->memory_ref) { 665 free(*priv); 666 free(sPriv); 667 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSubpicture:" 668 " Unable to allocate framebuffer memory!\n"); 669 return BadAlloc; 670 } 671 (*priv)[1] = sPriv->offsets[0] = sPriv->memory_ref->offset; 672 673 vXvMC->sPrivs[srfNo] = sPriv; 674 vXvMC->surfaces[srfNo] = pSubp->subpicture_id; 675 vXvMC->nSurfaces++; 676 677 return Success; 678} 679 680static void 681ViaXvMCDestroyContext(ScrnInfoPtr pScrn, XvMCContextPtr pContext) 682{ 683 VIAPtr pVia = VIAPTR(pScrn); 684 ViaXvMCPtr vXvMC = &(pVia->xvmc); 685 int i; 686 volatile ViaXvMCSAreaPriv *sAPriv; 687 viaPortPrivPtr pPriv; 688 XvPortRecPrivatePtr portPriv; 689 ViaXvMCXVPriv *vx; 690 691 for (i = 0; i < VIA_XVMC_MAX_CONTEXTS; i++) { 692 if (vXvMC->contexts[i] == pContext->context_id) { 693 694 sAPriv = (ViaXvMCSAreaPriv *) DRIGetSAREAPrivate(pScrn->pScreen); 695 portPriv = (XvPortRecPrivatePtr) pContext->port_priv; 696 pPriv = (viaPortPrivPtr) portPriv->DevPriv.ptr; 697 vx = (ViaXvMCXVPriv *) pPriv->xvmc_priv; 698 699 if ((i | VIA_XVMC_VALID) == vx->ctxDisplaying) { 700 vx->ctxDisplaying = 0; 701 } 702 703 free(vXvMC->cPrivs[i]); 704 vXvMC->cPrivs[i] = 0; 705 vXvMC->nContexts--; 706 vXvMC->contexts[i] = 0; 707 return; 708 } 709 } 710 return; 711} 712 713static void 714ViaXvMCDestroySurface(ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf) 715{ 716 VIAPtr pVia = VIAPTR(pScrn); 717 ViaXvMCPtr vXvMC = &(pVia->xvmc); 718 int i; 719 volatile ViaXvMCSAreaPriv *sAPriv; 720 XvMCContextPtr pContext = pSurf->context; 721 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) pContext->port_priv; 722 viaPortPrivPtr pPriv = (viaPortPrivPtr) portPriv->DevPriv.ptr; 723 ViaXvMCXVPriv *vx = (ViaXvMCXVPriv *) pPriv->xvmc_priv; 724 725 for (i = 0; i < VIA_XVMC_MAX_SURFACES; i++) { 726 if (vXvMC->surfaces[i] == pSurf->surface_id) { 727 728 sAPriv = (ViaXvMCSAreaPriv *) DRIGetSAREAPrivate(pScrn->pScreen); 729 { 730 DRM_CAS_RESULT(__ret); 731 DRM_CAS(&(sAPriv->XvMCDisplaying[vx->xvmc_port]), 732 i | VIA_XVMC_VALID, 0, __ret); 733 if (!__ret) 734 ViaOverlayHide(pScrn); 735 } 736 drm_bo_free(pScrn, vXvMC->sPrivs[i]->memory_ref); 737 free(vXvMC->sPrivs[i]); 738 vXvMC->nSurfaces--; 739 vXvMC->sPrivs[i] = 0; 740 vXvMC->surfaces[i] = 0; 741 return; 742 } 743 } 744 return; 745} 746 747static void 748ViaXvMCDestroySubpicture(ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp) 749{ 750 VIAPtr pVia = VIAPTR(pScrn); 751 ViaXvMCPtr vXvMC = &(pVia->xvmc); 752 int i; 753 volatile ViaXvMCSAreaPriv *sAPriv; 754 XvMCContextPtr pContext = pSubp->context; 755 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) pContext->port_priv; 756 viaPortPrivPtr pPriv = (viaPortPrivPtr) portPriv->DevPriv.ptr; 757 ViaXvMCXVPriv *vx = (ViaXvMCXVPriv *) pPriv->xvmc_priv; 758 759 for (i = 0; i < VIA_XVMC_MAX_SURFACES; i++) { 760 if (vXvMC->surfaces[i] == pSubp->subpicture_id) { 761 762 sAPriv = (ViaXvMCSAreaPriv *) DRIGetSAREAPrivate(pScrn->pScreen); 763 764 { 765 DRM_CAS_RESULT(__ret); 766 767 DRM_CAS(&(sAPriv->XvMCSubPicOn[vx->xvmc_port]), 768 i | VIA_XVMC_VALID, 0, __ret); 769 if (!__ret) { 770 /* Turn subpicture off. */ 771 while (VIAGETREG(V_COMPOSE_MODE) & 772 (V1_COMMAND_FIRE | V3_COMMAND_FIRE)) ; 773 VIASETREG(SUBP_CONTROL_STRIDE, 774 VIAGETREG(SUBP_CONTROL_STRIDE) & ~SUBP_HQV_ENABLE); 775 } 776 } 777 778 drm_bo_free(pScrn, vXvMC->sPrivs[i]->memory_ref); 779 free(vXvMC->sPrivs[i]); 780 vXvMC->nSurfaces--; 781 vXvMC->sPrivs[i] = 0; 782 vXvMC->surfaces[i] = 0; 783 784 return; 785 } 786 } 787 return; 788} 789 790/* 791 * Tell XvMC clients that Xv is currently displaying; 792 * return 1 if another client was displaying before. 793 */ 794static int 795viaXvMCSetDisplayLock(ScrnInfoPtr pScrn, ViaXvMCXVPriv * vx) 796{ 797 VIAPtr pVia = VIAPTR(pScrn); 798 ViaXvMCSAreaPriv *sAPriv = (ViaXvMCSAreaPriv *) 799 DRIGetSAREAPrivate(pScrn->pScreen); 800 801 if (vx->xvmc_port > 0) { 802 if ((VIA_XVMC_MAX_SURFACES | VIA_XVMC_VALID) != 803 sAPriv->XvMCDisplaying[vx->xvmc_port]) { 804 sAPriv->XvMCDisplaying[vx->xvmc_port] = 805 (VIA_XVMC_MAX_SURFACES | VIA_XVMC_VALID); 806 } 807 808 if (sAPriv->XvMCSubPicOn[vx->xvmc_port] & VIA_XVMC_VALID) { 809 sAPriv->XvMCSubPicOn[vx->xvmc_port] = 0; 810 while (VIAGETREG(V_COMPOSE_MODE) & 811 (V1_COMMAND_FIRE | V3_COMMAND_FIRE)) ; 812 VIASETREG(SUBP_CONTROL_STRIDE, 813 VIAGETREG(SUBP_CONTROL_STRIDE) & ~SUBP_HQV_ENABLE); 814 } 815 } 816 return 0; 817} 818 819int 820viaXvMCInitXv(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr XvAdapt) 821{ 822 viaPortPrivPtr pPriv; 823 ViaXvMCXVPriv *vx; 824 unsigned i, j; 825 826 for (j = 0; j < XvAdapt->nPorts; ++j) { 827 pPriv = (viaPortPrivPtr) XvAdapt->pPortPrivates[j].ptr; 828 829 if (NULL == (pPriv->xvmc_priv = calloc(1, sizeof(ViaXvMCXVPriv)))) 830 return BadAlloc; 831 832 for (i = 0; i < VIA_NUM_XVMC_ATTRIBUTES; ++i) { 833 attrAtoms[i] = MAKE_ATOM(attrXvMC[i]); 834 } 835 836 vx = (ViaXvMCXVPriv *) pPriv->xvmc_priv; 837 838 vx->ctxDisplaying = 0; 839 vx->xvAttr.numAttr = VIA_NUM_XVMC_ATTRIBUTES; 840 vx->xvmc_port = -1; 841 vx->newAttribute = 1; 842 843 /* Set up wrappers. */ 844 vx->GetPortAttribute = XvAdapt->GetPortAttribute; 845 vx->SetPortAttribute = XvAdapt->SetPortAttribute; 846 vx->PutImage = XvAdapt->PutImage; 847 848 XvAdapt->GetPortAttribute = viaXvMCInterceptXvGetAttribute; 849 XvAdapt->SetPortAttribute = viaXvMCInterceptXvAttribute; 850 XvAdapt->PutImage = viaXvMCInterceptPutImage; 851 852 for (i = 0; i < VIA_NUM_XVMC_ATTRIBUTES; ++i) { 853 vx->xvAttr.attributes[i].attribute = attrAtoms[i]; 854 vx->xvAttr.attributes[i].value = 0; 855 vx->GetPortAttribute(pScrn, attrAtoms[i], 856 &(vx->xvAttr.attributes[i].value), pPriv); 857 } 858 } 859 return Success; 860} 861 862static int 863viaXvMCInterceptXvAttribute(ScrnInfoPtr pScrn, Atom attribute, 864 INT32 value, pointer data) 865{ 866 unsigned i; 867 viaPortPrivPtr pPriv = (viaPortPrivPtr) data; 868 ViaXvMCXVPriv *vx = (ViaXvMCXVPriv *) pPriv->xvmc_priv; 869 870 if (VIAPTR(pScrn)->XvMCEnabled) { 871 for (i = 0; i < vx->xvAttr.numAttr; ++i) { 872 if (vx->xvAttr.attributes[i].attribute == attribute) { 873 vx->xvAttr.attributes[i].value = value; 874 if (vx->ctxDisplaying != 875 (VIA_XVMC_MAX_CONTEXTS | VIA_XVMC_VALID)) { 876 vx->newAttribute = 1; 877 return 0; 878 } 879 } 880 } 881 } 882 883 return vx->SetPortAttribute(pScrn, attribute, value, data); 884} 885 886static int 887viaXvMCInterceptXvGetAttribute(ScrnInfoPtr pScrn, Atom attribute, 888 INT32 * value, pointer data) 889{ 890 unsigned i; 891 viaPortPrivPtr pPriv = (viaPortPrivPtr) data; 892 ViaXvMCXVPriv *vx = (ViaXvMCXVPriv *) pPriv->xvmc_priv; 893 894 if (VIAPTR(pScrn)->XvMCEnabled) { 895 for (i = 0; i < vx->xvAttr.numAttr; ++i) { 896 if (vx->xvAttr.attributes[i].attribute == attribute) { 897 *value = vx->xvAttr.attributes[i].value; 898 return Success; 899 } 900 } 901 } 902 903 return vx->GetPortAttribute(pScrn, attribute, value, data); 904} 905 906static int 907viaXvMCDisplayAttributes(ScrnInfoPtr pScrn, 908 const ViaXvMCAttrHolder * ah, viaPortPrivPtr pPriv) 909{ 910 ViaXvMCXVPriv *vx = (ViaXvMCXVPriv *) pPriv->xvmc_priv; 911 unsigned i; 912 int ret; 913 914 for (i = 0; i < ah->numAttr; ++i) { 915 ret = vx->SetPortAttribute(pScrn, ah->attributes[i].attribute, 916 ah->attributes[i].value, pPriv); 917 if (ret) 918 return ret; 919 } 920 return Success; 921} 922 923static int 924viaXvMCInterceptPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, 925 short drw_x, short drw_y, short src_w, 926 short src_h, short drw_w, short drw_h, 927 int id, unsigned char *buf, short width, 928 short height, Bool sync, RegionPtr clipBoxes, 929 pointer data, DrawablePtr pDraw) 930{ 931 viaPortPrivPtr pPriv = (viaPortPrivPtr) data; 932 ViaXvMCXVPriv *vx = (ViaXvMCXVPriv *) pPriv->xvmc_priv; 933 934 if (VIAPTR(pScrn)->XvMCEnabled) { 935 if (FOURCC_XVMC == id) { 936 volatile ViaXvMCSAreaPriv *sAPriv; 937 ViaXvMCCommandBuffer *vXvMCData = (ViaXvMCCommandBuffer *) buf; 938 939 sAPriv = (ViaXvMCSAreaPriv *) DRIGetSAREAPrivate(pScrn->pScreen); 940 941 switch (vXvMCData->command) { 942 case VIA_XVMC_COMMAND_ATTRIBUTES: 943 if ((vXvMCData->ctxNo | VIA_XVMC_VALID) != vx->ctxDisplaying) 944 return 1; 945 viaXvMCDisplayAttributes(pScrn, &vXvMCData->attrib, pPriv); 946 return 0; 947 case VIA_XVMC_COMMAND_FDISPLAY: 948 if (sAPriv->XvMCDisplaying[vx->xvmc_port] != vXvMCData->srfNo) 949 return 1; 950 viaXvMCDisplayAttributes(pScrn, &vXvMCData->attrib, pPriv); 951 vx->ctxDisplaying = vXvMCData->ctxNo; 952 break; 953 case VIA_XVMC_COMMAND_DISPLAY: 954 if ((vXvMCData->ctxNo | VIA_XVMC_VALID) != vx->ctxDisplaying) { 955 viaXvMCDisplayAttributes(pScrn, &vXvMCData->attrib, pPriv); 956 } 957 if (sAPriv->XvMCDisplaying[vx->xvmc_port] != vXvMCData->srfNo) 958 return 1; 959 vx->ctxDisplaying = vXvMCData->ctxNo; 960 break; 961 case VIA_XVMC_COMMAND_UNDISPLAY: 962 { 963 DRM_CAS_RESULT(__ret); 964 DRM_CAS(&(sAPriv->XvMCDisplaying[vx->xvmc_port]), 965 vXvMCData->srfNo, 0, __ret); 966 if (!__ret) 967 ViaOverlayHide(pScrn); 968 } 969 return Success; 970 default: 971 break; 972 } 973 } else { 974 if ((VIA_XVMC_MAX_CONTEXTS | VIA_XVMC_VALID) != vx->ctxDisplaying) { 975 viaXvMCDisplayAttributes(pScrn, &vx->xvAttr, pPriv); 976 vx->ctxDisplaying = VIA_XVMC_MAX_CONTEXTS | VIA_XVMC_VALID; 977 } else if (vx->newAttribute) { 978 vx->newAttribute = 0; 979 viaXvMCDisplayAttributes(pScrn, &vx->xvAttr, pPriv); 980 } 981 viaXvMCSetDisplayLock(pScrn, vx); 982 } 983 } 984 return vx->PutImage(pScrn, src_x, src_y, drw_x, drw_y, src_w, src_h, 985 drw_w, drw_h, id, buf, width, height, sync, clipBoxes, 986 data, pDraw); 987} 988 989unsigned long 990viaXvMCPutImageSize(ScrnInfoPtr pScrn) 991{ 992 if (VIAPTR(pScrn)->XvMCEnabled) 993 return sizeof(ViaXvMCCommandBuffer); 994 return 0; 995} 996 997#endif /* HAVE_DRI */ 998