190b17f1bSmrg/***************************************************************************** 290b17f1bSmrg * VIA Unichrome XvMC extension client lib. 390b17f1bSmrg * 490b17f1bSmrg * Copyright (c) 2004-2005 Thomas Hellstr�m. All rights reserved. 590b17f1bSmrg * 690b17f1bSmrg * Permission is hereby granted, free of charge, to any person obtaining a 790b17f1bSmrg * copy of this software and associated documentation files (the "Software"), 890b17f1bSmrg * to deal in the Software without restriction, including without limitation 990b17f1bSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1090b17f1bSmrg * and/or sell copies of the Software, and to permit persons to whom the 1190b17f1bSmrg * Software is furnished to do so, subject to the following conditions: 1290b17f1bSmrg * 1390b17f1bSmrg * The above copyright notice and this permission notice shall be included in 1490b17f1bSmrg * all copies or substantial portions of the Software. 1590b17f1bSmrg * 1690b17f1bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1790b17f1bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1890b17f1bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1990b17f1bSmrg * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2090b17f1bSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2190b17f1bSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2290b17f1bSmrg * DEALINGS IN THE SOFTWARE. 2390b17f1bSmrg */ 2490b17f1bSmrg 2590b17f1bSmrg/* 2690b17f1bSmrg *Author: Thomas Hellstr�m, 2004. 2790b17f1bSmrg *Bugfixes by among others Pascal Brisset and Terry Barnaby. 2890b17f1bSmrg *DRI protocol support by Thomas Hellstr�m, 2005. 2990b17f1bSmrg */ 3090b17f1bSmrg 3190b17f1bSmrg#undef WAITPAUSE 3290b17f1bSmrg 3390b17f1bSmrg#include "viaXvMCPriv.h" 3490b17f1bSmrg#include "viaLowLevel.h" 3590b17f1bSmrg#include <stdio.h> 3690b17f1bSmrg#include <sys/ioctl.h> 3790b17f1bSmrg#include <sys/time.h> 3890b17f1bSmrg#include <time.h> 3990b17f1bSmrg#include <fourcc.h> 4090b17f1bSmrg#include <X11/extensions/Xv.h> 4190b17f1bSmrg#include <xf86drm.h> 4290b17f1bSmrg#include <pthread.h> 4390b17f1bSmrg#include "vldXvMC.h" 4490b17f1bSmrg#include "xf86dri.h" 4590b17f1bSmrg#include "driDrawable.h" 4690b17f1bSmrg 4790b17f1bSmrg#define SAREAPTR(ctx) ((ViaXvMCSAreaPriv *) \ 4890b17f1bSmrg (((CARD8 *)(ctx)->sAreaAddress) + \ 4990b17f1bSmrg (ctx)->sAreaPrivOffset)) 5090b17f1bSmrg 5190b17f1bSmrgtypedef struct 5290b17f1bSmrg{ 5390b17f1bSmrg int major; 5490b17f1bSmrg int minor; 5590b17f1bSmrg int patchlevel; 5690b17f1bSmrg} ViaDRMVersion; 5790b17f1bSmrg 5890b17f1bSmrgstatic int error_base; 5990b17f1bSmrgstatic int event_base; 6090b17f1bSmrgstatic unsigned numContexts = 0; 6190b17f1bSmrgstatic int globalFD; 6290b17f1bSmrgstatic drmAddress sAreaAddress; 6390b17f1bSmrgstatic drmAddress fbAddress; 6490b17f1bSmrgstatic drmAddress mmioAddress; 6590b17f1bSmrgstatic const ViaDRMVersion drmExpected = { 2, 0, 0 }; 6690b17f1bSmrgstatic const ViaDRMVersion drmCompat = { 2, 0, 0 }; 6790b17f1bSmrg 6890b17f1bSmrg#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X') 6990b17f1bSmrg 7090b17f1bSmrg#define ppthread_mutex_lock(arg) \ 7190b17f1bSmrg { \ 7290b17f1bSmrg pthread_mutex_lock(arg); \ 7390b17f1bSmrg } \ 7490b17f1bSmrg 7590b17f1bSmrg#define ppthread_mutex_unlock(arg) \ 7690b17f1bSmrg { \ 7790b17f1bSmrg pthread_mutex_unlock(arg); \ 7890b17f1bSmrg } \ 7990b17f1bSmrg 8090b17f1bSmrgstatic unsigned 8190b17f1bSmrgyOffs(ViaXvMCSurface * srf) 8290b17f1bSmrg{ 8390b17f1bSmrg return srf->offsets[0]; 8490b17f1bSmrg} 8590b17f1bSmrg 8690b17f1bSmrgstatic unsigned 8790b17f1bSmrgvOffs(ViaXvMCSurface * srf) 8890b17f1bSmrg{ 8990b17f1bSmrg return srf->offsets[0] + srf->yStride * srf->height; 9090b17f1bSmrg} 9190b17f1bSmrg 9290b17f1bSmrgstatic unsigned 9390b17f1bSmrguOffs(ViaXvMCSurface * srf) 9490b17f1bSmrg{ 9590b17f1bSmrg return srf->offsets[0] + (srf->yStride * srf->height) + 9690b17f1bSmrg (srf->yStride >> 1) * (srf->height >> 1); 9790b17f1bSmrg} 9890b17f1bSmrg 9990b17f1bSmrgstatic void 10090b17f1bSmrgdefaultQMatrices(ViaXvMCContext * ctx) 10190b17f1bSmrg{ 10290b17f1bSmrg int i; 10390b17f1bSmrg 10490b17f1bSmrg static const char intra[64] = { 10590b17f1bSmrg 8, 16, 19, 22, 26, 27, 29, 34, 16, 16, 22, 24, 27, 29, 34, 37, 10690b17f1bSmrg 19, 22, 26, 27, 29, 34, 34, 38, 22, 22, 26, 27, 29, 34, 37, 40, 10790b17f1bSmrg 22, 26, 27, 29, 32, 35, 40, 48, 26, 27, 29, 32, 35, 40, 48, 58, 10890b17f1bSmrg 26, 27, 29, 34, 38, 46, 56, 69, 27, 29, 35, 38, 46, 56, 69, 83 10990b17f1bSmrg }; 11090b17f1bSmrg 11190b17f1bSmrg for (i = 0; i < 64; ++i) { 11290b17f1bSmrg ctx->intra_quantiser_matrix[i] = intra[i]; 11390b17f1bSmrg ctx->non_intra_quantiser_matrix[i] = 16; 11490b17f1bSmrg } 11590b17f1bSmrg ctx->intraLoaded = 0; 11690b17f1bSmrg ctx->nonIntraLoaded = 0; 11790b17f1bSmrg} 11890b17f1bSmrg 11990b17f1bSmrgstatic void 12090b17f1bSmrgreleaseDecoder(ViaXvMCContext * ctx, int clearCtx) 12190b17f1bSmrg{ 12290b17f1bSmrg volatile ViaXvMCSAreaPriv *sAPriv; 12390b17f1bSmrg 12490b17f1bSmrg sAPriv = SAREAPTR(ctx); 12590b17f1bSmrg UNICHROME_UNLOCK(ctx->fd, UNICHROME_LOCK_DECODER1, sAPriv, 12690b17f1bSmrg ctx->drmcontext); 12790b17f1bSmrg} 12890b17f1bSmrg 12990b17f1bSmrgstatic int 13090b17f1bSmrggrabDecoder(ViaXvMCContext * ctx, int *hadLastLock) 13190b17f1bSmrg{ 13290b17f1bSmrg volatile ViaXvMCSAreaPriv *sAPriv = SAREAPTR(ctx); 13390b17f1bSmrg int retFtx, lc; 13490b17f1bSmrg 13590b17f1bSmrg /* 13690b17f1bSmrg * Try to grab the decoder. If it is not available we will sleep until 13790b17f1bSmrg * it becomes available or for a maximum of 20 ms. 13890b17f1bSmrg * Then try to grab it again, unless a timeout occured. If the decoder is 13990b17f1bSmrg * available, the lock should be reasonably fast. 14090b17f1bSmrg */ 14190b17f1bSmrg 14290b17f1bSmrg if (ctx->haveDecoder) { 14390b17f1bSmrg flushXvMCLowLevel(ctx->xl); /* Ignore errors here. */ 14490b17f1bSmrg 14590b17f1bSmrg /*fprintf(stderr,"ViaXvMC: ERROR: Trying to re-lock decoder.\n"); */ 14690b17f1bSmrg *hadLastLock = 1; 14790b17f1bSmrg return 0; 14890b17f1bSmrg } 14990b17f1bSmrg UNICHROME_LOCK(ctx->fd, UNICHROME_LOCK_DECODER1, sAPriv, ctx->drmcontext, 15090b17f1bSmrg lc, retFtx); 15190b17f1bSmrg *hadLastLock = (ctx->drmcontext == lc); 15290b17f1bSmrg 15390b17f1bSmrg return retFtx; 15490b17f1bSmrg} 15590b17f1bSmrg 15690b17f1bSmrgstatic void 15790b17f1bSmrgsetupAttribDesc(Display * display, XvPortID port, 15890b17f1bSmrg const ViaXvMCAttrHolder * attrib, XvAttribute attribDesc[]) 15990b17f1bSmrg{ 16090b17f1bSmrg XvAttribute *XvAttribs, *curAD; 16190b17f1bSmrg int num; 16290b17f1bSmrg unsigned i, j; 16390b17f1bSmrg 16490b17f1bSmrg XLockDisplay(display); 16590b17f1bSmrg XvAttribs = XvQueryPortAttributes(display, port, &num); 16690b17f1bSmrg for (i = 0; i < attrib->numAttr; ++i) { 16790b17f1bSmrg curAD = attribDesc + i; 16890b17f1bSmrg curAD->flags = 0; 16990b17f1bSmrg curAD->min_value = 0; 17090b17f1bSmrg curAD->max_value = 0; 17190b17f1bSmrg curAD->name = NULL; 17290b17f1bSmrg for (j = 0; j < num; ++j) { 17390b17f1bSmrg if (attrib->attributes[i].attribute == 17490b17f1bSmrg XInternAtom(display, XvAttribs[j].name, TRUE)) { 17590b17f1bSmrg *curAD = XvAttribs[j]; 17690b17f1bSmrg curAD->name = strdup(XvAttribs[j].name); 17790b17f1bSmrg break; 17890b17f1bSmrg } 17990b17f1bSmrg } 18090b17f1bSmrg } 18190b17f1bSmrg if (XvAttribs) 18290b17f1bSmrg XFree(XvAttribs); 18390b17f1bSmrg XUnlockDisplay(display); 18490b17f1bSmrg 18590b17f1bSmrg} 18690b17f1bSmrg 18790b17f1bSmrgstatic void 18890b17f1bSmrgreleaseAttribDesc(int numAttr, XvAttribute attribDesc[]) 18990b17f1bSmrg{ 19090b17f1bSmrg int i; 19190b17f1bSmrg 19290b17f1bSmrg for (i = 0; i < numAttr; ++i) { 19390b17f1bSmrg if (attribDesc[i].name) 19490b17f1bSmrg free(attribDesc[i].name); 19590b17f1bSmrg } 19690b17f1bSmrg} 19790b17f1bSmrg 19890b17f1bSmrgstatic Status 19990b17f1bSmrgreleaseContextResources(Display * display, XvMCContext * context, 20090b17f1bSmrg int freePrivate, Status errType) 20190b17f1bSmrg{ 20290b17f1bSmrg ViaXvMCContext *pViaXvMC = (ViaXvMCContext *) context->privData; 20390b17f1bSmrg 20490b17f1bSmrg switch (pViaXvMC->resources) { 20590b17f1bSmrg case context_drawHash: 20690b17f1bSmrg driDestroyHashContents(pViaXvMC->drawHash); 20790b17f1bSmrg drmHashDestroy(pViaXvMC->drawHash); 20890b17f1bSmrg case context_lowLevel: 20990b17f1bSmrg closeXvMCLowLevel(pViaXvMC->xl); 21090b17f1bSmrg case context_mutex: 21190b17f1bSmrg pthread_mutex_destroy(&pViaXvMC->ctxMutex); 21290b17f1bSmrg case context_drmContext: 21390b17f1bSmrg XLockDisplay(display); 21490b17f1bSmrg uniDRIDestroyContext(display, pViaXvMC->screen, pViaXvMC->id); 21590b17f1bSmrg XUnlockDisplay(display); 21690b17f1bSmrg case context_sAreaMap: 21790b17f1bSmrg numContexts--; 21890b17f1bSmrg if (numContexts == 0) 21990b17f1bSmrg drmUnmap(pViaXvMC->sAreaAddress, pViaXvMC->sAreaSize); 22090b17f1bSmrg case context_fbMap: 22190b17f1bSmrg if (numContexts == 0) 22290b17f1bSmrg drmUnmap(pViaXvMC->fbAddress, pViaXvMC->fbSize); 22390b17f1bSmrg case context_mmioMap: 22490b17f1bSmrg if (numContexts == 0) 22590b17f1bSmrg drmUnmap(pViaXvMC->mmioAddress, pViaXvMC->mmioSize); 22690b17f1bSmrg case context_fd: 22790b17f1bSmrg if (numContexts == 0) { 22890b17f1bSmrg if (pViaXvMC->fd >= 0) 22990b17f1bSmrg drmClose(pViaXvMC->fd); 23090b17f1bSmrg } 23190b17f1bSmrg pViaXvMC->fd = -1; 23290b17f1bSmrg case context_driConnection: 23390b17f1bSmrg if (numContexts == 0) { 23490b17f1bSmrg XLockDisplay(display); 23590b17f1bSmrg uniDRICloseConnection(display, pViaXvMC->screen); 23690b17f1bSmrg XUnlockDisplay(display); 23790b17f1bSmrg } 23890b17f1bSmrg case context_context: 23990b17f1bSmrg XLockDisplay(display); 24090b17f1bSmrg _xvmc_destroy_context(display, context); 24190b17f1bSmrg XUnlockDisplay(display); 24290b17f1bSmrg if (!freePrivate) 24390b17f1bSmrg break; 24490b17f1bSmrg default: 24590b17f1bSmrg free(pViaXvMC); 24690b17f1bSmrg context->privData = NULL; 24790b17f1bSmrg } 24890b17f1bSmrg return errType; 24990b17f1bSmrg} 25090b17f1bSmrg 25190b17f1bSmrg_X_EXPORT Status 25290b17f1bSmrgXvMCCreateContext(Display * display, XvPortID port, 25390b17f1bSmrg int surface_type_id, int width, int height, int flags, 25490b17f1bSmrg XvMCContext * context) 25590b17f1bSmrg{ 25690b17f1bSmrg ViaXvMCContext *pViaXvMC; 25790b17f1bSmrg int priv_count; 25890b17f1bSmrg uint *priv_data; 25990b17f1bSmrg uint magic; 26090b17f1bSmrg unsigned i; 26190b17f1bSmrg Status ret; 26290b17f1bSmrg int major, minor; 26390b17f1bSmrg ViaXvMCCreateContextRec *tmpComm; 26490b17f1bSmrg drmVersionPtr drmVer; 26590b17f1bSmrg char *curBusID; 26690b17f1bSmrg int isCapable; 26790b17f1bSmrg 26890b17f1bSmrg /* 26990b17f1bSmrg * Verify Obvious things first 27090b17f1bSmrg */ 27190b17f1bSmrg 27290b17f1bSmrg if (context == NULL) { 27390b17f1bSmrg return XvMCBadContext; 27490b17f1bSmrg } 27590b17f1bSmrg 27690b17f1bSmrg if (!(flags & XVMC_DIRECT)) { 27790b17f1bSmrg fprintf(stderr, "Indirect Rendering not supported! Using Direct.\n"); 27890b17f1bSmrg } 27990b17f1bSmrg 28090b17f1bSmrg /* 28190b17f1bSmrg *FIXME: Check $DISPLAY for legal values here 28290b17f1bSmrg */ 28390b17f1bSmrg 28490b17f1bSmrg context->surface_type_id = surface_type_id; 28590b17f1bSmrg context->width = (unsigned short)((width + 15) & ~15); 28690b17f1bSmrg context->height = (unsigned short)((height + 15) & ~15); 28790b17f1bSmrg context->flags = flags; 28890b17f1bSmrg context->port = port; 28990b17f1bSmrg 29090b17f1bSmrg /* 29190b17f1bSmrg * Width, Height, and flags are checked against surface_type_id 29290b17f1bSmrg * and port for validity inside the X server, no need to check 29390b17f1bSmrg * here. 29490b17f1bSmrg */ 29590b17f1bSmrg 29690b17f1bSmrg /* Allocate private Context data */ 29790b17f1bSmrg context->privData = (void *)malloc(sizeof(ViaXvMCContext)); 29890b17f1bSmrg if (!context->privData) { 29990b17f1bSmrg fprintf(stderr, "Unable to allocate resources for XvMC context.\n"); 30090b17f1bSmrg return BadAlloc; 30190b17f1bSmrg } 30290b17f1bSmrg 30390b17f1bSmrg pViaXvMC = (ViaXvMCContext *) context->privData; 30490b17f1bSmrg pViaXvMC->resources = context_none; 30590b17f1bSmrg 30690b17f1bSmrg /* Verify the XvMC extension exists */ 30790b17f1bSmrg 30890b17f1bSmrg XLockDisplay(display); 30990b17f1bSmrg if (!XvMCQueryExtension(display, &event_base, &error_base)) { 31090b17f1bSmrg fprintf(stderr, "XvMC Extension is not available!\n"); 31190b17f1bSmrg free(pViaXvMC); 31290b17f1bSmrg XUnlockDisplay(display); 31390b17f1bSmrg return BadAlloc; 31490b17f1bSmrg } 31590b17f1bSmrg 31690b17f1bSmrg /* Verify XvMC version */ 31790b17f1bSmrg ret = XvMCQueryVersion(display, &major, &minor); 31890b17f1bSmrg if (ret) { 31990b17f1bSmrg fprintf(stderr, "XvMCQuery Version Failed, unable to determine " 32090b17f1bSmrg "protocol version!\n"); 32190b17f1bSmrg } 32290b17f1bSmrg XUnlockDisplay(display); 32390b17f1bSmrg 32490b17f1bSmrg /* FIXME: Check Major and Minor here */ 32590b17f1bSmrg 32690b17f1bSmrg XLockDisplay(display); 32790b17f1bSmrg if ((ret = _xvmc_create_context(display, context, &priv_count, 32890b17f1bSmrg &priv_data))) { 32990b17f1bSmrg XUnlockDisplay(display); 33090b17f1bSmrg fprintf(stderr, "Unable to create XvMC Context!\n"); 33190b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 33290b17f1bSmrg } 33390b17f1bSmrg XUnlockDisplay(display); 33490b17f1bSmrg 33590b17f1bSmrg /* 33690b17f1bSmrg * Check size and version of returned data. 33790b17f1bSmrg */ 33890b17f1bSmrg 33990b17f1bSmrg tmpComm = (ViaXvMCCreateContextRec *) priv_data; 34090b17f1bSmrg if (priv_count != (sizeof(ViaXvMCCreateContextRec) >> 2)) { 34190b17f1bSmrg fprintf(stderr, "_xvmc_create_context() returned incorrect " 34290b17f1bSmrg "data size!\n"); 34390b17f1bSmrg fprintf(stderr, "\tExpected %d, got %d\n", 34490b17f1bSmrg ((int)(sizeof(ViaXvMCCreateContextRec) >> 2)), priv_count); 34590b17f1bSmrg XFree(priv_data); 34690b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 34790b17f1bSmrg } 34890b17f1bSmrg pViaXvMC->resources = context_context; 34990b17f1bSmrg 35090b17f1bSmrg if ((tmpComm->major != VIAXVMC_MAJOR) || 35190b17f1bSmrg (tmpComm->minor != VIAXVMC_MINOR)) { 35290b17f1bSmrg fprintf(stderr, "Version mismatch between the X via driver\n" 35390b17f1bSmrg "and the XvMC library. Cannot continue!\n"); 35490b17f1bSmrg XFree(priv_data); 35590b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 35690b17f1bSmrg } 35790b17f1bSmrg 35890b17f1bSmrg pViaXvMC->ctxNo = tmpComm->ctxNo; 35990b17f1bSmrg pViaXvMC->fbOffset = tmpComm->fbOffset; 36090b17f1bSmrg pViaXvMC->fbSize = tmpComm->fbSize; 36190b17f1bSmrg pViaXvMC->mmioOffset = tmpComm->mmioOffset; 36290b17f1bSmrg pViaXvMC->mmioSize = tmpComm->mmioSize; 36390b17f1bSmrg pViaXvMC->sAreaSize = tmpComm->sAreaSize; 36490b17f1bSmrg pViaXvMC->sAreaPrivOffset = tmpComm->sAreaPrivOffset; 36590b17f1bSmrg pViaXvMC->decoderOn = 0; 36690b17f1bSmrg pViaXvMC->xvMCPort = tmpComm->xvmc_port; 36790b17f1bSmrg pViaXvMC->useAGP = tmpComm->useAGP; 36890b17f1bSmrg pViaXvMC->attrib = tmpComm->initAttrs; 36990b17f1bSmrg pViaXvMC->screen = tmpComm->screen; 37090b17f1bSmrg pViaXvMC->depth = tmpComm->depth; 37190b17f1bSmrg pViaXvMC->stride = tmpComm->stride; 37290b17f1bSmrg pViaXvMC->chipId = tmpComm->chipId; 37390b17f1bSmrg 37490b17f1bSmrg /* 37590b17f1bSmrg * Must free the private data we were passed from X 37690b17f1bSmrg */ 37790b17f1bSmrg 37890b17f1bSmrg XFree(priv_data); 37990b17f1bSmrg priv_data = NULL; 38090b17f1bSmrg 38190b17f1bSmrg /* 38290b17f1bSmrg * Check for direct rendering capable, establish DRI and DRM connections, 38390b17f1bSmrg * map framebuffer, DRI shared area and read-only register areas. 38490b17f1bSmrg * Initial checking for drm has already been done by the server. 38590b17f1bSmrg * Only do this for the first context we create. 38690b17f1bSmrg */ 38790b17f1bSmrg 38890b17f1bSmrg if (numContexts == 0) { 38990b17f1bSmrg XLockDisplay(display); 39090b17f1bSmrg ret = 39190b17f1bSmrg uniDRIQueryDirectRenderingCapable(display, pViaXvMC->screen, 39290b17f1bSmrg &isCapable); 39390b17f1bSmrg if (!ret || !isCapable) { 39490b17f1bSmrg XUnlockDisplay(display); 39590b17f1bSmrg fprintf(stderr, 39690b17f1bSmrg "Direct Rendering is not available on this system!\n"); 39790b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 39890b17f1bSmrg } 39990b17f1bSmrg 40090b17f1bSmrg if (!uniDRIOpenConnection(display, pViaXvMC->screen, 40190b17f1bSmrg &pViaXvMC->sAreaOffset, &curBusID)) { 40290b17f1bSmrg XUnlockDisplay(display); 40390b17f1bSmrg fprintf(stderr, "Could not open DRI connection to X server!\n"); 40490b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 40590b17f1bSmrg } 40690b17f1bSmrg XUnlockDisplay(display); 40790b17f1bSmrg 40890b17f1bSmrg strncpy(pViaXvMC->busIdString, curBusID, 20); 40990b17f1bSmrg pViaXvMC->busIdString[20] = '\0'; 41090b17f1bSmrg XFree(curBusID); 41190b17f1bSmrg 41290b17f1bSmrg pViaXvMC->resources = context_driConnection; 41390b17f1bSmrg 41490b17f1bSmrg if ((pViaXvMC->fd = drmOpen("via", pViaXvMC->busIdString)) < 0) { 41590b17f1bSmrg fprintf(stderr, "DRM Device for via could not be opened.\n"); 41690b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 41790b17f1bSmrg } 41890b17f1bSmrg globalFD = pViaXvMC->fd; 41990b17f1bSmrg pViaXvMC->resources = context_fd; 42090b17f1bSmrg 42190b17f1bSmrg if (NULL == (drmVer = drmGetVersion(pViaXvMC->fd))) { 42290b17f1bSmrg fprintf(stderr, "viaXvMC: Could not get drm version."); 42390b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 42490b17f1bSmrg } 42590b17f1bSmrg if ((drmVer->version_major < drmExpected.major) || 42690b17f1bSmrg (drmVer->version_major > drmCompat.major) || 42790b17f1bSmrg ((drmVer->version_major == drmExpected.major) && 42890b17f1bSmrg (drmVer->version_minor < drmExpected.minor))) { 42990b17f1bSmrg fprintf(stderr, 43090b17f1bSmrg "viaXvMC: Kernel drm is not compatible with XvMC.\n"); 43190b17f1bSmrg fprintf(stderr, 43290b17f1bSmrg "viaXvMC: Kernel drm version: %d.%d.%d " 43390b17f1bSmrg "and I can work with versions %d.%d.x - %d.x.x\n" 43490b17f1bSmrg "Please update either this XvMC driver or your kernel DRM.\n", 43590b17f1bSmrg drmVer->version_major, drmVer->version_minor, 43690b17f1bSmrg drmVer->version_patchlevel, drmExpected.major, 43790b17f1bSmrg drmExpected.minor, drmCompat.major); 43890b17f1bSmrg drmFreeVersion(drmVer); 43990b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 44090b17f1bSmrg } 44190b17f1bSmrg drmFreeVersion(drmVer); 44290b17f1bSmrg drmGetMagic(pViaXvMC->fd, &magic); 44390b17f1bSmrg 44490b17f1bSmrg XLockDisplay(display); 44590b17f1bSmrg if (!uniDRIAuthConnection(display, pViaXvMC->screen, magic)) { 44690b17f1bSmrg XUnlockDisplay(display); 44790b17f1bSmrg fprintf(stderr, 44890b17f1bSmrg "viaXvMC: X server did not allow DRI. Check permissions.\n"); 44990b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 45090b17f1bSmrg } 45190b17f1bSmrg XUnlockDisplay(display); 45290b17f1bSmrg 45390b17f1bSmrg /* 45490b17f1bSmrg * Map the register memory 45590b17f1bSmrg */ 45690b17f1bSmrg 45790b17f1bSmrg if (drmMap(pViaXvMC->fd, pViaXvMC->mmioOffset, 45890b17f1bSmrg pViaXvMC->mmioSize, &mmioAddress) < 0) { 45990b17f1bSmrg fprintf(stderr, 46090b17f1bSmrg "Unable to map the display chip mmio registers.\n"); 46190b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 46290b17f1bSmrg } 46390b17f1bSmrg pViaXvMC->mmioAddress = mmioAddress; 46490b17f1bSmrg pViaXvMC->resources = context_mmioMap; 46590b17f1bSmrg 46690b17f1bSmrg /* 46790b17f1bSmrg * Map Framebuffer memory 46890b17f1bSmrg */ 46990b17f1bSmrg 47090b17f1bSmrg if (drmMap(pViaXvMC->fd, pViaXvMC->fbOffset, 47190b17f1bSmrg pViaXvMC->fbSize, &fbAddress) < 0) { 47290b17f1bSmrg fprintf(stderr, "Unable to map XvMC Framebuffer.\n"); 47390b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 47490b17f1bSmrg } 47590b17f1bSmrg pViaXvMC->fbAddress = fbAddress; 47690b17f1bSmrg pViaXvMC->resources = context_fbMap; 47790b17f1bSmrg 47890b17f1bSmrg /* 47990b17f1bSmrg * Map DRI Sarea. 48090b17f1bSmrg */ 48190b17f1bSmrg 48290b17f1bSmrg if (drmMap(pViaXvMC->fd, pViaXvMC->sAreaOffset, 48390b17f1bSmrg pViaXvMC->sAreaSize, &sAreaAddress) < 0) { 48490b17f1bSmrg fprintf(stderr, "Unable to map DRI SAREA.\n"); 48590b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 48690b17f1bSmrg } 48790b17f1bSmrg } else { 48890b17f1bSmrg pViaXvMC->fd = globalFD; 48990b17f1bSmrg pViaXvMC->mmioAddress = mmioAddress; 49090b17f1bSmrg pViaXvMC->fbAddress = fbAddress; 49190b17f1bSmrg } 49290b17f1bSmrg 49390b17f1bSmrg pViaXvMC->sAreaAddress = sAreaAddress; 49490b17f1bSmrg pViaXvMC->resources = context_sAreaMap; 49590b17f1bSmrg numContexts++; 49690b17f1bSmrg 49790b17f1bSmrg /* 49890b17f1bSmrg * Find a matching visual. Important only for direct drawing to the visible 49990b17f1bSmrg * frame-buffer. 50090b17f1bSmrg */ 50190b17f1bSmrg 50290b17f1bSmrg XLockDisplay(display); 50390b17f1bSmrg ret = XMatchVisualInfo(display, pViaXvMC->screen, 50490b17f1bSmrg (pViaXvMC->depth == 32) ? 24 : pViaXvMC->depth, TrueColor, 50590b17f1bSmrg &pViaXvMC->visualInfo); 50690b17f1bSmrg XUnlockDisplay(display); 50790b17f1bSmrg if (!ret) { 50890b17f1bSmrg fprintf(stderr, 50990b17f1bSmrg "viaXvMC: Could not find a matching TrueColor visual.\n"); 51090b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 51190b17f1bSmrg } 51290b17f1bSmrg 51390b17f1bSmrg if (!uniDRICreateContext(display, pViaXvMC->screen, 51490b17f1bSmrg pViaXvMC->visualInfo.visual, &pViaXvMC->id, 51590b17f1bSmrg &pViaXvMC->drmcontext)) { 51690b17f1bSmrg 51790b17f1bSmrg fprintf(stderr, "viaXvMC: Could not create DRI context.\n"); 51890b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 51990b17f1bSmrg } 52090b17f1bSmrg 52190b17f1bSmrg pViaXvMC->resources = context_drmContext; 52290b17f1bSmrg 52390b17f1bSmrg for (i = 0; i < VIA_MAX_RENDSURF; ++i) { 52490b17f1bSmrg pViaXvMC->rendSurf[i] = 0; 52590b17f1bSmrg } 52690b17f1bSmrg pViaXvMC->lastSrfDisplaying = ~0; 52790b17f1bSmrg setupAttribDesc(display, port, &pViaXvMC->attrib, pViaXvMC->attribDesc); 52890b17f1bSmrg 52990b17f1bSmrg pViaXvMC->hwLock = (drmLockPtr) pViaXvMC->sAreaAddress; 53090b17f1bSmrg defaultQMatrices(pViaXvMC); 53190b17f1bSmrg pViaXvMC->chromaIntraLoaded = 1; 53290b17f1bSmrg pViaXvMC->chromaNonIntraLoaded = 1; 53390b17f1bSmrg pViaXvMC->yStride = (width + 31) & ~31; 53490b17f1bSmrg pViaXvMC->haveDecoder = 0; 53590b17f1bSmrg pViaXvMC->attribChanged = 1; 53690b17f1bSmrg pViaXvMC->haveXv = 0; 53790b17f1bSmrg pViaXvMC->port = context->port; 53890b17f1bSmrg pthread_mutex_init(&pViaXvMC->ctxMutex, NULL); 53990b17f1bSmrg pViaXvMC->resources = context_mutex; 54090b17f1bSmrg pViaXvMC->timeStamp = 0; 54190b17f1bSmrg setRegion(0, 0, -1, -1, pViaXvMC->sRegion); 54290b17f1bSmrg setRegion(0, 0, -1, -1, pViaXvMC->dRegion); 54390b17f1bSmrg 54490b17f1bSmrg if (NULL == (pViaXvMC->xl = 54590b17f1bSmrg initXvMCLowLevel(pViaXvMC->fd, &pViaXvMC->drmcontext, 54690b17f1bSmrg pViaXvMC->hwLock, pViaXvMC->mmioAddress, 54790b17f1bSmrg pViaXvMC->fbAddress, pViaXvMC->stride, pViaXvMC->depth, 54890b17f1bSmrg context->width, context->height, 54990b17f1bSmrg pViaXvMC->useAGP, pViaXvMC->chipId))) { 55090b17f1bSmrg 55190b17f1bSmrg fprintf(stderr, "ViaXvMC: Could not allocate timestamp blit area.\n"); 55290b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 55390b17f1bSmrg } 55490b17f1bSmrg pViaXvMC->resources = context_lowLevel; 55590b17f1bSmrg setAGPSyncLowLevel(pViaXvMC->xl, 1, 0); 55690b17f1bSmrg 55790b17f1bSmrg if (NULL == (pViaXvMC->drawHash = drmHashCreate())) { 55890b17f1bSmrg fprintf(stderr, "ViaXvMC: Could not allocate drawable hash table.\n"); 55990b17f1bSmrg return releaseContextResources(display, context, 1, BadAlloc); 56090b17f1bSmrg } 56190b17f1bSmrg pViaXvMC->resources = context_drawHash; 56290b17f1bSmrg 56390b17f1bSmrg if (numContexts == 1) { 56490b17f1bSmrg hwlLock(pViaXvMC->xl, 1); 56590b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 0); 56690b17f1bSmrg viaVideoSubPictureOffLocked(pViaXvMC->xl); 56790b17f1bSmrg flushXvMCLowLevel(pViaXvMC->xl); 56890b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 1); 56990b17f1bSmrg hwlUnlock(pViaXvMC->xl, 1); 57090b17f1bSmrg } 57190b17f1bSmrg 57290b17f1bSmrg return Success; 57390b17f1bSmrg} 57490b17f1bSmrg 57590b17f1bSmrg_X_EXPORT Status 57690b17f1bSmrgXvMCDestroyContext(Display * display, XvMCContext * context) 57790b17f1bSmrg{ 57890b17f1bSmrg ViaXvMCContext *pViaXvMC; 57990b17f1bSmrg 58090b17f1bSmrg if (context == NULL) { 58190b17f1bSmrg return (error_base + XvMCBadContext); 58290b17f1bSmrg } 58390b17f1bSmrg if (NULL == (pViaXvMC = context->privData)) { 58490b17f1bSmrg return (error_base + XvMCBadContext); 58590b17f1bSmrg } 58690b17f1bSmrg 58790b17f1bSmrg /* 58890b17f1bSmrg * Release decoder if we have it. In case of crash or termination 58990b17f1bSmrg * before XvMCDestroyContext, the X server will take care of this. 59090b17f1bSmrg */ 59190b17f1bSmrg 59290b17f1bSmrg releaseAttribDesc(pViaXvMC->attrib.numAttr, pViaXvMC->attribDesc); 59390b17f1bSmrg releaseDecoder(pViaXvMC, 1); 59490b17f1bSmrg return releaseContextResources(display, context, 1, Success); 59590b17f1bSmrg} 59690b17f1bSmrg 59790b17f1bSmrg_X_EXPORT Status 59890b17f1bSmrgXvMCCreateSurface(Display * display, XvMCContext * context, 59990b17f1bSmrg XvMCSurface * surface) 60090b17f1bSmrg{ 60190b17f1bSmrg ViaXvMCContext *pViaXvMC; 60290b17f1bSmrg ViaXvMCSurface *pViaSurface; 60390b17f1bSmrg int priv_count; 60490b17f1bSmrg unsigned *priv_data; 60590b17f1bSmrg unsigned i; 60690b17f1bSmrg Status ret; 60790b17f1bSmrg 60890b17f1bSmrg if ((surface == NULL) || (context == NULL) || (display == NULL)) { 60990b17f1bSmrg return BadValue; 61090b17f1bSmrg } 61190b17f1bSmrg 61290b17f1bSmrg pViaXvMC = (ViaXvMCContext *) context->privData; 61390b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 61490b17f1bSmrg 61590b17f1bSmrg if (pViaXvMC == NULL) { 61690b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 61790b17f1bSmrg return (error_base + XvMCBadContext); 61890b17f1bSmrg } 61990b17f1bSmrg 62090b17f1bSmrg pViaSurface = surface->privData = 62190b17f1bSmrg (ViaXvMCSurface *) malloc(sizeof(ViaXvMCSurface)); 62290b17f1bSmrg if (!surface->privData) { 62390b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 62490b17f1bSmrg return BadAlloc; 62590b17f1bSmrg } 62690b17f1bSmrg XLockDisplay(display); 62790b17f1bSmrg if ((ret = _xvmc_create_surface(display, context, surface, 62890b17f1bSmrg &priv_count, &priv_data))) { 62990b17f1bSmrg XUnlockDisplay(display); 63090b17f1bSmrg free(pViaSurface); 63190b17f1bSmrg fprintf(stderr, "Unable to create XvMC Surface.\n"); 63290b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 63390b17f1bSmrg return ret; 63490b17f1bSmrg } 63590b17f1bSmrg XUnlockDisplay(display); 63690b17f1bSmrg 63790b17f1bSmrg pViaSurface->srfNo = priv_data[0]; 63890b17f1bSmrg 63990b17f1bSmrg /* 64090b17f1bSmrg * Store framebuffer offsets to the buffers allocated for this surface. 64190b17f1bSmrg * For some chipset revisions, surfaces may be double-buffered. 64290b17f1bSmrg */ 64390b17f1bSmrg 64490b17f1bSmrg pViaSurface->numBuffers = priv_data[1]; 64590b17f1bSmrg for (i = 0; i < pViaSurface->numBuffers; ++i) { 64690b17f1bSmrg pViaSurface->offsets[i] = priv_data[i + 2]; 64790b17f1bSmrg } 64890b17f1bSmrg pViaSurface->curBuf = 0; 64990b17f1bSmrg 65090b17f1bSmrg /* Free data returned from xvmc_create_surface */ 65190b17f1bSmrg 65290b17f1bSmrg XFree(priv_data); 65390b17f1bSmrg 65490b17f1bSmrg pViaSurface->width = context->width; 65590b17f1bSmrg pViaSurface->height = context->height; 65690b17f1bSmrg pViaSurface->yStride = pViaXvMC->yStride; 65790b17f1bSmrg pViaSurface->privContext = pViaXvMC; 65890b17f1bSmrg pViaSurface->privSubPic = NULL; 65990b17f1bSmrg pViaSurface->needsSync = 0; 66090b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 66190b17f1bSmrg return Success; 66290b17f1bSmrg} 66390b17f1bSmrg 66490b17f1bSmrg_X_EXPORT Status 66590b17f1bSmrgXvMCDestroySurface(Display * display, XvMCSurface * surface) 66690b17f1bSmrg{ 66790b17f1bSmrg ViaXvMCSurface *pViaSurface; 66890b17f1bSmrg 66990b17f1bSmrg if ((display == NULL) || (surface == NULL)) { 67090b17f1bSmrg return BadValue; 67190b17f1bSmrg } 67290b17f1bSmrg if (surface->privData == NULL) { 67390b17f1bSmrg return (error_base + XvMCBadSurface); 67490b17f1bSmrg } 67590b17f1bSmrg 67690b17f1bSmrg pViaSurface = (ViaXvMCSurface *) surface->privData; 67790b17f1bSmrg 67890b17f1bSmrg XLockDisplay(display); 67990b17f1bSmrg _xvmc_destroy_surface(display, surface); 68090b17f1bSmrg XUnlockDisplay(display); 68190b17f1bSmrg 68290b17f1bSmrg free(pViaSurface); 68390b17f1bSmrg surface->privData = NULL; 68490b17f1bSmrg return Success; 68590b17f1bSmrg} 68690b17f1bSmrg 68790b17f1bSmrg_X_EXPORT Status 68890b17f1bSmrgXvMCPutSlice2(Display * display, XvMCContext * context, char *slice, 68990b17f1bSmrg int nBytes, int sliceCode) 69090b17f1bSmrg{ 69190b17f1bSmrg ViaXvMCContext *pViaXvMC; 69290b17f1bSmrg CARD32 sCode = 0x00010000 | (sliceCode & 0xFF) << 24; 69390b17f1bSmrg 69490b17f1bSmrg if ((display == NULL) || (context == NULL)) { 69590b17f1bSmrg return BadValue; 69690b17f1bSmrg } 69790b17f1bSmrg if (NULL == (pViaXvMC = context->privData)) { 69890b17f1bSmrg return (error_base + XvMCBadContext); 69990b17f1bSmrg } 70090b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 70190b17f1bSmrg if (!pViaXvMC->haveDecoder) { 70290b17f1bSmrg fprintf(stderr, "XvMCPutSlice: This context does not own decoder!\n"); 70390b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 70490b17f1bSmrg return BadAlloc; 70590b17f1bSmrg } 70690b17f1bSmrg 70790b17f1bSmrg viaMpegWriteSlice(pViaXvMC->xl, (CARD8 *) slice, nBytes, sCode); 70890b17f1bSmrg 70990b17f1bSmrg flushPCIXvMCLowLevel(pViaXvMC->xl); 71090b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 71190b17f1bSmrg return Success; 71290b17f1bSmrg} 71390b17f1bSmrg 71490b17f1bSmrg_X_EXPORT Status 71590b17f1bSmrgXvMCPutSlice(Display * display, XvMCContext * context, char *slice, 71690b17f1bSmrg int nBytes) 71790b17f1bSmrg{ 71890b17f1bSmrg ViaXvMCContext *pViaXvMC; 71990b17f1bSmrg 72090b17f1bSmrg if ((display == NULL) || (context == NULL)) { 72190b17f1bSmrg return BadValue; 72290b17f1bSmrg } 72390b17f1bSmrg if (NULL == (pViaXvMC = context->privData)) { 72490b17f1bSmrg return (error_base + XvMCBadContext); 72590b17f1bSmrg } 72690b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 72790b17f1bSmrg 72890b17f1bSmrg if (!pViaXvMC->haveDecoder) { 72990b17f1bSmrg fprintf(stderr, "XvMCPutSlice: This context does not own decoder!\n"); 73090b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 73190b17f1bSmrg return BadAlloc; 73290b17f1bSmrg } 73390b17f1bSmrg 73490b17f1bSmrg viaMpegWriteSlice(pViaXvMC->xl, (CARD8 *) slice, nBytes, 0); 73590b17f1bSmrg flushPCIXvMCLowLevel(pViaXvMC->xl); 73690b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 73790b17f1bSmrg return Success; 73890b17f1bSmrg} 73990b17f1bSmrg 74090b17f1bSmrgstatic Status 74190b17f1bSmrgupdateXVOverlay(Display * display, ViaXvMCContext * pViaXvMC, 74290b17f1bSmrg ViaXvMCSurface * pViaSurface, Drawable draw, 74390b17f1bSmrg short srcx, short srcy, unsigned short srcw, 74490b17f1bSmrg unsigned short srch, short destx, short desty, 74590b17f1bSmrg unsigned short destw, unsigned short desth) 74690b17f1bSmrg{ 74790b17f1bSmrg ViaXvMCCommandBuffer buf; 74890b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 74990b17f1bSmrg Status ret; 75090b17f1bSmrg 75190b17f1bSmrg if (!pViaXvMC->haveXv) { 75290b17f1bSmrg pViaXvMC->xvImage = 75390b17f1bSmrg XvCreateImage(display, pViaXvMC->port, FOURCC_XVMC, 75490b17f1bSmrg (char *)&buf, pViaSurface->width, pViaSurface->height); 75590b17f1bSmrg pViaXvMC->gc = XCreateGC(display, draw, 0, 0); 75690b17f1bSmrg pViaXvMC->haveXv = 1; 75790b17f1bSmrg } 75890b17f1bSmrg pViaXvMC->draw = draw; 75990b17f1bSmrg pViaXvMC->xvImage->data = (char *)&buf; 76090b17f1bSmrg 76190b17f1bSmrg buf.command = (pViaXvMC->attribChanged) ? 76290b17f1bSmrg VIA_XVMC_COMMAND_FDISPLAY : VIA_XVMC_COMMAND_DISPLAY; 76390b17f1bSmrg buf.ctxNo = pViaXvMC->ctxNo | VIA_XVMC_VALID; 76490b17f1bSmrg buf.srfNo = pViaSurface->srfNo | VIA_XVMC_VALID; 76590b17f1bSmrg pViaSubPic = pViaSurface->privSubPic; 76690b17f1bSmrg buf.subPicNo = ((NULL == pViaSubPic) ? 0 : pViaSubPic->srfNo) 76790b17f1bSmrg | VIA_XVMC_VALID; 76890b17f1bSmrg buf.attrib = pViaXvMC->attrib; 76990b17f1bSmrg 77090b17f1bSmrg XLockDisplay(display); 77190b17f1bSmrg 77290b17f1bSmrg if ((ret = XvPutImage(display, pViaXvMC->port, draw, pViaXvMC->gc, 77390b17f1bSmrg pViaXvMC->xvImage, srcx, srcy, srcw, srch, 77490b17f1bSmrg destx, desty, destw, desth))) { 77590b17f1bSmrg XUnlockDisplay(display); 77690b17f1bSmrg return ret; 77790b17f1bSmrg } 77890b17f1bSmrg XSync(display, 0); 77990b17f1bSmrg XUnlockDisplay(display); 78090b17f1bSmrg pViaXvMC->attribChanged = 0; 78190b17f1bSmrg return Success; 78290b17f1bSmrg} 78390b17f1bSmrg 78490b17f1bSmrg_X_EXPORT Status 78590b17f1bSmrgXvMCPutSurface(Display * display, XvMCSurface * surface, Drawable draw, 78690b17f1bSmrg short srcx, short srcy, unsigned short srcw, 78790b17f1bSmrg unsigned short srch, short destx, short desty, 78890b17f1bSmrg unsigned short destw, unsigned short desth, int flags) 78990b17f1bSmrg{ 79090b17f1bSmrg /* 79190b17f1bSmrg * This function contains some hairy locking logic. What we really want to 79290b17f1bSmrg * do is to flip the picture ASAP, to get a low latency and smooth playback. 79390b17f1bSmrg * However, if somebody else used the overlay since we used it last or if it is 79490b17f1bSmrg * our first time, we'll have to call X to update the overlay first. Otherwise 79590b17f1bSmrg * we'll do the overlay update once we've flipped. Since we release the hardware 79690b17f1bSmrg * lock when we call X, X needs to verify using the SAREA that nobody else flipped 79790b17f1bSmrg * in a picture between the lock release and the X server control. Similarly 79890b17f1bSmrg * when the overlay update returns, we have to make sure that we still own the 79990b17f1bSmrg * overlay. 80090b17f1bSmrg */ 80190b17f1bSmrg 80290b17f1bSmrg ViaXvMCSurface *pViaSurface; 80390b17f1bSmrg ViaXvMCContext *pViaXvMC; 80490b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 80590b17f1bSmrg volatile ViaXvMCSAreaPriv *sAPriv; 80690b17f1bSmrg Status ret; 80790b17f1bSmrg unsigned dispSurface, lastSurface; 80890b17f1bSmrg int overlayUpdated; 80990b17f1bSmrg drawableInfo *drawInfo; 81090b17f1bSmrg XvMCRegion sReg, dReg; 81190b17f1bSmrg Bool forceUpdate = FALSE; 81290b17f1bSmrg 81390b17f1bSmrg if ((display == NULL) || (surface == NULL)) { 81490b17f1bSmrg return BadValue; 81590b17f1bSmrg } 81690b17f1bSmrg if (NULL == (pViaSurface = surface->privData)) { 81790b17f1bSmrg return (error_base + XvMCBadSurface); 81890b17f1bSmrg } 81990b17f1bSmrg if (NULL == (pViaXvMC = pViaSurface->privContext)) { 82090b17f1bSmrg return (error_base + XvMCBadContext); 82190b17f1bSmrg } 82290b17f1bSmrg 82390b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 82490b17f1bSmrg pViaSubPic = pViaSurface->privSubPic; 82590b17f1bSmrg sAPriv = SAREAPTR(pViaXvMC); 82690b17f1bSmrg 82790b17f1bSmrg setRegion(srcx, srcy, srcw, srch, sReg); 82890b17f1bSmrg setRegion(destx, desty, destw, desth, dReg); 82990b17f1bSmrg 83090b17f1bSmrg if ((!regionEqual(sReg, pViaXvMC->sRegion)) || 83190b17f1bSmrg (!regionEqual(dReg, pViaXvMC->dRegion))) { 83290b17f1bSmrg 83390b17f1bSmrg /* 83490b17f1bSmrg * Force update of the video overlay to match the new format. 83590b17f1bSmrg */ 83690b17f1bSmrg 83790b17f1bSmrg pViaXvMC->sRegion = sReg; 83890b17f1bSmrg pViaXvMC->dRegion = dReg; 83990b17f1bSmrg forceUpdate = TRUE; 84090b17f1bSmrg } 84190b17f1bSmrg 84290b17f1bSmrg hwlLock(pViaXvMC->xl, 1); 84390b17f1bSmrg 84490b17f1bSmrg if (getDRIDrawableInfoLocked(pViaXvMC->drawHash, display, 84590b17f1bSmrg pViaXvMC->screen, draw, 0, pViaXvMC->fd, pViaXvMC->drmcontext, 84690b17f1bSmrg pViaXvMC->sAreaAddress, FALSE, &drawInfo, sizeof(*drawInfo))) { 84790b17f1bSmrg 84890b17f1bSmrg hwlUnlock(pViaXvMC->xl, 1); 84990b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 85090b17f1bSmrg return BadAccess; 85190b17f1bSmrg } 85290b17f1bSmrg 85390b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 0); 85490b17f1bSmrg 85590b17f1bSmrg /* 85690b17f1bSmrg * Put a surface ID in the SAREA to "authenticate" to the 85790b17f1bSmrg * X server. 85890b17f1bSmrg */ 85990b17f1bSmrg 86090b17f1bSmrg dispSurface = sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort]; 86190b17f1bSmrg lastSurface = pViaXvMC->lastSrfDisplaying; 86290b17f1bSmrg sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort] = 86390b17f1bSmrg pViaXvMC->lastSrfDisplaying = pViaSurface->srfNo | VIA_XVMC_VALID; 86490b17f1bSmrg overlayUpdated = 0; 86590b17f1bSmrg 86690b17f1bSmrg viaVideoSetSWFLipLocked(pViaXvMC->xl, yOffs(pViaSurface), 86790b17f1bSmrg uOffs(pViaSurface), vOffs(pViaSurface), pViaSurface->yStride, 86890b17f1bSmrg pViaSurface->yStride >> 1); 86990b17f1bSmrg 87090b17f1bSmrg while ((lastSurface != dispSurface) || forceUpdate) { 87190b17f1bSmrg 87290b17f1bSmrg forceUpdate = FALSE; 87390b17f1bSmrg flushPCIXvMCLowLevel(pViaXvMC->xl); 87490b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 1); 87590b17f1bSmrg hwlUnlock(pViaXvMC->xl, 1); 87690b17f1bSmrg 87790b17f1bSmrg /* 87890b17f1bSmrg * We weren't the last to display. Update the overlay before flipping. 87990b17f1bSmrg */ 88090b17f1bSmrg 88190b17f1bSmrg ret = 88290b17f1bSmrg updateXVOverlay(display, pViaXvMC, pViaSurface, draw, srcx, srcy, 88390b17f1bSmrg srcw, srch, destx, desty, destw, desth); 88490b17f1bSmrg if (ret) { 88590b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 88690b17f1bSmrg return ret; 88790b17f1bSmrg } 88890b17f1bSmrg 88990b17f1bSmrg hwlLock(pViaXvMC->xl, 1); 89090b17f1bSmrg 89190b17f1bSmrg if (getDRIDrawableInfoLocked(pViaXvMC->drawHash, display, 89290b17f1bSmrg pViaXvMC->screen, draw, 0, pViaXvMC->fd, pViaXvMC->drmcontext, 89390b17f1bSmrg pViaXvMC->sAreaAddress, FALSE, &drawInfo, 89490b17f1bSmrg sizeof(*drawInfo))) { 89590b17f1bSmrg 89690b17f1bSmrg hwlUnlock(pViaXvMC->xl, 1); 89790b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 89890b17f1bSmrg return BadAccess; 89990b17f1bSmrg } 90090b17f1bSmrg 90190b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 0); 90290b17f1bSmrg lastSurface = pViaSurface->srfNo | VIA_XVMC_VALID; 90390b17f1bSmrg dispSurface = sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort]; 90490b17f1bSmrg overlayUpdated = 1; 90590b17f1bSmrg } 90690b17f1bSmrg 90790b17f1bSmrg /* 90890b17f1bSmrg * Subpictures 90990b17f1bSmrg */ 91090b17f1bSmrg 91190b17f1bSmrg if (NULL != pViaSubPic) { 91290b17f1bSmrg if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] 91390b17f1bSmrg != (pViaSubPic->srfNo | VIA_XVMC_VALID)) { 91490b17f1bSmrg sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] = 91590b17f1bSmrg pViaSubPic->srfNo | VIA_XVMC_VALID; 91690b17f1bSmrg viaVideoSubPictureLocked(pViaXvMC->xl, pViaSubPic); 91790b17f1bSmrg } 91890b17f1bSmrg } else { 91990b17f1bSmrg if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] & VIA_XVMC_VALID) { 92090b17f1bSmrg viaVideoSubPictureOffLocked(pViaXvMC->xl); 92190b17f1bSmrg sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] &= ~VIA_XVMC_VALID; 92290b17f1bSmrg } 92390b17f1bSmrg } 92490b17f1bSmrg 92590b17f1bSmrg /* 92690b17f1bSmrg * Flip 92790b17f1bSmrg */ 92890b17f1bSmrg 92990b17f1bSmrg viaVideoSWFlipLocked(pViaXvMC->xl, flags, 93090b17f1bSmrg pViaSurface->progressiveSequence); 93190b17f1bSmrg flushXvMCLowLevel(pViaXvMC->xl); 93290b17f1bSmrg 93390b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 1); 93490b17f1bSmrg hwlUnlock(pViaXvMC->xl, 1); 93590b17f1bSmrg 93690b17f1bSmrg if (overlayUpdated || !drawInfo->touched) { 93790b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 93890b17f1bSmrg return Success; 93990b17f1bSmrg } 94090b17f1bSmrg 94190b17f1bSmrg /* 94290b17f1bSmrg * Update overlay 94390b17f1bSmrg */ 94490b17f1bSmrg 94590b17f1bSmrg ret = 94690b17f1bSmrg updateXVOverlay(display, pViaXvMC, pViaSurface, draw, srcx, srcy, 94790b17f1bSmrg srcw, srch, destx, desty, destw, desth); 94890b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 94990b17f1bSmrg return ret; 95090b17f1bSmrg 95190b17f1bSmrg} 95290b17f1bSmrg 95390b17f1bSmrgvoid 95490b17f1bSmrgdebugControl(const XvMCMpegControl * control) 95590b17f1bSmrg{ 95690b17f1bSmrg printf("BVMV_range: %u\n", control->BVMV_range); 95790b17f1bSmrg printf("BHMV_range: %u\n", control->BHMV_range); 95890b17f1bSmrg printf("FVMV_range: %u\n", control->FVMV_range); 95990b17f1bSmrg printf("FHMV_range: %u\n", control->FHMV_range); 96090b17f1bSmrg printf("picture_structure: %u\n", control->picture_structure); 96190b17f1bSmrg printf("intra_dc_precision: %u\n", control->intra_dc_precision); 96290b17f1bSmrg printf("picture_coding_type: %u\n", control->picture_coding_type); 96390b17f1bSmrg printf("mpeg_coding: %u\n", control->mpeg_coding); 96490b17f1bSmrg printf("flags: 0x%x\n", control->flags); 96590b17f1bSmrg} 96690b17f1bSmrg 96790b17f1bSmrg_X_EXPORT Status 96890b17f1bSmrgXvMCBeginSurface(Display * display, 96990b17f1bSmrg XvMCContext * context, 97090b17f1bSmrg XvMCSurface * target_surface, 97190b17f1bSmrg XvMCSurface * past_surface, 97290b17f1bSmrg XvMCSurface * future_surface, const XvMCMpegControl * control) 97390b17f1bSmrg{ 97490b17f1bSmrg ViaXvMCSurface *targS, *futS, *pastS; 97590b17f1bSmrg ViaXvMCContext *pViaXvMC; 97690b17f1bSmrg int hadDecoderLast; 97790b17f1bSmrg CARD32 timeStamp; 97890b17f1bSmrg 97990b17f1bSmrg if ((display == NULL) || (context == NULL) || (target_surface == NULL)) { 98090b17f1bSmrg return BadValue; 98190b17f1bSmrg } 98290b17f1bSmrg 98390b17f1bSmrg pViaXvMC = context->privData; 98490b17f1bSmrg 98590b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 98690b17f1bSmrg if (grabDecoder(pViaXvMC, &hadDecoderLast)) { 98790b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 98890b17f1bSmrg return BadAlloc; 98990b17f1bSmrg } 99090b17f1bSmrg pViaXvMC->haveDecoder = 1; 99190b17f1bSmrg 99290b17f1bSmrg /* 99390b17f1bSmrg * We need to wait for decoder idle at next flush, since hardware doesn't queue 99490b17f1bSmrg * beginsurface requests until the decoder is idle. This is 99590b17f1bSmrg * done by waiting on the last previous timestamp, or if there was another context 99690b17f1bSmrg * having the decoder before us, by emitting a new one. 99790b17f1bSmrg */ 99890b17f1bSmrg 99990b17f1bSmrg if (pViaXvMC->useAGP) { 100090b17f1bSmrg if (!hadDecoderLast || pViaXvMC->timeStamp == 0) { 100190b17f1bSmrg timeStamp = viaDMATimeStampLowLevel(pViaXvMC->xl); 100290b17f1bSmrg if (flushXvMCLowLevel(pViaXvMC->xl)) { 100390b17f1bSmrg releaseDecoder(pViaXvMC, 0); 100490b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 100590b17f1bSmrg return BadAlloc; 100690b17f1bSmrg } 100790b17f1bSmrg pViaXvMC->timeStamp = timeStamp; 100890b17f1bSmrg } else { 100990b17f1bSmrg timeStamp = pViaXvMC->timeStamp; 101090b17f1bSmrg } 101190b17f1bSmrg setAGPSyncLowLevel(pViaXvMC->xl, 1, timeStamp); 101290b17f1bSmrg } 101390b17f1bSmrg 101490b17f1bSmrg if (!hadDecoderLast || !pViaXvMC->decoderOn) { 101590b17f1bSmrg pViaXvMC->intraLoaded = 0; 101690b17f1bSmrg pViaXvMC->nonIntraLoaded = 0; 101790b17f1bSmrg } 101890b17f1bSmrg 101990b17f1bSmrg viaMpegReset(pViaXvMC->xl); 102090b17f1bSmrg 102190b17f1bSmrg targS = (ViaXvMCSurface *) target_surface->privData; 102290b17f1bSmrg futS = NULL; 102390b17f1bSmrg pastS = NULL; 102490b17f1bSmrg 102590b17f1bSmrg pViaXvMC->rendSurf[0] = targS->srfNo | VIA_XVMC_VALID; 102690b17f1bSmrg if (future_surface) { 102790b17f1bSmrg futS = (ViaXvMCSurface *) future_surface->privData; 102890b17f1bSmrg futS->needsSync = 0; 102990b17f1bSmrg } 103090b17f1bSmrg if (past_surface) { 103190b17f1bSmrg pastS = (ViaXvMCSurface *) past_surface->privData; 103290b17f1bSmrg pastS->needsSync = 0; 103390b17f1bSmrg } 103490b17f1bSmrg 103590b17f1bSmrg targS->progressiveSequence = (control->flags & XVMC_PROGRESSIVE_SEQUENCE); 103690b17f1bSmrg targS->topFieldFirst = (control->flags & XVMC_TOP_FIELD_FIRST); 103790b17f1bSmrg targS->privSubPic = NULL; 103890b17f1bSmrg 103990b17f1bSmrg viaMpegSetSurfaceStride(pViaXvMC->xl, pViaXvMC); 104090b17f1bSmrg 104190b17f1bSmrg viaMpegSetFB(pViaXvMC->xl, 0, yOffs(targS), uOffs(targS), vOffs(targS)); 104290b17f1bSmrg if (past_surface) { 104390b17f1bSmrg viaMpegSetFB(pViaXvMC->xl, 1, yOffs(pastS), uOffs(pastS), 104490b17f1bSmrg vOffs(pastS)); 104590b17f1bSmrg } else { 104690b17f1bSmrg viaMpegSetFB(pViaXvMC->xl, 1, 0, 0, 0); 104790b17f1bSmrg } 104890b17f1bSmrg 104990b17f1bSmrg if (future_surface) { 105090b17f1bSmrg viaMpegSetFB(pViaXvMC->xl, 2, yOffs(futS), uOffs(futS), vOffs(futS)); 105190b17f1bSmrg } else { 105290b17f1bSmrg viaMpegSetFB(pViaXvMC->xl, 2, 0, 0, 0); 105390b17f1bSmrg } 105490b17f1bSmrg 105590b17f1bSmrg viaMpegBeginPicture(pViaXvMC->xl, pViaXvMC, context->width, 105690b17f1bSmrg context->height, control); 105790b17f1bSmrg flushPCIXvMCLowLevel(pViaXvMC->xl); 105890b17f1bSmrg targS->needsSync = 1; 105990b17f1bSmrg targS->syncMode = LL_MODE_DECODER_IDLE; 106090b17f1bSmrg pViaXvMC->decoderOn = 1; 106190b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 106290b17f1bSmrg return Success; 106390b17f1bSmrg} 106490b17f1bSmrg 106590b17f1bSmrg_X_EXPORT Status 106690b17f1bSmrgXvMCSyncSurface(Display * display, XvMCSurface * surface) 106790b17f1bSmrg{ 106890b17f1bSmrg ViaXvMCSurface *pViaSurface; 106990b17f1bSmrg ViaXvMCContext *pViaXvMC; 107090b17f1bSmrg unsigned i; 107190b17f1bSmrg 107290b17f1bSmrg if ((display == NULL) || (surface == NULL)) { 107390b17f1bSmrg return BadValue; 107490b17f1bSmrg } 107590b17f1bSmrg if (surface->privData == NULL) { 107690b17f1bSmrg return (error_base + XvMCBadSurface); 107790b17f1bSmrg } 107890b17f1bSmrg 107990b17f1bSmrg pViaSurface = (ViaXvMCSurface *) surface->privData; 108090b17f1bSmrg pViaXvMC = pViaSurface->privContext; 108190b17f1bSmrg 108290b17f1bSmrg if (pViaXvMC == NULL) { 108390b17f1bSmrg return (error_base + XvMCBadSurface); 108490b17f1bSmrg } 108590b17f1bSmrg 108690b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 108790b17f1bSmrg 108890b17f1bSmrg if (pViaSurface->needsSync) { 108990b17f1bSmrg CARD32 timeStamp = pViaSurface->timeStamp; 109090b17f1bSmrg int syncMode = pViaSurface->syncMode; 109190b17f1bSmrg 109290b17f1bSmrg if (pViaXvMC->useAGP) { 109390b17f1bSmrg 109490b17f1bSmrg syncMode = (pViaSurface->syncMode == LL_MODE_2D || 109590b17f1bSmrg pViaSurface->timeStamp < pViaXvMC->timeStamp) ? 109690b17f1bSmrg LL_MODE_2D : LL_MODE_DECODER_IDLE; 109790b17f1bSmrg if (pViaSurface->syncMode != LL_MODE_2D) 109890b17f1bSmrg timeStamp = pViaXvMC->timeStamp; 109990b17f1bSmrg 110090b17f1bSmrg } else if (syncMode != LL_MODE_2D && 110190b17f1bSmrg pViaXvMC->rendSurf[0] != (pViaSurface->srfNo | VIA_XVMC_VALID)) { 110290b17f1bSmrg 110390b17f1bSmrg pViaSurface->needsSync = 0; 110490b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 110590b17f1bSmrg return Success; 110690b17f1bSmrg } 110790b17f1bSmrg 110890b17f1bSmrg if (syncXvMCLowLevel(pViaXvMC->xl, syncMode, 1, 110990b17f1bSmrg pViaSurface->timeStamp)) { 111090b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 111190b17f1bSmrg return BadValue; 111290b17f1bSmrg } 111390b17f1bSmrg pViaSurface->needsSync = 0; 111490b17f1bSmrg } 111590b17f1bSmrg 111690b17f1bSmrg if (pViaXvMC->rendSurf[0] == (pViaSurface->srfNo | VIA_XVMC_VALID)) { 111790b17f1bSmrg pViaSurface->needsSync = 0; 111890b17f1bSmrg for (i = 0; i < VIA_MAX_RENDSURF; ++i) { 111990b17f1bSmrg pViaXvMC->rendSurf[i] = 0; 112090b17f1bSmrg } 112190b17f1bSmrg } 112290b17f1bSmrg 112390b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 112490b17f1bSmrg return Success; 112590b17f1bSmrg} 112690b17f1bSmrg 112790b17f1bSmrg_X_EXPORT Status 112890b17f1bSmrgXvMCLoadQMatrix(Display * display, XvMCContext * context, 112990b17f1bSmrg const XvMCQMatrix * qmx) 113090b17f1bSmrg{ 113190b17f1bSmrg ViaXvMCContext * pViaXvMC; 113290b17f1bSmrg 113390b17f1bSmrg if ((display == NULL) || (context == NULL)) { 113490b17f1bSmrg return BadValue; 113590b17f1bSmrg } 113690b17f1bSmrg if (NULL == (pViaXvMC = context->privData)) { 113790b17f1bSmrg return (error_base + XvMCBadContext); 113890b17f1bSmrg } 113990b17f1bSmrg 114090b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 114190b17f1bSmrg if (qmx->load_intra_quantiser_matrix) { 114290b17f1bSmrg memcpy(pViaXvMC->intra_quantiser_matrix, 114390b17f1bSmrg qmx->intra_quantiser_matrix, sizeof(qmx->intra_quantiser_matrix)); 114490b17f1bSmrg pViaXvMC->intraLoaded = 0; 114590b17f1bSmrg } 114690b17f1bSmrg 114790b17f1bSmrg if (qmx->load_non_intra_quantiser_matrix) { 114890b17f1bSmrg memcpy(pViaXvMC->non_intra_quantiser_matrix, 114990b17f1bSmrg qmx->non_intra_quantiser_matrix, 115090b17f1bSmrg sizeof(qmx->non_intra_quantiser_matrix)); 115190b17f1bSmrg pViaXvMC->nonIntraLoaded = 0; 115290b17f1bSmrg } 115390b17f1bSmrg 115490b17f1bSmrg if (qmx->load_chroma_intra_quantiser_matrix) { 115590b17f1bSmrg memcpy(pViaXvMC->chroma_intra_quantiser_matrix, 115690b17f1bSmrg qmx->chroma_intra_quantiser_matrix, 115790b17f1bSmrg sizeof(qmx->chroma_intra_quantiser_matrix)); 115890b17f1bSmrg pViaXvMC->chromaIntraLoaded = 0; 115990b17f1bSmrg } 116090b17f1bSmrg 116190b17f1bSmrg if (qmx->load_chroma_non_intra_quantiser_matrix) { 116290b17f1bSmrg memcpy(pViaXvMC->chroma_non_intra_quantiser_matrix, 116390b17f1bSmrg qmx->chroma_non_intra_quantiser_matrix, 116490b17f1bSmrg sizeof(qmx->chroma_non_intra_quantiser_matrix)); 116590b17f1bSmrg pViaXvMC->chromaNonIntraLoaded = 0; 116690b17f1bSmrg } 116790b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 116890b17f1bSmrg 116990b17f1bSmrg return Success; 117090b17f1bSmrg} 117190b17f1bSmrg 117290b17f1bSmrg/* 117390b17f1bSmrg * Below, we provide functions unusable for this implementation, but for 117490b17f1bSmrg * standard completeness. 117590b17f1bSmrg */ 117690b17f1bSmrg 117790b17f1bSmrg_X_EXPORT Status XvMCRenderSurface 117890b17f1bSmrg (Display * display, 117990b17f1bSmrg XvMCContext * context, 118090b17f1bSmrg unsigned int picture_structure, 118190b17f1bSmrg XvMCSurface * target_surface, 118290b17f1bSmrg XvMCSurface * past_surface, 118390b17f1bSmrg XvMCSurface * future_surface, 118490b17f1bSmrg unsigned int flags, 118590b17f1bSmrg unsigned int num_macroblocks, 118690b17f1bSmrg unsigned int first_macroblock, 118790b17f1bSmrg XvMCMacroBlockArray * macroblock_array, XvMCBlockArray * blocks) 118890b17f1bSmrg{ 118990b17f1bSmrg return (error_base + XvMCBadContext); 119090b17f1bSmrg} 119190b17f1bSmrg 119290b17f1bSmrg_X_EXPORT Status XvMCCreateBlocks 119390b17f1bSmrg (Display * display, 119490b17f1bSmrg XvMCContext * context, unsigned int num_blocks, XvMCBlockArray * block) 119590b17f1bSmrg{ 119690b17f1bSmrg return (error_base + XvMCBadContext); 119790b17f1bSmrg} 119890b17f1bSmrg 119990b17f1bSmrg_X_EXPORT Status 120090b17f1bSmrgXvMCDestroyBlocks(Display * display, XvMCBlockArray * block) 120190b17f1bSmrg{ 120290b17f1bSmrg return Success; 120390b17f1bSmrg} 120490b17f1bSmrg 120590b17f1bSmrg_X_EXPORT Status XvMCCreateMacroBlocks 120690b17f1bSmrg (Display * display, 120790b17f1bSmrg XvMCContext * context, 120890b17f1bSmrg unsigned int num_blocks, XvMCMacroBlockArray * blocks) 120990b17f1bSmrg{ 121090b17f1bSmrg return (error_base + XvMCBadContext); 121190b17f1bSmrg} 121290b17f1bSmrg 121390b17f1bSmrg_X_EXPORT Status 121490b17f1bSmrgXvMCDestroyMacroBlocks(Display * display, XvMCMacroBlockArray * block) 121590b17f1bSmrg{ 121690b17f1bSmrg return (error_base + XvMCBadContext); 121790b17f1bSmrg} 121890b17f1bSmrg 121990b17f1bSmrg_X_EXPORT Status 122090b17f1bSmrgXvMCCreateSubpicture(Display * display, 122190b17f1bSmrg XvMCContext * context, 122290b17f1bSmrg XvMCSubpicture * subpicture, 122390b17f1bSmrg unsigned short width, unsigned short height, int xvimage_id) 122490b17f1bSmrg{ 122590b17f1bSmrg ViaXvMCContext *pViaXvMC; 122690b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 122790b17f1bSmrg int priv_count; 122890b17f1bSmrg unsigned *priv_data; 122990b17f1bSmrg Status ret; 123090b17f1bSmrg 123190b17f1bSmrg if ((subpicture == NULL) || (context == NULL) || (display == NULL)) { 123290b17f1bSmrg return BadValue; 123390b17f1bSmrg } 123490b17f1bSmrg 123590b17f1bSmrg pViaXvMC = (ViaXvMCContext *) context->privData; 123690b17f1bSmrg if (pViaXvMC == NULL) { 123790b17f1bSmrg return (error_base + XvMCBadContext); 123890b17f1bSmrg } 123990b17f1bSmrg 124090b17f1bSmrg subpicture->privData = (ViaXvMCSubPicture *) 124190b17f1bSmrg malloc(sizeof(ViaXvMCSubPicture)); 124290b17f1bSmrg if (!subpicture->privData) { 124390b17f1bSmrg return BadAlloc; 124490b17f1bSmrg } 124590b17f1bSmrg 124690b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 124790b17f1bSmrg subpicture->width = context->width; 124890b17f1bSmrg subpicture->height = context->height; 124990b17f1bSmrg subpicture->xvimage_id = xvimage_id; 125090b17f1bSmrg pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData; 125190b17f1bSmrg 125290b17f1bSmrg XLockDisplay(display); 125390b17f1bSmrg if ((ret = _xvmc_create_subpicture(display, context, subpicture, 125490b17f1bSmrg &priv_count, &priv_data))) { 125590b17f1bSmrg XUnlockDisplay(display); 125690b17f1bSmrg free(pViaSubPic); 125790b17f1bSmrg fprintf(stderr, "Unable to create XvMC Subpicture.\n"); 125890b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 125990b17f1bSmrg return ret; 126090b17f1bSmrg } 126190b17f1bSmrg XUnlockDisplay(display); 126290b17f1bSmrg 126390b17f1bSmrg subpicture->num_palette_entries = VIA_SUBPIC_PALETTE_SIZE; 126490b17f1bSmrg subpicture->entry_bytes = 3; 126590b17f1bSmrg strncpy(subpicture->component_order, "YUV", 4); 126690b17f1bSmrg pViaSubPic->srfNo = priv_data[0]; 126790b17f1bSmrg pViaSubPic->offset = priv_data[1]; 126890b17f1bSmrg pViaSubPic->stride = (subpicture->width + 31) & ~31; 126990b17f1bSmrg pViaSubPic->privContext = pViaXvMC; 127090b17f1bSmrg pViaSubPic->ia44 = (xvimage_id == FOURCC_IA44); 127190b17f1bSmrg pViaSubPic->needsSync = 0; 127290b17f1bSmrg 127390b17f1bSmrg /* Free data returned from _xvmc_create_subpicture */ 127490b17f1bSmrg 127590b17f1bSmrg XFree(priv_data); 127690b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 127790b17f1bSmrg return Success; 127890b17f1bSmrg} 127990b17f1bSmrg 128090b17f1bSmrg_X_EXPORT Status 128190b17f1bSmrgXvMCSetSubpicturePalette(Display * display, XvMCSubpicture * subpicture, 128290b17f1bSmrg unsigned char *palette) 128390b17f1bSmrg{ 128490b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 128590b17f1bSmrg ViaXvMCContext *pViaXvMC; 128690b17f1bSmrg volatile ViaXvMCSAreaPriv *sAPriv; 128790b17f1bSmrg unsigned i; 128890b17f1bSmrg CARD32 tmp; 128990b17f1bSmrg 129090b17f1bSmrg if ((subpicture == NULL) || (display == NULL)) { 129190b17f1bSmrg return BadValue; 129290b17f1bSmrg } 129390b17f1bSmrg if (subpicture->privData == NULL) { 129490b17f1bSmrg return (error_base + XvMCBadSubpicture); 129590b17f1bSmrg } 129690b17f1bSmrg pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData; 129790b17f1bSmrg for (i = 0; i < VIA_SUBPIC_PALETTE_SIZE; ++i) { 129890b17f1bSmrg tmp = *palette++ << 8; 129990b17f1bSmrg tmp |= *palette++ << 16; 130090b17f1bSmrg tmp |= *palette++ << 24; 130190b17f1bSmrg tmp |= ((i & 0x0f) << 4) | 0x07; 130290b17f1bSmrg pViaSubPic->palette[i] = tmp; 130390b17f1bSmrg } 130490b17f1bSmrg 130590b17f1bSmrg pViaXvMC = pViaSubPic->privContext; 130690b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 130790b17f1bSmrg sAPriv = SAREAPTR(pViaXvMC); 130890b17f1bSmrg hwlLock(pViaXvMC->xl, 1); 130990b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 0); 131090b17f1bSmrg 131190b17f1bSmrg /* 131290b17f1bSmrg * If the subpicture is displaying, Immeadiately update it with the 131390b17f1bSmrg * new palette. 131490b17f1bSmrg */ 131590b17f1bSmrg 131690b17f1bSmrg if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] == 131790b17f1bSmrg (pViaSubPic->srfNo | VIA_XVMC_VALID)) { 131890b17f1bSmrg viaVideoSubPictureLocked(pViaXvMC->xl, pViaSubPic); 131990b17f1bSmrg } 132090b17f1bSmrg flushPCIXvMCLowLevel(pViaXvMC->xl); 132190b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 1); 132290b17f1bSmrg hwlUnlock(pViaXvMC->xl, 1); 132390b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 132490b17f1bSmrg return Success; 132590b17f1bSmrg} 132690b17f1bSmrg 132790b17f1bSmrgstatic int 132890b17f1bSmrgfindOverlap(unsigned width, unsigned height, 132990b17f1bSmrg short *dstX, short *dstY, 133090b17f1bSmrg short *srcX, short *srcY, unsigned short *areaW, unsigned short *areaH) 133190b17f1bSmrg{ 133290b17f1bSmrg int w, h; 133390b17f1bSmrg unsigned mWidth, mHeight; 133490b17f1bSmrg 133590b17f1bSmrg w = *areaW; 133690b17f1bSmrg h = *areaH; 133790b17f1bSmrg 133890b17f1bSmrg if ((*dstX >= width) || (*dstY >= height)) 133990b17f1bSmrg return 1; 134090b17f1bSmrg if (*dstX < 0) { 134190b17f1bSmrg w += *dstX; 134290b17f1bSmrg *srcX -= *dstX; 134390b17f1bSmrg *dstX = 0; 134490b17f1bSmrg } 134590b17f1bSmrg if (*dstY < 0) { 134690b17f1bSmrg h += *dstY; 134790b17f1bSmrg *srcY -= *dstY; 134890b17f1bSmrg *dstY = 0; 134990b17f1bSmrg } 135090b17f1bSmrg if ((w <= 0) || ((h <= 0))) 135190b17f1bSmrg return 1; 135290b17f1bSmrg mWidth = width - *dstX; 135390b17f1bSmrg mHeight = height - *dstY; 135490b17f1bSmrg *areaW = (w <= mWidth) ? w : mWidth; 135590b17f1bSmrg *areaH = (h <= mHeight) ? h : mHeight; 135690b17f1bSmrg return 0; 135790b17f1bSmrg} 135890b17f1bSmrg 135990b17f1bSmrg_X_EXPORT Status 136090b17f1bSmrgXvMCClearSubpicture(Display * display, 136190b17f1bSmrg XvMCSubpicture * subpicture, 136290b17f1bSmrg short x, 136390b17f1bSmrg short y, unsigned short width, unsigned short height, unsigned int color) 136490b17f1bSmrg{ 136590b17f1bSmrg 136690b17f1bSmrg ViaXvMCContext *pViaXvMC; 136790b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 136890b17f1bSmrg short dummyX, dummyY; 136990b17f1bSmrg unsigned long bOffs; 137090b17f1bSmrg 137190b17f1bSmrg if ((subpicture == NULL) || (display == NULL)) { 137290b17f1bSmrg return BadValue; 137390b17f1bSmrg } 137490b17f1bSmrg if (subpicture->privData == NULL) { 137590b17f1bSmrg return (error_base + XvMCBadSubpicture); 137690b17f1bSmrg } 137790b17f1bSmrg pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData; 137890b17f1bSmrg pViaXvMC = pViaSubPic->privContext; 137990b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 138090b17f1bSmrg 138190b17f1bSmrg /* Clip clearing area so that it fits inside subpicture. */ 138290b17f1bSmrg 138390b17f1bSmrg if (findOverlap(subpicture->width, subpicture->height, &x, &y, 138490b17f1bSmrg &dummyX, &dummyY, &width, &height)) { 138590b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 138690b17f1bSmrg return Success; 138790b17f1bSmrg } 138890b17f1bSmrg 138990b17f1bSmrg bOffs = pViaSubPic->offset + y * pViaSubPic->stride + x; 139090b17f1bSmrg viaBlit(pViaXvMC->xl, 8, 0, pViaSubPic->stride, bOffs, pViaSubPic->stride, 139190b17f1bSmrg width, height, 1, 1, VIABLIT_FILL, color); 139290b17f1bSmrg pViaSubPic->needsSync = 1; 139390b17f1bSmrg pViaSubPic->timeStamp = viaDMATimeStampLowLevel(pViaXvMC->xl); 139490b17f1bSmrg if (flushXvMCLowLevel(pViaXvMC->xl)) { 139590b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 139690b17f1bSmrg return BadValue; 139790b17f1bSmrg } 139890b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 139990b17f1bSmrg return Success; 140090b17f1bSmrg} 140190b17f1bSmrg 140290b17f1bSmrg_X_EXPORT Status 140390b17f1bSmrgXvMCCompositeSubpicture(Display * display, 140490b17f1bSmrg XvMCSubpicture * subpicture, 140590b17f1bSmrg XvImage * image, 140690b17f1bSmrg short srcx, 140790b17f1bSmrg short srcy, 140890b17f1bSmrg unsigned short width, unsigned short height, short dstx, short dsty) 140990b17f1bSmrg{ 141090b17f1bSmrg 141190b17f1bSmrg unsigned i; 141290b17f1bSmrg ViaXvMCContext *pViaXvMC; 141390b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 141490b17f1bSmrg CARD8 *dAddr, *sAddr; 141590b17f1bSmrg 141690b17f1bSmrg if ((subpicture == NULL) || (display == NULL) || (image == NULL)) { 141790b17f1bSmrg return BadValue; 141890b17f1bSmrg } 141990b17f1bSmrg if (NULL == (pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData)) { 142090b17f1bSmrg return (error_base + XvMCBadSubpicture); 142190b17f1bSmrg } 142290b17f1bSmrg 142390b17f1bSmrg pViaXvMC = pViaSubPic->privContext; 142490b17f1bSmrg 142590b17f1bSmrg if (image->id != subpicture->xvimage_id) 142690b17f1bSmrg return BadMatch; 142790b17f1bSmrg 142890b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 142990b17f1bSmrg 143090b17f1bSmrg /* 143190b17f1bSmrg * Clip copy area so that it fits inside subpicture and image. 143290b17f1bSmrg */ 143390b17f1bSmrg 143490b17f1bSmrg if (findOverlap(subpicture->width, subpicture->height, 143590b17f1bSmrg &dstx, &dsty, &srcx, &srcy, &width, &height)) { 143690b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 143790b17f1bSmrg return Success; 143890b17f1bSmrg } 143990b17f1bSmrg if (findOverlap(image->width, image->height, 144090b17f1bSmrg &srcx, &srcy, &dstx, &dsty, &width, &height)) { 144190b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 144290b17f1bSmrg return Success; 144390b17f1bSmrg } 144490b17f1bSmrg 144590b17f1bSmrg if (pViaSubPic->needsSync) { 144690b17f1bSmrg if (syncXvMCLowLevel(pViaXvMC->xl, LL_MODE_2D, 0, 144790b17f1bSmrg pViaSubPic->timeStamp)) { 144890b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 144990b17f1bSmrg return BadValue; 145090b17f1bSmrg } 145190b17f1bSmrg pViaSubPic->needsSync = 0; 145290b17f1bSmrg } 145390b17f1bSmrg 145490b17f1bSmrg for (i = 0; i < height; ++i) { 145590b17f1bSmrg dAddr = (((CARD8 *) pViaXvMC->fbAddress) + 145690b17f1bSmrg (pViaSubPic->offset + (dsty + i) * pViaSubPic->stride + dstx)); 145790b17f1bSmrg sAddr = (((CARD8 *) image->data) + 145890b17f1bSmrg (image->offsets[0] + (srcy + i) * image->pitches[0] + srcx)); 145990b17f1bSmrg memcpy(dAddr, sAddr, width); 146090b17f1bSmrg } 146190b17f1bSmrg 146290b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 146390b17f1bSmrg return Success; 146490b17f1bSmrg} 146590b17f1bSmrg 146690b17f1bSmrg_X_EXPORT Status 146790b17f1bSmrgXvMCBlendSubpicture(Display * display, 146890b17f1bSmrg XvMCSurface * target_surface, 146990b17f1bSmrg XvMCSubpicture * subpicture, 147090b17f1bSmrg short subx, 147190b17f1bSmrg short suby, 147290b17f1bSmrg unsigned short subw, 147390b17f1bSmrg unsigned short subh, 147490b17f1bSmrg short surfx, short surfy, unsigned short surfw, unsigned short surfh) 147590b17f1bSmrg{ 147690b17f1bSmrg ViaXvMCSurface *pViaSurface; 147790b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 147890b17f1bSmrg 147990b17f1bSmrg if ((display == NULL) || target_surface == NULL) { 148090b17f1bSmrg return BadValue; 148190b17f1bSmrg } 148290b17f1bSmrg 148390b17f1bSmrg if (subx || suby || surfx || surfy || (subw != surfw) || (subh != surfh)) { 148490b17f1bSmrg fprintf(stderr, "ViaXvMC: Only completely overlapping subpicture " 148590b17f1bSmrg "supported.\n"); 148690b17f1bSmrg return BadValue; 148790b17f1bSmrg } 148890b17f1bSmrg 148990b17f1bSmrg if (NULL == (pViaSurface = target_surface->privData)) { 149090b17f1bSmrg return (error_base + XvMCBadSurface); 149190b17f1bSmrg } 149290b17f1bSmrg 149390b17f1bSmrg if (subpicture) { 149490b17f1bSmrg 149590b17f1bSmrg if (NULL == (pViaSubPic = subpicture->privData)) { 149690b17f1bSmrg return (error_base + XvMCBadSubpicture); 149790b17f1bSmrg } 149890b17f1bSmrg 149990b17f1bSmrg pViaSurface->privSubPic = pViaSubPic; 150090b17f1bSmrg } else { 150190b17f1bSmrg pViaSurface->privSubPic = NULL; 150290b17f1bSmrg } 150390b17f1bSmrg return Success; 150490b17f1bSmrg} 150590b17f1bSmrg 150690b17f1bSmrg_X_EXPORT Status 150790b17f1bSmrgXvMCBlendSubpicture2(Display * display, 150890b17f1bSmrg XvMCSurface * source_surface, 150990b17f1bSmrg XvMCSurface * target_surface, 151090b17f1bSmrg XvMCSubpicture * subpicture, 151190b17f1bSmrg short subx, 151290b17f1bSmrg short suby, 151390b17f1bSmrg unsigned short subw, 151490b17f1bSmrg unsigned short subh, 151590b17f1bSmrg short surfx, short surfy, unsigned short surfw, unsigned short surfh) 151690b17f1bSmrg{ 151790b17f1bSmrg ViaXvMCSurface *pViaSurface, *pViaSSurface; 151890b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 151990b17f1bSmrg ViaXvMCContext *pViaXvMC; 152090b17f1bSmrg 152190b17f1bSmrg unsigned width, height; 152290b17f1bSmrg 152390b17f1bSmrg if ((display == NULL) || target_surface == NULL || source_surface == NULL) { 152490b17f1bSmrg return BadValue; 152590b17f1bSmrg } 152690b17f1bSmrg 152790b17f1bSmrg if (subx || suby || surfx || surfy || (subw != surfw) || (subh != surfh)) { 152890b17f1bSmrg fprintf(stderr, "ViaXvMC: Only completely overlapping subpicture " 152990b17f1bSmrg "supported.\n"); 153090b17f1bSmrg return BadMatch; 153190b17f1bSmrg } 153290b17f1bSmrg 153390b17f1bSmrg if (NULL == (pViaSurface = target_surface->privData)) { 153490b17f1bSmrg return (error_base + XvMCBadSurface); 153590b17f1bSmrg } 153690b17f1bSmrg 153790b17f1bSmrg if (NULL == (pViaSSurface = source_surface->privData)) { 153890b17f1bSmrg return (error_base + XvMCBadSurface); 153990b17f1bSmrg } 154090b17f1bSmrg pViaXvMC = pViaSurface->privContext; 154190b17f1bSmrg width = pViaSSurface->width; 154290b17f1bSmrg height = pViaSSurface->height; 154390b17f1bSmrg if (width != pViaSurface->width || height != pViaSSurface->height) { 154490b17f1bSmrg return BadMatch; 154590b17f1bSmrg } 154690b17f1bSmrg 154790b17f1bSmrg if (XvMCSyncSurface(display, source_surface)) { 154890b17f1bSmrg return BadValue; 154990b17f1bSmrg } 155090b17f1bSmrg 155190b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 155290b17f1bSmrg viaBlit(pViaXvMC->xl, 8, yOffs(pViaSSurface), pViaSSurface->yStride, 155390b17f1bSmrg yOffs(pViaSurface), pViaSurface->yStride, 155490b17f1bSmrg width, height, 1, 1, VIABLIT_COPY, 0); 155590b17f1bSmrg flushPCIXvMCLowLevel(pViaXvMC->xl); 155690b17f1bSmrg if (pViaXvMC->chipId != PCI_CHIP_VT3259) { 155790b17f1bSmrg 155890b17f1bSmrg /* 155990b17f1bSmrg * YV12 Chroma blit. 156090b17f1bSmrg */ 156190b17f1bSmrg 156290b17f1bSmrg viaBlit(pViaXvMC->xl, 8, uOffs(pViaSSurface), 156390b17f1bSmrg pViaSSurface->yStride >> 1, uOffs(pViaSurface), 156490b17f1bSmrg pViaSurface->yStride >> 1, width >> 1, height >> 1, 1, 1, 156590b17f1bSmrg VIABLIT_COPY, 0); 156690b17f1bSmrg flushPCIXvMCLowLevel(pViaXvMC->xl); 156790b17f1bSmrg viaBlit(pViaXvMC->xl, 8, vOffs(pViaSSurface), 156890b17f1bSmrg pViaSSurface->yStride >> 1, vOffs(pViaSurface), 156990b17f1bSmrg pViaSurface->yStride >> 1, width >> 1, height >> 1, 1, 1, 157090b17f1bSmrg VIABLIT_COPY, 0); 157190b17f1bSmrg } else { 157290b17f1bSmrg 157390b17f1bSmrg /* 157490b17f1bSmrg * NV12 Chroma blit. 157590b17f1bSmrg */ 157690b17f1bSmrg 157790b17f1bSmrg viaBlit(pViaXvMC->xl, 8, vOffs(pViaSSurface), pViaSSurface->yStride, 157890b17f1bSmrg vOffs(pViaSurface), pViaSurface->yStride, 157990b17f1bSmrg width, height >> 1, 1, 1, VIABLIT_COPY, 0); 158090b17f1bSmrg } 158190b17f1bSmrg pViaSurface->needsSync = 1; 158290b17f1bSmrg pViaSurface->syncMode = LL_MODE_2D; 158390b17f1bSmrg pViaSurface->timeStamp = viaDMATimeStampLowLevel(pViaXvMC->xl); 158490b17f1bSmrg if (flushXvMCLowLevel(pViaXvMC->xl)) { 158590b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 158690b17f1bSmrg return BadValue; 158790b17f1bSmrg } 158890b17f1bSmrg if (subpicture) { 158990b17f1bSmrg 159090b17f1bSmrg if (NULL == (pViaSubPic = subpicture->privData)) { 159190b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 159290b17f1bSmrg return (error_base + XvMCBadSubpicture); 159390b17f1bSmrg } 159490b17f1bSmrg 159590b17f1bSmrg pViaSurface->privSubPic = pViaSubPic; 159690b17f1bSmrg } else { 159790b17f1bSmrg pViaSurface->privSubPic = NULL; 159890b17f1bSmrg } 159990b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 160090b17f1bSmrg return Success; 160190b17f1bSmrg} 160290b17f1bSmrg 160390b17f1bSmrg_X_EXPORT Status 160490b17f1bSmrgXvMCSyncSubpicture(Display * display, XvMCSubpicture * subpicture) 160590b17f1bSmrg{ 160690b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 160790b17f1bSmrg ViaXvMCContext *pViaXvMC; 160890b17f1bSmrg Status retVal = 0; 160990b17f1bSmrg 161090b17f1bSmrg if ((display == NULL) || subpicture == NULL) { 161190b17f1bSmrg return BadValue; 161290b17f1bSmrg } 161390b17f1bSmrg if (NULL == (pViaSubPic = subpicture->privData)) { 161490b17f1bSmrg return (error_base + XvMCBadSubpicture); 161590b17f1bSmrg } 161690b17f1bSmrg 161790b17f1bSmrg pViaXvMC = pViaSubPic->privContext; 161890b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 161990b17f1bSmrg if (pViaSubPic->needsSync) { 162090b17f1bSmrg if (syncXvMCLowLevel(pViaXvMC->xl, LL_MODE_2D, 162190b17f1bSmrg 0, pViaSubPic->timeStamp)) { 162290b17f1bSmrg retVal = BadValue; 162390b17f1bSmrg } 162490b17f1bSmrg pViaSubPic->needsSync = 0; 162590b17f1bSmrg } 162690b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 162790b17f1bSmrg return retVal; 162890b17f1bSmrg} 162990b17f1bSmrg 163090b17f1bSmrg_X_EXPORT Status 163190b17f1bSmrgXvMCFlushSubpicture(Display * display, XvMCSubpicture * subpicture) 163290b17f1bSmrg{ 163390b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 163490b17f1bSmrg 163590b17f1bSmrg if ((display == NULL) || subpicture == NULL) { 163690b17f1bSmrg return BadValue; 163790b17f1bSmrg } 163890b17f1bSmrg if (NULL == (pViaSubPic = subpicture->privData)) { 163990b17f1bSmrg return (error_base + XvMCBadSubpicture); 164090b17f1bSmrg } 164190b17f1bSmrg 164290b17f1bSmrg return Success; 164390b17f1bSmrg} 164490b17f1bSmrg 164590b17f1bSmrg_X_EXPORT Status 164690b17f1bSmrgXvMCDestroySubpicture(Display * display, XvMCSubpicture * subpicture) 164790b17f1bSmrg{ 164890b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 164990b17f1bSmrg ViaXvMCContext *pViaXvMC; 165090b17f1bSmrg volatile ViaXvMCSAreaPriv *sAPriv; 165190b17f1bSmrg 165290b17f1bSmrg if ((display == NULL) || subpicture == NULL) { 165390b17f1bSmrg return BadValue; 165490b17f1bSmrg } 165590b17f1bSmrg if (NULL == (pViaSubPic = subpicture->privData)) { 165690b17f1bSmrg return (error_base + XvMCBadSubpicture); 165790b17f1bSmrg } 165890b17f1bSmrg pViaXvMC = pViaSubPic->privContext; 165990b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 166090b17f1bSmrg 166190b17f1bSmrg sAPriv = SAREAPTR(pViaXvMC); 166290b17f1bSmrg hwlLock(pViaXvMC->xl, 1); 166390b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 0); 166490b17f1bSmrg if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] == 166590b17f1bSmrg (pViaSubPic->srfNo | VIA_XVMC_VALID)) { 166690b17f1bSmrg viaVideoSubPictureOffLocked(pViaXvMC->xl); 166790b17f1bSmrg sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] = 0; 166890b17f1bSmrg } 166990b17f1bSmrg flushPCIXvMCLowLevel(pViaXvMC->xl); 167090b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 1); 167190b17f1bSmrg hwlUnlock(pViaXvMC->xl, 1); 167290b17f1bSmrg 167390b17f1bSmrg XLockDisplay(display); 167490b17f1bSmrg _xvmc_destroy_subpicture(display, subpicture); 167590b17f1bSmrg XUnlockDisplay(display); 167690b17f1bSmrg 167790b17f1bSmrg free(pViaSubPic); 167890b17f1bSmrg subpicture->privData = NULL; 167990b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 168090b17f1bSmrg 168190b17f1bSmrg return Success; 168290b17f1bSmrg} 168390b17f1bSmrg 168490b17f1bSmrg_X_EXPORT Status 168590b17f1bSmrgXvMCGetSubpictureStatus(Display * display, XvMCSubpicture * subpic, int *stat) 168690b17f1bSmrg{ 168790b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 168890b17f1bSmrg ViaXvMCContext *pViaXvMC; 168990b17f1bSmrg volatile ViaXvMCSAreaPriv *sAPriv; 169090b17f1bSmrg 169190b17f1bSmrg if ((display == NULL) || subpic == NULL) { 169290b17f1bSmrg return BadValue; 169390b17f1bSmrg } 169490b17f1bSmrg if (NULL == (pViaSubPic = subpic->privData)) { 169590b17f1bSmrg return (error_base + XvMCBadSubpicture); 169690b17f1bSmrg } 169790b17f1bSmrg if (stat) { 169890b17f1bSmrg *stat = 0; 169990b17f1bSmrg pViaXvMC = pViaSubPic->privContext; 170090b17f1bSmrg sAPriv = SAREAPTR(pViaXvMC); 170190b17f1bSmrg if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] == 170290b17f1bSmrg (pViaSubPic->srfNo | VIA_XVMC_VALID)) 170390b17f1bSmrg *stat |= XVMC_DISPLAYING; 170490b17f1bSmrg } 170590b17f1bSmrg return Success; 170690b17f1bSmrg} 170790b17f1bSmrg 170890b17f1bSmrg_X_EXPORT Status 170990b17f1bSmrgXvMCFlushSurface(Display * display, XvMCSurface * surface) 171090b17f1bSmrg{ 171190b17f1bSmrg ViaXvMCSurface *pViaSurface; 171290b17f1bSmrg ViaXvMCContext *pViaXvMC; 171390b17f1bSmrg Status ret; 171490b17f1bSmrg 171590b17f1bSmrg if ((display == NULL) || surface == NULL) { 171690b17f1bSmrg return BadValue; 171790b17f1bSmrg } 171890b17f1bSmrg if (NULL == (pViaSurface = surface->privData)) { 171990b17f1bSmrg return (error_base + XvMCBadSurface); 172090b17f1bSmrg } 172190b17f1bSmrg 172290b17f1bSmrg pViaXvMC = pViaSurface->privContext; 172390b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 172490b17f1bSmrg if (pViaSurface->needsSync) 172590b17f1bSmrg pViaSurface->timeStamp = pViaXvMC->timeStamp = 172690b17f1bSmrg viaDMATimeStampLowLevel(pViaXvMC->xl); 172790b17f1bSmrg ret = (flushXvMCLowLevel(pViaXvMC->xl)) ? BadValue : Success; 172890b17f1bSmrg if (pViaXvMC->rendSurf[0] == (pViaSurface->srfNo | VIA_XVMC_VALID)) { 172990b17f1bSmrg hwlLock(pViaXvMC->xl, 0); 173090b17f1bSmrg pViaXvMC->haveDecoder = 0; 173190b17f1bSmrg releaseDecoder(pViaXvMC, 0); 173290b17f1bSmrg hwlUnlock(pViaXvMC->xl, 0); 173390b17f1bSmrg } 173490b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 173590b17f1bSmrg return ret; 173690b17f1bSmrg} 173790b17f1bSmrg 173890b17f1bSmrg_X_EXPORT Status 173990b17f1bSmrgXvMCGetSurfaceStatus(Display * display, XvMCSurface * surface, int *stat) 174090b17f1bSmrg{ 174190b17f1bSmrg ViaXvMCSurface *pViaSurface; 174290b17f1bSmrg ViaXvMCContext *pViaXvMC; 174390b17f1bSmrg volatile ViaXvMCSAreaPriv *sAPriv; 174490b17f1bSmrg unsigned i; 174590b17f1bSmrg int ret = 0; 174690b17f1bSmrg 174790b17f1bSmrg if ((display == NULL) || surface == NULL) { 174890b17f1bSmrg return BadValue; 174990b17f1bSmrg } 175090b17f1bSmrg if (NULL == (pViaSurface = surface->privData)) { 175190b17f1bSmrg return (error_base + XvMCBadSurface); 175290b17f1bSmrg } 175390b17f1bSmrg if (stat) { 175490b17f1bSmrg *stat = 0; 175590b17f1bSmrg pViaXvMC = pViaSurface->privContext; 175690b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 175790b17f1bSmrg sAPriv = SAREAPTR(pViaXvMC); 175890b17f1bSmrg if (sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort] 175990b17f1bSmrg == (pViaSurface->srfNo | VIA_XVMC_VALID)) 176090b17f1bSmrg *stat |= XVMC_DISPLAYING; 176190b17f1bSmrg for (i = 0; i < VIA_MAX_RENDSURF; ++i) { 176290b17f1bSmrg if (pViaXvMC->rendSurf[i] == 176390b17f1bSmrg (pViaSurface->srfNo | VIA_XVMC_VALID)) { 176490b17f1bSmrg *stat |= XVMC_RENDERING; 176590b17f1bSmrg break; 176690b17f1bSmrg } 176790b17f1bSmrg } 176890b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 176990b17f1bSmrg } 177090b17f1bSmrg return ret; 177190b17f1bSmrg} 177290b17f1bSmrg 177390b17f1bSmrg_X_EXPORT XvAttribute * 177490b17f1bSmrgXvMCQueryAttributes(Display * display, XvMCContext * context, int *number) 177590b17f1bSmrg{ 177690b17f1bSmrg ViaXvMCContext *pViaXvMC; 177790b17f1bSmrg XvAttribute *ret; 177890b17f1bSmrg unsigned long siz; 177990b17f1bSmrg 178090b17f1bSmrg *number = 0; 178190b17f1bSmrg if ((display == NULL) || (context == NULL)) { 178290b17f1bSmrg return NULL; 178390b17f1bSmrg } 178490b17f1bSmrg 178590b17f1bSmrg if (NULL == (pViaXvMC = context->privData)) { 178690b17f1bSmrg return NULL; 178790b17f1bSmrg } 178890b17f1bSmrg 178990b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 179090b17f1bSmrg if (NULL != (ret = (XvAttribute *) 179190b17f1bSmrg malloc(siz = VIA_NUM_XVMC_ATTRIBUTES * sizeof(XvAttribute)))) { 179290b17f1bSmrg memcpy(ret, pViaXvMC->attribDesc, siz); 179390b17f1bSmrg *number = VIA_NUM_XVMC_ATTRIBUTES; 179490b17f1bSmrg } 179590b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 179690b17f1bSmrg 179790b17f1bSmrg return ret; 179890b17f1bSmrg} 179990b17f1bSmrg 180090b17f1bSmrg_X_EXPORT Status 180190b17f1bSmrgXvMCSetAttribute(Display * display, 180290b17f1bSmrg XvMCContext * context, Atom attribute, int value) 180390b17f1bSmrg{ 180490b17f1bSmrg int found; 180590b17f1bSmrg unsigned i; 180690b17f1bSmrg ViaXvMCContext *pViaXvMC; 180790b17f1bSmrg ViaXvMCCommandBuffer buf; 180890b17f1bSmrg 180990b17f1bSmrg if ((display == NULL) || (context == NULL)) { 181090b17f1bSmrg return (error_base + XvMCBadContext); 181190b17f1bSmrg } 181290b17f1bSmrg 181390b17f1bSmrg if (NULL == (pViaXvMC = context->privData)) { 181490b17f1bSmrg return (error_base + XvMCBadContext); 181590b17f1bSmrg } 181690b17f1bSmrg 181790b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 181890b17f1bSmrg 181990b17f1bSmrg found = 0; 182090b17f1bSmrg for (i = 0; i < pViaXvMC->attrib.numAttr; ++i) { 182190b17f1bSmrg if (attribute == pViaXvMC->attrib.attributes[i].attribute) { 182290b17f1bSmrg if ((!(pViaXvMC->attribDesc[i].flags & XvSettable)) || 182390b17f1bSmrg value < pViaXvMC->attribDesc[i].min_value || 182490b17f1bSmrg value > pViaXvMC->attribDesc[i].max_value) { 182590b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 182690b17f1bSmrg return BadValue; 182790b17f1bSmrg } 182890b17f1bSmrg pViaXvMC->attrib.attributes[i].value = value; 182990b17f1bSmrg found = 1; 183090b17f1bSmrg pViaXvMC->attribChanged = 1; 183190b17f1bSmrg break; 183290b17f1bSmrg } 183390b17f1bSmrg } 183490b17f1bSmrg if (!found) { 183590b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 183690b17f1bSmrg return BadMatch; 183790b17f1bSmrg } 183890b17f1bSmrg if (pViaXvMC->haveXv) { 183990b17f1bSmrg buf.command = VIA_XVMC_COMMAND_ATTRIBUTES; 184090b17f1bSmrg pViaXvMC->xvImage->data = (char *)&buf; 184190b17f1bSmrg buf.ctxNo = pViaXvMC->ctxNo | VIA_XVMC_VALID; 184290b17f1bSmrg buf.attrib = pViaXvMC->attrib; 184390b17f1bSmrg XLockDisplay(display); 184490b17f1bSmrg pViaXvMC->attribChanged = 184590b17f1bSmrg XvPutImage(display, pViaXvMC->port, pViaXvMC->draw, 184690b17f1bSmrg pViaXvMC->gc, pViaXvMC->xvImage, 0, 0, 1, 1, 0, 0, 1, 1); 184790b17f1bSmrg XUnlockDisplay(display); 184890b17f1bSmrg } 184990b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 185090b17f1bSmrg return Success; 185190b17f1bSmrg} 185290b17f1bSmrg 185390b17f1bSmrg_X_EXPORT Status 185490b17f1bSmrgXvMCGetAttribute(Display * display, 185590b17f1bSmrg XvMCContext * context, Atom attribute, int *value) 185690b17f1bSmrg{ 185790b17f1bSmrg int found; 185890b17f1bSmrg unsigned i; 185990b17f1bSmrg ViaXvMCContext *pViaXvMC; 186090b17f1bSmrg 186190b17f1bSmrg if ((display == NULL) || (context == NULL)) { 186290b17f1bSmrg return (error_base + XvMCBadContext); 186390b17f1bSmrg } 186490b17f1bSmrg 186590b17f1bSmrg if (NULL == (pViaXvMC = context->privData)) { 186690b17f1bSmrg return (error_base + XvMCBadContext); 186790b17f1bSmrg } 186890b17f1bSmrg 186990b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 187090b17f1bSmrg found = 0; 187190b17f1bSmrg for (i = 0; i < pViaXvMC->attrib.numAttr; ++i) { 187290b17f1bSmrg if (attribute == pViaXvMC->attrib.attributes[i].attribute) { 187390b17f1bSmrg if (pViaXvMC->attribDesc[i].flags & XvGettable) { 187490b17f1bSmrg *value = pViaXvMC->attrib.attributes[i].value; 187590b17f1bSmrg found = 1; 187690b17f1bSmrg break; 187790b17f1bSmrg } 187890b17f1bSmrg } 187990b17f1bSmrg } 188090b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 188190b17f1bSmrg 188290b17f1bSmrg if (!found) 188390b17f1bSmrg return BadMatch; 188490b17f1bSmrg return Success; 188590b17f1bSmrg} 188690b17f1bSmrg 188790b17f1bSmrg_X_EXPORT Status 188890b17f1bSmrgXvMCHideSurface(Display * display, XvMCSurface * surface) 188990b17f1bSmrg{ 189090b17f1bSmrg 189190b17f1bSmrg ViaXvMCSurface *pViaSurface; 189290b17f1bSmrg ViaXvMCContext *pViaXvMC; 189390b17f1bSmrg ViaXvMCSubPicture *pViaSubPic; 189490b17f1bSmrg volatile ViaXvMCSAreaPriv *sAPriv; 189590b17f1bSmrg ViaXvMCCommandBuffer buf; 189690b17f1bSmrg Status ret; 189790b17f1bSmrg 189890b17f1bSmrg if ((display == NULL) || (surface == NULL)) { 189990b17f1bSmrg return BadValue; 190090b17f1bSmrg } 190190b17f1bSmrg if (NULL == (pViaSurface = surface->privData)) { 190290b17f1bSmrg return (error_base + XvMCBadSurface); 190390b17f1bSmrg } 190490b17f1bSmrg if (NULL == (pViaXvMC = pViaSurface->privContext)) { 190590b17f1bSmrg return (error_base + XvMCBadContext); 190690b17f1bSmrg } 190790b17f1bSmrg 190890b17f1bSmrg ppthread_mutex_lock(&pViaXvMC->ctxMutex); 190990b17f1bSmrg if (!pViaXvMC->haveXv) { 191090b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 191190b17f1bSmrg return Success; 191290b17f1bSmrg } 191390b17f1bSmrg 191490b17f1bSmrg sAPriv = SAREAPTR(pViaXvMC); 191590b17f1bSmrg hwlLock(pViaXvMC->xl, 1); 191690b17f1bSmrg 191790b17f1bSmrg if (sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort] != 191890b17f1bSmrg (pViaSurface->srfNo | VIA_XVMC_VALID)) { 191990b17f1bSmrg hwlUnlock(pViaXvMC->xl, 1); 192090b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 192190b17f1bSmrg return Success; 192290b17f1bSmrg } 192390b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 0); 192490b17f1bSmrg if (NULL != (pViaSubPic = pViaSurface->privSubPic)) { 192590b17f1bSmrg if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] == 192690b17f1bSmrg (pViaSubPic->srfNo | VIA_XVMC_VALID)) { 192790b17f1bSmrg sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] &= ~VIA_XVMC_VALID; 192890b17f1bSmrg viaVideoSubPictureOffLocked(pViaXvMC->xl); 192990b17f1bSmrg } 193090b17f1bSmrg } 193190b17f1bSmrg flushPCIXvMCLowLevel(pViaXvMC->xl); 193290b17f1bSmrg setLowLevelLocking(pViaXvMC->xl, 1); 193390b17f1bSmrg hwlUnlock(pViaXvMC->xl, 1); 193490b17f1bSmrg 193590b17f1bSmrg buf.command = VIA_XVMC_COMMAND_UNDISPLAY; 193690b17f1bSmrg buf.ctxNo = pViaXvMC->ctxNo | VIA_XVMC_VALID; 193790b17f1bSmrg buf.srfNo = pViaSurface->srfNo | VIA_XVMC_VALID; 193890b17f1bSmrg pViaXvMC->xvImage->data = (char *)&buf; 193990b17f1bSmrg if ((ret = XvPutImage(display, pViaXvMC->port, pViaXvMC->draw, 194090b17f1bSmrg pViaXvMC->gc, pViaXvMC->xvImage, 0, 0, 1, 1, 0, 0, 1, 1))) { 194190b17f1bSmrg fprintf(stderr, "XvMCPutSurface: Hiding overlay failed.\n"); 194290b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 194390b17f1bSmrg return ret; 194490b17f1bSmrg } 194590b17f1bSmrg ppthread_mutex_unlock(&pViaXvMC->ctxMutex); 194690b17f1bSmrg return Success; 194790b17f1bSmrg} 1948