aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/XvMC/hw
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
committerReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
commitf4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch)
tree2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/XvMC/hw
parenta840692edc9c6d19cd7c057f68e39c7d95eb767d (diff)
downloadnx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository
Diffstat (limited to 'nx-X11/lib/XvMC/hw')
-rw-r--r--nx-X11/lib/XvMC/hw/i810/I810XvMC.c4507
-rw-r--r--nx-X11/lib/XvMC/hw/i810/I810XvMC.h469
-rw-r--r--nx-X11/lib/XvMC/hw/i810/Imakefile44
-rw-r--r--nx-X11/lib/XvMC/hw/via/driDrawable.c176
-rw-r--r--nx-X11/lib/XvMC/hw/via/driDrawable.h64
-rw-r--r--nx-X11/lib/XvMC/hw/via/unichrome/Imakefile51
-rw-r--r--nx-X11/lib/XvMC/hw/via/unichrome/viaLowLevel.c1056
-rw-r--r--nx-X11/lib/XvMC/hw/via/unichromeProA/Imakefile50
-rw-r--r--nx-X11/lib/XvMC/hw/via/unichromeProA/viaLowLevelPro.c1465
-rw-r--r--nx-X11/lib/XvMC/hw/via/viaLowLevel.h148
-rw-r--r--nx-X11/lib/XvMC/hw/via/viaXvMC.c1964
-rw-r--r--nx-X11/lib/XvMC/hw/via/viaXvMCPriv.h198
-rw-r--r--nx-X11/lib/XvMC/hw/via/xf86dri.c592
-rw-r--r--nx-X11/lib/XvMC/hw/via/xf86dri.h121
-rw-r--r--nx-X11/lib/XvMC/hw/via/xf86dristr.h343
15 files changed, 11248 insertions, 0 deletions
diff --git a/nx-X11/lib/XvMC/hw/i810/I810XvMC.c b/nx-X11/lib/XvMC/hw/i810/I810XvMC.c
new file mode 100644
index 000000000..89aa3ea4b
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/i810/I810XvMC.c
@@ -0,0 +1,4507 @@
+/***************************************************************************
+
+Copyright 2001 Intel Corporation. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*************************************************************************
+** File libI810XvMC.c
+**
+** Authors:
+** Matt Sottek <matthew.j.sottek@intel.com>
+** Bob Paauwe <bob.j.paauwe@intel.com>
+**
+**
+***************************************************************************/
+/* $XFree86: xc/lib/XvMC/hw/i810/I810XvMC.c,v 1.10 2002/10/30 12:52:01 alanh Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <X11/Xlibint.h>
+#include <fourcc.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+#include <X11/extensions/XvMClib.h>
+#include "I810XvMC.h"
+
+static int error_base;
+static int event_base;
+
+/***************************************************************************
+// Function: i810_get_free_buffer
+// Description: Allocates a free dma page using kernel ioctls, then
+// programs the data into the already allocated dma buffer list.
+// Arguments: pI810XvMC private data structure from the current context.
+// Notes: We faked the drmMapBufs for the i810's security so now we have
+// to insert an allocated page into the correct spot in the faked
+// list to keep up appearences.
+// Concept for this function was taken from Mesa sources.
+// Returns: drmBufPtr containing the information about the allocated page.
+***************************************************************************/
+drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC) {
+ drmI810DMA dma;
+ drmBufPtr buf;
+
+ dma.granted = 0;
+ dma.request_size = 4096;
+ while(!dma.granted) {
+ if(GET_BUFFER(pI810XvMC, dma) || !dma.granted)
+ FLUSH(pI810XvMC);
+ } /* No DMA granted */
+
+ buf = &(pI810XvMC->dmabufs->list[dma.request_idx]);
+ buf->idx = dma.request_idx;
+ buf->used = 0;
+ buf->total = dma.request_size;
+ buf->address = (drmAddress)dma.virtual;
+ return buf;
+}
+
+/***************************************************************************
+// Function: free_privContext
+// Description: Free's the private context structure if the reference
+// count is 0.
+***************************************************************************/
+void i810_free_privContext(i810XvMCContext *pI810XvMC) {
+
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+
+
+ pI810XvMC->ref--;
+ if(!pI810XvMC->ref) {
+ drmUnmapBufs(pI810XvMC->dmabufs);
+ drmUnmap(pI810XvMC->overlay.address,pI810XvMC->overlay.size);
+ drmUnmap(pI810XvMC->surfaces.address,pI810XvMC->surfaces.size);
+ drmClose(pI810XvMC->fd);
+
+ free(pI810XvMC->dmabufs->list);
+ free(pI810XvMC);
+ }
+
+ I810_UNLOCK(pI810XvMC);
+}
+
+
+/***************************************************************************
+// Function: XvMCCreateContext
+// Description: Create a XvMC context for the given surface parameters.
+// Arguments:
+// display - Connection to the X server.
+// port - XvPortID to use as avertised by the X connection.
+// surface_type_id - Unique identifier for the Surface type.
+// width - Width of the surfaces.
+// height - Height of the surfaces.
+// flags - one or more of the following
+// XVMC_DIRECT - A direct rendered context is requested.
+//
+// Notes: surface_type_id and width/height parameters must match those
+// returned by XvMCListSurfaceTypes.
+// Returns: Status
+***************************************************************************/
+Status XvMCCreateContext(Display *display, XvPortID port,
+ int surface_type_id, int width, int height, int flags,
+ XvMCContext *context) {
+ i810XvMCContext *pI810XvMC;
+ char busIdString[10];
+ int priv_count;
+ uint *priv_data;
+ uint magic;
+ Status ret;
+ int major, minor;
+
+ /* Verify Obvious things first */
+ if(context == NULL) {
+ return XvMCBadContext;
+ }
+
+ if(!(flags & XVMC_DIRECT)) {
+ /* Indirect */
+ printf("Indirect Rendering not supported!\nUsing Direct.");
+ }
+
+ /* Limit use to root for now */
+ if(geteuid()) {
+ printf("Use of XvMC on i810 is currently limited to root\n");
+ return BadAccess;
+ }
+
+ /* FIXME: Check $DISPLAY for legal values here */
+
+ context->surface_type_id = surface_type_id;
+ context->width = (unsigned short)width;
+ context->height = (unsigned short)height;
+ context->flags = flags;
+ context->port = port;
+ /*
+ Width, Height, and flags are checked against surface_type_id
+ and port for validity inside the X server, no need to check
+ here.
+ */
+
+ /* Allocate private Context data */
+ context->privData = (void *)malloc(sizeof(i810XvMCContext));
+ if(!context->privData) {
+ printf("Unable to allocate resources for XvMC context.\n");
+ return BadAlloc;
+ }
+ pI810XvMC = (i810XvMCContext *)context->privData;
+
+
+ /* Verify the XvMC extension exists */
+ if(! XvMCQueryExtension(display, &event_base,
+ &error_base)) {
+ printf("XvMC Extension is not available!\n");
+ return BadAlloc;
+ }
+ /* Verify XvMC version */
+ ret = XvMCQueryVersion(display, &major, &minor);
+ if(ret) {
+ printf("XvMCQuery Version Failed, unable to determine protocol version\n");
+ }
+ /* FIXME: Check Major and Minor here */
+
+ /* Check for drm */
+ if(! drmAvailable()) {
+ printf("Direct Rendering is not avilable on this system!\n");
+ return BadAlloc;
+ }
+
+ /*
+ Build the Attribute Atoms, and Initialize the ones that exist
+ in Xv.
+ */
+ pI810XvMC->xv_colorkey = XInternAtom(display,"XV_COLORKEY",0);
+ if(!pI810XvMC->xv_colorkey) {
+ return XvBadPort;
+ }
+ ret = XvGetPortAttribute(display,port,pI810XvMC->xv_colorkey,
+ &pI810XvMC->colorkey);
+ if(ret) {
+ return ret;
+ }
+ pI810XvMC->xv_brightness = XInternAtom(display,"XV_BRIGHTNESS",0);
+ pI810XvMC->xv_saturation = XInternAtom(display,"XV_SATURATION",0);
+ pI810XvMC->xv_contrast = XInternAtom(display,"XV_CONTRAST",0);
+ pI810XvMC->brightness = 0;
+ pI810XvMC->saturation = 0x80; /* 1.0 in 3.7 format */
+ pI810XvMC->contrast = 0x40; /* 1.0 in 3.6 format */
+
+ /* Open DRI Device */
+ if((pI810XvMC->fd = drmOpen("i810",NULL)) < 0) {
+ printf("DRM Device for i810 could not be opened.\n");
+ free(busIdString);
+ free(pI810XvMC);
+ return BadAccess;
+ } /* !pI810XvMC->fd */
+
+ /* Get magic number and put it in privData for passing */
+ drmGetMagic(pI810XvMC->fd,&magic);
+ context->flags = (unsigned long)magic;
+
+ /*
+ Pass control to the X server to create a drm_context_t for us and
+ validate the with/height and flags.
+ */
+ if((ret = _xvmc_create_context(display, context, &priv_count, &priv_data))) {
+ printf("Unable to create XvMC Context.\n");
+ return ret;
+ }
+
+ /*
+ X server returns a structure like this:
+ drm_context_t
+ fbBase
+ OverlayOffset
+ OverlaySize
+ SurfacesOffset
+ SurfacesSize
+ busIdString = 9 char + 1
+ */
+ if(priv_count != 9) {
+ printf("_xvmc_create_context() returned incorrect data size!\n");
+ printf("\tExpected 9, got %d\n",priv_count);
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC);
+ return BadAlloc;
+ }
+ pI810XvMC->drmcontext = priv_data[0];
+ pI810XvMC->fb_base = priv_data[1];
+ pI810XvMC->overlay.offset = priv_data[2] + priv_data[1];
+ pI810XvMC->overlay.size = priv_data[3];
+ pI810XvMC->surfaces.offset = priv_data[4] + priv_data[1];
+ pI810XvMC->surfaces.size = priv_data[5];
+ strncpy(pI810XvMC->busIdString,(char *)&priv_data[6],9);
+ pI810XvMC->busIdString[9] = '\0';
+
+ /* Must free the private data we were passed from X */
+ free(priv_data);
+
+ /* Initialize private context values */
+ pI810XvMC->current = 0;
+ pI810XvMC->lock = 0;
+ pI810XvMC->last_flip = 0;
+ pI810XvMC->dual_prime = 0;
+
+ /*
+ Map dma Buffers: Not really, this would be a drmMapBufs
+ but due to the i810 security model we have to just create an
+ empty data structure to fake it.
+ */
+ pI810XvMC->dmabufs = (drmBufMapPtr)malloc(sizeof(drmBufMap));
+ if(pI810XvMC->dmabufs == NULL) {
+ printf("Dma Bufs could not be mapped.\n");
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* pI810XvMC->dmabufs == NULL */
+ memset(pI810XvMC->dmabufs, 0, sizeof(drmBufMap));
+ pI810XvMC->dmabufs->list = (drmBufPtr)malloc(sizeof(drmBuf) *
+ I810_DMA_BUF_NR);
+ if(pI810XvMC->dmabufs->list == NULL) {
+ printf("Dma Bufs could not be mapped.\n");
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* pI810XvMC->dmabufs->list == NULL */
+ memset(pI810XvMC->dmabufs->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
+
+ /* Map the Overlay memory */
+ if(drmMap(pI810XvMC->fd,pI810XvMC->overlay.offset,
+ pI810XvMC->overlay.size,&(pI810XvMC->overlay.address)) < 0) {
+ printf("Unable to map Overlay at offset 0x%x and size 0x%x\n",
+ (unsigned int)pI810XvMC->overlay.offset,pI810XvMC->overlay.size);
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC->dmabufs->list);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* drmMap() < 0 */
+
+ /* Overlay Regs are offset 1024 into Overlay Map */
+ pI810XvMC->oregs = (i810OverlayRec *)
+ ((unsigned char *)pI810XvMC->overlay.address + 1024);
+
+ /* Map Surfaces */
+ if(drmMap(pI810XvMC->fd,pI810XvMC->surfaces.offset,
+ pI810XvMC->surfaces.size,&(pI810XvMC->surfaces.address)) < 0) {
+ printf("Unable to map XvMC Surfaces.\n");
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC->dmabufs->list);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* drmMap() < 0 */
+
+ /*
+ There is a tiny chance that someone was using the overlay and
+ issued a flip that hasn't finished. To be 100% sure I'll just
+ take the lock and sleep for the worst case time for a flip.
+ */
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+ usleep(20000); /* 1/50th Sec for 50hz refresh */
+
+ /* Set up Overlay regs with Initial Values */
+ pI810XvMC->oregs->YRGB_VPH = 0;
+ pI810XvMC->oregs->UV_VPH = 0;
+ pI810XvMC->oregs->HORZ_PH = 0;
+ pI810XvMC->oregs->INIT_PH = 0;
+ pI810XvMC->oregs->DWINPOS = 0;
+ pI810XvMC->oregs->DWINSZ = (I810_XVMC_MAXHEIGHT << 16) |
+ I810_XVMC_MAXWIDTH;
+ pI810XvMC->oregs->SWID = I810_XVMC_MAXWIDTH | (I810_XVMC_MAXWIDTH << 15);
+ pI810XvMC->oregs->SWIDQW = (I810_XVMC_MAXWIDTH >> 3) |
+ (I810_XVMC_MAXWIDTH << 12);
+ pI810XvMC->oregs->SHEIGHT = I810_XVMC_MAXHEIGHT |
+ (I810_XVMC_MAXHEIGHT << 15);
+ pI810XvMC->oregs->YRGBSCALE = 0x80004000; /* scale factor 1 */
+ pI810XvMC->oregs->UVSCALE = 0x80004000; /* scale factor 1 */
+ pI810XvMC->oregs->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */
+ pI810XvMC->oregs->OV0CLRC1 = 0x80; /* saturation: bypass */
+
+ /* Destination Colorkey Setup */
+ pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey);
+ pI810XvMC->oregs->DCLRKM = 0x80070307;
+
+
+ pI810XvMC->oregs->SCLRKVH = 0;
+ pI810XvMC->oregs->SCLRKVL = 0;
+ pI810XvMC->oregs->SCLRKM = 0; /* source color key disable */
+ pI810XvMC->oregs->OV0CONF = 0; /* two 720 pixel line buffers */
+
+ pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST | YUV_420;
+
+ pI810XvMC->ref = 1;
+
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+
+}
+
+/***************************************************************************
+// Function: XvMCDestroyContext
+// Description: Destorys the specified context.
+//
+// Arguments:
+// display - Specifies the connection to the server.
+// context - The context to be destroyed.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCDestroyContext(Display *display, XvMCContext *context) {
+ i810XvMCContext *pI810XvMC;
+
+ if(context == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ if(context->privData == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ pI810XvMC = (i810XvMCContext *)context->privData;
+
+ /* Turn off the overlay */
+ if(pI810XvMC->last_flip) {
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+
+ /* Make sure last flip is done */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+
+ pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST;
+ pI810XvMC->current = !pI810XvMC->current;
+ if(pI810XvMC->current == 1) {
+ pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0;
+ }
+ OVERLAY_FLIP(pI810XvMC);
+ pI810XvMC->last_flip++;
+
+ /* Wait for the flip */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+
+ I810_UNLOCK(pI810XvMC);
+ }
+
+ /* Pass Control to the X server to destroy the drm_context_t */
+ _xvmc_destroy_context(display, context);
+
+ i810_free_privContext(pI810XvMC);
+ context->privData = NULL;
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCCreateSurface
+***************************************************************************/
+Status XvMCCreateSurface( Display *display, XvMCContext *context,
+ XvMCSurface *surface) {
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSurface *pI810Surface;
+ int priv_count;
+ uint *priv_data;
+ Status ret;
+
+ if((surface == NULL) || (context == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ pI810XvMC = (i810XvMCContext *)context->privData;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+
+
+ surface->privData = (i810XvMCSurface *)malloc(sizeof(i810XvMCSurface));
+ if(!surface->privData) {
+ return BadAlloc;
+ }
+ pI810Surface = (i810XvMCSurface *)surface->privData;
+
+ /* Initialize private values */
+ pI810Surface->privContext = pI810XvMC;
+ pI810Surface->last_render = 0;
+ pI810Surface->last_flip = 0;
+ pI810Surface->second_field = 0;
+
+ if((ret = _xvmc_create_surface(display, context, surface,
+ &priv_count, &priv_data))) {
+ free(pI810Surface);
+ printf("Unable to create XvMCSurface.\n");
+ return ret;
+ }
+
+ /*
+ _xvmc_create_subpicture returns 2 uints with the offset into
+ the DRM map for the Y surface and UV surface.
+ */
+ if(priv_count != 2) {
+ printf("_xvmc_create_surface() return incorrect data size.\n");
+ printf("Expected 2 got %d\n",priv_count);
+ free(priv_data);
+ free(pI810Surface);
+ return BadAlloc;
+ }
+ /* Data == Client Address, offset == Physical address offset */
+ pI810Surface->data = pI810XvMC->surfaces.address;
+ pI810Surface->offset = pI810XvMC->surfaces.offset;
+
+
+ /*
+ i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch
+ and the Tiler need 512k aligned surfaces, basically we are
+ stuck with fixed memory with pitch 1024 for Y data. UV = 512.
+ */
+ pI810Surface->pitch = 10;
+ if((surface->surface_type_id == FOURCC_UYVY) ||
+ (surface->surface_type_id == FOURCC_YUY2)) {
+ /* This is not implemented server side. */
+ pI810Surface->pitch++;
+ }
+
+ /*
+ offsets[0,1,2] == Offsets from either data or offset for the Y
+ U and V surfaces.
+ */
+ pI810Surface->offsets[0] = priv_data[0];
+ if(((unsigned long)pI810Surface->data + pI810Surface->offsets[0]) & 4095) {
+ printf("XvMCCreateSurface: Surface offset 0 is not 4096 aligned\n");
+ }
+
+ if((surface->surface_type_id == FOURCC_UYVY) ||
+ (surface->surface_type_id == FOURCC_YUY2)) {
+ /* Packed surface, not fully implemented */
+ pI810Surface->offsets[1] = 0;
+ pI810Surface->offsets[2] = 0;
+ }
+ else {
+ /* Planar surface */
+ pI810Surface->offsets[1] = priv_data[1];
+ if(((unsigned long)pI810Surface->data + pI810Surface->offsets[1]) & 2047) {
+ printf("XvMCCreateSurface: Surface offset 1 is not 2048 aligned\n");
+ }
+
+ pI810Surface->offsets[2] = ((unsigned long)pI810Surface->offsets[1] +
+ (1<<(pI810Surface->pitch - 1)) * 288);
+ if(((unsigned long)pI810Surface->data + pI810Surface->offsets[2]) & 2047) {
+ printf("XvMCCreateSurface: Surface offset 2 is not 2048 aligned\n");
+ }
+
+ }
+
+ /* Free data returned from xvmc_create_surface */
+ free(priv_data);
+
+ /* Clear the surface to 0 */
+ memset((void *)((unsigned long)pI810Surface->data + (unsigned long)pI810Surface->offsets[0]),
+ 0, ((1<<pI810Surface->pitch) * surface->height));
+
+ switch(surface->surface_type_id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ /* Destination buffer info command */
+ pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[0]) & ~0xfc000fff) |
+ (pI810Surface->pitch - 9));
+ pI810Surface->dbi1u = ((((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[1]) & ~0xfc000fff) |
+ (pI810Surface->pitch - 10));
+ pI810Surface->dbi1v = ((((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[2]) & ~0xfc000fff) |
+ (pI810Surface->pitch - 10));
+
+ /* Destination buffer variables command */
+ pI810Surface->dbv1 = (0x8<<20) | (0x8<<16);
+ /* Map info command */
+ pI810Surface->mi1y = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 3);
+ pI810Surface->mi1u = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4);
+ pI810Surface->mi1v = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4);
+
+ pI810Surface->mi2y = (((unsigned int)surface->height - 1)<<16) |
+ ((unsigned int)surface->width - 1);
+ pI810Surface->mi2u = (((unsigned int)surface->height - 1)<<15) |
+ (((unsigned int)surface->width - 1)>>1);
+ pI810Surface->mi2v = pI810Surface->mi2u;
+
+ pI810Surface->mi3y = ((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[0]) & ~0x0000000f;
+ pI810Surface->mi3u = ((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[1]) & ~0x0000000f;
+ pI810Surface->mi3v = ((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[2]) & ~0x0000000f;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ /* Destination buffer info command */
+ pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[0]) & ~0xfc000fff) |
+ (pI810Surface->pitch - 9));
+ /* Destination buffer variables command */
+ if(surface->surface_type_id == FOURCC_YUY2) {
+ pI810Surface->dbv1 = 0x5<<8;
+ pI810Surface->mi1y = 0x5<<24 | pI810Surface->pitch | 0x1<<21;
+ }
+ else {
+ pI810Surface->dbv1 = 0x4<<8;
+ pI810Surface->mi1y = 0x5<<24 | (pI810Surface->pitch - 3);
+ }
+ pI810Surface->mi2y = (((unsigned int)surface->width - 1)<<16) |
+ ((unsigned int)surface->height - 1);
+ pI810Surface->mi3y = ((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[0]) & ~0xfc000fff;
+ break;
+ }
+ pI810XvMC->ref++;
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCDestroySurface
+***************************************************************************/
+Status XvMCDestroySurface(Display *display, XvMCSurface *surface) {
+ i810XvMCSurface *pI810Surface;
+ i810XvMCContext *pI810XvMC;
+
+ if((display == NULL) || (surface == NULL)) {
+ return BadValue;
+ }
+ if(surface->privData == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ pI810Surface = (i810XvMCSurface *)surface->privData;
+ if(pI810Surface->last_flip) {
+ XvMCSyncSurface(display,surface);
+ }
+ pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
+
+ _xvmc_destroy_surface(display,surface);
+
+ i810_free_privContext(pI810XvMC);
+
+ free(pI810Surface);
+ surface->privData = NULL;
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCreateBlocks
+***************************************************************************/
+Status XvMCCreateBlocks(Display *display, XvMCContext *context,
+ unsigned int num_blocks,
+ XvMCBlockArray *block) {
+
+ if((display == NULL) || (context == NULL) || (num_blocks == 0)) {
+ return BadValue;
+ }
+
+ block->blocks = (short *)malloc(num_blocks<<6 * sizeof(short));
+ if(block->blocks == NULL) {
+ return BadAlloc;
+ }
+
+ block->num_blocks = num_blocks;
+ block->context_id = context->context_id;
+
+ block->privData = NULL;
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCDestroyBlocks
+***************************************************************************/
+Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *block) {
+ if(display == NULL) {
+ return BadValue;
+ }
+
+ free(block->blocks);
+ block->num_blocks = 0;
+ block->context_id = 0;
+ block->privData = NULL;
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCreateMacroBlocks
+***************************************************************************/
+Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context,
+ unsigned int num_blocks,
+ XvMCMacroBlockArray *blocks) {
+
+ if((display == NULL) || (context == NULL) || (blocks == NULL) ||
+ (num_blocks == 0)) {
+ return BadValue;
+ }
+ memset(blocks,0,sizeof(XvMCMacroBlockArray));
+ blocks->context_id = context->context_id;
+ blocks->privData = NULL;
+
+ blocks->macro_blocks = (XvMCMacroBlock *)
+ malloc(num_blocks * sizeof(XvMCMacroBlock));
+ if(blocks->macro_blocks == NULL) {
+ return BadAlloc;
+ }
+ blocks->num_blocks = num_blocks;
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCDestroyMacroBlocks
+***************************************************************************/
+Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *block) {
+ if((display == NULL) || (block == NULL)) {
+ return BadValue;
+ }
+ if(block->macro_blocks) {
+ free(block->macro_blocks);
+ }
+ block->context_id = 0;
+ block->num_blocks = 0;
+ block->privData = NULL;
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: dp (Debug Print)
+// Description: This function prints out in hex i * uint32_t at the address
+// supplied. This enables you to print out the dma buffers from
+// within the debugger even though they are not in your address space.
+***************************************************************************/
+void dp(unsigned int *address, unsigned int i) {
+ int j;
+
+ printf("DebugPrint:\n");
+ for(j=0; j<i; j++) {
+ printf("0x%8.8x ",address[j]);
+ if(j && !(j & 7)) { printf("\n");}
+ }
+}
+
+/***************************************************************************
+// Macro: PACK_*
+// Description: Packs 16bit signed data from blocks into either 8bit unsigned
+// intra data or 16bit signed correction data, both packed into
+// 32 bit integers.
+***************************************************************************/
+#define PACK_INTRA_DATA(d,b,n) \
+ do { \
+ char *dp = (char *)d; \
+ char *bp = (char *)b; \
+ int counter; \
+ for(counter = 0; counter < n; counter++) { \
+ *dp++ = *bp; \
+ bp += 2; \
+ } \
+ }while(0);
+
+#define PACK_CORR_DATA(d,b,n) \
+ memcpy(d,b,n); \
+ d = (uint *)((unsigned long)d + n);
+
+#define MARK_CORR_DATA(d,n) \
+ do { \
+ uint* q = (uint*)((unsigned long)d - n); \
+ while((unsigned long)q < (unsigned long)d) { \
+ *q++ += 0x00330033; \
+ } \
+ }while(0);
+
+#define MARK_INTRA_BLOCK(d) \
+ do { \
+ int q; \
+ for(q=0; q<16; q++) { \
+ d[q] += 0x33333333; \
+ } \
+ }while(0);
+
+/*
+ Used for DCT 1 when we need DCT 0. Instead
+ of reading from one block we read from two and
+ interlace.
+*/
+#define PACK_CORR_DATA_1to0(d,top,bottom) \
+ do { \
+ short *t = top,*b = bottom; \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 16); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 16); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 16); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 16); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 16); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 16); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 16); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 16); \
+ }while(0);
+
+/* Used for DCT 0 when we need DCT 1. */
+#define PACK_CORR_DATA_0to1(d,top,bottom) \
+ do{ \
+ short *t = top,*b = bottom; \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 32); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 32); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 32); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ }while(0);
+
+#define PACK_CORR_DATA_SHORT(d,block) \
+ do { \
+ short *b = block; \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ }while(0);
+
+/* Lookup tables to speed common calculations */
+static unsigned int drps_table[] = {2<<6,3<<6};
+
+static unsigned int mvfs_table[] = {
+ 0x12,
+ 0x1a,
+ 0x13,
+ 0x1b
+};
+
+static unsigned int type_table[] = {
+ 0x1<<12, /* This is an error so make it Forward motion */
+ 0x1<<12,
+ 0x1<<12,
+ 0x1<<12,
+ 0x2<<12,
+ 0x2<<12,
+ 0x3<<12,
+ 0x3<<12,
+ 0x1<<12, /* Pattern but no Motion, Make motion Forward */
+ 0x1<<12,
+ 0x1<<12,
+ 0x1<<12,
+ 0x2<<12,
+ 0x2<<12,
+ 0x3<<12,
+ 0x3<<12
+};
+
+static unsigned int y_frame_bytes[] = {
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 128,128,128,128,256,256,256,256,
+ 256,256,256,256,384,384,384,384,
+ 128,128,128,128,256,256,256,256,
+ 256,256,256,256,384,384,384,384,
+ 256,256,256,256,384,384,384,384,
+ 384,384,384,384,512,512,512,512
+};
+
+static unsigned int u_frame_bytes[] = {
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128
+};
+
+static unsigned int v_frame_bytes[] = {
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128
+};
+
+static unsigned int y_first_field_bytes[] = {
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 128,128,128,128,128,128,128,128,
+ 128,128,128,128,128,128,128,128,
+ 128,128,128,128,128,128,128,128,
+ 128,128,128,128,128,128,128,128,
+ 256,256,256,256,256,256,256,256,
+ 256,256,256,256,256,256,256,256
+};
+
+static unsigned int y_second_field_bytes[] = {
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256
+};
+
+static unsigned int y_dct0_field_bytes[] = {
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 128,128,128,128,128,128,128,128,
+ 256,256,256,256,256,256,256,256,
+ 128,128,128,128,256,256,256,256,
+ 128,128,128,128,256,256,256,256,
+ 256,256,256,256,256,256,256,256,
+ 256,256,256,256,256,256,256,256
+};
+
+static unsigned int y_dct1_frame_bytes[] = {
+ 0,0,0,0,256,256,256,256,
+ 256,256,256,256,512,512,512,512,
+ 256,256,256,256,256,256,256,256,
+ 512,512,512,512,512,512,512,512,
+ 256,256,256,256,512,512,512,512,
+ 256,256,256,256,512,512,512,512,
+ 512,512,512,512,512,512,512,512,
+ 512,512,512,512,512,512,512,512
+};
+
+static unsigned int u_field_bytes[] = {
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64
+};
+
+static unsigned int v_field_bytes[] = {
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64
+};
+
+static short empty_block[] = {
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0
+};
+
+
+/***************************************************************************
+// Function: dispatchYContext
+// Description: Allocate a DMA buffer write the Y MC Context info in it,
+// and dispatch it to hardware.
+***************************************************************************/
+
+static __inline__ void dispatchYContext(i810XvMCSurface *privTarget,
+ i810XvMCSurface *privPast,
+ i810XvMCSurface *privFuture,
+ i810XvMCContext *pI810XvMC) {
+ uint *data;
+ drmBufPtr pDMA;
+ drm_i810_mc_t mc;
+
+ pDMA = i810_get_free_buffer(pI810XvMC);
+ data = pDMA->address;
+ *data++ = CMD_FLUSH;
+ *data++ = BOOLEAN_ENA_2;
+ *data++ = CMD_FLUSH;
+ *data++ = DEST_BUFFER_INFO;
+ *data++ = privTarget->dbi1y;
+ *data++ = DEST_BUFFER_VAR;
+ *data++ = privTarget->dbv1;
+ /* Past Surface */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privPast->mi1y;
+ *data++ = privPast->mi2y;
+ *data++ = privPast->mi3y;
+ /* Future Surface */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privFuture->mi1y | 0x1<<28;
+ *data++ = privFuture->mi2y;
+ *data++ = privFuture->mi3y;
+
+ mc.idx = pDMA->idx;
+ mc.used = (unsigned long)data - (unsigned long)pDMA->address;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+}
+
+static __inline__ void renderError(void) {
+ printf("Invalid Macroblock Parameters found.\n");
+ return;
+}
+
+/***************************************************************************
+// Function: renderIntrainFrame
+// Description: inline function that sets hardware parameters for an Intra
+// encoded macroblock in a Frame picture.
+***************************************************************************/
+static __inline__ void renderIntrainFrame(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,
+ short *block_ptr) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Y Blocks */
+ *dy++ = GFXBLOCK + 68;
+ *dy++ = (1<<30) | (3<<28) | (0xf<<24);
+ *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+ *dy++ = (16<<16) | 16;
+ *dy++ = 0;
+ *dy++ = 0;
+ PACK_INTRA_DATA(dy,block_ptr,256);
+ dy += 64;
+ block_ptr += 256;
+ /* End Y Blocks */
+
+ /* U Block */
+ *du++ = GFXBLOCK + 20;
+ *du++ = (2<<30) | (1<<28) | (1<<23);
+ *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
+ *du++ = (8<<16) | 8;
+ *du++ = 0;
+ *du++ = 0;
+ PACK_INTRA_DATA(du,block_ptr,64);
+ du += 16;
+ block_ptr += 64;
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 20;
+ *dv++ = (3<<30) | (1<<28) | (1<<22);
+ *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
+ *dv++ = (8<<16) | 8;
+ *dv++ = 0;
+ *dv++ = 0;
+ PACK_INTRA_DATA(dv,block_ptr,64);
+ dv += 16;
+ block_ptr += 64;
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderIntrainFrameDCT1
+// Description: inline function that sets hardware parameters for an Intra
+// encoded macroblock in a Frame picture with DCT type 1.
+***************************************************************************/
+static __inline__ void renderIntrainFrameDCT1(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+
+ /* Y Blocks */
+ *dy++ = GFXBLOCK + 36;
+ *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x2<<6);
+ *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+ *dy++ = (8<<16) | 16;
+ *dy++ = 0;
+ *dy++ = 0;
+ PACK_INTRA_DATA(dy,block_ptr,128);
+ dy += 32;
+ block_ptr += 128;
+
+ /* Second Y block */
+ *dy++ = GFXBLOCK + 36;
+ *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x3<<6);
+ *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+ *dy++ = (8<<16) | 16;
+ *dy++ = 0;
+ *dy++ = 0;
+ PACK_INTRA_DATA(dy,block_ptr,128);
+ dy += 32;
+ block_ptr += 128;
+ /* End Y Blocks */
+
+
+ /* U Block */
+ *du++ = GFXBLOCK + 20;
+ *du++ = (2<<30) | (1<<28) | (1<<23);
+ *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
+ *du++ = (8<<16) | 8;
+ *du++ = 0;
+ *du++ = 0;
+ PACK_INTRA_DATA(du,block_ptr,64);
+ du += 16;
+ block_ptr += 64;
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 20;
+ *dv++ = (3<<30) | (1<<28) | (1<<22);
+ *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
+ *dv++ = (8<<16) | 8;
+ *dv++ = 0;
+ *dv++ = 0;
+ PACK_INTRA_DATA(dv,block_ptr,64);
+ dv += 16;
+ block_ptr += 64;
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+
+/***************************************************************************
+// Function: renderIntrainField
+// Description: inline function that sets hardware parameters for an Intra
+// encoded macroblock in Field pictures.
+***************************************************************************/
+static __inline__ void renderIntrainField(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint ps) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+ uint dw1 = drps_table[~ps & 0x1];
+
+ /* Y Blocks */
+ *dy++ = GFXBLOCK + 68;
+ *dy++ = (1<<30) | (3<<28) | (0xf<<24) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = 0;
+ *dy++ = 0;
+ PACK_INTRA_DATA(dy,block_ptr,256);
+ dy += 64;
+ block_ptr += 256;
+ /* End Y Blocks */
+
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 20;
+ *du++ = (2<<30) | (1<<28) | (1<<23) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = 0;
+ *du++ = 0;
+ PACK_INTRA_DATA(du,block_ptr,64);
+ du += 16;
+ block_ptr += 64;
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 20;
+ *dv++ = (3<<30) | (1<<28) | (1<<22) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = 0;
+ *dv++ = 0;
+ PACK_INTRA_DATA(dv,block_ptr,64);
+ dv += 16;
+ block_ptr += 64;
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+
+/***************************************************************************
+// Function: renderFieldinField
+// Description: inline function that sets hardware parameters for a Field
+// encoded macroblock in a Field Picture.
+***************************************************************************/
+static __inline__ void renderFieldinField(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint ps, uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[2];
+ short bmv[2];
+ /* gfxblock dword 1 */
+ uint dw1;
+
+ uint parity = ~ps & XVMC_TOP_FIELD;
+
+ uint ysize = y_frame_bytes[mb->coded_block_pattern];
+ uint usize = u_frame_bytes[mb->coded_block_pattern];
+ uint vsize = v_frame_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+ /* i810 Specific flag used to identify the second field in a P frame */
+ if(flags & 0x80000000) {
+ /* P Frame */
+ if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) ==
+ parity) {
+ /* Same parity, use reference field (map0) */
+ dw1 = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
+ (((uint)mb->coded_block_pattern)<<22);
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = 0;
+ bmv[1] = 0;
+ }
+ else {
+ /*
+ Opposite parity, set up as if it were backward
+ motion and use map1.
+ */
+ dw1 = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
+ (((uint)mb->coded_block_pattern)<<22);
+ bmv[0] = mb->PMV[0][0][1];
+ bmv[1] = mb->PMV[0][0][0];
+ fmv[0] = 0;
+ fmv[1] = 0;
+ }
+ }
+ else {
+ dw1 = type_table[mb->macroblock_type & 0xf] |
+ drps_table[~ps & 0x1] |
+ mvfs_table[mb->motion_vertical_field_select & 3] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+
+ bmv[0] = mb->PMV[0][1][1];
+ bmv[1] = mb->PMV[0][1][0];
+ }
+
+ /* Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (3<<28) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ PACK_CORR_DATA(dy,block_ptr,ysize);
+ block_ptr = (short *)((unsigned long)block_ptr + ysize);
+ /* End Y Blocks */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: render16x8inField
+// Description: inline function that sets hardware parameters for a 16x8
+// encoded macroblock in a field picture.
+***************************************************************************/
+static __inline__ void render16x8inField(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint ps, uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[4];
+ short bmv[4];
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ uint y1size = y_first_field_bytes[mb->coded_block_pattern];
+ uint y2size = y_second_field_bytes[mb->coded_block_pattern];
+ uint usize = u_field_bytes[mb->coded_block_pattern];
+ uint vsize = v_field_bytes[mb->coded_block_pattern];
+
+ uint parity = ~ps & XVMC_TOP_FIELD;
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+ /* i810 Specific flag used to identify the second field in a P frame */
+ if(flags & 0x80000000) {
+ /* P Frame */
+ if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) ==
+ parity) {
+ /* Same parity, use reference field (map0) */
+ dw1[0] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = 0;
+ bmv[1] = 0;
+ }
+ else {
+ /*
+ Opposite parity, set up as if it were backward
+ motion and use map1.
+ */
+ dw1[0] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ bmv[0] = mb->PMV[0][0][1];
+ bmv[1] = mb->PMV[0][0][0];
+ fmv[0] = 0;
+ fmv[1] = 0;
+ }
+ if((mb->motion_vertical_field_select & XVMC_SELECT_SECOND_FORWARD) ==
+ (parity<<2)) {
+ /* Same parity, use reference field (map0) */
+ dw1[1] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
+ ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
+ (((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
+
+ fmv[2] = mb->PMV[1][0][1];
+ fmv[3] = mb->PMV[1][0][0];
+ bmv[2] = 0;
+ bmv[3] = 0;
+ }
+ else {
+ /*
+ Opposite parity, set up as if it were backward
+ motion and use map1.
+ */
+ dw1[1] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
+ ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
+ (((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
+
+ bmv[2] = mb->PMV[1][0][1];
+ bmv[3] = mb->PMV[1][0][0];
+ fmv[2] = 0;
+ fmv[3] = 0;
+ }
+ }
+ else {
+ dw1[0] = type_table[mb->macroblock_type & 0xf] |
+ drps_table[~ps & 0x1] |
+ mvfs_table[mb->motion_vertical_field_select & 3] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ dw1[1] = type_table[mb->macroblock_type & 0xf] |
+ drps_table[~ps & 0x1] |
+ mvfs_table[(mb->motion_vertical_field_select>>2) & 0x3] |
+ ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
+ (((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ fmv[2] = mb->PMV[1][0][1];
+ fmv[3] = mb->PMV[1][0][0];
+
+ bmv[0] = mb->PMV[0][1][1];
+ bmv[1] = mb->PMV[0][1][0];
+ bmv[2] = mb->PMV[1][1][1];
+ bmv[3] = mb->PMV[1][1][0];
+ }
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (y1size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ PACK_CORR_DATA(dy,block_ptr,y1size);
+ block_ptr = (short *)((unsigned long)block_ptr + y1size);
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (y2size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = (xy + 8);
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)&fmv[2];
+ *dy++ = *(uint *)&bmv[2];
+ PACK_CORR_DATA(dy,block_ptr,y2size);
+ block_ptr = (short *)((unsigned long)block_ptr + y2size);
+ /* End Y Blocks */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ fmv[2] /= 2;
+ fmv[3] /= 2;
+
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+ bmv[2] /= 2;
+ bmv[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+
+ /* Second U block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = (xy + 4);
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = (xy + 4);
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderDualPrimeinField
+// Description: inline function that sets hardware parameters for a Dual
+// prime encoded macroblock in a field picture.
+***************************************************************************/
+static __inline__ void renderDualPrimeinField(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint ps,
+ uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[2];
+ short bmv[2];
+ /* gfxblock dword 1 */
+ uint dw1;
+
+
+ uint ysize = y_frame_bytes[mb->coded_block_pattern];
+ uint usize = u_frame_bytes[mb->coded_block_pattern];
+ uint vsize = v_frame_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+
+ if(ps & XVMC_TOP_FIELD) {
+ dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 2<<6 | 2<<3 | 3;
+ }
+ else {
+ dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 3<<6 | 3<<3 | 2;
+ }
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = mb->PMV[0][1][1];
+ bmv[1] = mb->PMV[0][1][0];
+
+ /* Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (3<<28) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ PACK_CORR_DATA(dy,block_ptr,ysize);
+ block_ptr = (short *)((unsigned long)block_ptr + ysize);
+ /* End Y Blocks */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderFieldinFrame
+// Description: inline function that sets hardware parameters for a Field
+// encoded macroblock in a frame picture.
+***************************************************************************/
+static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[4];
+ short bmv[4];
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ uint y1size = y_first_field_bytes[mb->coded_block_pattern];
+ uint y2size = y_second_field_bytes[mb->coded_block_pattern];
+ uint usize = u_field_bytes[mb->coded_block_pattern];
+ uint vsize = v_field_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+
+ dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) |
+ mvfs_table[mb->motion_vertical_field_select & 3] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) |
+ mvfs_table[mb->motion_vertical_field_select>>2] |
+ (((mb->coded_block_pattern & 0x3) |
+ ((mb->coded_block_pattern & 0xc)<<2))<<22);
+
+ fmv[0] = mb->PMV[0][0][1]/2;
+ fmv[1] = mb->PMV[0][0][0];
+ fmv[2] = mb->PMV[1][0][1]/2;
+ fmv[3] = mb->PMV[1][0][0];
+
+ bmv[0] = mb->PMV[0][1][1]/2;
+ bmv[1] = mb->PMV[0][1][0];
+ bmv[2] = mb->PMV[1][1][1]/2;
+ bmv[3] = mb->PMV[1][1][0];
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (y1size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)&fmv[0];
+ *dy++ = *(uint *)&bmv[0];
+ PACK_CORR_DATA(dy,block_ptr,y1size);
+ block_ptr = (short *)((unsigned long)block_ptr + y1size);
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (y2size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)&fmv[2];
+ *dy++ = *(uint *)&bmv[2];
+ PACK_CORR_DATA(dy,block_ptr,y2size);
+ block_ptr = (short *)((unsigned long)block_ptr + y2size);
+ /* End Y Blocks */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ fmv[2] /= 2;
+ fmv[3] /= 2;
+
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+ bmv[2] /= 2;
+ bmv[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)&fmv[0];
+ *du++ = *(uint *)&bmv[0];
+ if(usize) {
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ }
+
+ /* Second U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ if(usize) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)&fmv[0];
+ *dv++ = *(uint *)&bmv[0];
+ if(vsize) {
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ }
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ if(vsize) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderFieldinFrameDCT0
+// Description: inline function that sets hardware parameters for a Field
+// encoded macroblock in a frame picture with DCT0.
+***************************************************************************/
+static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[4];
+ short bmv[4];
+ /* CBP */
+ uint cbp = (uint)mb->coded_block_pattern;
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ short * top_left_b = NULL;
+ short * top_right_b = NULL;
+ short * bottom_left_b = NULL;
+ short * bottom_right_b = NULL;
+
+ unsigned int ysize = y_dct0_field_bytes[cbp];
+ unsigned int usize = u_field_bytes[cbp];
+ unsigned int vsize = v_field_bytes[cbp];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+
+ dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) |
+ mvfs_table[mb->motion_vertical_field_select & 3] |
+ ((cbp | ((cbp<<2) & 0x30))<<22);
+
+ dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) |
+ mvfs_table[mb->motion_vertical_field_select>>2] |
+ ((cbp | ((cbp<<2) & 0x30))<<22);
+
+
+ fmv[0] = mb->PMV[0][0][1]/2;
+ fmv[1] = mb->PMV[0][0][0];
+ fmv[2] = mb->PMV[1][0][1]/2;
+ fmv[3] = mb->PMV[1][0][0];
+
+ bmv[0] = mb->PMV[0][1][1]/2;
+ bmv[1] = mb->PMV[0][1][0];
+ bmv[2] = mb->PMV[1][1][1]/2;
+ bmv[3] = mb->PMV[1][1][0];
+
+ /*
+ The i810 cannot use DCT0 directly with field motion, we have to
+ interlace the data for it. We use a zero block when the CBP has
+ one half of the to-be-interlaced data but not the other half.
+ */
+ top_left_b = &empty_block[0];
+ if(cbp & 0x20) {
+ top_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ top_right_b = &empty_block[0];
+ if(cbp & 0x10) {
+ top_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_left_b = &empty_block[0];
+ if(cbp & 0x8) {
+ bottom_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_right_b = &empty_block[0];
+ if(cbp & 0x4) {
+ bottom_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)&fmv[0];
+ *dy++ = *(uint *)&bmv[0];
+ if(dw1[0] & (1<<27)) {
+ PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
+ }
+ if(dw1[0] & (1<<26)) {
+ PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
+ }
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)&fmv[2];
+ *dy++ = *(uint *)&bmv[2];
+ if(dw1[1] & (1<<27)) {
+ top_left_b = (short *)((unsigned long)top_left_b + 16);
+ bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
+ PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
+ }
+ if(dw1[1] & (1<<26)) {
+ top_right_b = (short *)((unsigned long)top_right_b + 16);
+ bottom_right_b = (short *)((unsigned long)bottom_right_b + 16);
+ PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
+ }
+ /* End Y Blocks */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ fmv[2] /= 2;
+ fmv[3] /= 2;
+
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+ bmv[2] /= 2;
+ bmv[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)&fmv[0];
+ *du++ = *(uint *)&bmv[0];
+ if(usize) {
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ }
+
+ /* Second U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ if(usize) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)&fmv[0];
+ *dv++ = *(uint *)&bmv[0];
+ if(vsize) {
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ }
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ if(vsize) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderFrameinFrame
+// Description: inline function that sets hardware parameters for a Frame
+// encoded macroblock in a frame picture.
+***************************************************************************/
+static __inline__ void renderFrameinFrame(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[2];
+ short bmv[2];
+ /* gfxblock dword 1 */
+ uint dw1;
+
+ unsigned int ysize = y_frame_bytes[mb->coded_block_pattern];
+ unsigned int usize = u_frame_bytes[mb->coded_block_pattern];
+ unsigned int vsize = v_frame_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+ dw1 = type_table[mb->macroblock_type & 0xf] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+
+ bmv[0] = mb->PMV[0][1][1];
+ bmv[1] = mb->PMV[0][1][0];
+
+ /* Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (3<<28) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ PACK_CORR_DATA(dy,block_ptr,ysize);
+ block_ptr = (short *)((unsigned long)block_ptr + ysize);
+ /* End Y Blocks */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+ /* End U Block */
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+ /* End V Block */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderFrameinFrameDCT1
+// Description: inline function that sets hardware parameters for a Frame
+// encoded macroblock in a frame picture with DCT type 1.
+***************************************************************************/
+static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[4];
+ short bmv[4];
+
+ short * top_left_b = NULL;
+ short * top_right_b = NULL;
+ short * bottom_left_b = NULL;
+ short * bottom_right_b = NULL;
+
+ uint temp_bp = 0;
+
+ uint ysize = y_dct1_frame_bytes[mb->coded_block_pattern];
+ uint usize = u_frame_bytes[mb->coded_block_pattern];
+ uint vsize = v_frame_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+ uint dw1 = type_table[mb->macroblock_type & 0xf] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+
+ bmv[0] = mb->PMV[0][1][1];
+ bmv[1] = mb->PMV[0][1][0];
+
+ /*
+ It is easiest to find out what blocks are in need of reading first
+ rather than as we go.
+ */
+ top_left_b = &empty_block[0];
+ if(dw1 & (1<<27)) {
+ temp_bp |= (1<<25);
+ top_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ top_right_b = &empty_block[0];
+ if(dw1 & (1<<26)) {
+ temp_bp |= (1<<24);
+ top_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_left_b = &empty_block[0];
+ if(dw1 & (1<<25)) {
+ temp_bp |= (1<<27);
+ bottom_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_right_b = &empty_block[0];
+ if(dw1 & (1<<24)) {
+ temp_bp |= (1<<26);
+ bottom_right_b = block_ptr;
+ block_ptr += 64;
+ }
+ dw1 |= temp_bp;
+
+ /* Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (3<<28) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ if(dw1 & (1<<27)) {
+ PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
+ top_left_b = (short *)((unsigned long)top_left_b + 64);
+ bottom_left_b = (short *)((unsigned long)bottom_left_b + 64);
+ }
+ if(dw1 & (1<<26)) {
+ PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b);
+ top_right_b = (short *)((unsigned long)top_right_b + 64);
+ bottom_right_b = (short *)((unsigned long)bottom_right_b + 64);
+ }
+ if(dw1 & (1<<27)) {
+ PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
+ }
+ if(dw1 & (1<<26)) {
+ PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b);
+ }
+ /* End Y Block */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderDualPrimeinFrame
+// Description: inline function that sets hardware parameters for a Dual
+// Prime encoded macroblock in a frame picture with dct 1.
+***************************************************************************/
+static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[4];
+ short bmv[4];
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ uint y1size = y_first_field_bytes[mb->coded_block_pattern];
+ uint y2size = y_second_field_bytes[mb->coded_block_pattern];
+ uint usize = u_field_bytes[mb->coded_block_pattern];
+ uint vsize = v_field_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+
+ /*
+ Past Surface (map 0) is used for same parity prediction,
+ Future surface (map 1) is used for opposite.
+ */
+ dw1[0] = (((uint)mb->coded_block_pattern)<<22) |
+ 3<<12 | 2<<6 | 2<<3 | 3;
+ dw1[1] = (((mb->coded_block_pattern & 0x3) |
+ ((mb->coded_block_pattern & 0xc)<<2))<<22) |
+ 3<<12 | 3<<6 | 3<<3 | 2;
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = mb->PMV[1][0][1];
+ bmv[1] = mb->PMV[1][0][0];
+
+ fmv[2] = mb->PMV[0][0][1];
+ fmv[3] = mb->PMV[0][0][0];
+ bmv[2] = mb->PMV[1][1][1];
+ bmv[3] = mb->PMV[1][1][0];
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (y1size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;;
+ PACK_CORR_DATA(dy,block_ptr,y1size);
+ block_ptr = (short *)((unsigned long)block_ptr + y1size);
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (y2size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)&fmv[2];
+ *dy++ = *(uint *)&bmv[2];
+ PACK_CORR_DATA(dy,block_ptr,y2size);
+ block_ptr = (short *)((unsigned long)block_ptr + y2size);
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+
+ fmv[2] /= 2;
+ fmv[3] /= 2;
+ bmv[2] /= 2;
+ bmv[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ if(dw1[0] & (1<<23)) {
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ }
+
+ /* Second U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ if(dw1[1] & (1<<23)) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ if(dw1[0] & (1<<22)) {
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ }
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ if(dw1[1] & (1<<22)) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderDualPrimeinFrameDCT0
+// Description: inline function that sets hardware parameters for a Dual
+// Prime encoded macroblock in a frame picture with dct 0.
+***************************************************************************/
+static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,
+ short *block_ptr,
+ uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[4];
+ short bmv[4];
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ short * top_left_b = NULL;
+ short * top_right_b = NULL;
+ short * bottom_left_b = NULL;
+ short * bottom_right_b = NULL;
+
+ uint cbp = (uint)mb->coded_block_pattern;
+
+ uint ysize = y_dct0_field_bytes[cbp];
+ uint usize = u_field_bytes[cbp];
+ uint vsize = v_field_bytes[cbp];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+
+ /*
+ Past Surface (map 0) is used for same parity prediction,
+ Future surface (map 1) is used for opposite.
+ */
+ dw1[0] = ((cbp | ((cbp<<2) & 0x30))<<22) |
+ 3<<12 | 2<<6 | 2<<3 | 3;
+ dw1[1] = ((cbp | ((cbp<<2) & 0x30))<<22) |
+ 3<<12 | 3<<6 | 3<<3 | 2;
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = mb->PMV[1][0][1];
+ bmv[1] = mb->PMV[1][0][0];
+
+ fmv[2] = mb->PMV[0][0][1];
+ fmv[3] = mb->PMV[0][0][0];
+ bmv[2] = mb->PMV[1][1][1];
+ bmv[3] = mb->PMV[1][1][0];
+
+ /*
+ The i810 cannot use DCT0 directly with field motion, we have to
+ interlace the data for it. We use a zero block when the CBP has
+ one half of the to-be-interlaced data but not the other half.
+ */
+ top_left_b = &empty_block[0];
+ if(cbp & 0x20) {
+ top_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ top_right_b = &empty_block[0];
+ if(cbp & 0x10) {
+ top_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_left_b = &empty_block[0];
+ if(cbp & 0x8) {
+ bottom_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_right_b = &empty_block[0];
+ if(cbp & 0x4) {
+ bottom_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ if(cbp & 0x20) {
+ PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
+ }
+ if(cbp & 0x10) {
+ PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
+ }
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)&fmv[2];
+ *dy++ = *(uint *)&bmv[2];
+ if(cbp & 0x20) {
+ top_left_b = (short *)((unsigned long)top_left_b + 16);
+ bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
+ PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
+ }
+ if(cbp & 0x10) {
+ top_right_b = (short *)((unsigned long)top_right_b + 16);
+ bottom_right_b = (short *)((unsigned long)bottom_right_b + 16);
+ PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
+ }
+ /* End Y Blocks */
+
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+
+ fmv[2] /= 2;
+ fmv[3] /= 2;
+ bmv[2] /= 2;
+ bmv[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ if(cbp & (1<<23)) {
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ }
+
+ /* Second U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ if(cbp & (1<<23)) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ if(cbp & (1<<22)) {
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ }
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ if(cbp & (1<<22)) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+
+/***************************************************************************
+// Function: XvMCRenderSurface
+// Description: This function does the actual HWMC. Given a list of
+// macroblock structures it dispatched the hardware commands to execute
+// them. DMA buffer containing Y data are dispatched as they fill up
+// U and V DMA buffers are queued until all Y's are done. This minimizes
+// the context flipping and flushing required when switching between Y
+// U and V surfaces.
+***************************************************************************/
+#define UV_QUEUE 14
+Status XvMCRenderSurface(Display *display, XvMCContext *context,
+ unsigned int picture_structure,
+ XvMCSurface *target_surface,
+ XvMCSurface *past_surface,
+ XvMCSurface *future_surface,
+ unsigned int flags,
+ unsigned int num_macroblocks,
+ unsigned int first_macroblock,
+ XvMCMacroBlockArray *macroblock_array,
+ XvMCBlockArray *blocks) {
+ /* Dma Data Structures */
+ drmBufPtr pDMAy = NULL,pDMAu[UV_QUEUE],pDMAv[UV_QUEUE];
+ int u_index = 0,v_index = 0;
+ int dirty_context = 1;
+
+ /* Block Pointer */
+ short *block_ptr;
+ /* Current Macroblock Pointer */
+ XvMCMacroBlock *mb;
+
+ drm_i810_mc_t mc;
+ int i,j;
+ i810XvMCSurface *privTarget;
+ i810XvMCSurface *privFuture = NULL;
+ i810XvMCSurface *privPast = NULL;
+ i810XvMCContext *pI810XvMC;
+
+ /* DMA Pointers set to NULL */
+ uint *datay = NULL;
+ uint *datau = NULL;
+ uint *datav = NULL;
+
+
+ /* Check Parameters for validity */
+ if((target_surface == NULL) || (context == NULL) || (display == NULL)) {
+ printf("Error, Invalid Target,Context, or DIsplay!\n");
+ return BadValue;
+ }
+
+ if(num_macroblocks == 0) {return Success;}
+ if((macroblock_array == NULL) || (blocks == NULL)) {return BadValue;}
+ if(context->privData == NULL) {return BadValue;}
+ pI810XvMC = (i810XvMCContext *)context->privData;
+
+
+ if(target_surface->privData == NULL) {
+ printf("Error, Invalid Target Surface!\n");
+ return BadValue;
+ }
+ privTarget = (i810XvMCSurface *)target_surface->privData;
+
+ if(macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) {
+ printf("Error, Too many macroblocks requested for MB array size.\n");
+ return BadValue;
+ }
+
+ /* Test For YV12 Surface */
+ if(context->surface_type_id != FOURCC_YV12) {
+ printf("Error, HWMC only possible on YV12 Surfaces\n");
+ return BadValue;
+ }
+
+ /* P Frame Test */
+ if(past_surface == NULL) {
+ /* Just to avoid some ifs later. */
+ privPast = privTarget;
+ }
+ else {
+ if(past_surface->privData == NULL) {
+ printf("Error, Invalid Past Surface!\n");
+ return BadValue;
+ }
+ privPast = (i810XvMCSurface *)past_surface->privData;
+ }
+
+
+ /* B Frame Test */
+ if(future_surface == NULL) {
+ privFuture = privTarget;
+ if(pI810XvMC->dual_prime) {
+ privFuture = privPast;
+ /* I810 Specific flag for marking when dual prime is in use. */
+ flags |= 0x40000000;
+ }
+
+ /*
+ References are different for the Second Field Picture. The
+ i810 needs to know if it is the second field picture in a
+ P picture. We use a Private flag to mark this.
+ */
+ if(flags & XVMC_SECOND_FIELD) {
+ /* I810 Specific flag for marking second fields. */
+ flags |= 0x80000000;
+ }
+ }
+ else {
+ if((future_surface->privData == NULL) || (past_surface == NULL)) {
+ printf("Error, Invalid Future Surface or No Past Surface!\n");
+ return BadValue;
+ }
+ privFuture = (i810XvMCSurface *)future_surface->privData;
+
+ /*
+ Undo Second Field flag since the second field in B frames is just like
+ the first.
+ */
+ flags &= ~0x80000000;
+ }
+
+ /* Lock For DMA */
+ I810_LOCK(pI810XvMC,0);
+
+ for(i=first_macroblock; i<(num_macroblocks + first_macroblock); i++) {
+ /* Set up values needed for each macroblock */
+ mb = &macroblock_array->macro_blocks[i];
+ block_ptr = &(blocks->blocks[mb->index<<6]);
+
+ /* Lockup can happen if the coordinates are too far out of range */
+ if(mb->x > target_surface->width>>4) {
+ mb->x = 0;
+ }
+ if(mb->y > target_surface->height>>4) {
+ mb->y = 0;
+ }
+
+ /* If buffers are almost full dispatch them */
+ if(datay) {
+ pDMAy->used = (unsigned long)datay - (unsigned long)pDMAy->address;
+ if(pDMAy->used > 3520) {
+ if(dirty_context) {
+ dispatchYContext(privTarget,privPast,privFuture,pI810XvMC);
+ }
+ dirty_context = 0;
+ mc.idx = pDMAy->idx;
+ mc.used = pDMAy->used;
+ datay = NULL;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ } /* datay near full */
+ } /* if(datay) */
+ if(datau) {
+ pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address;
+ if(pDMAu[u_index]->used > 3904) {
+ u_index++;
+ datau = NULL;
+ if(u_index == UV_QUEUE) {
+ for(j=0; j<UV_QUEUE; j++) {
+ mc.idx = pDMAu[j]->idx;
+ mc.used = pDMAu[j]->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ }
+ u_index = 0;
+ dirty_context = 1;
+ } /* if(u_index == UV_QUEUE) */
+ } /* datau near full */
+ } /* if(datau) */
+ if(datav) {
+ pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address;
+ if(pDMAv[v_index]->used > 3904) {
+ v_index++;
+ datav = NULL;
+ if(v_index == UV_QUEUE) {
+ for(j=0; j<UV_QUEUE; j++) {
+ mc.idx = pDMAv[j]->idx;
+ mc.used = pDMAv[j]->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ }
+ v_index = 0;
+ dirty_context = 1;
+ } /* if(v_index == UV_QUEUE) */
+ } /* datav near full */
+ } /* if(datav) */
+
+ /* Allocate buffers if this is the first loop,or if we just dispatched */
+ if(datay == NULL) {
+ pDMAy = i810_get_free_buffer(pI810XvMC);
+ datay = pDMAy->address;
+ }/* if(datay == NULL) */
+ if(datau == NULL) {
+ pDMAu[u_index] = i810_get_free_buffer(pI810XvMC);
+ datau = pDMAu[u_index]->address;
+ if(u_index == 0) {
+ *datau++ = CMD_FLUSH;
+ *datau++ = BOOLEAN_ENA_2;
+ *datau++ = CMD_FLUSH;
+ *datau++ = DEST_BUFFER_INFO;
+ *datau++ = privTarget->dbi1u;
+ *datau++ = DEST_BUFFER_VAR;
+ *datau++ = privTarget->dbv1;
+ /* Past Surface */
+ *datau++ = CMD_MAP_INFO;
+ *datau++ = privPast->mi1u;
+ *datau++ = privPast->mi2u;
+ *datau++ = privPast->mi3u;
+ /* Future Surface */
+ *datau++ = CMD_MAP_INFO;
+ *datau++ = privFuture->mi1u | 0x1<<28;
+ *datau++ = privFuture->mi2u;
+ *datau++ = privFuture->mi3u;
+ }
+ } /* if(datau == NULL) */
+ if(datav == NULL) {
+ pDMAv[v_index] = i810_get_free_buffer(pI810XvMC);
+ datav = pDMAv[v_index]->address;
+ if(v_index == 0) {
+ *datav++ = CMD_FLUSH;
+ *datav++ = BOOLEAN_ENA_2;
+ *datav++ = CMD_FLUSH;
+ *datav++ = DEST_BUFFER_INFO;
+ *datav++ = privTarget->dbi1v;
+ *datav++ = DEST_BUFFER_VAR;
+ *datav++ = privTarget->dbv1;
+ /* Past Surface */
+ *datav++ = CMD_MAP_INFO;
+ *datav++ = privPast->mi1v;
+ *datav++ = privPast->mi2v;
+ *datav++ = privPast->mi3v;
+ /* Future Surface */
+ *datav++ = CMD_MAP_INFO;
+ *datav++ = privFuture->mi1v | 0x1<<28;
+ *datav++ = privFuture->mi2v;
+ *datav++ = privFuture->mi3v;
+ }
+ }/* if(datav == NULL) */
+
+ /* Catch no pattern case */
+ if(!(mb->macroblock_type & 0x8)) {
+ mb->coded_block_pattern = 0;
+ }
+
+
+ if(mb->motion_type == XVMC_PREDICTION_DUAL_PRIME) {
+ /*
+ By default the maps will not be set up for dual
+ prime. We have to change them.
+ */
+ if(!pI810XvMC->dual_prime) {
+ pI810XvMC->dual_prime = 1;
+ privFuture = privPast;
+ /* Y */
+ *datay++ = CMD_MAP_INFO;
+ *datay++ = privFuture->mi1y | 0x1<<28;
+ *datay++ = privFuture->mi2y;
+ *datay++ = privFuture->mi3y;
+ /* U */
+ *datau++ = CMD_MAP_INFO;
+ *datau++ = privFuture->mi1u | 0x1<<28;
+ *datau++ = privFuture->mi2u;
+ *datau++ = privFuture->mi3u;
+ /* V */
+ *datav++ = CMD_MAP_INFO;
+ *datav++ = privFuture->mi1v | 0x1<<28;
+ *datav++ = privFuture->mi2v;
+ *datav++ = privFuture->mi3v;
+ }
+ }
+ if((pI810XvMC->dual_prime) &&
+ (mb->motion_type != XVMC_PREDICTION_DUAL_PRIME)) {
+ pI810XvMC->dual_prime = 0;
+ privFuture = privTarget;
+ /* Y */
+ *datay++ = CMD_MAP_INFO;
+ *datay++ = privFuture->mi1y | 0x1<<28;
+ *datay++ = privFuture->mi2y;
+ *datay++ = privFuture->mi3y;
+ /* U */
+ *datau++ = CMD_MAP_INFO;
+ *datau++ = privFuture->mi1u | 0x1<<28;
+ *datau++ = privFuture->mi2u;
+ *datau++ = privFuture->mi3u;
+ /* V */
+ *datav++ = CMD_MAP_INFO;
+ *datav++ = privFuture->mi1v | 0x1<<28;
+ *datav++ = privFuture->mi2v;
+ *datav++ = privFuture->mi3v;
+ }
+
+
+ /* Frame Picture */
+ if((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
+ /* Intra Blocks */
+ if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
+ if(mb->dct_type) {
+ renderIntrainFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ }
+ renderIntrainFrame(&datay,&datau,&datav,mb,block_ptr);
+ continue;
+ }
+ switch((mb->motion_type & 0x3) | (mb->dct_type<<2)) {
+ case 0x2: /* Frame DCT0 */
+ renderFrameinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x5: /* Field DCT1 */
+ renderFieldinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x6: /* Frame DCT1 */
+ renderFrameinFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x1: /* Field DCT0 */
+ renderFieldinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x3: /* Dual Prime DCT0 */
+ renderDualPrimeinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x7: /* Dual Prime DCT1 */
+ renderDualPrimeinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ default: /* No Motion Type */
+ renderError();
+ continue;
+ } /* Switch */
+ } /* Frame Picture */
+
+ /* Field Pictures */
+ if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
+ renderIntrainField(&datay,&datau,&datav,mb,block_ptr,picture_structure);
+ continue;
+ }
+ switch(mb->motion_type & 0x3) {
+ case 0x1: /* Field Motion */
+ renderFieldinField(&datay,&datau,&datav,mb,block_ptr,picture_structure,
+ flags);
+ continue;
+ case 0x2: /* 16x8 Motion */
+ render16x8inField(&datay,&datau,&datav,mb,block_ptr,picture_structure,
+ flags);
+ continue;
+ case 0x3: /* Dual Prime */
+ renderDualPrimeinField(&datay,&datau,&datav,mb,block_ptr,
+ picture_structure,flags);
+ continue;
+ default: /* No Motion Type */
+ renderError();
+ continue;
+ }
+ continue;
+
+ } /* for each Macroblock */
+
+ /* Dispatch remaining DMA buffers */
+ if(dirty_context) {
+ dispatchYContext(privTarget,privPast,privFuture,pI810XvMC);
+ }
+ mc.idx = pDMAy->idx;
+ mc.used = (unsigned long)datay - (unsigned long)pDMAy->address;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+
+ pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address;
+ for(j=0; j<=u_index; j++) {
+ mc.idx = pDMAu[j]->idx;
+ mc.used = pDMAu[j]->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ }
+ pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address;
+ for(j=0; j<=v_index; j++) {
+ mc.idx = pDMAv[j]->idx;
+ mc.used = pDMAv[j]->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ }
+
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCPutSurface
+// Description:
+// Arguments:
+// display: Connection to X server
+// surface: Surface to be displayed
+// draw: X Drawable on which to display the surface
+// srcx: X coordinate of the top left corner of the region to be
+// displayed within the surface.
+// srcy: Y coordinate of the top left corner of the region to be
+// displayed within the surface.
+// srcw: Width of the region to be displayed.
+// srch: Height of the region to be displayed.
+// destx: X cordinate of the top left corner of the destination region
+// in the drawable coordinates.
+// desty: Y cordinate of the top left corner of the destination region
+// in the drawable coordinates.
+// destw: Width of the destination region.
+// desth: Height of the destination region.
+// flags: One or more of the following.
+// XVMC_TOP_FIELD - Display only the Top field of the surface.
+// XVMC_BOTTOM_FIELD - Display only the Bottom Field of the surface.
+// XVMC_FRAME_PICTURE - Display both fields or frame.
+//
+// Info: Portions of this function derived from i810_video.c (XFree86)
+//
+// This function is organized so that we wait as long as possible before
+// touching the overlay registers. Since we don't know that the last
+// flip has happened yet we want to give the overlay as long as
+// possible to catch up before we have to check on its progress. This
+// makes it unlikely that we have to wait on the last flip.
+***************************************************************************/
+Status XvMCPutSurface(Display *display,XvMCSurface *surface,
+ Drawable draw, short srcx, short srcy,
+ unsigned short srcw, unsigned short srch,
+ short destx, short desty,
+ unsigned short destw, unsigned short desth,
+ int flags) {
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSurface *pI810Surface;
+ i810OverlayRecPtr pORegs;
+ unsigned int ysrc_offset,uvsrc_offset;
+ Box extents;
+ uint window_width,window_height;
+ unsigned int xscaleInt = 0,xscaleFract = 0,yscaleInt = 0,yscaleFract = 0;
+ unsigned int xscaleFractUV = 0,xscaleIntUV = 0,yscaleFractUV = 0;
+ unsigned int yscaleIntUV = 0,yPitch = 0,uvPitch = 0;
+ unsigned int ovcmd = 0;
+ uint d;
+ double xscale,yscale;
+ int diff;
+ int clipped_srcx, clipped_srcy, clipped_destx, clipped_desty;
+ int clipped_srcw, clipped_srch, clipped_destw, clipped_desth;
+ uint x1,y1,root_width,root_height;
+ int x2 = 0, y2 = 0,unused;
+ uint nChilds;
+ int stat;
+ Window win,root,parent,*pChilds;
+
+
+ if((display == NULL) || (surface == NULL)) {
+ return BadValue;
+ }
+
+ if(surface->privData == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+ pI810Surface = (i810XvMCSurface *)surface->privData;
+ pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
+ pORegs = (i810OverlayRecPtr)pI810XvMC->oregs;
+
+
+ switch(surface->surface_type_id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ yPitch = (srcw + 7) & ~7;
+ uvPitch = ((srcw>>1) + 7) & ~7;
+ if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) {
+ srch = srch>>1;
+ }
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ /* FIXME: Non Planar not fully implemented. */
+ return BadValue;
+ yPitch = ((srcw + 7) & ~7) << 1;
+ break;
+ }/* switch(surface->surface_type_id) */
+
+ /*
+ FIXME: This should be using the DRI's clip rect but that isn't
+ all hooked up yet. This has some latency but we get by.
+ */
+ win = draw;
+ XQueryTree(display,win,&root,&parent,&pChilds,&nChilds);
+ if(nChilds) XFree(pChilds);
+ XGetGeometry(display,win, &root, &x2, &y2, &window_width,
+ &window_height, &d, &d);
+ x1 = x2;
+ y1 = y2;
+ win = parent;
+ do {
+ XQueryTree(display,win,&root,&parent,&pChilds,&nChilds);
+ if(nChilds) XFree(pChilds);
+ XGetGeometry(display,win, &root, &x2, &y2, &d, &d, &d, &d);
+ x1 += x2;
+ y1 += y2;
+ win = parent;
+ }while(win != root);
+ XGetGeometry(display,root, &root, &unused, &unused,
+ &root_width, &root_height, &d, &d);
+
+ /* Left edge of Video window clipped to screen */
+ extents.x1 = 0;
+ if(x1 > extents.x1) {
+ extents.x1 = x1;
+ }
+ /* Right edge of Video window clipped to screen */
+ extents.x2 = root_width;
+ if(extents.x2 > (x1 + window_width)) {
+ extents.x2 = x1 + window_width;
+ }
+ /* Top edge of Video window clipped to screen */
+ extents.y1 = 0;
+ if(y1 > extents.y1) {
+ extents.y1 = y1;
+ }
+ /* Bottom edge of Video window clipped to screen */
+ extents.y2 = root_height;
+ if(extents.y2 > (y1 + window_height)) {
+ extents.y2 = y1 + window_height;
+ }
+
+ /*
+ Clipping is more difficult than is seems. We need to keep the
+ scaling factors even if the destination window needs to be clipped.
+ We clip the destination window first then apply a scaled version
+ to the source window.
+ */
+
+ /* Put destination coords in screen coords */
+ destx += x1;
+ desty += y1;
+
+ /* Scale factors requested */
+ xscale = (double)srcw / (double)destw;
+ yscale = (double)srch / (double)desth;
+
+ /*
+ If destination window needs to be clipped we actually adjust both
+ the src and dest window so as to keep the scaling that was requested
+ */
+ clipped_srcx = srcx;
+ clipped_srcy = srcy;
+ clipped_destx = destx;
+ clipped_desty = desty;
+ clipped_srcw = srcw;
+ clipped_srch = srch;
+ clipped_destw = destw;
+ clipped_desth = desth;
+
+ /* Clip to the source surface boundaries */
+ if(clipped_srcx < 0) {
+ clipped_destx += (0 - clipped_srcx) / xscale;
+ clipped_srcw -= clipped_srcx;
+ clipped_destw -= clipped_srcx / xscale;
+ clipped_srcx = 0;
+ }
+ if((clipped_srcw + clipped_srcx) > surface->width) {
+ clipped_srcw = surface->width - clipped_srcx;
+ clipped_destw -= (clipped_srcw - srcw) / xscale;
+ }
+ if(clipped_srcy < 0) {
+ clipped_desty += (0 - clipped_srcy) / yscale;
+ clipped_srch -= clipped_srcy;
+ clipped_desth -= clipped_srcy / yscale;
+ clipped_srcy = 0;
+ }
+ if((clipped_srch + clipped_srcy) > surface->height) {
+ clipped_srch = surface->height - clipped_srcy;
+ clipped_desth -= (clipped_srch - srch) / yscale;
+ }
+
+ /* Clip to the extents */
+ if(clipped_destx < extents.x1) {
+ diff = extents.x1 - clipped_destx;
+ clipped_srcx += diff * xscale;
+ clipped_srcw -= diff * xscale;
+ clipped_destw -= diff;
+ clipped_destx = extents.x1;
+ }
+
+ diff = (clipped_destx + clipped_destw) - extents.x2;
+ if(diff > 0) {
+ clipped_destw -= diff;
+ clipped_srcw -= diff * xscale;
+ }
+
+ if(clipped_desty < extents.y1) {
+ diff = extents.y1 - clipped_desty;
+ clipped_srcy += diff * yscale;
+ clipped_srch -= diff * yscale;
+ clipped_desth -= diff;
+ clipped_desty = 0;
+ }
+
+ diff = (clipped_desty + clipped_desth) - extents.y2;
+ if(diff > 0) {
+ clipped_desth -= diff;
+ clipped_srch -= diff * yscale;
+ }
+
+ /* If the whole window is clipped turn off the overlay */
+ if((clipped_destx + clipped_destw < extents.x1) ||
+ (clipped_desty + clipped_desth < extents.y1) ||
+ (clipped_destx > extents.x2) ||
+ (clipped_desty > extents.y2)) {
+ return XvMCHideSurface(display, surface);
+ }
+
+ /*
+ Adjust the source offset width and height according to the clipped
+ destination window.
+ */
+ ysrc_offset = ((clipped_srcx + 1) & ~1) +
+ ((clipped_srcy + 1) & ~1) * (1<<pI810Surface->pitch);
+ uvsrc_offset = (clipped_srcx>>1) +
+ (clipped_srcy>>1) * (1<<(pI810Surface->pitch - 1));
+
+ /*
+ Initially, YCbCr and Overlay Enable and
+ vertical chrominance up interpolation and horozontal chrominance
+ up interpolation
+ */
+ ovcmd = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST | OVERLAY_ENABLE;
+
+ if ((clipped_destw != clipped_srcw) ||
+ (clipped_desth != clipped_srch)) {
+ xscaleInt = (clipped_srcw / clipped_destw) & 0x3;
+ xscaleFract = (clipped_srcw << 12) / clipped_destw;
+ yscaleInt = (clipped_srch / clipped_desth) & 0x3;
+ yscaleFract = (clipped_srch << 12) / clipped_desth;
+
+ if (clipped_destw > clipped_srcw) {
+ /* horizontal up-scaling */
+ ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER;
+ ovcmd |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION);
+ }
+
+ if (clipped_desth > clipped_srch) {
+ /* vertical up-scaling */
+ ovcmd &= ~VERTICAL_CHROMINANCE_FILTER;
+ ovcmd &= ~VERTICAL_LUMINANCE_FILTER;
+ ovcmd |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION);
+ }
+
+ if (clipped_destw < clipped_srcw) {
+ /* horizontal down-scaling */
+ ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER;
+ ovcmd |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION);
+ }
+
+ if (clipped_desth < clipped_srch) {
+ /* vertical down-scaling */
+ ovcmd &= ~VERTICAL_CHROMINANCE_FILTER;
+ ovcmd &= ~VERTICAL_LUMINANCE_FILTER;
+ ovcmd |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION);
+ }
+
+ /* now calculate the UV scaling factor */
+ if (xscaleFract) {
+ xscaleFractUV = xscaleFract >> MINUV_SCALE;
+ ovcmd &= ~HC_DOWN_INTERPOLATION;
+ ovcmd |= HC_UP_INTERPOLATION;
+ }
+
+ if (xscaleInt) {
+ xscaleIntUV = xscaleInt >> MINUV_SCALE;
+ if (xscaleIntUV) {
+ ovcmd &= ~HC_UP_INTERPOLATION;
+ }
+ }
+
+ if (yscaleFract) {
+ yscaleFractUV = yscaleFract >> MINUV_SCALE;
+ ovcmd &= ~VC_DOWN_INTERPOLATION;
+ ovcmd |= VC_UP_INTERPOLATION;
+ }
+
+ if (yscaleInt) {
+ yscaleIntUV = yscaleInt >> MINUV_SCALE;
+ if (yscaleIntUV) {
+ ovcmd &= ~VC_UP_INTERPOLATION;
+ ovcmd |= VC_DOWN_INTERPOLATION;
+ }
+ }
+
+ }/* if((destw != srcw) || (desth != srch)) */
+
+ /* Lock the DRM */
+ I810_LOCK(pI810XvMC,0);
+
+ /* Block until rendering on this surface is finished */
+ stat = XVMC_RENDERING;
+ while(stat & XVMC_RENDERING) {
+ XvMCGetSurfaceStatus(display,surface,&stat);
+ }
+ /* Block until the last flip is finished */
+ if(pI810XvMC->last_flip) {
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+ }
+
+ pI810XvMC->current = !pI810XvMC->current;
+ pORegs->OV0CMD = ovcmd;
+
+ if ((clipped_destw != clipped_srcw) ||
+ (clipped_desth != clipped_srch)) {
+ pORegs->YRGBSCALE = (xscaleInt << 15) |
+ ((xscaleFract & 0xFFF) << 3) | (yscaleInt) |
+ ((yscaleFract & 0xFFF) << 20);
+
+ pORegs->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) |
+ ((yscaleFractUV & 0xFFF) << 20);
+ }
+ else {
+ /* Normal 1:1 scaling */
+ pORegs->YRGBSCALE = 0x80004000;
+ pORegs->UVSCALE = 0x80004000;
+ }
+
+ pORegs->SHEIGHT = clipped_srch | (clipped_srch << 15);
+ pORegs->DWINPOS = (clipped_desty << 16) | clipped_destx;
+ pORegs->DWINSZ = ((clipped_desth<< 16) | (clipped_destw));
+
+ /* Attributes */
+ pORegs->OV0CLRC0 = ((pI810XvMC->contrast & 0x1ff)<<8) |
+ (pI810XvMC->brightness & 0xff);
+ pORegs->OV0CLRC1 = (pI810XvMC->saturation & 0x3ff);
+
+ /* Destination Colorkey Setup */
+ pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey);
+
+ /* buffer locations, add the offset from the clipping */
+ if(pI810XvMC->current) {
+ pORegs->OBUF_1Y = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[0] + ysrc_offset;
+ pORegs->OBUF_1V = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[2] + uvsrc_offset;
+ pORegs->OBUF_1U = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[1] + uvsrc_offset;
+ }
+ else {
+ pORegs->OBUF_0Y = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[0] + ysrc_offset;
+ pORegs->OBUF_0V = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[2] + uvsrc_offset;
+ pORegs->OBUF_0U = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[1] + uvsrc_offset;
+ }
+
+ switch(surface->surface_type_id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ pORegs->SWID = (uvPitch << 16) | yPitch;
+ pORegs->SWIDQW = (uvPitch << 13) | (yPitch >> 3);
+ pORegs->OV0STRIDE = (1<<pI810Surface->pitch) |
+ ((1<<pI810Surface->pitch) << 15);
+ pORegs->OV0CMD &= ~SOURCE_FORMAT;
+ pORegs->OV0CMD |= YUV_420;
+ if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) {
+ /* Top Field Only */
+ if(flags & XVMC_TOP_FIELD) {
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
+ BUFFER1_FIELD0);
+ }
+ else {
+ pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
+ BUFFER0_FIELD0);
+ }
+ pORegs->YRGB_VPH = 1<<15 | 1<<31;
+ pORegs->UV_VPH = 3<<14 | 3<<30;
+ pORegs->INIT_PH = 0x06 | 0x18;
+ }
+ /* Bottom Field Only */
+ else {
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
+ BUFFER1_FIELD1);
+ }
+ else {
+ pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
+ BUFFER0_FIELD1);
+ }
+ pORegs->YRGB_VPH = 0;
+ pORegs->UV_VPH = 7<<29 | 7<<13;
+ pORegs->INIT_PH = 0x06;
+ }
+ }
+ /* Frame Picture */
+ else {
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pORegs->OV0CMD |= BUFFER0_FIELD0;
+ }
+ pORegs->YRGB_VPH = 0;
+ pORegs->UV_VPH = 0;
+ pORegs->INIT_PH = 0;
+ }
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ pORegs->SWID = srcw;
+ pORegs->SWIDQW = srcw >> 3;
+ pORegs->OV0STRIDE = pI810Surface->pitch;
+ pORegs->OV0CMD &= ~SOURCE_FORMAT;
+ pORegs->OV0CMD |= YUV_422;
+ pORegs->OV0CMD &= ~OV_BYTE_ORDER;
+ if (surface->surface_type_id == FOURCC_UYVY) {
+ pORegs->OV0CMD |= Y_SWAP;
+ }
+
+ pORegs->OV0CMD &= ~BUFFER_AND_FIELD;
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pORegs->OV0CMD |= BUFFER0_FIELD0;
+ }
+
+ break;
+ } /* switch(surface->surface_type_id) */
+
+
+
+ OVERLAY_FLIP(pI810XvMC);
+
+ /*
+ The Overlay only flips when it knows you changed
+ something. So the first time change stuff while it
+ is watching to be sure.
+ */
+ if(!pI810XvMC->last_flip) {
+ pORegs->OV0CMD &= ~0x4;
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pORegs->OV0CMD |= BUFFER0_FIELD0;
+ }
+ }
+ pI810Surface->last_flip = ++pI810XvMC->last_flip;
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCSyncSurface
+// Arguments:
+// display - Connection to the X server
+// surface - The surface to synchronize
+// Info:
+// Returns: Status
+***************************************************************************/
+Status XvMCSyncSurface(Display *display,XvMCSurface *surface) {
+ Status ret;
+ int stat=0;
+ /*
+ FIXME: Perhaps a timer here to prevent lockup?
+ FIXME: Perhaps a usleep to not be busy waiting?
+ */
+ do {
+ ret = XvMCGetSurfaceStatus(display,surface,&stat);
+ }while(!ret && (stat & XVMC_RENDERING));
+ return ret;
+}
+
+/***************************************************************************
+// Function: XvMCFlushSurface
+// Description:
+// This function commits pending rendering requests to ensure that they
+// wll be completed in a finite amount of time.
+// Arguments:
+// display - Connection to X server
+// surface - Surface to flush
+// Info:
+// This command is a noop for i810 becuase we always dispatch buffers in
+// render. There is little gain to be had with 4k buffers.
+// Returns: Status
+***************************************************************************/
+Status XvMCFlushSurface(Display * display, XvMCSurface *surface) {
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCGetSurfaceStatus
+// Description:
+// Arguments:
+// display: connection to X server
+// surface: The surface to query
+// stat: One of the Following
+// XVMC_RENDERING - The last XvMCRenderSurface command has not
+// completed.
+// XVMC_DISPLAYING - The surface is currently being displayed or a
+// display is pending.
+***************************************************************************/
+Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface,
+ int *stat) {
+ i810XvMCSurface *privSurface;
+ i810XvMCContext *pI810XvMC;
+ int temp;
+
+ if((display == NULL) || (surface == NULL) || (stat == NULL)) {
+ return BadValue;
+ }
+ if(surface->privData == NULL) {
+ return BadValue;
+ }
+ *stat = 0;
+ privSurface = surface->privData;
+
+ pI810XvMC = privSurface->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ I810_LOCK(pI810XvMC,0);
+ if(privSurface->last_flip) {
+ /* This can not happen */
+ if(pI810XvMC->last_flip < privSurface->last_flip) {
+ printf("Error: Context last flip is less than surface last flip.\n");
+ return BadValue;
+ }
+ /*
+ If the context has 2 or more flips after this surface it
+ cannot be displaying. Don't bother to check.
+ */
+ if(!(pI810XvMC->last_flip > (privSurface->last_flip + 1))) {
+ /*
+ If this surface was the last flipped it is either displaying
+ or about to be so don't bother checking.
+ */
+ if(pI810XvMC->last_flip == privSurface->last_flip) {
+ *stat |= XVMC_DISPLAYING;
+ }
+ else {
+ /*
+ In this case there has been one more flip since our surface's
+ but we need to check if it is finished or not.
+ */
+ temp = GET_FSTATUS(pI810XvMC);
+ if(((temp & (1<<20))>>20) != pI810XvMC->current) {
+ *stat |= XVMC_DISPLAYING;
+ }
+ }
+ }
+ }
+
+ if(privSurface->last_render &&
+ (privSurface->last_render > GET_RSTATUS(pI810XvMC))) {
+ *stat |= XVMC_RENDERING;
+ }
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+}
+
+/***************************************************************************
+//
+// Surface manipulation functions
+//
+***************************************************************************/
+
+/***************************************************************************
+// Function: XvMCHideSurface
+// Description: Stops the display of a surface.
+// Arguments:
+// display - Connection to the X server.
+// surface - surface to be hidden.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCHideSurface(Display *display, XvMCSurface *surface) {
+ i810XvMCSurface *pI810Surface;
+ i810XvMCContext *pI810XvMC;
+ int ss, xx;
+
+ /* Did we get a good display and surface passed into us? */
+ if(display == NULL) {
+ return BadValue;
+ }
+
+ if(surface == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ XvMCSyncSurface(display, surface);
+
+ /* Get surface private data pointer */
+ if(surface->privData == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+ pI810Surface = (i810XvMCSurface *)surface->privData;
+
+ /*
+ Get the status of the surface, if it is not currently displayed
+ we don't need to worry about it.
+ */
+ if((xx = XvMCGetSurfaceStatus(display, surface, &ss)) != Success) {
+ return xx;
+ }
+ if(! (ss & XVMC_DISPLAYING)) {
+ return Success;
+ }
+
+ /* Get the associated context pointer */
+ pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ if(pI810XvMC->last_flip) {
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+
+ /* Make sure last flip is done */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+
+ /* Set the registers to turn the overlay off */
+ pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST;
+ pI810XvMC->current = !pI810XvMC->current;
+ if(pI810XvMC->current == 1) {
+ pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0;
+ }
+ OVERLAY_FLIP(pI810XvMC);
+ /*
+ Increment the context flip but not the surface. This way no
+ surface has the last flip #.
+ */
+ pI810XvMC->last_flip++;
+
+
+ /* Now wait until the hardware reads the registers and makes the change. */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current)
+
+ I810_UNLOCK(pI810XvMC);
+ }
+
+ return Success;
+}
+
+
+
+
+/***************************************************************************
+//
+// Functions that deal with subpictures
+//
+***************************************************************************/
+
+
+
+/***************************************************************************
+// Function: XvMCCreateSubpicture
+// Description: This creates a subpicture by filling out the XvMCSubpicture
+// structure passed to it and returning Success.
+// Arguments:
+// display - Connection to the X server.
+// context - The context to create the subpicture for.
+// subpicture - Pre-allocated XvMCSubpicture structure to be filled in.
+// width - of subpicture
+// height - of subpicture
+// xvimage_id - The id describing the XvImage format.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCCreateSubpicture(Display *display, XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ unsigned short width, unsigned short height,
+ int xvimage_id) {
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSubpicture *pI810Subpicture;
+ int priv_count;
+ uint *priv_data;
+ Status ret;
+
+ if((subpicture == NULL) || (context == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ pI810XvMC = (i810XvMCContext *)context->privData;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+
+
+ subpicture->context_id = context->context_id;
+ subpicture->xvimage_id = xvimage_id;
+
+ /* These need to be checked to make sure they are not too big! */
+ subpicture->width = width;
+ subpicture->height = height;
+
+ subpicture->privData =
+ (i810XvMCSubpicture *)malloc(sizeof(i810XvMCSubpicture));
+
+ if(!subpicture->privData) {
+ return BadAlloc;
+ }
+ pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+
+ if((ret = _xvmc_create_subpicture(display, context, subpicture,
+ &priv_count, &priv_data))) {
+ printf("Unable to create XvMCSubpicture.\n");
+ return ret;
+ }
+
+ if(priv_count != 1) {
+ printf("_xvmc_create_subpicture() returned incorrect data size.\n");
+ printf("Expected 1 got %d\n",priv_count);
+ free(priv_data);
+ return BadAlloc;
+ }
+ /* Data == Client Address, offset == Physical address offset */
+ pI810Subpicture->data = pI810XvMC->surfaces.address;
+ pI810Subpicture->offset = pI810XvMC->surfaces.offset;
+
+ /* Initialize private values */
+ pI810Subpicture->privContext = pI810XvMC;
+
+ pI810Subpicture->last_render = 0;
+ pI810Subpicture->last_flip = 0;
+
+ /* Based on the xvimage_id we will need to set the other values */
+ subpicture->num_palette_entries = 16;
+ subpicture->entry_bytes = 3;
+ strcpy(subpicture->component_order,"YUV");
+
+ /*
+ i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch
+ and the Tiler need 512k aligned surfaces, basically we are
+ stuck with fixed memory with pitch 1024.
+ */
+ pI810Subpicture->pitch = 10;
+
+ /*
+ offsets[0] == offset into the map described by either
+ address (Client memeory address) or offset (physical offset from fb base)
+ */
+ pI810Subpicture->offsets[0] = priv_data[0];
+ if(((unsigned long)pI810Subpicture->data + pI810Subpicture->offsets[0]) & 4095) {
+ printf("XvMCCreateSubpicture: Subpicture offset 0 is not 4096 aligned\n");
+ }
+
+ /* Free data returned from xvmc_create_surface */
+ free(priv_data);
+
+ /* Clear the surface to 0 */
+ memset((void *)((unsigned long)pI810Subpicture->data + (unsigned long)pI810Subpicture->offsets[0]),
+ 0, ((1<<pI810Subpicture->pitch) * subpicture->height));
+
+ switch(subpicture->xvimage_id) {
+ case FOURCC_IA44:
+ case FOURCC_AI44:
+ /* Destination buffer info command */
+ pI810Subpicture->dbi1 = ((((unsigned int)pI810Subpicture->offset +
+ pI810Subpicture->offsets[0]) & ~0xfc000fff) |
+ (pI810Subpicture->pitch - 9));
+
+ /* Destination buffer variables command */
+ pI810Subpicture->dbv1 = (0x8<<20) | (0x8<<16);
+
+ /* Map info command */
+ pI810Subpicture->mi1 = (0x0<<24) | (3<<21) | (1<<9) |
+ (pI810Subpicture->pitch - 3);
+
+ pI810Subpicture->mi2 = (((unsigned int)subpicture->height - 1)<<16) |
+ ((unsigned int)subpicture->width - 1);
+
+ pI810Subpicture->mi3 = ((unsigned int)pI810Subpicture->offset +
+ pI810Subpicture->offsets[0]) & ~0xfc00000f;
+ break;
+ default:
+ free(subpicture->privData);
+ return BadMatch;
+ }
+
+ pI810XvMC->ref++;
+ return Success;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCClearSubpicture
+// Description: Clear the area of the given subpicture to "color".
+// structure passed to it and returning Success.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpicture to clear.
+// x, y, width, height - rectangle in the subpicture to clear.
+// color - The data to file the rectangle with.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCClearSubpicture(Display *display, XvMCSubpicture *subpicture,
+ short x, short y,
+ unsigned short width, unsigned short height,
+ unsigned int color) {
+
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSubpicture *pI810Subpicture;
+ int i;
+
+ if((subpicture == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ if(!subpicture->privData) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if((x < 0) || (x + width > subpicture->width)) {
+ return BadValue;
+ }
+
+ if((y < 0) || (y + height > subpicture->height)) {
+ return BadValue;
+ }
+
+ for(i=y; i<y + height; i++) {
+ memset((void *)((unsigned long)pI810Subpicture->data +
+ (unsigned long)pI810Subpicture->offsets[0] + x +
+ (1<<pI810Subpicture->pitch) * i),(char)color,width);
+ }
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCompositeSubpicture
+// Description: Composite the XvImae on the subpicture. This composit uses
+// non-premultiplied alpha. Destination alpha is utilized
+// except for with indexed subpictures. Indexed subpictures
+// use a simple "replace".
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpicture to clear.
+// image - the XvImage to be used as the source of the composite.
+// srcx, srcy, width, height - The rectangle from the image to be used.
+// dstx, dsty - location in the subpicture to composite the source.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCCompositeSubpicture(Display *display, XvMCSubpicture *subpicture,
+ XvImage *image,
+ short srcx, short srcy,
+ unsigned short width, unsigned short height,
+ short dstx, short dsty) {
+
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSubpicture *pI810Subpicture;
+ int i;
+
+ if((subpicture == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ if(!subpicture->privData) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if((srcx < 0) || (srcx + width > image->width)) {
+ return BadValue;
+ }
+
+ if((dstx < 0) || (dstx + width > subpicture->width)) {
+ return BadValue;
+ }
+
+ if((srcy < 0) || (srcy + height > image->height)) {
+ return BadValue;
+ }
+
+ if((dsty < 0) || (dsty + height > subpicture->height)) {
+ return BadValue;
+ }
+
+ for(i=0; i<height; i++) {
+ memcpy((void *)((unsigned long)pI810Subpicture->data +
+ (unsigned long)pI810Subpicture->offsets[0] + dstx +
+ (1<<pI810Subpicture->pitch) * (i + dsty)),
+ (void *)((unsigned long)image->data +
+ (unsigned long)image->offsets[0] + srcx +
+ image->pitches[0] * (i + srcy))
+ ,width);
+ }
+
+ return Success;
+
+}
+
+
+/***************************************************************************
+// Function: XvMCDestroySubpicture
+// Description: Destroys the specified subpicture.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpicture to be destroyed.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture) {
+
+ i810XvMCSubpicture *pI810Subpicture;
+ i810XvMCContext *pI810XvMC;
+
+ if((display == NULL) || (subpicture == NULL)) {
+ return BadValue;
+ }
+ if(!subpicture->privData) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
+ if(!pI810XvMC) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+
+ if(pI810Subpicture->last_render) {
+ XvMCSyncSubpicture(display,subpicture);
+ }
+
+ _xvmc_destroy_subpicture(display,subpicture);
+
+ i810_free_privContext(pI810XvMC);
+
+ free(pI810Subpicture);
+ subpicture->privData = NULL;
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCSetSubpicturePalette
+// Description: Set the subpictures palette
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpiture to set palette for.
+// palette - A pointer to an array holding the palette data. The array
+// is num_palette_entries * entry_bytes in size.
+// Returns: Status
+***************************************************************************/
+
+Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture,
+ unsigned char *palette) {
+ i810XvMCSubpicture *privSubpicture;
+ int i,j;
+
+ if((display == NULL) || (subpicture == NULL)) {
+ return BadValue;
+ }
+ if(subpicture->privData == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ j=0;
+ for(i=0; i<16; i++) {
+ privSubpicture->palette[0][i] = palette[j++];
+ privSubpicture->palette[1][i] = palette[j++];
+ privSubpicture->palette[2][i] = palette[j++];
+ }
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCBlendSubpicture
+// Description:
+// The behavior of this function is different depending on whether
+// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
+// i810 only support frontend behavior.
+//
+// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
+//
+// XvMCBlendSubpicture is a no-op in this case.
+//
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture to be blended into the video.
+// target_surface - The surface to be displayed with the blended subpic.
+// source_surface - Source surface prior to blending.
+// subx, suby, subw, subh - The rectangle from the subpicture to use.
+// surfx, surfy, surfw, surfh - The rectangle in the surface to blend
+// blend the subpicture rectangle into. Scaling can ocure if
+// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCBlendSubpicture(Display *display, XvMCSurface *target_surface,
+ XvMCSubpicture *subpicture,
+ short subx, short suby,
+ unsigned short subw, unsigned short subh,
+ short surfx, short surfy,
+ unsigned short surfw, unsigned short surfh) {
+
+ return BadMatch;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCBlendSubpicture2
+// Description:
+// The behavior of this function is different depending on whether
+// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
+// i810 only supports frontend blending.
+//
+// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
+//
+// XvMCBlendSubpicture2 blends the source_surface and subpicture and
+// puts it in the target_surface. This does not effect the status of
+// the source surface but will cause the target_surface to query
+// XVMC_RENDERING until the blend is completed.
+//
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture to be blended into the video.
+// target_surface - The surface to be displayed with the blended subpic.
+// source_surface - Source surface prior to blending.
+// subx, suby, subw, subh - The rectangle from the subpicture to use.
+// surfx, surfy, surfw, surfh - The rectangle in the surface to blend
+// blend the subpicture rectangle into. Scaling can ocure if
+// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCBlendSubpicture2(Display *display,
+ XvMCSurface *source_surface,
+ XvMCSurface *target_surface,
+ XvMCSubpicture *subpicture,
+ short subx, short suby,
+ unsigned short subw, unsigned short subh,
+ short surfx, short surfy,
+ unsigned short surfw, unsigned short surfh) {
+ drmBufPtr pDMA;
+ unsigned int *data;
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSubpicture *privSubpicture;
+ i810XvMCSurface *privTarget;
+ i810XvMCSurface *privSource;
+ drm_i810_mc_t mc;
+ int i,j;
+
+ if(display == NULL) {
+ return BadValue;
+ }
+
+ if(subpicture == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if((target_surface == NULL) || (source_surface == NULL)) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ if((subpicture->xvimage_id != FOURCC_AI44) &&
+ (subpicture->xvimage_id != FOURCC_IA44)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if(!subpicture->privData) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)privSubpicture->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if(!target_surface->privData) {
+ return (error_base + XvMCBadSurface);
+ }
+ privTarget = (i810XvMCSurface *)target_surface->privData;
+
+ if(!source_surface->privData) {
+ return (error_base + XvMCBadSurface);
+ }
+ privSource = (i810XvMCSurface *)source_surface->privData;
+
+
+ /* Check that size isn't bigger than subpicture */
+ if((subx + subw) > subpicture->width) {
+ return BadValue;
+ }
+ if((suby + subh) > subpicture->height) {
+ return BadValue;
+ }
+ /* Check that dest isn't bigger than surface */
+ if((surfx + surfw) > target_surface->width) {
+ return BadValue;
+ }
+ if((surfy + surfh) > target_surface->height) {
+ return BadValue;
+ }
+ /* Make sure surfaces match */
+ if(target_surface->width != source_surface->width) {
+ return BadValue;
+ }
+ if(target_surface->height != source_surface->height) {
+ return BadValue;
+ }
+
+ /* Lock For DMA */
+ I810_LOCK(pI810XvMC,0);
+
+ /* Allocate DMA buffer */
+ pDMA = i810_get_free_buffer(pI810XvMC);
+ data = pDMA->address;
+
+ /* Copy Y data first */
+ /* SOURCE_COPY_BLT */
+ *data++ = (2<<29) | (0x43<<22) | 0x4;
+ *data++ = (0xcc<<16) | (1<<26) | (1<<privTarget->pitch);
+ *data++ = (target_surface->height<<16) | target_surface->width;
+ *data++ = privTarget->offset + privTarget->offsets[0];
+ *data++ = (1<<privSource->pitch);
+ *data++ = privSource->offset + privSource->offsets[0];
+
+ /* Select Context 1 for loading */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<8);
+ *data++ = CMD_FLUSH;
+
+ /* Load Palette */
+ *data++ = MAP_PALETTE_LOAD;
+ /* 16 levels of alpha for each Y */
+ switch(subpicture->xvimage_id) {
+ case FOURCC_IA44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (j<<12) | (j<<8) | privSubpicture->palette[0][i];
+ }
+ }
+ break;
+ case FOURCC_AI44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (i<<12) | (i<<8) | privSubpicture->palette[0][j];
+ }
+ }
+ break;
+ }
+ /* TARGET */
+ /* *data++ = CMD_FLUSH; */
+ /* *data++ = BOOLEAN_ENA_2; */
+ *data++ = CMD_FLUSH;
+ *data++ = DEST_BUFFER_INFO;
+ *data++ = privTarget->dbi1y;
+ *data++ = DEST_BUFFER_VAR;
+ *data++ = privTarget->dbv1;
+
+ /* ALPHA */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privSubpicture->mi1;
+ *data++ = privSubpicture->mi2;
+ *data++ = privSubpicture->mi3;
+
+ *data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
+ *data++ = BOOLEAN_ENA_1;
+ *data++ = SRC_DEST_BLEND_MONO | (0x940);
+ /* Map Filter */
+ *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (0x224);
+
+ /* Use context 1 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<16) | 1;
+ *data++ = CMD_FLUSH;
+
+ /* Drawing Rect Info */
+ *data++ = DRAWING_RECT_INFO;
+ *data++ = 0x0;
+ *data++ = 0x0;
+ *data++ = 0x0;
+ *data++ = 0x0;
+ *data++ = 0x0;
+
+ /* GFXPRIMITIVE RECTANGLE */
+ *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
+ /* Bottom Right Vertex */
+ *(float *)data++ = (float) (surfx + surfw);
+ *(float *)data++ = (float) (surfy + surfh);
+ *(float *)data++ = (float) (subx + subw);
+ *(float *)data++ = (float) (suby + subh);
+ /* Bottom Left Vertex */
+ *(float *)data++ = (float) surfx;
+ *(float *)data++ = (float) (surfy + surfh);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) (suby + subh);
+ /* Top Left Vertex */
+ *(float *)data++ = (float) surfx;
+ *(float *)data++ = (float) surfy;
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby;
+
+ /* Load and Use Context 0 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<16);
+ *data++ = CMD_FLUSH;
+
+ /* U data */
+ /* SOURCE_COPY_BLT */
+ *data++ = (2<<29) | (0x43<<22) | 0x4;
+ *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1));
+ *data++ = (target_surface->height<<15) | (target_surface->width>>1);
+ *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[1];
+ *data++ = (1<<(privSource->pitch - 1));
+ *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[1];
+
+ /* Context 1 select */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<8);
+ *data++ = CMD_FLUSH;
+ /* ALPHA PALETTE */
+ *data++ = MAP_PALETTE_LOAD;
+ /* 16 levels of alpha for each Y */
+ switch(subpicture->xvimage_id) {
+ case FOURCC_IA44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (j<<12) | (j<<8) | privSubpicture->palette[2][i];
+ }
+ }
+ break;
+ case FOURCC_AI44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (i<<12) | (i<<8) | privSubpicture->palette[2][j];
+ }
+ }
+ break;
+ }
+ /* TARGET */
+ *data++ = CMD_FLUSH;
+ *data++ = BOOLEAN_ENA_2;
+ *data++ = CMD_FLUSH;
+ *data++ = DEST_BUFFER_INFO;
+ *data++ = privTarget->dbi1u;
+ *data++ = DEST_BUFFER_VAR;
+ *data++ = privTarget->dbv1;
+
+ /* ALPHA */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privSubpicture->mi1;
+ *data++ = privSubpicture->mi2;
+ *data++ = privSubpicture->mi3;
+
+ *data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
+ *data++ = BOOLEAN_ENA_1;
+ *data++ = SRC_DEST_BLEND_MONO | (0x940);
+ /* Map Filter */
+ *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224);
+
+ /* Use context 1 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<16) | 1;
+ *data++ = CMD_FLUSH;
+
+ /* Drawing Rect Info */
+ *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+
+ /* Rectangle */
+ *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
+ /* Bottom Right */
+ *(float *)data++ = (float) ((surfx + surfw)>>1);
+ *(float *)data++ = (float) ((surfy + surfh)>>1);
+ *(float *)data++ = (float) subx + subw;
+ *(float *)data++ = (float) suby + subh;
+ /* Bottom Left */
+ *(float *)data++ = (float) (surfx>>1);
+ *(float *)data++ = (float) ((surfy + surfh)>>1);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby + subh;
+ /* Top Left */
+ *(float *)data++ = (float) (surfx>>1);
+ *(float *)data++ = (float) (surfy>>1);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby;
+
+ /* Load and Use Context 0 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<16);
+ *data++ = CMD_FLUSH;
+
+ /* V data */
+ /* SOURCE_COPY_BLT */
+ *data++ = (2<<29) | (0x43<<22) | 0x4;
+ *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1));
+ *data++ = (target_surface->height<<15) | (target_surface->width>>1);
+ *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[2];
+ *data++ = (1<<(privSource->pitch - 1));
+ *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[2];
+
+ /* Context 1 select */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<8);
+ *data++ = CMD_FLUSH;
+
+ /* ALPHA PALETTE */
+ *data++ = MAP_PALETTE_LOAD;
+ /* 16 levels of alpha for each Y */
+ switch(subpicture->xvimage_id) {
+ case FOURCC_IA44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (j<<12) | (j<<8) | privSubpicture->palette[1][i];
+ }
+ }
+ break;
+ case FOURCC_AI44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (i<<12) | (i<<8) | privSubpicture->palette[1][j];
+ }
+ }
+ break;
+ }
+ /* TARGET */
+ *data++ = CMD_FLUSH;
+ *data++ = BOOLEAN_ENA_2;
+ *data++ = CMD_FLUSH;
+ *data++ = DEST_BUFFER_INFO;
+ *data++ = privTarget->dbi1v;
+ *data++ = DEST_BUFFER_VAR;
+ *data++ = privTarget->dbv1;
+
+ /* ALPHA */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privSubpicture->mi1;
+ *data++ = privSubpicture->mi2;
+ *data++ = privSubpicture->mi3;
+
+ *data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
+ *data++ = BOOLEAN_ENA_1;
+ *data++ = SRC_DEST_BLEND_MONO | (0x940);
+ /* Map Filter */
+ *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224);
+
+ /* Use context 1 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<16) | 1;
+ *data++ = CMD_FLUSH;
+
+ /* Drawing Rect Info */
+ *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+
+ /* Rectangle */
+ *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
+ /* Bottom Right */
+ *(float *)data++ = (float) ((surfx + surfw)>>1);
+ *(float *)data++ = (float) ((surfy + surfh)>>1);
+ *(float *)data++ = (float) subx + subw;
+ *(float *)data++ = (float) suby + subh;
+ /* Bottom Left */
+ *(float *)data++ = (float) (surfx>>1);
+ *(float *)data++ = (float) ((surfy + surfh)>>1);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby + subh;
+ /* Top Left */
+ *(float *)data++ = (float) (surfx>>1);
+ *(float *)data++ = (float) (surfy>>1);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby;
+
+ /* Load and Use Context 0 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<16);
+ *data++ = CMD_FLUSH;
+
+
+ /* Dispatch */
+ pDMA->used = (unsigned long)data - (unsigned long)pDMA->address;
+ mc.idx = pDMA->idx;
+ mc.used = pDMA->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+
+ I810_UNLOCK(pI810XvMC);
+ return Success;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCSyncSubpicture
+// Description: This function blocks until all composite/clear requests on
+// the subpicture have been complete.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture to synchronize
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture) {
+ Status ret;
+ int stat=0;
+ do {
+ ret = XvMCGetSubpictureStatus(display,subpicture,&stat);
+ }while(!ret && (stat & XVMC_RENDERING));
+ return ret;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCFlushSubpicture
+// Description: This function commits pending composite/clear requests to
+// ensure that they will be completed in a finite amount of
+// time.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture whos compsiting should be flushed
+//
+// Returns: Status
+// NOTES: i810 always dispatches commands so flush is a no-op
+***************************************************************************/
+Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture) {
+ if(display == NULL) {
+ return BadValue;
+ }
+ if(subpicture == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ return Success;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCGetSubpictureStatus
+// Description: This function gets the current status of a subpicture
+//
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture whos status is being queried
+// stat - The status of the subpicture. It can be any of the following
+// OR'd together:
+// XVMC_RENDERING - Last composite or clear request not completed
+// XVMC_DISPLAYING - Suppicture currently being displayed.
+//
+// Returns: Status
+// Notes: i810 always blends into a third surface so the subpicture is
+// never actually displaying, only a copy of it is displaying. We only
+// have to worry about the rendering case.
+***************************************************************************/
+Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture,
+ int *stat) {
+
+ i810XvMCSubpicture *privSubpicture;
+ i810XvMCContext *pI810XvMC;
+
+ if((display == NULL) || (stat == NULL)) {
+ return BadValue;
+ }
+ if((subpicture == NULL) || (subpicture->privData == NULL)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ *stat = 0;
+ privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)privSubpicture->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ I810_LOCK(pI810XvMC,0);
+
+ if(privSubpicture->last_render &&
+ (privSubpicture->last_render > GET_RSTATUS(pI810XvMC))) {
+ *stat |= XVMC_RENDERING;
+ }
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+}
+
+#define NUM_XVMC_ATTRIBUTES 4
+static XvAttribute I810_XVMC_ATTRIBUTES[] = {
+ {XvGettable | XvSettable, 0, 0xffffff, "XV_COLORKEY"},
+ {XvGettable | XvSettable, -127, +127, "XV_BRIGHTNESS"},
+ {XvGettable | XvSettable, 0, 0x1ff, "XV_CONTRAST"},
+ {XvGettable | XvSettable, 0, 0x3ff, "XV_SATURATION"}
+};
+
+
+/***************************************************************************
+// Function: XvMCQueryAttributes
+// Description: An array of XvAttributes of size "number" is returned by
+// this function. If there are no attributes, NULL is returned and number
+// is set to 0. The array may be freed with xfree().
+//
+// Arguments:
+// display - Connection to the X server.
+// context - The context whos attributes we are querying.
+// number - The number of returned atoms.
+//
+// Returns:
+// An array of XvAttributes.
+// Notes:
+// For i810 we support these Attributes:
+// XV_COLORKEY: The colorkey value, initialized from the Xv value at
+// context creation time.
+// XV_BRIGHTNESS
+// XV_CONTRAST
+// XV_SATURATION
+***************************************************************************/
+XvAttribute *XvMCQueryAttributes(Display *display, XvMCContext *context,
+ int *number) {
+ i810XvMCContext *pI810XvMC;
+ XvAttribute *attributes;
+
+ if(number == NULL) {
+ return NULL;
+ }
+ if(display == NULL) {
+ *number = 0;
+ return NULL;
+ }
+ if(context == NULL) {
+ *number = 0;
+ return NULL;
+ }
+ pI810XvMC = context->privData;
+ if(pI810XvMC == NULL) {
+ *number = 0;
+ return NULL;
+ }
+
+ attributes = (XvAttribute *)malloc(NUM_XVMC_ATTRIBUTES *
+ sizeof(XvAttribute));
+ if(attributes == NULL) {
+ *number = 0;
+ return NULL;
+ }
+
+ memcpy(attributes,I810_XVMC_ATTRIBUTES,(NUM_XVMC_ATTRIBUTES *
+ sizeof(XvAttribute)));
+
+ *number = NUM_XVMC_ATTRIBUTES;
+ return attributes;
+}
+
+/***************************************************************************
+// Function: XvMCSetAttribute
+// Description: This function sets a context-specific attribute.
+//
+// Arguments:
+// display - Connection to the X server.
+// context - The context whos attributes we are querying.
+// attribute - The X atom of the attribute to be changed.
+// value - The new value for the attribute.
+//
+// Returns:
+// Status
+// Notes:
+// For i810 we support these Attributes:
+// XV_COLORKEY: The colorkey value, initialized from the Xv value at
+// context creation time.
+// XV_BRIGHTNESS
+// XV_CONTRAST
+// XV_SATURATION
+***************************************************************************/
+Status XvMCSetAttribute(Display *display, XvMCContext *context,
+ Atom attribute, int value) {
+ i810XvMCContext *pI810XvMC;
+
+ if(display == NULL) {
+ return BadValue;
+ }
+ if(context == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ pI810XvMC = context->privData;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+
+ if(attribute == pI810XvMC->xv_colorkey) {
+ if((value < I810_XVMC_ATTRIBUTES[0].min_value) ||
+ (value > I810_XVMC_ATTRIBUTES[0].max_value)) {
+ return BadValue;
+ }
+ pI810XvMC->colorkey = value;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_brightness) {
+ if((value < I810_XVMC_ATTRIBUTES[1].min_value) ||
+ (value > I810_XVMC_ATTRIBUTES[1].max_value)) {
+ return BadValue;
+ }
+ pI810XvMC->brightness = value;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_saturation) {
+ if((value < I810_XVMC_ATTRIBUTES[2].min_value) ||
+ (value > I810_XVMC_ATTRIBUTES[2].max_value)) {
+ return BadValue;
+ }
+ pI810XvMC->saturation = value;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_contrast) {
+ if((value < I810_XVMC_ATTRIBUTES[3].min_value) ||
+ (value > I810_XVMC_ATTRIBUTES[3].max_value)) {
+ return BadValue;
+ }
+ pI810XvMC->contrast = value;
+ return Success;
+ }
+ return BadValue;
+}
+
+/***************************************************************************
+// Function: XvMCGetAttribute
+// Description: This function queries a context-specific attribute and
+// returns the value.
+//
+// Arguments:
+// display - Connection to the X server.
+// context - The context whos attributes we are querying.
+// attribute - The X atom of the attribute to be queried
+// value - The returned attribute value
+//
+// Returns:
+// Status
+// Notes:
+// For i810 we support these Attributes:
+// XV_COLORKEY: The colorkey value, initialized from the Xv value at
+// context creation time.
+// XV_BRIGHTNESS
+// XV_CONTRAST
+// XV_SATURATION
+***************************************************************************/
+Status XvMCGetAttribute(Display *display, XvMCContext *context,
+ Atom attribute, int *value) {
+ i810XvMCContext *pI810XvMC;
+
+ if(display == NULL) {
+ return BadValue;
+ }
+ if(context == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ pI810XvMC = context->privData;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ if(value == NULL) {
+ return BadValue;
+ }
+
+ if(attribute == pI810XvMC->xv_colorkey) {
+ *value = pI810XvMC->colorkey;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_brightness) {
+ *value = pI810XvMC->brightness;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_saturation) {
+ *value = pI810XvMC->saturation;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_contrast) {
+ *value = pI810XvMC->contrast;
+ return Success;
+ }
+ return BadValue;
+}
+
+
+
+
diff --git a/nx-X11/lib/XvMC/hw/i810/I810XvMC.h b/nx-X11/lib/XvMC/hw/i810/I810XvMC.h
new file mode 100644
index 000000000..ba8c792d0
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/i810/I810XvMC.h
@@ -0,0 +1,469 @@
+/***************************************************************************
+
+Copyright 2001 Intel Corporation. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/***************************************************************************
+ * libI810XvMC.h: MC Driver i810 includes
+ *
+ * Authors:
+ * Matt Sottek <matthew.j.sottek@intel.com>
+ *
+ *
+ ***************************************************************************/
+/* $XFree86: xc/lib/XvMC/hw/i810/I810XvMC.h,v 1.3 2002/10/30 12:52:02 alanh Exp $ */
+
+
+#ifndef I810XVMC_H
+#define I810XVMC_H
+
+/* #define XVMC_DEBUG(x) do {x; }while(0); */
+#define XVMC_DEBUG(x)
+
+#include "xf86drm.h"
+#include "i810_common.h"
+#include <X11/Xlibint.h>
+
+
+/***************************************************************************
+// i810OverlayRec: Structure that is used to reference the overlay
+// register memory. A i810OverlayRecPtr is set to the address of the
+// allocated overlay registers.
+***************************************************************************/
+typedef struct _i810OverlayRec {
+ unsigned int OBUF_0Y;
+ unsigned int OBUF_1Y;
+ unsigned int OBUF_0U;
+ unsigned int OBUF_0V;
+ unsigned int OBUF_1U;
+ unsigned int OBUF_1V;
+ unsigned int OV0STRIDE;
+ unsigned int YRGB_VPH;
+ unsigned int UV_VPH;
+ unsigned int HORZ_PH;
+ unsigned int INIT_PH;
+ unsigned int DWINPOS;
+ unsigned int DWINSZ;
+ unsigned int SWID;
+ unsigned int SWIDQW;
+ unsigned int SHEIGHT;
+ unsigned int YRGBSCALE;
+ unsigned int UVSCALE;
+ unsigned int OV0CLRC0;
+ unsigned int OV0CLRC1;
+ unsigned int DCLRKV;
+ unsigned int DCLRKM;
+ unsigned int SCLRKVH;
+ unsigned int SCLRKVL;
+ unsigned int SCLRKM;
+ unsigned int OV0CONF;
+ unsigned int OV0CMD;
+} i810OverlayRec, *i810OverlayRecPtr;
+
+
+/***************************************************************************
+// i810XvMCDrmMap: Holds the data about the DRM maps
+***************************************************************************/
+typedef struct _i810XvMCDrmMap {
+ drm_handle_t offset;
+ drmAddress address;
+ unsigned int size;
+} i810XvMCDrmMap, *i810XvMCDrmMapPtr;
+
+/***************************************************************************
+// i810XvMCContext: Private Context data referenced via the privData
+// pointer in the XvMCContext structure.
+***************************************************************************/
+typedef struct _i810XvMCContext {
+ int fd; /* File descriptor for /dev/dri */
+ i810XvMCDrmMap overlay;
+ i810XvMCDrmMap surfaces;
+ drmBufMapPtr dmabufs; /* Data structure to hold available dma buffers */
+ drm_context_t drmcontext;
+ unsigned int last_render;
+ unsigned int last_flip;
+ unsigned short ref;
+ unsigned short current;
+ int lock; /* Lightweight lock to avoid locking twice */
+ char busIdString[10]; /* PCI:0:1:0 or PCI:0:2:0 */
+ i810OverlayRecPtr oregs;
+ unsigned int dual_prime; /* Flag to identify when dual prime is in use. */
+ unsigned int fb_base;
+ Atom xv_colorkey;
+ Atom xv_brightness;
+ Atom xv_contrast;
+ Atom xv_saturation;
+ int brightness;
+ int saturation;
+ int contrast;
+ int colorkey;
+} i810XvMCContext;
+
+/***************************************************************************
+// i810XvMCSurface: Private data structure for each XvMCSurface. This
+// structure is referenced by the privData pointer in the XvMCSurface
+// structure.
+***************************************************************************/
+typedef struct _i810XvMCSurface {
+ unsigned int pitch;
+ unsigned int dbi1y; /* Destination buffer info command word 1 for Y */
+ unsigned int dbi1u; /* Destination buffer info command word 1 for U */
+ unsigned int dbi1v; /* Destination buffer info command word 1 for V */
+ unsigned int dbv1; /* Destination buffer variables command word 1 */
+ unsigned int mi1y; /* Map Info command word 1 (Minus bit 28) for Y */
+ unsigned int mi1u; /* Map Info command word 1 (Minus bit 28) for U */
+ unsigned int mi1v; /* Map Info command word 1 (Minus bit 28) for V */
+ unsigned int mi2y; /* Map info command word 2 for y */
+ unsigned int mi2u; /* Map info command word 2 for y */
+ unsigned int mi2v; /* Map info command word 2 for y */
+ unsigned int mi3y; /* Map info command word 3 */
+ unsigned int mi3u; /* Map info command word 3 */
+ unsigned int mi3v; /* Map info command word 3 */
+ unsigned int last_render;
+ unsigned int last_flip;
+ unsigned int second_field; /* Flags a surface that is only half done */
+ drmAddress data;
+ drm_handle_t offset;
+ unsigned int offsets[3];
+ i810XvMCContext *privContext;
+} i810XvMCSurface;
+
+/***************************************************************************
+// i810XvMCSubpicture: Private data structure for each XvMCSubpicture. This
+// structure is referenced by the privData pointer in the XvMCSubpicture
+// structure.
+***************************************************************************/
+typedef struct _i810XvMCSubpicture {
+ unsigned int pitch;
+ unsigned int dbi1; /* Destination buffer info command word 1 */
+ unsigned int dbv1; /* Destination buffer variables command word */
+ unsigned int mi1; /* Map Info command word 1 (Minus bit 28) */
+ unsigned int mi2; /* Map info command word 2 */
+ unsigned int mi3; /* Map info command word 3 */
+ unsigned int last_render;
+ unsigned int last_flip;
+ drmAddress data;
+ drm_handle_t offset;
+ unsigned int offsets[1];
+ unsigned char palette[3][16];
+ i810XvMCContext *privContext;
+} i810XvMCSubpicture;
+
+typedef struct _Box {
+ int x1,y1,x2,y2;
+} Box, *BoxPtr;
+
+/***************************************************************************
+// drm_i810_overlay_t: Structure returned by overlay info ioctl.
+// NOTE: If you change this structure you will have to change the equiv.
+// structure in the kernel.
+***************************************************************************/
+typedef struct _drm_i810_overlay_t {
+ unsigned int offset;
+ unsigned int physical;
+} drm_i810_overlay_t;
+
+/***************************************************************************
+// drm_i810_dma_t: Structure used by dma allocation ioctl.
+// NOTE: If you change this structure you will have to change the equiv.
+// structure in the kernel.
+***************************************************************************/
+typedef struct _drm_i810_dma {
+ void *virtual;
+ int request_idx;
+ int request_size;
+ int granted;
+} drm_i810_dma_t;
+
+/***************************************************************************
+// drm_i810_mc_t: Structure used by mc dispatch ioctl.
+// NOTE: If you change this structure you will have to change the equiv.
+// structure in the kernel.
+***************************************************************************/
+typedef struct _drm_i810_mc {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int num_blocks; /* number of GFXBlocks */
+ int *length; /* List of lengths for GFXBlocks */
+ unsigned int last_render; /* Last render request */
+} drm_i810_mc_t;
+
+/* Subpicture fourcc */
+#define FOURCC_IA44 0x34344149
+
+/* Static Parameters */
+#define I810_XVMC_MAXWIDTH 720
+#define I810_XVMC_MAXHEIGHT 576
+#define I810_DEFAULT16_COLORKEY 31
+#define I810_DMA_BUF_NR 256
+
+/* COMMANDS */
+#define CMD_FLUSH ((4<<23) | 0x1)
+#define BOOLEAN_ENA_1 ((3<<29) | (3<<24) | (3<<2))
+#define BOOLEAN_ENA_2 ((3<<29) | (4<<24) | (3<<16) | (1<<3) | (1<<2))
+#define DEST_BUFFER_INFO (0x15<<23)
+#define DEST_BUFFER_VAR ((0x3<<29) | (0x1d<<24) | (0x85<<16))
+#define DRAWING_RECT_INFO ((3<<29) | (0x1d<<24) | (0x80<<16) | 3)
+#define GFXBLOCK ((0x3<<29) | (0x1e<<24))
+#define CMD_MAP_INFO ((0x3<<29) | (0x1d<<24) | 0x2)
+#define MAP_PALETTE_LOAD ((3<<29) | (0x1d<<24) | (0x82<<16) | 0xff)
+#define VERTEX_FORMAT ((3<<29) | (0x5<<24))
+#define SRC_DEST_BLEND_MONO ((3<<29) | (8<<24))
+
+/* Bit Patterns */
+
+/*
+ * OV0CMD - Overlay Command Register
+ */
+#define VERTICAL_CHROMINANCE_FILTER 0x70000000
+#define VC_SCALING_OFF 0x00000000
+#define VC_LINE_REPLICATION 0x10000000
+#define VC_UP_INTERPOLATION 0x20000000
+#define VC_PIXEL_DROPPING 0x50000000
+#define VC_DOWN_INTERPOLATION 0x60000000
+#define VERTICAL_LUMINANCE_FILTER 0x0E000000
+#define VL_SCALING_OFF 0x00000000
+#define VL_LINE_REPLICATION 0x02000000
+#define VL_UP_INTERPOLATION 0x04000000
+#define VL_PIXEL_DROPPING 0x0A000000
+#define VL_DOWN_INTERPOLATION 0x0C000000
+#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000
+#define HC_SCALING_OFF 0x00000000
+#define HC_LINE_REPLICATION 0x00400000
+#define HC_UP_INTERPOLATION 0x00800000
+#define HC_PIXEL_DROPPING 0x01400000
+#define HC_DOWN_INTERPOLATION 0x01800000
+#define HORIZONTAL_LUMINANCE_FILTER 0x00380000
+#define HL_SCALING_OFF 0x00000000
+#define HL_LINE_REPLICATION 0x00080000
+#define HL_UP_INTERPOLATION 0x00100000
+#define HL_PIXEL_DROPPING 0x00280000
+#define HL_DOWN_INTERPOLATION 0x00300000
+
+#define Y_ADJUST 0x00010000
+#define OV_BYTE_ORDER 0x0000C000
+#define UV_SWAP 0x00004000
+#define Y_SWAP 0x00008000
+#define Y_AND_UV_SWAP 0x0000C000
+#define SOURCE_FORMAT 0x00003C00
+#define RGB_555 0x00000800
+#define RGB_565 0x00000C00
+#define YUV_422 0x00002000
+#define YUV_411 0x00002400
+#define YUV_420 0x00003000
+#define YUV_410 0x00003800
+#define VERTICAL_PHASE_BOTH 0x00000020
+#define FLIP_TYPE_FIELD 0x00000020
+#define FLIP_TYPE_FRAME 0x00000000
+#define BUFFER_AND_FIELD 0x00000006
+#define BUFFER0_FIELD0 0x00000000
+#define BUFFER0_FIELD1 0x00000002
+#define BUFFER1_FIELD0 0x00000004
+#define BUFFER1_FIELD1 0x00000006
+#define OVERLAY_ENABLE 0x00000001
+
+/*
+ * DOV0STA - Display/Overlay 0 Status Register
+ */
+#define DOV0STA 0x30008
+#define OV0ADD 0x30000
+#define MINUV_SCALE 0x1
+
+#define RGB16ToColorKey(c) \
+ (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
+
+/* Locking Macros lightweight lock used to prevent relocking */
+#define I810_LOCK(c,f) \
+ if(!c->lock) { \
+ drmGetLock(c->fd, c->drmcontext, f); \
+ } \
+ c->lock++;
+
+#define I810_UNLOCK(c) \
+ c->lock--; \
+ if(!c->lock) { \
+ drmUnlock(c->fd, c->drmcontext); \
+ }
+
+/*
+ Block until the passed in value (n) is the active
+ buffer on the overlay.
+*/
+#define BLOCK_OVERLAY(c,n) \
+ do { \
+ int temp,i=0; \
+ while(i < 100000) { \
+ temp = GET_FSTATUS(c); \
+ if(((temp & (1<<20))>>20) == n) { \
+ break; \
+ } \
+ usleep(10); \
+ } \
+ if(i == 100000) { \
+ printf("Overlay Lockup.\n"); \
+ return BadAlloc; \
+ } \
+ }while(0);
+
+#define OVERLAY_INFO(c,i) drmCommandRead(c->fd, DRM_I810_OV0INFO, &i, sizeof(i))
+#define OVERLAY_FLIP(c) drmCommandNone(c->fd, DRM_I810_OV0FLIP)
+#define GET_FSTATUS(c) drmCommandNone(c->fd, DRM_I810_FSTATUS)
+#define I810_MC(c,mc) drmCommandWrite(c->fd, DRM_I810_MC, &mc, sizeof(mc))
+#define GET_RSTATUS(c) drmCommandNone(c->fd, DRM_I810_RSTATUS)
+#define GET_BUFFER(c,dma) drmCommandWriteRead(c->fd, DRM_I810_GETBUF, &dma, sizeof(drmI810DMA))
+#define FLUSH(c) drmCommandNone(c->fd, DRM_I810_FLUSH)
+
+/*
+ Definitions for temporary wire protocol hooks to be replaced
+ when a HW independent libXvMC is created.
+*/
+extern Status _xvmc_create_context(Display *dpy, XvMCContext *context,
+ int *priv_count, uint **priv_data);
+
+extern Status _xvmc_destroy_context(Display *dpy, XvMCContext *context);
+
+extern Status _xvmc_create_surface(Display *dpy, XvMCContext *context,
+ XvMCSurface *surface, int *priv_count,
+ uint **priv_data);
+
+extern Status _xvmc_destroy_surface(Display *dpy, XvMCSurface *surface);
+
+extern Status _xvmc_create_subpicture(Display *dpy, XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ int *priv_count, uint **priv_data);
+
+extern Status _xvmc_destroy_subpicture(Display *dpy,
+ XvMCSubpicture *subpicture);
+
+/*
+ Prototypes
+*/
+drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC);
+void i810_free_privContext(i810XvMCContext *pI810XvMC);
+void dp(unsigned int *address, unsigned int i);
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nx-X11/lib/XvMC/hw/i810/Imakefile b/nx-X11/lib/XvMC/hw/i810/Imakefile
new file mode 100644
index 000000000..b7956d01e
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/i810/Imakefile
@@ -0,0 +1,44 @@
+XCOMM $XFree86: xc/lib/XvMC/hw/i810/Imakefile,v 1.2 2002/10/30 12:52:02 alanh Exp $
+#define DoNormalLib NormalLibXvMC
+#define DoSharedLib SharedLibXvMC
+#define DoDebugLib DebugLibXvMC
+#define DoProfileLib ProfileLibXvMC
+#define LibName I810XvMC
+#define SoRev SOXVMCREV
+#define LibHeaders NO
+
+#include <Threads.tmpl>
+
+#ifdef SharedXvMCReqs
+REQUIREDLIBS = SharedXvMCReqs
+#endif
+
+#if Malloc0ReturnsNull
+ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL
+#endif
+
+ DEFINES = $(ALLOC_DEFINES) -DTRUE=1 -DFALSE=0
+ INCLUDES = -I$(XINCLUDESRC) -I$(INCLUDESRC) -I$(XLIBSRC) -I$(EXTINCSRC) \
+ -I$(XF86COMSRC) -I$(XF86OSSRC) -I$(DRMSRCDIR)/shared-core \
+ -I$(XF86DRIVERSRC)/i810
+ SRCS = I810XvMC.c
+ OBJS = I810XvMC.o xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o
+ LINTLIBS = $(LINTXLIB)
+
+
+#include <Library.tmpl>
+
+
+#if defined(LinuxArchitecture)
+
+LIBDRM_DIR = ../../../../extras/drm/libdrm
+
+LinkSourceFile(xf86drm.c,$(LIBDRM_DIR))
+LinkSourceFile(xf86drmHash.c,$(LIBDRM_DIR))
+LinkSourceFile(xf86drmRandom.c,$(LIBDRM_DIR))
+LinkSourceFile(xf86drmSL.c,$(LIBDRM_DIR))
+
+#endif
+
+DependTarget()
+
diff --git a/nx-X11/lib/XvMC/hw/via/driDrawable.c b/nx-X11/lib/XvMC/hw/via/driDrawable.c
new file mode 100644
index 000000000..35934d89d
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/driDrawable.c
@@ -0,0 +1,176 @@
+/*****************************************************************************
+ * driDrawable.c: Lean Version of DRI utilities.
+ *
+ * Copyright (c) 2005 Thomas Hellstrom. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+#include "xf86drm.h"
+#include "drm.h"
+#include "xf86dri.h"
+#include "drm_sarea.h"
+#include "driDrawable.h"
+
+
+static unsigned
+drawStamp(volatile drm_sarea_t *pSarea, int index)
+{
+ return pSarea->drawableTable[index].stamp;
+}
+
+int
+getDRIDrawableInfoLocked(void *drawHash, Display *display, int screen, Drawable draw,
+ unsigned lockFlags, int drmFD, drm_context_t drmContext,
+ drmAddress sarea, Bool updateInfo, drawableInfo **info,
+ unsigned long infoSize)
+{
+ drawableInfo *drawInfo;
+ void *res;
+ drm_drawable_t drmDraw=0;
+ volatile drm_sarea_t *pSarea = (drm_sarea_t *) sarea;
+ drm_clip_rect_t *clipFront, *clipBack;
+
+ int ret;
+
+
+ if (drmHashLookup(drawHash, (unsigned long) draw, &res)) {
+
+ /*
+ * The drawable is unknown to us. Create it and put it in the
+ * hash table.
+ */
+
+ DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
+ if (!uniDRICreateDrawable(display, screen, draw,
+ &drmDraw)) {
+ DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
+ return 1;
+ }
+ DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
+
+
+ drawInfo = (drawableInfo *) malloc(infoSize);
+ if (!drawInfo) return 1;
+
+ drawInfo->drmDraw = drmDraw;
+ drawInfo->stamp = 0;
+ drawInfo->clipFront = 0;
+ drawInfo->clipBack = 0;
+
+ drmHashInsert( drawHash, (unsigned long) draw, drawInfo);
+
+ } else {
+ drawInfo = res;
+ }
+
+
+ drawInfo->touched = FALSE;
+ while (!drawInfo->clipFront || drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) {
+
+ /*
+ * The drawable has been touched since we last got info about it.
+ * obtain new info from the X server.
+ */
+
+ drawInfo->touched = TRUE;
+
+ if (updateInfo || !drawInfo->clipFront) {
+ DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
+
+ ret = uniDRIGetDrawableInfo(display, screen, draw,
+ &drawInfo->index, &drawInfo->stamp, &drawInfo->x,
+ &drawInfo->y, &drawInfo->w, &drawInfo->h,
+ &drawInfo->numClipFront, &clipFront,
+ &drawInfo->backX, &drawInfo->backY,
+ &drawInfo->numClipBack, &clipBack);
+
+ DRM_LIGHT_LOCK(drmFD, &pSarea->lock, drmContext);
+
+ /*
+ * Error. Probably the drawable is destroyed. Return error and old values.
+ */
+
+ if (!ret) {
+ free(drawInfo);
+ drawInfo = NULL;
+ drmHashDelete(drawHash, (unsigned long) draw);
+
+ DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
+ uniDRIDestroyDrawable( display, screen, draw);
+ DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
+
+ return 1;
+ }
+
+ if (drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) {
+
+ /*
+ * The info is already outdated. Sigh. Have another go.
+ */
+
+ XFree(clipFront);
+ XFree(clipBack);
+ continue;
+ }
+
+ if (drawInfo->clipFront) XFree(drawInfo->clipFront);
+ drawInfo->clipFront = clipFront;
+ if (drawInfo->clipBack) XFree(drawInfo->clipBack);
+ drawInfo->clipBack = clipBack;
+ } else {
+ if (!drawInfo->clipFront) drawInfo->clipFront = (drm_clip_rect_t *) ~0UL;
+ drawInfo->stamp = drawStamp(pSarea, drawInfo->index);
+ }
+ }
+ *info = drawInfo;
+ return 0;
+}
+
+void
+driDestroyHashContents(void *drawHash)
+{
+ unsigned long key;
+ void *content;
+ drawableInfo *drawInfo;
+
+
+ if (drmHashFirst(drawHash, &key, &content) < 1)
+ return;
+ drawInfo = (drawableInfo *) content;
+ if (drawInfo->clipBack) XFree(drawInfo->clipBack);
+ if (drawInfo->clipFront) XFree(drawInfo->clipFront);
+ free(drawInfo);
+ while(drmHashNext(drawHash, &key, &content) == 1) {
+ drawInfo = (drawableInfo *) content;
+ if (drawInfo->clipBack) XFree(drawInfo->clipBack);
+ if (drawInfo->clipFront) XFree(drawInfo->clipFront);
+ free(drawInfo);
+ }
+
+ return ;
+}
+
+
diff --git a/nx-X11/lib/XvMC/hw/via/driDrawable.h b/nx-X11/lib/XvMC/hw/via/driDrawable.h
new file mode 100644
index 000000000..e5651058b
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/driDrawable.h
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * driDrawable.h: Lean Version of DRI utilities.
+ *
+ * Copyright (c) 2005 Thomas Hellstrom. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRIDRAWABLE_H
+#define _DRIDRAWABLE_H
+
+typedef struct _drawableInfo {
+ drm_drawable_t drmDraw;
+ unsigned stamp;
+ unsigned index;
+ drm_clip_rect_t *clipFront;
+ drm_clip_rect_t *clipBack;
+ int x;
+ int y;
+ int w;
+ int h;
+ int backX;
+ int backY;
+ int numClipFront;
+ int numClipBack;
+ Bool touched;
+} drawableInfo;
+
+/*
+ * Get updated info about the drawable "draw". The drawableInfo record returned is malloced
+ * and administrated internally. Never free it unless you know exactly what you are doing.
+ * The drm hash table "drawHash" needs to be initialized externally.
+ */
+
+extern int
+getDRIDrawableInfoLocked (void *drawHash, Display *display, int screen, Drawable draw,
+ unsigned lockFlags, int drmFD, drm_context_t drmContext,
+ drmAddress sarea, Bool updateInfo, drawableInfo **info,
+ unsigned long infoSize);
+
+/*
+ * Free all resources created by the above function. Typically done on exit.
+ */
+
+extern void
+driDestroyHashContents(void *drawHash);
+
+#endif
diff --git a/nx-X11/lib/XvMC/hw/via/unichrome/Imakefile b/nx-X11/lib/XvMC/hw/via/unichrome/Imakefile
new file mode 100644
index 000000000..bc9120972
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/unichrome/Imakefile
@@ -0,0 +1,51 @@
+#define DoNormalLib NormalLibXvMC
+#define DoSharedLib SharedLibXvMC
+#define DoDebugLib DebugLibXvMC
+#define DoProfileLib ProfileLibXvMC
+#define LibName viaXvMC
+#define SoRev SOXVMCREV
+#define LibHeaders NO
+
+#include <Threads.tmpl>
+
+#ifdef SharedXvMCReqs
+REQUIREDLIBS = SharedXvMCReqs -lXv
+#endif
+
+#if Malloc0ReturnsNull
+ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL
+#endif
+
+ DEFINES = $(ALLOC_DEFINES) -DTRUE=1 -DFALSE=0
+ INCLUDES = -I$(XINCLUDESRC) -I$(INCLUDESRC) -I$(XLIBSRC) -I$(EXTINCSRC) \
+ -I$(XF86COMSRC) -I$(XF86OSSRC) -I$(DRMSRCDIR)/shared-core \
+ -I$(XF86OSSRC)/linux/drm/kernel -I$(XF86DRIVERSRC)/via
+ SRCS = viaLowLevel.c
+ OBJS = viaXvMC.o viaLowLevel.o xf86drm.o xf86drmHash.o \
+ xf86drmRandom.o xf86drmSL.o xf86dri.o driDrawable.o
+ LINTLIBS = $(LINTXLIB)
+
+
+#include <Library.tmpl>
+
+
+#if defined(LinuxArchitecture)
+
+LIBDRM_DIR = ../../../../../extras/drm/libdrm
+
+LinkSourceFile(xf86drm.c,$(LIBDRM_DIR))
+LinkSourceFile(xf86drmHash.c,$(LIBDRM_DIR))
+LinkSourceFile(xf86drmRandom.c,$(LIBDRM_DIR))
+LinkSourceFile(xf86drmSL.c,$(LIBDRM_DIR))
+LinkSourceFile(viaLowLevel.h,..)
+LinkSourceFile(driDrawable.h,..)
+LinkSourceFile(viaXvMCPriv.h,..)
+LinkSourceFile(xf86dri.h,..)
+LinkSourceFile(xf86dristr.h,..)
+LinkSourceFile(xf86dri.c,..)
+LinkSourceFile(driDrawable.c,..)
+LinkSourceFile(viaXvMC.c,..)
+#endif
+
+DependTarget()
+
diff --git a/nx-X11/lib/XvMC/hw/via/unichrome/viaLowLevel.c b/nx-X11/lib/XvMC/hw/via/unichrome/viaLowLevel.c
new file mode 100644
index 000000000..1add1ca5d
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/unichrome/viaLowLevel.c
@@ -0,0 +1,1056 @@
+/*****************************************************************************
+ * VIA Unichrome XvMC extension client lib.
+ *
+ * Copyright (c) 2004 Thomas Hellström. All rights reserved.
+ * Copyright (c) 2003 Andreas Robinson. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Low-level functions that deal directly with the hardware. In the future,
+ * these functions might be implemented in a kernel module. Also, some of them
+ * would benefit from DMA.
+ *
+ * Authors: Andreas Robinson 2003. Thomas Hellström 2004.
+ */
+
+
+
+#include "viaXvMCPriv.h"
+#include "viaLowLevel.h"
+#include <time.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+typedef struct{
+ CARD32 agp_buffer[LL_AGP_CMDBUF_SIZE];
+ CARD32 pci_buffer[LL_PCI_CMDBUF_SIZE];
+ unsigned agp_pos;
+ unsigned pci_pos;
+ unsigned flip_pos;
+ int use_agp;
+ int agp_mode;
+ int agp_header_start;
+ int agp_index;
+ int fd;
+ drm_context_t *drmcontext;
+ drmLockPtr hwLock;
+ drmAddress mmioAddress;
+ drmAddress fbAddress;
+ unsigned fbStride;
+ unsigned fbDepth;
+ unsigned width;
+ unsigned height;
+ unsigned curWaitFlags;
+ int performLocking;
+ unsigned errors;
+ drm_via_mem_t tsMem;
+ CARD32 tsOffset;
+ volatile CARD32 *tsP;
+ CARD32 curTimeStamp;
+ CARD32 lastReadTimeStamp;
+ int agpSync;
+ CARD32 agpSyncTimeStamp;
+ unsigned chipId;
+}XvMCLowLevel;
+
+
+
+
+
+/*
+ * For Other architectures than i386 these might have to be modified for
+ * bigendian etc.
+ */
+
+#define MPEGIN(xl,reg) \
+ *((volatile CARD32 *)(((CARD8 *)(xl)->mmioAddress) + 0xc00 + (reg)))
+
+#define VIDIN(ctx,reg) \
+ *((volatile CARD32 *)(((CARD8 *)(ctx)->mmioAddress) + 0x200 + (reg)))
+
+#define REGIN(ctx,reg) \
+ *((volatile CARD32 *)(((CARD8 *)(ctx)->mmioAddress) + 0x0000 + (reg)))
+
+#define HQV_CONTROL 0x1D0
+#define HQV_SRC_STARTADDR_Y 0x1D4
+#define HQV_SRC_STARTADDR_U 0x1D8
+#define HQV_SRC_STARTADDR_V 0x1DC
+#define HQV_MINIFY_DEBLOCK 0x1E8
+
+#define HQV_SW_FLIP 0x00000010
+#define HQV_FLIP_STATUS 0x00000001
+#define HQV_SUBPIC_FLIP 0x00008000
+#define HQV_FLIP_ODD 0x00000020
+#define HQV_DEINTERLACE 0x00010000
+#define HQV_FIELD_2_FRAME 0x00020000
+#define HQV_FRAME_2_FIELD 0x00040000
+#define HQV_FIELD_UV 0x00100000
+#define HQV_DEBLOCK_HOR 0x00008000
+#define HQV_DEBLOCK_VER 0x80000000
+
+#define V_COMPOSE_MODE 0x98
+#define V1_COMMAND_FIRE 0x80000000
+#define V3_COMMAND_FIRE 0x40000000
+
+/* SUBPICTURE Registers */
+#define SUBP_CONTROL_STRIDE 0x1C0
+#define SUBP_STARTADDR 0x1C4
+#define RAM_TABLE_CONTROL 0x1C8
+#define RAM_TABLE_READ 0x1CC
+
+/* SUBP_CONTROL_STRIDE 0x3c0 */
+#define SUBP_HQV_ENABLE 0x00010000
+#define SUBP_IA44 0x00020000
+#define SUBP_AI44 0x00000000
+#define SUBP_STRIDE_MASK 0x00001fff
+#define SUBP_CONTROL_MASK 0x00070000
+
+/* RAM_TABLE_CONTROL 0x3c8 */
+#define RAM_TABLE_RGB_ENABLE 0x00000007
+
+
+#define VIA_REG_STATUS 0x400
+#define VIA_REG_GEMODE 0x004
+#define VIA_REG_SRCBASE 0x030
+#define VIA_REG_DSTBASE 0x034
+#define VIA_REG_PITCH 0x038
+#define VIA_REG_SRCCOLORKEY 0x01C
+#define VIA_REG_KEYCONTROL 0x02C
+#define VIA_REG_SRCPOS 0x008
+#define VIA_REG_DSTPOS 0x00C
+#define VIA_REG_GECMD 0x000
+#define VIA_REG_DIMENSION 0x010 /* width and height */
+#define VIA_REG_FGCOLOR 0x018
+
+
+#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */
+#define VIA_CMD_RGTR_BUSY 0x00000080 /* Command Regulator is busy */
+#define VIA_2D_ENG_BUSY 0x00000001 /* 2D Engine is busy */
+#define VIA_3D_ENG_BUSY 0x00000002 /* 3D Engine is busy */
+#define VIA_GEM_8bpp 0x00000000
+#define VIA_GEM_16bpp 0x00000100
+#define VIA_GEM_32bpp 0x00000300
+#define VIA_GEC_BLT 0x00000001
+#define VIA_PITCH_ENABLE 0x80000000
+#define VIA_GEC_INCX 0x00000000
+#define VIA_GEC_DECY 0x00004000
+#define VIA_GEC_INCY 0x00000000
+#define VIA_GEC_DECX 0x00008000
+#define VIA_GEC_FIXCOLOR_PAT 0x00002000
+
+
+#define VIA_BLIT_CLEAR 0x00
+#define VIA_BLIT_COPY 0xCC
+#define VIA_BLIT_FILL 0xF0
+#define VIA_BLIT_SET 0xFF
+
+#define VIA_SYNCWAITTIMEOUT 50000 /* Might be a bit conservative */
+#define VIA_DMAWAITTIMEOUT 150000
+#define VIA_VIDWAITTIMEOUT 50000
+#define VIA_XVMC_DECODERTIMEOUT 50000 /*(microseconds)*/
+
+#define H1_ADDR(val) (((val) >> 2) | 0xF0000000)
+#define WAITFLAGS(xl, flags) \
+ (xl)->curWaitFlags |= (flags)
+#define BEGIN_RING_AGP(xl,size) \
+ do { \
+ if ((xl)->agp_pos > (LL_AGP_CMDBUF_SIZE-(size))) { \
+ agpFlush(xl); \
+ } \
+ } while(0)
+#define OUT_RING_AGP(xl, val) \
+ (xl)->agp_buffer[(xl)->agp_pos++] = (val)
+#define OUT_RING_QW_AGP(xl, val1, val2) \
+ do { \
+ (xl)->agp_buffer[(xl)->agp_pos++] = (val1); \
+ (xl)->agp_buffer[(xl)->agp_pos++] = (val2); \
+ } while (0)
+
+
+#define LL_HW_LOCK(xl) \
+ do { \
+ DRM_LOCK((xl)->fd,(xl)->hwLock,*(xl)->drmcontext,0); \
+ } while(0);
+#define LL_HW_UNLOCK(xl) \
+ do { \
+ DRM_UNLOCK((xl)->fd,(xl)->hwLock,*(xl)->drmcontext); \
+ } while(0);
+
+
+/*
+ * We want to have two concurrent types of thread taking the hardware
+ * lock simulataneously. One is the video out thread that needs immediate
+ * access to flip an image. The other is everything else which may have
+ * the lock for quite some time. This is only so the video out thread can
+ * sneak in and display an image while other resources are busy.
+ */
+
+
+void
+hwlLock(void *xlp, int videoLock)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ LL_HW_LOCK(xl);
+}
+
+void
+hwlUnlock(void *xlp, int videoLock)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ LL_HW_UNLOCK(xl);
+}
+
+static unsigned
+timeDiff(struct timeval *now,struct timeval *then) {
+ return (now->tv_usec >= then->tv_usec) ?
+ now->tv_usec - then->tv_usec :
+ 1000000 - (then->tv_usec - now->tv_usec);
+}
+
+void
+setAGPSyncLowLevel(void *xlp, int val, CARD32 timeStamp)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ xl->agpSync = val;
+ xl->agpSyncTimeStamp = timeStamp;
+}
+
+CARD32
+viaDMATimeStampLowLevel(void *xlp)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ if (xl->use_agp) {
+ viaBlit(xl, 32, xl->tsOffset, 1, xl->tsOffset, 1, 1, 1, 0, 0,
+ VIABLIT_FILL, xl->curTimeStamp);
+ return xl->curTimeStamp++;
+ }
+ return 0;
+}
+
+static void
+viaDMAWaitTimeStamp(XvMCLowLevel *xl, CARD32 timeStamp, int doSleep)
+{
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+
+ if (xl->use_agp && (timeStamp > xl->lastReadTimeStamp)) {
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+
+ while(timeStamp > (xl->lastReadTimeStamp = *xl->tsP)) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_DMAWAITTIMEOUT) {
+ if((timeStamp > (xl->lastReadTimeStamp = *xl->tsP))) {
+ xl->errors |= LL_DMA_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+ }
+}
+
+static int
+viaDMAInitTimeStamp(XvMCLowLevel *xl)
+{
+ int ret = 0;
+
+ if (xl->use_agp) {
+ xl->tsMem.context = *(xl->drmcontext);
+ xl->tsMem.size = 64;
+ xl->tsMem.type = VIA_MEM_VIDEO;
+ if (drmCommandWriteRead(xl->fd, DRM_VIA_ALLOCMEM, &xl->tsMem, sizeof(xl->tsMem)) < 0)
+ return ret;
+ if (xl->tsMem.size != 64)
+ return -1;
+ xl->tsOffset = (xl->tsMem.offset + 31) & ~31;
+ xl->tsP = (CARD32 *)xl->fbAddress + (xl->tsOffset >> 2);
+ xl->curTimeStamp = 1;
+ *xl->tsP = 0;
+ }
+ return 0;
+}
+
+static int
+viaDMACleanupTimeStamp(XvMCLowLevel *xl)
+{
+
+ if (!(xl->tsMem.size) || !xl->use_agp) return 0;
+ return drmCommandWrite(xl->fd, DRM_VIA_FREEMEM, &xl->tsMem, sizeof(xl->tsMem));
+}
+
+
+static CARD32
+viaMpegGetStatus(XvMCLowLevel *xl)
+{
+ return MPEGIN(xl,0x54);
+}
+
+static int
+viaMpegIsBusy(XvMCLowLevel *xl, CARD32 mask, CARD32 idle)
+{
+ CARD32 tmp = viaMpegGetStatus(xl);
+
+ /*
+ * Error detected.
+ * FIXME: Are errors really shown when error concealment is on?
+ */
+
+ if (tmp & 0x70) return 0;
+
+ return (tmp & mask) != idle;
+}
+
+
+static void
+syncDMA(XvMCLowLevel *xl, unsigned int doSleep)
+{
+
+ /*
+ * Ideally, we'd like to have an interrupt wait here, but, according to second hand
+ * information, the hardware does not support this, although earlier S3 chips do that.
+ * It is therefore not implemented into the DRM, and we'll do a user space wait here.
+ */
+
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+ while( !(REGIN(xl, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY)) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_DMAWAITTIMEOUT) {
+ if( !(REGIN(xl, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY)) {
+ xl->errors |= LL_DMA_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+ while( REGIN(xl, VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY ) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_DMAWAITTIMEOUT) {
+ if( REGIN(xl, VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY ) {
+ xl->errors |= LL_DMA_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+}
+
+static void
+syncVideo(XvMCLowLevel *xl, unsigned int doSleep)
+{
+ /*
+ * Wait for HQV completion. Nothing strange here. We assume that the HQV
+ * Handles syncing to the V1 / V3 engines by itself. It should be safe to
+ * always wait for SUBPIC_FLIP completion although subpictures are not always
+ * used.
+ */
+
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+ while(VIDIN(xl, HQV_CONTROL) & (HQV_SW_FLIP | HQV_SUBPIC_FLIP)) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_SYNCWAITTIMEOUT) {
+ if(VIDIN(xl, HQV_CONTROL) & (HQV_SW_FLIP | HQV_SUBPIC_FLIP)) {
+ xl->errors |= LL_VIDEO_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+}
+
+static void
+syncAccel(XvMCLowLevel *xl, unsigned int mode, unsigned int doSleep)
+{
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+ CARD32 mask = ((mode & LL_MODE_2D) ? VIA_2D_ENG_BUSY : 0) |
+ ((mode & LL_MODE_3D) ? VIA_3D_ENG_BUSY : 0);
+
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+ while( REGIN(xl, VIA_REG_STATUS) & mask) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_SYNCWAITTIMEOUT) {
+ if( REGIN(xl, VIA_REG_STATUS) & mask) {
+ xl->errors |= LL_ACCEL_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+}
+
+
+static void
+syncMpeg(XvMCLowLevel *xl, unsigned int mode, unsigned int doSleep)
+{
+ /*
+ * Ideally, we'd like to have an interrupt wait here, but from information from VIA
+ * at least the MPEG completion interrupt is broken on the CLE266, which was
+ * discovered during validation of the chip.
+ */
+
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+ CARD32 busyMask = 0;
+ CARD32 idleVal = 0;
+ CARD32 ret;
+
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+ if (mode & LL_MODE_DECODER_SLICE) {
+ busyMask = VIA_SLICEBUSYMASK;
+ idleVal = VIA_SLICEIDLEVAL;
+ }
+ if (mode & LL_MODE_DECODER_IDLE) {
+ busyMask |= VIA_BUSYMASK;
+ idleVal = VIA_IDLEVAL;
+ }
+ while(viaMpegIsBusy(xl, busyMask, idleVal)) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_XVMC_DECODERTIMEOUT) {
+ if (viaMpegIsBusy(xl, busyMask, idleVal)) {
+ xl->errors |= LL_DECODER_TIMEDOUT;
+ }
+ break;
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+
+ ret = viaMpegGetStatus(xl);
+ if (ret & 0x70) {
+ xl->errors |= ((ret & 0x70) >> 3);
+ }
+ return;
+}
+
+static void
+pciFlush(XvMCLowLevel *xl)
+{
+ int ret;
+ drm_via_cmdbuffer_t b;
+ unsigned mode=xl->curWaitFlags;
+
+ b.buf = (char *)xl->pci_buffer;
+ b.size = xl->pci_pos * sizeof(CARD32);
+ if (xl->performLocking) hwlLock(xl,0);
+ if ((mode != LL_MODE_VIDEO) && (mode != 0))
+ syncDMA(xl, 0);
+ if ((mode & LL_MODE_2D) || (mode & LL_MODE_3D))
+ syncAccel(xl, mode, 0);
+ if (mode & LL_MODE_VIDEO)
+ syncVideo(xl, 0);
+ if (mode & (LL_MODE_DECODER_SLICE | LL_MODE_DECODER_IDLE))
+ syncMpeg(xl, mode, 0);
+ ret = drmCommandWrite(xl->fd, DRM_VIA_PCICMD, &b, sizeof(b));
+ if (xl->performLocking) hwlUnlock(xl,0);
+ if (ret) {
+ xl->errors |= LL_PCI_COMMAND_ERR;
+ }
+ xl->pci_pos = 0;
+ xl->curWaitFlags = 0;
+}
+
+static void
+agpFlush(XvMCLowLevel *xl)
+{
+ drm_via_cmdbuffer_t b;
+ int ret;
+
+ if (xl->use_agp) {
+ b.buf = (char *)xl->agp_buffer;
+ b.size = xl->agp_pos * sizeof(CARD32);
+ if (xl->agpSync) {
+ syncXvMCLowLevel(xl, LL_MODE_DECODER_IDLE, 1, xl->agpSyncTimeStamp);
+ xl->agpSync = 0;
+ }
+ if (xl->performLocking) hwlLock(xl,0);
+ do {
+ ret = drmCommandWrite(xl->fd, DRM_VIA_CMDBUFFER, &b, sizeof(b));
+ } while (-EAGAIN == ret);
+ if (xl->performLocking) hwlUnlock(xl,0);
+
+ if (ret) {
+ xl->errors |= LL_AGP_COMMAND_ERR;
+ } else {
+ xl->agp_pos = 0;
+ }
+ xl->curWaitFlags &= LL_MODE_VIDEO;
+ } else {
+ unsigned mode=xl->curWaitFlags;
+
+ b.buf = (char *)xl->agp_buffer;
+ b.size = xl->agp_pos * sizeof(CARD32);
+ if (xl->performLocking) hwlLock(xl,0);
+ if ((mode != LL_MODE_VIDEO) && (mode != 0))
+ syncDMA(xl, 0);
+ if ((mode & LL_MODE_2D) || (mode & LL_MODE_3D))
+ syncAccel(xl, mode, 0);
+ if (mode & LL_MODE_VIDEO)
+ syncVideo(xl, 0);
+ if (mode & (LL_MODE_DECODER_SLICE | LL_MODE_DECODER_IDLE))
+ syncMpeg(xl, mode, 0);
+ ret = drmCommandWrite(xl->fd, DRM_VIA_PCICMD, &b, sizeof(b));
+ if (xl->performLocking) hwlUnlock(xl,0);
+ if (ret) {
+ xl->errors |= LL_PCI_COMMAND_ERR;
+ }
+ xl->agp_pos = 0;
+ xl->curWaitFlags = 0;
+ }
+}
+
+unsigned
+flushXvMCLowLevel(void *xlp)
+{
+ unsigned
+ errors;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ if(xl->pci_pos) pciFlush(xl);
+ if(xl->agp_pos) agpFlush(xl);
+ errors = xl->errors;
+ xl->errors = 0;
+ return errors;
+}
+
+void
+flushPCIXvMCLowLevel(void *xlp)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ if(xl->pci_pos) pciFlush(xl);
+ if (!xl->use_agp && xl->agp_pos) agpFlush(xl);
+}
+
+
+__inline static void pciCommand(XvMCLowLevel *xl, unsigned offset, unsigned value, unsigned flags)
+{
+ if (xl->pci_pos > (LL_PCI_CMDBUF_SIZE-2)) pciFlush(xl);
+ if (flags) xl->curWaitFlags |= flags;
+ xl->pci_buffer[xl->pci_pos++] = (offset >> 2) | 0xF0000000;
+ xl->pci_buffer[xl->pci_pos++] = value;
+}
+
+void
+viaMpegSetSurfaceStride(void *xlp, ViaXvMCContext *ctx)
+{
+ CARD32 y_stride = ctx->yStride;
+ CARD32 uv_stride = y_stride >> 1;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+
+ BEGIN_RING_AGP(xl, 2);
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc50), (y_stride >> 3) | ((uv_stride >> 3) << 16));
+ WAITFLAGS(xl, LL_MODE_DECODER_IDLE);
+}
+
+
+void
+viaVideoSetSWFLipLocked(void *xlp, unsigned yOffs, unsigned uOffs,
+ unsigned vOffs, unsigned yStride, unsigned uvStride)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ pciCommand(xl,HQV_SRC_STARTADDR_Y | 0x200,yOffs,LL_MODE_VIDEO);
+ pciCommand(xl,HQV_SRC_STARTADDR_U | 0x200,uOffs,0);
+ pciCommand(xl,HQV_SRC_STARTADDR_V | 0x200,vOffs,0);
+}
+
+void
+viaVideoSWFlipLocked(void *xlp, unsigned flags,
+ int progressiveSequence)
+{
+ CARD32 andWd,orWd;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ andWd = 0;
+ orWd = 0;
+
+ if ((flags & XVMC_FRAME_PICTURE) == XVMC_BOTTOM_FIELD) {
+ andWd = 0xFFFFFFFFU;
+ orWd = HQV_FIELD_UV |
+ HQV_DEINTERLACE |
+ HQV_FIELD_2_FRAME |
+ HQV_FRAME_2_FIELD |
+ HQV_SW_FLIP |
+ HQV_FLIP_ODD |
+ HQV_FLIP_STATUS |
+ HQV_SUBPIC_FLIP;
+ } else if ((flags & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) {
+ andWd = ~HQV_FLIP_ODD;
+ orWd = HQV_FIELD_UV |
+ HQV_DEINTERLACE |
+ HQV_FIELD_2_FRAME |
+ HQV_FRAME_2_FIELD |
+ HQV_SW_FLIP |
+ HQV_FLIP_STATUS |
+ HQV_SUBPIC_FLIP;
+ } else if ((flags & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
+ andWd = ~(HQV_DEINTERLACE |
+ HQV_FRAME_2_FIELD |
+ HQV_FIELD_2_FRAME |
+ HQV_FIELD_UV);
+ orWd = HQV_SW_FLIP |
+ HQV_FLIP_STATUS |
+ HQV_SUBPIC_FLIP;
+ }
+ if (progressiveSequence) {
+ andWd &= ~HQV_FIELD_UV;
+ orWd &= ~HQV_FIELD_UV;
+ }
+
+ pciCommand(xl,HQV_CONTROL | 0x200,(VIDIN(xl,HQV_CONTROL) & andWd) | orWd, 0);
+}
+
+void
+viaMpegSetFB(void *xlp,unsigned i,
+ unsigned yOffs,
+ unsigned uOffs,
+ unsigned vOffs)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ i *= 12;
+ BEGIN_RING_AGP(xl, 6);
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc20 + i), yOffs >> 3);
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc24 + i), uOffs >> 3);
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc28 + i), vOffs >> 3);
+ WAITFLAGS(xl, LL_MODE_DECODER_IDLE);
+}
+
+void
+viaMpegBeginPicture(void *xlp,ViaXvMCContext *ctx,
+ unsigned width,
+ unsigned height,
+ const XvMCMpegControl *control) {
+
+ unsigned j, mb_width, mb_height;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ mb_width = (width + 15) >> 4;
+
+ mb_height =
+ ((control->mpeg_coding == XVMC_MPEG_2) &&
+ (control->flags & XVMC_PROGRESSIVE_SEQUENCE)) ?
+ 2*((height+31) >> 5) : (((height+15) >> 4));
+
+ BEGIN_RING_AGP(xl, 144);
+ WAITFLAGS(xl, LL_MODE_DECODER_IDLE);
+
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc00),
+ ((control->picture_structure & XVMC_FRAME_PICTURE) << 2) |
+ ((control->picture_coding_type & 3) << 4) |
+ ((control->flags & XVMC_ALTERNATE_SCAN) ? (1 << 6) : 0));
+
+ if (!(ctx->intraLoaded)) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc5c), 0);
+ for (j = 0; j < 64; j += 4) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc60),
+ ctx->intra_quantiser_matrix[j] |
+ (ctx->intra_quantiser_matrix[j+1] << 8) |
+ (ctx->intra_quantiser_matrix[j+2] << 16) |
+ (ctx->intra_quantiser_matrix[j+3] << 24));
+ }
+ ctx->intraLoaded = 1;
+ }
+
+ if (!(ctx->nonIntraLoaded)) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc5c), 1);
+ for (j = 0; j < 64; j += 4) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc60),
+ ctx->non_intra_quantiser_matrix[j] |
+ (ctx->non_intra_quantiser_matrix[j+1] << 8) |
+ (ctx->non_intra_quantiser_matrix[j+2] << 16) |
+ (ctx->non_intra_quantiser_matrix[j+3] << 24));
+ }
+ ctx->nonIntraLoaded = 1;
+ }
+
+ if (!(ctx->chromaIntraLoaded)) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc5c), 2);
+ for (j = 0; j < 64; j += 4) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc60),
+ ctx->chroma_intra_quantiser_matrix[j] |
+ (ctx->chroma_intra_quantiser_matrix[j+1] << 8) |
+ (ctx->chroma_intra_quantiser_matrix[j+2] << 16) |
+ (ctx->chroma_intra_quantiser_matrix[j+3] << 24));
+ }
+ ctx->chromaIntraLoaded = 1;
+ }
+
+ if (!(ctx->chromaNonIntraLoaded)) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc5c), 3);
+ for (j = 0; j < 64; j += 4) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc60),
+ ctx->chroma_non_intra_quantiser_matrix[j] |
+ (ctx->chroma_non_intra_quantiser_matrix[j+1] << 8) |
+ (ctx->chroma_non_intra_quantiser_matrix[j+2] << 16) |
+ (ctx->chroma_non_intra_quantiser_matrix[j+3] << 24));
+ }
+ ctx->chromaNonIntraLoaded = 1;
+ }
+
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc90),
+ ((mb_width * mb_height) & 0x3fff) |
+ ((control->flags & XVMC_PRED_DCT_FRAME) ? ( 1 << 14) : 0) |
+ ((control->flags & XVMC_TOP_FIELD_FIRST) ? (1 << 15) : 0 ) |
+ ((control->mpeg_coding == XVMC_MPEG_2) ? (1 << 16) : 0) |
+ ((mb_width & 0xff) << 18));
+
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc94),
+ ((control->flags & XVMC_CONCEALMENT_MOTION_VECTORS) ? 1 : 0) |
+ ((control->flags & XVMC_Q_SCALE_TYPE) ? 2 : 0) |
+ ((control->intra_dc_precision & 3) << 2) |
+ (((1 + 0x100000 / mb_width) & 0xfffff) << 4) |
+ ((control->flags & XVMC_INTRA_VLC_FORMAT) ? (1 << 24) : 0));
+
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc98),
+ (((control->FHMV_range) & 0xf) << 0) |
+ (((control->FVMV_range) & 0xf) << 4) |
+ (((control->BHMV_range) & 0xf) << 8) |
+ (((control->BVMV_range) & 0xf) << 12) |
+ ((control->flags & XVMC_SECOND_FIELD) ? (1 << 20) : 0) |
+ (0x0a6 << 16));
+
+}
+
+
+
+void
+viaMpegReset(void *xlp)
+{
+ int i,j;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ BEGIN_RING_AGP(xl, 100);
+ WAITFLAGS(xl, LL_MODE_DECODER_IDLE);
+
+ for (i = 0; i < 14; i++)
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc08) ,0);
+
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc98), 0x400000);
+
+ for (i = 0; i < 6; i++) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc0c), 0x43 | 0x20);
+ for (j = 0xc10; j < 0xc20; j += 4)
+ OUT_RING_QW_AGP(xl, H1_ADDR(j), 0);
+ }
+
+
+ OUT_RING_QW_AGP(xl,H1_ADDR(0xc0c), 0xc3 | 0x20);
+ for (j = 0xc10; j < 0xc20; j += 4)
+ OUT_RING_QW_AGP(xl,H1_ADDR(j),0);
+
+}
+
+void
+viaMpegWriteSlice(void *xlp, CARD8* slice, int nBytes, CARD32 sCode)
+{
+ int i, n, r;
+ CARD32* buf;
+ int count;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+
+ if (xl->errors & (LL_DECODER_TIMEDOUT |
+ LL_IDCT_FIFO_ERROR |
+ LL_SLICE_FIFO_ERROR |
+ LL_SLICE_FAULT)) return;
+
+ n = nBytes >> 2;
+ if (sCode) nBytes += 4;
+ r = nBytes & 3;
+ buf = (CARD32*) slice;
+
+ if (r) nBytes += 4 - r;
+
+ nBytes += 8;
+
+ BEGIN_RING_AGP(xl, 4);
+ WAITFLAGS(xl, LL_MODE_DECODER_IDLE);
+
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xc9c), nBytes);
+
+ if (sCode) OUT_RING_QW_AGP(xl, H1_ADDR(0xca0), sCode);
+
+ i = 0;
+ count = 0;
+
+ do {
+ count += (LL_AGP_CMDBUF_SIZE -20) >> 1;
+ count = (count > n) ? n : count;
+ BEGIN_RING_AGP(xl, (count - i) << 1);
+
+ for (; i < count; i++) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xca0), *buf++);
+ }
+ } while (i < n);
+
+ BEGIN_RING_AGP(xl, 6);
+
+ if (r) {
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xca0), *buf & ((1 << (r << 3)) - 1));
+ }
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xca0), 0);
+ OUT_RING_QW_AGP(xl, H1_ADDR(0xca0), 0);
+
+}
+
+void
+viaVideoSubPictureOffLocked(void *xlp) {
+
+ CARD32 stride;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+
+ stride = VIDIN(xl,SUBP_CONTROL_STRIDE);
+
+ pciCommand(xl, SUBP_CONTROL_STRIDE | 0x200, stride & ~SUBP_HQV_ENABLE,LL_MODE_VIDEO);
+}
+
+void
+viaVideoSubPictureLocked(void *xlp,ViaXvMCSubPicture *pViaSubPic) {
+
+ unsigned i;
+ CARD32 cWord;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+
+ for (i=0; i<VIA_SUBPIC_PALETTE_SIZE; ++i) {
+ pciCommand(xl, RAM_TABLE_CONTROL | 0x200, pViaSubPic->palette[i],LL_MODE_VIDEO);
+ }
+
+ pciCommand(xl, SUBP_STARTADDR | 0x200, pViaSubPic->offset, 0);
+ cWord = (pViaSubPic->stride & SUBP_STRIDE_MASK) | SUBP_HQV_ENABLE;
+ cWord |= (pViaSubPic->ia44) ? SUBP_IA44 : SUBP_AI44;
+ pciCommand(xl, SUBP_CONTROL_STRIDE | 0x200, cWord, 0);
+}
+
+void
+viaBlit(void *xlp,unsigned bpp,unsigned srcBase,
+ unsigned srcPitch,unsigned dstBase,unsigned dstPitch,
+ unsigned w,unsigned h,int xdir,int ydir, unsigned blitMode,
+ unsigned color)
+{
+
+ CARD32 dwGEMode = 0, srcY=0, srcX, dstY=0, dstX;
+ CARD32 cmd;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+
+ if (!w || !h)
+ return;
+
+ switch (bpp) {
+ case 16:
+ dwGEMode |= VIA_GEM_16bpp;
+ break;
+ case 32:
+ dwGEMode |= VIA_GEM_32bpp;
+ break;
+ default:
+ dwGEMode |= VIA_GEM_8bpp;
+ break;
+ }
+
+ srcX = srcBase & 31;
+ dstX = dstBase & 31;
+ switch (bpp) {
+ case 16:
+ dwGEMode |= VIA_GEM_16bpp;
+ srcX >>= 2;
+ dstX >>= 2;
+ break;
+ case 32:
+ dwGEMode |= VIA_GEM_32bpp;
+ srcX >>= 4;
+ dstX >>= 4;
+ break;
+ default:
+ dwGEMode |= VIA_GEM_8bpp;
+ break;
+ }
+
+ BEGIN_RING_AGP(xl, 20);
+ WAITFLAGS(xl, LL_MODE_2D);
+
+
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_GEMODE), dwGEMode);
+ cmd = 0;
+
+ if (xdir < 0) {
+ cmd |= VIA_GEC_DECX;
+ srcX += (w - 1);
+ dstX += (w - 1);
+ }
+ if (ydir < 0) {
+ cmd |= VIA_GEC_DECY;
+ srcY += (h - 1);
+ dstY += (h - 1);
+ }
+
+ switch(blitMode) {
+ case VIABLIT_TRANSCOPY:
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_SRCCOLORKEY), color);
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_KEYCONTROL), 0x4000);
+ cmd |= VIA_GEC_BLT | (VIA_BLIT_COPY << 24);
+ break;
+ case VIABLIT_FILL:
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_FGCOLOR), color);
+ cmd |= VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | (VIA_BLIT_FILL << 24);
+ break;
+ default:
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_KEYCONTROL), 0x0);
+ cmd |= VIA_GEC_BLT | (VIA_BLIT_COPY << 24);
+ }
+
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_SRCBASE), (srcBase & ~31) >> 3);
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_DSTBASE), (dstBase & ~31) >> 3);
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_PITCH), VIA_PITCH_ENABLE |
+ (srcPitch >> 3) | (((dstPitch) >> 3) << 16));
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_SRCPOS), ((srcY << 16) | srcX));
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_DSTPOS), ((dstY << 16) | dstX));
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_DIMENSION), (((h - 1) << 16) | (w - 1)));
+ OUT_RING_QW_AGP(xl, H1_ADDR(VIA_REG_GECMD), cmd);
+}
+
+unsigned
+syncXvMCLowLevel(void *xlp, unsigned int mode, unsigned int doSleep,
+ CARD32 timeStamp)
+{
+ unsigned
+ errors;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ if (mode == 0) {
+ errors = xl->errors;
+ xl->errors = 0;
+ return errors;
+ }
+
+ if ((mode & (LL_MODE_VIDEO | LL_MODE_3D)) || !xl->use_agp) {
+ if (xl->performLocking)
+ hwlLock(xl,0);
+ if ((mode != LL_MODE_VIDEO))
+ syncDMA(xl, doSleep);
+ if (mode & LL_MODE_3D)
+ syncAccel(xl, mode, doSleep);
+ if (mode & LL_MODE_VIDEO)
+ syncVideo(xl, doSleep);
+ if (xl->performLocking)
+ hwlUnlock(xl,0);
+ } else {
+ viaDMAWaitTimeStamp(xl, timeStamp, doSleep);
+ }
+
+ if (mode & (LL_MODE_DECODER_SLICE | LL_MODE_DECODER_IDLE))
+ syncMpeg(xl, mode, doSleep);
+
+ errors = xl->errors;
+ xl->errors = 0;
+
+ return errors;
+}
+
+
+extern void
+*initXvMCLowLevel(int fd, drm_context_t *ctx,
+ drmLockPtr hwLock, drmAddress mmioAddress,
+ drmAddress fbAddress, unsigned fbStride, unsigned fbDepth,
+ unsigned width, unsigned height, int useAgp, unsigned chipId )
+
+{
+ int ret;
+
+ XvMCLowLevel *xl = (XvMCLowLevel *)malloc(sizeof(XvMCLowLevel));
+ if (!xl) return NULL;
+
+ xl->agp_pos = 0;
+ xl->pci_pos = 0;
+ xl->use_agp = useAgp;
+ xl->fd = fd;
+ xl->drmcontext = ctx;
+ xl->hwLock = hwLock;
+ xl->mmioAddress = mmioAddress;
+ xl->fbAddress = fbAddress;
+ xl->curWaitFlags = 0;
+ xl->performLocking = 1;
+ xl->errors = 0;
+ xl->agpSync = 0;
+ ret = viaDMAInitTimeStamp(xl);
+ if (ret) {
+ free(xl);
+ return NULL;
+ }
+ return xl;
+}
+
+void
+setLowLevelLocking(void *xlp, int performLocking)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ xl->performLocking = performLocking;
+}
+
+void
+closeXvMCLowLevel(void *xlp)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ viaDMACleanupTimeStamp(xl);
+ free(xl);
+}
+
diff --git a/nx-X11/lib/XvMC/hw/via/unichromeProA/Imakefile b/nx-X11/lib/XvMC/hw/via/unichromeProA/Imakefile
new file mode 100644
index 000000000..f87ae9b05
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/unichromeProA/Imakefile
@@ -0,0 +1,50 @@
+#define DoNormalLib NormalLibXvMC
+#define DoSharedLib SharedLibXvMC
+#define DoDebugLib DebugLibXvMC
+#define DoProfileLib ProfileLibXvMC
+#define LibName viaXvMCPro
+#define SoRev SOXVMCREV
+#define LibHeaders NO
+
+#include <Threads.tmpl>
+
+#ifdef SharedXvMCReqs
+REQUIREDLIBS = SharedXvMCReqs -lXv
+#endif
+
+#if Malloc0ReturnsNull
+ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL
+#endif
+
+ DEFINES = $(ALLOC_DEFINES) -DTRUE=1 -DFALSE=0
+ INCLUDES = -I$(XINCLUDESRC) -I$(INCLUDESRC) -I$(XLIBSRC) -I$(EXTINCSRC) \
+ -I$(XF86COMSRC) -I$(XF86OSSRC) -I$(DRMSRCDIR)/shared-core \
+ -I$(XF86OSSRC)/linux/drm/kernel -I$(XF86DRIVERSRC)/via
+ SRCS = viaLowLevelPro.c
+ OBJS = viaXvMC.o viaLowLevelPro.o xf86drm.o xf86drmHash.o \
+ xf86drmRandom.o xf86drmSL.o xf86dri.o driDrawable.o
+ LINTLIBS = $(LINTXLIB)
+
+
+#include <Library.tmpl>
+
+
+#if defined(LinuxArchitecture)
+LIBDRM_DIR = ../../../../../extras/drm/libdrm
+
+LinkSourceFile(xf86drm.c,$(LIBDRM_DIR))
+LinkSourceFile(xf86drmHash.c,$(LIBDRM_DIR))
+LinkSourceFile(xf86drmRandom.c,$(LIBDRM_DIR))
+LinkSourceFile(xf86drmSL.c,$(LIBDRM_DIR))
+LinkSourceFile(viaLowLevel.h,..)
+LinkSourceFile(driDrawable.h,..)
+LinkSourceFile(viaXvMCPriv.h,..)
+LinkSourceFile(xf86dri.h,..)
+LinkSourceFile(xf86dristr.h,..)
+LinkSourceFile(xf86dri.c,..)
+LinkSourceFile(driDrawable.c,..)
+LinkSourceFile(viaXvMC.c,..)
+#endif
+
+DependTarget()
+
diff --git a/nx-X11/lib/XvMC/hw/via/unichromeProA/viaLowLevelPro.c b/nx-X11/lib/XvMC/hw/via/unichromeProA/viaLowLevelPro.c
new file mode 100644
index 000000000..666166c96
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/unichromeProA/viaLowLevelPro.c
@@ -0,0 +1,1465 @@
+/*****************************************************************************
+ * VIA Unichrome XvMC extension client lib.
+ *
+ * Copyright (c) 2004 Thomas Hellström. All rights reserved.
+ * Copyright (c) 2003 Andreas Robinson. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Low-level functions that deal directly with the hardware. In the future,
+ * these functions might be implemented in a kernel module. Also, some of them
+ * would benefit from DMA.
+ *
+ * Authors:
+ * Andreas Robinson 2003. (Initial decoder interface functions).
+ * Thomas Hellstrom 2004, 2005 (Blitting functions, AGP and locking, Unichrome Pro Video AGP).
+ * Ivor Hewitt 2005 (Unichrome Pro modifications and merging).
+ */
+
+/* IH
+ * I've left the proReg or-ing in case we need/want to implement the V1/V3
+ * register toggle too, which also moves the register locations.
+ * The CN400 has dual mpeg decoders, not sure at the moment whether these
+ * are also operated through independent registers also.
+ */
+
+#undef VIDEO_DMA
+#define HQV_USE_IRQ
+#define UNICHROME_PRO
+
+#include "viaXvMCPriv.h"
+#include "viaLowLevel.h"
+#include "driDrawable.h"
+#include <time.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+typedef enum {ll_init, ll_agpBuf, ll_pciBuf, ll_timeStamp, ll_llBuf}
+ LLState;
+
+
+typedef struct {
+ drm_via_mem_t mem;
+ unsigned offset;
+ unsigned stride;
+ unsigned height;
+} LowLevelBuffer;
+
+struct _XvMCLowLevel;
+
+typedef struct _ViaCommandBuffer {
+ CARD32 *buf;
+ CARD32 waitFlags;
+ unsigned pos;
+ unsigned bufSize;
+ int mode;
+ int header_start;
+ int rindex;
+ void (*flushFunc)(struct _ViaCommandBuffer *cb, struct _XvMCLowLevel *xl);
+} ViaCommandBuffer;
+
+typedef struct _XvMCLowLevel{
+ ViaCommandBuffer agpBuf, pciBuf, *videoBuf;
+ int use_agp;
+ int fd;
+ drm_context_t *drmcontext;
+ drmLockPtr hwLock;
+ drmAddress mmioAddress;
+ drmAddress fbAddress;
+ unsigned fbStride;
+ unsigned fbDepth;
+ unsigned width;
+ unsigned height;
+ int performLocking;
+ unsigned errors;
+ drm_via_mem_t tsMem;
+ CARD32 tsOffset;
+ volatile CARD32 *tsP;
+ CARD32 curTimeStamp;
+ CARD32 lastReadTimeStamp;
+ int agpSync;
+ CARD32 agpSyncTimeStamp;
+ unsigned chipId;
+
+ /*
+ * Data for video-engine less display
+ */
+
+ XvMCRegion sRegion;
+ XvMCRegion dRegion;
+ LowLevelBuffer scale;
+ LowLevelBuffer back;
+ Bool downScaling;
+ CARD32 downScaleW;
+ CARD32 downScaleH;
+ CARD32 upScaleW;
+ CARD32 upScaleH;
+ unsigned fetch;
+ unsigned line;
+ LLState state;
+}XvMCLowLevel;
+
+
+/*
+ * For Other architectures than i386 these might have to be modified for
+ * bigendian etc.
+ */
+
+
+#define MPEGIN(xl,reg) \
+ *((volatile CARD32 *)(((CARD8 *)(xl)->mmioAddress) + 0xc00 + (reg)))
+
+#define VIDIN(ctx,reg) \
+ *((volatile CARD32 *)(((CARD8 *)(ctx)->mmioAddress) + 0x200 + (reg)))
+
+#define REGIN(ctx,reg) \
+ *((volatile CARD32 *)(((CARD8 *)(ctx)->mmioAddress) + 0x0000 + (reg)))
+
+#define HQV_CONTROL 0x1D0
+#define HQV_SRC_OFFSET 0x1CC
+#define HQV_SRC_STARTADDR_Y 0x1D4
+#define HQV_SRC_STARTADDR_U 0x1D8
+#define HQV_SRC_STARTADDR_V 0x1DC
+#define HQV_MINIFY_DEBLOCK 0x1E8
+
+#define REG_HQV1_INDEX 0x00001000
+
+#define HQV_SW_FLIP 0x00000010
+#define HQV_FLIP_STATUS 0x00000001
+#define HQV_SUBPIC_FLIP 0x00008000
+#define HQV_FLIP_ODD 0x00000020
+#define HQV_DEINTERLACE 0x00010000
+#define HQV_FIELD_2_FRAME 0x00020000
+#define HQV_FRAME_2_FIELD 0x00040000
+#define HQV_FIELD_UV 0x00100000
+#define HQV_DEBLOCK_HOR 0x00008000
+#define HQV_DEBLOCK_VER 0x80000000
+#define HQV_YUV420 0xC0000000
+#define HQV_YUV422 0x80000000
+#define HQV_ENABLE 0x08000000
+#define HQV_GEN_IRQ 0x00000080
+
+#define HQV_SCALE_ENABLE 0x00000800
+#define HQV_SCALE_DOWN 0x00001000
+
+#define V_COMPOSE_MODE 0x98
+#define V1_COMMAND_FIRE 0x80000000
+#define V3_COMMAND_FIRE 0x40000000
+
+/* SUBPICTURE Registers */
+#define SUBP_CONTROL_STRIDE 0x1C0
+#define SUBP_STARTADDR 0x1C4
+#define RAM_TABLE_CONTROL 0x1C8
+#define RAM_TABLE_READ 0x1CC
+
+/* SUBP_CONTROL_STRIDE 0x3c0 */
+#define SUBP_HQV_ENABLE 0x00010000
+#define SUBP_IA44 0x00020000
+#define SUBP_AI44 0x00000000
+#define SUBP_STRIDE_MASK 0x00001fff
+#define SUBP_CONTROL_MASK 0x00070000
+
+/* RAM_TABLE_CONTROL 0x3c8 */
+#define RAM_TABLE_RGB_ENABLE 0x00000007
+
+
+#define VIA_REG_STATUS 0x400
+#define VIA_REG_GEMODE 0x004
+#define VIA_REG_SRCBASE 0x030
+#define VIA_REG_DSTBASE 0x034
+#define VIA_REG_PITCH 0x038
+#define VIA_REG_SRCCOLORKEY 0x01C
+#define VIA_REG_KEYCONTROL 0x02C
+#define VIA_REG_SRCPOS 0x008
+#define VIA_REG_DSTPOS 0x00C
+#define VIA_REG_GECMD 0x000
+#define VIA_REG_DIMENSION 0x010 /* width and height */
+#define VIA_REG_FGCOLOR 0x018
+
+
+#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */
+#define VIA_CMD_RGTR_BUSY 0x00000080 /* Command Regulator is busy */
+#define VIA_2D_ENG_BUSY 0x00000001 /* 2D Engine is busy */
+#define VIA_3D_ENG_BUSY 0x00000002 /* 3D Engine is busy */
+#define VIA_GEM_8bpp 0x00000000
+#define VIA_GEM_16bpp 0x00000100
+#define VIA_GEM_32bpp 0x00000300
+#define VIA_GEC_BLT 0x00000001
+#define VIA_PITCH_ENABLE 0x80000000
+#define VIA_GEC_INCX 0x00000000
+#define VIA_GEC_DECY 0x00004000
+#define VIA_GEC_INCY 0x00000000
+#define VIA_GEC_DECX 0x00008000
+#define VIA_GEC_FIXCOLOR_PAT 0x00002000
+
+
+#define VIA_BLIT_CLEAR 0x00
+#define VIA_BLIT_COPY 0xCC
+#define VIA_BLIT_FILL 0xF0
+#define VIA_BLIT_SET 0xFF
+
+#define VIA_SYNCWAITTIMEOUT 50000 /* Might be a bit conservative */
+#define VIA_DMAWAITTIMEOUT 150000
+#define VIA_VIDWAITTIMEOUT 50000
+#define VIA_XVMC_DECODERTIMEOUT 50000 /*(microseconds)*/
+
+#define VIA_AGP_HEADER5 0xFE040000
+#define VIA_AGP_HEADER6 0xFE050000
+
+typedef struct{
+ CARD32 data;
+ Bool set;
+} HQVRegister;
+
+
+#define H1_ADDR(val) (((val) >> 2) | 0xF0000000)
+#define WAITFLAGS(cb, flags) \
+ (cb)->waitFlags |= (flags)
+#define BEGIN_RING_AGP(cb, xl, size) \
+ do { \
+ if ((cb)->pos > ((cb)->bufSize-(size))) { \
+ cb->flushFunc(cb, xl); \
+ } \
+ } while(0)
+#define OUT_RING_AGP(cb, val) do{ \
+ (cb)->buf[(cb)->pos++] = (val); \
+ } while(0);
+
+#define OUT_RING_QW_AGP(cb, val1, val2) \
+ do { \
+ (cb)->buf[(cb)->pos++] = (val1); \
+ (cb)->buf[(cb)->pos++] = (val2); \
+ } while (0)
+
+
+#define BEGIN_HEADER5_AGP(cb, xl, index) \
+ do { \
+ BEGIN_RING_AGP(cb, xl, 8); \
+ (cb)->mode = VIA_AGP_HEADER5; \
+ (cb)->rindex = (index); \
+ (cb)->header_start = (cb)->pos; \
+ (cb)->pos += 4; \
+ } while (0)
+
+#define BEGIN_HEADER6_AGP(cb, xl) \
+ do { \
+ BEGIN_RING_AGP(cb, xl, 8); \
+ (cb)->mode = VIA_AGP_HEADER6; \
+ (cb)->header_start = (cb)->pos; \
+ (cb)->pos += 4; \
+ } while (0)
+
+#define BEGIN_HEADER5_DATA(cb, xl, size, index) \
+ do { \
+ if ((cb)->pos > ((cb)->bufSize - ((size) + 16))) { \
+ cb->flushFunc(cb, xl); \
+ BEGIN_HEADER5_AGP(cb, xl, index); \
+ } else if ((cb)->mode && (((cb)->mode != VIA_AGP_HEADER5) || \
+ ((cb)->rindex != index))) { \
+ finish_header_agp(cb); \
+ BEGIN_HEADER5_AGP((cb), xl, (index)); \
+ } else if (cb->mode != VIA_AGP_HEADER5) { \
+ BEGIN_HEADER5_AGP((cb), xl, (index)); \
+ } \
+ }while(0)
+
+#define BEGIN_HEADER6_DATA(cb, xl, size) \
+ do{ \
+ if ((cb)->pos > (cb->bufSize-(((size) << 1) + 16))) { \
+ cb->flushFunc(cb, xl); \
+ BEGIN_HEADER6_AGP(cb, xl); \
+ } else if ((cb)->mode && ((cb)->mode != VIA_AGP_HEADER6)) { \
+ finish_header_agp(cb); \
+ BEGIN_HEADER6_AGP(cb, xl); \
+ } \
+ else if ((cb->mode != VIA_AGP_HEADER6)) { \
+ BEGIN_HEADER6_AGP(cb, (xl)); \
+ } \
+ }while(0)
+
+#define HQV_SHADOW_BASE 0x3CC
+#define HQV_SHADOW_SIZE 13
+
+#define SETHQVSHADOW(shadow, offset, value) \
+ do { \
+ HQVRegister *r = (shadow) + (((offset) - HQV_SHADOW_BASE) >> 2); \
+ r->data = (value); \
+ r->set = TRUE; \
+ } while(0)
+
+#define GETHQVSHADOW(shadow, offset) ((shadow)[(offset - HQV_SHADOW_BASE) >> 2].data)
+
+#define LL_HW_LOCK(xl) \
+ do { \
+ DRM_LOCK((xl)->fd,(xl)->hwLock,*(xl)->drmcontext,0); \
+ } while(0);
+#define LL_HW_UNLOCK(xl) \
+ do { \
+ DRM_UNLOCK((xl)->fd,(xl)->hwLock,*(xl)->drmcontext); \
+ } while(0);
+
+static HQVRegister hqvShadow[HQV_SHADOW_SIZE];
+
+
+static void
+initHQVShadow(HQVRegister *r)
+{
+ int i;
+
+ for(i=0; i<HQV_SHADOW_SIZE; ++i) {
+ r->data = 0;
+ r++->set = FALSE;
+ }
+}
+
+static void
+setHQVDeblocking(HQVRegister *shadow, Bool on, Bool lowPass)
+{
+ CARD32 tmp = GETHQVSHADOW(shadow, 0x3DC);
+
+ if (!on) {
+ tmp &= ~(1 << 27);
+ SETHQVSHADOW(shadow, 0x3DC , tmp);
+ return;
+ }
+
+ tmp |= (8 << 16) | (1 << 27);
+ if (lowPass)
+ tmp |= (1 << 26);
+ SETHQVSHADOW(shadow, 0x3DC , tmp);
+
+ tmp = GETHQVSHADOW(shadow, 0x3D4);
+ tmp |= (6 << 27);
+ SETHQVSHADOW(shadow, 0x3D4, tmp);
+
+ tmp = GETHQVSHADOW(shadow, 0x3D8);
+ tmp |= (19 << 27);
+ SETHQVSHADOW(shadow, 0x3D8, tmp);
+}
+
+static void
+setHQVStartAddress(HQVRegister *shadow, unsigned yOffs, unsigned uOffs,
+ unsigned stride, unsigned format)
+{
+ CARD32 tmp = GETHQVSHADOW(shadow, 0x3D4);
+
+ tmp |= yOffs & 0x03FFFFF0;
+ SETHQVSHADOW(shadow, 0x3D4, tmp);
+ tmp = GETHQVSHADOW(shadow, 0x3D8);
+ tmp |= uOffs & 0x03FFFFF0;
+ SETHQVSHADOW(shadow, 0x3D8, tmp);
+ tmp = GETHQVSHADOW(shadow, 0x3F8);
+ tmp |= (stride & 0x1FF8);
+ SETHQVSHADOW(shadow, 0x3F8, tmp);
+ tmp = GETHQVSHADOW(shadow, 0x3D0);
+
+ if (format == 0) {
+ /*
+ * NV12
+ */
+ tmp |= (0x0C << 28);
+ } else if (format == 1) {
+ /*
+ * RGB16
+ */
+ tmp |= (0x02 << 28);
+ } else if (format == 2) {
+ /*
+ * RGB32
+ */
+ ;
+ }
+ SETHQVSHADOW(shadow, 0x3D0, tmp);
+}
+
+static void
+setHQVDeinterlacing(HQVRegister *shadow, CARD32 frameType)
+{
+ CARD32 tmp = GETHQVSHADOW(shadow, 0x3D0);
+
+
+ if ((frameType & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) {
+ tmp |= HQV_FIELD_UV |
+ HQV_DEINTERLACE |
+ HQV_FIELD_2_FRAME |
+ HQV_FRAME_2_FIELD;
+ } else if ((frameType & XVMC_FRAME_PICTURE) == XVMC_BOTTOM_FIELD) {
+ tmp |= HQV_FIELD_UV |
+ HQV_DEINTERLACE |
+ HQV_FIELD_2_FRAME |
+ HQV_FRAME_2_FIELD |
+ HQV_FLIP_ODD;
+ }
+ SETHQVSHADOW(shadow, 0x3D0, tmp);
+}
+
+static void
+setHQVTripleBuffer(HQVRegister *shadow, Bool on)
+{
+ CARD32 tmp = GETHQVSHADOW(shadow, 0x3D0);
+
+ if (on)
+ tmp |= ( 1 << 26 );
+ else
+ tmp &= ~( 1 << 26 );
+ SETHQVSHADOW(shadow, 0x3D0, tmp);
+}
+
+static void
+finish_header_agp(ViaCommandBuffer *cb)
+{
+ int
+ numDWords,i;
+ CARD32
+ *hb;
+
+ if (!cb->mode) return;
+ numDWords = cb->pos - cb->header_start - 4;
+ hb = cb->buf + cb->header_start;
+ switch (cb->mode) {
+ case VIA_AGP_HEADER5:
+ hb[0] = VIA_AGP_HEADER5 | cb->rindex;
+ hb[1] = numDWords ;
+ hb[2] = 0x00F50000; /* SW debug flag. (?) */
+ break;
+ default:
+ hb[0] = VIA_AGP_HEADER6;
+ hb[1] = numDWords >> 1 ;
+ hb[2] = 0x00F60000; /* SW debug flag. (?) */
+ break;
+ }
+ hb[3] = 0;
+ if (numDWords & 3) {
+ for (i=0; i<(4 - (numDWords & 3)); ++i)
+ OUT_RING_AGP(cb, 0x00000000);
+ }
+ cb->mode = 0;
+}
+
+void
+hwlLock(void *xlp, int videoLock)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ LL_HW_LOCK(xl);
+}
+
+void
+hwlUnlock(void *xlp, int videoLock)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ LL_HW_UNLOCK(xl);
+}
+
+static unsigned
+timeDiff(struct timeval *now,struct timeval *then) {
+ return (now->tv_usec >= then->tv_usec) ?
+ now->tv_usec - then->tv_usec :
+ 1000000 - (then->tv_usec - now->tv_usec);
+}
+
+void
+setAGPSyncLowLevel(void *xlp, int val, CARD32 timeStamp)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ xl->agpSync = val;
+ xl->agpSyncTimeStamp = timeStamp;
+}
+
+CARD32
+viaDMATimeStampLowLevel(void *xlp)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ if (xl->use_agp) {
+ viaBlit(xl, 32, xl->tsOffset, 1, xl->tsOffset, 1, 1, 1, 0, 0,
+ VIABLIT_FILL, xl->curTimeStamp);
+ return xl->curTimeStamp++;
+ }
+ return 0;
+}
+
+static void
+viaDMAWaitTimeStamp(XvMCLowLevel *xl, CARD32 timeStamp, int doSleep)
+{
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+
+ if (xl->use_agp && (xl->lastReadTimeStamp - timeStamp > (1 << 23))) {
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+
+ while(((xl->lastReadTimeStamp = *xl->tsP) - timeStamp) > (1 << 23)) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_DMAWAITTIMEOUT) {
+ if(((xl->lastReadTimeStamp = *xl->tsP) - timeStamp) > (1 << 23)) {
+ xl->errors |= LL_DMA_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+ }
+}
+
+static int
+viaDMAInitTimeStamp(XvMCLowLevel *xl)
+{
+ int ret = 0;
+
+ if (xl->use_agp) {
+ xl->tsMem.context = *(xl->drmcontext);
+ xl->tsMem.size = 64;
+ xl->tsMem.type = VIA_MEM_VIDEO;
+ if ((ret = drmCommandWriteRead(xl->fd, DRM_VIA_ALLOCMEM,
+ &xl->tsMem, sizeof(xl->tsMem))) < 0)
+ return ret;
+ if (xl->tsMem.size != 64)
+ return -1;
+ xl->tsOffset = (xl->tsMem.offset + 31) & ~31;
+ xl->tsP = (CARD32 *)xl->fbAddress + (xl->tsOffset >> 2);
+ xl->curTimeStamp = 1;
+ *xl->tsP = 0;
+ }
+ return 0;
+}
+
+static int
+viaDMACleanupTimeStamp(XvMCLowLevel *xl)
+{
+
+ if (!(xl->tsMem.size) || !xl->use_agp) return 0;
+ return drmCommandWrite(xl->fd, DRM_VIA_FREEMEM, &xl->tsMem, sizeof(xl->tsMem));
+}
+
+
+static CARD32
+viaMpegGetStatus(XvMCLowLevel *xl)
+{
+ return MPEGIN(xl,0x54);
+}
+
+static int
+viaMpegIsBusy(XvMCLowLevel *xl, CARD32 mask, CARD32 idle)
+{
+ CARD32 tmp = viaMpegGetStatus(xl);
+
+ /*
+ * Error detected.
+ * FIXME: Are errors really shown when error concealment is on?
+ */
+
+ if (tmp & 0x70) return 0;
+
+ return (tmp & mask) != idle;
+}
+
+
+static void
+syncDMA(XvMCLowLevel *xl, unsigned int doSleep)
+{
+
+ /*
+ * Ideally, we'd like to have an interrupt wait here, but, according to second hand
+ * information, the hardware does not support this, although earlier S3 chips do that.
+ * It is therefore not implemented into the DRM, and we'll do a user space wait here.
+ */
+
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+ while( !(REGIN(xl, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY)) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_DMAWAITTIMEOUT) {
+ if( !(REGIN(xl, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY)) {
+ xl->errors |= LL_DMA_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+ while( REGIN(xl, VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY ) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_DMAWAITTIMEOUT) {
+ if( REGIN(xl, VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY ) {
+ xl->errors |= LL_DMA_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+}
+
+#ifdef HQV_USE_IRQ
+static void
+syncVideo(XvMCLowLevel *xl, unsigned int doSleep)
+{
+ int proReg = REG_HQV1_INDEX;
+
+ /*
+ * Wait for HQV completion using completion interrupt. Nothing strange here.
+ * Note that the interrupt handler clears the HQV_FLIP_STATUS bit, so we
+ * can't wait on that one.
+ */
+
+ if ((VIDIN(xl, HQV_CONTROL|proReg) & (HQV_SW_FLIP | HQV_SUBPIC_FLIP))) {
+ drm_via_irqwait_t irqw;
+ irqw.request.irq = 1;
+ irqw.request.type = VIA_IRQ_ABSOLUTE;
+ if (drmCommandWriteRead(xl->fd, DRM_VIA_WAIT_IRQ, &irqw, sizeof(irqw)) < 0)
+ xl->errors |= LL_VIDEO_TIMEDOUT;
+ }
+}
+#else
+static void
+syncVideo(XvMCLowLevel *xl, unsigned int doSleep)
+{
+ /*
+ * Wait for HQV completion. Nothing strange here. We assume that the HQV
+ * Handles syncing to the V1 / V3 engines by itself. It should be safe to
+ * always wait for SUBPIC_FLIP completion although subpictures are not always
+ * used.
+ */
+
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+
+ int proReg = REG_HQV1_INDEX;
+
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+ while((VIDIN(xl, HQV_CONTROL|proReg) & (HQV_SW_FLIP | HQV_SUBPIC_FLIP )) ) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_SYNCWAITTIMEOUT) {
+ if((VIDIN(xl, HQV_CONTROL|proReg) & (HQV_SW_FLIP | HQV_SUBPIC_FLIP )) ) {
+ xl->errors |= LL_VIDEO_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+}
+#endif
+
+static void
+syncAccel(XvMCLowLevel *xl, unsigned int mode, unsigned int doSleep)
+{
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+ CARD32 mask = ((mode & LL_MODE_2D) ? VIA_2D_ENG_BUSY : 0) |
+ ((mode & LL_MODE_3D) ? VIA_3D_ENG_BUSY : 0);
+
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+ while( REGIN(xl, VIA_REG_STATUS) & mask) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_SYNCWAITTIMEOUT) {
+ if( REGIN(xl, VIA_REG_STATUS) & mask) {
+ xl->errors |= LL_ACCEL_TIMEDOUT;
+ break;
+ }
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+}
+
+
+static void
+syncMpeg(XvMCLowLevel *xl, unsigned int mode, unsigned int doSleep)
+{
+ /*
+ * Ideally, we'd like to have an interrupt wait here, but from information from VIA
+ * at least the MPEG completion interrupt is broken on the CLE266, which was
+ * discovered during validation of the chip.
+ */
+
+ struct timeval now, then;
+ struct timezone here;
+ struct timespec sleep, rem;
+ CARD32 busyMask = 0;
+ CARD32 idleVal = 0;
+ CARD32 ret;
+
+ sleep.tv_nsec = 1;
+ sleep.tv_sec = 0;
+ here.tz_minuteswest = 0;
+ here.tz_dsttime = 0;
+ gettimeofday(&then,&here);
+ if (mode & LL_MODE_DECODER_SLICE) {
+ busyMask = VIA_SLICEBUSYMASK;
+ idleVal = VIA_SLICEIDLEVAL;
+ }
+ if (mode & LL_MODE_DECODER_IDLE) {
+ busyMask |= VIA_BUSYMASK;
+ idleVal = VIA_IDLEVAL;
+ }
+ while(viaMpegIsBusy(xl, busyMask, idleVal)) {
+ gettimeofday(&now,&here);
+ if (timeDiff(&now,&then) > VIA_XVMC_DECODERTIMEOUT) {
+ if (viaMpegIsBusy(xl, busyMask, idleVal)) {
+ xl->errors |= LL_DECODER_TIMEDOUT;
+ }
+ break;
+ }
+ if (doSleep) nanosleep(&sleep, &rem);
+ }
+
+ ret = viaMpegGetStatus(xl);
+ if (ret & 0x70) {
+ xl->errors |= ((ret & 0x70) >> 3);
+ }
+ return;
+}
+
+static void
+pciFlush(ViaCommandBuffer *cb, XvMCLowLevel *xl)
+{
+ int ret;
+ drm_via_cmdbuffer_t b;
+ unsigned mode = cb->waitFlags;
+
+ finish_header_agp(cb);
+ b.buf = (char *)cb->buf;
+ b.size = cb->pos * sizeof(CARD32);
+ if (xl->performLocking) hwlLock(xl,0);
+ if (((mode == LL_MODE_VIDEO) && (xl->videoBuf == &xl->agpBuf)) ||
+ ((mode != LL_MODE_VIDEO) && (mode != 0)))
+ syncDMA(xl, 0);
+ if ((mode & LL_MODE_2D) || (mode & LL_MODE_3D)) {
+ syncAccel(xl, mode, 0);
+ }
+ if (mode & LL_MODE_VIDEO) {
+ syncVideo(xl, 1);
+ }
+ if (mode & (LL_MODE_DECODER_SLICE | LL_MODE_DECODER_IDLE)) {
+ syncMpeg(xl, mode, 0);
+ }
+ ret = drmCommandWrite(xl->fd, DRM_VIA_PCICMD, &b, sizeof(b));
+ if (xl->performLocking) hwlUnlock(xl,0);
+ if (ret) {
+ xl->errors |= LL_PCI_COMMAND_ERR;
+ }
+ cb->pos = 0;
+ cb->waitFlags = 0;
+}
+
+static void
+agpFlush(ViaCommandBuffer *cb, XvMCLowLevel *xl)
+{
+ drm_via_cmdbuffer_t b;
+ int ret;
+ int i;
+
+ finish_header_agp(cb);
+ if (xl->use_agp) {
+ b.buf = (char *)cb->buf;
+ b.size = cb->pos * sizeof(CARD32);
+ if (xl->agpSync) {
+ syncXvMCLowLevel(xl, LL_MODE_DECODER_IDLE, 1, xl->agpSyncTimeStamp);
+ xl->agpSync = 0;
+ }
+ if (xl->performLocking) hwlLock(xl,0);
+ do {
+ ret = drmCommandWrite(xl->fd, DRM_VIA_CMDBUFFER, &b, sizeof(b));
+ } while (-EAGAIN == ret);
+ if (xl->performLocking) hwlUnlock(xl,0);
+
+ if (ret) {
+ xl->errors |= LL_AGP_COMMAND_ERR;
+ for(i=0; i<cb->pos; i+=2) {
+ printf("0x%x, 0x%x\n", (unsigned) cb->buf[i], (unsigned) cb->buf[i+1]);
+ }
+ exit(-1);
+ } else {
+ cb->pos = 0;
+ }
+ cb->waitFlags &= LL_MODE_VIDEO; /* FIXME: Check this! */
+ } else {
+ unsigned mode=cb->waitFlags;
+
+ b.buf = (char *)cb->buf;
+ b.size = cb->pos * sizeof(CARD32);
+ if (xl->performLocking) hwlLock(xl,0);
+ if (((mode == LL_MODE_VIDEO) && (cb == &xl->agpBuf)) ||
+ ((mode != LL_MODE_VIDEO) && (mode != 0)))
+ syncDMA(xl, 0);
+ if ((mode & LL_MODE_2D) || (mode & LL_MODE_3D))
+ syncAccel(xl, mode, 0);
+ if (mode & LL_MODE_VIDEO)
+ syncVideo(xl, 1);
+ if (mode & (LL_MODE_DECODER_SLICE | LL_MODE_DECODER_IDLE))
+ syncMpeg(xl, mode, 0);
+ ret = drmCommandWrite(xl->fd, DRM_VIA_PCICMD, &b, sizeof(b));
+ if (xl->performLocking) hwlUnlock(xl,0);
+ if (ret) {
+ xl->errors |= LL_PCI_COMMAND_ERR;
+ }
+ cb->pos = 0;
+ cb->waitFlags = 0;
+ }
+}
+
+static void
+uploadHQVShadow(XvMCLowLevel *xl, unsigned offset, HQVRegister *shadow,
+ Bool flip)
+{
+ int i;
+ CARD32 tmp;
+ ViaCommandBuffer *cb = xl->videoBuf;
+
+ BEGIN_HEADER6_DATA(cb, xl, HQV_SHADOW_SIZE);
+ WAITFLAGS(cb, LL_MODE_VIDEO);
+
+ if (shadow[0].set)
+ OUT_RING_QW_AGP(cb, 0x3CC + offset, 0);
+
+ for (i=2; i < HQV_SHADOW_SIZE; ++i) {
+ if (shadow[i].set) {
+ OUT_RING_QW_AGP(cb, offset + HQV_SHADOW_BASE + ( i << 2) , shadow[i].data);
+ shadow[i].set = FALSE;
+ }
+ }
+
+ /*
+ * Finally the control register for flip.
+ */
+
+ if (flip) {
+ tmp = GETHQVSHADOW( shadow, 0x3D0);
+ OUT_RING_QW_AGP(cb, offset + HQV_CONTROL + 0x200 ,
+ HQV_ENABLE | HQV_GEN_IRQ | HQV_SUBPIC_FLIP | HQV_SW_FLIP | tmp);
+ }
+ shadow[0].set = FALSE;
+ shadow[1].set = FALSE;
+}
+
+
+
+
+unsigned
+flushXvMCLowLevel(void *xlp)
+{
+ unsigned
+ errors;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+
+ if(xl->pciBuf.pos) pciFlush(&xl->pciBuf, xl);
+ if(xl->agpBuf.pos) agpFlush(&xl->agpBuf, xl);
+ errors = xl->errors;
+ if (errors) printf("Error 0x%x\n", errors);
+ xl->errors = 0;
+ return errors;
+}
+
+void
+flushPCIXvMCLowLevel(void *xlp)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+
+ if(xl->pciBuf.pos) pciFlush(&xl->pciBuf, xl);
+ if ((!xl->use_agp && xl->agpBuf.pos)) agpFlush(&xl->agpBuf, xl);
+}
+
+
+void
+viaMpegSetSurfaceStride(void *xlp, ViaXvMCContext *ctx)
+{
+ CARD32 y_stride = ctx->yStride;
+ CARD32 uv_stride = y_stride >> 1;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ ViaCommandBuffer *cb = &xl->agpBuf;
+
+ BEGIN_HEADER6_DATA(cb, xl, 1);
+ OUT_RING_QW_AGP(cb, 0xc50, (y_stride >> 3) | ((uv_stride >> 3) << 16));
+ WAITFLAGS(cb, LL_MODE_DECODER_IDLE);
+}
+
+
+void
+viaVideoSetSWFLipLocked(void *xlp, unsigned yOffs, unsigned uOffs,
+ unsigned vOffs, unsigned yStride, unsigned uvStride)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ initHQVShadow(hqvShadow);
+ setHQVStartAddress(hqvShadow, yOffs, vOffs, yStride, 0);
+ if (xl->videoBuf == &xl->agpBuf)
+ syncDMA(xl, 1);
+ syncVideo(xl, 1);
+ uploadHQVShadow(xl, REG_HQV1_INDEX, hqvShadow, FALSE);
+ xl->videoBuf->flushFunc(xl->videoBuf, xl);
+}
+
+void
+viaVideoSWFlipLocked(void *xlp, unsigned flags,
+ Bool progressiveSequence)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ setHQVDeinterlacing(hqvShadow, flags);
+ setHQVDeblocking(hqvShadow,( (flags & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE), TRUE);
+ setHQVTripleBuffer(hqvShadow, TRUE);
+ if (xl->videoBuf == &xl->agpBuf)
+ syncDMA(xl, 1);
+ syncVideo(xl, 1);
+ uploadHQVShadow(xl, REG_HQV1_INDEX, hqvShadow, TRUE);
+ xl->videoBuf->flushFunc(xl->videoBuf, xl);
+}
+
+
+void
+viaMpegSetFB(void *xlp,unsigned i,
+ unsigned yOffs,
+ unsigned uOffs,
+ unsigned vOffs)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ ViaCommandBuffer *cb = &xl->agpBuf;
+
+ i *= (4*2);
+ BEGIN_HEADER6_DATA(cb,xl, 2);
+ OUT_RING_QW_AGP(cb, 0xc28 + i, yOffs >> 3);
+ OUT_RING_QW_AGP(cb, 0xc2c + i, vOffs >> 3);
+
+ WAITFLAGS(cb, LL_MODE_DECODER_IDLE);
+}
+
+void
+viaMpegBeginPicture(void *xlp,ViaXvMCContext *ctx,
+ unsigned width,
+ unsigned height,
+ const XvMCMpegControl *control) {
+
+ unsigned j, mb_width, mb_height;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ ViaCommandBuffer *cb = &xl->agpBuf;
+
+ mb_width = (width + 15) >> 4;
+
+ mb_height =
+ ((control->mpeg_coding == XVMC_MPEG_2) &&
+ (control->flags & XVMC_PROGRESSIVE_SEQUENCE)) ?
+ 2*((height+31) >> 5) : (((height+15) >> 4));
+
+ BEGIN_HEADER6_DATA(cb,xl, 72);
+ WAITFLAGS(cb, LL_MODE_DECODER_IDLE);
+
+ OUT_RING_QW_AGP(cb, 0xc00,
+ ((control->picture_structure & XVMC_FRAME_PICTURE) << 2) |
+ ((control->picture_coding_type & 3) << 4) |
+ ((control->flags & XVMC_ALTERNATE_SCAN) ? (1 << 6) : 0));
+
+ if (!(ctx->intraLoaded)) {
+ OUT_RING_QW_AGP(cb, 0xc5c, 0);
+ for (j = 0; j < 64; j += 4) {
+ OUT_RING_QW_AGP(cb, 0xc60,
+ ctx->intra_quantiser_matrix[j] |
+ (ctx->intra_quantiser_matrix[j+1] << 8) |
+ (ctx->intra_quantiser_matrix[j+2] << 16) |
+ (ctx->intra_quantiser_matrix[j+3] << 24));
+ }
+ ctx->intraLoaded = 1;
+ }
+
+ if (!(ctx->nonIntraLoaded)) {
+ OUT_RING_QW_AGP(cb, 0xc5c, 1);
+ for (j = 0; j < 64; j += 4) {
+ OUT_RING_QW_AGP(cb, 0xc60,
+ ctx->non_intra_quantiser_matrix[j] |
+ (ctx->non_intra_quantiser_matrix[j+1] << 8) |
+ (ctx->non_intra_quantiser_matrix[j+2] << 16) |
+ (ctx->non_intra_quantiser_matrix[j+3] << 24));
+ }
+ ctx->nonIntraLoaded = 1;
+ }
+
+ if (!(ctx->chromaIntraLoaded)) {
+ OUT_RING_QW_AGP(cb, 0xc5c, 2);
+ for (j = 0; j < 64; j += 4) {
+ OUT_RING_QW_AGP(cb, 0xc60,
+ ctx->chroma_intra_quantiser_matrix[j] |
+ (ctx->chroma_intra_quantiser_matrix[j+1] << 8) |
+ (ctx->chroma_intra_quantiser_matrix[j+2] << 16) |
+ (ctx->chroma_intra_quantiser_matrix[j+3] << 24));
+ }
+ ctx->chromaIntraLoaded = 1;
+ }
+
+ if (!(ctx->chromaNonIntraLoaded)) {
+ OUT_RING_QW_AGP(cb, 0xc5c, 3);
+ for (j = 0; j < 64; j += 4) {
+ OUT_RING_QW_AGP(cb, 0xc60,
+ ctx->chroma_non_intra_quantiser_matrix[j] |
+ (ctx->chroma_non_intra_quantiser_matrix[j+1] << 8) |
+ (ctx->chroma_non_intra_quantiser_matrix[j+2] << 16) |
+ (ctx->chroma_non_intra_quantiser_matrix[j+3] << 24));
+ }
+ ctx->chromaNonIntraLoaded = 1;
+ }
+
+ OUT_RING_QW_AGP(cb, 0xc90,
+ ((mb_width * mb_height) & 0x3fff) |
+ ((control->flags & XVMC_PRED_DCT_FRAME) ? ( 1 << 14) : 0) |
+ ((control->flags & XVMC_TOP_FIELD_FIRST) ? (1 << 15) : 0 ) |
+ ((control->mpeg_coding == XVMC_MPEG_2) ? (1 << 16) : 0) |
+ ((mb_width & 0xff) << 18));
+
+ OUT_RING_QW_AGP(cb, 0xc94,
+ ((control->flags & XVMC_CONCEALMENT_MOTION_VECTORS) ? 1 : 0) |
+ ((control->flags & XVMC_Q_SCALE_TYPE) ? 2 : 0) |
+ ((control->intra_dc_precision & 3) << 2) |
+ (((1 + 0x100000 / mb_width) & 0xfffff) << 4) |
+ ((control->flags & XVMC_INTRA_VLC_FORMAT) ? (1 << 24) : 0));
+
+ OUT_RING_QW_AGP(cb, 0xc98,
+ (((control->FHMV_range) & 0xf) << 0) |
+ (((control->FVMV_range) & 0xf) << 4) |
+ (((control->BHMV_range) & 0xf) << 8) |
+ (((control->BVMV_range) & 0xf) << 12) |
+ ((control->flags & XVMC_SECOND_FIELD) ? (1 << 20) : 0) |
+ (0x0a6 << 16));
+
+}
+
+
+
+void
+viaMpegReset(void *xlp)
+{
+ int i,j;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ ViaCommandBuffer *cb = &xl->agpBuf;
+
+ BEGIN_HEADER6_DATA(cb,xl, 99);
+ WAITFLAGS(cb, LL_MODE_DECODER_IDLE);
+
+ OUT_RING_QW_AGP(cb, 0xcf0 ,0);
+
+ for (i = 0; i < 6; i++) {
+ OUT_RING_QW_AGP(cb, 0xcc0 ,0);
+ OUT_RING_QW_AGP(cb, 0xc0c, 0x43|0x20 );
+ for (j = 0xc10; j < 0xc20; j += 4)
+ OUT_RING_QW_AGP(cb, j, 0);
+ }
+
+ OUT_RING_QW_AGP(cb, 0xc0c, 0x1c3);
+ for (j = 0xc10; j < 0xc20; j += 4)
+ OUT_RING_QW_AGP(cb,j,0);
+
+ for (i = 0; i < 19; i++)
+ OUT_RING_QW_AGP(cb, 0xc08 ,0);
+
+ OUT_RING_QW_AGP(cb, 0xc98, 0x400000);
+
+ for (i = 0; i < 6; i++) {
+ OUT_RING_QW_AGP(cb, 0xcc0 ,0);
+ OUT_RING_QW_AGP(cb, 0xc0c, 0x1c3|0x20);
+ for (j = 0xc10; j < 0xc20; j += 4)
+ OUT_RING_QW_AGP(cb,j,0);
+ }
+ OUT_RING_QW_AGP(cb, 0xcf0 ,0);
+
+}
+
+void
+viaMpegWriteSlice(void *xlp, CARD8* slice, int nBytes, CARD32 sCode)
+{
+ int i, n, r;
+ CARD32* buf;
+ int count;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ ViaCommandBuffer *cb = &xl->agpBuf;
+
+ if (xl->errors & (LL_DECODER_TIMEDOUT |
+ LL_IDCT_FIFO_ERROR |
+ LL_SLICE_FIFO_ERROR |
+ LL_SLICE_FAULT)) return;
+
+ n = nBytes >> 2;
+ if (sCode) nBytes += 4;
+ r = nBytes & 3;
+ buf = (CARD32*) slice;
+
+ if (r) nBytes += 4 - r;
+
+ nBytes += 8;
+
+ BEGIN_HEADER6_DATA(cb,xl, 2);
+ WAITFLAGS(cb, LL_MODE_DECODER_IDLE);
+ OUT_RING_QW_AGP(cb, 0xc9c, nBytes);
+
+ if (sCode) OUT_RING_QW_AGP(cb, 0xca0, sCode);
+
+ i = 0;
+ count = 0;
+
+ do {
+ count += (LL_AGP_CMDBUF_SIZE -20);
+ count = (count > n) ? n : count;
+ BEGIN_HEADER5_DATA(cb, xl, (count - i), 0xca0);
+
+ for (; i < count; i++) {
+ OUT_RING_AGP(cb, *buf++);
+ }
+ finish_header_agp(cb);
+ } while (i < n);
+
+ BEGIN_HEADER5_DATA(cb, xl, 3, 0xca0);
+
+ if (r) {
+ OUT_RING_AGP(cb, *buf & ((1 << (r << 3)) - 1));
+ }
+ OUT_RING_AGP(cb,0);
+ OUT_RING_AGP(cb,0);
+ finish_header_agp(cb);
+}
+
+void
+viaVideoSubPictureOffLocked(void *xlp) {
+
+ CARD32 stride;
+ int proReg = REG_HQV1_INDEX;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ ViaCommandBuffer *cb = xl->videoBuf;
+
+ if (xl->videoBuf == &xl->agpBuf)
+ syncDMA(xl, 1);
+ stride = VIDIN(xl,proReg|SUBP_CONTROL_STRIDE);
+ WAITFLAGS(cb, LL_MODE_VIDEO);
+ BEGIN_HEADER6_DATA(cb, xl, 1);
+ OUT_RING_QW_AGP(cb, proReg|SUBP_CONTROL_STRIDE | 0x200, stride & ~SUBP_HQV_ENABLE);
+}
+
+void
+viaVideoSubPictureLocked(void *xlp, ViaXvMCSubPicture *pViaSubPic) {
+
+ unsigned i;
+ CARD32 cWord;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ int proReg = REG_HQV1_INDEX;
+ ViaCommandBuffer *cb = xl->videoBuf;
+
+ if (xl->videoBuf == &xl->agpBuf)
+ syncDMA(xl, 1);
+ WAITFLAGS(cb, LL_MODE_VIDEO);
+ BEGIN_HEADER6_DATA(cb, xl, VIA_SUBPIC_PALETTE_SIZE + 2);
+ for (i=0; i<VIA_SUBPIC_PALETTE_SIZE; ++i) {
+ OUT_RING_QW_AGP(cb, proReg|RAM_TABLE_CONTROL | 0x200, pViaSubPic->palette[i]);
+ }
+
+ cWord = (pViaSubPic->stride & SUBP_STRIDE_MASK) | SUBP_HQV_ENABLE;
+ cWord |= (pViaSubPic->ia44) ? SUBP_IA44 : SUBP_AI44;
+ OUT_RING_QW_AGP(cb, proReg|SUBP_STARTADDR | 0x200, pViaSubPic->offset);
+ OUT_RING_QW_AGP(cb, proReg|SUBP_CONTROL_STRIDE | 0x200, cWord);
+}
+
+void
+viaBlit(void *xlp,unsigned bpp,unsigned srcBase,
+ unsigned srcPitch,unsigned dstBase,unsigned dstPitch,
+ unsigned w,unsigned h,int xdir,int ydir, unsigned blitMode,
+ unsigned color)
+{
+
+ CARD32 dwGEMode = 0, srcY=0, srcX, dstY=0, dstX;
+ CARD32 cmd;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ ViaCommandBuffer *cb = &xl->agpBuf;
+
+ if (!w || !h)
+ return;
+
+ finish_header_agp(cb);
+
+ switch (bpp) {
+ case 16:
+ dwGEMode |= VIA_GEM_16bpp;
+ break;
+ case 32:
+ dwGEMode |= VIA_GEM_32bpp;
+ break;
+ default:
+ dwGEMode |= VIA_GEM_8bpp;
+ break;
+ }
+
+ srcX = srcBase & 31;
+ dstX = dstBase & 31;
+ switch (bpp) {
+ case 16:
+ dwGEMode |= VIA_GEM_16bpp;
+ srcX >>= 2;
+ dstX >>= 2;
+ break;
+ case 32:
+ dwGEMode |= VIA_GEM_32bpp;
+ srcX >>= 4;
+ dstX >>= 4;
+ break;
+ default:
+ dwGEMode |= VIA_GEM_8bpp;
+ break;
+ }
+
+ BEGIN_RING_AGP(cb, xl, 20);
+ WAITFLAGS(cb, LL_MODE_2D);
+
+
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_GEMODE), dwGEMode);
+ cmd = 0;
+
+ if (xdir < 0) {
+ cmd |= VIA_GEC_DECX;
+ srcX += (w - 1);
+ dstX += (w - 1);
+ }
+ if (ydir < 0) {
+ cmd |= VIA_GEC_DECY;
+ srcY += (h - 1);
+ dstY += (h - 1);
+ }
+
+ switch(blitMode) {
+ case VIABLIT_TRANSCOPY:
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_SRCCOLORKEY), color);
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_KEYCONTROL), 0x4000);
+ cmd |= VIA_GEC_BLT | (VIA_BLIT_COPY << 24);
+ break;
+ case VIABLIT_FILL:
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_FGCOLOR), color);
+ cmd |= VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | (VIA_BLIT_FILL << 24);
+ break;
+ default:
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_KEYCONTROL), 0x0);
+ cmd |= VIA_GEC_BLT | (VIA_BLIT_COPY << 24);
+ }
+
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_SRCBASE), (srcBase & ~31) >> 3);
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_DSTBASE), (dstBase & ~31) >> 3);
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_PITCH), VIA_PITCH_ENABLE |
+ (srcPitch >> 3) | (((dstPitch) >> 3) << 16));
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_SRCPOS), ((srcY << 16) | srcX));
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_DSTPOS), ((dstY << 16) | dstX));
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_DIMENSION), (((h - 1) << 16) | (w - 1)));
+ OUT_RING_QW_AGP(cb, H1_ADDR(VIA_REG_GECMD), cmd);
+}
+
+unsigned
+syncXvMCLowLevel(void *xlp, unsigned int mode, unsigned int doSleep,
+ CARD32 timeStamp)
+{
+ unsigned
+ errors;
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+
+ if (mode == 0) {
+ errors = xl->errors;
+ xl->errors = 0;
+ return errors;
+ }
+
+ if ((mode & (LL_MODE_VIDEO | LL_MODE_3D)) || !xl->use_agp) {
+ if (xl->performLocking)
+ hwlLock(xl,0);
+ if ((xl->videoBuf == &xl->agpBuf) || (mode != LL_MODE_VIDEO))
+ syncDMA(xl, doSleep);
+ if (mode & LL_MODE_3D)
+ syncAccel(xl, mode, doSleep);
+ if (mode & LL_MODE_VIDEO)
+ syncVideo(xl, doSleep);
+ if (xl->performLocking)
+ hwlUnlock(xl,0);
+ } else {
+ viaDMAWaitTimeStamp(xl, timeStamp, doSleep);
+ }
+
+ if (mode & (LL_MODE_DECODER_SLICE | LL_MODE_DECODER_IDLE))
+ syncMpeg(xl, mode, doSleep);
+
+ errors = xl->errors;
+ xl->errors = 0;
+
+ return errors;
+}
+
+static int
+updateLowLevelBuf(XvMCLowLevel *xl, LowLevelBuffer *buf,
+ unsigned width, unsigned height)
+{
+ unsigned
+ stride, size;
+ drm_via_mem_t *mem = &buf->mem;
+ int ret;
+
+ stride = (width + 31) & ~31;
+ size = stride * height + (xl->fbDepth >> 3);
+
+ if (size != mem->size) {
+ if (mem->size)
+ drmCommandWrite(xl->fd, DRM_VIA_FREEMEM, mem, sizeof(*mem));
+ mem->context = *(xl->drmcontext);
+ mem->size = size;
+ mem->type = VIA_MEM_VIDEO;
+
+ if (((ret = drmCommandWriteRead(xl->fd, DRM_VIA_ALLOCMEM, mem, sizeof(mem))) < 0) ||
+ mem->size != size) {
+ mem->size = 0;
+ return -1;
+ }
+ }
+
+ buf->offset = (mem->offset + 31) & ~31;
+ buf->stride = stride;
+ buf->height = height;
+ return 0;
+}
+
+static void
+cleanupLowLevelBuf(XvMCLowLevel *xl, LowLevelBuffer *buf)
+{
+ drm_via_mem_t *mem = &buf->mem;
+
+ if (mem->size)
+ drmCommandWrite(xl->fd, DRM_VIA_FREEMEM, mem, sizeof(mem));
+ mem->size = 0;
+}
+
+
+static void
+*releaseXvMCLowLevel(XvMCLowLevel *xl)
+{
+ switch(xl->state) {
+ case ll_llBuf:
+ cleanupLowLevelBuf(xl, &xl->scale);
+ case ll_timeStamp:
+ viaDMACleanupTimeStamp(xl);
+ case ll_pciBuf:
+ free(xl->pciBuf.buf);
+ case ll_agpBuf:
+ free(xl->agpBuf.buf);
+ case ll_init:
+ free(xl);
+ default:
+ ;
+ }
+ return NULL;
+}
+
+
+void
+*initXvMCLowLevel(int fd, drm_context_t *ctx,
+ drmLockPtr hwLock, drmAddress mmioAddress,
+ drmAddress fbAddress, unsigned fbStride, unsigned fbDepth,
+ unsigned width, unsigned height, int useAgp, unsigned chipId )
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *)malloc(sizeof(XvMCLowLevel));
+
+ if (!xl) return NULL;
+ xl->state = ll_init;
+
+ xl->agpBuf.buf = (CARD32 *)malloc(LL_AGP_CMDBUF_SIZE * sizeof(CARD32));
+ if (!xl->agpBuf.buf) return releaseXvMCLowLevel(xl);
+ xl->state = ll_agpBuf;
+ xl->agpBuf.bufSize = LL_AGP_CMDBUF_SIZE;
+ xl->agpBuf.flushFunc = &agpFlush;
+ xl->agpBuf.pos = 0;
+ xl->agpBuf.mode = 0;
+ xl->agpBuf.waitFlags = 0;
+
+ xl->pciBuf.buf = (CARD32 *)malloc(LL_PCI_CMDBUF_SIZE * sizeof(CARD32));
+ if (!xl->pciBuf.buf) return releaseXvMCLowLevel(xl);
+ xl->state = ll_pciBuf;
+ xl->pciBuf.bufSize = LL_PCI_CMDBUF_SIZE;
+ xl->pciBuf.flushFunc = &pciFlush;
+ xl->pciBuf.pos = 0;
+ xl->pciBuf.mode = 0;
+ xl->pciBuf.waitFlags = 0;
+
+ xl->use_agp = useAgp;
+ xl->fd = fd;
+ xl->drmcontext = ctx;
+ xl->hwLock = hwLock;
+ xl->mmioAddress = mmioAddress;
+ xl->fbAddress = fbAddress;
+ xl->fbDepth = fbDepth;
+ xl->fbStride = fbStride;
+ xl->width = width;
+ xl->height = height;
+ xl->performLocking = 1;
+ xl->errors = 0;
+ xl->agpSync = 0;
+ xl->chipId = chipId;
+
+ if (viaDMAInitTimeStamp(xl))
+ return releaseXvMCLowLevel(xl);
+ xl->state = ll_timeStamp;
+
+ xl->scale.mem.size = 0;
+ xl->back.mem.size = 0;
+
+ if (updateLowLevelBuf(xl, &xl->scale, width, height))
+ return releaseXvMCLowLevel(xl);
+ xl->state = ll_llBuf;
+
+#ifdef VIDEO_DMA
+ xl->videoBuf = &xl->agpBuf;
+#else
+ xl->videoBuf = &xl->pciBuf;
+#endif
+
+ return xl;
+}
+
+void
+setLowLevelLocking(void *xlp, int performLocking)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ xl->performLocking = performLocking;
+}
+
+void
+closeXvMCLowLevel(void *xlp)
+{
+ XvMCLowLevel *xl = (XvMCLowLevel *) xlp;
+ releaseXvMCLowLevel(xl);
+}
diff --git a/nx-X11/lib/XvMC/hw/via/viaLowLevel.h b/nx-X11/lib/XvMC/hw/via/viaLowLevel.h
new file mode 100644
index 000000000..12e5fe373
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/viaLowLevel.h
@@ -0,0 +1,148 @@
+/*****************************************************************************
+ * VIA Unichrome XvMC extension client lib.
+ *
+ * Copyright (c) 2004 The Unichrome Project. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Authors: Thomas Hellström 2004 - 2005.
+ */
+
+
+#ifndef VIA_LOWLEVEL_H
+#define VIA_LOWLEVEL_H
+
+
+/*
+ * The below define is cache size sensitive. Increasing the AGP buffer size
+ * will enable the library to do deeper pipelining, but will degrade the
+ * performance in the drm dma command verifier.
+ */
+
+#define LL_AGP_CMDBUF_SIZE (4096*2)
+#define LL_PCI_CMDBUF_SIZE (4096)
+
+#define LL_MODE_DECODER_SLICE 0x01
+#define LL_MODE_DECODER_IDLE 0x02
+#define LL_MODE_VIDEO 0x04
+#define LL_MODE_2D 0x08
+#define LL_MODE_3D 0x10
+
+/*
+ * Errors
+ */
+
+#define LL_DECODER_TIMEDOUT 0x00000001
+#define LL_IDCT_FIFO_ERROR 0x00000002
+#define LL_SLICE_FIFO_ERROR 0x00000004
+#define LL_SLICE_FAULT 0x00000008
+#define LL_DMA_TIMEDOUT 0x00000010
+#define LL_VIDEO_TIMEDOUT 0x00000020
+#define LL_ACCEL_TIMEDOUT 0x00000040
+#define LL_PCI_COMMAND_ERR 0x00000080
+#define LL_AGP_COMMAND_ERR 0x00000100
+
+#define VIA_SLICEBUSYMASK 0x00000200
+#define VIA_BUSYMASK 0x00000207
+#define VIA_SLICEIDLEVAL 0x00000200
+#define VIA_IDLEVAL 0x00000204
+
+#include "via_drm.h"
+#include "viaXvMCPriv.h"
+
+#define setRegion(xx,yy,ww,hh,region) \
+ do { \
+ (region).x = (xx); \
+ (region).y = (yy); \
+ (region).w = (ww); \
+ (region).h = (hh); \
+ } while(0)
+
+#define regionEqual(r1, r2) \
+ ((r1).x == (r2).x && \
+ (r1).y == (r2).y && \
+ (r1).w == (r2).w && \
+ (r1).h == (r2).h)
+
+
+
+extern void
+*initXvMCLowLevel(int fd, drm_context_t *ctx,
+ drmLockPtr hwLock, drmAddress mmioAddress,
+ drmAddress fbAddress, unsigned fbStride, unsigned fbDepth,
+ unsigned width, unsigned height, int useAgp, unsigned chipId );
+
+extern void setLowLevelLocking(void *xlp, int perFormLocking);
+extern void closeXvMCLowLevel(void *xlp);
+extern void flushPCIXvMCLowLevel(void *xlp);
+extern CARD32 viaDMATimeStampLowLevel(void *xlp);
+extern void setAGPSyncLowLevel(void *xlp, int val, CARD32 timeStamp);
+
+
+/*
+ * These two functions also return and clear the current error status.
+ */
+
+extern unsigned flushXvMCLowLevel(void *xlp);
+extern unsigned syncXvMCLowLevel(void *xlp, unsigned int mode,
+ unsigned int doSleep, CARD32 timeStamp);
+
+extern void hwlUnlock(void *xlp, int videoLock);
+extern void hwlLock(void *xlp, int videoLock);
+
+extern void viaVideoSetSWFLipLocked(void *xlp, unsigned yOffs, unsigned uOffs,
+ unsigned vOffs, unsigned yStride, unsigned uvStride);
+
+extern void viaMpegReset(void *xlp);
+extern void viaMpegWriteSlice(void *xlp, CARD8* slice,
+ int nBytes, CARD32 sCode);
+extern void viaMpegSetSurfaceStride(void *xlp, ViaXvMCContext *ctx);
+extern void viaMpegSetFB(void *xlp,unsigned i, unsigned yOffs,
+ unsigned uOffs, unsigned vOffs);
+extern void viaMpegBeginPicture(void *xlp, ViaXvMCContext *ctx,unsigned width,
+ unsigned height,const XvMCMpegControl *control);
+
+/*
+ * Low-level Video functions in viaLowLevel.c
+ */
+
+
+extern void viaBlit(void *xlp,unsigned bpp,unsigned srcBase,
+ unsigned srcPitch,unsigned dstBase,unsigned dstPitch,
+ unsigned w,unsigned h,int xdir,int ydir,
+ unsigned blitMode, unsigned color);
+
+extern void viaVideoSWFlipLocked(void *xlp, unsigned flags,
+ int progressiveSequence);
+
+extern void viaVideoSubPictureLocked(void *xlp,ViaXvMCSubPicture *pViaSubPic);
+extern void viaVideoSubPictureOffLocked(void *xlp);
+
+
+
+
+#define PCI_CHIP_VT3204 0x3108 /* K8M800 */
+#define PCI_CHIP_VT3259 0x3118 /* PM800/PM880/CN400 */
+#define PCI_CHIP_CLE3122 0x3122 /* CLE266 */
+#define PCI_CHIP_VT3205 0x7205 /* KM400 */
+
+#endif
diff --git a/nx-X11/lib/XvMC/hw/via/viaXvMC.c b/nx-X11/lib/XvMC/hw/via/viaXvMC.c
new file mode 100644
index 000000000..eebc87ea8
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/viaXvMC.c
@@ -0,0 +1,1964 @@
+/*****************************************************************************
+ * VIA Unichrome XvMC extension client lib.
+ *
+ * Copyright (c) 2004-2005 Thomas Hellström. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ *Author: Thomas Hellström, 2004.
+ *Bugfixes by among others Pascal Brisset and Terry Barnaby.
+ *DRI protocol support by Thomas Hellström, 2005.
+ */
+
+#undef WAITPAUSE
+
+#include "viaXvMCPriv.h"
+#include "viaLowLevel.h"
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <time.h>
+#include <fourcc.h>
+#include <X11/extensions/Xv.h>
+#include <xf86drm.h>
+#include <pthread.h>
+#include <X11/extensions/vldXvMC.h>
+#include "xf86dri.h"
+#include "driDrawable.h"
+
+#define SAREAPTR(ctx) ((ViaXvMCSAreaPriv *) \
+ (((CARD8 *)(ctx)->sAreaAddress) + \
+ (ctx)->sAreaPrivOffset))
+
+
+
+static int error_base;
+static int event_base;
+static unsigned numContexts = 0;
+static int globalFD;
+static drmAddress sAreaAddress;
+static drmAddress fbAddress;
+static drmAddress mmioAddress;
+
+
+#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X')
+
+#define ppthread_mutex_lock(arg) \
+ { \
+ pthread_mutex_lock(arg); \
+ } \
+
+#define ppthread_mutex_unlock(arg) \
+ { \
+ pthread_mutex_unlock(arg); \
+ } \
+
+static unsigned yOffs (ViaXvMCSurface *srf)
+{
+ return srf->offsets[0];
+}
+
+static unsigned vOffs (ViaXvMCSurface *srf)
+{
+ return srf->offsets[0] + srf->yStride * srf->height;
+}
+
+static unsigned uOffs (ViaXvMCSurface *srf)
+{
+ return srf->offsets[0] + ( srf->yStride * srf->height) +
+ (srf->yStride >> 1) * (srf->height >> 1);
+}
+
+
+static void defaultQMatrices(ViaXvMCContext *ctx)
+{
+ int i;
+
+ static const char intra[64] = {
+ 8, 16, 19, 22, 26, 27, 29, 34, 16, 16, 22, 24, 27, 29, 34, 37,
+ 19, 22, 26, 27, 29, 34, 34, 38, 22, 22, 26, 27, 29, 34, 37, 40,
+ 22, 26, 27, 29, 32, 35, 40, 48, 26, 27, 29, 32, 35, 40, 48, 58,
+ 26, 27, 29, 34, 38, 46, 56, 69, 27, 29, 35, 38, 46, 56, 69, 83
+ };
+
+ for( i=0; i<64; ++i) {
+ ctx->intra_quantiser_matrix[i] = intra[i];
+ ctx->non_intra_quantiser_matrix[i] = 16;
+ }
+ ctx->intraLoaded = 0;
+ ctx->nonIntraLoaded = 0;
+}
+
+
+static void releaseDecoder(ViaXvMCContext *ctx,int clearCtx)
+{
+ volatile ViaXvMCSAreaPriv *sAPriv;
+
+ sAPriv = SAREAPTR(ctx);
+ UNICHROME_UNLOCK(ctx->fd, UNICHROME_LOCK_DECODER1, sAPriv, ctx->drmcontext);
+}
+
+
+static int grabDecoder( ViaXvMCContext *ctx, int *hadLastLock)
+{
+ volatile ViaXvMCSAreaPriv *sAPriv = SAREAPTR(ctx);
+ int retFtx, lc;
+
+ /*
+ * Try to grab the decoder. If it is not available we will sleep until
+ * it becomes available or for a maximum of 20 ms.
+ * Then try to grab it again, unless a timeout occured. If the decoder is
+ * available, the lock should be reasonably fast.
+ */
+
+ if (ctx->haveDecoder) {
+ flushXvMCLowLevel(ctx->xl); /* Ignore errors here. */
+
+ /*fprintf(stderr,"ViaXvMC: ERROR: Trying to re-lock decoder.\n"); */
+ *hadLastLock = 1;
+ return 0;
+ }
+ UNICHROME_LOCK(ctx->fd, UNICHROME_LOCK_DECODER1, sAPriv, ctx->drmcontext, lc,
+ retFtx);
+ *hadLastLock = (ctx->drmcontext == lc);
+
+ return retFtx;
+}
+
+static void setupAttribDesc(Display *display, XvPortID port,
+ const ViaXvMCAttrHolder *attrib,
+ XvAttribute attribDesc[])
+{
+ XvAttribute *XvAttribs,*curAD;
+ int num;
+ unsigned i,j;
+
+ XLockDisplay(display);
+ XvAttribs = XvQueryPortAttributes(display, port, &num);
+ for(i=0; i<attrib->numAttr; ++i) {
+ curAD = attribDesc + i;
+ curAD->flags = 0;
+ curAD->min_value = 0;
+ curAD->max_value = 0;
+ curAD->name = NULL;
+ for(j=0; j<num; ++j) {
+ if (attrib->attributes[i].attribute ==
+ XInternAtom(display,XvAttribs[j].name,TRUE)) {
+ *curAD = XvAttribs[j];
+ curAD->name = strdup(XvAttribs[j].name);
+ break;
+ }
+ }
+ }
+ if (XvAttribs) XFree(XvAttribs);
+ XUnlockDisplay(display);
+
+}
+
+static void releaseAttribDesc(int numAttr, XvAttribute attribDesc[])
+{
+ int i;
+
+ for (i=0; i<numAttr; ++i) {
+ if (attribDesc[i].name)
+ free(attribDesc[i].name);
+ }
+}
+
+static Status releaseContextResources(Display *display, XvMCContext *context,
+ int freePrivate, Status errType)
+{
+ ViaXvMCContext *pViaXvMC = (ViaXvMCContext *) context->privData;
+
+ switch(pViaXvMC->resources) {
+ case context_drawHash:
+ driDestroyHashContents( pViaXvMC->drawHash );
+ drmHashDestroy( pViaXvMC->drawHash );
+ case context_lowLevel:
+ closeXvMCLowLevel(pViaXvMC->xl);
+ case context_mutex:
+ pthread_mutex_destroy(&pViaXvMC->ctxMutex);
+ case context_drmContext:
+ XLockDisplay(display);
+ uniDRIDestroyContext(display, pViaXvMC->screen, pViaXvMC->id);
+ XUnlockDisplay(display);
+ case context_sAreaMap:
+ numContexts--;
+ if (numContexts == 0)
+ drmUnmap(pViaXvMC->sAreaAddress,pViaXvMC->sAreaSize);
+ case context_fbMap:
+ if (numContexts == 0)
+ drmUnmap(pViaXvMC->fbAddress,pViaXvMC->fbSize);
+ case context_mmioMap:
+ if (numContexts == 0)
+ drmUnmap(pViaXvMC->mmioAddress,pViaXvMC->mmioSize);
+ case context_fd:
+ if (numContexts == 0) {
+ if (pViaXvMC->fd >= 0)
+ drmClose(pViaXvMC->fd);
+ }
+ pViaXvMC->fd = -1;
+ case context_driConnection:
+ if (numContexts == 0) {
+ XLockDisplay(display);
+ uniDRICloseConnection(display, pViaXvMC->screen);
+ XUnlockDisplay(display);
+ }
+ case context_context:
+ XLockDisplay(display);
+ _xvmc_destroy_context(display, context);
+ XUnlockDisplay(display);
+ if (!freePrivate) break;
+ default:
+ free(pViaXvMC);
+ }
+ return errType;
+}
+
+Status XvMCCreateContext(Display *display, XvPortID port,
+ int surface_type_id, int width, int height, int flags,
+ XvMCContext *context)
+{
+ ViaXvMCContext *pViaXvMC;
+ int priv_count;
+ uint *priv_data;
+ uint magic;
+ unsigned i;
+ Status ret;
+ int major, minor;
+ ViaXvMCCreateContextRec *tmpComm;
+ drmVersionPtr drmVer;
+ char *curBusID;
+ int isCapable;
+
+ /*
+ * Verify Obvious things first
+ */
+
+ if(context == NULL) {
+ return XvMCBadContext;
+ }
+
+ if(!(flags & XVMC_DIRECT)) {
+ fprintf(stderr,"Indirect Rendering not supported! Using Direct.\n");
+ }
+
+ /*
+ *FIXME: Check $DISPLAY for legal values here
+ */
+
+ context->surface_type_id = surface_type_id;
+ context->width = (unsigned short)((width + 15) & ~15);
+ context->height = (unsigned short)((height + 15) & ~15);
+ context->flags = flags;
+ context->port = port;
+
+ /*
+ * Width, Height, and flags are checked against surface_type_id
+ * and port for validity inside the X server, no need to check
+ * here.
+ */
+
+ /* Allocate private Context data */
+ context->privData = (void *)malloc(sizeof(ViaXvMCContext));
+ if(!context->privData) {
+ fprintf(stderr,"Unable to allocate resources for XvMC context.\n");
+ return BadAlloc;
+ }
+
+ pViaXvMC = (ViaXvMCContext *)context->privData;
+ pViaXvMC->resources = context_none;
+
+ /* Verify the XvMC extension exists */
+
+ XLockDisplay(display);
+ if(! XvMCQueryExtension(display, &event_base,
+ &error_base)) {
+ fprintf(stderr,"XvMC Extension is not available!\n");
+ free(pViaXvMC);
+ XUnlockDisplay(display);
+ return BadAlloc;
+ }
+
+ /* Verify XvMC version */
+ ret = XvMCQueryVersion(display, &major, &minor);
+ if(ret) {
+ fprintf(stderr,"XvMCQuery Version Failed, unable to determine "
+ "protocol version!\n");
+ }
+ XUnlockDisplay(display);
+
+ /* FIXME: Check Major and Minor here */
+
+ XLockDisplay(display);
+ if((ret = _xvmc_create_context(display, context, &priv_count,
+ &priv_data))) {
+ XUnlockDisplay(display);
+ fprintf(stderr,"Unable to create XvMC Context.\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ XUnlockDisplay(display);
+
+ /*
+ * Check size and version of returned data.
+ */
+
+ tmpComm = ( ViaXvMCCreateContextRec *) priv_data;
+ if(priv_count != (sizeof(ViaXvMCCreateContextRec) >> 2)) {
+ fprintf(stderr,"_xvmc_create_context() returned incorrect "
+ "data size!\n");
+ fprintf(stderr,"\tExpected %d, got %d\n",
+ (int) (sizeof(ViaXvMCCreateContextRec) >> 2),
+ (int) priv_count);
+ XFree(priv_data);
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ pViaXvMC->resources = context_context;
+
+ if ((tmpComm->major != VIAXVMC_MAJOR) ||
+ (tmpComm->minor != VIAXVMC_MINOR)) {
+ fprintf(stderr,"Version mismatch between the X via driver\n"
+ "and the XvMC library. Cannot continue!\n");
+ XFree(priv_data);
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+
+ pViaXvMC->ctxNo = tmpComm->ctxNo;
+ pViaXvMC->fbOffset = tmpComm->fbOffset;
+ pViaXvMC->fbSize = tmpComm->fbSize;
+ pViaXvMC->mmioOffset = tmpComm->mmioOffset;
+ pViaXvMC->mmioSize = tmpComm->mmioSize;
+ pViaXvMC->sAreaSize = tmpComm->sAreaSize;
+ pViaXvMC->sAreaPrivOffset = tmpComm->sAreaPrivOffset;
+ pViaXvMC->decoderOn = 0;
+ pViaXvMC->xvMCPort = tmpComm->xvmc_port;
+ pViaXvMC->useAGP = tmpComm->useAGP;
+ pViaXvMC->attrib = tmpComm->initAttrs;
+ pViaXvMC->screen = tmpComm->screen;
+ pViaXvMC->depth = tmpComm->depth;
+ pViaXvMC->stride = tmpComm->stride;
+ pViaXvMC->chipId = tmpComm->chipId;
+
+ /*
+ * Must free the private data we were passed from X
+ */
+
+ XFree(priv_data);
+
+ /*
+ * Check for direct rendering capable, establish DRI and DRM connections,
+ * map framebuffer, DRI shared area and read-only register areas.
+ * Initial checking for drm has already been done by the server.
+ * Only do this for the first context we create.
+ */
+
+ if (numContexts == 0) {
+ XLockDisplay(display);
+ ret = uniDRIQueryDirectRenderingCapable(display, pViaXvMC->screen, &isCapable);
+ if (!ret || !isCapable) {
+ XUnlockDisplay(display);
+ fprintf(stderr,"Direct Rendering is not available on this system!\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+
+ if (!uniDRIOpenConnection(display, pViaXvMC->screen, &pViaXvMC->sAreaOffset,
+ &curBusID)) {
+ XUnlockDisplay(display);
+ fprintf(stderr,"Could not open DRI connection to X server!\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ XUnlockDisplay(display);
+
+ strncpy(pViaXvMC->busIdString,curBusID,20);
+ pViaXvMC->busIdString[20] = '\0';
+ XFree(curBusID);
+
+ pViaXvMC->resources = context_driConnection;
+
+ if((pViaXvMC->fd = drmOpen("via",pViaXvMC->busIdString)) < 0) {
+ fprintf(stderr,"DRM Device for via could not be opened.\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ globalFD = pViaXvMC->fd;
+ pViaXvMC->resources = context_fd;
+
+ if (NULL == (drmVer = drmGetVersion(pViaXvMC->fd))) {
+ fprintf(stderr,
+ "viaXvMC: Could not get drm version.");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ if (((drmVer->version_major != 2 ) || (drmVer->version_minor < 0))) {
+ fprintf(stderr,
+ "viaXvMC: Kernel drm is not compatible with XvMC.\n");
+ fprintf(stderr,
+ "viaXvMC: Kernel drm version: %d.%d.%d "
+ "and I need at least version 2.0.0.\n"
+ "Please update.\n",
+ drmVer->version_major,drmVer->version_minor,
+ drmVer->version_patchlevel);
+ drmFreeVersion(drmVer);
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ drmFreeVersion(drmVer);
+ drmGetMagic(pViaXvMC->fd,&magic);
+
+ XLockDisplay(display);
+ if (!uniDRIAuthConnection(display, pViaXvMC->screen, magic)) {
+ XUnlockDisplay(display);
+ fprintf(stderr, "viaXvMC: X server did not allow DRI. Check permissions.\n");
+ XFree(priv_data);
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ XUnlockDisplay(display);
+
+ /*
+ * Map the register memory
+ */
+
+ if(drmMap(pViaXvMC->fd,pViaXvMC->mmioOffset,
+ pViaXvMC->mmioSize,&mmioAddress) < 0) {
+ fprintf(stderr,"Unable to map the display chip mmio registers.\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ pViaXvMC->mmioAddress = mmioAddress;
+ pViaXvMC->resources = context_mmioMap;
+
+ /*
+ * Map Framebuffer memory
+ */
+
+ if(drmMap(pViaXvMC->fd,pViaXvMC->fbOffset,
+ pViaXvMC->fbSize,&fbAddress) < 0) {
+ fprintf(stderr,"Unable to map XvMC Framebuffer.\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ pViaXvMC->fbAddress = fbAddress;
+ pViaXvMC->resources = context_fbMap;
+
+
+ /*
+ * Map DRI Sarea.
+ */
+
+ if(drmMap(pViaXvMC->fd,pViaXvMC->sAreaOffset,
+ pViaXvMC->sAreaSize,&sAreaAddress) < 0) {
+ fprintf(stderr,"Unable to map DRI SAREA.\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ } else {
+ pViaXvMC->fd = globalFD;
+ pViaXvMC->mmioAddress = mmioAddress;
+ pViaXvMC->fbAddress = fbAddress;
+ }
+
+ pViaXvMC->sAreaAddress = sAreaAddress;
+ pViaXvMC->resources = context_sAreaMap;
+ numContexts++;
+
+ /*
+ * Find a matching visual. Important only for direct drawing to the visible
+ * frame-buffer.
+ */
+
+ XLockDisplay(display);
+ ret = XMatchVisualInfo(display, pViaXvMC->screen,
+ (pViaXvMC->depth == 32) ? 24 : pViaXvMC->depth, TrueColor,
+ &pViaXvMC->visualInfo);
+ XUnlockDisplay(display);
+ if (!ret) {
+ fprintf(stderr, "viaXvMC: Could not find a matching TrueColor visual.\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+
+ if (!uniDRICreateContext(display, pViaXvMC->screen, pViaXvMC->visualInfo.visual,
+ &pViaXvMC->id, &pViaXvMC->drmcontext)) {
+
+ fprintf(stderr, "viaXvMC: Could not create DRI context.\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+
+ pViaXvMC->resources = context_drmContext;
+
+ for (i=0; i<VIA_MAX_RENDSURF; ++i) {
+ pViaXvMC->rendSurf[i] = 0;
+ }
+ pViaXvMC->lastSrfDisplaying = ~0;
+ setupAttribDesc(display, port, &pViaXvMC->attrib, pViaXvMC->attribDesc);
+
+ pViaXvMC->hwLock = (drmLockPtr) pViaXvMC->sAreaAddress;
+ defaultQMatrices(pViaXvMC);
+ pViaXvMC->chromaIntraLoaded = 1;
+ pViaXvMC->chromaNonIntraLoaded = 1;
+ pViaXvMC->yStride = (width + 31) & ~31;
+ pViaXvMC->haveDecoder = 0;
+ pViaXvMC->attribChanged = 1;
+ pViaXvMC->haveXv = 0;
+ pViaXvMC->port = context->port;
+ pthread_mutex_init(&pViaXvMC->ctxMutex,NULL);
+ pViaXvMC->resources = context_mutex;
+ pViaXvMC->timeStamp = 0;
+ setRegion(0,0,-1,-1,pViaXvMC->sRegion);
+ setRegion(0,0,-1,-1,pViaXvMC->dRegion);
+
+ if (NULL == (pViaXvMC->xl =
+ initXvMCLowLevel(pViaXvMC->fd, &pViaXvMC->drmcontext,
+ pViaXvMC->hwLock, pViaXvMC->mmioAddress,
+ pViaXvMC->fbAddress, pViaXvMC->stride, pViaXvMC->depth,
+ context->width, context->height,
+ pViaXvMC->useAGP, pViaXvMC->chipId))) {
+
+ fprintf(stderr,"ViaXvMC: Could not allocate timestamp blit area.\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ pViaXvMC->resources = context_lowLevel;
+ setAGPSyncLowLevel(pViaXvMC->xl, 1, 0);
+
+ if (NULL == (pViaXvMC->drawHash = drmHashCreate())) {
+ fprintf(stderr,"ViaXvMC: Could not allocate drawable hash table.\n");
+ return releaseContextResources(display, context, 1, BadAlloc);
+ }
+ pViaXvMC->resources = context_drawHash;
+
+
+ if (numContexts == 1) {
+ hwlLock(pViaXvMC->xl,1);
+ setLowLevelLocking(pViaXvMC->xl,0);
+ viaVideoSubPictureOffLocked(pViaXvMC->xl);
+ flushXvMCLowLevel(pViaXvMC->xl);
+ setLowLevelLocking(pViaXvMC->xl,1);
+ hwlUnlock(pViaXvMC->xl,1);
+ }
+
+ return Success;
+}
+
+
+Status XvMCDestroyContext(Display *display, XvMCContext *context)
+{
+ ViaXvMCContext *pViaXvMC;
+
+
+ if(context == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ if(NULL == (pViaXvMC = context->privData)) {
+ return (error_base + XvMCBadContext);
+ }
+
+ /*
+ * Release decoder if we have it. In case of crash or termination
+ * before XvMCDestroyContext, the X server will take care of this.
+ */
+
+ releaseAttribDesc(pViaXvMC->attrib.numAttr,pViaXvMC->attribDesc);
+ releaseDecoder(pViaXvMC,1);
+ return releaseContextResources(display, context, 1, Success);
+}
+
+Status XvMCCreateSurface( Display *display, XvMCContext *context,
+ XvMCSurface *surface)
+{
+ ViaXvMCContext *pViaXvMC;
+ ViaXvMCSurface *pViaSurface;
+ int priv_count;
+ unsigned *priv_data;
+ unsigned i;
+ Status ret;
+
+ if((surface == NULL) || (context == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ pViaXvMC = (ViaXvMCContext *)context->privData;
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+
+ if(pViaXvMC == NULL) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return (error_base + XvMCBadContext);
+ }
+
+ pViaSurface = surface->privData = (ViaXvMCSurface *)malloc(sizeof(ViaXvMCSurface));
+ if(!surface->privData) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadAlloc;
+ }
+ XLockDisplay(display);
+ if((ret = _xvmc_create_surface(display, context, surface,
+ &priv_count, &priv_data))) {
+ XUnlockDisplay(display);
+ free(pViaSurface);
+ fprintf(stderr,"Unable to create XvMC Surface.\n");
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return ret;
+ }
+ XUnlockDisplay(display);
+
+ pViaSurface->srfNo = priv_data[0];
+
+ /*
+ * Store framebuffer offsets to the buffers allocated for this surface.
+ * For some chipset revisions, surfaces may be double-buffered.
+ */
+
+ pViaSurface->numBuffers = priv_data[1];
+ for (i=0; i < pViaSurface->numBuffers; ++i) {
+ pViaSurface->offsets[i] = priv_data[i+2];
+ }
+ pViaSurface->curBuf = 0;
+
+
+ /* Free data returned from xvmc_create_surface */
+
+ XFree(priv_data);
+
+ pViaSurface->width = context->width;
+ pViaSurface->height = context->height;
+ pViaSurface->yStride = pViaXvMC->yStride;
+ pViaSurface->privContext = pViaXvMC;
+ pViaSurface->privSubPic = NULL;
+ pViaSurface->needsSync = 0;
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
+{
+ ViaXvMCSurface *pViaSurface;
+
+ if((display == NULL) || (surface == NULL)) {
+ return BadValue;
+ }
+ if(surface->privData == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ pViaSurface = (ViaXvMCSurface *)surface->privData;
+
+ XLockDisplay(display);
+ _xvmc_destroy_surface(display,surface);
+ XUnlockDisplay(display);
+
+ free(pViaSurface);
+ surface->privData = NULL;
+ return Success;
+}
+
+Status XvMCPutSlice2(Display *display,XvMCContext *context, char *slice,
+ int nBytes, int sliceCode)
+{
+ ViaXvMCContext *pViaXvMC;
+ CARD32 sCode = 0x00010000 | (sliceCode & 0xFF) << 24;
+
+ if((display == NULL) || (context == NULL)) {
+ return BadValue;
+ }
+ if(NULL == (pViaXvMC = context->privData)) {
+ return (error_base + XvMCBadContext);
+ }
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ if (!pViaXvMC->haveDecoder) {
+ fprintf(stderr,"XvMCPutSlice: This context does not own decoder!\n");
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadAlloc;
+ }
+
+ viaMpegWriteSlice(pViaXvMC->xl, (CARD8 *)slice, nBytes, sCode);
+
+ flushPCIXvMCLowLevel(pViaXvMC->xl);
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+Status XvMCPutSlice(Display *display,XvMCContext *context, char *slice,
+ int nBytes)
+{
+ ViaXvMCContext *pViaXvMC;
+
+ if((display == NULL) || (context == NULL)) {
+ return BadValue;
+ }
+ if(NULL == (pViaXvMC = context->privData)) {
+ return (error_base + XvMCBadContext);
+ }
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+
+ if (!pViaXvMC->haveDecoder) {
+ fprintf(stderr,"XvMCPutSlice: This context does not own decoder!\n");
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadAlloc;
+ }
+
+ viaMpegWriteSlice(pViaXvMC->xl, (CARD8 *)slice, nBytes, 0);
+ flushPCIXvMCLowLevel(pViaXvMC->xl);
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+
+static Status updateXVOverlay(Display *display,ViaXvMCContext *pViaXvMC,
+ ViaXvMCSurface *pViaSurface, Drawable draw,
+ short srcx, short srcy, unsigned short srcw,
+ unsigned short srch,short destx,short desty,
+ unsigned short destw,unsigned short desth)
+{
+ ViaXvMCCommandBuffer buf;
+ ViaXvMCSubPicture *pViaSubPic;
+ Status ret;
+
+ if (!pViaXvMC->haveXv) {
+ pViaXvMC->xvImage =
+ XvCreateImage(display,pViaXvMC->port,FOURCC_XVMC,
+ (char *)&buf,pViaSurface->width,
+ pViaSurface->height);
+ pViaXvMC->gc = XCreateGC(display,draw,0,0);
+ pViaXvMC->haveXv = 1;
+ }
+ pViaXvMC->draw = draw;
+ pViaXvMC->xvImage->data = (char *)&buf;
+
+ buf.command = (pViaXvMC->attribChanged) ?
+ VIA_XVMC_COMMAND_FDISPLAY : VIA_XVMC_COMMAND_DISPLAY;
+ buf.ctxNo = pViaXvMC->ctxNo | VIA_XVMC_VALID;
+ buf.srfNo = pViaSurface->srfNo | VIA_XVMC_VALID;
+ pViaSubPic = pViaSurface->privSubPic;
+ buf.subPicNo = ((NULL == pViaSubPic) ? 0 : pViaSubPic->srfNo )
+ | VIA_XVMC_VALID;
+ buf.attrib = pViaXvMC->attrib;
+
+ XLockDisplay(display);
+
+ if ((ret = XvPutImage(display,pViaXvMC->port,draw,pViaXvMC->gc,
+ pViaXvMC->xvImage,srcx,srcy,srcw,srch,
+ destx,desty,destw,desth))) {
+ XUnlockDisplay(display);
+ return ret;
+ }
+ XSync(display, 0);
+ XUnlockDisplay(display);
+ pViaXvMC->attribChanged = 0;
+ return Success;
+}
+
+
+Status XvMCPutSurface(Display *display,XvMCSurface *surface,Drawable draw,
+ short srcx, short srcy, unsigned short srcw,
+ unsigned short srch,short destx,short desty,
+ unsigned short destw,unsigned short desth, int flags)
+{
+ /*
+ * This function contains some hairy locking logic. What we really want to
+ * do is to flip the picture ASAP, to get a low latency and smooth playback.
+ * However, if somebody else used the overlay since we used it last or if it is
+ * our first time, we'll have to call X to update the overlay first. Otherwise
+ * we'll do the overlay update once we've flipped. Since we release the hardware
+ * lock when we call X, X needs to verify using the SAREA that nobody else flipped
+ * in a picture between the lock release and the X server control. Similarly
+ * when the overlay update returns, we have to make sure that we still own the
+ * overlay.
+ */
+
+ ViaXvMCSurface *pViaSurface;
+ ViaXvMCContext *pViaXvMC;
+ ViaXvMCSubPicture *pViaSubPic;
+ volatile ViaXvMCSAreaPriv *sAPriv;
+ Status ret;
+ unsigned dispSurface, lastSurface;
+ int overlayUpdated;
+ drawableInfo *drawInfo;
+ XvMCRegion sReg, dReg;
+ Bool forceUpdate = FALSE;
+
+ if((display == NULL) || (surface == NULL)) {
+ return BadValue;
+ }
+ if(NULL == (pViaSurface = surface->privData )) {
+ return (error_base + XvMCBadSurface);
+ }
+ if (NULL == (pViaXvMC = pViaSurface->privContext)) {
+ return (error_base + XvMCBadContext);
+ }
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ pViaSubPic = pViaSurface->privSubPic;
+ sAPriv = SAREAPTR( pViaXvMC );
+
+ setRegion(srcx, srcy, srcw, srch, sReg);
+ setRegion(destx, desty, destw, desth, dReg);
+
+
+ if ((!regionEqual(sReg, pViaXvMC->sRegion)) ||
+ (!regionEqual(dReg, pViaXvMC->dRegion))) {
+
+ /*
+ * Force update of the video overlay to match the new format.
+ */
+
+ pViaXvMC->sRegion = sReg;
+ pViaXvMC->dRegion = dReg;
+ forceUpdate = TRUE;
+ }
+
+
+ hwlLock(pViaXvMC->xl,1);
+
+ if (getDRIDrawableInfoLocked(pViaXvMC->drawHash, display, pViaXvMC->screen, draw, 0,
+ pViaXvMC->fd, pViaXvMC->drmcontext, pViaXvMC->sAreaAddress,
+ FALSE, &drawInfo, sizeof(*drawInfo))) {
+
+ hwlUnlock(pViaXvMC->xl,1);
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadAccess;
+ }
+
+ setLowLevelLocking(pViaXvMC->xl,0);
+
+
+ /*
+ * Put a surface ID in the SAREA to "authenticate" to the
+ * X server.
+ */
+
+ dispSurface = sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort];
+ lastSurface = pViaXvMC->lastSrfDisplaying;
+ sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort] =
+ pViaXvMC->lastSrfDisplaying = pViaSurface->srfNo | VIA_XVMC_VALID;
+ overlayUpdated = 0;
+
+ viaVideoSetSWFLipLocked(pViaXvMC->xl, yOffs(pViaSurface), uOffs(pViaSurface),
+ vOffs(pViaSurface), pViaSurface->yStride, pViaSurface->yStride >> 1);
+
+ while ((lastSurface != dispSurface) || forceUpdate) {
+
+ forceUpdate = FALSE;
+ flushPCIXvMCLowLevel(pViaXvMC->xl);
+ setLowLevelLocking(pViaXvMC->xl,1);
+ hwlUnlock(pViaXvMC->xl,1);
+
+ /*
+ * We weren't the last to display. Update the overlay before flipping.
+ */
+
+ ret = updateXVOverlay(display,pViaXvMC,pViaSurface,draw,srcx,srcy,srcw,
+ srch,destx,desty,destw,desth);
+ if (ret) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return ret;
+ }
+
+ hwlLock(pViaXvMC->xl,1);
+
+ if (getDRIDrawableInfoLocked(pViaXvMC->drawHash, display, pViaXvMC->screen, draw, 0,
+ pViaXvMC->fd, pViaXvMC->drmcontext, pViaXvMC->sAreaAddress,
+ FALSE, &drawInfo, sizeof(*drawInfo))) {
+
+ hwlUnlock(pViaXvMC->xl,1);
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadAccess;
+ }
+
+ setLowLevelLocking(pViaXvMC->xl,0);
+ lastSurface = pViaSurface->srfNo | VIA_XVMC_VALID;
+ dispSurface = sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort];
+ overlayUpdated = 1;
+ }
+
+
+ /*
+ * Subpictures
+ */
+
+ if (NULL != pViaSubPic) {
+ if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort]
+ != (pViaSubPic->srfNo | VIA_XVMC_VALID)) {
+ sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] =
+ pViaSubPic->srfNo | VIA_XVMC_VALID;
+ viaVideoSubPictureLocked(pViaXvMC->xl, pViaSubPic);
+ }
+ } else {
+ if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] & VIA_XVMC_VALID) {
+ viaVideoSubPictureOffLocked(pViaXvMC->xl);
+ sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] &= ~VIA_XVMC_VALID;
+ }
+ }
+
+ /*
+ * Flip
+ */
+
+ viaVideoSWFlipLocked(pViaXvMC->xl, flags, pViaSurface->progressiveSequence);
+ flushXvMCLowLevel(pViaXvMC->xl);
+
+ setLowLevelLocking(pViaXvMC->xl,1);
+ hwlUnlock(pViaXvMC->xl,1);
+
+ if (overlayUpdated || !drawInfo->touched ) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+ }
+
+ /*
+ * Update overlay
+ */
+
+ ret = updateXVOverlay(display,pViaXvMC,pViaSurface,draw,srcx,srcy,srcw,
+ srch,destx,desty,destw,desth);
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return ret;
+
+}
+
+Status XvMCBeginSurface(Display *display,
+ XvMCContext *context,
+ XvMCSurface *target_surface,
+ XvMCSurface *past_surface,
+ XvMCSurface *future_surface,
+ const XvMCMpegControl *control)
+{
+ ViaXvMCSurface *targS,*futS,*pastS;
+ ViaXvMCContext *pViaXvMC;
+ int hadDecoderLast;
+ CARD32 timeStamp;
+
+ if((display == NULL) || (context == NULL) || (target_surface == NULL)) {
+ return BadValue;
+ }
+
+ pViaXvMC = context->privData;
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ if (grabDecoder(pViaXvMC, &hadDecoderLast)) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadAlloc;
+ }
+ pViaXvMC->haveDecoder = 1;
+
+ /*
+ * We need to wait for decoder idle at next flush, since hardware doesn't queue
+ * beginsurface requests until the decoder is idle. This is
+ * done by waiting on the last previous timestamp, or if there was another context
+ * having the decoder before us, by emitting a new one.
+ */
+
+ if (pViaXvMC->useAGP) {
+ if (!hadDecoderLast || pViaXvMC->timeStamp == 0) {
+ timeStamp = viaDMATimeStampLowLevel(pViaXvMC->xl);
+ if (flushXvMCLowLevel(pViaXvMC->xl)) {
+ releaseDecoder(pViaXvMC, 0);
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadAlloc;
+ }
+ pViaXvMC->timeStamp = timeStamp;
+ } else {
+ timeStamp = pViaXvMC->timeStamp;
+ }
+ setAGPSyncLowLevel(pViaXvMC->xl, 1, timeStamp);
+ }
+
+ if (!hadDecoderLast || !pViaXvMC->decoderOn) {
+ pViaXvMC->intraLoaded = 0;
+ pViaXvMC->nonIntraLoaded = 0;
+ }
+
+ viaMpegReset(pViaXvMC->xl);
+
+ targS = (ViaXvMCSurface *)target_surface->privData;
+ futS = NULL;
+ pastS = NULL;
+
+
+ pViaXvMC->rendSurf[0] = targS->srfNo | VIA_XVMC_VALID;
+ if (future_surface) {
+ futS = (ViaXvMCSurface *)future_surface->privData;
+ futS->needsSync = 0;
+ }
+ if (past_surface) {
+ pastS = (ViaXvMCSurface *)past_surface->privData;
+ pastS->needsSync = 0;
+ }
+
+
+ targS->progressiveSequence = (control->flags & XVMC_PROGRESSIVE_SEQUENCE);
+ targS->topFieldFirst = (control->flags & XVMC_TOP_FIELD_FIRST);
+ targS->privSubPic = NULL;
+
+ viaMpegSetSurfaceStride(pViaXvMC->xl,pViaXvMC);
+
+ viaMpegSetFB(pViaXvMC->xl,0,yOffs(targS),uOffs(targS),vOffs(targS));
+ if (past_surface) {
+ viaMpegSetFB(pViaXvMC->xl,1,yOffs(pastS),uOffs(pastS),vOffs(pastS));
+ } else {
+ viaMpegSetFB(pViaXvMC->xl,1,0,0,0);
+ }
+
+ if (future_surface) {
+ viaMpegSetFB(pViaXvMC->xl,2,yOffs(futS),uOffs(futS),vOffs(futS));
+ } else {
+ viaMpegSetFB(pViaXvMC->xl,2,0,0,0);
+ }
+
+ viaMpegBeginPicture(pViaXvMC->xl,pViaXvMC,context->width,context->height,control);
+ flushPCIXvMCLowLevel(pViaXvMC->xl);
+ targS->needsSync = 1;
+ targS->syncMode = LL_MODE_DECODER_IDLE;
+ pViaXvMC->decoderOn = 1;
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+
+Status XvMCSyncSurface(Display *display,XvMCSurface *surface)
+{
+ ViaXvMCSurface *pViaSurface;
+ ViaXvMCContext *pViaXvMC;
+ unsigned i;
+
+ if((display == NULL) || (surface == NULL)) {
+ return BadValue;
+ }
+ if(surface->privData == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ pViaSurface = (ViaXvMCSurface *)surface->privData;
+ pViaXvMC = pViaSurface->privContext;
+
+ if(pViaXvMC == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+
+ if (pViaSurface->needsSync) {
+ CARD32 timeStamp = pViaSurface->timeStamp;
+ int syncMode = pViaSurface->syncMode;
+
+ if (pViaXvMC->useAGP) {
+
+ syncMode = (pViaSurface->syncMode == LL_MODE_2D ||
+ pViaSurface->timeStamp < pViaXvMC->timeStamp) ?
+ LL_MODE_2D : LL_MODE_DECODER_IDLE;
+ if (pViaSurface->syncMode != LL_MODE_2D)
+ timeStamp = pViaXvMC->timeStamp;
+
+ } else if (syncMode != LL_MODE_2D &&
+ pViaXvMC->rendSurf[0] != (pViaSurface->srfNo | VIA_XVMC_VALID)) {
+
+ pViaSurface->needsSync = 0;
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+ }
+
+ if (syncXvMCLowLevel(pViaXvMC->xl, syncMode, 1,
+ pViaSurface->timeStamp)) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadValue;
+ }
+ pViaSurface->needsSync = 0;
+ }
+
+ if (pViaXvMC->rendSurf[0] == (pViaSurface->srfNo | VIA_XVMC_VALID)) {
+ pViaSurface->needsSync = 0;
+ for (i=0; i<VIA_MAX_RENDSURF; ++i) {
+ pViaXvMC->rendSurf[i] = 0;
+ }
+ }
+
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+Status XvMCLoadQMatrix(Display *display, XvMCContext *context,
+ const XvMCQMatrix *qmx)
+{
+ ViaXvMCContext
+ *pViaXvMC;
+
+ if((display == NULL) || (context == NULL)) {
+ return BadValue;
+ }
+ if(NULL == (pViaXvMC = context->privData)) {
+ return (error_base + XvMCBadContext);
+ }
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ if (qmx->load_intra_quantiser_matrix) {
+ memcpy(pViaXvMC->intra_quantiser_matrix,
+ qmx->intra_quantiser_matrix,
+ sizeof(qmx->intra_quantiser_matrix));
+ pViaXvMC->intraLoaded = 0;
+ }
+
+ if (qmx->load_non_intra_quantiser_matrix) {
+ memcpy(pViaXvMC->non_intra_quantiser_matrix,
+ qmx->non_intra_quantiser_matrix,
+ sizeof(qmx->non_intra_quantiser_matrix));
+ pViaXvMC->nonIntraLoaded = 0;
+ }
+
+ if (qmx->load_chroma_intra_quantiser_matrix) {
+ memcpy(pViaXvMC->chroma_intra_quantiser_matrix,
+ qmx->chroma_intra_quantiser_matrix,
+ sizeof(qmx->chroma_intra_quantiser_matrix));
+ pViaXvMC->chromaIntraLoaded = 0;
+ }
+
+ if (qmx->load_chroma_non_intra_quantiser_matrix) {
+ memcpy(pViaXvMC->chroma_non_intra_quantiser_matrix,
+ qmx->chroma_non_intra_quantiser_matrix,
+ sizeof(qmx->chroma_non_intra_quantiser_matrix));
+ pViaXvMC->chromaNonIntraLoaded = 0;
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+
+ return Success;
+}
+
+/*
+ * Below, we provide functions unusable for this implementation, but for
+ * standard completeness.
+ */
+
+
+Status XvMCRenderSurface
+(
+ Display *display,
+ XvMCContext *context,
+ unsigned int picture_structure,
+ XvMCSurface *target_surface,
+ XvMCSurface *past_surface,
+ XvMCSurface *future_surface,
+ unsigned int flags,
+ unsigned int num_macroblocks,
+ unsigned int first_macroblock,
+ XvMCMacroBlockArray *macroblock_array,
+ XvMCBlockArray *blocks
+ )
+{
+ return (error_base + XvMCBadContext);
+}
+
+Status XvMCCreateBlocks
+(
+ Display *display,
+ XvMCContext *context,
+ unsigned int num_blocks,
+ XvMCBlockArray * block
+ )
+{
+ return (error_base + XvMCBadContext);
+}
+
+Status XvMCDestroyBlocks (Display *display, XvMCBlockArray * block)
+{
+ return Success;
+}
+
+Status XvMCCreateMacroBlocks
+(
+ Display *display,
+ XvMCContext *context,
+ unsigned int num_blocks,
+ XvMCMacroBlockArray * blocks
+ )
+{
+ return (error_base + XvMCBadContext);
+}
+
+Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray * block)
+{
+ return (error_base + XvMCBadContext);
+}
+
+Status XvMCCreateSubpicture( Display *display,
+ XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ unsigned short width,
+ unsigned short height,
+ int xvimage_id)
+{
+ ViaXvMCContext *pViaXvMC;
+ ViaXvMCSubPicture *pViaSubPic;
+ int priv_count;
+ unsigned *priv_data;
+ Status ret;
+
+ if((subpicture == NULL) || (context == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ pViaXvMC = (ViaXvMCContext *)context->privData;
+ if(pViaXvMC == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+
+ subpicture->privData = (ViaXvMCSubPicture *)
+ malloc(sizeof(ViaXvMCSubPicture));
+ if(!subpicture->privData) {
+ return BadAlloc;
+ }
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ subpicture->width = context->width;
+ subpicture->height = context->height;
+ subpicture->xvimage_id = xvimage_id;
+ pViaSubPic = (ViaXvMCSubPicture *)subpicture->privData;
+
+ XLockDisplay(display);
+ if((ret = _xvmc_create_subpicture(display, context, subpicture,
+ &priv_count, &priv_data))) {
+ XUnlockDisplay(display);
+ free(pViaSubPic);
+ fprintf(stderr,"Unable to create XvMC Subpicture.\n");
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return ret;
+ }
+ XUnlockDisplay(display);
+
+
+ subpicture->num_palette_entries = VIA_SUBPIC_PALETTE_SIZE;
+ subpicture->entry_bytes = 3;
+ strncpy(subpicture->component_order,"YUV",4);
+ pViaSubPic->srfNo = priv_data[0];
+ pViaSubPic->offset = priv_data[1];
+ pViaSubPic->stride = (subpicture->width + 31) & ~31;
+ pViaSubPic->privContext = pViaXvMC;
+ pViaSubPic->ia44 = (xvimage_id == FOURCC_IA44);
+ pViaSubPic->needsSync = 0;
+
+ /* Free data returned from _xvmc_create_subpicture */
+
+ XFree(priv_data);
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+Status
+XvMCSetSubpicturePalette (Display *display, XvMCSubpicture *subpicture,
+ unsigned char *palette)
+{
+ ViaXvMCSubPicture *pViaSubPic;
+ ViaXvMCContext *pViaXvMC;
+ volatile ViaXvMCSAreaPriv *sAPriv;
+ unsigned i;
+ CARD32 tmp;
+
+ if((subpicture == NULL) || (display == NULL)){
+ return BadValue;
+ }
+ if(subpicture->privData == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData;
+ for (i=0; i < VIA_SUBPIC_PALETTE_SIZE; ++i) {
+ tmp = *palette++ << 8;
+ tmp |= *palette++ << 16;
+ tmp |= *palette++ << 24;
+ tmp |= ((i & 0x0f) << 4) | 0x07;
+ pViaSubPic->palette[i] = tmp;
+ }
+
+ pViaXvMC = pViaSubPic->privContext;
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ sAPriv = SAREAPTR( pViaXvMC );
+ hwlLock(pViaXvMC->xl,1);
+ setLowLevelLocking(pViaXvMC->xl,0);
+
+ /*
+ * If the subpicture is displaying, Immeadiately update it with the
+ * new palette.
+ */
+
+ if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] ==
+ (pViaSubPic->srfNo | VIA_XVMC_VALID)) {
+ viaVideoSubPictureLocked(pViaXvMC->xl,pViaSubPic);
+ }
+ flushPCIXvMCLowLevel(pViaXvMC->xl);
+ setLowLevelLocking(pViaXvMC->xl,1);
+ hwlUnlock(pViaXvMC->xl,1);
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+
+static int findOverlap(unsigned width,unsigned height,
+ short *dstX, short *dstY,
+ short *srcX, short *srcY,
+ unsigned short *areaW, unsigned short *areaH)
+{
+ int
+ w,h;
+ unsigned
+ mWidth,mHeight;
+
+ w = *areaW;
+ h = *areaH;
+
+ if ((*dstX >= width) || (*dstY >= height))
+ return 1;
+ if (*dstX < 0) {
+ w += *dstX;
+ *srcX -= *dstX;
+ *dstX = 0;
+ }
+ if (*dstY < 0) {
+ h += *dstY;
+ *srcY -= *dstY;
+ *dstY = 0;
+ }
+ if ((w <= 0) || ((h <= 0)))
+ return 1;
+ mWidth = width - *dstX;
+ mHeight = height - *dstY;
+ *areaW = (w <= mWidth) ? w : mWidth;
+ *areaH = (h <= mHeight) ? h : mHeight;
+ return 0;
+}
+
+
+
+Status XvMCClearSubpicture (
+ Display *display,
+ XvMCSubpicture *subpicture,
+ short x,
+ short y,
+ unsigned short width,
+ unsigned short height,
+ unsigned int color
+ )
+{
+
+ ViaXvMCContext *pViaXvMC;
+ ViaXvMCSubPicture *pViaSubPic;
+ short dummyX,dummyY;
+ unsigned long bOffs;
+
+ if((subpicture == NULL) || (display == NULL)) {
+ return BadValue;
+ }
+ if(subpicture->privData == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ pViaSubPic = (ViaXvMCSubPicture *) subpicture->privData;
+ pViaXvMC = pViaSubPic->privContext;
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+
+ /* Clip clearing area so that it fits inside subpicture. */
+
+ if (findOverlap(subpicture->width, subpicture->height, &x, &y,
+ &dummyX, &dummyY, &width, &height)) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+ }
+
+ bOffs = pViaSubPic->offset + y*pViaSubPic->stride + x;
+ viaBlit(pViaXvMC->xl, 8, 0, pViaSubPic->stride, bOffs, pViaSubPic->stride,
+ width, height, 1, 1, VIABLIT_FILL, color);
+ pViaSubPic->needsSync = 1;
+ pViaSubPic->timeStamp = viaDMATimeStampLowLevel(pViaXvMC->xl);
+ if (flushXvMCLowLevel(pViaXvMC->xl)) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadValue;
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+Status
+XvMCCompositeSubpicture (
+ Display *display,
+ XvMCSubpicture *subpicture,
+ XvImage *image,
+ short srcx,
+ short srcy,
+ unsigned short width,
+ unsigned short height,
+ short dstx,
+ short dsty
+ )
+{
+
+ unsigned i;
+ ViaXvMCContext *pViaXvMC;
+ ViaXvMCSubPicture *pViaSubPic;
+ CARD8 *dAddr, *sAddr;
+
+ if((subpicture == NULL) || (display == NULL) || (image == NULL)){
+ return BadValue;
+ }
+ if(NULL == (pViaSubPic = (ViaXvMCSubPicture *)subpicture->privData)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ pViaXvMC = pViaSubPic->privContext;
+
+
+ if (image->id != subpicture->xvimage_id)
+ return BadMatch;
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+
+
+ /*
+ * Clip copy area so that it fits inside subpicture and image.
+ */
+
+ if (findOverlap(subpicture->width, subpicture->height,
+ &dstx, &dsty, &srcx, &srcy, &width, &height)) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+ }
+ if (findOverlap(image->width, image->height,
+ &srcx, &srcy, &dstx, &dsty, &width, &height)) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+ }
+
+ if (pViaSubPic->needsSync) {
+ if (syncXvMCLowLevel(pViaXvMC->xl, LL_MODE_2D, 0, pViaSubPic->timeStamp)) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadValue;
+ }
+ pViaSubPic->needsSync = 0;
+ }
+
+ for(i=0; i<height; ++i) {
+ dAddr = (((CARD8 *)pViaXvMC->fbAddress) +
+ (pViaSubPic->offset + (dsty+i)*pViaSubPic->stride + dstx));
+ sAddr = (((CARD8 *)image->data) +
+ (image->offsets[0] + (srcy+i)*image->pitches[0] + srcx));
+ memcpy(dAddr,sAddr,width);
+ }
+
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+
+
+Status
+XvMCBlendSubpicture (
+ Display *display,
+ XvMCSurface *target_surface,
+ XvMCSubpicture *subpicture,
+ short subx,
+ short suby,
+ unsigned short subw,
+ unsigned short subh,
+ short surfx,
+ short surfy,
+ unsigned short surfw,
+ unsigned short surfh
+ )
+{
+ ViaXvMCSurface *pViaSurface;
+ ViaXvMCSubPicture *pViaSubPic;
+
+ if((display == NULL) || target_surface == NULL){
+ return BadValue;
+ }
+
+ if (subx || suby || surfx || surfy ||
+ (subw != surfw) || (subh != surfh)) {
+ fprintf(stderr,"ViaXvMC: Only completely overlapping subpicture "
+ "supported.\n");
+ return BadValue;
+ }
+
+ if(NULL == (pViaSurface = target_surface->privData)) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ if (subpicture) {
+
+ if(NULL == (pViaSubPic = subpicture->privData)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ pViaSurface->privSubPic = pViaSubPic;
+ } else {
+ pViaSurface->privSubPic = NULL;
+ }
+ return Success;
+}
+
+Status
+XvMCBlendSubpicture2 (
+ Display *display,
+ XvMCSurface *source_surface,
+ XvMCSurface *target_surface,
+ XvMCSubpicture *subpicture,
+ short subx,
+ short suby,
+ unsigned short subw,
+ unsigned short subh,
+ short surfx,
+ short surfy,
+ unsigned short surfw,
+ unsigned short surfh
+ )
+{
+ ViaXvMCSurface *pViaSurface,*pViaSSurface;
+ ViaXvMCSubPicture *pViaSubPic;
+ ViaXvMCContext *pViaXvMC;
+
+ unsigned width,height;
+
+ if((display == NULL) || target_surface == NULL || source_surface == NULL){
+ return BadValue;
+ }
+
+ if (subx || suby || surfx || surfy ||
+ (subw != surfw) || (subh != surfh)) {
+ fprintf(stderr,"ViaXvMC: Only completely overlapping subpicture "
+ "supported.\n");
+ return BadMatch;
+ }
+
+ if(NULL == (pViaSurface = target_surface->privData)) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ if(NULL == (pViaSSurface = source_surface->privData)) {
+ return (error_base + XvMCBadSurface);
+ }
+ pViaXvMC = pViaSurface->privContext;
+ width = pViaSSurface->width;
+ height = pViaSSurface->height;
+ if (width != pViaSurface->width || height != pViaSSurface->height) {
+ return BadMatch;
+ }
+
+ if (XvMCSyncSurface(display,source_surface)) {
+ return BadValue;
+ }
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ viaBlit(pViaXvMC->xl, 8, yOffs(pViaSSurface), pViaSSurface->yStride,
+ yOffs(pViaSurface), pViaSurface->yStride,
+ width, height, 1, 1, VIABLIT_COPY, 0);
+ flushPCIXvMCLowLevel(pViaXvMC->xl);
+ if (pViaXvMC->chipId != PCI_CHIP_VT3259) {
+
+ /*
+ * YV12 Chroma blit.
+ */
+
+ viaBlit(pViaXvMC->xl, 8, uOffs(pViaSSurface), pViaSSurface->yStride >> 1,
+ uOffs(pViaSurface), pViaSurface->yStride >> 1,
+ width >> 1, height >> 1, 1, 1, VIABLIT_COPY, 0);
+ flushPCIXvMCLowLevel(pViaXvMC->xl);
+ viaBlit(pViaXvMC->xl, 8, vOffs(pViaSSurface), pViaSSurface->yStride >> 1,
+ vOffs(pViaSurface), pViaSurface->yStride >> 1,
+ width >> 1, height >> 1, 1, 1, VIABLIT_COPY, 0);
+ } else {
+
+ /*
+ * NV12 Chroma blit.
+ */
+
+ viaBlit(pViaXvMC->xl, 8, vOffs(pViaSSurface), pViaSSurface->yStride,
+ vOffs(pViaSurface), pViaSurface->yStride,
+ width, height >> 1, 1, 1, VIABLIT_COPY, 0);
+ }
+ pViaSurface->needsSync = 1;
+ pViaSurface->syncMode = LL_MODE_2D;
+ pViaSurface->timeStamp = viaDMATimeStampLowLevel(pViaXvMC->xl);
+ if (flushXvMCLowLevel(pViaXvMC->xl)) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadValue;
+ }
+ if (subpicture) {
+
+ if(NULL == (pViaSubPic = subpicture->privData)) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ pViaSurface->privSubPic = pViaSubPic;
+ } else {
+ pViaSurface->privSubPic = NULL;
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+
+Status
+XvMCSyncSubpicture (Display *display, XvMCSubpicture *subpicture)
+{
+ ViaXvMCSubPicture *pViaSubPic;
+ ViaXvMCContext *pViaXvMC;
+ Status retVal=0;
+
+ if((display == NULL) || subpicture == NULL){
+ return BadValue;
+ }
+ if(NULL == (pViaSubPic = subpicture->privData)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ pViaXvMC = pViaSubPic->privContext;
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ if (pViaSubPic->needsSync) {
+ if (syncXvMCLowLevel(pViaXvMC->xl, LL_MODE_2D,
+ 0, pViaSubPic->timeStamp)) {
+ retVal = BadValue;
+ }
+ pViaSubPic->needsSync = 0;
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return retVal;
+}
+
+Status
+XvMCFlushSubpicture (Display *display, XvMCSubpicture *subpicture)
+{
+ ViaXvMCSubPicture *pViaSubPic;
+
+ if((display == NULL) || subpicture == NULL){
+ return BadValue;
+ }
+ if(NULL == (pViaSubPic = subpicture->privData)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ return Success;
+}
+
+Status
+XvMCDestroySubpicture (Display *display, XvMCSubpicture *subpicture)
+{
+ ViaXvMCSubPicture *pViaSubPic;
+ ViaXvMCContext *pViaXvMC;
+ volatile ViaXvMCSAreaPriv *sAPriv;
+
+ if((display == NULL) || subpicture == NULL){
+ return BadValue;
+ }
+ if(NULL == (pViaSubPic = subpicture->privData)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ pViaXvMC = pViaSubPic->privContext;
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+
+
+ sAPriv = SAREAPTR(pViaXvMC);
+ hwlLock(pViaXvMC->xl,1);
+ setLowLevelLocking(pViaXvMC->xl,0);
+ if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] ==
+ ( pViaSubPic->srfNo | VIA_XVMC_VALID )) {
+ viaVideoSubPictureOffLocked(pViaXvMC->xl);
+ sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] = 0;
+ }
+ flushPCIXvMCLowLevel(pViaXvMC->xl);
+ setLowLevelLocking(pViaXvMC->xl,1);
+ hwlUnlock(pViaXvMC->xl,1);
+
+ XLockDisplay(display);
+ _xvmc_destroy_subpicture(display,subpicture);
+ XUnlockDisplay(display);
+
+ free(pViaSubPic);
+ subpicture->privData = NULL;
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+
+ return Success;
+}
+
+Status
+XvMCGetSubpictureStatus (Display *display, XvMCSubpicture *subpic, int *stat)
+{
+ ViaXvMCSubPicture *pViaSubPic;
+ ViaXvMCContext *pViaXvMC;
+ volatile ViaXvMCSAreaPriv *sAPriv;
+
+
+ if((display == NULL) || subpic == NULL){
+ return BadValue;
+ }
+ if(NULL == (pViaSubPic = subpic->privData)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ if (stat) {
+ *stat = 0;
+ pViaXvMC = pViaSubPic->privContext;
+ sAPriv = SAREAPTR( pViaXvMC );
+ if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] ==
+ (pViaSubPic->srfNo | VIA_XVMC_VALID))
+ *stat |= XVMC_DISPLAYING;
+ }
+ return Success;
+}
+
+Status
+XvMCFlushSurface (Display *display, XvMCSurface *surface)
+{
+ ViaXvMCSurface *pViaSurface;
+ ViaXvMCContext *pViaXvMC;
+ Status ret;
+
+ if((display == NULL) || surface == NULL){
+ return BadValue;
+ }
+ if(NULL == (pViaSurface = surface->privData)) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ pViaXvMC = pViaSurface->privContext;
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ if (pViaSurface->needsSync)
+ pViaSurface->timeStamp = pViaXvMC->timeStamp =
+ viaDMATimeStampLowLevel(pViaXvMC->xl);
+ ret = (flushXvMCLowLevel(pViaXvMC->xl)) ? BadValue : Success;
+ if (pViaXvMC->rendSurf[0] == (pViaSurface->srfNo | VIA_XVMC_VALID)) {
+ hwlLock(pViaXvMC->xl,0);
+ pViaXvMC->haveDecoder = 0;
+ releaseDecoder(pViaXvMC, 0);
+ hwlUnlock(pViaXvMC->xl,0);
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return ret;
+}
+
+Status
+XvMCGetSurfaceStatus (Display *display, XvMCSurface *surface, int *stat)
+{
+ ViaXvMCSurface *pViaSurface;
+ ViaXvMCContext *pViaXvMC;
+ volatile ViaXvMCSAreaPriv *sAPriv;
+ unsigned i;
+ int ret = 0;
+
+ if((display == NULL) || surface == NULL){
+ return BadValue;
+ }
+ if(NULL == (pViaSurface = surface->privData)) {
+ return (error_base + XvMCBadSurface);
+ }
+ if (stat) {
+ *stat = 0;
+ pViaXvMC = pViaSurface->privContext;
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ sAPriv = SAREAPTR( pViaXvMC );
+ if (sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort]
+ == (pViaSurface->srfNo | VIA_XVMC_VALID))
+ *stat |= XVMC_DISPLAYING;
+ for (i=0; i<VIA_MAX_RENDSURF; ++i) {
+ if(pViaXvMC->rendSurf[i] ==
+ (pViaSurface->srfNo | VIA_XVMC_VALID)) {
+ *stat |= XVMC_RENDERING;
+ break;
+ }
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ }
+ return ret;
+}
+
+XvAttribute *
+XvMCQueryAttributes (
+ Display *display,
+ XvMCContext *context,
+ int *number
+ )
+{
+ ViaXvMCContext *pViaXvMC;
+ XvAttribute *ret;
+ unsigned long siz;
+
+ *number = 0;
+ if ((display == NULL) || (context == NULL)) {
+ return NULL;
+ }
+
+ if (NULL == (pViaXvMC = context->privData)) {
+ return NULL;
+ }
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ if (NULL != (ret = (XvAttribute *)
+ malloc(siz = VIA_NUM_XVMC_ATTRIBUTES*sizeof(XvAttribute)))) {
+ memcpy(ret,pViaXvMC->attribDesc,siz);
+ *number = VIA_NUM_XVMC_ATTRIBUTES;
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+
+ return ret;
+}
+
+Status
+XvMCSetAttribute (
+ Display *display,
+ XvMCContext *context,
+ Atom attribute,
+ int value
+ )
+{
+ int found;
+ unsigned i;
+ ViaXvMCContext *pViaXvMC;
+ ViaXvMCCommandBuffer buf;
+
+ if ((display == NULL) || (context == NULL)) {
+ return (error_base + XvMCBadContext);
+ }
+
+ if (NULL == (pViaXvMC = context->privData)) {
+ return (error_base + XvMCBadContext);
+ }
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+
+ found = 0;
+ for (i=0; i < pViaXvMC->attrib.numAttr; ++i) {
+ if (attribute == pViaXvMC->attrib.attributes[i].attribute) {
+ if ((!(pViaXvMC->attribDesc[i].flags & XvSettable)) ||
+ value < pViaXvMC->attribDesc[i].min_value ||
+ value > pViaXvMC->attribDesc[i].max_value)
+ return BadValue;
+ pViaXvMC->attrib.attributes[i].value = value;
+ found = 1;
+ pViaXvMC->attribChanged = 1;
+ break;
+ }
+ }
+ if (!found) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return BadMatch;
+ }
+ if (pViaXvMC->haveXv) {
+ buf.command = VIA_XVMC_COMMAND_ATTRIBUTES;
+ pViaXvMC->xvImage->data = (char *)&buf;
+ buf.ctxNo = pViaXvMC->ctxNo | VIA_XVMC_VALID;
+ buf.attrib = pViaXvMC->attrib;
+ XLockDisplay(display);
+ pViaXvMC->attribChanged =
+ XvPutImage(display,pViaXvMC->port,pViaXvMC->draw,
+ pViaXvMC->gc,
+ pViaXvMC->xvImage,0,0,1,1,0,0,1,1);
+ XUnlockDisplay(display);
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
+
+
+Status
+XvMCGetAttribute (
+ Display *display,
+ XvMCContext *context,
+ Atom attribute,
+ int *value
+ )
+{
+ int found;
+ unsigned i;
+ ViaXvMCContext *pViaXvMC;
+
+ if ((display == NULL) || (context == NULL)) {
+ return (error_base + XvMCBadContext);
+ }
+
+ if (NULL == (pViaXvMC = context->privData)) {
+ return (error_base + XvMCBadContext);
+ }
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ found = 0;
+ for (i=0; i < pViaXvMC->attrib.numAttr; ++i) {
+ if (attribute == pViaXvMC->attrib.attributes[i].attribute) {
+ if (pViaXvMC->attribDesc[i].flags & XvGettable) {
+ *value = pViaXvMC->attrib.attributes[i].value;
+ found = 1;
+ break;
+ }
+ }
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+
+ if (!found)
+ return BadMatch;
+ return Success;
+}
+
+
+Status XvMCHideSurface(Display *display,XvMCSurface *surface)
+{
+
+ ViaXvMCSurface *pViaSurface;
+ ViaXvMCContext *pViaXvMC;
+ ViaXvMCSubPicture *pViaSubPic;
+ volatile ViaXvMCSAreaPriv *sAPriv;
+ ViaXvMCCommandBuffer buf;
+ Status ret;
+
+ if ((display == NULL) || (surface == NULL)) {
+ return BadValue;
+ }
+ if (NULL == (pViaSurface = surface->privData )) {
+ return (error_base + XvMCBadSurface);
+ }
+ if (NULL == (pViaXvMC = pViaSurface->privContext)) {
+ return (error_base + XvMCBadContext);
+ }
+
+ ppthread_mutex_lock( &pViaXvMC->ctxMutex );
+ if (!pViaXvMC->haveXv) {
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+ }
+
+ sAPriv = SAREAPTR( pViaXvMC );
+ hwlLock(pViaXvMC->xl,1);
+
+ if (sAPriv->XvMCDisplaying[pViaXvMC->xvMCPort] !=
+ (pViaSurface->srfNo | VIA_XVMC_VALID)) {
+ hwlUnlock(pViaXvMC->xl,1);
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+ }
+ setLowLevelLocking(pViaXvMC->xl,0);
+ if (NULL != (pViaSubPic = pViaSurface->privSubPic)) {
+ if (sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] ==
+ (pViaSubPic->srfNo | VIA_XVMC_VALID)) {
+ sAPriv->XvMCSubPicOn[pViaXvMC->xvMCPort] &= ~VIA_XVMC_VALID;
+ viaVideoSubPictureOffLocked(pViaXvMC->xl);
+ }
+ }
+ flushPCIXvMCLowLevel(pViaXvMC->xl);
+ setLowLevelLocking(pViaXvMC->xl,1);
+ hwlUnlock(pViaXvMC->xl,1);
+
+ buf.command = VIA_XVMC_COMMAND_UNDISPLAY;
+ buf.ctxNo = pViaXvMC->ctxNo | VIA_XVMC_VALID;
+ buf.srfNo = pViaSurface->srfNo | VIA_XVMC_VALID;
+ pViaXvMC->xvImage->data = (char *)&buf;
+ if ((ret = XvPutImage(display,pViaXvMC->port,pViaXvMC->draw,
+ pViaXvMC->gc,
+ pViaXvMC->xvImage,0,0,1,1,0,0,1,1))) {
+ fprintf(stderr,"XvMCPutSurface: Hiding overlay failed.\n");
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return ret;
+ }
+ ppthread_mutex_unlock( &pViaXvMC->ctxMutex );
+ return Success;
+}
diff --git a/nx-X11/lib/XvMC/hw/via/viaXvMCPriv.h b/nx-X11/lib/XvMC/hw/via/viaXvMCPriv.h
new file mode 100644
index 000000000..de4976a25
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/viaXvMCPriv.h
@@ -0,0 +1,198 @@
+/*****************************************************************************
+ * VIA Unichrome XvMC extension client lib.
+ *
+ * Copyright (c) 2004 Thomas Hellström. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _VIAXVMCPRIV_H
+#define _VIAXVMCPRIV_H 1
+
+#include <X11/Xlibint.h>
+#include <X11/extensions/XvMC.h>
+#include <X11/extensions/XvMClib.h>
+#include <stdlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/vldXvMC.h>
+#include "via_xvmc.h"
+
+typedef struct{
+ int x;
+ int y;
+ int w;
+ int h;
+} XvMCRegion;
+
+
+extern Status _xvmc_create_context(Display *dpy, XvMCContext *context,
+ int *priv_count, uint **priv_data);
+extern Status _xvmc_destroy_context(Display *dpy, XvMCContext *context);
+extern Status _xvmc_create_surface(Display *dpy, XvMCContext *context,
+ XvMCSurface *surface, int *priv_count,
+ uint **priv_data);
+extern Status _xvmc_destroy_surface(Display *dpy, XvMCSurface *surface);
+extern Status _xvmc_create_subpicture(Display *dpy, XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ int *priv_count, uint **priv_data);
+extern Status _xvmc_destroy_subpicture(Display *dpy,
+ XvMCSubpicture *subpicture);
+
+#define VIA_SUBPIC_PALETTE_SIZE 16 /*Number of colors in subpicture palette*/
+#define VIA_CBUFFERSIZE 4096 /*Hardware command buffer size*/
+#define VIA_MAX_BUFS 2 /*Number of YUV buffers per surface*/
+#define VIA_MAX_RENDSURF 3 /*Maximum numbers of surfaces per context
+ that can answer RENDERING to a rendering
+ query*/
+
+typedef enum{
+ context_drawHash,
+ context_lowLevel,
+ context_mutex,
+ context_sAreaMap,
+ context_fbMap,
+ context_mmioMap,
+ context_drmContext,
+ context_fd,
+ context_driConnection,
+ context_context,
+ context_none
+} ContextRes;
+
+
+typedef struct{
+ unsigned ctxNo; /* XvMC private context reference number */
+ pthread_mutex_t ctxMutex; /* Mutex for multi-threading. Not used */
+ drm_context_t drmcontext; /* The drm context */
+ drm_handle_t fbOffset; /* Handle to drm frame-buffer area */
+ drm_handle_t mmioOffset; /* Handle to drm mmio area */
+ drm_handle_t sAreaOffset; /* Handle to drm shared memory area */
+ unsigned fbSize; /* Size of drm frame-buffer area */
+ unsigned mmioSize; /* Size of drm mmio area */
+ unsigned sAreaSize; /* Size of drm shared memory area */
+ unsigned sAreaPrivOffset; /* Offset in sarea to private part */
+ drmAddress fbAddress; /* Virtual address of frame buffer area */
+ drmAddress mmioAddress; /* Virtual address of mmio area */
+ drmAddress sAreaAddress; /* Virtual address of shared memory area */
+ char busIdString[21]; /* Busid of video card */
+ unsigned yStride; /* Y stride of surfaces in this context */
+ int fd; /* FD for connection to drm module */
+ unsigned char intra_quantiser_matrix[64];
+ unsigned char non_intra_quantiser_matrix[64];
+ unsigned char chroma_intra_quantiser_matrix[64];
+ unsigned char chroma_non_intra_quantiser_matrix[64];
+ unsigned rendSurf[VIA_MAX_RENDSURF]; /* Which surfaces answer rendering to
+ a rendering query */
+ int decoderOn; /* Decoder switched on ? */
+ int intraLoaded; /* Intra quantiser matrix loaded in
+ decoder? */
+ int nonIntraLoaded; /* Non-Intra quantiser matrix loaded
+ in decoder */
+ int chromaIntraLoaded;
+ int chromaNonIntraLoaded;
+ int haveDecoder; /* Does this context own decoder? */
+ int attribChanged; /* Attributes have changed and need to
+ be uploaded to Xv at next frame
+ display */
+ drmLockPtr hwLock; /* Virtual address Pointer to the
+ heavyweight drm hardware lock */
+ unsigned xvMCPort; /* XvMC private port. Corresponds to
+ an Xv port, but not by number */
+ ViaXvMCAttrHolder attrib; /* This contexts attributes and their
+ values */
+ XvAttribute attribDesc[VIA_NUM_XVMC_ATTRIBUTES]; /* Attribute decriptions */
+ int useAGP; /* Use the AGP ringbuffer to upload data to the chip */
+ void *xl; /* Lowlevel context. Opaque to us. */
+ int haveXv; /* Have I initialized the Xv
+ connection for this surface? */
+ XvImage *xvImage; /* Fake Xv Image used for command
+ buffer transport to the X server */
+ GC gc; /* X GC needed for displaying */
+ Drawable draw; /* Drawable to undisplay from */
+ XvPortID port; /* Xv Port ID when displaying */
+ int lastSrfDisplaying;
+ ContextRes resources;
+ CARD32 timeStamp;
+ CARD32 videoTimeStamp;
+ XID id;
+ unsigned screen;
+ unsigned depth;
+ unsigned stride;
+ XVisualInfo visualInfo;
+ void *drawHash;
+ CARD32 chipId;
+ XvMCRegion sRegion;
+ XvMCRegion dRegion;
+}ViaXvMCContext;
+
+typedef struct{
+ pthread_mutex_t subMutex; /* Currently not used. */
+ unsigned srfNo; /* XvMC private surface number */
+ unsigned offset; /* Offset into frame-buffer area */
+ unsigned stride; /* Storage stride */
+ unsigned width; /* Width */
+ unsigned height; /* Height */
+ CARD32 palette[VIA_SUBPIC_PALETTE_SIZE]; /* YUV Palette */
+ ViaXvMCContext *privContext; /* Pointer to context private data */
+ int ia44; /* IA44 or AI44 format */
+ int needsSync;
+ CARD32 timeStamp;
+}ViaXvMCSubPicture;
+
+
+typedef struct{
+ pthread_mutex_t srfMutex; /* For multithreading. Not used. */
+ pthread_cond_t bufferAvailable; /* For multithreading. Not used. */
+ unsigned srfNo; /* XvMC private surface numbers */
+ unsigned numBuffers; /* Number of picture buffers */
+ unsigned curBuf; /* Which is the current buffer? */
+ unsigned offsets[VIA_MAX_BUFS]; /* Offsets of picture buffers
+ into the frame-buffer area */
+ unsigned yStride; /* Stride of YUV420 Y component. */
+ unsigned width; /* Dimensions */
+ unsigned height;
+ int progressiveSequence; /* Mpeg progressive picture? Hmm? */
+ ViaXvMCContext *privContext; /* XvMC context private part. */
+ ViaXvMCSubPicture *privSubPic; /* Subpicture to be blended when
+ displaying. NULL if none. */
+ int needsSync;
+ int syncMode;
+ CARD32 timeStamp;
+ int topFieldFirst;
+}ViaXvMCSurface;
+
+/*
+ * Take and release the global drm hardware lock.
+ */
+
+#define HW_LOCK(ctx) \
+ DRM_LOCK((ctx)->fd,(ctx)->hwLock,(ctx)->drmcontext,0)
+#define HW_UNLOCK(ctx) \
+ DRM_UNLOCK((ctx)->fd,(ctx->hwLock),(ctx)->drmcontext)
+
+/*
+ * Low-level Mpeg functions in viaLowLevel.c
+ */
+
+#define VIABLIT_TRANSCOPY 0
+#define VIABLIT_COPY 1
+#define VIABLIT_FILL 2
+
+
+#endif
diff --git a/nx-X11/lib/XvMC/hw/via/xf86dri.c b/nx-X11/lib/XvMC/hw/via/xf86dri.c
new file mode 100644
index 000000000..dd1d1e072
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/xf86dri.c
@@ -0,0 +1,592 @@
+/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+/* #include "glheader.h" */
+#include "xf86dristr.h"
+
+static XExtensionInfo _xf86dri_info_data;
+static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
+static char xf86dri_extension_name[] = XF86DRINAME;
+
+#define uniDRICheckExtension(dpy,i,val) \
+ XextCheckExtension (dpy, i, xf86dri_extension_name, val)
+
+/*****************************************************************************
+ * *
+ * private utility routines *
+ * *
+ *****************************************************************************/
+
+static int close_display(Display *dpy, XExtCodes *extCodes);
+static /* const */ XExtensionHooks xf86dri_extension_hooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ close_display, /* close_display */
+ NULL, /* wire_to_event */
+ NULL, /* event_to_wire */
+ NULL, /* error */
+ NULL, /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info,
+ xf86dri_extension_name,
+ &xf86dri_extension_hooks,
+ 0, NULL)
+
+static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info)
+
+
+/*****************************************************************************
+ * *
+ * public XFree86-DRI Extension routines *
+ * *
+ *****************************************************************************/
+
+#if 0
+#include <stdio.h>
+#define TRACE(msg) fprintf(stderr,"uniDRI%s\n", msg);
+#else
+#define TRACE(msg)
+#endif
+
+
+ Bool uniDRIQueryExtension (dpy, event_basep, error_basep)
+ Display *dpy;
+ int *event_basep, *error_basep;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+
+ TRACE("QueryExtension...");
+ if (XextHasExtension(info)) {
+ *event_basep = info->codes->first_event;
+ *error_basep = info->codes->first_error;
+ TRACE("QueryExtension... return True");
+ return True;
+ } else {
+ TRACE("QueryExtension... return False");
+ return False;
+ }
+}
+
+ Bool uniDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
+ Display* dpy;
+ int* majorVersion;
+ int* minorVersion;
+ int* patchVersion;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIQueryVersionReply rep;
+ xXF86DRIQueryVersionReq *req;
+
+ TRACE("QueryVersion...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryVersion, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryVersion;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return False");
+ return False;
+ }
+ *majorVersion = rep.majorVersion;
+ *minorVersion = rep.minorVersion;
+ *patchVersion = rep.patchVersion;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return True");
+ return True;
+}
+
+ Bool uniDRIQueryDirectRenderingCapable(dpy, screen, isCapable)
+ Display* dpy;
+ int screen;
+ Bool* isCapable;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIQueryDirectRenderingCapableReply rep;
+ xXF86DRIQueryDirectRenderingCapableReq *req;
+
+ TRACE("QueryDirectRenderingCapable...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryDirectRenderingCapable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return False");
+ return False;
+ }
+ *isCapable = rep.isCapable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return True");
+ return True;
+}
+
+ Bool uniDRIOpenConnection(dpy, screen, hSAREA, busIdString)
+ Display* dpy;
+ int screen;
+ drm_handle_t * hSAREA;
+ char **busIdString;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIOpenConnectionReply rep;
+ xXF86DRIOpenConnectionReq *req;
+
+ TRACE("OpenConnection...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIOpenConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIOpenConnection;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+
+ *hSAREA = rep.hSAREALow;
+#ifdef LONG64
+ *hSAREA |= ((drm_handle_t)rep.hSAREAHigh) << 32;
+#endif
+
+ if (rep.length) {
+ if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
+ _XEatData(dpy, ((rep.busIdStringLength+3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+ _XReadPad(dpy, *busIdString, rep.busIdStringLength);
+ } else {
+ *busIdString = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return True");
+ return True;
+}
+
+ Bool uniDRIAuthConnection(dpy, screen, magic)
+ Display* dpy;
+ int screen;
+ drm_magic_t magic;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIAuthConnectionReq *req;
+ xXF86DRIAuthConnectionReply rep;
+
+ TRACE("AuthConnection...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIAuthConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIAuthConnection;
+ req->screen = screen;
+ req->magic = magic;
+ rep.authenticated = 0;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return False");
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return True");
+ return True;
+}
+
+ Bool uniDRICloseConnection(dpy, screen)
+ Display* dpy;
+ int screen;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRICloseConnectionReq *req;
+
+ TRACE("CloseConnection...");
+
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICloseConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICloseConnection;
+ req->screen = screen;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CloseConnection... return True");
+ return True;
+}
+
+ Bool uniDRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion,
+ ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
+ Display* dpy;
+ int screen;
+ int* ddxDriverMajorVersion;
+ int* ddxDriverMinorVersion;
+ int* ddxDriverPatchVersion;
+ char** clientDriverName;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIGetClientDriverNameReply rep;
+ xXF86DRIGetClientDriverNameReq *req;
+
+ TRACE("GetClientDriverName...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetClientDriverName, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetClientDriverName;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+
+ *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
+ *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
+ *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
+
+ if (rep.length) {
+ if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
+ _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+ _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
+ } else {
+ *clientDriverName = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return True");
+ return True;
+}
+
+ Bool uniDRICreateContextWithConfig(dpy, screen, configID, context,
+ hHWContext)
+ Display* dpy;
+ int screen;
+ int configID;
+ XID* context;
+ drm_context_t * hHWContext;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRICreateContextReply rep;
+ xXF86DRICreateContextReq *req;
+
+ TRACE("CreateContext...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateContext;
+ req->visual = configID;
+ req->screen = screen;
+ *context = XAllocID(dpy);
+ req->context = *context;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return False");
+ return False;
+ }
+ *hHWContext = rep.hHWContext;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return True");
+ return True;
+}
+
+ Bool uniDRICreateContext(dpy, screen, visual, context, hHWContext)
+ Display* dpy;
+ int screen;
+ Visual* visual;
+ XID* context;
+ drm_context_t * hHWContext;
+{
+ return uniDRICreateContextWithConfig( dpy, screen, visual->visualid,
+ context, hHWContext );
+}
+
+ Bool uniDRIDestroyContext( Display * ndpy, int screen,
+ XID context )
+{
+ Display * const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIDestroyContextReq *req;
+
+ TRACE("DestroyContext...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyContext;
+ req->screen = screen;
+ req->context = context;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyContext... return True");
+ return True;
+}
+
+Bool uniDRICreateDrawable( Display * ndpy, int screen,
+ Drawable drawable, drm_drawable_t * hHWDrawable )
+{
+ Display * const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRICreateDrawableReply rep;
+ xXF86DRICreateDrawableReq *req;
+
+ TRACE("CreateDrawable...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return False");
+ return False;
+ }
+ *hHWDrawable = rep.hHWDrawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return True");
+ return True;
+}
+
+Bool uniDRIDestroyDrawable( Display * ndpy, int screen,
+ Drawable drawable )
+{
+ Display * const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIDestroyDrawableReq *req;
+
+ TRACE("DestroyDrawable...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyDrawable... return True");
+ return True;
+}
+
+ Bool uniDRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
+ unsigned int* index, unsigned int* stamp,
+ int* X, int* Y, int* W, int* H,
+ int* numClipRects, drm_clip_rect_t ** pClipRects,
+ int* backX, int* backY,
+ int* numBackClipRects, drm_clip_rect_t ** pBackClipRects )
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIGetDrawableInfoReply rep;
+ xXF86DRIGetDrawableInfoReq *req;
+ int total_rects;
+
+ TRACE("GetDrawableInfo...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDrawableInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDrawableInfo;
+ req->screen = screen;
+ req->drawable = drawable;
+
+ if (!_XReply(dpy, (xReply *)&rep, 1, xFalse))
+ {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+ *index = rep.drawableTableIndex;
+ *stamp = rep.drawableTableStamp;
+ *X = (int)rep.drawableX;
+ *Y = (int)rep.drawableY;
+ *W = (int)rep.drawableWidth;
+ *H = (int)rep.drawableHeight;
+ *numClipRects = rep.numClipRects;
+ total_rects = *numClipRects;
+
+ *backX = rep.backX;
+ *backY = rep.backY;
+ *numBackClipRects = rep.numBackClipRects;
+ total_rects += *numBackClipRects;
+
+#if 0
+ /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
+ * backwards compatibility (Because of the >> 2 shift) but the fix
+ * enables multi-threaded apps to work.
+ */
+ if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
+ SIZEOF(xGenericReply) +
+ total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) {
+ _XEatData(dpy, rep.length);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+#endif
+
+ if (*numClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numClipRects);
+
+ *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
+ if (*pClipRects)
+ _XRead(dpy, (char*)*pClipRects, len);
+ } else {
+ *pClipRects = NULL;
+ }
+
+ if (*numBackClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
+
+ *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
+ if (*pBackClipRects)
+ _XRead(dpy, (char*)*pBackClipRects, len);
+ } else {
+ *pBackClipRects = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return True");
+ return True;
+}
+
+ Bool uniDRIGetDeviceInfo(dpy, screen, hFrameBuffer,
+ fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
+ Display* dpy;
+ int screen;
+ drm_handle_t * hFrameBuffer;
+ int* fbOrigin;
+ int* fbSize;
+ int* fbStride;
+ int* devPrivateSize;
+ void** pDevPrivate;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIGetDeviceInfoReply rep;
+ xXF86DRIGetDeviceInfoReq *req;
+
+ TRACE("GetDeviceInfo...");
+ uniDRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDeviceInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDeviceInfo;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+
+ *hFrameBuffer = rep.hFrameBufferLow;
+#ifdef LONG64
+ *hFrameBuffer |= ((drm_handle_t)rep.hFrameBufferHigh) << 32;
+#endif
+
+ *fbOrigin = rep.framebufferOrigin;
+ *fbSize = rep.framebufferSize;
+ *fbStride = rep.framebufferStride;
+ *devPrivateSize = rep.devPrivateSize;
+
+ if (rep.length) {
+ if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
+ _XEatData(dpy, ((rep.devPrivateSize+3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+ _XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize);
+ } else {
+ *pDevPrivate = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return True");
+ return True;
+}
+
diff --git a/nx-X11/lib/XvMC/hw/via/xf86dri.h b/nx-X11/lib/XvMC/hw/via/xf86dri.h
new file mode 100644
index 000000000..f82b573fe
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/xf86dri.h
@@ -0,0 +1,121 @@
+/* $XFree86: xc/lib/GL/dri/xf86dri.h,v 1.8 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/**
+ * \file xf86dri.h
+ * Protocol numbers and function prototypes for DRI X protocol.
+ *
+ * \author Kevin E. Martin <martin@valinux.com>
+ * \author Jens Owen <jens@tungstengraphics.com>
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+#ifndef _XF86DRI_H_
+#define _XF86DRI_H_
+
+#include <X11/Xfuncproto.h>
+#include <xf86drm.h>
+
+#define X_XF86DRIQueryVersion 0
+#define X_XF86DRIQueryDirectRenderingCapable 1
+#define X_XF86DRIOpenConnection 2
+#define X_XF86DRICloseConnection 3
+#define X_XF86DRIGetClientDriverName 4
+#define X_XF86DRICreateContext 5
+#define X_XF86DRIDestroyContext 6
+#define X_XF86DRICreateDrawable 7
+#define X_XF86DRIDestroyDrawable 8
+#define X_XF86DRIGetDrawableInfo 9
+#define X_XF86DRIGetDeviceInfo 10
+#define X_XF86DRIAuthConnection 11
+#define X_XF86DRIOpenFullScreen 12 /* Deprecated */
+#define X_XF86DRICloseFullScreen 13 /* Deprecated */
+
+#define XF86DRINumberEvents 0
+
+#define XF86DRIClientNotLocal 0
+#define XF86DRIOperationNotSupported 1
+#define XF86DRINumberErrors (XF86DRIOperationNotSupported + 1)
+
+#ifndef _XF86DRI_SERVER_
+
+
+_XFUNCPROTOBEGIN
+
+Bool uniDRIQueryExtension( Display *dpy, int *event_base, int *error_base );
+
+Bool uniDRIQueryVersion( Display *dpy, int *majorVersion, int *minorVersion,
+ int *patchVersion );
+
+Bool uniDRIQueryDirectRenderingCapable( Display *dpy, int screen,
+ Bool *isCapable );
+
+Bool uniDRIOpenConnection( Display *dpy, int screen, drm_handle_t *hSAREA,
+ char **busIDString );
+
+Bool uniDRIAuthConnection( Display *dpy, int screen, drm_magic_t magic );
+
+Bool uniDRICloseConnection( Display *dpy, int screen );
+
+Bool uniDRIGetClientDriverName( Display *dpy, int screen,
+ int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
+ int *ddxDriverPatchVersion, char **clientDriverName );
+
+Bool uniDRICreateContext( Display *dpy, int screen, Visual *visual,
+ XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
+
+Bool uniDRICreateContextWithConfig( Display *dpy, int screen, int configID,
+ XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
+
+extern Bool uniDRIDestroyContext( Display *dpy, int screen,
+ XID context_id );
+
+extern Bool uniDRICreateDrawable( Display *dpy, int screen,
+ Drawable drawable, drm_drawable_t *hHWDrawable );
+
+extern Bool uniDRIDestroyDrawable( Display *dpy, int screen,
+ Drawable drawable);
+
+Bool uniDRIGetDrawableInfo( Display *dpy, int screen, Drawable drawable,
+ unsigned int *index, unsigned int *stamp,
+ int *X, int *Y, int *W, int *H,
+ int *numClipRects, drm_clip_rect_t ** pClipRects,
+ int *backX, int *backY,
+ int *numBackClipRects, drm_clip_rect_t **pBackClipRects );
+
+Bool uniDRIGetDeviceInfo( Display *dpy, int screen,
+ drm_handle_t *hFrameBuffer, int *fbOrigin, int *fbSize,
+ int *fbStride, int *devPrivateSize, void **pDevPrivate );
+
+_XFUNCPROTOEND
+
+#endif /* _XF86DRI_SERVER_ */
+
+#endif /* _XF86DRI_H_ */
+
diff --git a/nx-X11/lib/XvMC/hw/via/xf86dristr.h b/nx-X11/lib/XvMC/hw/via/xf86dristr.h
new file mode 100644
index 000000000..ac05b183b
--- /dev/null
+++ b/nx-X11/lib/XvMC/hw/via/xf86dristr.h
@@ -0,0 +1,343 @@
+/* $XFree86: xc/lib/GL/dri/xf86dristr.h,v 1.10 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Fiath <faith@valinux.com>
+ *
+ */
+
+#ifndef _XF86DRISTR_H_
+#define _XF86DRISTR_H_
+
+#include "xf86dri.h"
+
+#define XF86DRINAME "XFree86-DRI"
+
+/* The DRI version number. This was originally set to be the same of the
+ * XFree86 version number. However, this version is really indepedent of
+ * the XFree86 version.
+ *
+ * Version History:
+ * 4.0.0: Original
+ * 4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02
+ * 4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02
+ */
+#define XF86DRI_MAJOR_VERSION 4
+#define XF86DRI_MINOR_VERSION 1
+#define XF86DRI_PATCH_VERSION 0
+
+typedef struct _XF86DRIQueryVersion {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIQueryVersion */
+ CARD16 length B16;
+} xXF86DRIQueryVersionReq;
+#define sz_xXF86DRIQueryVersionReq 4
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 majorVersion B16; /* major version of DRI protocol */
+ CARD16 minorVersion B16; /* minor version of DRI protocol */
+ CARD32 patchVersion B32; /* patch version of DRI protocol */
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIQueryVersionReply;
+#define sz_xXF86DRIQueryVersionReply 32
+
+typedef struct _XF86DRIQueryDirectRenderingCapable {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIQueryDirectRenderingCapableReq;
+#define sz_xXF86DRIQueryDirectRenderingCapableReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ BOOL isCapable;
+ BOOL pad2;
+ BOOL pad3;
+ BOOL pad4;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+ CARD32 pad9 B32;
+} xXF86DRIQueryDirectRenderingCapableReply;
+#define sz_xXF86DRIQueryDirectRenderingCapableReply 32
+
+typedef struct _XF86DRIOpenConnection {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIOpenConnectionReq;
+#define sz_xXF86DRIOpenConnectionReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hSAREALow B32;
+ CARD32 hSAREAHigh B32;
+ CARD32 busIdStringLength B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+} xXF86DRIOpenConnectionReply;
+#define sz_xXF86DRIOpenConnectionReply 32
+
+typedef struct _XF86DRIAuthConnection {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 magic B32;
+} xXF86DRIAuthConnectionReq;
+#define sz_xXF86DRIAuthConnectionReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 authenticated B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIAuthConnectionReply;
+#define zx_xXF86DRIAuthConnectionReply 32
+
+typedef struct _XF86DRICloseConnection {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRICloseConnectionReq;
+#define sz_xXF86DRICloseConnectionReq 8
+
+typedef struct _XF86DRIGetClientDriverName {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetClientDriverName */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetClientDriverNameReq;
+#define sz_xXF86DRIGetClientDriverNameReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 ddxDriverMajorVersion B32;
+ CARD32 ddxDriverMinorVersion B32;
+ CARD32 ddxDriverPatchVersion B32;
+ CARD32 clientDriverNameLength B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIGetClientDriverNameReply;
+#define sz_xXF86DRIGetClientDriverNameReply 32
+
+typedef struct _XF86DRICreateContext {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 visual B32;
+ CARD32 context B32;
+} xXF86DRICreateContextReq;
+#define sz_xXF86DRICreateContextReq 16
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWContext B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateContextReply;
+#define sz_xXF86DRICreateContextReply 32
+
+typedef struct _XF86DRIDestroyContext {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 context B32;
+} xXF86DRIDestroyContextReq;
+#define sz_xXF86DRIDestroyContextReq 12
+
+typedef struct _XF86DRICreateDrawable {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICreateDrawableReq;
+#define sz_xXF86DRICreateDrawableReq 12
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWDrawable B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateDrawableReply;
+#define sz_xXF86DRICreateDrawableReply 32
+
+typedef struct _XF86DRIDestroyDrawable {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIDestroyDrawableReq;
+#define sz_xXF86DRIDestroyDrawableReq 12
+
+typedef struct _XF86DRIGetDrawableInfo {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDrawableInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIGetDrawableInfoReq;
+#define sz_xXF86DRIGetDrawableInfoReq 12
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 drawableTableIndex B32;
+ CARD32 drawableTableStamp B32;
+ INT16 drawableX B16;
+ INT16 drawableY B16;
+ INT16 drawableWidth B16;
+ INT16 drawableHeight B16;
+ CARD32 numClipRects B32;
+ INT16 backX B16;
+ INT16 backY B16;
+ CARD32 numBackClipRects B32;
+} xXF86DRIGetDrawableInfoReply;
+
+#define sz_xXF86DRIGetDrawableInfoReply 36
+
+
+typedef struct _XF86DRIGetDeviceInfo {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDeviceInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetDeviceInfoReq;
+#define sz_xXF86DRIGetDeviceInfoReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hFrameBufferLow B32;
+ CARD32 hFrameBufferHigh B32;
+ CARD32 framebufferOrigin B32;
+ CARD32 framebufferSize B32;
+ CARD32 framebufferStride B32;
+ CARD32 devPrivateSize B32;
+} xXF86DRIGetDeviceInfoReply;
+#define sz_xXF86DRIGetDeviceInfoReply 32
+
+typedef struct _XF86DRIOpenFullScreen {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIOpenFullScreenReq;
+#define sz_xXF86DRIOpenFullScreenReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 isFullScreen B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIOpenFullScreenReply;
+#define sz_xXF86DRIOpenFullScreenReply 32
+
+typedef struct _XF86DRICloseFullScreen {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICloseFullScreenReq;
+#define sz_xXF86DRICloseFullScreenReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xXF86DRICloseFullScreenReply;
+#define sz_xXF86DRICloseFullScreenReply 32
+
+
+#endif /* _XF86DRISTR_H_ */