diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/XvMC/hw | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-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.c | 4507 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/i810/I810XvMC.h | 469 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/i810/Imakefile | 44 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/driDrawable.c | 176 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/driDrawable.h | 64 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/unichrome/Imakefile | 51 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/unichrome/viaLowLevel.c | 1056 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/unichromeProA/Imakefile | 50 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/unichromeProA/viaLowLevelPro.c | 1465 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/viaLowLevel.h | 148 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/viaXvMC.c | 1964 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/viaXvMCPriv.h | 198 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/xf86dri.c | 592 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/xf86dri.h | 121 | ||||
-rw-r--r-- | nx-X11/lib/XvMC/hw/via/xf86dristr.h | 343 |
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 = ¯oblock_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_ */ |