viaXvMC.c revision 90b17f1b
1/***************************************************************************** 2 * VIA Unichrome XvMC extension client lib. 3 * 4 * Copyright (c) 2004-2005 Thomas Hellstr�m. All rights reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24 25/* 26 *Author: Thomas Hellstr�m, 2004. 27 *Bugfixes by among others Pascal Brisset and Terry Barnaby. 28 *DRI protocol support by Thomas Hellstr�m, 2005. 29 */ 30 31#undef WAITPAUSE 32 33#include "viaXvMCPriv.h" 34#include "viaLowLevel.h" 35#include <stdio.h> 36#include <sys/ioctl.h> 37#include <sys/time.h> 38#include <time.h> 39#include <fourcc.h> 40#include <X11/extensions/Xv.h> 41#include <xf86drm.h> 42#include <pthread.h> 43#include "vldXvMC.h" 44#include "xf86dri.h" 45#include "driDrawable.h" 46 47#define SAREAPTR(ctx) ((ViaXvMCSAreaPriv *) \ 48 (((CARD8 *)(ctx)->sAreaAddress) + \ 49 (ctx)->sAreaPrivOffset)) 50 51typedef struct 52{ 53 int major; 54 int minor; 55 int patchlevel; 56} ViaDRMVersion; 57 58static int error_base; 59static int event_base; 60static unsigned numContexts = 0; 61static int globalFD; 62static drmAddress sAreaAddress; 63static drmAddress fbAddress; 64static drmAddress mmioAddress; 65static const ViaDRMVersion drmExpected = { 2, 0, 0 }; 66static const ViaDRMVersion drmCompat = { 2, 0, 0 }; 67 68#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X') 69 70#define ppthread_mutex_lock(arg) \ 71 { \ 72 pthread_mutex_lock(arg); \ 73 } \ 74 75#define ppthread_mutex_unlock(arg) \ 76 { \ 77 pthread_mutex_unlock(arg); \ 78 } \ 79 80static unsigned 81yOffs(ViaXvMCSurface * srf) 82{ 83 return srf->offsets[0]; 84} 85 86static unsigned 87vOffs(ViaXvMCSurface * srf) 88{ 89 return srf->offsets[0] + srf->yStride * srf->height; 90} 91 92static unsigned 93uOffs(ViaXvMCSurface * srf) 94{ 95 return srf->offsets[0] + (srf->yStride * srf->height) + 96 (srf->yStride >> 1) * (srf->height >> 1); 97} 98 99static void 100defaultQMatrices(ViaXvMCContext * ctx) 101{ 102 int i; 103 104 static const char intra[64] = { 105 8, 16, 19, 22, 26, 27, 29, 34, 16, 16, 22, 24, 27, 29, 34, 37, 106 19, 22, 26, 27, 29, 34, 34, 38, 22, 22, 26, 27, 29, 34, 37, 40, 107 22, 26, 27, 29, 32, 35, 40, 48, 26, 27, 29, 32, 35, 40, 48, 58, 108 26, 27, 29, 34, 38, 46, 56, 69, 27, 29, 35, 38, 46, 56, 69, 83 109 }; 110 111 for (i = 0; i < 64; ++i) { 112 ctx->intra_quantiser_matrix[i] = intra[i]; 113 ctx->non_intra_quantiser_matrix[i] = 16; 114 } 115 ctx->intraLoaded = 0; 116 ctx->nonIntraLoaded = 0; 117} 118 119static void 120releaseDecoder(ViaXvMCContext * ctx, int clearCtx) 121{ 122 volatile ViaXvMCSAreaPriv *sAPriv; 123 124 sAPriv = SAREAPTR(ctx); 125 UNICHROME_UNLOCK(ctx->fd, UNICHROME_LOCK_DECODER1, sAPriv, 126 ctx->drmcontext); 127} 128 129static int 130grabDecoder(ViaXvMCContext * ctx, int *hadLastLock) 131{ 132 volatile ViaXvMCSAreaPriv *sAPriv = SAREAPTR(ctx); 133 int retFtx, lc; 134 135 /* 136 * Try to grab the decoder. If it is not available we will sleep until 137 * it becomes available or for a maximum of 20 ms. 138 * Then try to grab it again, unless a timeout occured. If the decoder is 139 * available, the lock should be reasonably fast. 140 */ 141 142 if (ctx->haveDecoder) { 143 flushXvMCLowLevel(ctx->xl); /* Ignore errors here. */ 144 145 /*fprintf(stderr,"ViaXvMC: ERROR: Trying to re-lock decoder.\n"); */ 146 *hadLastLock = 1; 147 return 0; 148 } 149 UNICHROME_LOCK(ctx->fd, UNICHROME_LOCK_DECODER1, sAPriv, ctx->drmcontext, 150 lc, retFtx); 151 *hadLastLock = (ctx->drmcontext == lc); 152 153 return retFtx; 154} 155 156static void 157setupAttribDesc(Display * display, XvPortID port, 158 const ViaXvMCAttrHolder * attrib, XvAttribute attribDesc[]) 159{ 160 XvAttribute *XvAttribs, *curAD; 161 int num; 162 unsigned i, j; 163 164 XLockDisplay(display); 165 XvAttribs = XvQueryPortAttributes(display, port, &num); 166 for (i = 0; i < attrib->numAttr; ++i) { 167 curAD = attribDesc + i; 168 curAD->flags = 0; 169 curAD->min_value = 0; 170 curAD->max_value = 0; 171 curAD->name = NULL; 172 for (j = 0; j < num; ++j) { 173 if (attrib->attributes[i].attribute == 174 XInternAtom(display, XvAttribs[j].name, TRUE)) { 175 *curAD = XvAttribs[j]; 176 curAD->name = strdup(XvAttribs[j].name); 177 break; 178 } 179 } 180 } 181 if (XvAttribs) 182 XFree(XvAttribs); 183 XUnlockDisplay(display); 184 185} 186 187static void 188releaseAttribDesc(int numAttr, XvAttribute attribDesc[]) 189{ 190 int i; 191 192 for (i = 0; i < numAttr; ++i) { 193 if (attribDesc[i].name) 194 free(attribDesc[i].name); 195 } 196} 197 198static Status 199releaseContextResources(Display * display, XvMCContext * context, 200 int freePrivate, Status errType) 201{ 202 ViaXvMCContext *pViaXvMC = (ViaXvMCContext *) context->privData; 203 204 switch (pViaXvMC->resources) { 205 case context_drawHash: 206 driDestroyHashContents(pViaXvMC->drawHash); 207 drmHashDestroy(pViaXvMC->drawHash); 208 case context_lowLevel: 209 closeXvMCLowLevel(pViaXvMC->xl); 210 case context_mutex: 211 pthread_mutex_destroy(&pViaXvMC->ctxMutex); 212 case context_drmContext: 213 XLockDisplay(display); 214 uniDRIDestroyContext(display, pViaXvMC->screen, pViaXvMC->id); 215 XUnlockDisplay(display); 216 case context_sAreaMap: 217 numContexts--; 218 if (numContexts == 0) 219 drmUnmap(pViaXvMC->sAreaAddress, pViaXvMC->sAreaSize); 220 case context_fbMap: 221 if (numContexts == 0) 222 drmUnmap(pViaXvMC->fbAddress, pViaXvMC->fbSize); 223 case context_mmioMap: 224 if (numContexts == 0) 225 drmUnmap(pViaXvMC->mmioAddress, pViaXvMC->mmioSize); 226 case context_fd: 227 if (numContexts == 0) { 228 if (pViaXvMC->fd >= 0) 229 drmClose(pViaXvMC->fd); 230 } 231 pViaXvMC->fd = -1; 232 case context_driConnection: 233 if (numContexts == 0) { 234 XLockDisplay(display); 235 uniDRICloseConnection(display, pViaXvMC->screen); 236 XUnlockDisplay(display); 237 } 238 case context_context: 239 XLockDisplay(display); 240 _xvmc_destroy_context(display, context); 241 XUnlockDisplay(display); 242 if (!freePrivate) 243 break; 244 default: 245 free(pViaXvMC); 246 context->privData = NULL; 247 } 248 return errType; 249} 250 251_X_EXPORT Status 252XvMCCreateContext(Display * display, XvPortID port, 253 int surface_type_id, int width, int height, int flags, 254 XvMCContext * context) 255{ 256 ViaXvMCContext *pViaXvMC; 257 int priv_count; 258 uint *priv_data; 259 uint magic; 260 unsigned i; 261 Status ret; 262 int major, minor; 263 ViaXvMCCreateContextRec *tmpComm; 264 drmVersionPtr drmVer; 265 char *curBusID; 266 int isCapable; 267 268 /* 269 * Verify Obvious things first 270 */ 271 272 if (context == NULL) { 273 return XvMCBadContext; 274 } 275 276 if (!(flags & XVMC_DIRECT)) { 277 fprintf(stderr, "Indirect Rendering not supported! Using Direct.\n"); 278 } 279 280 /* 281 *FIXME: Check $DISPLAY for legal values here 282 */ 283 284 context->surface_type_id = surface_type_id; 285 context->width = (unsigned short)((width + 15) & ~15); 286 context->height = (unsigned short)((height + 15) & ~15); 287 context->flags = flags; 288 context->port = port; 289 290 /* 291 * Width, Height, and flags are checked against surface_type_id 292 * and port for validity inside the X server, no need to check 293 * here. 294 */ 295 296 /* Allocate private Context data */ 297 context->privData = (void *)malloc(sizeof(ViaXvMCContext)); 298 if (!context->privData) { 299 fprintf(stderr, "Unable to allocate resources for XvMC context.\n"); 300 return BadAlloc; 301 } 302 303 pViaXvMC = (ViaXvMCContext *) context->privData; 304 pViaXvMC->resources = context_none; 305 306 /* Verify the XvMC extension exists */ 307 308 XLockDisplay(display); 309 if (!XvMCQueryExtension(display, &event_base, &error_base)) { 310 fprintf(stderr, "XvMC Extension is not available!\n"); 311 free(pViaXvMC); 312 XUnlockDisplay(display); 313 return BadAlloc; 314 } 315 316 /* Verify XvMC version */ 317 ret = XvMCQueryVersion(display, &major, &minor); 318 if (ret) { 319 fprintf(stderr, "XvMCQuery Version Failed, unable to determine " 320 "protocol version!\n"); 321 } 322 XUnlockDisplay(display); 323 324 /* FIXME: Check Major and Minor here */ 325 326 XLockDisplay(display); 327 if ((ret = _xvmc_create_context(display, context, &priv_count, 328 &priv_data))) { 329 XUnlockDisplay(display); 330 fprintf(stderr, "Unable to create XvMC Context!\n"); 331 return releaseContextResources(display, context, 1, BadAlloc); 332 } 333 XUnlockDisplay(display); 334 335 /* 336 * Check size and version of returned data. 337 */ 338 339 tmpComm = (ViaXvMCCreateContextRec *) priv_data; 340 if (priv_count != (sizeof(ViaXvMCCreateContextRec) >> 2)) { 341 fprintf(stderr, "_xvmc_create_context() returned incorrect " 342 "data size!\n"); 343 fprintf(stderr, "\tExpected %d, got %d\n", 344 ((int)(sizeof(ViaXvMCCreateContextRec) >> 2)), priv_count); 345 XFree(priv_data); 346 return releaseContextResources(display, context, 1, BadAlloc); 347 } 348 pViaXvMC->resources = context_context; 349 350 if ((tmpComm->major != VIAXVMC_MAJOR) || 351 (tmpComm->minor != VIAXVMC_MINOR)) { 352 fprintf(stderr, "Version mismatch between the X via driver\n" 353 "and the XvMC library. Cannot continue!\n"); 354 XFree(priv_data); 355 return releaseContextResources(display, context, 1, BadAlloc); 356 } 357 358 pViaXvMC->ctxNo = tmpComm->ctxNo; 359 pViaXvMC->fbOffset = tmpComm->fbOffset; 360 pViaXvMC->fbSize = tmpComm->fbSize; 361 pViaXvMC->mmioOffset = tmpComm->mmioOffset; 362 pViaXvMC->mmioSize = tmpComm->mmioSize; 363 pViaXvMC->sAreaSize = tmpComm->sAreaSize; 364 pViaXvMC->sAreaPrivOffset = tmpComm->sAreaPrivOffset; 365 pViaXvMC->decoderOn = 0; 366 pViaXvMC->xvMCPort = tmpComm->xvmc_port; 367 pViaXvMC->useAGP = tmpComm->useAGP; 368 pViaXvMC->attrib = tmpComm->initAttrs; 369 pViaXvMC->screen = tmpComm->screen; 370 pViaXvMC->depth = tmpComm->depth; 371 pViaXvMC->stride = tmpComm->stride; 372 pViaXvMC->chipId = tmpComm->chipId; 373 374 /* 375 * Must free the private data we were passed from X 376 */ 377 378 XFree(priv_data); 379 priv_data = NULL; 380 381 /* 382 * Check for direct rendering capable, establish DRI and DRM connections, 383 * map framebuffer, DRI shared area and read-only register areas. 384 * Initial checking for drm has already been done by the server. 385 * Only do this for the first context we create. 386 */ 387 388 if (numContexts == 0) { 389 XLockDisplay(display); 390 ret = 391 uniDRIQueryDirectRenderingCapable(display, pViaXvMC->screen, 392 &isCapable); 393 if (!ret || !isCapable) { 394 XUnlockDisplay(display); 395 fprintf(stderr, 396 "Direct Rendering is not available on this system!\n"); 397 return releaseContextResources(display, context, 1, BadAlloc); 398 } 399 400 if (!uniDRIOpenConnection(display, pViaXvMC->screen, 401 &pViaXvMC->sAreaOffset, &curBusID)) { 402 XUnlockDisplay(display); 403 fprintf(stderr, "Could not open DRI connection to X server!\n"); 404 return releaseContextResources(display, context, 1, BadAlloc); 405 } 406 XUnlockDisplay(display); 407 408 strncpy(pViaXvMC->busIdString, curBusID, 20); 409 pViaXvMC->busIdString[20] = '\0'; 410 XFree(curBusID); 411 412 pViaXvMC->resources = context_driConnection; 413 414 if ((pViaXvMC->fd = drmOpen("via", pViaXvMC->busIdString)) < 0) { 415 fprintf(stderr, "DRM Device for via could not be opened.\n"); 416 return releaseContextResources(display, context, 1, BadAlloc); 417 } 418 globalFD = pViaXvMC->fd; 419 pViaXvMC->resources = context_fd; 420 421 if (NULL == (drmVer = drmGetVersion(pViaXvMC->fd))) { 422 fprintf(stderr, "viaXvMC: Could not get drm version."); 423 return releaseContextResources(display, context, 1, BadAlloc); 424 } 425 if ((drmVer->version_major < drmExpected.major) || 426 (drmVer->version_major > drmCompat.major) || 427 ((drmVer->version_major == drmExpected.major) && 428 (drmVer->version_minor < drmExpected.minor))) { 429 fprintf(stderr, 430 "viaXvMC: Kernel drm is not compatible with XvMC.\n"); 431 fprintf(stderr, 432 "viaXvMC: Kernel drm version: %d.%d.%d " 433 "and I can work with versions %d.%d.x - %d.x.x\n" 434 "Please update either this XvMC driver or your kernel DRM.\n", 435 drmVer->version_major, drmVer->version_minor, 436 drmVer->version_patchlevel, drmExpected.major, 437 drmExpected.minor, drmCompat.major); 438 drmFreeVersion(drmVer); 439 return releaseContextResources(display, context, 1, BadAlloc); 440 } 441 drmFreeVersion(drmVer); 442 drmGetMagic(pViaXvMC->fd, &magic); 443 444 XLockDisplay(display); 445 if (!uniDRIAuthConnection(display, pViaXvMC->screen, magic)) { 446 XUnlockDisplay(display); 447 fprintf(stderr, 448 "viaXvMC: X server did not allow DRI. Check permissions.\n"); 449 return releaseContextResources(display, context, 1, BadAlloc); 450 } 451 XUnlockDisplay(display); 452 453 /* 454 * Map the register memory 455 */ 456 457 if (drmMap(pViaXvMC->fd, pViaXvMC->mmioOffset, 458 pViaXvMC->mmioSize, &mmioAddress) < 0) { 459 fprintf(stderr, 460 "Unable to map the display chip mmio registers.\n"); 461 return releaseContextResources(display, context, 1, BadAlloc); 462 } 463 pViaXvMC->mmioAddress = mmioAddress; 464 pViaXvMC->resources = context_mmioMap; 465 466 /* 467 * Map Framebuffer memory 468 */ 469 470 if (drmMap(pViaXvMC->fd, pViaXvMC->fbOffset, 471 pViaXvMC->fbSize, &fbAddress) < 0) { 472 fprintf(stderr, "Unable to map XvMC Framebuffer.\n"); 473 return releaseContextResources(display, context, 1, BadAlloc); 474 } 475 pViaXvMC->fbAddress = fbAddress; 476 pViaXvMC->resources = context_fbMap; 477 478 /* 479 * Map DRI Sarea. 480 */ 481 482 if (drmMap(pViaXvMC->fd, pViaXvMC->sAreaOffset, 483 pViaXvMC->sAreaSize, &sAreaAddress) < 0) { 484 fprintf(stderr, "Unable to map DRI SAREA.\n"); 485 return releaseContextResources(display, context, 1, BadAlloc); 486 } 487 } else { 488 pViaXvMC->fd = globalFD; 489 pViaXvMC->mmioAddress = mmioAddress; 490 pViaXvMC->fbAddress = fbAddress; 491 } 492 493 pViaXvMC->sAreaAddress = sAreaAddress; 494 pViaXvMC->resources = context_sAreaMap; 495 numContexts++; 496 497 /* 498 * Find a matching visual. Important only for direct drawing to the visible 499 * frame-buffer. 500 */ 501 502 XLockDisplay(display); 503 ret = XMatchVisualInfo(display, pViaXvMC->screen, 504 (pViaXvMC->depth == 32) ? 24 : pViaXvMC->depth, TrueColor, 505 &pViaXvMC->visualInfo); 506 XUnlockDisplay(display); 507 if (!ret) { 508 fprintf(stderr, 509 "viaXvMC: Could not find a matching TrueColor visual.\n"); 510 return releaseContextResources(display, context, 1, BadAlloc); 511 } 512 513 if (!uniDRICreateContext(display, pViaXvMC->screen, 514 pViaXvMC->visualInfo.visual, &pViaXvMC->id, 515 &pViaXvMC->drmcontext)) { 516 517 fprintf(stderr, "viaXvMC: Could not create DRI context.\n"); 518 return releaseContextResources(display, context, 1, BadAlloc); 519 } 520 521 pViaXvMC->resources = context_drmContext; 522 523 for (i = 0; i < VIA_MAX_RENDSURF; ++i) { 524 pViaXvMC->rendSurf[i] = 0; 525 } 526 pViaXvMC->lastSrfDisplaying = ~0; 527 setupAttribDesc(display, port, &pViaXvMC->attrib, pViaXvMC->attribDesc); 528 529 pViaXvMC->hwLock = (drmLockPtr) pViaXvMC->sAreaAddress; 530 defaultQMatrices(pViaXvMC); 531 pViaXvMC->chromaIntraLoaded = 1; 532 pViaXvMC->chromaNonIntraLoaded = 1; 533 pViaXvMC->yStride = (width + 31) & ~31; 534 pViaXvMC->haveDecoder = 0; 535 pViaXvMC->attribChanged = 1; 536 pViaXvMC->haveXv = 0; 537 pViaXvMC->port = context->port; 538 pthread_mutex_init(&pViaXvMC->ctxMutex, NULL); 539 pViaXvMC->resources = context_mutex; 540 pViaXvMC->timeStamp = 0; 541 setRegion(0, 0, -1, -1, pViaXvMC->sRegion); 542 setRegion(0, 0, -1, -1, pViaXvMC->dRegion); 543 544 if (NULL == (pViaXvMC->xl = 545 initXvMCLowLevel(pViaXvMC->fd, &pViaXvMC->drmcontext, 546 pViaXvMC->hwLock, pViaXvMC->mmioAddress, 547 pViaXvMC->fbAddress, pViaXvMC->stride, pViaXvMC->depth, 548 context->width, context->height, 549 pViaXvMC->useAGP, pViaXvMC->chipId))) { 550 551 fprintf(stderr, "ViaXvMC: Could not allocate timestamp blit area.\n"); 552 return releaseContextResources(display, context, 1, BadAlloc); 553 } 554 pViaXvMC->resources = context_lowLevel; 555 setAGPSyncLowLevel(pViaXvMC->xl, 1, 0); 556 557 if (NULL == (pViaXvMC->drawHash = drmHashCreate())) { 558 fprintf(stderr, "ViaXvMC: Could not allocate drawable hash table.\n"); 559 return releaseContextResources(display, context, 1, BadAlloc); 560 } 561 pViaXvMC->resources = context_drawHash; 562 563 if (numContexts == 1) { 564 hwlLock(pViaXvMC->xl, 1); 565 setLowLevelLocking(pViaXvMC->xl, 0); 566 viaVideoSubPictureOffLocked(pViaXvMC->xl); 567 flushXvMCLowLevel(pViaXvMC->xl); 568 setLowLevelLocking(pViaXvMC->xl, 1); 569 hwlUnlock(pViaXvMC->xl, 1); 570 } 571 572 return Success; 573} 574 575_X_EXPORT Status 576XvMCDestroyContext(Display * display, XvMCContext * context) 577{ 578 ViaXvMCContext *pViaXvMC; 579 580 if (context == NULL) { 581 return (error_base + XvMCBadContext); 582 } 583 if (NULL == (pViaXvMC = context->privData)) { 584 return (error_base + XvMCBadContext); 585 } 586 587 /* 588 * Release decoder if we have it. In case of crash or termination 589 * before XvMCDestroyContext, the X server will take care of this. 590 */ 591 592 releaseAttribDesc(pViaXvMC->attrib.numAttr, pViaXvMC->attribDesc); 593 releaseDecoder(pViaXvMC, 1); 594 return releaseContextResources(display, context, 1, Success); 595} 596 597_X_EXPORT Status 598XvMCCreateSurface(Display * display, XvMCContext * context, 599 XvMCSurface * surface) 600{ 601 ViaXvMCContext *pViaXvMC; 602 ViaXvMCSurface *pViaSurface; 603 int priv_count; 604 unsigned *priv_data; 605 unsigned i; 606 Status ret; 607 608 if ((surface == NULL) || (context == NULL) || (display == NULL)) { 609 return BadValue; 610 } 611 612 pViaXvMC = (ViaXvMCContext *) context->privData; 613 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 614 615 if (pViaXvMC == NULL) { 616 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 617 return (error_base + XvMCBadContext); 618 } 619 620 pViaSurface = surface->privData = 621 (ViaXvMCSurface *) malloc(sizeof(ViaXvMCSurface)); 622 if (!surface->privData) { 623 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 624 return BadAlloc; 625 } 626 XLockDisplay(display); 627 if ((ret = _xvmc_create_surface(display, context, surface, 628 &priv_count, &priv_data))) { 629 XUnlockDisplay(display); 630 free(pViaSurface); 631 fprintf(stderr, "Unable to create XvMC Surface.\n"); 632 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 633 return ret; 634 } 635 XUnlockDisplay(display); 636 637 pViaSurface->srfNo = priv_data[0]; 638 639 /* 640 * Store framebuffer offsets to the buffers allocated for this surface. 641 * For some chipset revisions, surfaces may be double-buffered. 642 */ 643 644 pViaSurface->numBuffers = priv_data[1]; 645 for (i = 0; i < pViaSurface->numBuffers; ++i) { 646 pViaSurface->offsets[i] = priv_data[i + 2]; 647 } 648 pViaSurface->curBuf = 0; 649 650 /* Free data returned from xvmc_create_surface */ 651 652 XFree(priv_data); 653 654 pViaSurface->width = context->width; 655 pViaSurface->height = context->height; 656 pViaSurface->yStride = pViaXvMC->yStride; 657 pViaSurface->privContext = pViaXvMC; 658 pViaSurface->privSubPic = NULL; 659 pViaSurface->needsSync = 0; 660 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 661 return Success; 662} 663 664_X_EXPORT Status 665XvMCDestroySurface(Display * display, XvMCSurface * surface) 666{ 667 ViaXvMCSurface *pViaSurface; 668 669 if ((display == NULL) || (surface == NULL)) { 670 return BadValue; 671 } 672 if (surface->privData == NULL) { 673 return (error_base + XvMCBadSurface); 674 } 675 676 pViaSurface = (ViaXvMCSurface *) surface->privData; 677 678 XLockDisplay(display); 679 _xvmc_destroy_surface(display, surface); 680 XUnlockDisplay(display); 681 682 free(pViaSurface); 683 surface->privData = NULL; 684 return Success; 685} 686 687_X_EXPORT Status 688XvMCPutSlice2(Display * display, XvMCContext * context, char *slice, 689 int nBytes, int sliceCode) 690{ 691 ViaXvMCContext *pViaXvMC; 692 CARD32 sCode = 0x00010000 | (sliceCode & 0xFF) << 24; 693 694 if ((display == NULL) || (context == NULL)) { 695 return BadValue; 696 } 697 if (NULL == (pViaXvMC = context->privData)) { 698 return (error_base + XvMCBadContext); 699 } 700 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 701 if (!pViaXvMC->haveDecoder) { 702 fprintf(stderr, "XvMCPutSlice: This context does not own decoder!\n"); 703 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 704 return BadAlloc; 705 } 706 707 viaMpegWriteSlice(pViaXvMC->xl, (CARD8 *) slice, nBytes, sCode); 708 709 flushPCIXvMCLowLevel(pViaXvMC->xl); 710 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 711 return Success; 712} 713 714_X_EXPORT Status 715XvMCPutSlice(Display * display, XvMCContext * context, char *slice, 716 int nBytes) 717{ 718 ViaXvMCContext *pViaXvMC; 719 720 if ((display == NULL) || (context == NULL)) { 721 return BadValue; 722 } 723 if (NULL == (pViaXvMC = context->privData)) { 724 return (error_base + XvMCBadContext); 725 } 726 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 727 728 if (!pViaXvMC->haveDecoder) { 729 fprintf(stderr, "XvMCPutSlice: This context does not own decoder!\n"); 730 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 731 return BadAlloc; 732 } 733 734 viaMpegWriteSlice(pViaXvMC->xl, (CARD8 *) slice, nBytes, 0); 735 flushPCIXvMCLowLevel(pViaXvMC->xl); 736 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 737 return Success; 738} 739 740static Status 741updateXVOverlay(Display * display, ViaXvMCContext * pViaXvMC, 742 ViaXvMCSurface * pViaSurface, Drawable draw, 743 short srcx, short srcy, unsigned short srcw, 744 unsigned short srch, short destx, short desty, 745 unsigned short destw, unsigned short desth) 746{ 747 ViaXvMCCommandBuffer buf; 748 ViaXvMCSubPicture *pViaSubPic; 749 Status ret; 750 751 if (!pViaXvMC->haveXv) { 752 pViaXvMC->xvImage = 753 XvCreateImage(display, pViaXvMC->port, FOURCC_XVMC, 754 (char *)&buf, pViaSurface->width, pViaSurface->height); 755 pViaXvMC->gc = XCreateGC(display, draw, 0, 0); 756 pViaXvMC->haveXv = 1; 757 } 758 pViaXvMC->draw = draw; 759 pViaXvMC->xvImage->data = (char *)&buf; 760 761 buf.command = (pViaXvMC->attribChanged) ? 762 VIA_XVMC_COMMAND_FDISPLAY : VIA_XVMC_COMMAND_DISPLAY; 763 buf.ctxNo = pViaXvMC->ctxNo | VIA_XVMC_VALID; 764 buf.srfNo = pViaSurface->srfNo | VIA_XVMC_VALID; 765 pViaSubPic = pViaSurface->privSubPic; 766 buf.subPicNo = ((NULL == pViaSubPic) ? 0 : pViaSubPic->srfNo) 767 | VIA_XVMC_VALID; 768 buf.attrib = pViaXvMC->attrib; 769 770 XLockDisplay(display); 771 772 if ((ret = XvPutImage(display, pViaXvMC->port, draw, pViaXvMC->gc, 773 pViaXvMC->xvImage, srcx, srcy, srcw, srch, 774 destx, desty, destw, desth))) { 775 XUnlockDisplay(display); 776 return ret; 777 } 778 XSync(display, 0); 779 XUnlockDisplay(display); 780 pViaXvMC->attribChanged = 0; 781 return Success; 782} 783 784_X_EXPORT Status 785XvMCPutSurface(Display * display, XvMCSurface * surface, Drawable draw, 786 short srcx, short srcy, unsigned short srcw, 787 unsigned short srch, short destx, short desty, 788 unsigned short destw, unsigned short desth, int flags) 789{ 790 /* 791 * This function contains some hairy locking logic. What we really want to 792 * do is to flip the picture ASAP, to get a low latency and smooth playback. 793 * However, if somebody else used the overlay since we used it last or if it is 794 * our first time, we'll have to call X to update the overlay first. Otherwise 795 * we'll do the overlay update once we've flipped. Since we release the hardware 796 * lock when we call X, X needs to verify using the SAREA that nobody else flipped 797 * in a picture between the lock release and the X server control. Similarly 798 * when the overlay update returns, we have to make sure that we still own the 799 * overlay. 800 */ 801 802 ViaXvMCSurface *pViaSurface; 803 ViaXvMCContext *pViaXvMC; 804 ViaXvMCSubPicture *pViaSubPic; 805 volatile ViaXvMCSAreaPriv *sAPriv; 806 Status ret; 807 unsigned dispSurface, lastSurface; 808 int overlayUpdated; 809 drawableInfo *drawInfo; 810 XvMCRegion sReg, dReg; 811 Bool forceUpdate = FALSE; 812 813 if ((display == NULL) || (surface == NULL)) { 814 return BadValue; 815 } 816 if (NULL == (pViaSurface = surface->privData)) { 817 return (error_base + XvMCBadSurface); 818 } 819 if (NULL == (pViaXvMC = pViaSurface->privContext)) { 820 return (error_base + XvMCBadContext); 821 } 822 823 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 824 pViaSubPic = pViaSurface->privSubPic; 825 sAPriv = SAREAPTR(pViaXvMC); 826 827 setRegion(srcx, srcy, srcw, srch, sReg); 828 setRegion(destx, desty, destw, desth, dReg); 829 830 if ((!regionEqual(sReg, pViaXvMC->sRegion)) || 831 (!regionEqual(dReg, pViaXvMC->dRegion))) { 832 833 /* 834 * Force update of the video overlay to match the new format. 835 */ 836 837 pViaXvMC->sRegion = sReg; 838 pViaXvMC->dRegion = dReg; 839 forceUpdate = TRUE; 840 } 841 842 hwlLock(pViaXvMC->xl, 1); 843 844 if (getDRIDrawableInfoLocked(pViaXvMC->drawHash, display, 845 pViaXvMC->screen, draw, 0, pViaXvMC->fd, pViaXvMC->drmcontext, 846 pViaXvMC->sAreaAddress, FALSE, &drawInfo, sizeof(*drawInfo))) { 847 848 hwlUnlock(pViaXvMC->xl, 1); 849 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 850 return BadAccess; 851 } 852 853 setLowLevelLocking(pViaXvMC->xl, 0); 854 855 /* 856 * Put a surface ID in the SAREA to "authenticate" to the 857 * X server. 858 */ 859 860 dispSurface = sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort]; 861 lastSurface = pViaXvMC->lastSrfDisplaying; 862 sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort] = 863 pViaXvMC->lastSrfDisplaying = pViaSurface->srfNo | VIA_XVMC_VALID; 864 overlayUpdated = 0; 865 866 viaVideoSetSWFLipLocked(pViaXvMC->xl, yOffs(pViaSurface), 867 uOffs(pViaSurface), vOffs(pViaSurface), pViaSurface->yStride, 868 pViaSurface->yStride >> 1); 869 870 while ((lastSurface != dispSurface) || forceUpdate) { 871 872 forceUpdate = FALSE; 873 flushPCIXvMCLowLevel(pViaXvMC->xl); 874 setLowLevelLocking(pViaXvMC->xl, 1); 875 hwlUnlock(pViaXvMC->xl, 1); 876 877 /* 878 * We weren't the last to display. Update the overlay before flipping. 879 */ 880 881 ret = 882 updateXVOverlay(display, pViaXvMC, pViaSurface, draw, srcx, srcy, 883 srcw, srch, destx, desty, destw, desth); 884 if (ret) { 885 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 886 return ret; 887 } 888 889 hwlLock(pViaXvMC->xl, 1); 890 891 if (getDRIDrawableInfoLocked(pViaXvMC->drawHash, display, 892 pViaXvMC->screen, draw, 0, pViaXvMC->fd, pViaXvMC->drmcontext, 893 pViaXvMC->sAreaAddress, FALSE, &drawInfo, 894 sizeof(*drawInfo))) { 895 896 hwlUnlock(pViaXvMC->xl, 1); 897 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 898 return BadAccess; 899 } 900 901 setLowLevelLocking(pViaXvMC->xl, 0); 902 lastSurface = pViaSurface->srfNo | VIA_XVMC_VALID; 903 dispSurface = sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort]; 904 overlayUpdated = 1; 905 } 906 907 /* 908 * Subpictures 909 */ 910 911 if (NULL != pViaSubPic) { 912 if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] 913 != (pViaSubPic->srfNo | VIA_XVMC_VALID)) { 914 sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] = 915 pViaSubPic->srfNo | VIA_XVMC_VALID; 916 viaVideoSubPictureLocked(pViaXvMC->xl, pViaSubPic); 917 } 918 } else { 919 if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] & VIA_XVMC_VALID) { 920 viaVideoSubPictureOffLocked(pViaXvMC->xl); 921 sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] &= ~VIA_XVMC_VALID; 922 } 923 } 924 925 /* 926 * Flip 927 */ 928 929 viaVideoSWFlipLocked(pViaXvMC->xl, flags, 930 pViaSurface->progressiveSequence); 931 flushXvMCLowLevel(pViaXvMC->xl); 932 933 setLowLevelLocking(pViaXvMC->xl, 1); 934 hwlUnlock(pViaXvMC->xl, 1); 935 936 if (overlayUpdated || !drawInfo->touched) { 937 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 938 return Success; 939 } 940 941 /* 942 * Update overlay 943 */ 944 945 ret = 946 updateXVOverlay(display, pViaXvMC, pViaSurface, draw, srcx, srcy, 947 srcw, srch, destx, desty, destw, desth); 948 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 949 return ret; 950 951} 952 953void 954debugControl(const XvMCMpegControl * control) 955{ 956 printf("BVMV_range: %u\n", control->BVMV_range); 957 printf("BHMV_range: %u\n", control->BHMV_range); 958 printf("FVMV_range: %u\n", control->FVMV_range); 959 printf("FHMV_range: %u\n", control->FHMV_range); 960 printf("picture_structure: %u\n", control->picture_structure); 961 printf("intra_dc_precision: %u\n", control->intra_dc_precision); 962 printf("picture_coding_type: %u\n", control->picture_coding_type); 963 printf("mpeg_coding: %u\n", control->mpeg_coding); 964 printf("flags: 0x%x\n", control->flags); 965} 966 967_X_EXPORT Status 968XvMCBeginSurface(Display * display, 969 XvMCContext * context, 970 XvMCSurface * target_surface, 971 XvMCSurface * past_surface, 972 XvMCSurface * future_surface, const XvMCMpegControl * control) 973{ 974 ViaXvMCSurface *targS, *futS, *pastS; 975 ViaXvMCContext *pViaXvMC; 976 int hadDecoderLast; 977 CARD32 timeStamp; 978 979 if ((display == NULL) || (context == NULL) || (target_surface == NULL)) { 980 return BadValue; 981 } 982 983 pViaXvMC = context->privData; 984 985 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 986 if (grabDecoder(pViaXvMC, &hadDecoderLast)) { 987 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 988 return BadAlloc; 989 } 990 pViaXvMC->haveDecoder = 1; 991 992 /* 993 * We need to wait for decoder idle at next flush, since hardware doesn't queue 994 * beginsurface requests until the decoder is idle. This is 995 * done by waiting on the last previous timestamp, or if there was another context 996 * having the decoder before us, by emitting a new one. 997 */ 998 999 if (pViaXvMC->useAGP) { 1000 if (!hadDecoderLast || pViaXvMC->timeStamp == 0) { 1001 timeStamp = viaDMATimeStampLowLevel(pViaXvMC->xl); 1002 if (flushXvMCLowLevel(pViaXvMC->xl)) { 1003 releaseDecoder(pViaXvMC, 0); 1004 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1005 return BadAlloc; 1006 } 1007 pViaXvMC->timeStamp = timeStamp; 1008 } else { 1009 timeStamp = pViaXvMC->timeStamp; 1010 } 1011 setAGPSyncLowLevel(pViaXvMC->xl, 1, timeStamp); 1012 } 1013 1014 if (!hadDecoderLast || !pViaXvMC->decoderOn) { 1015 pViaXvMC->intraLoaded = 0; 1016 pViaXvMC->nonIntraLoaded = 0; 1017 } 1018 1019 viaMpegReset(pViaXvMC->xl); 1020 1021 targS = (ViaXvMCSurface *) target_surface->privData; 1022 futS = NULL; 1023 pastS = NULL; 1024 1025 pViaXvMC->rendSurf[0] = targS->srfNo | VIA_XVMC_VALID; 1026 if (future_surface) { 1027 futS = (ViaXvMCSurface *) future_surface->privData; 1028 futS->needsSync = 0; 1029 } 1030 if (past_surface) { 1031 pastS = (ViaXvMCSurface *) past_surface->privData; 1032 pastS->needsSync = 0; 1033 } 1034 1035 targS->progressiveSequence = (control->flags & XVMC_PROGRESSIVE_SEQUENCE); 1036 targS->topFieldFirst = (control->flags & XVMC_TOP_FIELD_FIRST); 1037 targS->privSubPic = NULL; 1038 1039 viaMpegSetSurfaceStride(pViaXvMC->xl, pViaXvMC); 1040 1041 viaMpegSetFB(pViaXvMC->xl, 0, yOffs(targS), uOffs(targS), vOffs(targS)); 1042 if (past_surface) { 1043 viaMpegSetFB(pViaXvMC->xl, 1, yOffs(pastS), uOffs(pastS), 1044 vOffs(pastS)); 1045 } else { 1046 viaMpegSetFB(pViaXvMC->xl, 1, 0, 0, 0); 1047 } 1048 1049 if (future_surface) { 1050 viaMpegSetFB(pViaXvMC->xl, 2, yOffs(futS), uOffs(futS), vOffs(futS)); 1051 } else { 1052 viaMpegSetFB(pViaXvMC->xl, 2, 0, 0, 0); 1053 } 1054 1055 viaMpegBeginPicture(pViaXvMC->xl, pViaXvMC, context->width, 1056 context->height, control); 1057 flushPCIXvMCLowLevel(pViaXvMC->xl); 1058 targS->needsSync = 1; 1059 targS->syncMode = LL_MODE_DECODER_IDLE; 1060 pViaXvMC->decoderOn = 1; 1061 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1062 return Success; 1063} 1064 1065_X_EXPORT Status 1066XvMCSyncSurface(Display * display, XvMCSurface * surface) 1067{ 1068 ViaXvMCSurface *pViaSurface; 1069 ViaXvMCContext *pViaXvMC; 1070 unsigned i; 1071 1072 if ((display == NULL) || (surface == NULL)) { 1073 return BadValue; 1074 } 1075 if (surface->privData == NULL) { 1076 return (error_base + XvMCBadSurface); 1077 } 1078 1079 pViaSurface = (ViaXvMCSurface *) surface->privData; 1080 pViaXvMC = pViaSurface->privContext; 1081 1082 if (pViaXvMC == NULL) { 1083 return (error_base + XvMCBadSurface); 1084 } 1085 1086 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1087 1088 if (pViaSurface->needsSync) { 1089 CARD32 timeStamp = pViaSurface->timeStamp; 1090 int syncMode = pViaSurface->syncMode; 1091 1092 if (pViaXvMC->useAGP) { 1093 1094 syncMode = (pViaSurface->syncMode == LL_MODE_2D || 1095 pViaSurface->timeStamp < pViaXvMC->timeStamp) ? 1096 LL_MODE_2D : LL_MODE_DECODER_IDLE; 1097 if (pViaSurface->syncMode != LL_MODE_2D) 1098 timeStamp = pViaXvMC->timeStamp; 1099 1100 } else if (syncMode != LL_MODE_2D && 1101 pViaXvMC->rendSurf[0] != (pViaSurface->srfNo | VIA_XVMC_VALID)) { 1102 1103 pViaSurface->needsSync = 0; 1104 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1105 return Success; 1106 } 1107 1108 if (syncXvMCLowLevel(pViaXvMC->xl, syncMode, 1, 1109 pViaSurface->timeStamp)) { 1110 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1111 return BadValue; 1112 } 1113 pViaSurface->needsSync = 0; 1114 } 1115 1116 if (pViaXvMC->rendSurf[0] == (pViaSurface->srfNo | VIA_XVMC_VALID)) { 1117 pViaSurface->needsSync = 0; 1118 for (i = 0; i < VIA_MAX_RENDSURF; ++i) { 1119 pViaXvMC->rendSurf[i] = 0; 1120 } 1121 } 1122 1123 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1124 return Success; 1125} 1126 1127_X_EXPORT Status 1128XvMCLoadQMatrix(Display * display, XvMCContext * context, 1129 const XvMCQMatrix * qmx) 1130{ 1131 ViaXvMCContext * pViaXvMC; 1132 1133 if ((display == NULL) || (context == NULL)) { 1134 return BadValue; 1135 } 1136 if (NULL == (pViaXvMC = context->privData)) { 1137 return (error_base + XvMCBadContext); 1138 } 1139 1140 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1141 if (qmx->load_intra_quantiser_matrix) { 1142 memcpy(pViaXvMC->intra_quantiser_matrix, 1143 qmx->intra_quantiser_matrix, sizeof(qmx->intra_quantiser_matrix)); 1144 pViaXvMC->intraLoaded = 0; 1145 } 1146 1147 if (qmx->load_non_intra_quantiser_matrix) { 1148 memcpy(pViaXvMC->non_intra_quantiser_matrix, 1149 qmx->non_intra_quantiser_matrix, 1150 sizeof(qmx->non_intra_quantiser_matrix)); 1151 pViaXvMC->nonIntraLoaded = 0; 1152 } 1153 1154 if (qmx->load_chroma_intra_quantiser_matrix) { 1155 memcpy(pViaXvMC->chroma_intra_quantiser_matrix, 1156 qmx->chroma_intra_quantiser_matrix, 1157 sizeof(qmx->chroma_intra_quantiser_matrix)); 1158 pViaXvMC->chromaIntraLoaded = 0; 1159 } 1160 1161 if (qmx->load_chroma_non_intra_quantiser_matrix) { 1162 memcpy(pViaXvMC->chroma_non_intra_quantiser_matrix, 1163 qmx->chroma_non_intra_quantiser_matrix, 1164 sizeof(qmx->chroma_non_intra_quantiser_matrix)); 1165 pViaXvMC->chromaNonIntraLoaded = 0; 1166 } 1167 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1168 1169 return Success; 1170} 1171 1172/* 1173 * Below, we provide functions unusable for this implementation, but for 1174 * standard completeness. 1175 */ 1176 1177_X_EXPORT Status XvMCRenderSurface 1178 (Display * display, 1179 XvMCContext * context, 1180 unsigned int picture_structure, 1181 XvMCSurface * target_surface, 1182 XvMCSurface * past_surface, 1183 XvMCSurface * future_surface, 1184 unsigned int flags, 1185 unsigned int num_macroblocks, 1186 unsigned int first_macroblock, 1187 XvMCMacroBlockArray * macroblock_array, XvMCBlockArray * blocks) 1188{ 1189 return (error_base + XvMCBadContext); 1190} 1191 1192_X_EXPORT Status XvMCCreateBlocks 1193 (Display * display, 1194 XvMCContext * context, unsigned int num_blocks, XvMCBlockArray * block) 1195{ 1196 return (error_base + XvMCBadContext); 1197} 1198 1199_X_EXPORT Status 1200XvMCDestroyBlocks(Display * display, XvMCBlockArray * block) 1201{ 1202 return Success; 1203} 1204 1205_X_EXPORT Status XvMCCreateMacroBlocks 1206 (Display * display, 1207 XvMCContext * context, 1208 unsigned int num_blocks, XvMCMacroBlockArray * blocks) 1209{ 1210 return (error_base + XvMCBadContext); 1211} 1212 1213_X_EXPORT Status 1214XvMCDestroyMacroBlocks(Display * display, XvMCMacroBlockArray * block) 1215{ 1216 return (error_base + XvMCBadContext); 1217} 1218 1219_X_EXPORT Status 1220XvMCCreateSubpicture(Display * display, 1221 XvMCContext * context, 1222 XvMCSubpicture * subpicture, 1223 unsigned short width, unsigned short height, int xvimage_id) 1224{ 1225 ViaXvMCContext *pViaXvMC; 1226 ViaXvMCSubPicture *pViaSubPic; 1227 int priv_count; 1228 unsigned *priv_data; 1229 Status ret; 1230 1231 if ((subpicture == NULL) || (context == NULL) || (display == NULL)) { 1232 return BadValue; 1233 } 1234 1235 pViaXvMC = (ViaXvMCContext *) context->privData; 1236 if (pViaXvMC == NULL) { 1237 return (error_base + XvMCBadContext); 1238 } 1239 1240 subpicture->privData = (ViaXvMCSubPicture *) 1241 malloc(sizeof(ViaXvMCSubPicture)); 1242 if (!subpicture->privData) { 1243 return BadAlloc; 1244 } 1245 1246 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1247 subpicture->width = context->width; 1248 subpicture->height = context->height; 1249 subpicture->xvimage_id = xvimage_id; 1250 pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData; 1251 1252 XLockDisplay(display); 1253 if ((ret = _xvmc_create_subpicture(display, context, subpicture, 1254 &priv_count, &priv_data))) { 1255 XUnlockDisplay(display); 1256 free(pViaSubPic); 1257 fprintf(stderr, "Unable to create XvMC Subpicture.\n"); 1258 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1259 return ret; 1260 } 1261 XUnlockDisplay(display); 1262 1263 subpicture->num_palette_entries = VIA_SUBPIC_PALETTE_SIZE; 1264 subpicture->entry_bytes = 3; 1265 strncpy(subpicture->component_order, "YUV", 4); 1266 pViaSubPic->srfNo = priv_data[0]; 1267 pViaSubPic->offset = priv_data[1]; 1268 pViaSubPic->stride = (subpicture->width + 31) & ~31; 1269 pViaSubPic->privContext = pViaXvMC; 1270 pViaSubPic->ia44 = (xvimage_id == FOURCC_IA44); 1271 pViaSubPic->needsSync = 0; 1272 1273 /* Free data returned from _xvmc_create_subpicture */ 1274 1275 XFree(priv_data); 1276 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1277 return Success; 1278} 1279 1280_X_EXPORT Status 1281XvMCSetSubpicturePalette(Display * display, XvMCSubpicture * subpicture, 1282 unsigned char *palette) 1283{ 1284 ViaXvMCSubPicture *pViaSubPic; 1285 ViaXvMCContext *pViaXvMC; 1286 volatile ViaXvMCSAreaPriv *sAPriv; 1287 unsigned i; 1288 CARD32 tmp; 1289 1290 if ((subpicture == NULL) || (display == NULL)) { 1291 return BadValue; 1292 } 1293 if (subpicture->privData == NULL) { 1294 return (error_base + XvMCBadSubpicture); 1295 } 1296 pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData; 1297 for (i = 0; i < VIA_SUBPIC_PALETTE_SIZE; ++i) { 1298 tmp = *palette++ << 8; 1299 tmp |= *palette++ << 16; 1300 tmp |= *palette++ << 24; 1301 tmp |= ((i & 0x0f) << 4) | 0x07; 1302 pViaSubPic->palette[i] = tmp; 1303 } 1304 1305 pViaXvMC = pViaSubPic->privContext; 1306 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1307 sAPriv = SAREAPTR(pViaXvMC); 1308 hwlLock(pViaXvMC->xl, 1); 1309 setLowLevelLocking(pViaXvMC->xl, 0); 1310 1311 /* 1312 * If the subpicture is displaying, Immeadiately update it with the 1313 * new palette. 1314 */ 1315 1316 if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] == 1317 (pViaSubPic->srfNo | VIA_XVMC_VALID)) { 1318 viaVideoSubPictureLocked(pViaXvMC->xl, pViaSubPic); 1319 } 1320 flushPCIXvMCLowLevel(pViaXvMC->xl); 1321 setLowLevelLocking(pViaXvMC->xl, 1); 1322 hwlUnlock(pViaXvMC->xl, 1); 1323 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1324 return Success; 1325} 1326 1327static int 1328findOverlap(unsigned width, unsigned height, 1329 short *dstX, short *dstY, 1330 short *srcX, short *srcY, unsigned short *areaW, unsigned short *areaH) 1331{ 1332 int w, h; 1333 unsigned mWidth, mHeight; 1334 1335 w = *areaW; 1336 h = *areaH; 1337 1338 if ((*dstX >= width) || (*dstY >= height)) 1339 return 1; 1340 if (*dstX < 0) { 1341 w += *dstX; 1342 *srcX -= *dstX; 1343 *dstX = 0; 1344 } 1345 if (*dstY < 0) { 1346 h += *dstY; 1347 *srcY -= *dstY; 1348 *dstY = 0; 1349 } 1350 if ((w <= 0) || ((h <= 0))) 1351 return 1; 1352 mWidth = width - *dstX; 1353 mHeight = height - *dstY; 1354 *areaW = (w <= mWidth) ? w : mWidth; 1355 *areaH = (h <= mHeight) ? h : mHeight; 1356 return 0; 1357} 1358 1359_X_EXPORT Status 1360XvMCClearSubpicture(Display * display, 1361 XvMCSubpicture * subpicture, 1362 short x, 1363 short y, unsigned short width, unsigned short height, unsigned int color) 1364{ 1365 1366 ViaXvMCContext *pViaXvMC; 1367 ViaXvMCSubPicture *pViaSubPic; 1368 short dummyX, dummyY; 1369 unsigned long bOffs; 1370 1371 if ((subpicture == NULL) || (display == NULL)) { 1372 return BadValue; 1373 } 1374 if (subpicture->privData == NULL) { 1375 return (error_base + XvMCBadSubpicture); 1376 } 1377 pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData; 1378 pViaXvMC = pViaSubPic->privContext; 1379 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1380 1381 /* Clip clearing area so that it fits inside subpicture. */ 1382 1383 if (findOverlap(subpicture->width, subpicture->height, &x, &y, 1384 &dummyX, &dummyY, &width, &height)) { 1385 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1386 return Success; 1387 } 1388 1389 bOffs = pViaSubPic->offset + y * pViaSubPic->stride + x; 1390 viaBlit(pViaXvMC->xl, 8, 0, pViaSubPic->stride, bOffs, pViaSubPic->stride, 1391 width, height, 1, 1, VIABLIT_FILL, color); 1392 pViaSubPic->needsSync = 1; 1393 pViaSubPic->timeStamp = viaDMATimeStampLowLevel(pViaXvMC->xl); 1394 if (flushXvMCLowLevel(pViaXvMC->xl)) { 1395 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1396 return BadValue; 1397 } 1398 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1399 return Success; 1400} 1401 1402_X_EXPORT Status 1403XvMCCompositeSubpicture(Display * display, 1404 XvMCSubpicture * subpicture, 1405 XvImage * image, 1406 short srcx, 1407 short srcy, 1408 unsigned short width, unsigned short height, short dstx, short dsty) 1409{ 1410 1411 unsigned i; 1412 ViaXvMCContext *pViaXvMC; 1413 ViaXvMCSubPicture *pViaSubPic; 1414 CARD8 *dAddr, *sAddr; 1415 1416 if ((subpicture == NULL) || (display == NULL) || (image == NULL)) { 1417 return BadValue; 1418 } 1419 if (NULL == (pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData)) { 1420 return (error_base + XvMCBadSubpicture); 1421 } 1422 1423 pViaXvMC = pViaSubPic->privContext; 1424 1425 if (image->id != subpicture->xvimage_id) 1426 return BadMatch; 1427 1428 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1429 1430 /* 1431 * Clip copy area so that it fits inside subpicture and image. 1432 */ 1433 1434 if (findOverlap(subpicture->width, subpicture->height, 1435 &dstx, &dsty, &srcx, &srcy, &width, &height)) { 1436 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1437 return Success; 1438 } 1439 if (findOverlap(image->width, image->height, 1440 &srcx, &srcy, &dstx, &dsty, &width, &height)) { 1441 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1442 return Success; 1443 } 1444 1445 if (pViaSubPic->needsSync) { 1446 if (syncXvMCLowLevel(pViaXvMC->xl, LL_MODE_2D, 0, 1447 pViaSubPic->timeStamp)) { 1448 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1449 return BadValue; 1450 } 1451 pViaSubPic->needsSync = 0; 1452 } 1453 1454 for (i = 0; i < height; ++i) { 1455 dAddr = (((CARD8 *) pViaXvMC->fbAddress) + 1456 (pViaSubPic->offset + (dsty + i) * pViaSubPic->stride + dstx)); 1457 sAddr = (((CARD8 *) image->data) + 1458 (image->offsets[0] + (srcy + i) * image->pitches[0] + srcx)); 1459 memcpy(dAddr, sAddr, width); 1460 } 1461 1462 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1463 return Success; 1464} 1465 1466_X_EXPORT Status 1467XvMCBlendSubpicture(Display * display, 1468 XvMCSurface * target_surface, 1469 XvMCSubpicture * subpicture, 1470 short subx, 1471 short suby, 1472 unsigned short subw, 1473 unsigned short subh, 1474 short surfx, short surfy, unsigned short surfw, unsigned short surfh) 1475{ 1476 ViaXvMCSurface *pViaSurface; 1477 ViaXvMCSubPicture *pViaSubPic; 1478 1479 if ((display == NULL) || target_surface == NULL) { 1480 return BadValue; 1481 } 1482 1483 if (subx || suby || surfx || surfy || (subw != surfw) || (subh != surfh)) { 1484 fprintf(stderr, "ViaXvMC: Only completely overlapping subpicture " 1485 "supported.\n"); 1486 return BadValue; 1487 } 1488 1489 if (NULL == (pViaSurface = target_surface->privData)) { 1490 return (error_base + XvMCBadSurface); 1491 } 1492 1493 if (subpicture) { 1494 1495 if (NULL == (pViaSubPic = subpicture->privData)) { 1496 return (error_base + XvMCBadSubpicture); 1497 } 1498 1499 pViaSurface->privSubPic = pViaSubPic; 1500 } else { 1501 pViaSurface->privSubPic = NULL; 1502 } 1503 return Success; 1504} 1505 1506_X_EXPORT Status 1507XvMCBlendSubpicture2(Display * display, 1508 XvMCSurface * source_surface, 1509 XvMCSurface * target_surface, 1510 XvMCSubpicture * subpicture, 1511 short subx, 1512 short suby, 1513 unsigned short subw, 1514 unsigned short subh, 1515 short surfx, short surfy, unsigned short surfw, unsigned short surfh) 1516{ 1517 ViaXvMCSurface *pViaSurface, *pViaSSurface; 1518 ViaXvMCSubPicture *pViaSubPic; 1519 ViaXvMCContext *pViaXvMC; 1520 1521 unsigned width, height; 1522 1523 if ((display == NULL) || target_surface == NULL || source_surface == NULL) { 1524 return BadValue; 1525 } 1526 1527 if (subx || suby || surfx || surfy || (subw != surfw) || (subh != surfh)) { 1528 fprintf(stderr, "ViaXvMC: Only completely overlapping subpicture " 1529 "supported.\n"); 1530 return BadMatch; 1531 } 1532 1533 if (NULL == (pViaSurface = target_surface->privData)) { 1534 return (error_base + XvMCBadSurface); 1535 } 1536 1537 if (NULL == (pViaSSurface = source_surface->privData)) { 1538 return (error_base + XvMCBadSurface); 1539 } 1540 pViaXvMC = pViaSurface->privContext; 1541 width = pViaSSurface->width; 1542 height = pViaSSurface->height; 1543 if (width != pViaSurface->width || height != pViaSSurface->height) { 1544 return BadMatch; 1545 } 1546 1547 if (XvMCSyncSurface(display, source_surface)) { 1548 return BadValue; 1549 } 1550 1551 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1552 viaBlit(pViaXvMC->xl, 8, yOffs(pViaSSurface), pViaSSurface->yStride, 1553 yOffs(pViaSurface), pViaSurface->yStride, 1554 width, height, 1, 1, VIABLIT_COPY, 0); 1555 flushPCIXvMCLowLevel(pViaXvMC->xl); 1556 if (pViaXvMC->chipId != PCI_CHIP_VT3259) { 1557 1558 /* 1559 * YV12 Chroma blit. 1560 */ 1561 1562 viaBlit(pViaXvMC->xl, 8, uOffs(pViaSSurface), 1563 pViaSSurface->yStride >> 1, uOffs(pViaSurface), 1564 pViaSurface->yStride >> 1, width >> 1, height >> 1, 1, 1, 1565 VIABLIT_COPY, 0); 1566 flushPCIXvMCLowLevel(pViaXvMC->xl); 1567 viaBlit(pViaXvMC->xl, 8, vOffs(pViaSSurface), 1568 pViaSSurface->yStride >> 1, vOffs(pViaSurface), 1569 pViaSurface->yStride >> 1, width >> 1, height >> 1, 1, 1, 1570 VIABLIT_COPY, 0); 1571 } else { 1572 1573 /* 1574 * NV12 Chroma blit. 1575 */ 1576 1577 viaBlit(pViaXvMC->xl, 8, vOffs(pViaSSurface), pViaSSurface->yStride, 1578 vOffs(pViaSurface), pViaSurface->yStride, 1579 width, height >> 1, 1, 1, VIABLIT_COPY, 0); 1580 } 1581 pViaSurface->needsSync = 1; 1582 pViaSurface->syncMode = LL_MODE_2D; 1583 pViaSurface->timeStamp = viaDMATimeStampLowLevel(pViaXvMC->xl); 1584 if (flushXvMCLowLevel(pViaXvMC->xl)) { 1585 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1586 return BadValue; 1587 } 1588 if (subpicture) { 1589 1590 if (NULL == (pViaSubPic = subpicture->privData)) { 1591 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1592 return (error_base + XvMCBadSubpicture); 1593 } 1594 1595 pViaSurface->privSubPic = pViaSubPic; 1596 } else { 1597 pViaSurface->privSubPic = NULL; 1598 } 1599 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1600 return Success; 1601} 1602 1603_X_EXPORT Status 1604XvMCSyncSubpicture(Display * display, XvMCSubpicture * subpicture) 1605{ 1606 ViaXvMCSubPicture *pViaSubPic; 1607 ViaXvMCContext *pViaXvMC; 1608 Status retVal = 0; 1609 1610 if ((display == NULL) || subpicture == NULL) { 1611 return BadValue; 1612 } 1613 if (NULL == (pViaSubPic = subpicture->privData)) { 1614 return (error_base + XvMCBadSubpicture); 1615 } 1616 1617 pViaXvMC = pViaSubPic->privContext; 1618 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1619 if (pViaSubPic->needsSync) { 1620 if (syncXvMCLowLevel(pViaXvMC->xl, LL_MODE_2D, 1621 0, pViaSubPic->timeStamp)) { 1622 retVal = BadValue; 1623 } 1624 pViaSubPic->needsSync = 0; 1625 } 1626 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1627 return retVal; 1628} 1629 1630_X_EXPORT Status 1631XvMCFlushSubpicture(Display * display, XvMCSubpicture * subpicture) 1632{ 1633 ViaXvMCSubPicture *pViaSubPic; 1634 1635 if ((display == NULL) || subpicture == NULL) { 1636 return BadValue; 1637 } 1638 if (NULL == (pViaSubPic = subpicture->privData)) { 1639 return (error_base + XvMCBadSubpicture); 1640 } 1641 1642 return Success; 1643} 1644 1645_X_EXPORT Status 1646XvMCDestroySubpicture(Display * display, XvMCSubpicture * subpicture) 1647{ 1648 ViaXvMCSubPicture *pViaSubPic; 1649 ViaXvMCContext *pViaXvMC; 1650 volatile ViaXvMCSAreaPriv *sAPriv; 1651 1652 if ((display == NULL) || subpicture == NULL) { 1653 return BadValue; 1654 } 1655 if (NULL == (pViaSubPic = subpicture->privData)) { 1656 return (error_base + XvMCBadSubpicture); 1657 } 1658 pViaXvMC = pViaSubPic->privContext; 1659 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1660 1661 sAPriv = SAREAPTR(pViaXvMC); 1662 hwlLock(pViaXvMC->xl, 1); 1663 setLowLevelLocking(pViaXvMC->xl, 0); 1664 if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] == 1665 (pViaSubPic->srfNo | VIA_XVMC_VALID)) { 1666 viaVideoSubPictureOffLocked(pViaXvMC->xl); 1667 sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] = 0; 1668 } 1669 flushPCIXvMCLowLevel(pViaXvMC->xl); 1670 setLowLevelLocking(pViaXvMC->xl, 1); 1671 hwlUnlock(pViaXvMC->xl, 1); 1672 1673 XLockDisplay(display); 1674 _xvmc_destroy_subpicture(display, subpicture); 1675 XUnlockDisplay(display); 1676 1677 free(pViaSubPic); 1678 subpicture->privData = NULL; 1679 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1680 1681 return Success; 1682} 1683 1684_X_EXPORT Status 1685XvMCGetSubpictureStatus(Display * display, XvMCSubpicture * subpic, int *stat) 1686{ 1687 ViaXvMCSubPicture *pViaSubPic; 1688 ViaXvMCContext *pViaXvMC; 1689 volatile ViaXvMCSAreaPriv *sAPriv; 1690 1691 if ((display == NULL) || subpic == NULL) { 1692 return BadValue; 1693 } 1694 if (NULL == (pViaSubPic = subpic->privData)) { 1695 return (error_base + XvMCBadSubpicture); 1696 } 1697 if (stat) { 1698 *stat = 0; 1699 pViaXvMC = pViaSubPic->privContext; 1700 sAPriv = SAREAPTR(pViaXvMC); 1701 if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] == 1702 (pViaSubPic->srfNo | VIA_XVMC_VALID)) 1703 *stat |= XVMC_DISPLAYING; 1704 } 1705 return Success; 1706} 1707 1708_X_EXPORT Status 1709XvMCFlushSurface(Display * display, XvMCSurface * surface) 1710{ 1711 ViaXvMCSurface *pViaSurface; 1712 ViaXvMCContext *pViaXvMC; 1713 Status ret; 1714 1715 if ((display == NULL) || surface == NULL) { 1716 return BadValue; 1717 } 1718 if (NULL == (pViaSurface = surface->privData)) { 1719 return (error_base + XvMCBadSurface); 1720 } 1721 1722 pViaXvMC = pViaSurface->privContext; 1723 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1724 if (pViaSurface->needsSync) 1725 pViaSurface->timeStamp = pViaXvMC->timeStamp = 1726 viaDMATimeStampLowLevel(pViaXvMC->xl); 1727 ret = (flushXvMCLowLevel(pViaXvMC->xl)) ? BadValue : Success; 1728 if (pViaXvMC->rendSurf[0] == (pViaSurface->srfNo | VIA_XVMC_VALID)) { 1729 hwlLock(pViaXvMC->xl, 0); 1730 pViaXvMC->haveDecoder = 0; 1731 releaseDecoder(pViaXvMC, 0); 1732 hwlUnlock(pViaXvMC->xl, 0); 1733 } 1734 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1735 return ret; 1736} 1737 1738_X_EXPORT Status 1739XvMCGetSurfaceStatus(Display * display, XvMCSurface * surface, int *stat) 1740{ 1741 ViaXvMCSurface *pViaSurface; 1742 ViaXvMCContext *pViaXvMC; 1743 volatile ViaXvMCSAreaPriv *sAPriv; 1744 unsigned i; 1745 int ret = 0; 1746 1747 if ((display == NULL) || surface == NULL) { 1748 return BadValue; 1749 } 1750 if (NULL == (pViaSurface = surface->privData)) { 1751 return (error_base + XvMCBadSurface); 1752 } 1753 if (stat) { 1754 *stat = 0; 1755 pViaXvMC = pViaSurface->privContext; 1756 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1757 sAPriv = SAREAPTR(pViaXvMC); 1758 if (sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort] 1759 == (pViaSurface->srfNo | VIA_XVMC_VALID)) 1760 *stat |= XVMC_DISPLAYING; 1761 for (i = 0; i < VIA_MAX_RENDSURF; ++i) { 1762 if (pViaXvMC->rendSurf[i] == 1763 (pViaSurface->srfNo | VIA_XVMC_VALID)) { 1764 *stat |= XVMC_RENDERING; 1765 break; 1766 } 1767 } 1768 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1769 } 1770 return ret; 1771} 1772 1773_X_EXPORT XvAttribute * 1774XvMCQueryAttributes(Display * display, XvMCContext * context, int *number) 1775{ 1776 ViaXvMCContext *pViaXvMC; 1777 XvAttribute *ret; 1778 unsigned long siz; 1779 1780 *number = 0; 1781 if ((display == NULL) || (context == NULL)) { 1782 return NULL; 1783 } 1784 1785 if (NULL == (pViaXvMC = context->privData)) { 1786 return NULL; 1787 } 1788 1789 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1790 if (NULL != (ret = (XvAttribute *) 1791 malloc(siz = VIA_NUM_XVMC_ATTRIBUTES * sizeof(XvAttribute)))) { 1792 memcpy(ret, pViaXvMC->attribDesc, siz); 1793 *number = VIA_NUM_XVMC_ATTRIBUTES; 1794 } 1795 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1796 1797 return ret; 1798} 1799 1800_X_EXPORT Status 1801XvMCSetAttribute(Display * display, 1802 XvMCContext * context, Atom attribute, int value) 1803{ 1804 int found; 1805 unsigned i; 1806 ViaXvMCContext *pViaXvMC; 1807 ViaXvMCCommandBuffer buf; 1808 1809 if ((display == NULL) || (context == NULL)) { 1810 return (error_base + XvMCBadContext); 1811 } 1812 1813 if (NULL == (pViaXvMC = context->privData)) { 1814 return (error_base + XvMCBadContext); 1815 } 1816 1817 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1818 1819 found = 0; 1820 for (i = 0; i < pViaXvMC->attrib.numAttr; ++i) { 1821 if (attribute == pViaXvMC->attrib.attributes[i].attribute) { 1822 if ((!(pViaXvMC->attribDesc[i].flags & XvSettable)) || 1823 value < pViaXvMC->attribDesc[i].min_value || 1824 value > pViaXvMC->attribDesc[i].max_value) { 1825 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1826 return BadValue; 1827 } 1828 pViaXvMC->attrib.attributes[i].value = value; 1829 found = 1; 1830 pViaXvMC->attribChanged = 1; 1831 break; 1832 } 1833 } 1834 if (!found) { 1835 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1836 return BadMatch; 1837 } 1838 if (pViaXvMC->haveXv) { 1839 buf.command = VIA_XVMC_COMMAND_ATTRIBUTES; 1840 pViaXvMC->xvImage->data = (char *)&buf; 1841 buf.ctxNo = pViaXvMC->ctxNo | VIA_XVMC_VALID; 1842 buf.attrib = pViaXvMC->attrib; 1843 XLockDisplay(display); 1844 pViaXvMC->attribChanged = 1845 XvPutImage(display, pViaXvMC->port, pViaXvMC->draw, 1846 pViaXvMC->gc, pViaXvMC->xvImage, 0, 0, 1, 1, 0, 0, 1, 1); 1847 XUnlockDisplay(display); 1848 } 1849 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1850 return Success; 1851} 1852 1853_X_EXPORT Status 1854XvMCGetAttribute(Display * display, 1855 XvMCContext * context, Atom attribute, int *value) 1856{ 1857 int found; 1858 unsigned i; 1859 ViaXvMCContext *pViaXvMC; 1860 1861 if ((display == NULL) || (context == NULL)) { 1862 return (error_base + XvMCBadContext); 1863 } 1864 1865 if (NULL == (pViaXvMC = context->privData)) { 1866 return (error_base + XvMCBadContext); 1867 } 1868 1869 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1870 found = 0; 1871 for (i = 0; i < pViaXvMC->attrib.numAttr; ++i) { 1872 if (attribute == pViaXvMC->attrib.attributes[i].attribute) { 1873 if (pViaXvMC->attribDesc[i].flags & XvGettable) { 1874 *value = pViaXvMC->attrib.attributes[i].value; 1875 found = 1; 1876 break; 1877 } 1878 } 1879 } 1880 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1881 1882 if (!found) 1883 return BadMatch; 1884 return Success; 1885} 1886 1887_X_EXPORT Status 1888XvMCHideSurface(Display * display, XvMCSurface * surface) 1889{ 1890 1891 ViaXvMCSurface *pViaSurface; 1892 ViaXvMCContext *pViaXvMC; 1893 ViaXvMCSubPicture *pViaSubPic; 1894 volatile ViaXvMCSAreaPriv *sAPriv; 1895 ViaXvMCCommandBuffer buf; 1896 Status ret; 1897 1898 if ((display == NULL) || (surface == NULL)) { 1899 return BadValue; 1900 } 1901 if (NULL == (pViaSurface = surface->privData)) { 1902 return (error_base + XvMCBadSurface); 1903 } 1904 if (NULL == (pViaXvMC = pViaSurface->privContext)) { 1905 return (error_base + XvMCBadContext); 1906 } 1907 1908 ppthread_mutex_lock(&pViaXvMC->ctxMutex); 1909 if (!pViaXvMC->haveXv) { 1910 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1911 return Success; 1912 } 1913 1914 sAPriv = SAREAPTR(pViaXvMC); 1915 hwlLock(pViaXvMC->xl, 1); 1916 1917 if (sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort] != 1918 (pViaSurface->srfNo | VIA_XVMC_VALID)) { 1919 hwlUnlock(pViaXvMC->xl, 1); 1920 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1921 return Success; 1922 } 1923 setLowLevelLocking(pViaXvMC->xl, 0); 1924 if (NULL != (pViaSubPic = pViaSurface->privSubPic)) { 1925 if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] == 1926 (pViaSubPic->srfNo | VIA_XVMC_VALID)) { 1927 sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] &= ~VIA_XVMC_VALID; 1928 viaVideoSubPictureOffLocked(pViaXvMC->xl); 1929 } 1930 } 1931 flushPCIXvMCLowLevel(pViaXvMC->xl); 1932 setLowLevelLocking(pViaXvMC->xl, 1); 1933 hwlUnlock(pViaXvMC->xl, 1); 1934 1935 buf.command = VIA_XVMC_COMMAND_UNDISPLAY; 1936 buf.ctxNo = pViaXvMC->ctxNo | VIA_XVMC_VALID; 1937 buf.srfNo = pViaSurface->srfNo | VIA_XVMC_VALID; 1938 pViaXvMC->xvImage->data = (char *)&buf; 1939 if ((ret = XvPutImage(display, pViaXvMC->port, pViaXvMC->draw, 1940 pViaXvMC->gc, pViaXvMC->xvImage, 0, 0, 1, 1, 0, 0, 1, 1))) { 1941 fprintf(stderr, "XvMCPutSurface: Hiding overlay failed.\n"); 1942 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1943 return ret; 1944 } 1945 ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 1946 return Success; 1947} 1948