1428d7b3dSmrg/***************************************************************************
2428d7b3dSmrg
3428d7b3dSmrgCopyright 2001 Intel Corporation.  All Rights Reserved.
4428d7b3dSmrg
5428d7b3dSmrgPermission is hereby granted, free of charge, to any person obtaining a
6428d7b3dSmrgcopy of this software and associated documentation files (the
7428d7b3dSmrg"Software"), to deal in the Software without restriction, including
8428d7b3dSmrgwithout limitation the rights to use, copy, modify, merge, publish,
9428d7b3dSmrgdistribute, sub license, and/or sell copies of the Software, and to
10428d7b3dSmrgpermit persons to whom the Software is furnished to do so, subject to
11428d7b3dSmrgthe following conditions:
12428d7b3dSmrg
13428d7b3dSmrgThe above copyright notice and this permission notice (including the
14428d7b3dSmrgnext paragraph) shall be included in all copies or substantial portions
15428d7b3dSmrgof the Software.
16428d7b3dSmrg
17428d7b3dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18428d7b3dSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19428d7b3dSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20428d7b3dSmrgIN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
21428d7b3dSmrgDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22428d7b3dSmrgOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
23428d7b3dSmrgTHE USE OR OTHER DEALINGS IN THE SOFTWARE.
24428d7b3dSmrg
25428d7b3dSmrg**************************************************************************/
26428d7b3dSmrg
27428d7b3dSmrg/*************************************************************************
28428d7b3dSmrg** File libI810XvMC.c
29428d7b3dSmrg**
30428d7b3dSmrg** Authors:
31428d7b3dSmrg**      Matt Sottek <matthew.j.sottek@intel.com>
32428d7b3dSmrg**      Bob Paauwe  <bob.j.paauwe@intel.com>
33428d7b3dSmrg**
34428d7b3dSmrg**
35428d7b3dSmrg***************************************************************************/
36428d7b3dSmrg#include <stdio.h>
37428d7b3dSmrg#include <stdlib.h>
38428d7b3dSmrg#include <unistd.h>
39428d7b3dSmrg#include <errno.h>
40428d7b3dSmrg#include <signal.h>
41428d7b3dSmrg#include <fcntl.h>
42428d7b3dSmrg#include <dirent.h>
43428d7b3dSmrg#include <string.h>
44428d7b3dSmrg
45428d7b3dSmrg#include <sys/ioctl.h>
46428d7b3dSmrg#include <X11/Xlibint.h>
47428d7b3dSmrg#include <fourcc.h>
48428d7b3dSmrg#include <X11/extensions/Xv.h>
49428d7b3dSmrg#include <X11/extensions/Xvlib.h>
50428d7b3dSmrg#include <X11/extensions/XvMC.h>
51428d7b3dSmrg#include <X11/extensions/XvMClib.h>
52428d7b3dSmrg#include "I810XvMC.h"
53428d7b3dSmrg
54428d7b3dSmrgstatic int error_base;
55428d7b3dSmrgstatic int event_base;
56428d7b3dSmrg
57428d7b3dSmrg/***************************************************************************
58428d7b3dSmrg// Function: i810_get_free_buffer
59428d7b3dSmrg// Description: Allocates a free dma page using kernel ioctls, then
60428d7b3dSmrg//   programs the data into the already allocated dma buffer list.
61428d7b3dSmrg// Arguments: pI810XvMC private data structure from the current context.
62428d7b3dSmrg// Notes: We faked the drmMapBufs for the i810's security so now we have
63428d7b3dSmrg//   to insert an allocated page into the correct spot in the faked
64428d7b3dSmrg//   list to keep up appearences.
65428d7b3dSmrg//   Concept for this function was taken from Mesa sources.
66428d7b3dSmrg// Returns: drmBufPtr containing the information about the allocated page.
67428d7b3dSmrg***************************************************************************/
68428d7b3dSmrgdrmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC) {
69428d7b3dSmrg   drmI810DMA dma;
70428d7b3dSmrg   drmBufPtr buf;
71428d7b3dSmrg
72428d7b3dSmrg   dma.granted = 0;
73428d7b3dSmrg   dma.request_size = 4096;
74428d7b3dSmrg   while(!dma.granted) {
75428d7b3dSmrg     if(GET_BUFFER(pI810XvMC, dma) || !dma.granted)
76428d7b3dSmrg       FLUSH(pI810XvMC);
77428d7b3dSmrg   } /* No DMA granted */
78428d7b3dSmrg
79428d7b3dSmrg   buf = &(pI810XvMC->dmabufs->list[dma.request_idx]);
80428d7b3dSmrg   buf->idx = dma.request_idx;
81428d7b3dSmrg   buf->used = 0;
82428d7b3dSmrg   buf->total = dma.request_size;
83428d7b3dSmrg   buf->address = (drmAddress)dma.virtual;
84428d7b3dSmrg   return buf;
85428d7b3dSmrg}
86428d7b3dSmrg
87428d7b3dSmrg/***************************************************************************
88428d7b3dSmrg// Function: free_privContext
89428d7b3dSmrg// Description: Free's the private context structure if the reference
90428d7b3dSmrg//  count is 0.
91428d7b3dSmrg***************************************************************************/
92428d7b3dSmrgvoid i810_free_privContext(i810XvMCContext *pI810XvMC) {
93428d7b3dSmrg
94428d7b3dSmrg  I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
95428d7b3dSmrg
96428d7b3dSmrg
97428d7b3dSmrg  pI810XvMC->ref--;
98428d7b3dSmrg  if(!pI810XvMC->ref) {
99428d7b3dSmrg    drmUnmapBufs(pI810XvMC->dmabufs);
100428d7b3dSmrg    drmUnmap(pI810XvMC->overlay.address,pI810XvMC->overlay.size);
101428d7b3dSmrg    drmUnmap(pI810XvMC->surfaces.address,pI810XvMC->surfaces.size);
102428d7b3dSmrg    drmClose(pI810XvMC->fd);
103428d7b3dSmrg
104428d7b3dSmrg    free(pI810XvMC->dmabufs->list);
105428d7b3dSmrg    free(pI810XvMC);
106428d7b3dSmrg  }
107428d7b3dSmrg
108428d7b3dSmrg  I810_UNLOCK(pI810XvMC);
109428d7b3dSmrg}
110428d7b3dSmrg
111428d7b3dSmrg
112428d7b3dSmrg/***************************************************************************
113428d7b3dSmrg// Function: XvMCCreateContext
114428d7b3dSmrg// Description: Create a XvMC context for the given surface parameters.
115428d7b3dSmrg// Arguments:
116428d7b3dSmrg//   display - Connection to the X server.
117428d7b3dSmrg//   port - XvPortID to use as avertised by the X connection.
118428d7b3dSmrg//   surface_type_id - Unique identifier for the Surface type.
119428d7b3dSmrg//   width - Width of the surfaces.
120428d7b3dSmrg//   height - Height of the surfaces.
121428d7b3dSmrg//   flags - one or more of the following
122428d7b3dSmrg//      XVMC_DIRECT - A direct rendered context is requested.
123428d7b3dSmrg//
124428d7b3dSmrg// Notes: surface_type_id and width/height parameters must match those
125428d7b3dSmrg//        returned by XvMCListSurfaceTypes.
126428d7b3dSmrg// Returns: Status
127428d7b3dSmrg***************************************************************************/
128428d7b3dSmrg_X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
129428d7b3dSmrg			 int surface_type_id, int width, int height, int flags,
130428d7b3dSmrg			 XvMCContext *context) {
131428d7b3dSmrg  i810XvMCContext *pI810XvMC;
132428d7b3dSmrg  int priv_count;
133428d7b3dSmrg  uint *priv_data;
134428d7b3dSmrg  uint magic;
135428d7b3dSmrg  Status ret;
136428d7b3dSmrg  int major, minor;
137428d7b3dSmrg
138428d7b3dSmrg  /* Verify Obvious things first */
139428d7b3dSmrg  if(context == NULL) {
140428d7b3dSmrg    return XvMCBadContext;
141428d7b3dSmrg  }
142428d7b3dSmrg
143428d7b3dSmrg  if(!(flags & XVMC_DIRECT)) {
144428d7b3dSmrg    /* Indirect */
145428d7b3dSmrg    printf("Indirect Rendering not supported!\nUsing Direct.");
146428d7b3dSmrg  }
147428d7b3dSmrg
148428d7b3dSmrg  /* Limit use to root for now */
149428d7b3dSmrg  if(geteuid()) {
150428d7b3dSmrg    printf("Use of XvMC on i810 is currently limited to root\n");
151428d7b3dSmrg    return BadAccess;
152428d7b3dSmrg  }
153428d7b3dSmrg
154428d7b3dSmrg  /* FIXME: Check $DISPLAY for legal values here */
155428d7b3dSmrg
156428d7b3dSmrg  context->surface_type_id = surface_type_id;
157428d7b3dSmrg  context->width = (unsigned short)width;
158428d7b3dSmrg  context->height = (unsigned short)height;
159428d7b3dSmrg  context->flags = flags;
160428d7b3dSmrg  context->port = port;
161428d7b3dSmrg  /*
162428d7b3dSmrg     Width, Height, and flags are checked against surface_type_id
163428d7b3dSmrg     and port for validity inside the X server, no need to check
164428d7b3dSmrg     here.
165428d7b3dSmrg  */
166428d7b3dSmrg
167428d7b3dSmrg  /* Allocate private Context data */
168428d7b3dSmrg  context->privData = (void *)malloc(sizeof(i810XvMCContext));
169428d7b3dSmrg  if(!context->privData) {
170428d7b3dSmrg    printf("Unable to allocate resources for XvMC context.\n");
171428d7b3dSmrg    return BadAlloc;
172428d7b3dSmrg  }
173428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)context->privData;
174428d7b3dSmrg
175428d7b3dSmrg
176428d7b3dSmrg  /* Verify the XvMC extension exists */
177428d7b3dSmrg  if(! XvMCQueryExtension(display, &event_base,
178428d7b3dSmrg			  &error_base)) {
179428d7b3dSmrg    printf("XvMC Extension is not available!\n");
180428d7b3dSmrg    return BadAlloc;
181428d7b3dSmrg  }
182428d7b3dSmrg  /* Verify XvMC version */
183428d7b3dSmrg  ret = XvMCQueryVersion(display, &major, &minor);
184428d7b3dSmrg  if(ret) {
185428d7b3dSmrg    printf("XvMCQuery Version Failed, unable to determine protocol version\n");
186428d7b3dSmrg  }
187428d7b3dSmrg  /* FIXME: Check Major and Minor here */
188428d7b3dSmrg
189428d7b3dSmrg  /* Check for drm */
190428d7b3dSmrg  if(! drmAvailable()) {
191428d7b3dSmrg    printf("Direct Rendering is not avilable on this system!\n");
192428d7b3dSmrg    return BadAlloc;
193428d7b3dSmrg  }
194428d7b3dSmrg
195428d7b3dSmrg  /*
196428d7b3dSmrg     Build the Attribute Atoms, and Initialize the ones that exist
197428d7b3dSmrg     in Xv.
198428d7b3dSmrg  */
199428d7b3dSmrg  pI810XvMC->xv_colorkey = XInternAtom(display,"XV_COLORKEY",0);
200428d7b3dSmrg  if(!pI810XvMC->xv_colorkey) {
201428d7b3dSmrg    return XvBadPort;
202428d7b3dSmrg  }
203428d7b3dSmrg  ret = XvGetPortAttribute(display,port,pI810XvMC->xv_colorkey,
204428d7b3dSmrg			   &pI810XvMC->colorkey);
205428d7b3dSmrg  if(ret) {
206428d7b3dSmrg    return ret;
207428d7b3dSmrg  }
208428d7b3dSmrg  pI810XvMC->xv_brightness = XInternAtom(display,"XV_BRIGHTNESS",0);
209428d7b3dSmrg  pI810XvMC->xv_saturation = XInternAtom(display,"XV_SATURATION",0);
210428d7b3dSmrg  pI810XvMC->xv_contrast = XInternAtom(display,"XV_CONTRAST",0);
211428d7b3dSmrg  pI810XvMC->brightness = 0;
212428d7b3dSmrg  pI810XvMC->saturation = 0x80;  /* 1.0 in 3.7 format */
213428d7b3dSmrg  pI810XvMC->contrast = 0x40; /* 1.0 in 3.6 format */
214428d7b3dSmrg
215428d7b3dSmrg  /* Open DRI Device */
216428d7b3dSmrg  if((pI810XvMC->fd = drmOpen("i810",NULL)) < 0) {
217428d7b3dSmrg    printf("DRM Device for i810 could not be opened.\n");
218428d7b3dSmrg    free(pI810XvMC);
219428d7b3dSmrg    return BadAccess;
220428d7b3dSmrg  } /* !pI810XvMC->fd */
221428d7b3dSmrg
222428d7b3dSmrg  /* Get magic number and put it in privData for passing */
223428d7b3dSmrg  drmGetMagic(pI810XvMC->fd,&magic);
224428d7b3dSmrg  context->flags = (unsigned long)magic;
225428d7b3dSmrg
226428d7b3dSmrg  /*
227428d7b3dSmrg    Pass control to the X server to create a drm_context_t for us and
228428d7b3dSmrg    validate the with/height and flags.
229428d7b3dSmrg  */
230428d7b3dSmrg  if((ret = _xvmc_create_context(display, context, &priv_count, &priv_data))) {
231428d7b3dSmrg    printf("Unable to create XvMC Context.\n");
232428d7b3dSmrg    return ret;
233428d7b3dSmrg  }
234428d7b3dSmrg
235428d7b3dSmrg  /*
236428d7b3dSmrg     X server returns a structure like this:
237428d7b3dSmrg     drm_context_t
238428d7b3dSmrg     fbBase
239428d7b3dSmrg     OverlayOffset
240428d7b3dSmrg     OverlaySize
241428d7b3dSmrg     SurfacesOffset
242428d7b3dSmrg     SurfacesSize
243428d7b3dSmrg     busIdString = 9 char + 1
244428d7b3dSmrg  */
245428d7b3dSmrg  if(priv_count != 9) {
246428d7b3dSmrg    printf("_xvmc_create_context() returned incorrect data size!\n");
247428d7b3dSmrg    printf("\tExpected 9, got %d\n",priv_count);
248428d7b3dSmrg    _xvmc_destroy_context(display, context);
249428d7b3dSmrg    free(pI810XvMC);
250428d7b3dSmrg    return BadAlloc;
251428d7b3dSmrg  }
252428d7b3dSmrg  pI810XvMC->drmcontext = priv_data[0];
253428d7b3dSmrg  pI810XvMC->fb_base = priv_data[1];
254428d7b3dSmrg  pI810XvMC->overlay.offset = priv_data[2] + priv_data[1];
255428d7b3dSmrg  pI810XvMC->overlay.size = priv_data[3];
256428d7b3dSmrg  pI810XvMC->surfaces.offset = priv_data[4] + priv_data[1];
257428d7b3dSmrg  pI810XvMC->surfaces.size = priv_data[5];
258428d7b3dSmrg  strncpy(pI810XvMC->busIdString,(char *)&priv_data[6],9);
259428d7b3dSmrg  pI810XvMC->busIdString[9] = '\0';
260428d7b3dSmrg
261428d7b3dSmrg  /* Must free the private data we were passed from X */
262428d7b3dSmrg  free(priv_data);
263428d7b3dSmrg
264428d7b3dSmrg  /* Initialize private context values */
265428d7b3dSmrg  pI810XvMC->current = 0;
266428d7b3dSmrg  pI810XvMC->lock = 0;
267428d7b3dSmrg  pI810XvMC->last_flip = 0;
268428d7b3dSmrg  pI810XvMC->dual_prime = 0;
269428d7b3dSmrg
270428d7b3dSmrg  /*
271428d7b3dSmrg     Map dma Buffers: Not really, this would be a drmMapBufs
272428d7b3dSmrg     but due to the i810 security model we have to just create an
273428d7b3dSmrg     empty data structure to fake it.
274428d7b3dSmrg  */
275428d7b3dSmrg  pI810XvMC->dmabufs = (drmBufMapPtr)malloc(sizeof(drmBufMap));
276428d7b3dSmrg  if(pI810XvMC->dmabufs == NULL) {
277428d7b3dSmrg    printf("Dma Bufs could not be mapped.\n");
278428d7b3dSmrg    _xvmc_destroy_context(display, context);
279428d7b3dSmrg    free(pI810XvMC);
280428d7b3dSmrg    return BadAlloc;
281428d7b3dSmrg  } /* pI810XvMC->dmabufs == NULL */
282428d7b3dSmrg  memset(pI810XvMC->dmabufs, 0, sizeof(drmBufMap));
283428d7b3dSmrg  pI810XvMC->dmabufs->list = (drmBufPtr)malloc(sizeof(drmBuf) *
284428d7b3dSmrg					       I810_DMA_BUF_NR);
285428d7b3dSmrg  if(pI810XvMC->dmabufs->list == NULL) {
286428d7b3dSmrg    printf("Dma Bufs could not be mapped.\n");
287428d7b3dSmrg    _xvmc_destroy_context(display, context);
288428d7b3dSmrg    free(pI810XvMC);
289428d7b3dSmrg    return BadAlloc;
290428d7b3dSmrg  } /* pI810XvMC->dmabufs->list == NULL */
291428d7b3dSmrg  memset(pI810XvMC->dmabufs->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
292428d7b3dSmrg
293428d7b3dSmrg  /* Map the Overlay memory */
294428d7b3dSmrg  if(drmMap(pI810XvMC->fd,pI810XvMC->overlay.offset,
295428d7b3dSmrg	    pI810XvMC->overlay.size,&(pI810XvMC->overlay.address)) < 0) {
296428d7b3dSmrg    printf("Unable to map Overlay at offset 0x%x and size 0x%x\n",
297428d7b3dSmrg	   (unsigned int)pI810XvMC->overlay.offset,pI810XvMC->overlay.size);
298428d7b3dSmrg    _xvmc_destroy_context(display, context);
299428d7b3dSmrg    free(pI810XvMC->dmabufs->list);
300428d7b3dSmrg    free(pI810XvMC);
301428d7b3dSmrg    return BadAlloc;
302428d7b3dSmrg  } /* drmMap() < 0 */
303428d7b3dSmrg
304428d7b3dSmrg  /* Overlay Regs are offset 1024 into Overlay Map */
305428d7b3dSmrg  pI810XvMC->oregs = (i810OverlayRec *)
306428d7b3dSmrg    ((unsigned char *)pI810XvMC->overlay.address + 1024);
307428d7b3dSmrg
308428d7b3dSmrg  /* Map Surfaces */
309428d7b3dSmrg  if(drmMap(pI810XvMC->fd,pI810XvMC->surfaces.offset,
310428d7b3dSmrg	    pI810XvMC->surfaces.size,&(pI810XvMC->surfaces.address)) < 0) {
311428d7b3dSmrg    printf("Unable to map XvMC Surfaces.\n");
312428d7b3dSmrg    _xvmc_destroy_context(display, context);
313428d7b3dSmrg    free(pI810XvMC->dmabufs->list);
314428d7b3dSmrg    free(pI810XvMC);
315428d7b3dSmrg    return BadAlloc;
316428d7b3dSmrg  } /* drmMap() < 0 */
317428d7b3dSmrg
318428d7b3dSmrg  /*
319428d7b3dSmrg    There is a tiny chance that someone was using the overlay and
320428d7b3dSmrg    issued a flip that hasn't finished. To be 100% sure I'll just
321428d7b3dSmrg    take the lock and sleep for the worst case time for a flip.
322428d7b3dSmrg  */
323428d7b3dSmrg  I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
324428d7b3dSmrg  usleep(20000);  /* 1/50th Sec for 50hz refresh */
325428d7b3dSmrg
326428d7b3dSmrg  /* Set up Overlay regs with Initial Values */
327428d7b3dSmrg  pI810XvMC->oregs->YRGB_VPH = 0;
328428d7b3dSmrg  pI810XvMC->oregs->UV_VPH = 0;
329428d7b3dSmrg  pI810XvMC->oregs->HORZ_PH = 0;
330428d7b3dSmrg  pI810XvMC->oregs->INIT_PH = 0;
331428d7b3dSmrg  pI810XvMC->oregs->DWINPOS = 0;
332428d7b3dSmrg  pI810XvMC->oregs->DWINSZ = (I810_XVMC_MAXHEIGHT << 16) |
333428d7b3dSmrg    I810_XVMC_MAXWIDTH;
334428d7b3dSmrg  pI810XvMC->oregs->SWID =  I810_XVMC_MAXWIDTH | (I810_XVMC_MAXWIDTH << 15);
335428d7b3dSmrg  pI810XvMC->oregs->SWIDQW = (I810_XVMC_MAXWIDTH >> 3) |
336428d7b3dSmrg    (I810_XVMC_MAXWIDTH << 12);
337428d7b3dSmrg  pI810XvMC->oregs->SHEIGHT = I810_XVMC_MAXHEIGHT |
338428d7b3dSmrg    (I810_XVMC_MAXHEIGHT << 15);
339428d7b3dSmrg  pI810XvMC->oregs->YRGBSCALE = 0x80004000; /* scale factor 1 */
340428d7b3dSmrg  pI810XvMC->oregs->UVSCALE = 0x80004000;   /* scale factor 1 */
341428d7b3dSmrg  pI810XvMC->oregs->OV0CLRC0 = 0x4000;      /* brightness: 0 contrast: 1.0 */
342428d7b3dSmrg  pI810XvMC->oregs->OV0CLRC1 = 0x80;        /* saturation: bypass */
343428d7b3dSmrg
344428d7b3dSmrg  /* Destination Colorkey Setup */
345428d7b3dSmrg  pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey);
346428d7b3dSmrg  pI810XvMC->oregs->DCLRKM = 0x80070307;
347428d7b3dSmrg
348428d7b3dSmrg
349428d7b3dSmrg  pI810XvMC->oregs->SCLRKVH = 0;
350428d7b3dSmrg  pI810XvMC->oregs->SCLRKVL = 0;
351428d7b3dSmrg  pI810XvMC->oregs->SCLRKM = 0; /* source color key disable */
352428d7b3dSmrg  pI810XvMC->oregs->OV0CONF = 0; /* two 720 pixel line buffers */
353428d7b3dSmrg
354428d7b3dSmrg  pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
355428d7b3dSmrg    Y_ADJUST | YUV_420;
356428d7b3dSmrg
357428d7b3dSmrg  pI810XvMC->ref = 1;
358428d7b3dSmrg
359428d7b3dSmrg  I810_UNLOCK(pI810XvMC);
360428d7b3dSmrg
361428d7b3dSmrg  return Success;
362428d7b3dSmrg
363428d7b3dSmrg}
364428d7b3dSmrg
365428d7b3dSmrg/***************************************************************************
366428d7b3dSmrg// Function: XvMCDestroyContext
367428d7b3dSmrg// Description: Destorys the specified context.
368428d7b3dSmrg//
369428d7b3dSmrg// Arguments:
370428d7b3dSmrg//   display - Specifies the connection to the server.
371428d7b3dSmrg//   context - The context to be destroyed.
372428d7b3dSmrg//
373428d7b3dSmrg// Returns: Status
374428d7b3dSmrg***************************************************************************/
375428d7b3dSmrg_X_EXPORT Status XvMCDestroyContext(Display *display, XvMCContext *context) {
376428d7b3dSmrg  i810XvMCContext *pI810XvMC;
377428d7b3dSmrg
378428d7b3dSmrg  if(context == NULL) {
379428d7b3dSmrg    return (error_base + XvMCBadContext);
380428d7b3dSmrg  }
381428d7b3dSmrg  if(context->privData == NULL) {
382428d7b3dSmrg    return (error_base + XvMCBadContext);
383428d7b3dSmrg  }
384428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)context->privData;
385428d7b3dSmrg
386428d7b3dSmrg  /* Turn off the overlay */
387428d7b3dSmrg  if(pI810XvMC->last_flip) {
388428d7b3dSmrg    I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
389428d7b3dSmrg
390428d7b3dSmrg    /* Make sure last flip is done */
391428d7b3dSmrg    BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
392428d7b3dSmrg
393428d7b3dSmrg    pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
394428d7b3dSmrg      Y_ADJUST;
395428d7b3dSmrg    pI810XvMC->current = !pI810XvMC->current;
396428d7b3dSmrg    if(pI810XvMC->current == 1) {
397428d7b3dSmrg      pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0;
398428d7b3dSmrg    }
399428d7b3dSmrg    else {
400428d7b3dSmrg      pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0;
401428d7b3dSmrg    }
402428d7b3dSmrg    OVERLAY_FLIP(pI810XvMC);
403428d7b3dSmrg    pI810XvMC->last_flip++;
404428d7b3dSmrg
405428d7b3dSmrg    /* Wait for the flip */
406428d7b3dSmrg    BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
407428d7b3dSmrg
408428d7b3dSmrg    I810_UNLOCK(pI810XvMC);
409428d7b3dSmrg  }
410428d7b3dSmrg
411428d7b3dSmrg  /* Pass Control to the X server to destroy the drm_context_t */
412428d7b3dSmrg  _xvmc_destroy_context(display, context);
413428d7b3dSmrg
414428d7b3dSmrg  i810_free_privContext(pI810XvMC);
415428d7b3dSmrg  context->privData = NULL;
416428d7b3dSmrg
417428d7b3dSmrg  return Success;
418428d7b3dSmrg}
419428d7b3dSmrg
420428d7b3dSmrg
421428d7b3dSmrg/***************************************************************************
422428d7b3dSmrg// Function: XvMCCreateSurface
423428d7b3dSmrg***************************************************************************/
424428d7b3dSmrg_X_EXPORT Status XvMCCreateSurface( Display *display, XvMCContext *context,
425428d7b3dSmrg			  XvMCSurface *surface) {
426428d7b3dSmrg  i810XvMCContext *pI810XvMC;
427428d7b3dSmrg  i810XvMCSurface *pI810Surface;
428428d7b3dSmrg  int priv_count;
429428d7b3dSmrg  uint *priv_data;
430428d7b3dSmrg  Status ret;
431428d7b3dSmrg
432428d7b3dSmrg  if((surface == NULL) || (context == NULL) || (display == NULL)){
433428d7b3dSmrg    return BadValue;
434428d7b3dSmrg  }
435428d7b3dSmrg
436428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)context->privData;
437428d7b3dSmrg  if(pI810XvMC == NULL) {
438428d7b3dSmrg    return (error_base + XvMCBadContext);
439428d7b3dSmrg  }
440428d7b3dSmrg
441428d7b3dSmrg
442428d7b3dSmrg  surface->privData = (i810XvMCSurface *)malloc(sizeof(i810XvMCSurface));
443428d7b3dSmrg  if(!surface->privData) {
444428d7b3dSmrg    return BadAlloc;
445428d7b3dSmrg  }
446428d7b3dSmrg  pI810Surface = (i810XvMCSurface *)surface->privData;
447428d7b3dSmrg
448428d7b3dSmrg  /* Initialize private values */
449428d7b3dSmrg  pI810Surface->privContext = pI810XvMC;
450428d7b3dSmrg  pI810Surface->last_render = 0;
451428d7b3dSmrg  pI810Surface->last_flip = 0;
452428d7b3dSmrg  pI810Surface->second_field = 0;
453428d7b3dSmrg
454428d7b3dSmrg  if((ret = _xvmc_create_surface(display, context, surface,
455428d7b3dSmrg				&priv_count, &priv_data))) {
456428d7b3dSmrg    free(pI810Surface);
457428d7b3dSmrg    printf("Unable to create XvMCSurface.\n");
458428d7b3dSmrg    return ret;
459428d7b3dSmrg  }
460428d7b3dSmrg
461428d7b3dSmrg  /*
462428d7b3dSmrg    _xvmc_create_subpicture returns 2 uints with the offset into
463428d7b3dSmrg    the DRM map for the Y surface and UV surface.
464428d7b3dSmrg  */
465428d7b3dSmrg  if(priv_count != 2) {
466428d7b3dSmrg    printf("_xvmc_create_surface() return incorrect data size.\n");
467428d7b3dSmrg    printf("Expected 2 got %d\n",priv_count);
468428d7b3dSmrg    free(priv_data);
469428d7b3dSmrg    free(pI810Surface);
470428d7b3dSmrg    return BadAlloc;
471428d7b3dSmrg  }
472428d7b3dSmrg  /* Data == Client Address, offset == Physical address offset */
473428d7b3dSmrg  pI810Surface->data = pI810XvMC->surfaces.address;
474428d7b3dSmrg  pI810Surface->offset = pI810XvMC->surfaces.offset;
475428d7b3dSmrg
476428d7b3dSmrg
477428d7b3dSmrg  /*
478428d7b3dSmrg     i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch
479428d7b3dSmrg     and the Tiler need 512k aligned surfaces, basically we are
480428d7b3dSmrg     stuck with fixed memory with pitch 1024 for Y data. UV = 512.
481428d7b3dSmrg  */
482428d7b3dSmrg  pI810Surface->pitch = 10;
483428d7b3dSmrg  if((surface->surface_type_id == FOURCC_UYVY) ||
484428d7b3dSmrg     (surface->surface_type_id == FOURCC_YUY2)) {
485428d7b3dSmrg    /* This is not implemented server side. */
486428d7b3dSmrg    pI810Surface->pitch++;
487428d7b3dSmrg  }
488428d7b3dSmrg
489428d7b3dSmrg  /*
490428d7b3dSmrg    offsets[0,1,2] == Offsets from either data or offset for the Y
491428d7b3dSmrg    U and V surfaces.
492428d7b3dSmrg  */
493428d7b3dSmrg  pI810Surface->offsets[0] = priv_data[0];
494428d7b3dSmrg  if(((unsigned long)pI810Surface->data + pI810Surface->offsets[0]) & 4095) {
495428d7b3dSmrg    printf("XvMCCreateSurface: Surface offset 0 is not 4096 aligned\n");
496428d7b3dSmrg  }
497428d7b3dSmrg
498428d7b3dSmrg  if((surface->surface_type_id == FOURCC_UYVY) ||
499428d7b3dSmrg     (surface->surface_type_id == FOURCC_YUY2)) {
500428d7b3dSmrg    /* Packed surface, not fully implemented */
501428d7b3dSmrg    pI810Surface->offsets[1] = 0;
502428d7b3dSmrg    pI810Surface->offsets[2] = 0;
503428d7b3dSmrg  }
504428d7b3dSmrg  else {
505428d7b3dSmrg    /* Planar surface */
506428d7b3dSmrg    pI810Surface->offsets[1] = priv_data[1];
507428d7b3dSmrg    if(((unsigned long)pI810Surface->data + pI810Surface->offsets[1]) & 2047) {
508428d7b3dSmrg      printf("XvMCCreateSurface: Surface offset 1 is not 2048 aligned\n");
509428d7b3dSmrg    }
510428d7b3dSmrg
511428d7b3dSmrg    pI810Surface->offsets[2] = ((unsigned long)pI810Surface->offsets[1] +
512428d7b3dSmrg				(1<<(pI810Surface->pitch - 1)) * 288);
513428d7b3dSmrg    if(((unsigned long)pI810Surface->data + pI810Surface->offsets[2]) & 2047) {
514428d7b3dSmrg      printf("XvMCCreateSurface: Surface offset 2 is not 2048 aligned\n");
515428d7b3dSmrg    }
516428d7b3dSmrg
517428d7b3dSmrg  }
518428d7b3dSmrg
519428d7b3dSmrg  /* Free data returned from xvmc_create_surface */
520428d7b3dSmrg  free(priv_data);
521428d7b3dSmrg
522428d7b3dSmrg  /* Clear the surface to 0 */
523428d7b3dSmrg  memset((void *)((unsigned long)pI810Surface->data + (unsigned long)pI810Surface->offsets[0]),
524428d7b3dSmrg	 0, ((1<<pI810Surface->pitch) * surface->height));
525428d7b3dSmrg
526428d7b3dSmrg  switch(surface->surface_type_id) {
527428d7b3dSmrg  case FOURCC_YV12:
528428d7b3dSmrg  case FOURCC_I420:
529428d7b3dSmrg    /* Destination buffer info command */
530428d7b3dSmrg    pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset +
531428d7b3dSmrg			     pI810Surface->offsets[0]) & ~0xfc000fff) |
532428d7b3dSmrg			   (pI810Surface->pitch - 9));
533428d7b3dSmrg    pI810Surface->dbi1u = ((((unsigned int)pI810Surface->offset +
534428d7b3dSmrg			     pI810Surface->offsets[1]) & ~0xfc000fff) |
535428d7b3dSmrg			   (pI810Surface->pitch - 10));
536428d7b3dSmrg    pI810Surface->dbi1v = ((((unsigned int)pI810Surface->offset +
537428d7b3dSmrg			     pI810Surface->offsets[2]) & ~0xfc000fff) |
538428d7b3dSmrg			   (pI810Surface->pitch - 10));
539428d7b3dSmrg
540428d7b3dSmrg    /* Destination buffer variables command */
541428d7b3dSmrg    pI810Surface->dbv1 = (0x8<<20) | (0x8<<16);
542428d7b3dSmrg    /* Map info command */
543428d7b3dSmrg    pI810Surface->mi1y = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 3);
544428d7b3dSmrg    pI810Surface->mi1u = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4);
545428d7b3dSmrg    pI810Surface->mi1v = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4);
546428d7b3dSmrg
547428d7b3dSmrg    pI810Surface->mi2y = (((unsigned int)surface->height - 1)<<16) |
548428d7b3dSmrg      ((unsigned int)surface->width - 1);
549428d7b3dSmrg    pI810Surface->mi2u = (((unsigned int)surface->height - 1)<<15) |
550428d7b3dSmrg      (((unsigned int)surface->width - 1)>>1);
551428d7b3dSmrg    pI810Surface->mi2v = pI810Surface->mi2u;
552428d7b3dSmrg
553428d7b3dSmrg    pI810Surface->mi3y = ((unsigned int)pI810Surface->offset +
554428d7b3dSmrg			  pI810Surface->offsets[0]) & ~0x0000000f;
555428d7b3dSmrg    pI810Surface->mi3u = ((unsigned int)pI810Surface->offset +
556428d7b3dSmrg			  pI810Surface->offsets[1]) & ~0x0000000f;
557428d7b3dSmrg    pI810Surface->mi3v = ((unsigned int)pI810Surface->offset +
558428d7b3dSmrg			  pI810Surface->offsets[2]) & ~0x0000000f;
559428d7b3dSmrg    break;
560428d7b3dSmrg  case FOURCC_UYVY:
561428d7b3dSmrg  case FOURCC_YUY2:
562428d7b3dSmrg  default:
563428d7b3dSmrg    /* Destination buffer info command */
564428d7b3dSmrg    pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset +
565428d7b3dSmrg			     pI810Surface->offsets[0]) & ~0xfc000fff) |
566428d7b3dSmrg			   (pI810Surface->pitch - 9));
567428d7b3dSmrg    /* Destination buffer variables command */
568428d7b3dSmrg    if(surface->surface_type_id == FOURCC_YUY2) {
569428d7b3dSmrg      pI810Surface->dbv1 = 0x5<<8;
570428d7b3dSmrg      pI810Surface->mi1y = 0x5<<24 | pI810Surface->pitch | 0x1<<21;
571428d7b3dSmrg    }
572428d7b3dSmrg    else {
573428d7b3dSmrg      pI810Surface->dbv1 = 0x4<<8;
574428d7b3dSmrg      pI810Surface->mi1y = 0x5<<24 | (pI810Surface->pitch - 3);
575428d7b3dSmrg    }
576428d7b3dSmrg    pI810Surface->mi2y = (((unsigned int)surface->width - 1)<<16) |
577428d7b3dSmrg      ((unsigned int)surface->height - 1);
578428d7b3dSmrg    pI810Surface->mi3y = ((unsigned int)pI810Surface->offset +
579428d7b3dSmrg			  pI810Surface->offsets[0]) & ~0xfc000fff;
580428d7b3dSmrg    break;
581428d7b3dSmrg  }
582428d7b3dSmrg  pI810XvMC->ref++;
583428d7b3dSmrg
584428d7b3dSmrg  return Success;
585428d7b3dSmrg}
586428d7b3dSmrg
587428d7b3dSmrg
588428d7b3dSmrg/***************************************************************************
589428d7b3dSmrg// Function: XvMCDestroySurface
590428d7b3dSmrg***************************************************************************/
591428d7b3dSmrg_X_EXPORT Status XvMCDestroySurface(Display *display, XvMCSurface *surface) {
592428d7b3dSmrg  i810XvMCSurface *pI810Surface;
593428d7b3dSmrg  i810XvMCContext *pI810XvMC;
594428d7b3dSmrg
595428d7b3dSmrg  if((display == NULL) || (surface == NULL)) {
596428d7b3dSmrg    return BadValue;
597428d7b3dSmrg  }
598428d7b3dSmrg  if(surface->privData == NULL) {
599428d7b3dSmrg    return (error_base + XvMCBadSurface);
600428d7b3dSmrg  }
601428d7b3dSmrg
602428d7b3dSmrg  pI810Surface = (i810XvMCSurface *)surface->privData;
603428d7b3dSmrg  if(pI810Surface->last_flip) {
604428d7b3dSmrg    XvMCSyncSurface(display,surface);
605428d7b3dSmrg  }
606428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
607428d7b3dSmrg
608428d7b3dSmrg  _xvmc_destroy_surface(display,surface);
609428d7b3dSmrg
610428d7b3dSmrg  i810_free_privContext(pI810XvMC);
611428d7b3dSmrg
612428d7b3dSmrg  free(pI810Surface);
613428d7b3dSmrg  surface->privData = NULL;
614428d7b3dSmrg  return Success;
615428d7b3dSmrg}
616428d7b3dSmrg
617428d7b3dSmrg/***************************************************************************
618428d7b3dSmrg// Function: XvMCCreateBlocks
619428d7b3dSmrg***************************************************************************/
620428d7b3dSmrg_X_EXPORT Status XvMCCreateBlocks(Display *display, XvMCContext *context,
621428d7b3dSmrg			unsigned int num_blocks,
622428d7b3dSmrg			XvMCBlockArray *block) {
623428d7b3dSmrg
624428d7b3dSmrg  if((display == NULL) || (context == NULL) || (num_blocks == 0)) {
625428d7b3dSmrg    return BadValue;
626428d7b3dSmrg  }
627428d7b3dSmrg
628428d7b3dSmrg  block->blocks = (short *)malloc(num_blocks<<6 * sizeof(short));
629428d7b3dSmrg  if(block->blocks == NULL) {
630428d7b3dSmrg    return BadAlloc;
631428d7b3dSmrg  }
632428d7b3dSmrg
633428d7b3dSmrg  block->num_blocks = num_blocks;
634428d7b3dSmrg  block->context_id = context->context_id;
635428d7b3dSmrg
636428d7b3dSmrg  block->privData = NULL;
637428d7b3dSmrg
638428d7b3dSmrg  return Success;
639428d7b3dSmrg}
640428d7b3dSmrg
641428d7b3dSmrg/***************************************************************************
642428d7b3dSmrg// Function: XvMCDestroyBlocks
643428d7b3dSmrg***************************************************************************/
644428d7b3dSmrg_X_EXPORT Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *block) {
645428d7b3dSmrg  if(display == NULL) {
646428d7b3dSmrg    return BadValue;
647428d7b3dSmrg  }
648428d7b3dSmrg
649428d7b3dSmrg  free(block->blocks);
650428d7b3dSmrg  block->num_blocks = 0;
651428d7b3dSmrg  block->context_id = 0;
652428d7b3dSmrg  block->privData = NULL;
653428d7b3dSmrg  return Success;
654428d7b3dSmrg}
655428d7b3dSmrg
656428d7b3dSmrg/***************************************************************************
657428d7b3dSmrg// Function: XvMCCreateMacroBlocks
658428d7b3dSmrg***************************************************************************/
659428d7b3dSmrg_X_EXPORT Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context,
660428d7b3dSmrg			     unsigned int num_blocks,
661428d7b3dSmrg			     XvMCMacroBlockArray *blocks) {
662428d7b3dSmrg
663428d7b3dSmrg  if((display == NULL) || (context == NULL) || (blocks == NULL) ||
664428d7b3dSmrg      (num_blocks == 0)) {
665428d7b3dSmrg    return BadValue;
666428d7b3dSmrg  }
667428d7b3dSmrg  memset(blocks,0,sizeof(XvMCMacroBlockArray));
668428d7b3dSmrg  blocks->context_id = context->context_id;
669428d7b3dSmrg  blocks->privData = NULL;
670428d7b3dSmrg
671428d7b3dSmrg  blocks->macro_blocks = (XvMCMacroBlock *)
672428d7b3dSmrg    malloc(num_blocks * sizeof(XvMCMacroBlock));
673428d7b3dSmrg  if(blocks->macro_blocks == NULL) {
674428d7b3dSmrg    return BadAlloc;
675428d7b3dSmrg  }
676428d7b3dSmrg  blocks->num_blocks = num_blocks;
677428d7b3dSmrg
678428d7b3dSmrg  return Success;
679428d7b3dSmrg}
680428d7b3dSmrg
681428d7b3dSmrg/***************************************************************************
682428d7b3dSmrg// Function: XvMCDestroyMacroBlocks
683428d7b3dSmrg***************************************************************************/
684428d7b3dSmrg_X_EXPORT Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *block) {
685428d7b3dSmrg  if((display == NULL) || (block == NULL)) {
686428d7b3dSmrg    return BadValue;
687428d7b3dSmrg  }
688428d7b3dSmrg  if(block->macro_blocks) {
689428d7b3dSmrg    free(block->macro_blocks);
690428d7b3dSmrg  }
691428d7b3dSmrg  block->context_id = 0;
692428d7b3dSmrg  block->num_blocks = 0;
693428d7b3dSmrg  block->privData = NULL;
694428d7b3dSmrg
695428d7b3dSmrg  return Success;
696428d7b3dSmrg}
697428d7b3dSmrg
698428d7b3dSmrg
699428d7b3dSmrg/***************************************************************************
700428d7b3dSmrg// Function: dp (Debug Print)
701428d7b3dSmrg// Description: This function prints out in hex i * uint32_t at the address
702428d7b3dSmrg//  supplied. This enables you to print out the dma buffers from
703428d7b3dSmrg//  within the debugger even though they are not in your address space.
704428d7b3dSmrg***************************************************************************/
705428d7b3dSmrgvoid dp(unsigned int *address, unsigned int i) {
706428d7b3dSmrg  int j;
707428d7b3dSmrg
708428d7b3dSmrg  printf("DebugPrint:\n");
709428d7b3dSmrg  for(j=0; j<i; j++) {
710428d7b3dSmrg    printf("0x%8.8x ",address[j]);
711428d7b3dSmrg    if(j && !(j & 7)) { printf("\n");}
712428d7b3dSmrg  }
713428d7b3dSmrg}
714428d7b3dSmrg
715428d7b3dSmrg/***************************************************************************
716428d7b3dSmrg// Macro: PACK_*
717428d7b3dSmrg// Description: Packs 16bit signed data from blocks into either 8bit unsigned
718428d7b3dSmrg//  intra data or 16bit signed correction data, both packed into
719428d7b3dSmrg//  32 bit integers.
720428d7b3dSmrg***************************************************************************/
721428d7b3dSmrg#define PACK_INTRA_DATA(d,b,n)                  \
722428d7b3dSmrg  do {                                          \
723428d7b3dSmrg   char *dp = (char *)d;                        \
724428d7b3dSmrg   char *bp = (char *)b;                        \
725428d7b3dSmrg   int counter;                                 \
726428d7b3dSmrg   for(counter = 0; counter < n; counter++) {   \
727428d7b3dSmrg     *dp++ = *bp;                               \
728428d7b3dSmrg     bp += 2;                                   \
729428d7b3dSmrg   }                                            \
730428d7b3dSmrg  }while(0);
731428d7b3dSmrg
732428d7b3dSmrg#define PACK_CORR_DATA(d,b,n)          \
733428d7b3dSmrg            memcpy(d,b,n);             \
734428d7b3dSmrg            d = (uint *)((unsigned long)d + n);
735428d7b3dSmrg
736428d7b3dSmrg#define MARK_CORR_DATA(d,n)                          \
737428d7b3dSmrg            do {                                     \
738428d7b3dSmrg              uint* q = (uint*)((unsigned long)d - n);        \
739428d7b3dSmrg              while((unsigned long)q < (unsigned long)d) {             \
740428d7b3dSmrg               *q++ += 0x00330033;                   \
741428d7b3dSmrg              }                                      \
742428d7b3dSmrg	    }while(0);
743428d7b3dSmrg
744428d7b3dSmrg#define MARK_INTRA_BLOCK(d)         \
745428d7b3dSmrg           do {                     \
746428d7b3dSmrg             int q;                 \
747428d7b3dSmrg             for(q=0; q<16; q++) {  \
748428d7b3dSmrg               d[q] += 0x33333333;  \
749428d7b3dSmrg             }                      \
750428d7b3dSmrg	    }while(0);
751428d7b3dSmrg
752428d7b3dSmrg/*
753428d7b3dSmrg  Used for DCT 1 when we need DCT 0. Instead
754428d7b3dSmrg  of reading from one block we read from two and
755428d7b3dSmrg  interlace.
756428d7b3dSmrg*/
757428d7b3dSmrg#define PACK_CORR_DATA_1to0(d,top,bottom)            \
758428d7b3dSmrg            do {                                     \
759428d7b3dSmrg              short *t = top,*b = bottom;            \
760428d7b3dSmrg              PACK_CORR_DATA(d,t,16);                \
761428d7b3dSmrg              t = (short *)((unsigned long)t + 16);           \
762428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
763428d7b3dSmrg              b = (short *)((unsigned long)b + 16);           \
764428d7b3dSmrg              PACK_CORR_DATA(d,t,16);                \
765428d7b3dSmrg              t = (short *)((unsigned long)t + 16);           \
766428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
767428d7b3dSmrg              b = (short *)((unsigned long)b + 16);           \
768428d7b3dSmrg              PACK_CORR_DATA(d,t,16);                \
769428d7b3dSmrg              t = (short *)((unsigned long)t + 16);           \
770428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
771428d7b3dSmrg              b = (short *)((unsigned long)b + 16);           \
772428d7b3dSmrg              PACK_CORR_DATA(d,t,16);                \
773428d7b3dSmrg              t = (short *)((unsigned long)t + 16);           \
774428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
775428d7b3dSmrg              b = (short *)((unsigned long)b + 16);           \
776428d7b3dSmrg            }while(0);
777428d7b3dSmrg
778428d7b3dSmrg/* Used for DCT 0 when we need DCT 1. */
779428d7b3dSmrg#define PACK_CORR_DATA_0to1(d,top,bottom)            \
780428d7b3dSmrg            do{                                      \
781428d7b3dSmrg              short *t = top,*b = bottom;            \
782428d7b3dSmrg              PACK_CORR_DATA(d,t,16);                \
783428d7b3dSmrg              t = (short *)((unsigned long)t + 32);           \
784428d7b3dSmrg              PACK_CORR_DATA(d,t,16);                \
785428d7b3dSmrg              t = (short *)((unsigned long)t + 32);           \
786428d7b3dSmrg              PACK_CORR_DATA(d,t,16);                \
787428d7b3dSmrg              t = (short *)((unsigned long)t + 32);           \
788428d7b3dSmrg              PACK_CORR_DATA(d,t,16);                \
789428d7b3dSmrg              t = (short *)((unsigned long)t + 32);           \
790428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
791428d7b3dSmrg              b = (short *)((unsigned long)b + 32);           \
792428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
793428d7b3dSmrg              b = (short *)((unsigned long)b + 32);           \
794428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
795428d7b3dSmrg              b = (short *)((unsigned long)b + 32);           \
796428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
797428d7b3dSmrg              b = (short *)((unsigned long)b + 32);           \
798428d7b3dSmrg            }while(0);
799428d7b3dSmrg
800428d7b3dSmrg#define PACK_CORR_DATA_SHORT(d,block)                \
801428d7b3dSmrg            do {                                     \
802428d7b3dSmrg              short *b = block;                      \
803428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
804428d7b3dSmrg              b = (short *)((unsigned long)b + 32);           \
805428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
806428d7b3dSmrg              b = (short *)((unsigned long)b + 32);           \
807428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
808428d7b3dSmrg              b = (short *)((unsigned long)b + 32);           \
809428d7b3dSmrg              PACK_CORR_DATA(d,b,16);                \
810428d7b3dSmrg              b = (short *)((unsigned long)b + 32);           \
811428d7b3dSmrg            }while(0);
812428d7b3dSmrg
813428d7b3dSmrg/* Lookup tables to speed common calculations */
814428d7b3dSmrgstatic unsigned int drps_table[] = {2<<6,3<<6};
815428d7b3dSmrg
816428d7b3dSmrgstatic unsigned int mvfs_table[] = {
817428d7b3dSmrg  0x12,
818428d7b3dSmrg  0x1a,
819428d7b3dSmrg  0x13,
820428d7b3dSmrg  0x1b
821428d7b3dSmrg};
822428d7b3dSmrg
823428d7b3dSmrgstatic unsigned int type_table[] = {
824428d7b3dSmrg  0x1<<12,   /* This is an error so make it Forward motion */
825428d7b3dSmrg  0x1<<12,
826428d7b3dSmrg  0x1<<12,
827428d7b3dSmrg  0x1<<12,
828428d7b3dSmrg  0x2<<12,
829428d7b3dSmrg  0x2<<12,
830428d7b3dSmrg  0x3<<12,
831428d7b3dSmrg  0x3<<12,
832428d7b3dSmrg  0x1<<12,  /* Pattern but no Motion, Make motion Forward */
833428d7b3dSmrg  0x1<<12,
834428d7b3dSmrg  0x1<<12,
835428d7b3dSmrg  0x1<<12,
836428d7b3dSmrg  0x2<<12,
837428d7b3dSmrg  0x2<<12,
838428d7b3dSmrg  0x3<<12,
839428d7b3dSmrg  0x3<<12
840428d7b3dSmrg};
841428d7b3dSmrg
842428d7b3dSmrgstatic unsigned int y_frame_bytes[] = {
843428d7b3dSmrg  0,0,0,0,128,128,128,128,
844428d7b3dSmrg  128,128,128,128,256,256,256,256,
845428d7b3dSmrg  128,128,128,128,256,256,256,256,
846428d7b3dSmrg  256,256,256,256,384,384,384,384,
847428d7b3dSmrg  128,128,128,128,256,256,256,256,
848428d7b3dSmrg  256,256,256,256,384,384,384,384,
849428d7b3dSmrg  256,256,256,256,384,384,384,384,
850428d7b3dSmrg  384,384,384,384,512,512,512,512
851428d7b3dSmrg};
852428d7b3dSmrg
853428d7b3dSmrgstatic unsigned int u_frame_bytes[] = {
854428d7b3dSmrg  0,0,128,128,0,0,128,128,
855428d7b3dSmrg  0,0,128,128,0,0,128,128,
856428d7b3dSmrg  0,0,128,128,0,0,128,128,
857428d7b3dSmrg  0,0,128,128,0,0,128,128,
858428d7b3dSmrg  0,0,128,128,0,0,128,128,
859428d7b3dSmrg  0,0,128,128,0,0,128,128,
860428d7b3dSmrg  0,0,128,128,0,0,128,128,
861428d7b3dSmrg  0,0,128,128,0,0,128,128
862428d7b3dSmrg};
863428d7b3dSmrg
864428d7b3dSmrgstatic unsigned int v_frame_bytes[] = {
865428d7b3dSmrg  0,128,0,128,0,128,0,128,
866428d7b3dSmrg  0,128,0,128,0,128,0,128,
867428d7b3dSmrg  0,128,0,128,0,128,0,128,
868428d7b3dSmrg  0,128,0,128,0,128,0,128,
869428d7b3dSmrg  0,128,0,128,0,128,0,128,
870428d7b3dSmrg  0,128,0,128,0,128,0,128,
871428d7b3dSmrg  0,128,0,128,0,128,0,128,
872428d7b3dSmrg  0,128,0,128,0,128,0,128
873428d7b3dSmrg};
874428d7b3dSmrg
875428d7b3dSmrgstatic unsigned int y_first_field_bytes[] = {
876428d7b3dSmrg  0,0,0,0,0,0,0,0,
877428d7b3dSmrg  0,0,0,0,0,0,0,0,
878428d7b3dSmrg  128,128,128,128,128,128,128,128,
879428d7b3dSmrg  128,128,128,128,128,128,128,128,
880428d7b3dSmrg  128,128,128,128,128,128,128,128,
881428d7b3dSmrg  128,128,128,128,128,128,128,128,
882428d7b3dSmrg  256,256,256,256,256,256,256,256,
883428d7b3dSmrg  256,256,256,256,256,256,256,256
884428d7b3dSmrg};
885428d7b3dSmrg
886428d7b3dSmrgstatic unsigned int y_second_field_bytes[] = {
887428d7b3dSmrg  0,0,0,0,128,128,128,128,
888428d7b3dSmrg  128,128,128,128,256,256,256,256,
889428d7b3dSmrg  0,0,0,0,128,128,128,128,
890428d7b3dSmrg  128,128,128,128,256,256,256,256,
891428d7b3dSmrg  0,0,0,0,128,128,128,128,
892428d7b3dSmrg  128,128,128,128,256,256,256,256,
893428d7b3dSmrg  0,0,0,0,128,128,128,128,
894428d7b3dSmrg  128,128,128,128,256,256,256,256
895428d7b3dSmrg};
896428d7b3dSmrg
897428d7b3dSmrgstatic unsigned int y_dct0_field_bytes[] = {
898428d7b3dSmrg  0,0,0,0,128,128,128,128,
899428d7b3dSmrg  128,128,128,128,256,256,256,256,
900428d7b3dSmrg  128,128,128,128,128,128,128,128,
901428d7b3dSmrg  256,256,256,256,256,256,256,256,
902428d7b3dSmrg  128,128,128,128,256,256,256,256,
903428d7b3dSmrg  128,128,128,128,256,256,256,256,
904428d7b3dSmrg  256,256,256,256,256,256,256,256,
905428d7b3dSmrg  256,256,256,256,256,256,256,256
906428d7b3dSmrg};
907428d7b3dSmrg
908428d7b3dSmrgstatic unsigned int y_dct1_frame_bytes[] = {
909428d7b3dSmrg  0,0,0,0,256,256,256,256,
910428d7b3dSmrg  256,256,256,256,512,512,512,512,
911428d7b3dSmrg  256,256,256,256,256,256,256,256,
912428d7b3dSmrg  512,512,512,512,512,512,512,512,
913428d7b3dSmrg  256,256,256,256,512,512,512,512,
914428d7b3dSmrg  256,256,256,256,512,512,512,512,
915428d7b3dSmrg  512,512,512,512,512,512,512,512,
916428d7b3dSmrg  512,512,512,512,512,512,512,512
917428d7b3dSmrg};
918428d7b3dSmrg
919428d7b3dSmrgstatic unsigned int u_field_bytes[] = {
920428d7b3dSmrg  0,0,64,64,0,0,64,64,
921428d7b3dSmrg  0,0,64,64,0,0,64,64,
922428d7b3dSmrg  0,0,64,64,0,0,64,64,
923428d7b3dSmrg  0,0,64,64,0,0,64,64,
924428d7b3dSmrg  0,0,64,64,0,0,64,64,
925428d7b3dSmrg  0,0,64,64,0,0,64,64,
926428d7b3dSmrg  0,0,64,64,0,0,64,64,
927428d7b3dSmrg  0,0,64,64,0,0,64,64
928428d7b3dSmrg};
929428d7b3dSmrg
930428d7b3dSmrgstatic unsigned int v_field_bytes[] = {
931428d7b3dSmrg  0,64,0,64,0,64,0,64,
932428d7b3dSmrg  0,64,0,64,0,64,0,64,
933428d7b3dSmrg  0,64,0,64,0,64,0,64,
934428d7b3dSmrg  0,64,0,64,0,64,0,64,
935428d7b3dSmrg  0,64,0,64,0,64,0,64,
936428d7b3dSmrg  0,64,0,64,0,64,0,64,
937428d7b3dSmrg  0,64,0,64,0,64,0,64,
938428d7b3dSmrg  0,64,0,64,0,64,0,64
939428d7b3dSmrg};
940428d7b3dSmrg
941428d7b3dSmrgstatic short empty_block[] = {
942428d7b3dSmrg  0,0,0,0,0,0,0,0,
943428d7b3dSmrg  0,0,0,0,0,0,0,0,
944428d7b3dSmrg  0,0,0,0,0,0,0,0,
945428d7b3dSmrg  0,0,0,0,0,0,0,0,
946428d7b3dSmrg  0,0,0,0,0,0,0,0,
947428d7b3dSmrg  0,0,0,0,0,0,0,0,
948428d7b3dSmrg  0,0,0,0,0,0,0,0,
949428d7b3dSmrg  0,0,0,0,0,0,0,0
950428d7b3dSmrg};
951428d7b3dSmrg
952428d7b3dSmrg
953428d7b3dSmrg/***************************************************************************
954428d7b3dSmrg// Function: dispatchYContext
955428d7b3dSmrg// Description: Allocate a DMA buffer write the Y MC Context info in it,
956428d7b3dSmrg//  and dispatch it to hardware.
957428d7b3dSmrg***************************************************************************/
958428d7b3dSmrg
959428d7b3dSmrgstatic __inline__ void dispatchYContext(i810XvMCSurface *privTarget,
960428d7b3dSmrg					i810XvMCSurface *privPast,
961428d7b3dSmrg					i810XvMCSurface *privFuture,
962428d7b3dSmrg					i810XvMCContext *pI810XvMC) {
963428d7b3dSmrg  uint *data;
964428d7b3dSmrg  drmBufPtr pDMA;
965428d7b3dSmrg  drm_i810_mc_t mc;
966428d7b3dSmrg
967428d7b3dSmrg  pDMA = i810_get_free_buffer(pI810XvMC);
968428d7b3dSmrg  data = pDMA->address;
969428d7b3dSmrg  *data++ = CMD_FLUSH;
970428d7b3dSmrg  *data++ = BOOLEAN_ENA_2;
971428d7b3dSmrg  *data++ = CMD_FLUSH;
972428d7b3dSmrg  *data++ = DEST_BUFFER_INFO;
973428d7b3dSmrg  *data++ = privTarget->dbi1y;
974428d7b3dSmrg  *data++ = DEST_BUFFER_VAR;
975428d7b3dSmrg  *data++ = privTarget->dbv1;
976428d7b3dSmrg  /* Past Surface */
977428d7b3dSmrg  *data++ = CMD_MAP_INFO;
978428d7b3dSmrg  *data++ = privPast->mi1y;
979428d7b3dSmrg  *data++ = privPast->mi2y;
980428d7b3dSmrg  *data++ = privPast->mi3y;
981428d7b3dSmrg  /* Future Surface */
982428d7b3dSmrg  *data++ = CMD_MAP_INFO;
983428d7b3dSmrg  *data++ = privFuture->mi1y | 0x1<<28;
984428d7b3dSmrg  *data++ = privFuture->mi2y;
985428d7b3dSmrg  *data++ = privFuture->mi3y;
986428d7b3dSmrg
987428d7b3dSmrg  mc.idx = pDMA->idx;
988428d7b3dSmrg  mc.used = (unsigned long)data - (unsigned long)pDMA->address;
989428d7b3dSmrg  mc.last_render = ++pI810XvMC->last_render;
990428d7b3dSmrg  privTarget->last_render = pI810XvMC->last_render;
991428d7b3dSmrg  I810_MC(pI810XvMC,mc);
992428d7b3dSmrg}
993428d7b3dSmrg
994428d7b3dSmrgstatic __inline__ void renderError(void) {
995428d7b3dSmrg  printf("Invalid Macroblock Parameters found.\n");
996428d7b3dSmrg  return;
997428d7b3dSmrg}
998428d7b3dSmrg
999428d7b3dSmrg/***************************************************************************
1000428d7b3dSmrg// Function: renderIntrainFrame
1001428d7b3dSmrg// Description: inline function that sets hardware parameters for an Intra
1002428d7b3dSmrg//  encoded macroblock in a Frame picture.
1003428d7b3dSmrg***************************************************************************/
1004428d7b3dSmrgstatic __inline__ void renderIntrainFrame(uint **datay,uint **datau,
1005428d7b3dSmrg					  uint **datav,
1006428d7b3dSmrg					  XvMCMacroBlock *mb,
1007428d7b3dSmrg					  short *block_ptr) {
1008428d7b3dSmrg
1009428d7b3dSmrg  register uint *dy = *datay;
1010428d7b3dSmrg  register uint *du = *datau;
1011428d7b3dSmrg  register uint *dv = *datav;
1012428d7b3dSmrg
1013428d7b3dSmrg  /* Y Blocks */
1014428d7b3dSmrg  *dy++ = GFXBLOCK + 68;
1015428d7b3dSmrg  *dy++ = (1<<30) | (3<<28) | (0xf<<24);
1016428d7b3dSmrg  *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<4);
1017428d7b3dSmrg  *dy++ = (16<<16) | 16;
1018428d7b3dSmrg  *dy++ = 0;
1019428d7b3dSmrg  *dy++ = 0;
1020428d7b3dSmrg  PACK_INTRA_DATA(dy,block_ptr,256);
1021428d7b3dSmrg  dy += 64;
1022428d7b3dSmrg  block_ptr += 256;
1023428d7b3dSmrg  /* End Y Blocks */
1024428d7b3dSmrg
1025428d7b3dSmrg  /* U Block */
1026428d7b3dSmrg  *du++ = GFXBLOCK + 20;
1027428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | (1<<23);
1028428d7b3dSmrg  *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
1029428d7b3dSmrg  *du++ = (8<<16) | 8;
1030428d7b3dSmrg  *du++ = 0;
1031428d7b3dSmrg  *du++ = 0;
1032428d7b3dSmrg  PACK_INTRA_DATA(du,block_ptr,64);
1033428d7b3dSmrg  du += 16;
1034428d7b3dSmrg  block_ptr += 64;
1035428d7b3dSmrg
1036428d7b3dSmrg  /* V Block */
1037428d7b3dSmrg  *dv++ = GFXBLOCK + 20;
1038428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | (1<<22);
1039428d7b3dSmrg  *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
1040428d7b3dSmrg  *dv++ = (8<<16) | 8;
1041428d7b3dSmrg  *dv++ = 0;
1042428d7b3dSmrg  *dv++ = 0;
1043428d7b3dSmrg  PACK_INTRA_DATA(dv,block_ptr,64);
1044428d7b3dSmrg  dv += 16;
1045428d7b3dSmrg  block_ptr += 64;
1046428d7b3dSmrg
1047428d7b3dSmrg  *datay = dy;
1048428d7b3dSmrg  *datau = du;
1049428d7b3dSmrg  *datav = dv;
1050428d7b3dSmrg}
1051428d7b3dSmrg
1052428d7b3dSmrg/***************************************************************************
1053428d7b3dSmrg// Function: renderIntrainFrameDCT1
1054428d7b3dSmrg// Description: inline function that sets hardware parameters for an Intra
1055428d7b3dSmrg//  encoded macroblock in a Frame picture with DCT type 1.
1056428d7b3dSmrg***************************************************************************/
1057428d7b3dSmrgstatic __inline__ void renderIntrainFrameDCT1(uint **datay,uint **datau,
1058428d7b3dSmrg					      uint **datav,XvMCMacroBlock *mb,
1059428d7b3dSmrg					      short *block_ptr,uint flags) {
1060428d7b3dSmrg
1061428d7b3dSmrg  register uint *dy = *datay;
1062428d7b3dSmrg  register uint *du = *datau;
1063428d7b3dSmrg  register uint *dv = *datav;
1064428d7b3dSmrg
1065428d7b3dSmrg
1066428d7b3dSmrg  /* Y Blocks */
1067428d7b3dSmrg  *dy++ = GFXBLOCK + 36;
1068428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x2<<6);
1069428d7b3dSmrg  *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3);
1070428d7b3dSmrg  *dy++ = (8<<16) | 16;
1071428d7b3dSmrg  *dy++ = 0;
1072428d7b3dSmrg  *dy++ = 0;
1073428d7b3dSmrg  PACK_INTRA_DATA(dy,block_ptr,128);
1074428d7b3dSmrg  dy += 32;
1075428d7b3dSmrg  block_ptr += 128;
1076428d7b3dSmrg
1077428d7b3dSmrg  /* Second Y block */
1078428d7b3dSmrg  *dy++ = GFXBLOCK + 36;
1079428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x3<<6);
1080428d7b3dSmrg  *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3);
1081428d7b3dSmrg  *dy++ = (8<<16) | 16;
1082428d7b3dSmrg  *dy++ = 0;
1083428d7b3dSmrg  *dy++ = 0;
1084428d7b3dSmrg  PACK_INTRA_DATA(dy,block_ptr,128);
1085428d7b3dSmrg  dy += 32;
1086428d7b3dSmrg  block_ptr += 128;
1087428d7b3dSmrg  /* End Y Blocks */
1088428d7b3dSmrg
1089428d7b3dSmrg
1090428d7b3dSmrg  /* U Block */
1091428d7b3dSmrg  *du++ = GFXBLOCK + 20;
1092428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | (1<<23);
1093428d7b3dSmrg  *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
1094428d7b3dSmrg  *du++ = (8<<16) | 8;
1095428d7b3dSmrg  *du++ = 0;
1096428d7b3dSmrg  *du++ = 0;
1097428d7b3dSmrg  PACK_INTRA_DATA(du,block_ptr,64);
1098428d7b3dSmrg  du += 16;
1099428d7b3dSmrg  block_ptr += 64;
1100428d7b3dSmrg
1101428d7b3dSmrg  /* V Block */
1102428d7b3dSmrg  *dv++ = GFXBLOCK + 20;
1103428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | (1<<22);
1104428d7b3dSmrg  *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
1105428d7b3dSmrg  *dv++ = (8<<16) | 8;
1106428d7b3dSmrg  *dv++ = 0;
1107428d7b3dSmrg  *dv++ = 0;
1108428d7b3dSmrg  PACK_INTRA_DATA(dv,block_ptr,64);
1109428d7b3dSmrg  dv += 16;
1110428d7b3dSmrg  block_ptr += 64;
1111428d7b3dSmrg
1112428d7b3dSmrg  *datay = dy;
1113428d7b3dSmrg  *datau = du;
1114428d7b3dSmrg  *datav = dv;
1115428d7b3dSmrg}
1116428d7b3dSmrg
1117428d7b3dSmrg
1118428d7b3dSmrg/***************************************************************************
1119428d7b3dSmrg// Function: renderIntrainField
1120428d7b3dSmrg// Description: inline function that sets hardware parameters for an Intra
1121428d7b3dSmrg//  encoded macroblock in Field pictures.
1122428d7b3dSmrg***************************************************************************/
1123428d7b3dSmrgstatic __inline__ void renderIntrainField(uint **datay,uint **datau,
1124428d7b3dSmrg					  uint **datav,
1125428d7b3dSmrg					  XvMCMacroBlock *mb,short *block_ptr,
1126428d7b3dSmrg					  uint ps) {
1127428d7b3dSmrg
1128428d7b3dSmrg  register uint *dy = *datay;
1129428d7b3dSmrg  register uint *du = *datau;
1130428d7b3dSmrg  register uint *dv = *datav;
1131428d7b3dSmrg
1132428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
1133428d7b3dSmrg  uint dw1 = drps_table[~ps & 0x1];
1134428d7b3dSmrg
1135428d7b3dSmrg  /* Y Blocks */
1136428d7b3dSmrg  *dy++ = GFXBLOCK + 68;
1137428d7b3dSmrg  *dy++ = (1<<30) | (3<<28) | (0xf<<24) | dw1;
1138428d7b3dSmrg  *dy++ = xy;
1139428d7b3dSmrg  *dy++ = (16<<16) | 16;
1140428d7b3dSmrg  *dy++ = 0;
1141428d7b3dSmrg  *dy++ = 0;
1142428d7b3dSmrg  PACK_INTRA_DATA(dy,block_ptr,256);
1143428d7b3dSmrg  dy += 64;
1144428d7b3dSmrg  block_ptr += 256;
1145428d7b3dSmrg  /* End Y Blocks */
1146428d7b3dSmrg
1147428d7b3dSmrg  xy >>= 1;
1148428d7b3dSmrg
1149428d7b3dSmrg  /* U Block */
1150428d7b3dSmrg  *du++ = GFXBLOCK + 20;
1151428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | (1<<23) | dw1;
1152428d7b3dSmrg  *du++ = xy;
1153428d7b3dSmrg  *du++ = (8<<16) | 8;
1154428d7b3dSmrg  *du++ = 0;
1155428d7b3dSmrg  *du++ = 0;
1156428d7b3dSmrg  PACK_INTRA_DATA(du,block_ptr,64);
1157428d7b3dSmrg  du += 16;
1158428d7b3dSmrg  block_ptr += 64;
1159428d7b3dSmrg
1160428d7b3dSmrg  /* V Block */
1161428d7b3dSmrg  *dv++ = GFXBLOCK + 20;
1162428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | (1<<22) | dw1;
1163428d7b3dSmrg  *dv++ = xy;
1164428d7b3dSmrg  *dv++ = (8<<16) | 8;
1165428d7b3dSmrg  *dv++ = 0;
1166428d7b3dSmrg  *dv++ = 0;
1167428d7b3dSmrg  PACK_INTRA_DATA(dv,block_ptr,64);
1168428d7b3dSmrg  dv += 16;
1169428d7b3dSmrg  block_ptr += 64;
1170428d7b3dSmrg
1171428d7b3dSmrg  *datay = dy;
1172428d7b3dSmrg  *datau = du;
1173428d7b3dSmrg  *datav = dv;
1174428d7b3dSmrg}
1175428d7b3dSmrg
1176428d7b3dSmrg
1177428d7b3dSmrg/***************************************************************************
1178428d7b3dSmrg// Function: renderFieldinField
1179428d7b3dSmrg// Description: inline function that sets hardware parameters for a Field
1180428d7b3dSmrg//  encoded macroblock in a Field Picture.
1181428d7b3dSmrg***************************************************************************/
1182428d7b3dSmrgstatic __inline__ void renderFieldinField(uint **datay,uint **datau,
1183428d7b3dSmrg					  uint **datav,
1184428d7b3dSmrg					  XvMCMacroBlock *mb,short *block_ptr,
1185428d7b3dSmrg					  uint ps, uint flags) {
1186428d7b3dSmrg
1187428d7b3dSmrg  register uint *dy = *datay;
1188428d7b3dSmrg  register uint *du = *datau;
1189428d7b3dSmrg  register uint *dv = *datav;
1190428d7b3dSmrg
1191428d7b3dSmrg  /* Motion Vectors */
1192428d7b3dSmrg  short fmv[2];
1193428d7b3dSmrg  short bmv[2];
1194428d7b3dSmrg  /* gfxblock dword 1 */
1195428d7b3dSmrg  uint dw1;
1196428d7b3dSmrg
1197428d7b3dSmrg  uint parity = ~ps & XVMC_TOP_FIELD;
1198428d7b3dSmrg
1199428d7b3dSmrg  uint ysize = y_frame_bytes[mb->coded_block_pattern];
1200428d7b3dSmrg  uint usize = u_frame_bytes[mb->coded_block_pattern];
1201428d7b3dSmrg  uint vsize = v_frame_bytes[mb->coded_block_pattern];
1202428d7b3dSmrg
1203428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
1204428d7b3dSmrg
1205428d7b3dSmrg  /* i810 Specific flag used to identify the second field in a P frame */
1206428d7b3dSmrg  if(flags & 0x80000000) {
1207428d7b3dSmrg    /* P Frame */
1208428d7b3dSmrg    if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) ==
1209428d7b3dSmrg      parity) {
1210428d7b3dSmrg      /* Same parity, use reference field (map0) */
1211428d7b3dSmrg      dw1 = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
1212428d7b3dSmrg	(((uint)mb->coded_block_pattern)<<22);
1213428d7b3dSmrg      fmv[0] = mb->PMV[0][0][1];
1214428d7b3dSmrg      fmv[1] = mb->PMV[0][0][0];
1215428d7b3dSmrg      bmv[0] = 0;
1216428d7b3dSmrg      bmv[1] = 0;
1217428d7b3dSmrg    }
1218428d7b3dSmrg    else {
1219428d7b3dSmrg      /*
1220428d7b3dSmrg	Opposite parity, set up as if it were backward
1221428d7b3dSmrg	motion and use map1.
1222428d7b3dSmrg      */
1223428d7b3dSmrg      dw1 = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
1224428d7b3dSmrg	(((uint)mb->coded_block_pattern)<<22);
1225428d7b3dSmrg      bmv[0] = mb->PMV[0][0][1];
1226428d7b3dSmrg      bmv[1] = mb->PMV[0][0][0];
1227428d7b3dSmrg      fmv[0] = 0;
1228428d7b3dSmrg      fmv[1] = 0;
1229428d7b3dSmrg    }
1230428d7b3dSmrg  }
1231428d7b3dSmrg  else {
1232428d7b3dSmrg    dw1 = type_table[mb->macroblock_type & 0xf] |
1233428d7b3dSmrg      drps_table[~ps & 0x1] |
1234428d7b3dSmrg      mvfs_table[mb->motion_vertical_field_select & 3] |
1235428d7b3dSmrg      (((uint)mb->coded_block_pattern)<<22);
1236428d7b3dSmrg
1237428d7b3dSmrg    fmv[0] = mb->PMV[0][0][1];
1238428d7b3dSmrg    fmv[1] = mb->PMV[0][0][0];
1239428d7b3dSmrg
1240428d7b3dSmrg    bmv[0] = mb->PMV[0][1][1];
1241428d7b3dSmrg    bmv[1] = mb->PMV[0][1][0];
1242428d7b3dSmrg  }
1243428d7b3dSmrg
1244428d7b3dSmrg  /* Y Block */
1245428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (ysize>>2);
1246428d7b3dSmrg  *dy++ = (1<<30) | (3<<28) | dw1;
1247428d7b3dSmrg  *dy++ = xy;
1248428d7b3dSmrg  *dy++ = (16<<16) | 16;
1249428d7b3dSmrg  *dy++ = *(uint *)fmv;
1250428d7b3dSmrg  *dy++ = *(uint *)bmv;
1251428d7b3dSmrg  PACK_CORR_DATA(dy,block_ptr,ysize);
1252428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + ysize);
1253428d7b3dSmrg  /* End Y Blocks */
1254428d7b3dSmrg
1255428d7b3dSmrg  fmv[0] /= 2;
1256428d7b3dSmrg  fmv[1] /= 2;
1257428d7b3dSmrg  bmv[0] /= 2;
1258428d7b3dSmrg  bmv[1] /= 2;
1259428d7b3dSmrg  xy >>= 1;
1260428d7b3dSmrg
1261428d7b3dSmrg  /* U Block */
1262428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
1263428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1;
1264428d7b3dSmrg  *du++ = xy;
1265428d7b3dSmrg  *du++ = (8<<16) | 8;
1266428d7b3dSmrg  *du++ = *(uint *)fmv;
1267428d7b3dSmrg  *du++ = *(uint *)bmv;
1268428d7b3dSmrg  PACK_CORR_DATA(du,block_ptr,usize);
1269428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + usize);
1270428d7b3dSmrg
1271428d7b3dSmrg  /* V Block */
1272428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
1273428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1;
1274428d7b3dSmrg  *dv++ = xy;
1275428d7b3dSmrg  *dv++ = (8<<16) | 8;
1276428d7b3dSmrg  *dv++ = *(uint *)fmv;
1277428d7b3dSmrg  *dv++ = *(uint *)bmv;
1278428d7b3dSmrg  PACK_CORR_DATA(dv,block_ptr,vsize);
1279428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + vsize);
1280428d7b3dSmrg
1281428d7b3dSmrg  *datay = dy;
1282428d7b3dSmrg  *datau = du;
1283428d7b3dSmrg  *datav = dv;
1284428d7b3dSmrg}
1285428d7b3dSmrg
1286428d7b3dSmrg/***************************************************************************
1287428d7b3dSmrg// Function: render16x8inField
1288428d7b3dSmrg// Description: inline function that sets hardware parameters for a 16x8
1289428d7b3dSmrg//  encoded macroblock in a field picture.
1290428d7b3dSmrg***************************************************************************/
1291428d7b3dSmrgstatic __inline__ void render16x8inField(uint **datay,uint **datau,
1292428d7b3dSmrg					 uint **datav,
1293428d7b3dSmrg					 XvMCMacroBlock *mb,short *block_ptr,
1294428d7b3dSmrg					 uint ps, uint flags) {
1295428d7b3dSmrg
1296428d7b3dSmrg  register uint *dy = *datay;
1297428d7b3dSmrg  register uint *du = *datau;
1298428d7b3dSmrg  register uint *dv = *datav;
1299428d7b3dSmrg
1300428d7b3dSmrg  /* Motion Vectors */
1301428d7b3dSmrg  short fmv[4];
1302428d7b3dSmrg  short bmv[4];
1303428d7b3dSmrg  /* gfxblock dword 1 */
1304428d7b3dSmrg  uint dw1[2];
1305428d7b3dSmrg
1306428d7b3dSmrg  uint y1size = y_first_field_bytes[mb->coded_block_pattern];
1307428d7b3dSmrg  uint y2size = y_second_field_bytes[mb->coded_block_pattern];
1308428d7b3dSmrg  uint usize = u_field_bytes[mb->coded_block_pattern];
1309428d7b3dSmrg  uint vsize = v_field_bytes[mb->coded_block_pattern];
1310428d7b3dSmrg
1311428d7b3dSmrg  uint parity = ~ps & XVMC_TOP_FIELD;
1312428d7b3dSmrg
1313428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
1314428d7b3dSmrg
1315428d7b3dSmrg  /* i810 Specific flag used to identify the second field in a P frame */
1316428d7b3dSmrg  if(flags & 0x80000000) {
1317428d7b3dSmrg    /* P Frame */
1318428d7b3dSmrg    if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) ==
1319428d7b3dSmrg      parity) {
1320428d7b3dSmrg      /* Same parity, use reference field (map0) */
1321428d7b3dSmrg      dw1[0] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
1322428d7b3dSmrg	(((uint)mb->coded_block_pattern)<<22);
1323428d7b3dSmrg
1324428d7b3dSmrg      fmv[0] = mb->PMV[0][0][1];
1325428d7b3dSmrg      fmv[1] = mb->PMV[0][0][0];
1326428d7b3dSmrg      bmv[0] = 0;
1327428d7b3dSmrg      bmv[1] = 0;
1328428d7b3dSmrg    }
1329428d7b3dSmrg    else {
1330428d7b3dSmrg      /*
1331428d7b3dSmrg	Opposite parity, set up as if it were backward
1332428d7b3dSmrg	motion and use map1.
1333428d7b3dSmrg      */
1334428d7b3dSmrg      dw1[0] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
1335428d7b3dSmrg	(((uint)mb->coded_block_pattern)<<22);
1336428d7b3dSmrg
1337428d7b3dSmrg      bmv[0] = mb->PMV[0][0][1];
1338428d7b3dSmrg      bmv[1] = mb->PMV[0][0][0];
1339428d7b3dSmrg      fmv[0] = 0;
1340428d7b3dSmrg      fmv[1] = 0;
1341428d7b3dSmrg    }
1342428d7b3dSmrg    if((mb->motion_vertical_field_select & XVMC_SELECT_SECOND_FORWARD) ==
1343428d7b3dSmrg       (parity<<2)) {
1344428d7b3dSmrg      /* Same parity, use reference field (map0) */
1345428d7b3dSmrg      dw1[1] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
1346428d7b3dSmrg	((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
1347428d7b3dSmrg	 (((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
1348428d7b3dSmrg
1349428d7b3dSmrg      fmv[2] = mb->PMV[1][0][1];
1350428d7b3dSmrg      fmv[3] = mb->PMV[1][0][0];
1351428d7b3dSmrg      bmv[2] = 0;
1352428d7b3dSmrg      bmv[3] = 0;
1353428d7b3dSmrg    }
1354428d7b3dSmrg    else {
1355428d7b3dSmrg      /*
1356428d7b3dSmrg	 Opposite parity, set up as if it were backward
1357428d7b3dSmrg	 motion and use map1.
1358428d7b3dSmrg      */
1359428d7b3dSmrg      dw1[1] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
1360428d7b3dSmrg	((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
1361428d7b3dSmrg	 (((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
1362428d7b3dSmrg
1363428d7b3dSmrg      bmv[2] = mb->PMV[1][0][1];
1364428d7b3dSmrg      bmv[3] = mb->PMV[1][0][0];
1365428d7b3dSmrg      fmv[2] = 0;
1366428d7b3dSmrg      fmv[3] = 0;
1367428d7b3dSmrg    }
1368428d7b3dSmrg  }
1369428d7b3dSmrg  else {
1370428d7b3dSmrg    dw1[0] = type_table[mb->macroblock_type & 0xf] |
1371428d7b3dSmrg      drps_table[~ps & 0x1] |
1372428d7b3dSmrg      mvfs_table[mb->motion_vertical_field_select & 3] |
1373428d7b3dSmrg      (((uint)mb->coded_block_pattern)<<22);
1374428d7b3dSmrg
1375428d7b3dSmrg    dw1[1] = type_table[mb->macroblock_type & 0xf] |
1376428d7b3dSmrg      drps_table[~ps & 0x1] |
1377428d7b3dSmrg      mvfs_table[(mb->motion_vertical_field_select>>2) & 0x3] |
1378428d7b3dSmrg      ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
1379428d7b3dSmrg       (((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
1380428d7b3dSmrg
1381428d7b3dSmrg    fmv[0] = mb->PMV[0][0][1];
1382428d7b3dSmrg    fmv[1] = mb->PMV[0][0][0];
1383428d7b3dSmrg    fmv[2] = mb->PMV[1][0][1];
1384428d7b3dSmrg    fmv[3] = mb->PMV[1][0][0];
1385428d7b3dSmrg
1386428d7b3dSmrg    bmv[0] = mb->PMV[0][1][1];
1387428d7b3dSmrg    bmv[1] = mb->PMV[0][1][0];
1388428d7b3dSmrg    bmv[2] = mb->PMV[1][1][1];
1389428d7b3dSmrg    bmv[3] = mb->PMV[1][1][0];
1390428d7b3dSmrg  }
1391428d7b3dSmrg
1392428d7b3dSmrg  /* First Y Block */
1393428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (y1size>>2);
1394428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[0];
1395428d7b3dSmrg  *dy++ = xy;
1396428d7b3dSmrg  *dy++ = (8<<16) | 16;
1397428d7b3dSmrg  *dy++ = *(uint *)fmv;
1398428d7b3dSmrg  *dy++ = *(uint *)bmv;
1399428d7b3dSmrg  PACK_CORR_DATA(dy,block_ptr,y1size);
1400428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + y1size);
1401428d7b3dSmrg
1402428d7b3dSmrg  /* Second Y Block */
1403428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (y2size>>2);
1404428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[1];
1405428d7b3dSmrg  *dy++ = (xy + 8);
1406428d7b3dSmrg  *dy++ = (8<<16) | 16;
1407428d7b3dSmrg  *dy++ = *(uint *)&fmv[2];
1408428d7b3dSmrg  *dy++ = *(uint *)&bmv[2];
1409428d7b3dSmrg  PACK_CORR_DATA(dy,block_ptr,y2size);
1410428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + y2size);
1411428d7b3dSmrg  /* End Y Blocks */
1412428d7b3dSmrg
1413428d7b3dSmrg  fmv[0] /= 2;
1414428d7b3dSmrg  fmv[1] /= 2;
1415428d7b3dSmrg  fmv[2] /= 2;
1416428d7b3dSmrg  fmv[3] /= 2;
1417428d7b3dSmrg
1418428d7b3dSmrg  bmv[0] /= 2;
1419428d7b3dSmrg  bmv[1] /= 2;
1420428d7b3dSmrg  bmv[2] /= 2;
1421428d7b3dSmrg  bmv[3] /= 2;
1422428d7b3dSmrg
1423428d7b3dSmrg  xy >>= 1;
1424428d7b3dSmrg
1425428d7b3dSmrg  /* U Blocks */
1426428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
1427428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[0];
1428428d7b3dSmrg  *du++ = xy;
1429428d7b3dSmrg  *du++ = (4<<16) | 8;
1430428d7b3dSmrg  *du++ = *(uint *)fmv;
1431428d7b3dSmrg  *du++ = *(uint *)bmv;
1432428d7b3dSmrg  PACK_CORR_DATA(du,block_ptr,usize);
1433428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + usize);
1434428d7b3dSmrg
1435428d7b3dSmrg  /* Second U block */
1436428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
1437428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[1];
1438428d7b3dSmrg  *du++ = (xy + 4);
1439428d7b3dSmrg  *du++ = (4<<16) | 8;
1440428d7b3dSmrg  *du++ = *(uint *)&fmv[2];
1441428d7b3dSmrg  *du++ = *(uint *)&bmv[2];
1442428d7b3dSmrg  PACK_CORR_DATA(du,block_ptr,usize);
1443428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + usize);
1444428d7b3dSmrg  /* End U Blocks */
1445428d7b3dSmrg
1446428d7b3dSmrg  /* V Blocks */
1447428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
1448428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[0];
1449428d7b3dSmrg  *dv++ = xy;
1450428d7b3dSmrg  *dv++ = (4<<16) | 8;
1451428d7b3dSmrg  *dv++ = *(uint *)fmv;
1452428d7b3dSmrg  *dv++ = *(uint *)bmv;
1453428d7b3dSmrg  PACK_CORR_DATA(dv,block_ptr,vsize);
1454428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + vsize);
1455428d7b3dSmrg
1456428d7b3dSmrg  /* Second V Block */
1457428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
1458428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[1];
1459428d7b3dSmrg  *dv++ = (xy + 4);
1460428d7b3dSmrg  *dv++ = (4<<16) | 8;
1461428d7b3dSmrg  *dv++ = *(uint *)&fmv[2];
1462428d7b3dSmrg  *dv++ = *(uint *)&bmv[2];
1463428d7b3dSmrg  PACK_CORR_DATA(dv,block_ptr,vsize);
1464428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + vsize);
1465428d7b3dSmrg  /* End V Blocks */
1466428d7b3dSmrg
1467428d7b3dSmrg  *datay = dy;
1468428d7b3dSmrg  *datau = du;
1469428d7b3dSmrg  *datav = dv;
1470428d7b3dSmrg}
1471428d7b3dSmrg
1472428d7b3dSmrg/***************************************************************************
1473428d7b3dSmrg// Function: renderDualPrimeinField
1474428d7b3dSmrg// Description: inline function that sets hardware parameters for a Dual
1475428d7b3dSmrg//  prime encoded macroblock in a field picture.
1476428d7b3dSmrg***************************************************************************/
1477428d7b3dSmrgstatic __inline__ void renderDualPrimeinField(uint **datay,uint **datau,
1478428d7b3dSmrg					      uint **datav,XvMCMacroBlock *mb,
1479428d7b3dSmrg					      short *block_ptr,uint ps,
1480428d7b3dSmrg					      uint flags) {
1481428d7b3dSmrg
1482428d7b3dSmrg  register uint *dy = *datay;
1483428d7b3dSmrg  register uint *du = *datau;
1484428d7b3dSmrg  register uint *dv = *datav;
1485428d7b3dSmrg
1486428d7b3dSmrg  /* Motion Vectors */
1487428d7b3dSmrg  short fmv[2];
1488428d7b3dSmrg  short bmv[2];
1489428d7b3dSmrg  /* gfxblock dword 1 */
1490428d7b3dSmrg  uint dw1;
1491428d7b3dSmrg
1492428d7b3dSmrg
1493428d7b3dSmrg  uint ysize = y_frame_bytes[mb->coded_block_pattern];
1494428d7b3dSmrg  uint usize = u_frame_bytes[mb->coded_block_pattern];
1495428d7b3dSmrg  uint vsize = v_frame_bytes[mb->coded_block_pattern];
1496428d7b3dSmrg
1497428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
1498428d7b3dSmrg
1499428d7b3dSmrg
1500428d7b3dSmrg  if(ps & XVMC_TOP_FIELD) {
1501428d7b3dSmrg    dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 2<<6 | 2<<3 | 3;
1502428d7b3dSmrg  }
1503428d7b3dSmrg  else {
1504428d7b3dSmrg    dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 3<<6 | 3<<3 | 2;
1505428d7b3dSmrg  }
1506428d7b3dSmrg  fmv[0] = mb->PMV[0][0][1];
1507428d7b3dSmrg  fmv[1] = mb->PMV[0][0][0];
1508428d7b3dSmrg  bmv[0] = mb->PMV[0][1][1];
1509428d7b3dSmrg  bmv[1] = mb->PMV[0][1][0];
1510428d7b3dSmrg
1511428d7b3dSmrg  /* Y Block */
1512428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (ysize>>2);
1513428d7b3dSmrg  *dy++ = (1<<30) | (3<<28) | dw1;
1514428d7b3dSmrg  *dy++ = xy;
1515428d7b3dSmrg  *dy++ = (16<<16) | 16;
1516428d7b3dSmrg  *dy++ = *(uint *)fmv;
1517428d7b3dSmrg  *dy++ = *(uint *)bmv;
1518428d7b3dSmrg  PACK_CORR_DATA(dy,block_ptr,ysize);
1519428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + ysize);
1520428d7b3dSmrg  /* End Y Blocks */
1521428d7b3dSmrg
1522428d7b3dSmrg  fmv[0] /= 2;
1523428d7b3dSmrg  fmv[1] /= 2;
1524428d7b3dSmrg  bmv[0] /= 2;
1525428d7b3dSmrg  bmv[1] /= 2;
1526428d7b3dSmrg  xy >>= 1;
1527428d7b3dSmrg
1528428d7b3dSmrg  /* U Block */
1529428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
1530428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1;
1531428d7b3dSmrg  *du++ = xy;
1532428d7b3dSmrg  *du++ = (8<<16) | 8;
1533428d7b3dSmrg  *du++ = *(uint *)fmv;
1534428d7b3dSmrg  *du++ = *(uint *)bmv;
1535428d7b3dSmrg  PACK_CORR_DATA(du,block_ptr,usize);
1536428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + usize);
1537428d7b3dSmrg
1538428d7b3dSmrg  /* V Block */
1539428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
1540428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1;
1541428d7b3dSmrg  *dv++ = xy;
1542428d7b3dSmrg  *dv++ = (8<<16) | 8;
1543428d7b3dSmrg  *dv++ = *(uint *)fmv;
1544428d7b3dSmrg  *dv++ = *(uint *)bmv;
1545428d7b3dSmrg  PACK_CORR_DATA(dv,block_ptr,vsize);
1546428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + vsize);
1547428d7b3dSmrg
1548428d7b3dSmrg  *datay = dy;
1549428d7b3dSmrg  *datau = du;
1550428d7b3dSmrg  *datav = dv;
1551428d7b3dSmrg}
1552428d7b3dSmrg
1553428d7b3dSmrg/***************************************************************************
1554428d7b3dSmrg// Function: renderFieldinFrame
1555428d7b3dSmrg// Description: inline function that sets hardware parameters for a Field
1556428d7b3dSmrg//  encoded macroblock in a frame picture.
1557428d7b3dSmrg***************************************************************************/
1558428d7b3dSmrgtypedef union {
1559428d7b3dSmrg  short	s[4];
1560428d7b3dSmrg  uint  u[2];
1561428d7b3dSmrg} su_t;
1562428d7b3dSmrg
1563428d7b3dSmrgstatic __inline__ void renderFieldinFrame(uint **datay,uint **datau,
1564428d7b3dSmrg					  uint **datav,
1565428d7b3dSmrg					  XvMCMacroBlock *mb,short *block_ptr,
1566428d7b3dSmrg					  uint flags) {
1567428d7b3dSmrg
1568428d7b3dSmrg  register uint *dy = *datay;
1569428d7b3dSmrg  register uint *du = *datau;
1570428d7b3dSmrg  register uint *dv = *datav;
1571428d7b3dSmrg
1572428d7b3dSmrg  /* Motion Vectors */
1573428d7b3dSmrg  su_t fmv;
1574428d7b3dSmrg  su_t bmv;
1575428d7b3dSmrg  /* gfxblock dword 1 */
1576428d7b3dSmrg  uint dw1[2];
1577428d7b3dSmrg
1578428d7b3dSmrg  uint y1size = y_first_field_bytes[mb->coded_block_pattern];
1579428d7b3dSmrg  uint y2size = y_second_field_bytes[mb->coded_block_pattern];
1580428d7b3dSmrg  uint usize = u_field_bytes[mb->coded_block_pattern];
1581428d7b3dSmrg  uint vsize = v_field_bytes[mb->coded_block_pattern];
1582428d7b3dSmrg
1583428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
1584428d7b3dSmrg
1585428d7b3dSmrg  dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) |
1586428d7b3dSmrg    mvfs_table[mb->motion_vertical_field_select & 3] |
1587428d7b3dSmrg    (((uint)mb->coded_block_pattern)<<22);
1588428d7b3dSmrg
1589428d7b3dSmrg  dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) |
1590428d7b3dSmrg    mvfs_table[mb->motion_vertical_field_select>>2] |
1591428d7b3dSmrg    (((mb->coded_block_pattern & 0x3) |
1592428d7b3dSmrg      ((mb->coded_block_pattern & 0xc)<<2))<<22);
1593428d7b3dSmrg
1594428d7b3dSmrg  fmv.s[0] = mb->PMV[0][0][1]/2;
1595428d7b3dSmrg  fmv.s[1] = mb->PMV[0][0][0];
1596428d7b3dSmrg  fmv.s[2] = mb->PMV[1][0][1]/2;
1597428d7b3dSmrg  fmv.s[3] = mb->PMV[1][0][0];
1598428d7b3dSmrg
1599428d7b3dSmrg  bmv.s[0] = mb->PMV[0][1][1]/2;
1600428d7b3dSmrg  bmv.s[1] = mb->PMV[0][1][0];
1601428d7b3dSmrg  bmv.s[2] = mb->PMV[1][1][1]/2;
1602428d7b3dSmrg  bmv.s[3] = mb->PMV[1][1][0];
1603428d7b3dSmrg
1604428d7b3dSmrg  /* First Y Block */
1605428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (y1size>>2);
1606428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[0];
1607428d7b3dSmrg  *dy++ = xy;
1608428d7b3dSmrg  *dy++ = (8<<16) | 16;
1609428d7b3dSmrg  *dy++ = fmv.u[0];
1610428d7b3dSmrg  *dy++ = bmv.u[0];
1611428d7b3dSmrg  PACK_CORR_DATA(dy,block_ptr,y1size);
1612428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + y1size);
1613428d7b3dSmrg
1614428d7b3dSmrg  /* Second Y Block */
1615428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (y2size>>2);
1616428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[1];
1617428d7b3dSmrg  *dy++ = xy;
1618428d7b3dSmrg  *dy++ = (8<<16) | 16;
1619428d7b3dSmrg  *dy++ = fmv.u[1];
1620428d7b3dSmrg  *dy++ = bmv.u[1];
1621428d7b3dSmrg  PACK_CORR_DATA(dy,block_ptr,y2size);
1622428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + y2size);
1623428d7b3dSmrg  /* End Y Blocks */
1624428d7b3dSmrg
1625428d7b3dSmrg  fmv.s[0] /= 2;
1626428d7b3dSmrg  fmv.s[1] /= 2;
1627428d7b3dSmrg  fmv.s[2] /= 2;
1628428d7b3dSmrg  fmv.s[3] /= 2;
1629428d7b3dSmrg
1630428d7b3dSmrg  bmv.s[0] /= 2;
1631428d7b3dSmrg  bmv.s[1] /= 2;
1632428d7b3dSmrg  bmv.s[2] /= 2;
1633428d7b3dSmrg  bmv.s[3] /= 2;
1634428d7b3dSmrg
1635428d7b3dSmrg  xy >>= 1;
1636428d7b3dSmrg
1637428d7b3dSmrg  /* U Blocks */
1638428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
1639428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[0];
1640428d7b3dSmrg  *du++ = xy;
1641428d7b3dSmrg  *du++ = (4<<16) | 8;
1642428d7b3dSmrg  *du++ = fmv.u[0];
1643428d7b3dSmrg  *du++ = bmv.u[0];
1644428d7b3dSmrg  if(usize) {
1645428d7b3dSmrg    PACK_CORR_DATA_SHORT(du,block_ptr);
1646428d7b3dSmrg  }
1647428d7b3dSmrg
1648428d7b3dSmrg  /* Second U Block */
1649428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
1650428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[1];
1651428d7b3dSmrg  *du++ = xy;
1652428d7b3dSmrg  *du++ = (4<<16) | 8;
1653428d7b3dSmrg  *du++ = fmv.u[1];
1654428d7b3dSmrg  *du++ = bmv.u[1];
1655428d7b3dSmrg  if(usize) {
1656428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 16);
1657428d7b3dSmrg    PACK_CORR_DATA_SHORT(du,block_ptr);
1658428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 112);
1659428d7b3dSmrg  }
1660428d7b3dSmrg  /* End U Blocks */
1661428d7b3dSmrg
1662428d7b3dSmrg  /* V Blocks */
1663428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
1664428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[0];
1665428d7b3dSmrg  *dv++ = xy;
1666428d7b3dSmrg  *dv++ = (4<<16) | 8;
1667428d7b3dSmrg  *dv++ = fmv.u[0];
1668428d7b3dSmrg  *dv++ = bmv.u[0];
1669428d7b3dSmrg  if(vsize) {
1670428d7b3dSmrg    PACK_CORR_DATA_SHORT(dv,block_ptr);
1671428d7b3dSmrg  }
1672428d7b3dSmrg
1673428d7b3dSmrg  /* Second V Block */
1674428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
1675428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[1];
1676428d7b3dSmrg  *dv++ = xy;
1677428d7b3dSmrg  *dv++ = (4<<16) | 8;
1678428d7b3dSmrg  *dv++ = fmv.u[1];
1679428d7b3dSmrg  *dv++ = bmv.u[1];
1680428d7b3dSmrg  if(vsize) {
1681428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 16);
1682428d7b3dSmrg    PACK_CORR_DATA_SHORT(dv,block_ptr);
1683428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 112);
1684428d7b3dSmrg  }
1685428d7b3dSmrg  /* End V Blocks */
1686428d7b3dSmrg
1687428d7b3dSmrg  *datay = dy;
1688428d7b3dSmrg  *datau = du;
1689428d7b3dSmrg  *datav = dv;
1690428d7b3dSmrg}
1691428d7b3dSmrg
1692428d7b3dSmrg/***************************************************************************
1693428d7b3dSmrg// Function: renderFieldinFrameDCT0
1694428d7b3dSmrg// Description: inline function that sets hardware parameters for a Field
1695428d7b3dSmrg//  encoded macroblock in a frame picture with DCT0.
1696428d7b3dSmrg***************************************************************************/
1697428d7b3dSmrgstatic __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
1698428d7b3dSmrg					      uint **datav,XvMCMacroBlock *mb,
1699428d7b3dSmrg					      short *block_ptr,uint flags) {
1700428d7b3dSmrg
1701428d7b3dSmrg  register uint *dy = *datay;
1702428d7b3dSmrg  register uint *du = *datau;
1703428d7b3dSmrg  register uint *dv = *datav;
1704428d7b3dSmrg
1705428d7b3dSmrg  /* Motion Vectors */
1706428d7b3dSmrg  su_t fmv;
1707428d7b3dSmrg  su_t bmv;
1708428d7b3dSmrg  /* CBP */
1709428d7b3dSmrg  uint cbp = (uint)mb->coded_block_pattern;
1710428d7b3dSmrg  /* gfxblock dword 1 */
1711428d7b3dSmrg  uint dw1[2];
1712428d7b3dSmrg
1713428d7b3dSmrg  short * top_left_b = NULL;
1714428d7b3dSmrg  short * top_right_b = NULL;
1715428d7b3dSmrg  short * bottom_left_b = NULL;
1716428d7b3dSmrg  short * bottom_right_b = NULL;
1717428d7b3dSmrg
1718428d7b3dSmrg  unsigned int ysize = y_dct0_field_bytes[cbp];
1719428d7b3dSmrg  unsigned int usize = u_field_bytes[cbp];
1720428d7b3dSmrg  unsigned int vsize = v_field_bytes[cbp];
1721428d7b3dSmrg
1722428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
1723428d7b3dSmrg
1724428d7b3dSmrg  dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) |
1725428d7b3dSmrg    mvfs_table[mb->motion_vertical_field_select & 3] |
1726428d7b3dSmrg    ((cbp | ((cbp<<2) & 0x30))<<22);
1727428d7b3dSmrg
1728428d7b3dSmrg  dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) |
1729428d7b3dSmrg    mvfs_table[mb->motion_vertical_field_select>>2] |
1730428d7b3dSmrg    ((cbp | ((cbp<<2) & 0x30))<<22);
1731428d7b3dSmrg
1732428d7b3dSmrg
1733428d7b3dSmrg  fmv.s[0] = mb->PMV[0][0][1]/2;
1734428d7b3dSmrg  fmv.s[1] = mb->PMV[0][0][0];
1735428d7b3dSmrg  fmv.s[2] = mb->PMV[1][0][1]/2;
1736428d7b3dSmrg  fmv.s[3] = mb->PMV[1][0][0];
1737428d7b3dSmrg
1738428d7b3dSmrg  bmv.s[0] = mb->PMV[0][1][1]/2;
1739428d7b3dSmrg  bmv.s[1] = mb->PMV[0][1][0];
1740428d7b3dSmrg  bmv.s[2] = mb->PMV[1][1][1]/2;
1741428d7b3dSmrg  bmv.s[3] = mb->PMV[1][1][0];
1742428d7b3dSmrg
1743428d7b3dSmrg  /*
1744428d7b3dSmrg    The i810 cannot use DCT0 directly with field motion, we have to
1745428d7b3dSmrg    interlace the data for it. We use a zero block when the CBP has
1746428d7b3dSmrg    one half of the to-be-interlaced data but not the other half.
1747428d7b3dSmrg  */
1748428d7b3dSmrg  top_left_b = &empty_block[0];
1749428d7b3dSmrg  if(cbp & 0x20) {
1750428d7b3dSmrg    top_left_b = block_ptr;
1751428d7b3dSmrg    block_ptr += 64;
1752428d7b3dSmrg  }
1753428d7b3dSmrg
1754428d7b3dSmrg  top_right_b = &empty_block[0];
1755428d7b3dSmrg  if(cbp & 0x10) {
1756428d7b3dSmrg    top_right_b = block_ptr;
1757428d7b3dSmrg    block_ptr += 64;
1758428d7b3dSmrg  }
1759428d7b3dSmrg
1760428d7b3dSmrg  bottom_left_b = &empty_block[0];
1761428d7b3dSmrg  if(cbp & 0x8) {
1762428d7b3dSmrg    bottom_left_b = block_ptr;
1763428d7b3dSmrg    block_ptr += 64;
1764428d7b3dSmrg  }
1765428d7b3dSmrg
1766428d7b3dSmrg  bottom_right_b = &empty_block[0];
1767428d7b3dSmrg  if(cbp & 0x4) {
1768428d7b3dSmrg    bottom_right_b = block_ptr;
1769428d7b3dSmrg    block_ptr += 64;
1770428d7b3dSmrg  }
1771428d7b3dSmrg
1772428d7b3dSmrg  /* First Y Block */
1773428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (ysize>>2);
1774428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[0];
1775428d7b3dSmrg  *dy++ = xy;
1776428d7b3dSmrg  *dy++ = (8<<16) | 16;
1777428d7b3dSmrg  *dy++ = fmv.u[0];
1778428d7b3dSmrg  *dy++ = bmv.u[0];
1779428d7b3dSmrg  if(dw1[0] & (1<<27)) {
1780428d7b3dSmrg    PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
1781428d7b3dSmrg  }
1782428d7b3dSmrg  if(dw1[0] & (1<<26)) {
1783428d7b3dSmrg    PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
1784428d7b3dSmrg  }
1785428d7b3dSmrg
1786428d7b3dSmrg  /* Second Y Block */
1787428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (ysize>>2);
1788428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[1];
1789428d7b3dSmrg  *dy++ = xy;
1790428d7b3dSmrg  *dy++ = (8<<16) | 16;
1791428d7b3dSmrg  *dy++ = fmv.u[1];
1792428d7b3dSmrg  *dy++ = bmv.u[1];
1793428d7b3dSmrg  if(dw1[1] & (1<<27)) {
1794428d7b3dSmrg    top_left_b = (short *)((unsigned long)top_left_b + 16);
1795428d7b3dSmrg    bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
1796428d7b3dSmrg    PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
1797428d7b3dSmrg  }
1798428d7b3dSmrg  if(dw1[1] & (1<<26)) {
1799428d7b3dSmrg    top_right_b = (short *)((unsigned long)top_right_b + 16);
1800428d7b3dSmrg    bottom_right_b = (short *)((unsigned long)bottom_right_b + 16);
1801428d7b3dSmrg    PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
1802428d7b3dSmrg  }
1803428d7b3dSmrg  /* End Y Blocks */
1804428d7b3dSmrg
1805428d7b3dSmrg  fmv.s[0] /= 2;
1806428d7b3dSmrg  fmv.s[1] /= 2;
1807428d7b3dSmrg  fmv.s[2] /= 2;
1808428d7b3dSmrg  fmv.s[3] /= 2;
1809428d7b3dSmrg
1810428d7b3dSmrg  bmv.s[0] /= 2;
1811428d7b3dSmrg  bmv.s[1] /= 2;
1812428d7b3dSmrg  bmv.s[2] /= 2;
1813428d7b3dSmrg  bmv.s[3] /= 2;
1814428d7b3dSmrg
1815428d7b3dSmrg  xy >>= 1;
1816428d7b3dSmrg
1817428d7b3dSmrg  /* U Blocks */
1818428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
1819428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[0];
1820428d7b3dSmrg  *du++ = xy;
1821428d7b3dSmrg  *du++ = (4<<16) | 8;
1822428d7b3dSmrg  *du++ = fmv.u[0];
1823428d7b3dSmrg  *du++ = bmv.u[0];
1824428d7b3dSmrg  if(usize) {
1825428d7b3dSmrg    PACK_CORR_DATA_SHORT(du,block_ptr);
1826428d7b3dSmrg  }
1827428d7b3dSmrg
1828428d7b3dSmrg  /* Second U Block */
1829428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
1830428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[1];
1831428d7b3dSmrg  *du++ = xy;
1832428d7b3dSmrg  *du++ = (4<<16) | 8;
1833428d7b3dSmrg  *du++ = fmv.u[1];
1834428d7b3dSmrg  *du++ = bmv.u[1];
1835428d7b3dSmrg  if(usize) {
1836428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 16);
1837428d7b3dSmrg    PACK_CORR_DATA_SHORT(du,block_ptr);
1838428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 112);
1839428d7b3dSmrg  }
1840428d7b3dSmrg  /* End U Blocks */
1841428d7b3dSmrg
1842428d7b3dSmrg  /* V Blocks */
1843428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
1844428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[0];
1845428d7b3dSmrg  *dv++ = xy;
1846428d7b3dSmrg  *dv++ = (4<<16) | 8;
1847428d7b3dSmrg  *dv++ = fmv.u[0];
1848428d7b3dSmrg  *dv++ = bmv.u[0];
1849428d7b3dSmrg  if(vsize) {
1850428d7b3dSmrg    PACK_CORR_DATA_SHORT(dv,block_ptr);
1851428d7b3dSmrg  }
1852428d7b3dSmrg
1853428d7b3dSmrg  /* Second V Block */
1854428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
1855428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[1];
1856428d7b3dSmrg  *dv++ = xy;
1857428d7b3dSmrg  *dv++ = (4<<16) | 8;
1858428d7b3dSmrg  *dv++ = fmv.u[1];
1859428d7b3dSmrg  *dv++ = bmv.u[1];
1860428d7b3dSmrg  if(vsize) {
1861428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 16);
1862428d7b3dSmrg    PACK_CORR_DATA_SHORT(dv,block_ptr);
1863428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 112);
1864428d7b3dSmrg  }
1865428d7b3dSmrg  /* End V Blocks */
1866428d7b3dSmrg
1867428d7b3dSmrg  *datay = dy;
1868428d7b3dSmrg  *datau = du;
1869428d7b3dSmrg  *datav = dv;
1870428d7b3dSmrg}
1871428d7b3dSmrg
1872428d7b3dSmrg/***************************************************************************
1873428d7b3dSmrg// Function: renderFrameinFrame
1874428d7b3dSmrg// Description: inline function that sets hardware parameters for a Frame
1875428d7b3dSmrg//  encoded macroblock in a frame picture.
1876428d7b3dSmrg***************************************************************************/
1877428d7b3dSmrgstatic __inline__ void renderFrameinFrame(uint **datay,uint **datau,
1878428d7b3dSmrg					  uint **datav,
1879428d7b3dSmrg					  XvMCMacroBlock *mb,short *block_ptr,
1880428d7b3dSmrg					  uint flags) {
1881428d7b3dSmrg
1882428d7b3dSmrg  register uint *dy = *datay;
1883428d7b3dSmrg  register uint *du = *datau;
1884428d7b3dSmrg  register uint *dv = *datav;
1885428d7b3dSmrg
1886428d7b3dSmrg  /* Motion Vectors */
1887428d7b3dSmrg  su_t fmv;
1888428d7b3dSmrg  su_t bmv;
1889428d7b3dSmrg  /* gfxblock dword 1 */
1890428d7b3dSmrg  uint dw1;
1891428d7b3dSmrg
1892428d7b3dSmrg  unsigned int ysize = y_frame_bytes[mb->coded_block_pattern];
1893428d7b3dSmrg  unsigned int usize = u_frame_bytes[mb->coded_block_pattern];
1894428d7b3dSmrg  unsigned int vsize = v_frame_bytes[mb->coded_block_pattern];
1895428d7b3dSmrg
1896428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
1897428d7b3dSmrg
1898428d7b3dSmrg  dw1 = type_table[mb->macroblock_type & 0xf] |
1899428d7b3dSmrg    (((uint)mb->coded_block_pattern)<<22);
1900428d7b3dSmrg
1901428d7b3dSmrg
1902428d7b3dSmrg  fmv.s[0] = mb->PMV[0][0][1];
1903428d7b3dSmrg  fmv.s[1] = mb->PMV[0][0][0];
1904428d7b3dSmrg
1905428d7b3dSmrg  bmv.s[0] = mb->PMV[0][1][1];
1906428d7b3dSmrg  bmv.s[1] = mb->PMV[0][1][0];
1907428d7b3dSmrg
1908428d7b3dSmrg  /* Y Block */
1909428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (ysize>>2);
1910428d7b3dSmrg  *dy++ = (1<<30) | (3<<28) | dw1;
1911428d7b3dSmrg  *dy++ = xy;
1912428d7b3dSmrg  *dy++ = (16<<16) | 16;
1913428d7b3dSmrg  *dy++ = fmv.u[0];
1914428d7b3dSmrg  *dy++ = bmv.u[0];
1915428d7b3dSmrg  PACK_CORR_DATA(dy,block_ptr,ysize);
1916428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + ysize);
1917428d7b3dSmrg  /* End Y Blocks */
1918428d7b3dSmrg
1919428d7b3dSmrg  fmv.s[0] /= 2;
1920428d7b3dSmrg  fmv.s[1] /= 2;
1921428d7b3dSmrg
1922428d7b3dSmrg  bmv.s[0] /= 2;
1923428d7b3dSmrg  bmv.s[1] /= 2;
1924428d7b3dSmrg
1925428d7b3dSmrg  xy >>= 1;
1926428d7b3dSmrg
1927428d7b3dSmrg  /* U Block */
1928428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
1929428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1;
1930428d7b3dSmrg  *du++ = xy;
1931428d7b3dSmrg  *du++ = (8<<16) | 8;
1932428d7b3dSmrg  *du++ = fmv.u[0];
1933428d7b3dSmrg  *du++ = bmv.u[0];
1934428d7b3dSmrg  PACK_CORR_DATA(du,block_ptr,usize);
1935428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + usize);
1936428d7b3dSmrg  /* End U Block */
1937428d7b3dSmrg
1938428d7b3dSmrg  /* V Block */
1939428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
1940428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1;
1941428d7b3dSmrg  *dv++ = xy;
1942428d7b3dSmrg  *dv++ = (8<<16) | 8;
1943428d7b3dSmrg  *dv++ = fmv.u[0];
1944428d7b3dSmrg  *dv++ = bmv.u[0];
1945428d7b3dSmrg  PACK_CORR_DATA(dv,block_ptr,vsize);
1946428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + vsize);
1947428d7b3dSmrg  /* End V Block */
1948428d7b3dSmrg
1949428d7b3dSmrg  *datay = dy;
1950428d7b3dSmrg  *datau = du;
1951428d7b3dSmrg  *datav = dv;
1952428d7b3dSmrg}
1953428d7b3dSmrg
1954428d7b3dSmrg/***************************************************************************
1955428d7b3dSmrg// Function: renderFrameinFrameDCT1
1956428d7b3dSmrg// Description: inline function that sets hardware parameters for a Frame
1957428d7b3dSmrg//  encoded macroblock in a frame picture with DCT type 1.
1958428d7b3dSmrg***************************************************************************/
1959428d7b3dSmrgstatic __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
1960428d7b3dSmrg					      uint **datav,XvMCMacroBlock *mb,
1961428d7b3dSmrg					      short *block_ptr,uint flags) {
1962428d7b3dSmrg
1963428d7b3dSmrg  register uint *dy = *datay;
1964428d7b3dSmrg  register uint *du = *datau;
1965428d7b3dSmrg  register uint *dv = *datav;
1966428d7b3dSmrg
1967428d7b3dSmrg  /* Motion Vectors */
1968428d7b3dSmrg  su_t fmv;
1969428d7b3dSmrg  su_t bmv;
1970428d7b3dSmrg
1971428d7b3dSmrg  short * top_left_b = NULL;
1972428d7b3dSmrg  short * top_right_b = NULL;
1973428d7b3dSmrg  short * bottom_left_b = NULL;
1974428d7b3dSmrg  short * bottom_right_b = NULL;
1975428d7b3dSmrg
1976428d7b3dSmrg  uint temp_bp = 0;
1977428d7b3dSmrg
1978428d7b3dSmrg  uint ysize = y_dct1_frame_bytes[mb->coded_block_pattern];
1979428d7b3dSmrg  uint usize = u_frame_bytes[mb->coded_block_pattern];
1980428d7b3dSmrg  uint vsize = v_frame_bytes[mb->coded_block_pattern];
1981428d7b3dSmrg
1982428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
1983428d7b3dSmrg
1984428d7b3dSmrg  uint dw1 = type_table[mb->macroblock_type & 0xf] |
1985428d7b3dSmrg    (((uint)mb->coded_block_pattern)<<22);
1986428d7b3dSmrg
1987428d7b3dSmrg  fmv.s[0] = mb->PMV[0][0][1];
1988428d7b3dSmrg  fmv.s[1] = mb->PMV[0][0][0];
1989428d7b3dSmrg
1990428d7b3dSmrg  bmv.s[0] = mb->PMV[0][1][1];
1991428d7b3dSmrg  bmv.s[1] = mb->PMV[0][1][0];
1992428d7b3dSmrg
1993428d7b3dSmrg  /*
1994428d7b3dSmrg    It is easiest to find out what blocks are in need of reading first
1995428d7b3dSmrg    rather than as we go.
1996428d7b3dSmrg  */
1997428d7b3dSmrg  top_left_b = &empty_block[0];
1998428d7b3dSmrg  if(dw1 & (1<<27)) {
1999428d7b3dSmrg    temp_bp |= (1<<25);
2000428d7b3dSmrg    top_left_b = block_ptr;
2001428d7b3dSmrg    block_ptr += 64;
2002428d7b3dSmrg  }
2003428d7b3dSmrg
2004428d7b3dSmrg  top_right_b = &empty_block[0];
2005428d7b3dSmrg  if(dw1 & (1<<26)) {
2006428d7b3dSmrg    temp_bp |= (1<<24);
2007428d7b3dSmrg    top_right_b = block_ptr;
2008428d7b3dSmrg    block_ptr += 64;
2009428d7b3dSmrg  }
2010428d7b3dSmrg
2011428d7b3dSmrg  bottom_left_b = &empty_block[0];
2012428d7b3dSmrg  if(dw1 & (1<<25)) {
2013428d7b3dSmrg    temp_bp |= (1<<27);
2014428d7b3dSmrg    bottom_left_b = block_ptr;
2015428d7b3dSmrg    block_ptr += 64;
2016428d7b3dSmrg  }
2017428d7b3dSmrg
2018428d7b3dSmrg  bottom_right_b = &empty_block[0];
2019428d7b3dSmrg  if(dw1 & (1<<24)) {
2020428d7b3dSmrg    temp_bp |= (1<<26);
2021428d7b3dSmrg    bottom_right_b = block_ptr;
2022428d7b3dSmrg    block_ptr += 64;
2023428d7b3dSmrg  }
2024428d7b3dSmrg  dw1 |= temp_bp;
2025428d7b3dSmrg
2026428d7b3dSmrg  /* Y Block */
2027428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (ysize>>2);
2028428d7b3dSmrg  *dy++ = (1<<30) | (3<<28) | dw1;
2029428d7b3dSmrg  *dy++ = xy;
2030428d7b3dSmrg  *dy++ = (16<<16) | 16;
2031428d7b3dSmrg  *dy++ = fmv.u[0];
2032428d7b3dSmrg  *dy++ = bmv.u[0];
2033428d7b3dSmrg  if(dw1 & (1<<27)) {
2034428d7b3dSmrg    PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
2035428d7b3dSmrg    top_left_b = (short *)((unsigned long)top_left_b + 64);
2036428d7b3dSmrg    bottom_left_b = (short *)((unsigned long)bottom_left_b + 64);
2037428d7b3dSmrg  }
2038428d7b3dSmrg  if(dw1 & (1<<26)) {
2039428d7b3dSmrg    PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b);
2040428d7b3dSmrg    top_right_b = (short *)((unsigned long)top_right_b + 64);
2041428d7b3dSmrg    bottom_right_b = (short *)((unsigned long)bottom_right_b + 64);
2042428d7b3dSmrg  }
2043428d7b3dSmrg  if(dw1 & (1<<27)) {
2044428d7b3dSmrg    PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
2045428d7b3dSmrg  }
2046428d7b3dSmrg  if(dw1 & (1<<26)) {
2047428d7b3dSmrg    PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b);
2048428d7b3dSmrg  }
2049428d7b3dSmrg  /* End Y Block */
2050428d7b3dSmrg
2051428d7b3dSmrg  fmv.s[0] /= 2;
2052428d7b3dSmrg  fmv.s[1] /= 2;
2053428d7b3dSmrg
2054428d7b3dSmrg  bmv.s[0] /= 2;
2055428d7b3dSmrg  bmv.s[1] /= 2;
2056428d7b3dSmrg
2057428d7b3dSmrg  xy >>= 1;
2058428d7b3dSmrg
2059428d7b3dSmrg  /* U Block */
2060428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
2061428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1;
2062428d7b3dSmrg  *du++ = xy;
2063428d7b3dSmrg  *du++ = (8<<16) | 8;
2064428d7b3dSmrg  *du++ = fmv.u[0];
2065428d7b3dSmrg  *du++ = bmv.u[0];
2066428d7b3dSmrg  PACK_CORR_DATA(du,block_ptr,usize);
2067428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + usize);
2068428d7b3dSmrg
2069428d7b3dSmrg  /* V Block */
2070428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
2071428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1;
2072428d7b3dSmrg  *dv++ = xy;
2073428d7b3dSmrg  *dv++ = (8<<16) | 8;
2074428d7b3dSmrg  *dv++ = fmv.u[0];
2075428d7b3dSmrg  *dv++ = bmv.u[0];
2076428d7b3dSmrg  PACK_CORR_DATA(dv,block_ptr,vsize);
2077428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + vsize);
2078428d7b3dSmrg
2079428d7b3dSmrg  *datay = dy;
2080428d7b3dSmrg  *datau = du;
2081428d7b3dSmrg  *datav = dv;
2082428d7b3dSmrg}
2083428d7b3dSmrg
2084428d7b3dSmrg/***************************************************************************
2085428d7b3dSmrg// Function: renderDualPrimeinFrame
2086428d7b3dSmrg// Description: inline function that sets hardware parameters for a Dual
2087428d7b3dSmrg//  Prime encoded macroblock in a frame picture with dct 1.
2088428d7b3dSmrg***************************************************************************/
2089428d7b3dSmrgstatic __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
2090428d7b3dSmrg					      uint **datav,XvMCMacroBlock *mb,
2091428d7b3dSmrg					      short *block_ptr,uint flags) {
2092428d7b3dSmrg
2093428d7b3dSmrg  register uint *dy = *datay;
2094428d7b3dSmrg  register uint *du = *datau;
2095428d7b3dSmrg  register uint *dv = *datav;
2096428d7b3dSmrg
2097428d7b3dSmrg  /* Motion Vectors */
2098428d7b3dSmrg  su_t fmv;
2099428d7b3dSmrg  su_t bmv;
2100428d7b3dSmrg  /* gfxblock dword 1 */
2101428d7b3dSmrg  uint dw1[2];
2102428d7b3dSmrg
2103428d7b3dSmrg  uint y1size = y_first_field_bytes[mb->coded_block_pattern];
2104428d7b3dSmrg  uint y2size = y_second_field_bytes[mb->coded_block_pattern];
2105428d7b3dSmrg  uint usize = u_field_bytes[mb->coded_block_pattern];
2106428d7b3dSmrg  uint vsize = v_field_bytes[mb->coded_block_pattern];
2107428d7b3dSmrg
2108428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
2109428d7b3dSmrg
2110428d7b3dSmrg  /*
2111428d7b3dSmrg    Past Surface (map 0) is used for same parity prediction,
2112428d7b3dSmrg    Future surface (map 1) is used for opposite.
2113428d7b3dSmrg  */
2114428d7b3dSmrg  dw1[0] = (((uint)mb->coded_block_pattern)<<22) |
2115428d7b3dSmrg    3<<12 | 2<<6 | 2<<3 | 3;
2116428d7b3dSmrg  dw1[1] = (((mb->coded_block_pattern & 0x3) |
2117428d7b3dSmrg	     ((mb->coded_block_pattern & 0xc)<<2))<<22) |
2118428d7b3dSmrg    3<<12 | 3<<6 | 3<<3 | 2;
2119428d7b3dSmrg
2120428d7b3dSmrg  fmv.s[0] = mb->PMV[0][0][1];
2121428d7b3dSmrg  fmv.s[1] = mb->PMV[0][0][0];
2122428d7b3dSmrg  bmv.s[0] = mb->PMV[1][0][1];
2123428d7b3dSmrg  bmv.s[1] = mb->PMV[1][0][0];
2124428d7b3dSmrg
2125428d7b3dSmrg  fmv.s[2] = mb->PMV[0][0][1];
2126428d7b3dSmrg  fmv.s[3] = mb->PMV[0][0][0];
2127428d7b3dSmrg  bmv.s[2] = mb->PMV[1][1][1];
2128428d7b3dSmrg  bmv.s[3] = mb->PMV[1][1][0];
2129428d7b3dSmrg
2130428d7b3dSmrg  /* First Y Block */
2131428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (y1size>>2);
2132428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[0];
2133428d7b3dSmrg  *dy++ = xy;
2134428d7b3dSmrg  *dy++ = (8<<16) | 16;
2135428d7b3dSmrg  *dy++ = fmv.u[0];
2136428d7b3dSmrg  *dy++ = bmv.u[0];;
2137428d7b3dSmrg  PACK_CORR_DATA(dy,block_ptr,y1size);
2138428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + y1size);
2139428d7b3dSmrg
2140428d7b3dSmrg  /* Second Y Block */
2141428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (y2size>>2);
2142428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[1];
2143428d7b3dSmrg  *dy++ = xy;
2144428d7b3dSmrg  *dy++ = (8<<16) | 16;
2145428d7b3dSmrg  *dy++ = fmv.u[1];
2146428d7b3dSmrg  *dy++ = bmv.u[1];
2147428d7b3dSmrg  PACK_CORR_DATA(dy,block_ptr,y2size);
2148428d7b3dSmrg  block_ptr = (short *)((unsigned long)block_ptr + y2size);
2149428d7b3dSmrg
2150428d7b3dSmrg  fmv.s[0] /= 2;
2151428d7b3dSmrg  fmv.s[1] /= 2;
2152428d7b3dSmrg  bmv.s[0] /= 2;
2153428d7b3dSmrg  bmv.s[1] /= 2;
2154428d7b3dSmrg
2155428d7b3dSmrg  fmv.s[2] /= 2;
2156428d7b3dSmrg  fmv.s[3] /= 2;
2157428d7b3dSmrg  bmv.s[2] /= 2;
2158428d7b3dSmrg  bmv.s[3] /= 2;
2159428d7b3dSmrg
2160428d7b3dSmrg  xy >>= 1;
2161428d7b3dSmrg
2162428d7b3dSmrg  /* U Blocks */
2163428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
2164428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[0];
2165428d7b3dSmrg  *du++ = xy;
2166428d7b3dSmrg  *du++ = (4<<16) | 8;
2167428d7b3dSmrg  *du++ = fmv.u[0];
2168428d7b3dSmrg  *du++ = bmv.u[0];
2169428d7b3dSmrg  if(dw1[0] & (1<<23)) {
2170428d7b3dSmrg    PACK_CORR_DATA_SHORT(du,block_ptr);
2171428d7b3dSmrg  }
2172428d7b3dSmrg
2173428d7b3dSmrg  /* Second U Block */
2174428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
2175428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[1];
2176428d7b3dSmrg  *du++ = xy;
2177428d7b3dSmrg  *du++ = (4<<16) | 8;
2178428d7b3dSmrg  *du++ = fmv.u[1];
2179428d7b3dSmrg  *du++ = bmv.u[1];
2180428d7b3dSmrg  if(dw1[1] & (1<<23)) {
2181428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 16);
2182428d7b3dSmrg    PACK_CORR_DATA_SHORT(du,block_ptr);
2183428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 112);
2184428d7b3dSmrg  }
2185428d7b3dSmrg  /* End U Blocks */
2186428d7b3dSmrg
2187428d7b3dSmrg  /* V Blocks */
2188428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
2189428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[0];
2190428d7b3dSmrg  *dv++ = xy;
2191428d7b3dSmrg  *dv++ = (4<<16) | 8;
2192428d7b3dSmrg  *dv++ = fmv.u[0];
2193428d7b3dSmrg  *dv++ = bmv.u[0];
2194428d7b3dSmrg  if(dw1[0] & (1<<22)) {
2195428d7b3dSmrg    PACK_CORR_DATA_SHORT(dv,block_ptr);
2196428d7b3dSmrg  }
2197428d7b3dSmrg
2198428d7b3dSmrg  /* Second V Block */
2199428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
2200428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[1];
2201428d7b3dSmrg  *dv++ = xy;
2202428d7b3dSmrg  *dv++ = (4<<16) | 8;
2203428d7b3dSmrg  *dv++ = fmv.u[1];
2204428d7b3dSmrg  *dv++ = bmv.u[1];
2205428d7b3dSmrg  if(dw1[1] & (1<<22)) {
2206428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 16);
2207428d7b3dSmrg    PACK_CORR_DATA_SHORT(dv,block_ptr);
2208428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 112);
2209428d7b3dSmrg  }
2210428d7b3dSmrg  /* End V Blocks */
2211428d7b3dSmrg
2212428d7b3dSmrg  *datay = dy;
2213428d7b3dSmrg  *datau = du;
2214428d7b3dSmrg  *datav = dv;
2215428d7b3dSmrg}
2216428d7b3dSmrg
2217428d7b3dSmrg/***************************************************************************
2218428d7b3dSmrg// Function: renderDualPrimeinFrameDCT0
2219428d7b3dSmrg// Description: inline function that sets hardware parameters for a Dual
2220428d7b3dSmrg//  Prime encoded macroblock in a frame picture with dct 0.
2221428d7b3dSmrg***************************************************************************/
2222428d7b3dSmrgstatic __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
2223428d7b3dSmrg						  uint **datav,
2224428d7b3dSmrg						  XvMCMacroBlock *mb,
2225428d7b3dSmrg						  short *block_ptr,
2226428d7b3dSmrg						  uint flags) {
2227428d7b3dSmrg
2228428d7b3dSmrg  register uint *dy = *datay;
2229428d7b3dSmrg  register uint *du = *datau;
2230428d7b3dSmrg  register uint *dv = *datav;
2231428d7b3dSmrg
2232428d7b3dSmrg  /* Motion Vectors */
2233428d7b3dSmrg  su_t fmv;
2234428d7b3dSmrg  su_t bmv;
2235428d7b3dSmrg  /* gfxblock dword 1 */
2236428d7b3dSmrg  uint dw1[2];
2237428d7b3dSmrg
2238428d7b3dSmrg  short * top_left_b = NULL;
2239428d7b3dSmrg  short * top_right_b = NULL;
2240428d7b3dSmrg  short * bottom_left_b = NULL;
2241428d7b3dSmrg  short * bottom_right_b = NULL;
2242428d7b3dSmrg
2243428d7b3dSmrg  uint cbp = (uint)mb->coded_block_pattern;
2244428d7b3dSmrg
2245428d7b3dSmrg  uint ysize = y_dct0_field_bytes[cbp];
2246428d7b3dSmrg  uint usize = u_field_bytes[cbp];
2247428d7b3dSmrg  uint vsize = v_field_bytes[cbp];
2248428d7b3dSmrg
2249428d7b3dSmrg  uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
2250428d7b3dSmrg
2251428d7b3dSmrg  /*
2252428d7b3dSmrg    Past Surface (map 0) is used for same parity prediction,
2253428d7b3dSmrg    Future surface (map 1) is used for opposite.
2254428d7b3dSmrg  */
2255428d7b3dSmrg  dw1[0] = ((cbp | ((cbp<<2) & 0x30))<<22) |
2256428d7b3dSmrg    3<<12 | 2<<6 | 2<<3 | 3;
2257428d7b3dSmrg  dw1[1] = ((cbp | ((cbp<<2) & 0x30))<<22) |
2258428d7b3dSmrg    3<<12 | 3<<6 | 3<<3 | 2;
2259428d7b3dSmrg
2260428d7b3dSmrg  fmv.s[0] = mb->PMV[0][0][1];
2261428d7b3dSmrg  fmv.s[1] = mb->PMV[0][0][0];
2262428d7b3dSmrg  bmv.s[0] = mb->PMV[1][0][1];
2263428d7b3dSmrg  bmv.s[1] = mb->PMV[1][0][0];
2264428d7b3dSmrg
2265428d7b3dSmrg  fmv.s[2] = mb->PMV[0][0][1];
2266428d7b3dSmrg  fmv.s[3] = mb->PMV[0][0][0];
2267428d7b3dSmrg  bmv.s[2] = mb->PMV[1][1][1];
2268428d7b3dSmrg  bmv.s[3] = mb->PMV[1][1][0];
2269428d7b3dSmrg
2270428d7b3dSmrg  /*
2271428d7b3dSmrg    The i810 cannot use DCT0 directly with field motion, we have to
2272428d7b3dSmrg    interlace the data for it. We use a zero block when the CBP has
2273428d7b3dSmrg    one half of the to-be-interlaced data but not the other half.
2274428d7b3dSmrg  */
2275428d7b3dSmrg  top_left_b = &empty_block[0];
2276428d7b3dSmrg  if(cbp & 0x20) {
2277428d7b3dSmrg    top_left_b = block_ptr;
2278428d7b3dSmrg    block_ptr += 64;
2279428d7b3dSmrg  }
2280428d7b3dSmrg
2281428d7b3dSmrg  top_right_b = &empty_block[0];
2282428d7b3dSmrg  if(cbp & 0x10) {
2283428d7b3dSmrg    top_right_b = block_ptr;
2284428d7b3dSmrg    block_ptr += 64;
2285428d7b3dSmrg  }
2286428d7b3dSmrg
2287428d7b3dSmrg  bottom_left_b = &empty_block[0];
2288428d7b3dSmrg  if(cbp & 0x8) {
2289428d7b3dSmrg    bottom_left_b = block_ptr;
2290428d7b3dSmrg    block_ptr += 64;
2291428d7b3dSmrg  }
2292428d7b3dSmrg
2293428d7b3dSmrg  bottom_right_b = &empty_block[0];
2294428d7b3dSmrg  if(cbp & 0x4) {
2295428d7b3dSmrg    bottom_right_b = block_ptr;
2296428d7b3dSmrg    block_ptr += 64;
2297428d7b3dSmrg  }
2298428d7b3dSmrg
2299428d7b3dSmrg  /* First Y Block */
2300428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (ysize>>2);
2301428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[0];
2302428d7b3dSmrg  *dy++ = xy;
2303428d7b3dSmrg  *dy++ = (8<<16) | 16;
2304428d7b3dSmrg  *dy++ = fmv.u[0];
2305428d7b3dSmrg  *dy++ = bmv.u[0];
2306428d7b3dSmrg  if(cbp & 0x20) {
2307428d7b3dSmrg    PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
2308428d7b3dSmrg  }
2309428d7b3dSmrg  if(cbp & 0x10) {
2310428d7b3dSmrg    PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
2311428d7b3dSmrg  }
2312428d7b3dSmrg
2313428d7b3dSmrg  /* Second Y Block */
2314428d7b3dSmrg  *dy++ = GFXBLOCK + 4 + (ysize>>2);
2315428d7b3dSmrg  *dy++ = (1<<30) | (2<<28) | dw1[1];
2316428d7b3dSmrg  *dy++ = xy;
2317428d7b3dSmrg  *dy++ = (8<<16) | 16;
2318428d7b3dSmrg  *dy++ = fmv.u[1];
2319428d7b3dSmrg  *dy++ = bmv.u[1];
2320428d7b3dSmrg  if(cbp & 0x20) {
2321428d7b3dSmrg    top_left_b = (short *)((unsigned long)top_left_b + 16);
2322428d7b3dSmrg    bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
2323428d7b3dSmrg    PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
2324428d7b3dSmrg  }
2325428d7b3dSmrg  if(cbp & 0x10) {
2326428d7b3dSmrg    top_right_b = (short *)((unsigned long)top_right_b + 16);
2327428d7b3dSmrg    bottom_right_b = (short *)((unsigned long)bottom_right_b + 16);
2328428d7b3dSmrg    PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
2329428d7b3dSmrg  }
2330428d7b3dSmrg  /* End Y Blocks */
2331428d7b3dSmrg
2332428d7b3dSmrg
2333428d7b3dSmrg  fmv.s[0] /= 2;
2334428d7b3dSmrg  fmv.s[1] /= 2;
2335428d7b3dSmrg  bmv.s[0] /= 2;
2336428d7b3dSmrg  bmv.s[1] /= 2;
2337428d7b3dSmrg
2338428d7b3dSmrg  fmv.s[2] /= 2;
2339428d7b3dSmrg  fmv.s[3] /= 2;
2340428d7b3dSmrg  bmv.s[2] /= 2;
2341428d7b3dSmrg  bmv.s[3] /= 2;
2342428d7b3dSmrg
2343428d7b3dSmrg  xy >>= 1;
2344428d7b3dSmrg
2345428d7b3dSmrg  /* U Blocks */
2346428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
2347428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[0];
2348428d7b3dSmrg  *du++ = xy;
2349428d7b3dSmrg  *du++ = (4<<16) | 8;
2350428d7b3dSmrg  *du++ = fmv.u[0];
2351428d7b3dSmrg  *du++ = bmv.u[0];
2352428d7b3dSmrg  if(cbp & (1<<23)) {
2353428d7b3dSmrg    PACK_CORR_DATA_SHORT(du,block_ptr);
2354428d7b3dSmrg  }
2355428d7b3dSmrg
2356428d7b3dSmrg  /* Second U Block */
2357428d7b3dSmrg  *du++ = GFXBLOCK + 4 + (usize>>2);
2358428d7b3dSmrg  *du++ = (2<<30) | (1<<28) | dw1[1];
2359428d7b3dSmrg  *du++ = xy;
2360428d7b3dSmrg  *du++ = (4<<16) | 8;
2361428d7b3dSmrg  *du++ = fmv.u[1];
2362428d7b3dSmrg  *du++ = bmv.u[1];
2363428d7b3dSmrg  if(cbp & (1<<23)) {
2364428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 16);
2365428d7b3dSmrg    PACK_CORR_DATA_SHORT(du,block_ptr);
2366428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 112);
2367428d7b3dSmrg  }
2368428d7b3dSmrg  /* End U Blocks */
2369428d7b3dSmrg
2370428d7b3dSmrg  /* V Blocks */
2371428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
2372428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[0];
2373428d7b3dSmrg  *dv++ = xy;
2374428d7b3dSmrg  *dv++ = (4<<16) | 8;
2375428d7b3dSmrg  *dv++ = fmv.u[0];
2376428d7b3dSmrg  *dv++ = bmv.u[0];
2377428d7b3dSmrg  if(cbp & (1<<22)) {
2378428d7b3dSmrg    PACK_CORR_DATA_SHORT(dv,block_ptr);
2379428d7b3dSmrg  }
2380428d7b3dSmrg
2381428d7b3dSmrg  /* Second V Block */
2382428d7b3dSmrg  *dv++ = GFXBLOCK + 4 + (vsize>>2);
2383428d7b3dSmrg  *dv++ = (3<<30) | (1<<28) | dw1[1];
2384428d7b3dSmrg  *dv++ = xy;
2385428d7b3dSmrg  *dv++ = (4<<16) | 8;
2386428d7b3dSmrg  *dv++ = fmv.u[1];
2387428d7b3dSmrg  *dv++ = bmv.u[1];
2388428d7b3dSmrg  if(cbp & (1<<22)) {
2389428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 16);
2390428d7b3dSmrg    PACK_CORR_DATA_SHORT(dv,block_ptr);
2391428d7b3dSmrg    block_ptr = (short *)((unsigned long)block_ptr + 112);
2392428d7b3dSmrg  }
2393428d7b3dSmrg  /* End V Blocks */
2394428d7b3dSmrg
2395428d7b3dSmrg  *datay = dy;
2396428d7b3dSmrg  *datau = du;
2397428d7b3dSmrg  *datav = dv;
2398428d7b3dSmrg}
2399428d7b3dSmrg
2400428d7b3dSmrg
2401428d7b3dSmrg/***************************************************************************
2402428d7b3dSmrg// Function: XvMCRenderSurface
2403428d7b3dSmrg// Description: This function does the actual HWMC. Given a list of
2404428d7b3dSmrg//  macroblock structures it dispatched the hardware commands to execute
2405428d7b3dSmrg//  them. DMA buffer containing Y data are dispatched as they fill up
2406428d7b3dSmrg//  U and V DMA buffers are queued until all Y's are done. This minimizes
2407428d7b3dSmrg//  the context flipping and flushing required when switching between Y
2408428d7b3dSmrg//  U and V surfaces.
2409428d7b3dSmrg***************************************************************************/
2410428d7b3dSmrg#define UV_QUEUE 14
2411428d7b3dSmrg_X_EXPORT Status XvMCRenderSurface(Display *display, XvMCContext *context,
2412428d7b3dSmrg			 unsigned int picture_structure,
2413428d7b3dSmrg			 XvMCSurface *target_surface,
2414428d7b3dSmrg			 XvMCSurface *past_surface,
2415428d7b3dSmrg			 XvMCSurface *future_surface,
2416428d7b3dSmrg			 unsigned int flags,
2417428d7b3dSmrg			 unsigned int num_macroblocks,
2418428d7b3dSmrg			 unsigned int first_macroblock,
2419428d7b3dSmrg			 XvMCMacroBlockArray *macroblock_array,
2420428d7b3dSmrg			 XvMCBlockArray *blocks) {
2421428d7b3dSmrg  /* Dma Data Structures */
2422428d7b3dSmrg  drmBufPtr pDMAy = NULL,pDMAu[UV_QUEUE],pDMAv[UV_QUEUE];
2423428d7b3dSmrg  int u_index = 0,v_index = 0;
2424428d7b3dSmrg  int dirty_context = 1;
2425428d7b3dSmrg
2426428d7b3dSmrg  /* Block Pointer */
2427428d7b3dSmrg  short *block_ptr;
2428428d7b3dSmrg  /* Current Macroblock Pointer */
2429428d7b3dSmrg  XvMCMacroBlock *mb;
2430428d7b3dSmrg
2431428d7b3dSmrg  drm_i810_mc_t mc;
2432428d7b3dSmrg  int i,j;
2433428d7b3dSmrg  i810XvMCSurface *privTarget;
2434428d7b3dSmrg  i810XvMCSurface *privFuture = NULL;
2435428d7b3dSmrg  i810XvMCSurface *privPast = NULL;
2436428d7b3dSmrg  i810XvMCContext *pI810XvMC;
2437428d7b3dSmrg
2438428d7b3dSmrg  /* DMA Pointers set to NULL */
2439428d7b3dSmrg  uint *datay = NULL;
2440428d7b3dSmrg  uint *datau = NULL;
2441428d7b3dSmrg  uint *datav = NULL;
2442428d7b3dSmrg
2443428d7b3dSmrg
2444428d7b3dSmrg  /* Check Parameters for validity */
2445428d7b3dSmrg  if((target_surface == NULL) || (context == NULL) || (display == NULL)) {
2446428d7b3dSmrg    printf("Error, Invalid Target,Context, or DIsplay!\n");
2447428d7b3dSmrg    return BadValue;
2448428d7b3dSmrg  }
2449428d7b3dSmrg
2450428d7b3dSmrg  if(num_macroblocks == 0) {return Success;}
2451428d7b3dSmrg  if((macroblock_array == NULL) || (blocks == NULL)) {return BadValue;}
2452428d7b3dSmrg  if(context->privData == NULL) {return BadValue;}
2453428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)context->privData;
2454428d7b3dSmrg
2455428d7b3dSmrg
2456428d7b3dSmrg  if(target_surface->privData == NULL) {
2457428d7b3dSmrg    printf("Error, Invalid Target Surface!\n");
2458428d7b3dSmrg    return BadValue;
2459428d7b3dSmrg  }
2460428d7b3dSmrg  privTarget = (i810XvMCSurface *)target_surface->privData;
2461428d7b3dSmrg
2462428d7b3dSmrg  if(macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) {
2463428d7b3dSmrg    printf("Error, Too many macroblocks requested for MB array size.\n");
2464428d7b3dSmrg    return BadValue;
2465428d7b3dSmrg  }
2466428d7b3dSmrg
2467428d7b3dSmrg  /* Test For YV12 Surface */
2468428d7b3dSmrg  if(context->surface_type_id != FOURCC_YV12) {
2469428d7b3dSmrg    printf("Error, HWMC only possible on YV12 Surfaces\n");
2470428d7b3dSmrg    return BadValue;
2471428d7b3dSmrg  }
2472428d7b3dSmrg
2473428d7b3dSmrg  /* P Frame Test */
2474428d7b3dSmrg  if(past_surface == NULL) {
2475428d7b3dSmrg    /* Just to avoid some ifs later. */
2476428d7b3dSmrg    privPast = privTarget;
2477428d7b3dSmrg  }
2478428d7b3dSmrg  else {
2479428d7b3dSmrg    if(past_surface->privData == NULL) {
2480428d7b3dSmrg      printf("Error, Invalid Past Surface!\n");
2481428d7b3dSmrg      return BadValue;
2482428d7b3dSmrg    }
2483428d7b3dSmrg    privPast = (i810XvMCSurface *)past_surface->privData;
2484428d7b3dSmrg  }
2485428d7b3dSmrg
2486428d7b3dSmrg
2487428d7b3dSmrg  /* B Frame Test */
2488428d7b3dSmrg  if(future_surface == NULL) {
2489428d7b3dSmrg    privFuture = privTarget;
2490428d7b3dSmrg    if(pI810XvMC->dual_prime) {
2491428d7b3dSmrg      privFuture = privPast;
2492428d7b3dSmrg      /* I810 Specific flag for marking when dual prime is in use. */
2493428d7b3dSmrg      flags |= 0x40000000;
2494428d7b3dSmrg    }
2495428d7b3dSmrg
2496428d7b3dSmrg    /*
2497428d7b3dSmrg      References are different for the Second Field Picture. The
2498428d7b3dSmrg      i810 needs to know if it is the second field picture in a
2499428d7b3dSmrg      P picture. We use a Private flag to mark this.
2500428d7b3dSmrg    */
2501428d7b3dSmrg    if(flags & XVMC_SECOND_FIELD) {
2502428d7b3dSmrg      /* I810 Specific flag for marking second fields. */
2503428d7b3dSmrg      flags |= 0x80000000;
2504428d7b3dSmrg    }
2505428d7b3dSmrg  }
2506428d7b3dSmrg  else {
2507428d7b3dSmrg    if((future_surface->privData == NULL) || (past_surface == NULL)) {
2508428d7b3dSmrg      printf("Error, Invalid Future Surface or No Past Surface!\n");
2509428d7b3dSmrg      return BadValue;
2510428d7b3dSmrg    }
2511428d7b3dSmrg    privFuture = (i810XvMCSurface *)future_surface->privData;
2512428d7b3dSmrg
2513428d7b3dSmrg    /*
2514428d7b3dSmrg      Undo Second Field flag since the second field in B frames is just like
2515428d7b3dSmrg      the first.
2516428d7b3dSmrg    */
2517428d7b3dSmrg    flags &= ~0x80000000;
2518428d7b3dSmrg  }
2519428d7b3dSmrg
2520428d7b3dSmrg  /* Lock For DMA */
2521428d7b3dSmrg  I810_LOCK(pI810XvMC,0);
2522428d7b3dSmrg
2523428d7b3dSmrg  for(i=first_macroblock; i<(num_macroblocks + first_macroblock); i++) {
2524428d7b3dSmrg    /* Set up values needed for each macroblock */
2525428d7b3dSmrg    mb = &macroblock_array->macro_blocks[i];
2526428d7b3dSmrg    block_ptr = &(blocks->blocks[mb->index<<6]);
2527428d7b3dSmrg
2528428d7b3dSmrg    /* Lockup can happen if the coordinates are too far out of range */
2529428d7b3dSmrg    if(mb->x > target_surface->width>>4) {
2530428d7b3dSmrg      mb->x = 0;
2531428d7b3dSmrg    }
2532428d7b3dSmrg    if(mb->y > target_surface->height>>4) {
2533428d7b3dSmrg      mb->y = 0;
2534428d7b3dSmrg    }
2535428d7b3dSmrg
2536428d7b3dSmrg    /* If buffers are almost full dispatch them */
2537428d7b3dSmrg    if(datay) {
2538428d7b3dSmrg      pDMAy->used = (unsigned long)datay - (unsigned long)pDMAy->address;
2539428d7b3dSmrg      if(pDMAy->used  > 3520) {
2540428d7b3dSmrg	if(dirty_context) {
2541428d7b3dSmrg	  dispatchYContext(privTarget,privPast,privFuture,pI810XvMC);
2542428d7b3dSmrg	}
2543428d7b3dSmrg	dirty_context = 0;
2544428d7b3dSmrg	mc.idx = pDMAy->idx;
2545428d7b3dSmrg	mc.used = pDMAy->used;
2546428d7b3dSmrg	datay = NULL;
2547428d7b3dSmrg	mc.last_render = ++pI810XvMC->last_render;
2548428d7b3dSmrg	privTarget->last_render = pI810XvMC->last_render;
2549428d7b3dSmrg	I810_MC(pI810XvMC,mc);
2550428d7b3dSmrg      } /* datay near full */
2551428d7b3dSmrg    } /* if(datay) */
2552428d7b3dSmrg    if(datau) {
2553428d7b3dSmrg      pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address;
2554428d7b3dSmrg      if(pDMAu[u_index]->used > 3904) {
2555428d7b3dSmrg	u_index++;
2556428d7b3dSmrg	datau = NULL;
2557428d7b3dSmrg	if(u_index == UV_QUEUE) {
2558428d7b3dSmrg	  for(j=0; j<UV_QUEUE; j++) {
2559428d7b3dSmrg	    mc.idx = pDMAu[j]->idx;
2560428d7b3dSmrg	    mc.used = pDMAu[j]->used;
2561428d7b3dSmrg	    mc.last_render = ++pI810XvMC->last_render;
2562428d7b3dSmrg	    privTarget->last_render = pI810XvMC->last_render;
2563428d7b3dSmrg	    I810_MC(pI810XvMC,mc);
2564428d7b3dSmrg	  }
2565428d7b3dSmrg	  u_index = 0;
2566428d7b3dSmrg	  dirty_context = 1;
2567428d7b3dSmrg	} /* if(u_index == UV_QUEUE) */
2568428d7b3dSmrg      } /* datau near full */
2569428d7b3dSmrg    } /* if(datau) */
2570428d7b3dSmrg    if(datav) {
2571428d7b3dSmrg      pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address;
2572428d7b3dSmrg      if(pDMAv[v_index]->used > 3904) {
2573428d7b3dSmrg	v_index++;
2574428d7b3dSmrg	datav = NULL;
2575428d7b3dSmrg	if(v_index == UV_QUEUE) {
2576428d7b3dSmrg	  for(j=0; j<UV_QUEUE; j++) {
2577428d7b3dSmrg	    mc.idx = pDMAv[j]->idx;
2578428d7b3dSmrg	    mc.used = pDMAv[j]->used;
2579428d7b3dSmrg	    mc.last_render = ++pI810XvMC->last_render;
2580428d7b3dSmrg	    privTarget->last_render = pI810XvMC->last_render;
2581428d7b3dSmrg	    I810_MC(pI810XvMC,mc);
2582428d7b3dSmrg	  }
2583428d7b3dSmrg	  v_index = 0;
2584428d7b3dSmrg	  dirty_context = 1;
2585428d7b3dSmrg	} /* if(v_index == UV_QUEUE) */
2586428d7b3dSmrg      } /* datav near full */
2587428d7b3dSmrg    } /* if(datav) */
2588428d7b3dSmrg
2589428d7b3dSmrg    /* Allocate buffers if this is the first loop,or if we just dispatched */
2590428d7b3dSmrg    if(datay == NULL) {
2591428d7b3dSmrg      pDMAy = i810_get_free_buffer(pI810XvMC);
2592428d7b3dSmrg      datay = pDMAy->address;
2593428d7b3dSmrg    }/* if(datay == NULL) */
2594428d7b3dSmrg    if(datau == NULL) {
2595428d7b3dSmrg      pDMAu[u_index] = i810_get_free_buffer(pI810XvMC);
2596428d7b3dSmrg      datau = pDMAu[u_index]->address;
2597428d7b3dSmrg      if(u_index == 0) {
2598428d7b3dSmrg	*datau++ = CMD_FLUSH;
2599428d7b3dSmrg	*datau++ = BOOLEAN_ENA_2;
2600428d7b3dSmrg	*datau++ = CMD_FLUSH;
2601428d7b3dSmrg	*datau++ = DEST_BUFFER_INFO;
2602428d7b3dSmrg	*datau++ = privTarget->dbi1u;
2603428d7b3dSmrg	*datau++ = DEST_BUFFER_VAR;
2604428d7b3dSmrg	*datau++ = privTarget->dbv1;
2605428d7b3dSmrg	/* Past Surface */
2606428d7b3dSmrg	*datau++ = CMD_MAP_INFO;
2607428d7b3dSmrg	*datau++ = privPast->mi1u;
2608428d7b3dSmrg	*datau++ = privPast->mi2u;
2609428d7b3dSmrg	*datau++ = privPast->mi3u;
2610428d7b3dSmrg	/* Future Surface */
2611428d7b3dSmrg	*datau++ = CMD_MAP_INFO;
2612428d7b3dSmrg	*datau++ = privFuture->mi1u | 0x1<<28;
2613428d7b3dSmrg	*datau++ = privFuture->mi2u;
2614428d7b3dSmrg	*datau++ = privFuture->mi3u;
2615428d7b3dSmrg      }
2616428d7b3dSmrg    } /* if(datau == NULL) */
2617428d7b3dSmrg    if(datav == NULL) {
2618428d7b3dSmrg      pDMAv[v_index] = i810_get_free_buffer(pI810XvMC);
2619428d7b3dSmrg      datav = pDMAv[v_index]->address;
2620428d7b3dSmrg      if(v_index == 0) {
2621428d7b3dSmrg	*datav++ = CMD_FLUSH;
2622428d7b3dSmrg	*datav++ = BOOLEAN_ENA_2;
2623428d7b3dSmrg	*datav++ = CMD_FLUSH;
2624428d7b3dSmrg	*datav++ = DEST_BUFFER_INFO;
2625428d7b3dSmrg	*datav++ = privTarget->dbi1v;
2626428d7b3dSmrg	*datav++ = DEST_BUFFER_VAR;
2627428d7b3dSmrg	*datav++ = privTarget->dbv1;
2628428d7b3dSmrg	/* Past Surface */
2629428d7b3dSmrg	*datav++ = CMD_MAP_INFO;
2630428d7b3dSmrg	*datav++ = privPast->mi1v;
2631428d7b3dSmrg	*datav++ = privPast->mi2v;
2632428d7b3dSmrg	*datav++ = privPast->mi3v;
2633428d7b3dSmrg	/* Future Surface */
2634428d7b3dSmrg	*datav++ = CMD_MAP_INFO;
2635428d7b3dSmrg	*datav++ = privFuture->mi1v | 0x1<<28;
2636428d7b3dSmrg	*datav++ = privFuture->mi2v;
2637428d7b3dSmrg	*datav++ = privFuture->mi3v;
2638428d7b3dSmrg      }
2639428d7b3dSmrg    }/* if(datav == NULL) */
2640428d7b3dSmrg
2641428d7b3dSmrg    /* Catch no pattern case */
2642428d7b3dSmrg    if(!(mb->macroblock_type & 0x8)) {
2643428d7b3dSmrg      mb->coded_block_pattern = 0;
2644428d7b3dSmrg    }
2645428d7b3dSmrg
2646428d7b3dSmrg
2647428d7b3dSmrg    if(mb->motion_type == XVMC_PREDICTION_DUAL_PRIME) {
2648428d7b3dSmrg      /*
2649428d7b3dSmrg	By default the maps will not be set up for dual
2650428d7b3dSmrg	prime. We have to change them.
2651428d7b3dSmrg      */
2652428d7b3dSmrg      if(!pI810XvMC->dual_prime) {
2653428d7b3dSmrg	pI810XvMC->dual_prime = 1;
2654428d7b3dSmrg	privFuture = privPast;
2655428d7b3dSmrg	/* Y */
2656428d7b3dSmrg	*datay++ = CMD_MAP_INFO;
2657428d7b3dSmrg	*datay++ = privFuture->mi1y | 0x1<<28;
2658428d7b3dSmrg	*datay++ = privFuture->mi2y;
2659428d7b3dSmrg	*datay++ = privFuture->mi3y;
2660428d7b3dSmrg	/* U */
2661428d7b3dSmrg	*datau++ = CMD_MAP_INFO;
2662428d7b3dSmrg	*datau++ = privFuture->mi1u | 0x1<<28;
2663428d7b3dSmrg	*datau++ = privFuture->mi2u;
2664428d7b3dSmrg	*datau++ = privFuture->mi3u;
2665428d7b3dSmrg	/* V */
2666428d7b3dSmrg	*datav++ = CMD_MAP_INFO;
2667428d7b3dSmrg	*datav++ = privFuture->mi1v | 0x1<<28;
2668428d7b3dSmrg	*datav++ = privFuture->mi2v;
2669428d7b3dSmrg	*datav++ = privFuture->mi3v;
2670428d7b3dSmrg      }
2671428d7b3dSmrg    }
2672428d7b3dSmrg    if((pI810XvMC->dual_prime) &&
2673428d7b3dSmrg       (mb->motion_type != XVMC_PREDICTION_DUAL_PRIME)) {
2674428d7b3dSmrg      	pI810XvMC->dual_prime = 0;
2675428d7b3dSmrg	privFuture = privTarget;
2676428d7b3dSmrg	/* Y */
2677428d7b3dSmrg	*datay++ = CMD_MAP_INFO;
2678428d7b3dSmrg	*datay++ = privFuture->mi1y | 0x1<<28;
2679428d7b3dSmrg	*datay++ = privFuture->mi2y;
2680428d7b3dSmrg	*datay++ = privFuture->mi3y;
2681428d7b3dSmrg	/* U */
2682428d7b3dSmrg	*datau++ = CMD_MAP_INFO;
2683428d7b3dSmrg	*datau++ = privFuture->mi1u | 0x1<<28;
2684428d7b3dSmrg	*datau++ = privFuture->mi2u;
2685428d7b3dSmrg	*datau++ = privFuture->mi3u;
2686428d7b3dSmrg	/* V */
2687428d7b3dSmrg	*datav++ = CMD_MAP_INFO;
2688428d7b3dSmrg	*datav++ = privFuture->mi1v | 0x1<<28;
2689428d7b3dSmrg	*datav++ = privFuture->mi2v;
2690428d7b3dSmrg	*datav++ = privFuture->mi3v;
2691428d7b3dSmrg    }
2692428d7b3dSmrg
2693428d7b3dSmrg
2694428d7b3dSmrg    /* Frame Picture */
2695428d7b3dSmrg    if((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
2696428d7b3dSmrg      /* Intra Blocks */
2697428d7b3dSmrg      if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
2698428d7b3dSmrg	if(mb->dct_type) {
2699428d7b3dSmrg	  renderIntrainFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags);
2700428d7b3dSmrg	  continue;
2701428d7b3dSmrg	}
2702428d7b3dSmrg	renderIntrainFrame(&datay,&datau,&datav,mb,block_ptr);
2703428d7b3dSmrg	continue;
2704428d7b3dSmrg      }
2705428d7b3dSmrg      switch((mb->motion_type & 0x3) | (mb->dct_type<<2)) {
2706428d7b3dSmrg      case 0x2:  /* Frame DCT0 */
2707428d7b3dSmrg	renderFrameinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
2708428d7b3dSmrg	continue;
2709428d7b3dSmrg      case 0x5:  /* Field DCT1 */
2710428d7b3dSmrg	renderFieldinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
2711428d7b3dSmrg	continue;
2712428d7b3dSmrg      case 0x6: /* Frame DCT1 */
2713428d7b3dSmrg	renderFrameinFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags);
2714428d7b3dSmrg	continue;
2715428d7b3dSmrg      case 0x1: /* Field DCT0 */
2716428d7b3dSmrg	renderFieldinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags);
2717428d7b3dSmrg	continue;
2718428d7b3dSmrg      case 0x3:  /* Dual Prime DCT0 */
2719428d7b3dSmrg	renderDualPrimeinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
2720428d7b3dSmrg	continue;
2721428d7b3dSmrg      case 0x7:  /* Dual Prime DCT1 */
2722428d7b3dSmrg	renderDualPrimeinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags);
2723428d7b3dSmrg	continue;
2724428d7b3dSmrg      default:  /* No Motion Type */
2725428d7b3dSmrg	renderError();
2726428d7b3dSmrg	continue;
2727428d7b3dSmrg      } /* Switch */
2728428d7b3dSmrg    } /* Frame Picture */
2729428d7b3dSmrg
2730428d7b3dSmrg    /* Field Pictures */
2731428d7b3dSmrg    if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
2732428d7b3dSmrg      renderIntrainField(&datay,&datau,&datav,mb,block_ptr,picture_structure);
2733428d7b3dSmrg      continue;
2734428d7b3dSmrg    }
2735428d7b3dSmrg    switch(mb->motion_type & 0x3) {
2736428d7b3dSmrg    case 0x1: /* Field Motion */
2737428d7b3dSmrg      renderFieldinField(&datay,&datau,&datav,mb,block_ptr,picture_structure,
2738428d7b3dSmrg			 flags);
2739428d7b3dSmrg      continue;
2740428d7b3dSmrg    case 0x2: /* 16x8 Motion */
2741428d7b3dSmrg      render16x8inField(&datay,&datau,&datav,mb,block_ptr,picture_structure,
2742428d7b3dSmrg			flags);
2743428d7b3dSmrg      continue;
2744428d7b3dSmrg    case 0x3: /* Dual Prime */
2745428d7b3dSmrg      renderDualPrimeinField(&datay,&datau,&datav,mb,block_ptr,
2746428d7b3dSmrg			     picture_structure,flags);
2747428d7b3dSmrg      continue;
2748428d7b3dSmrg    default:  /* No Motion Type */
2749428d7b3dSmrg      renderError();
2750428d7b3dSmrg      continue;
2751428d7b3dSmrg    }
2752428d7b3dSmrg    continue;
2753428d7b3dSmrg
2754428d7b3dSmrg  } /* for each Macroblock */
2755428d7b3dSmrg
2756428d7b3dSmrg  /* Dispatch remaining DMA buffers */
2757428d7b3dSmrg  if(dirty_context) {
2758428d7b3dSmrg    dispatchYContext(privTarget,privPast,privFuture,pI810XvMC);
2759428d7b3dSmrg  }
2760428d7b3dSmrg  mc.idx = pDMAy->idx;
2761428d7b3dSmrg  mc.used = (unsigned long)datay - (unsigned long)pDMAy->address;
2762428d7b3dSmrg  mc.last_render = ++pI810XvMC->last_render;
2763428d7b3dSmrg  privTarget->last_render = pI810XvMC->last_render;
2764428d7b3dSmrg  I810_MC(pI810XvMC,mc);
2765428d7b3dSmrg
2766428d7b3dSmrg  pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address;
2767428d7b3dSmrg  for(j=0; j<=u_index; j++) {
2768428d7b3dSmrg    mc.idx = pDMAu[j]->idx;
2769428d7b3dSmrg    mc.used = pDMAu[j]->used;
2770428d7b3dSmrg    mc.last_render = ++pI810XvMC->last_render;
2771428d7b3dSmrg    privTarget->last_render = pI810XvMC->last_render;
2772428d7b3dSmrg    I810_MC(pI810XvMC,mc);
2773428d7b3dSmrg  }
2774428d7b3dSmrg  pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address;
2775428d7b3dSmrg  for(j=0; j<=v_index; j++) {
2776428d7b3dSmrg    mc.idx = pDMAv[j]->idx;
2777428d7b3dSmrg    mc.used = pDMAv[j]->used;
2778428d7b3dSmrg    mc.last_render = ++pI810XvMC->last_render;
2779428d7b3dSmrg    privTarget->last_render = pI810XvMC->last_render;
2780428d7b3dSmrg    I810_MC(pI810XvMC,mc);
2781428d7b3dSmrg  }
2782428d7b3dSmrg
2783428d7b3dSmrg  I810_UNLOCK(pI810XvMC);
2784428d7b3dSmrg
2785428d7b3dSmrg  return Success;
2786428d7b3dSmrg}
2787428d7b3dSmrg
2788428d7b3dSmrg/***************************************************************************
2789428d7b3dSmrg// Function: XvMCPutSurface
2790428d7b3dSmrg// Description:
2791428d7b3dSmrg// Arguments:
2792428d7b3dSmrg//  display: Connection to X server
2793428d7b3dSmrg//  surface: Surface to be displayed
2794428d7b3dSmrg//  draw: X Drawable on which to display the surface
2795428d7b3dSmrg//  srcx: X coordinate of the top left corner of the region to be
2796428d7b3dSmrg//          displayed within the surface.
2797428d7b3dSmrg//  srcy: Y coordinate of the top left corner of the region to be
2798428d7b3dSmrg//          displayed within the surface.
2799428d7b3dSmrg//  srcw: Width of the region to be displayed.
2800428d7b3dSmrg//  srch: Height of the region to be displayed.
2801428d7b3dSmrg//  destx: X cordinate of the top left corner of the destination region
2802428d7b3dSmrg//         in the drawable coordinates.
2803428d7b3dSmrg//  desty: Y cordinate of the top left corner of the destination region
2804428d7b3dSmrg//         in the drawable coordinates.
2805428d7b3dSmrg//  destw: Width of the destination region.
2806428d7b3dSmrg//  desth: Height of the destination region.
2807428d7b3dSmrg//  flags: One or more of the following.
2808428d7b3dSmrg//     XVMC_TOP_FIELD - Display only the Top field of the surface.
2809428d7b3dSmrg//     XVMC_BOTTOM_FIELD - Display only the Bottom Field of the surface.
2810428d7b3dSmrg//     XVMC_FRAME_PICTURE - Display both fields or frame.
2811428d7b3dSmrg//
2812428d7b3dSmrg// Info: Portions of this function derived from i810_video.c (XFree86)
2813428d7b3dSmrg//
2814428d7b3dSmrg//   This function is organized so that we wait as long as possible before
2815428d7b3dSmrg//   touching the overlay registers. Since we don't know that the last
2816428d7b3dSmrg//   flip has happened yet we want to give the overlay as long as
2817428d7b3dSmrg//   possible to catch up before we have to check on its progress. This
2818428d7b3dSmrg//   makes it unlikely that we have to wait on the last flip.
2819428d7b3dSmrg***************************************************************************/
2820428d7b3dSmrg_X_EXPORT Status XvMCPutSurface(Display *display,XvMCSurface *surface,
2821428d7b3dSmrg		      Drawable draw, short srcx, short srcy,
2822428d7b3dSmrg		      unsigned short srcw, unsigned short srch,
2823428d7b3dSmrg		      short destx, short desty,
2824428d7b3dSmrg		      unsigned short destw, unsigned short desth,
2825428d7b3dSmrg		      int flags) {
2826428d7b3dSmrg  i810XvMCContext *pI810XvMC;
2827428d7b3dSmrg  i810XvMCSurface *pI810Surface;
2828428d7b3dSmrg  i810OverlayRecPtr pORegs;
2829428d7b3dSmrg  unsigned int ysrc_offset,uvsrc_offset;
2830428d7b3dSmrg  Box extents;
2831428d7b3dSmrg  uint window_width,window_height;
2832428d7b3dSmrg  unsigned int xscaleInt = 0,xscaleFract = 0,yscaleInt = 0,yscaleFract = 0;
2833428d7b3dSmrg  unsigned int xscaleFractUV = 0,xscaleIntUV = 0,yscaleFractUV = 0;
2834428d7b3dSmrg  unsigned int yscaleIntUV = 0,yPitch = 0,uvPitch = 0;
2835428d7b3dSmrg  unsigned int ovcmd = 0;
2836428d7b3dSmrg  uint d;
2837428d7b3dSmrg  double xscale,yscale;
2838428d7b3dSmrg  int diff;
2839428d7b3dSmrg  int clipped_srcx, clipped_srcy, clipped_destx, clipped_desty;
2840428d7b3dSmrg  int clipped_srcw, clipped_srch, clipped_destw, clipped_desth;
2841428d7b3dSmrg  uint x1,y1,root_width,root_height;
2842428d7b3dSmrg  int x2 = 0, y2 = 0,unused;
2843428d7b3dSmrg  uint nChilds;
2844428d7b3dSmrg  int stat;
2845428d7b3dSmrg  Window win,root,parent,*pChilds;
2846428d7b3dSmrg
2847428d7b3dSmrg
2848428d7b3dSmrg  if((display == NULL) || (surface == NULL)) {
2849428d7b3dSmrg    return BadValue;
2850428d7b3dSmrg  }
2851428d7b3dSmrg
2852428d7b3dSmrg  if(surface->privData == NULL) {
2853428d7b3dSmrg    return (error_base + XvMCBadSurface);
2854428d7b3dSmrg  }
2855428d7b3dSmrg  pI810Surface = (i810XvMCSurface *)surface->privData;
2856428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
2857428d7b3dSmrg  pORegs = (i810OverlayRecPtr)pI810XvMC->oregs;
2858428d7b3dSmrg
2859428d7b3dSmrg
2860428d7b3dSmrg  switch(surface->surface_type_id) {
2861428d7b3dSmrg  case FOURCC_YV12:
2862428d7b3dSmrg  case FOURCC_I420:
2863428d7b3dSmrg    yPitch = (srcw + 7) & ~7;
2864428d7b3dSmrg    uvPitch = ((srcw>>1) + 7) & ~7;
2865428d7b3dSmrg    if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) {
2866428d7b3dSmrg      srch = srch>>1;
2867428d7b3dSmrg    }
2868428d7b3dSmrg    break;
2869428d7b3dSmrg  case FOURCC_UYVY:
2870428d7b3dSmrg  case FOURCC_YUY2:
2871428d7b3dSmrg  default:
2872428d7b3dSmrg    /* FIXME: Non Planar not fully implemented. */
2873428d7b3dSmrg    return BadValue;
2874428d7b3dSmrg    yPitch = ((srcw + 7) & ~7) << 1;
2875428d7b3dSmrg    break;
2876428d7b3dSmrg  }/* switch(surface->surface_type_id) */
2877428d7b3dSmrg
2878428d7b3dSmrg  /*
2879428d7b3dSmrg    FIXME: This should be using the DRI's clip rect but that isn't
2880428d7b3dSmrg    all hooked up yet. This has some latency but we get by.
2881428d7b3dSmrg  */
2882428d7b3dSmrg  win = draw;
2883428d7b3dSmrg  XQueryTree(display,win,&root,&parent,&pChilds,&nChilds);
2884428d7b3dSmrg  if(nChilds) XFree(pChilds);
2885428d7b3dSmrg  XGetGeometry(display,win, &root, &x2, &y2, &window_width,
2886428d7b3dSmrg	       &window_height, &d, &d);
2887428d7b3dSmrg  x1 = x2;
2888428d7b3dSmrg  y1 = y2;
2889428d7b3dSmrg  win = parent;
2890428d7b3dSmrg  do {
2891428d7b3dSmrg    XQueryTree(display,win,&root,&parent,&pChilds,&nChilds);
2892428d7b3dSmrg    if(nChilds) XFree(pChilds);
2893428d7b3dSmrg    XGetGeometry(display,win, &root, &x2, &y2, &d, &d, &d, &d);
2894428d7b3dSmrg    x1 += x2;
2895428d7b3dSmrg    y1 += y2;
2896428d7b3dSmrg    win = parent;
2897428d7b3dSmrg  }while(win != root);
2898428d7b3dSmrg  XGetGeometry(display,root, &root, &unused, &unused,
2899428d7b3dSmrg               &root_width, &root_height, &d, &d);
2900428d7b3dSmrg
2901428d7b3dSmrg  /* Left edge of Video window clipped to screen */
2902428d7b3dSmrg  extents.x1 = 0;
2903428d7b3dSmrg  if(x1 > extents.x1) {
2904428d7b3dSmrg    extents.x1 = x1;
2905428d7b3dSmrg  }
2906428d7b3dSmrg  /* Right edge of Video window clipped to screen */
2907428d7b3dSmrg  extents.x2 = root_width;
2908428d7b3dSmrg  if(extents.x2 > (x1 + window_width)) {
2909428d7b3dSmrg    extents.x2 = x1 + window_width;
2910428d7b3dSmrg  }
2911428d7b3dSmrg  /* Top edge of Video window clipped to screen */
2912428d7b3dSmrg  extents.y1 = 0;
2913428d7b3dSmrg  if(y1 > extents.y1) {
2914428d7b3dSmrg    extents.y1 = y1;
2915428d7b3dSmrg  }
2916428d7b3dSmrg  /* Bottom edge of Video window clipped to screen */
2917428d7b3dSmrg  extents.y2 = root_height;
2918428d7b3dSmrg  if(extents.y2 > (y1 + window_height)) {
2919428d7b3dSmrg    extents.y2 = y1 + window_height;
2920428d7b3dSmrg  }
2921428d7b3dSmrg
2922428d7b3dSmrg  /*
2923428d7b3dSmrg    Clipping is more difficult than is seems. We need to keep the
2924428d7b3dSmrg    scaling factors even if the destination window needs to be clipped.
2925428d7b3dSmrg    We clip the destination window first then apply a scaled version
2926428d7b3dSmrg    to the source window.
2927428d7b3dSmrg  */
2928428d7b3dSmrg
2929428d7b3dSmrg  /* Put destination coords in screen coords */
2930428d7b3dSmrg  destx += x1;
2931428d7b3dSmrg  desty += y1;
2932428d7b3dSmrg
2933428d7b3dSmrg  /* Scale factors requested */
2934428d7b3dSmrg  xscale = (double)srcw / (double)destw;
2935428d7b3dSmrg  yscale = (double)srch / (double)desth;
2936428d7b3dSmrg
2937428d7b3dSmrg  /*
2938428d7b3dSmrg    If destination window needs to be clipped we actually adjust both
2939428d7b3dSmrg    the src and dest window so as to keep the scaling that was requested
2940428d7b3dSmrg  */
2941428d7b3dSmrg  clipped_srcx = srcx;
2942428d7b3dSmrg  clipped_srcy = srcy;
2943428d7b3dSmrg  clipped_destx = destx;
2944428d7b3dSmrg  clipped_desty = desty;
2945428d7b3dSmrg  clipped_srcw = srcw;
2946428d7b3dSmrg  clipped_srch = srch;
2947428d7b3dSmrg  clipped_destw = destw;
2948428d7b3dSmrg  clipped_desth = desth;
2949428d7b3dSmrg
2950428d7b3dSmrg  /* Clip to the source surface boundaries */
2951428d7b3dSmrg  if(clipped_srcx < 0) {
2952428d7b3dSmrg    clipped_destx += (0 - clipped_srcx) / xscale;
2953428d7b3dSmrg    clipped_srcw -= clipped_srcx;
2954428d7b3dSmrg    clipped_destw -= clipped_srcx / xscale;
2955428d7b3dSmrg    clipped_srcx = 0;
2956428d7b3dSmrg  }
2957428d7b3dSmrg  if((clipped_srcw + clipped_srcx) > surface->width) {
2958428d7b3dSmrg    clipped_srcw = surface->width - clipped_srcx;
2959428d7b3dSmrg    clipped_destw -= (clipped_srcw - srcw) / xscale;
2960428d7b3dSmrg  }
2961428d7b3dSmrg  if(clipped_srcy < 0) {
2962428d7b3dSmrg    clipped_desty += (0 - clipped_srcy) / yscale;
2963428d7b3dSmrg    clipped_srch -= clipped_srcy;
2964428d7b3dSmrg    clipped_desth -= clipped_srcy / yscale;
2965428d7b3dSmrg    clipped_srcy = 0;
2966428d7b3dSmrg  }
2967428d7b3dSmrg  if((clipped_srch + clipped_srcy) > surface->height) {
2968428d7b3dSmrg    clipped_srch = surface->height - clipped_srcy;
2969428d7b3dSmrg    clipped_desth -= (clipped_srch - srch) / yscale;
2970428d7b3dSmrg  }
2971428d7b3dSmrg
2972428d7b3dSmrg  /* Clip to the extents */
2973428d7b3dSmrg  if(clipped_destx < extents.x1) {
2974428d7b3dSmrg    diff = extents.x1 - clipped_destx;
2975428d7b3dSmrg    clipped_srcx += diff * xscale;
2976428d7b3dSmrg    clipped_srcw -= diff * xscale;
2977428d7b3dSmrg    clipped_destw -= diff;
2978428d7b3dSmrg    clipped_destx = extents.x1;
2979428d7b3dSmrg  }
2980428d7b3dSmrg
2981428d7b3dSmrg  diff = (clipped_destx + clipped_destw) - extents.x2;
2982428d7b3dSmrg  if(diff > 0) {
2983428d7b3dSmrg    clipped_destw -= diff;
2984428d7b3dSmrg    clipped_srcw -= diff * xscale;
2985428d7b3dSmrg  }
2986428d7b3dSmrg
2987428d7b3dSmrg  if(clipped_desty < extents.y1) {
2988428d7b3dSmrg    diff = extents.y1 - clipped_desty;
2989428d7b3dSmrg    clipped_srcy += diff * yscale;
2990428d7b3dSmrg    clipped_srch -= diff * yscale;
2991428d7b3dSmrg    clipped_desth -= diff;
2992428d7b3dSmrg    clipped_desty = 0;
2993428d7b3dSmrg  }
2994428d7b3dSmrg
2995428d7b3dSmrg  diff = (clipped_desty + clipped_desth) - extents.y2;
2996428d7b3dSmrg  if(diff > 0) {
2997428d7b3dSmrg    clipped_desth -= diff;
2998428d7b3dSmrg    clipped_srch -= diff * yscale;
2999428d7b3dSmrg  }
3000428d7b3dSmrg
3001428d7b3dSmrg  /* If the whole window is clipped turn off the overlay */
3002428d7b3dSmrg  if((clipped_destx + clipped_destw < extents.x1) ||
3003428d7b3dSmrg     (clipped_desty + clipped_desth < extents.y1) ||
3004428d7b3dSmrg     (clipped_destx > extents.x2) ||
3005428d7b3dSmrg     (clipped_desty > extents.y2)) {
3006428d7b3dSmrg    return XvMCHideSurface(display, surface);
3007428d7b3dSmrg  }
3008428d7b3dSmrg
3009428d7b3dSmrg  /*
3010428d7b3dSmrg    Adjust the source offset width and height according to the clipped
3011428d7b3dSmrg    destination window.
3012428d7b3dSmrg  */
3013428d7b3dSmrg  ysrc_offset = ((clipped_srcx + 1) & ~1) +
3014428d7b3dSmrg    ((clipped_srcy + 1) & ~1) * (1<<pI810Surface->pitch);
3015428d7b3dSmrg  uvsrc_offset = (clipped_srcx>>1) +
3016428d7b3dSmrg    (clipped_srcy>>1) * (1<<(pI810Surface->pitch - 1));
3017428d7b3dSmrg
3018428d7b3dSmrg  /*
3019428d7b3dSmrg    Initially, YCbCr and Overlay Enable and
3020428d7b3dSmrg    vertical chrominance up interpolation and horozontal chrominance
3021428d7b3dSmrg    up interpolation
3022428d7b3dSmrg  */
3023428d7b3dSmrg  ovcmd = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
3024428d7b3dSmrg    Y_ADJUST | OVERLAY_ENABLE;
3025428d7b3dSmrg
3026428d7b3dSmrg  if ((clipped_destw != clipped_srcw) ||
3027428d7b3dSmrg      (clipped_desth != clipped_srch)) {
3028428d7b3dSmrg    xscaleInt = (clipped_srcw / clipped_destw) & 0x3;
3029428d7b3dSmrg    xscaleFract = (clipped_srcw << 12) / clipped_destw;
3030428d7b3dSmrg    yscaleInt = (clipped_srch / clipped_desth) & 0x3;
3031428d7b3dSmrg    yscaleFract = (clipped_srch << 12) / clipped_desth;
3032428d7b3dSmrg
3033428d7b3dSmrg    if (clipped_destw > clipped_srcw) {
3034428d7b3dSmrg      /* horizontal up-scaling */
3035428d7b3dSmrg      ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER;
3036428d7b3dSmrg      ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER;
3037428d7b3dSmrg      ovcmd |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION);
3038428d7b3dSmrg    }
3039428d7b3dSmrg
3040428d7b3dSmrg    if (clipped_desth > clipped_srch) {
3041428d7b3dSmrg      /* vertical up-scaling */
3042428d7b3dSmrg      ovcmd &= ~VERTICAL_CHROMINANCE_FILTER;
3043428d7b3dSmrg      ovcmd &= ~VERTICAL_LUMINANCE_FILTER;
3044428d7b3dSmrg      ovcmd |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION);
3045428d7b3dSmrg    }
3046428d7b3dSmrg
3047428d7b3dSmrg    if (clipped_destw < clipped_srcw) {
3048428d7b3dSmrg      /* horizontal down-scaling */
3049428d7b3dSmrg      ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER;
3050428d7b3dSmrg      ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER;
3051428d7b3dSmrg      ovcmd |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION);
3052428d7b3dSmrg    }
3053428d7b3dSmrg
3054428d7b3dSmrg    if (clipped_desth < clipped_srch) {
3055428d7b3dSmrg      /* vertical down-scaling */
3056428d7b3dSmrg      ovcmd &= ~VERTICAL_CHROMINANCE_FILTER;
3057428d7b3dSmrg      ovcmd &= ~VERTICAL_LUMINANCE_FILTER;
3058428d7b3dSmrg      ovcmd |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION);
3059428d7b3dSmrg    }
3060428d7b3dSmrg
3061428d7b3dSmrg    /* now calculate the UV scaling factor */
3062428d7b3dSmrg    if (xscaleFract) {
3063428d7b3dSmrg      xscaleFractUV = xscaleFract >> MINUV_SCALE;
3064428d7b3dSmrg      ovcmd &= ~HC_DOWN_INTERPOLATION;
3065428d7b3dSmrg      ovcmd |= HC_UP_INTERPOLATION;
3066428d7b3dSmrg    }
3067428d7b3dSmrg
3068428d7b3dSmrg    if (xscaleInt) {
3069428d7b3dSmrg      xscaleIntUV = xscaleInt >> MINUV_SCALE;
3070428d7b3dSmrg      if (xscaleIntUV) {
3071428d7b3dSmrg	ovcmd &= ~HC_UP_INTERPOLATION;
3072428d7b3dSmrg      }
3073428d7b3dSmrg    }
3074428d7b3dSmrg
3075428d7b3dSmrg    if (yscaleFract) {
3076428d7b3dSmrg      yscaleFractUV = yscaleFract >> MINUV_SCALE;
3077428d7b3dSmrg      ovcmd &= ~VC_DOWN_INTERPOLATION;
3078428d7b3dSmrg      ovcmd |= VC_UP_INTERPOLATION;
3079428d7b3dSmrg    }
3080428d7b3dSmrg
3081428d7b3dSmrg    if (yscaleInt) {
3082428d7b3dSmrg      yscaleIntUV = yscaleInt >> MINUV_SCALE;
3083428d7b3dSmrg      if (yscaleIntUV) {
3084428d7b3dSmrg	ovcmd &= ~VC_UP_INTERPOLATION;
3085428d7b3dSmrg	ovcmd |= VC_DOWN_INTERPOLATION;
3086428d7b3dSmrg      }
3087428d7b3dSmrg    }
3088428d7b3dSmrg
3089428d7b3dSmrg  }/* if((destw != srcw) || (desth != srch)) */
3090428d7b3dSmrg
3091428d7b3dSmrg  /* Lock the DRM */
3092428d7b3dSmrg  I810_LOCK(pI810XvMC,0);
3093428d7b3dSmrg
3094428d7b3dSmrg  /* Block until rendering on this surface is finished */
3095428d7b3dSmrg  stat = XVMC_RENDERING;
3096428d7b3dSmrg  while(stat & XVMC_RENDERING) {
3097428d7b3dSmrg    XvMCGetSurfaceStatus(display,surface,&stat);
3098428d7b3dSmrg  }
3099428d7b3dSmrg  /* Block until the last flip is finished */
3100428d7b3dSmrg  if(pI810XvMC->last_flip) {
3101428d7b3dSmrg    BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
3102428d7b3dSmrg  }
3103428d7b3dSmrg
3104428d7b3dSmrg  pI810XvMC->current = !pI810XvMC->current;
3105428d7b3dSmrg  pORegs->OV0CMD = ovcmd;
3106428d7b3dSmrg
3107428d7b3dSmrg  if ((clipped_destw != clipped_srcw) ||
3108428d7b3dSmrg      (clipped_desth != clipped_srch)) {
3109428d7b3dSmrg    pORegs->YRGBSCALE = (xscaleInt << 15) |
3110428d7b3dSmrg      ((xscaleFract & 0xFFF) << 3) | (yscaleInt) |
3111428d7b3dSmrg      ((yscaleFract & 0xFFF) << 20);
3112428d7b3dSmrg
3113428d7b3dSmrg    pORegs->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) |
3114428d7b3dSmrg      ((yscaleFractUV & 0xFFF) << 20);
3115428d7b3dSmrg  }
3116428d7b3dSmrg  else {
3117428d7b3dSmrg    /* Normal 1:1 scaling */
3118428d7b3dSmrg    pORegs->YRGBSCALE = 0x80004000;
3119428d7b3dSmrg    pORegs->UVSCALE = 0x80004000;
3120428d7b3dSmrg  }
3121428d7b3dSmrg
3122428d7b3dSmrg  pORegs->SHEIGHT = clipped_srch | (clipped_srch << 15);
3123428d7b3dSmrg  pORegs->DWINPOS = (clipped_desty << 16) | clipped_destx;
3124428d7b3dSmrg  pORegs->DWINSZ = ((clipped_desth<< 16) | (clipped_destw));
3125428d7b3dSmrg
3126428d7b3dSmrg  /* Attributes */
3127428d7b3dSmrg  pORegs->OV0CLRC0 = ((pI810XvMC->contrast & 0x1ff)<<8) |
3128428d7b3dSmrg    (pI810XvMC->brightness & 0xff);
3129428d7b3dSmrg  pORegs->OV0CLRC1 = (pI810XvMC->saturation & 0x3ff);
3130428d7b3dSmrg
3131428d7b3dSmrg  /* Destination Colorkey Setup */
3132428d7b3dSmrg  pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey);
3133428d7b3dSmrg
3134428d7b3dSmrg  /* buffer locations, add the offset from the clipping */
3135428d7b3dSmrg  if(pI810XvMC->current) {
3136428d7b3dSmrg    pORegs->OBUF_1Y = (unsigned long)pI810Surface->offset +
3137428d7b3dSmrg      (unsigned long)pI810Surface->offsets[0] + ysrc_offset;
3138428d7b3dSmrg    pORegs->OBUF_1V = (unsigned long)pI810Surface->offset +
3139428d7b3dSmrg      (unsigned long)pI810Surface->offsets[2] + uvsrc_offset;
3140428d7b3dSmrg    pORegs->OBUF_1U = (unsigned long)pI810Surface->offset +
3141428d7b3dSmrg      (unsigned long)pI810Surface->offsets[1] + uvsrc_offset;
3142428d7b3dSmrg  }
3143428d7b3dSmrg  else {
3144428d7b3dSmrg    pORegs->OBUF_0Y = (unsigned long)pI810Surface->offset +
3145428d7b3dSmrg      (unsigned long)pI810Surface->offsets[0] + ysrc_offset;
3146428d7b3dSmrg    pORegs->OBUF_0V = (unsigned long)pI810Surface->offset +
3147428d7b3dSmrg      (unsigned long)pI810Surface->offsets[2] + uvsrc_offset;
3148428d7b3dSmrg    pORegs->OBUF_0U = (unsigned long)pI810Surface->offset +
3149428d7b3dSmrg      (unsigned long)pI810Surface->offsets[1] + uvsrc_offset;
3150428d7b3dSmrg  }
3151428d7b3dSmrg
3152428d7b3dSmrg  switch(surface->surface_type_id) {
3153428d7b3dSmrg  case FOURCC_YV12:
3154428d7b3dSmrg  case FOURCC_I420:
3155428d7b3dSmrg    pORegs->SWID = (uvPitch << 16) | yPitch;
3156428d7b3dSmrg    pORegs->SWIDQW = (uvPitch << 13) | (yPitch >> 3);
3157428d7b3dSmrg    pORegs->OV0STRIDE = (1<<pI810Surface->pitch) |
3158428d7b3dSmrg      ((1<<pI810Surface->pitch) << 15);
3159428d7b3dSmrg    pORegs->OV0CMD &= ~SOURCE_FORMAT;
3160428d7b3dSmrg    pORegs->OV0CMD |= YUV_420;
3161428d7b3dSmrg    if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) {
3162428d7b3dSmrg      /* Top Field Only */
3163428d7b3dSmrg      if(flags & XVMC_TOP_FIELD) {
3164428d7b3dSmrg	if(pI810XvMC->current == 1) {
3165428d7b3dSmrg	  pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
3166428d7b3dSmrg			     BUFFER1_FIELD0);
3167428d7b3dSmrg	}
3168428d7b3dSmrg	else {
3169428d7b3dSmrg	  pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
3170428d7b3dSmrg			     BUFFER0_FIELD0);
3171428d7b3dSmrg	}
3172428d7b3dSmrg	pORegs->YRGB_VPH = 1<<15 | 1<<31;
3173428d7b3dSmrg	pORegs->UV_VPH = 3<<14 | 3<<30;
3174428d7b3dSmrg	pORegs->INIT_PH = 0x06 | 0x18;
3175428d7b3dSmrg      }
3176428d7b3dSmrg      /* Bottom Field Only */
3177428d7b3dSmrg      else {
3178428d7b3dSmrg	if(pI810XvMC->current == 1) {
3179428d7b3dSmrg	  pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
3180428d7b3dSmrg			     BUFFER1_FIELD1);
3181428d7b3dSmrg	}
3182428d7b3dSmrg	else {
3183428d7b3dSmrg	  pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
3184428d7b3dSmrg			     BUFFER0_FIELD1);
3185428d7b3dSmrg	}
3186428d7b3dSmrg	pORegs->YRGB_VPH = 0;
3187428d7b3dSmrg	pORegs->UV_VPH = 7<<29 | 7<<13;
3188428d7b3dSmrg	pORegs->INIT_PH = 0x06;
3189428d7b3dSmrg      }
3190428d7b3dSmrg    }
3191428d7b3dSmrg    /* Frame Picture */
3192428d7b3dSmrg    else {
3193428d7b3dSmrg      if(pI810XvMC->current == 1) {
3194428d7b3dSmrg	pORegs->OV0CMD |= BUFFER1_FIELD0;
3195428d7b3dSmrg      }
3196428d7b3dSmrg      else {
3197428d7b3dSmrg	pORegs->OV0CMD |= BUFFER0_FIELD0;
3198428d7b3dSmrg      }
3199428d7b3dSmrg      pORegs->YRGB_VPH = 0;
3200428d7b3dSmrg      pORegs->UV_VPH = 0;
3201428d7b3dSmrg      pORegs->INIT_PH = 0;
3202428d7b3dSmrg    }
3203428d7b3dSmrg    break;
3204428d7b3dSmrg  case FOURCC_UYVY:
3205428d7b3dSmrg  case FOURCC_YUY2:
3206428d7b3dSmrg  default:
3207428d7b3dSmrg    pORegs->SWID = srcw;
3208428d7b3dSmrg    pORegs->SWIDQW = srcw >> 3;
3209428d7b3dSmrg    pORegs->OV0STRIDE = pI810Surface->pitch;
3210428d7b3dSmrg    pORegs->OV0CMD &= ~SOURCE_FORMAT;
3211428d7b3dSmrg    pORegs->OV0CMD |= YUV_422;
3212428d7b3dSmrg    pORegs->OV0CMD &= ~OV_BYTE_ORDER;
3213428d7b3dSmrg    if (surface->surface_type_id == FOURCC_UYVY) {
3214428d7b3dSmrg      pORegs->OV0CMD |= Y_SWAP;
3215428d7b3dSmrg    }
3216428d7b3dSmrg
3217428d7b3dSmrg    pORegs->OV0CMD &= ~BUFFER_AND_FIELD;
3218428d7b3dSmrg    if(pI810XvMC->current == 1) {
3219428d7b3dSmrg      pORegs->OV0CMD |= BUFFER1_FIELD0;
3220428d7b3dSmrg    }
3221428d7b3dSmrg    else {
3222428d7b3dSmrg      pORegs->OV0CMD |= BUFFER0_FIELD0;
3223428d7b3dSmrg    }
3224428d7b3dSmrg
3225428d7b3dSmrg    break;
3226428d7b3dSmrg  } /* switch(surface->surface_type_id) */
3227428d7b3dSmrg
3228428d7b3dSmrg
3229428d7b3dSmrg
3230428d7b3dSmrg  OVERLAY_FLIP(pI810XvMC);
3231428d7b3dSmrg
3232428d7b3dSmrg  /*
3233428d7b3dSmrg    The Overlay only flips when it knows you changed
3234428d7b3dSmrg    something. So the first time change stuff while it
3235428d7b3dSmrg    is watching to be sure.
3236428d7b3dSmrg  */
3237428d7b3dSmrg  if(!pI810XvMC->last_flip) {
3238428d7b3dSmrg    pORegs->OV0CMD &= ~0x4;
3239428d7b3dSmrg    if(pI810XvMC->current == 1) {
3240428d7b3dSmrg      pORegs->OV0CMD |= BUFFER1_FIELD0;
3241428d7b3dSmrg    }
3242428d7b3dSmrg    else {
3243428d7b3dSmrg      pORegs->OV0CMD |= BUFFER0_FIELD0;
3244428d7b3dSmrg    }
3245428d7b3dSmrg  }
3246428d7b3dSmrg  pI810Surface->last_flip = ++pI810XvMC->last_flip;
3247428d7b3dSmrg  I810_UNLOCK(pI810XvMC);
3248428d7b3dSmrg
3249428d7b3dSmrg  return Success;
3250428d7b3dSmrg}
3251428d7b3dSmrg
3252428d7b3dSmrg/***************************************************************************
3253428d7b3dSmrg// Function: XvMCSyncSurface
3254428d7b3dSmrg// Arguments:
3255428d7b3dSmrg//   display - Connection to the X server
3256428d7b3dSmrg//   surface - The surface to synchronize
3257428d7b3dSmrg// Info:
3258428d7b3dSmrg// Returns: Status
3259428d7b3dSmrg***************************************************************************/
3260428d7b3dSmrg_X_EXPORT Status XvMCSyncSurface(Display *display,XvMCSurface *surface) {
3261428d7b3dSmrg  Status ret;
3262428d7b3dSmrg  int stat=0;
3263428d7b3dSmrg  /*
3264428d7b3dSmrg    FIXME: Perhaps a timer here to prevent lockup?
3265428d7b3dSmrg    FIXME: Perhaps a usleep to not be busy waiting?
3266428d7b3dSmrg  */
3267428d7b3dSmrg  do {
3268428d7b3dSmrg    ret = XvMCGetSurfaceStatus(display,surface,&stat);
3269428d7b3dSmrg  }while(!ret && (stat & XVMC_RENDERING));
3270428d7b3dSmrg  return ret;
3271428d7b3dSmrg}
3272428d7b3dSmrg
3273428d7b3dSmrg/***************************************************************************
3274428d7b3dSmrg// Function: XvMCFlushSurface
3275428d7b3dSmrg// Description:
3276428d7b3dSmrg//   This function commits pending rendering requests to ensure that they
3277428d7b3dSmrg//   wll be completed in a finite amount of time.
3278428d7b3dSmrg// Arguments:
3279428d7b3dSmrg//   display - Connection to X server
3280428d7b3dSmrg//   surface - Surface to flush
3281428d7b3dSmrg// Info:
3282428d7b3dSmrg//   This command is a noop for i810 becuase we always dispatch buffers in
3283428d7b3dSmrg//   render. There is little gain to be had with 4k buffers.
3284428d7b3dSmrg// Returns: Status
3285428d7b3dSmrg***************************************************************************/
3286428d7b3dSmrg_X_EXPORT Status XvMCFlushSurface(Display * display, XvMCSurface *surface) {
3287428d7b3dSmrg  return Success;
3288428d7b3dSmrg}
3289428d7b3dSmrg
3290428d7b3dSmrg/***************************************************************************
3291428d7b3dSmrg// Function: XvMCGetSurfaceStatus
3292428d7b3dSmrg// Description:
3293428d7b3dSmrg// Arguments:
3294428d7b3dSmrg//  display: connection to X server
3295428d7b3dSmrg//  surface: The surface to query
3296428d7b3dSmrg//  stat: One of the Following
3297428d7b3dSmrg//    XVMC_RENDERING - The last XvMCRenderSurface command has not
3298428d7b3dSmrg//                     completed.
3299428d7b3dSmrg//    XVMC_DISPLAYING - The surface is currently being displayed or a
3300428d7b3dSmrg//                     display is pending.
3301428d7b3dSmrg***************************************************************************/
3302428d7b3dSmrg_X_EXPORT Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface,
3303428d7b3dSmrg			    int *stat) {
3304428d7b3dSmrg  i810XvMCSurface *privSurface;
3305428d7b3dSmrg  i810XvMCContext *pI810XvMC;
3306428d7b3dSmrg  int temp;
3307428d7b3dSmrg
3308428d7b3dSmrg  if((display == NULL) || (surface == NULL) || (stat == NULL)) {
3309428d7b3dSmrg    return BadValue;
3310428d7b3dSmrg  }
3311428d7b3dSmrg  if(surface->privData == NULL) {
3312428d7b3dSmrg    return BadValue;
3313428d7b3dSmrg  }
3314428d7b3dSmrg  *stat = 0;
3315428d7b3dSmrg  privSurface = surface->privData;
3316428d7b3dSmrg
3317428d7b3dSmrg  pI810XvMC = privSurface->privContext;
3318428d7b3dSmrg  if(pI810XvMC == NULL) {
3319428d7b3dSmrg    return (error_base + XvMCBadSurface);
3320428d7b3dSmrg  }
3321428d7b3dSmrg
3322428d7b3dSmrg  I810_LOCK(pI810XvMC,0);
3323428d7b3dSmrg  if(privSurface->last_flip) {
3324428d7b3dSmrg    /* This can not happen */
3325428d7b3dSmrg    if(pI810XvMC->last_flip < privSurface->last_flip) {
3326428d7b3dSmrg      printf("Error: Context last flip is less than surface last flip.\n");
3327428d7b3dSmrg      return BadValue;
3328428d7b3dSmrg    }
3329428d7b3dSmrg    /*
3330428d7b3dSmrg      If the context has 2 or more flips after this surface it
3331428d7b3dSmrg      cannot be displaying. Don't bother to check.
3332428d7b3dSmrg    */
3333428d7b3dSmrg    if(!(pI810XvMC->last_flip > (privSurface->last_flip + 1))) {
3334428d7b3dSmrg      /*
3335428d7b3dSmrg	If this surface was the last flipped it is either displaying
3336428d7b3dSmrg	or about to be so don't bother checking.
3337428d7b3dSmrg      */
3338428d7b3dSmrg      if(pI810XvMC->last_flip == privSurface->last_flip) {
3339428d7b3dSmrg	*stat |= XVMC_DISPLAYING;
3340428d7b3dSmrg      }
3341428d7b3dSmrg      else {
3342428d7b3dSmrg	/*
3343428d7b3dSmrg	  In this case there has been one more flip since our surface's
3344428d7b3dSmrg	  but we need to check if it is finished or not.
3345428d7b3dSmrg	*/
3346428d7b3dSmrg	temp = GET_FSTATUS(pI810XvMC);
3347428d7b3dSmrg	if(((temp & (1<<20))>>20) != pI810XvMC->current) {
3348428d7b3dSmrg	  *stat |= XVMC_DISPLAYING;
3349428d7b3dSmrg	}
3350428d7b3dSmrg      }
3351428d7b3dSmrg    }
3352428d7b3dSmrg  }
3353428d7b3dSmrg
3354428d7b3dSmrg  if(privSurface->last_render &&
3355428d7b3dSmrg      (privSurface->last_render > GET_RSTATUS(pI810XvMC))) {
3356428d7b3dSmrg    *stat |= XVMC_RENDERING;
3357428d7b3dSmrg  }
3358428d7b3dSmrg  I810_UNLOCK(pI810XvMC);
3359428d7b3dSmrg
3360428d7b3dSmrg  return Success;
3361428d7b3dSmrg}
3362428d7b3dSmrg
3363428d7b3dSmrg/***************************************************************************
3364428d7b3dSmrg//
3365428d7b3dSmrg//  Surface manipulation functions
3366428d7b3dSmrg//
3367428d7b3dSmrg***************************************************************************/
3368428d7b3dSmrg
3369428d7b3dSmrg/***************************************************************************
3370428d7b3dSmrg// Function: XvMCHideSurface
3371428d7b3dSmrg// Description: Stops the display of a surface.
3372428d7b3dSmrg// Arguments:
3373428d7b3dSmrg//   display - Connection to the X server.
3374428d7b3dSmrg//   surface - surface to be hidden.
3375428d7b3dSmrg//
3376428d7b3dSmrg// Returns: Status
3377428d7b3dSmrg***************************************************************************/
3378428d7b3dSmrg_X_EXPORT Status XvMCHideSurface(Display *display, XvMCSurface *surface) {
3379428d7b3dSmrg  i810XvMCSurface *pI810Surface;
3380428d7b3dSmrg  i810XvMCContext *pI810XvMC;
3381428d7b3dSmrg  int ss, xx;
3382428d7b3dSmrg
3383428d7b3dSmrg  /* Did we get a good display and surface passed into us? */
3384428d7b3dSmrg  if(display == NULL) {
3385428d7b3dSmrg    return BadValue;
3386428d7b3dSmrg  }
3387428d7b3dSmrg
3388428d7b3dSmrg  if(surface == NULL) {
3389428d7b3dSmrg    return (error_base + XvMCBadSurface);
3390428d7b3dSmrg  }
3391428d7b3dSmrg
3392428d7b3dSmrg  XvMCSyncSurface(display, surface);
3393428d7b3dSmrg
3394428d7b3dSmrg  /* Get surface private data pointer */
3395428d7b3dSmrg  if(surface->privData == NULL) {
3396428d7b3dSmrg    return (error_base + XvMCBadSurface);
3397428d7b3dSmrg  }
3398428d7b3dSmrg  pI810Surface = (i810XvMCSurface *)surface->privData;
3399428d7b3dSmrg
3400428d7b3dSmrg  /*
3401428d7b3dSmrg    Get the status of the surface, if it is not currently displayed
3402428d7b3dSmrg    we don't need to worry about it.
3403428d7b3dSmrg  */
3404428d7b3dSmrg  if((xx = XvMCGetSurfaceStatus(display, surface, &ss)) != Success) {
3405428d7b3dSmrg    return xx;
3406428d7b3dSmrg  }
3407428d7b3dSmrg  if(! (ss & XVMC_DISPLAYING)) {
3408428d7b3dSmrg    return Success;
3409428d7b3dSmrg  }
3410428d7b3dSmrg
3411428d7b3dSmrg  /* Get the associated context pointer */
3412428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
3413428d7b3dSmrg  if(pI810XvMC == NULL) {
3414428d7b3dSmrg    return (error_base + XvMCBadSurface);
3415428d7b3dSmrg  }
3416428d7b3dSmrg
3417428d7b3dSmrg  if(pI810XvMC->last_flip) {
3418428d7b3dSmrg    I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
3419428d7b3dSmrg
3420428d7b3dSmrg    /* Make sure last flip is done */
3421428d7b3dSmrg    BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
3422428d7b3dSmrg
3423428d7b3dSmrg    /* Set the registers to turn the overlay off */
3424428d7b3dSmrg    pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
3425428d7b3dSmrg      Y_ADJUST;
3426428d7b3dSmrg    pI810XvMC->current = !pI810XvMC->current;
3427428d7b3dSmrg    if(pI810XvMC->current == 1) {
3428428d7b3dSmrg      pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0;
3429428d7b3dSmrg    }
3430428d7b3dSmrg    else {
3431428d7b3dSmrg      pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0;
3432428d7b3dSmrg    }
3433428d7b3dSmrg    OVERLAY_FLIP(pI810XvMC);
3434428d7b3dSmrg    /*
3435428d7b3dSmrg      Increment the context flip but not the surface. This way no
3436428d7b3dSmrg      surface has the last flip #.
3437428d7b3dSmrg    */
3438428d7b3dSmrg    pI810XvMC->last_flip++;
3439428d7b3dSmrg
3440428d7b3dSmrg
3441428d7b3dSmrg    /* Now wait until the hardware reads the registers and makes the change. */
3442428d7b3dSmrg    BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current)
3443428d7b3dSmrg
3444428d7b3dSmrg      I810_UNLOCK(pI810XvMC);
3445428d7b3dSmrg  }
3446428d7b3dSmrg
3447428d7b3dSmrg  return Success;
3448428d7b3dSmrg}
3449428d7b3dSmrg
3450428d7b3dSmrg
3451428d7b3dSmrg
3452428d7b3dSmrg
3453428d7b3dSmrg/***************************************************************************
3454428d7b3dSmrg//
3455428d7b3dSmrg// Functions that deal with subpictures
3456428d7b3dSmrg//
3457428d7b3dSmrg***************************************************************************/
3458428d7b3dSmrg
3459428d7b3dSmrg
3460428d7b3dSmrg
3461428d7b3dSmrg/***************************************************************************
3462428d7b3dSmrg// Function: XvMCCreateSubpicture
3463428d7b3dSmrg// Description: This creates a subpicture by filling out the XvMCSubpicture
3464428d7b3dSmrg//              structure passed to it and returning Success.
3465428d7b3dSmrg// Arguments:
3466428d7b3dSmrg//   display - Connection to the X server.
3467428d7b3dSmrg//   context - The context to create the subpicture for.
3468428d7b3dSmrg//   subpicture - Pre-allocated XvMCSubpicture structure to be filled in.
3469428d7b3dSmrg//   width - of subpicture
3470428d7b3dSmrg//   height - of subpicture
3471428d7b3dSmrg//   xvimage_id - The id describing the XvImage format.
3472428d7b3dSmrg//
3473428d7b3dSmrg// Returns: Status
3474428d7b3dSmrg***************************************************************************/
3475428d7b3dSmrg_X_EXPORT Status XvMCCreateSubpicture(Display *display, XvMCContext *context,
3476428d7b3dSmrg                          XvMCSubpicture *subpicture,
3477428d7b3dSmrg                          unsigned short width, unsigned short height,
3478428d7b3dSmrg                          int xvimage_id) {
3479428d7b3dSmrg  i810XvMCContext *pI810XvMC;
3480428d7b3dSmrg  i810XvMCSubpicture *pI810Subpicture;
3481428d7b3dSmrg  int priv_count;
3482428d7b3dSmrg  uint *priv_data;
3483428d7b3dSmrg  Status ret;
3484428d7b3dSmrg
3485428d7b3dSmrg  if((subpicture == NULL) || (context == NULL) || (display == NULL)){
3486428d7b3dSmrg    return BadValue;
3487428d7b3dSmrg  }
3488428d7b3dSmrg
3489428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)context->privData;
3490428d7b3dSmrg  if(pI810XvMC == NULL) {
3491428d7b3dSmrg    return (error_base + XvMCBadContext);
3492428d7b3dSmrg  }
3493428d7b3dSmrg
3494428d7b3dSmrg
3495428d7b3dSmrg  subpicture->context_id = context->context_id;
3496428d7b3dSmrg  subpicture->xvimage_id = xvimage_id;
3497428d7b3dSmrg
3498428d7b3dSmrg  /* These need to be checked to make sure they are not too big! */
3499428d7b3dSmrg  subpicture->width = width;
3500428d7b3dSmrg  subpicture->height = height;
3501428d7b3dSmrg
3502428d7b3dSmrg  subpicture->privData =
3503428d7b3dSmrg    (i810XvMCSubpicture *)malloc(sizeof(i810XvMCSubpicture));
3504428d7b3dSmrg
3505428d7b3dSmrg  if(!subpicture->privData) {
3506428d7b3dSmrg    return BadAlloc;
3507428d7b3dSmrg  }
3508428d7b3dSmrg  pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
3509428d7b3dSmrg
3510428d7b3dSmrg
3511428d7b3dSmrg  if((ret = _xvmc_create_subpicture(display, context, subpicture,
3512428d7b3dSmrg				    &priv_count, &priv_data))) {
3513428d7b3dSmrg    printf("Unable to create XvMCSubpicture.\n");
3514428d7b3dSmrg    return ret;
3515428d7b3dSmrg  }
3516428d7b3dSmrg
3517428d7b3dSmrg  if(priv_count != 1) {
3518428d7b3dSmrg    printf("_xvmc_create_subpicture() returned incorrect data size.\n");
3519428d7b3dSmrg    printf("Expected 1 got %d\n",priv_count);
3520428d7b3dSmrg    free(priv_data);
3521428d7b3dSmrg    return BadAlloc;
3522428d7b3dSmrg  }
3523428d7b3dSmrg  /* Data == Client Address, offset == Physical address offset */
3524428d7b3dSmrg  pI810Subpicture->data = pI810XvMC->surfaces.address;
3525428d7b3dSmrg  pI810Subpicture->offset = pI810XvMC->surfaces.offset;
3526428d7b3dSmrg
3527428d7b3dSmrg  /* Initialize private values */
3528428d7b3dSmrg  pI810Subpicture->privContext = pI810XvMC;
3529428d7b3dSmrg
3530428d7b3dSmrg  pI810Subpicture->last_render = 0;
3531428d7b3dSmrg  pI810Subpicture->last_flip = 0;
3532428d7b3dSmrg
3533428d7b3dSmrg  /* Based on the xvimage_id we will need to set the other values */
3534428d7b3dSmrg  subpicture->num_palette_entries = 16;
3535428d7b3dSmrg  subpicture->entry_bytes = 3;
3536428d7b3dSmrg  strcpy(subpicture->component_order,"YUV");
3537428d7b3dSmrg
3538428d7b3dSmrg  /*
3539428d7b3dSmrg    i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch
3540428d7b3dSmrg    and the Tiler need 512k aligned surfaces, basically we are
3541428d7b3dSmrg    stuck with fixed memory with pitch 1024.
3542428d7b3dSmrg  */
3543428d7b3dSmrg  pI810Subpicture->pitch = 10;
3544428d7b3dSmrg
3545428d7b3dSmrg  /*
3546428d7b3dSmrg     offsets[0] == offset into the map described by either
3547428d7b3dSmrg     address (Client memeory address) or offset (physical offset from fb base)
3548428d7b3dSmrg  */
3549428d7b3dSmrg  pI810Subpicture->offsets[0] = priv_data[0];
3550428d7b3dSmrg  if(((unsigned long)pI810Subpicture->data + pI810Subpicture->offsets[0]) & 4095) {
3551428d7b3dSmrg    printf("XvMCCreateSubpicture: Subpicture offset 0 is not 4096 aligned\n");
3552428d7b3dSmrg  }
3553428d7b3dSmrg
3554428d7b3dSmrg  /* Free data returned from xvmc_create_surface */
3555428d7b3dSmrg  free(priv_data);
3556428d7b3dSmrg
3557428d7b3dSmrg  /* Clear the surface to 0 */
3558428d7b3dSmrg  memset((void *)((unsigned long)pI810Subpicture->data + (unsigned long)pI810Subpicture->offsets[0]),
3559428d7b3dSmrg	 0, ((1<<pI810Subpicture->pitch) * subpicture->height));
3560428d7b3dSmrg
3561428d7b3dSmrg  switch(subpicture->xvimage_id) {
3562428d7b3dSmrg  case FOURCC_IA44:
3563428d7b3dSmrg  case FOURCC_AI44:
3564428d7b3dSmrg    /* Destination buffer info command */
3565428d7b3dSmrg    pI810Subpicture->dbi1 = ((((unsigned int)pI810Subpicture->offset +
3566428d7b3dSmrg			       pI810Subpicture->offsets[0]) & ~0xfc000fff) |
3567428d7b3dSmrg			     (pI810Subpicture->pitch - 9));
3568428d7b3dSmrg
3569428d7b3dSmrg    /* Destination buffer variables command */
3570428d7b3dSmrg    pI810Subpicture->dbv1 = (0x8<<20) | (0x8<<16);
3571428d7b3dSmrg
3572428d7b3dSmrg    /* Map info command */
3573428d7b3dSmrg    pI810Subpicture->mi1 = (0x0<<24) | (3<<21) | (1<<9) |
3574428d7b3dSmrg      (pI810Subpicture->pitch - 3);
3575428d7b3dSmrg
3576428d7b3dSmrg    pI810Subpicture->mi2 = (((unsigned int)subpicture->height - 1)<<16) |
3577428d7b3dSmrg      ((unsigned int)subpicture->width - 1);
3578428d7b3dSmrg
3579428d7b3dSmrg    pI810Subpicture->mi3 = ((unsigned int)pI810Subpicture->offset +
3580428d7b3dSmrg			 pI810Subpicture->offsets[0]) & ~0xfc00000f;
3581428d7b3dSmrg    break;
3582428d7b3dSmrg  default:
3583428d7b3dSmrg    free(subpicture->privData);
3584428d7b3dSmrg    return BadMatch;
3585428d7b3dSmrg  }
3586428d7b3dSmrg
3587428d7b3dSmrg  pI810XvMC->ref++;
3588428d7b3dSmrg  return Success;
3589428d7b3dSmrg}
3590428d7b3dSmrg
3591428d7b3dSmrg
3592428d7b3dSmrg
3593428d7b3dSmrg/***************************************************************************
3594428d7b3dSmrg// Function: XvMCClearSubpicture
3595428d7b3dSmrg// Description: Clear the area of the given subpicture to "color".
3596428d7b3dSmrg//              structure passed to it and returning Success.
3597428d7b3dSmrg// Arguments:
3598428d7b3dSmrg//   display - Connection to the X server.
3599428d7b3dSmrg//   subpicture - Subpicture to clear.
3600428d7b3dSmrg//   x, y, width, height - rectangle in the subpicture to clear.
3601428d7b3dSmrg//   color - The data to file the rectangle with.
3602428d7b3dSmrg//
3603428d7b3dSmrg// Returns: Status
3604428d7b3dSmrg***************************************************************************/
3605428d7b3dSmrg_X_EXPORT Status XvMCClearSubpicture(Display *display, XvMCSubpicture *subpicture,
3606428d7b3dSmrg                          short x, short y,
3607428d7b3dSmrg                          unsigned short width, unsigned short height,
3608428d7b3dSmrg                          unsigned int color) {
3609428d7b3dSmrg
3610428d7b3dSmrg  i810XvMCContext *pI810XvMC;
3611428d7b3dSmrg  i810XvMCSubpicture *pI810Subpicture;
3612428d7b3dSmrg  int i;
3613428d7b3dSmrg
3614428d7b3dSmrg  if((subpicture == NULL) || (display == NULL)){
3615428d7b3dSmrg    return BadValue;
3616428d7b3dSmrg  }
3617428d7b3dSmrg
3618428d7b3dSmrg  if(!subpicture->privData) {
3619428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
3620428d7b3dSmrg  }
3621428d7b3dSmrg  pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
3622428d7b3dSmrg
3623428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
3624428d7b3dSmrg  if(pI810XvMC == NULL) {
3625428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
3626428d7b3dSmrg  }
3627428d7b3dSmrg
3628428d7b3dSmrg  if((x < 0) || (x + width > subpicture->width)) {
3629428d7b3dSmrg    return BadValue;
3630428d7b3dSmrg  }
3631428d7b3dSmrg
3632428d7b3dSmrg  if((y < 0) || (y + height > subpicture->height)) {
3633428d7b3dSmrg    return BadValue;
3634428d7b3dSmrg  }
3635428d7b3dSmrg
3636428d7b3dSmrg  for(i=y; i<y + height; i++) {
3637428d7b3dSmrg    memset((void *)((unsigned long)pI810Subpicture->data +
3638428d7b3dSmrg		    (unsigned long)pI810Subpicture->offsets[0] + x +
3639428d7b3dSmrg		    (1<<pI810Subpicture->pitch) * i),(char)color,width);
3640428d7b3dSmrg  }
3641428d7b3dSmrg
3642428d7b3dSmrg  return Success;
3643428d7b3dSmrg}
3644428d7b3dSmrg
3645428d7b3dSmrg/***************************************************************************
3646428d7b3dSmrg// Function: XvMCCompositeSubpicture
3647428d7b3dSmrg// Description: Composite the XvImae on the subpicture. This composit uses
3648428d7b3dSmrg//              non-premultiplied alpha. Destination alpha is utilized
3649428d7b3dSmrg//              except for with indexed subpictures. Indexed subpictures
3650428d7b3dSmrg//              use a simple "replace".
3651428d7b3dSmrg// Arguments:
3652428d7b3dSmrg//   display - Connection to the X server.
3653428d7b3dSmrg//   subpicture - Subpicture to clear.
3654428d7b3dSmrg//   image - the XvImage to be used as the source of the composite.
3655428d7b3dSmrg//   srcx, srcy, width, height - The rectangle from the image to be used.
3656428d7b3dSmrg//   dstx, dsty - location in the subpicture to composite the source.
3657428d7b3dSmrg//
3658428d7b3dSmrg// Returns: Status
3659428d7b3dSmrg***************************************************************************/
3660428d7b3dSmrg_X_EXPORT Status XvMCCompositeSubpicture(Display *display, XvMCSubpicture *subpicture,
3661428d7b3dSmrg                               XvImage *image,
3662428d7b3dSmrg                               short srcx, short srcy,
3663428d7b3dSmrg                               unsigned short width, unsigned short height,
3664428d7b3dSmrg                               short dstx, short dsty) {
3665428d7b3dSmrg
3666428d7b3dSmrg  i810XvMCContext *pI810XvMC;
3667428d7b3dSmrg  i810XvMCSubpicture *pI810Subpicture;
3668428d7b3dSmrg  int i;
3669428d7b3dSmrg
3670428d7b3dSmrg  if((subpicture == NULL) || (display == NULL)){
3671428d7b3dSmrg    return BadValue;
3672428d7b3dSmrg  }
3673428d7b3dSmrg
3674428d7b3dSmrg  if(!subpicture->privData) {
3675428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
3676428d7b3dSmrg  }
3677428d7b3dSmrg  pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
3678428d7b3dSmrg
3679428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
3680428d7b3dSmrg  if(pI810XvMC == NULL) {
3681428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
3682428d7b3dSmrg  }
3683428d7b3dSmrg
3684428d7b3dSmrg  if((srcx < 0) || (srcx + width > image->width)) {
3685428d7b3dSmrg    return BadValue;
3686428d7b3dSmrg  }
3687428d7b3dSmrg
3688428d7b3dSmrg  if((dstx < 0) || (dstx + width > subpicture->width)) {
3689428d7b3dSmrg    return BadValue;
3690428d7b3dSmrg  }
3691428d7b3dSmrg
3692428d7b3dSmrg  if((srcy < 0) || (srcy + height > image->height)) {
3693428d7b3dSmrg    return BadValue;
3694428d7b3dSmrg  }
3695428d7b3dSmrg
3696428d7b3dSmrg  if((dsty < 0) || (dsty + height > subpicture->height)) {
3697428d7b3dSmrg    return BadValue;
3698428d7b3dSmrg  }
3699428d7b3dSmrg
3700428d7b3dSmrg  for(i=0; i<height; i++) {
3701428d7b3dSmrg    memcpy((void *)((unsigned long)pI810Subpicture->data +
3702428d7b3dSmrg		    (unsigned long)pI810Subpicture->offsets[0] + dstx +
3703428d7b3dSmrg		    (1<<pI810Subpicture->pitch) * (i + dsty)),
3704428d7b3dSmrg	   (void *)((unsigned long)image->data +
3705428d7b3dSmrg		    (unsigned long)image->offsets[0] + srcx +
3706428d7b3dSmrg		    image->pitches[0] * (i + srcy))
3707428d7b3dSmrg	   ,width);
3708428d7b3dSmrg  }
3709428d7b3dSmrg
3710428d7b3dSmrg  return Success;
3711428d7b3dSmrg
3712428d7b3dSmrg}
3713428d7b3dSmrg
3714428d7b3dSmrg
3715428d7b3dSmrg/***************************************************************************
3716428d7b3dSmrg// Function: XvMCDestroySubpicture
3717428d7b3dSmrg// Description: Destroys the specified subpicture.
3718428d7b3dSmrg// Arguments:
3719428d7b3dSmrg//   display - Connection to the X server.
3720428d7b3dSmrg//   subpicture - Subpicture to be destroyed.
3721428d7b3dSmrg//
3722428d7b3dSmrg// Returns: Status
3723428d7b3dSmrg***************************************************************************/
3724428d7b3dSmrg_X_EXPORT Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture) {
3725428d7b3dSmrg
3726428d7b3dSmrg  i810XvMCSubpicture *pI810Subpicture;
3727428d7b3dSmrg  i810XvMCContext *pI810XvMC;
3728428d7b3dSmrg
3729428d7b3dSmrg  if((display == NULL) || (subpicture == NULL)) {
3730428d7b3dSmrg    return BadValue;
3731428d7b3dSmrg  }
3732428d7b3dSmrg  if(!subpicture->privData) {
3733428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
3734428d7b3dSmrg  }
3735428d7b3dSmrg  pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
3736428d7b3dSmrg
3737428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
3738428d7b3dSmrg  if(!pI810XvMC) {
3739428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
3740428d7b3dSmrg  }
3741428d7b3dSmrg
3742428d7b3dSmrg
3743428d7b3dSmrg  if(pI810Subpicture->last_render) {
3744428d7b3dSmrg    XvMCSyncSubpicture(display,subpicture);
3745428d7b3dSmrg  }
3746428d7b3dSmrg
3747428d7b3dSmrg  _xvmc_destroy_subpicture(display,subpicture);
3748428d7b3dSmrg
3749428d7b3dSmrg  i810_free_privContext(pI810XvMC);
3750428d7b3dSmrg
3751428d7b3dSmrg  free(pI810Subpicture);
3752428d7b3dSmrg  subpicture->privData = NULL;
3753428d7b3dSmrg  return Success;
3754428d7b3dSmrg}
3755428d7b3dSmrg
3756428d7b3dSmrg
3757428d7b3dSmrg/***************************************************************************
3758428d7b3dSmrg// Function: XvMCSetSubpicturePalette
3759428d7b3dSmrg// Description: Set the subpictures palette
3760428d7b3dSmrg// Arguments:
3761428d7b3dSmrg//   display - Connection to the X server.
3762428d7b3dSmrg//   subpicture - Subpiture to set palette for.
3763428d7b3dSmrg//   palette - A pointer to an array holding the palette data. The array
3764428d7b3dSmrg//     is num_palette_entries * entry_bytes in size.
3765428d7b3dSmrg// Returns: Status
3766428d7b3dSmrg***************************************************************************/
3767428d7b3dSmrg
3768428d7b3dSmrg_X_EXPORT Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture,
3769428d7b3dSmrg				unsigned char *palette) {
3770428d7b3dSmrg i810XvMCSubpicture *privSubpicture;
3771428d7b3dSmrg int i,j;
3772428d7b3dSmrg
3773428d7b3dSmrg if((display == NULL) || (subpicture == NULL)) {
3774428d7b3dSmrg   return BadValue;
3775428d7b3dSmrg }
3776428d7b3dSmrg if(subpicture->privData == NULL) {
3777428d7b3dSmrg   return (error_base + XvMCBadSubpicture);
3778428d7b3dSmrg }
3779428d7b3dSmrg privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
3780428d7b3dSmrg
3781428d7b3dSmrg j=0;
3782428d7b3dSmrg for(i=0; i<16; i++) {
3783428d7b3dSmrg   privSubpicture->palette[0][i] = palette[j++];
3784428d7b3dSmrg   privSubpicture->palette[1][i] = palette[j++];
3785428d7b3dSmrg   privSubpicture->palette[2][i] = palette[j++];
3786428d7b3dSmrg }
3787428d7b3dSmrg return Success;
3788428d7b3dSmrg}
3789428d7b3dSmrg
3790428d7b3dSmrg/***************************************************************************
3791428d7b3dSmrg// Function: XvMCBlendSubpicture
3792428d7b3dSmrg// Description:
3793428d7b3dSmrg//    The behavior of this function is different depending on whether
3794428d7b3dSmrg//    or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
3795428d7b3dSmrg//    i810 only support frontend behavior.
3796428d7b3dSmrg//
3797428d7b3dSmrg//    XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
3798428d7b3dSmrg//
3799428d7b3dSmrg//    XvMCBlendSubpicture is a no-op in this case.
3800428d7b3dSmrg//
3801428d7b3dSmrg// Arguments:
3802428d7b3dSmrg//   display - Connection to the X server.
3803428d7b3dSmrg//   subpicture - The subpicture to be blended into the video.
3804428d7b3dSmrg//   target_surface - The surface to be displayed with the blended subpic.
3805428d7b3dSmrg//   source_surface - Source surface prior to blending.
3806428d7b3dSmrg//   subx, suby, subw, subh - The rectangle from the subpicture to use.
3807428d7b3dSmrg//   surfx, surfy, surfw, surfh - The rectangle in the surface to blend
3808428d7b3dSmrg//      blend the subpicture rectangle into. Scaling can ocure if
3809428d7b3dSmrg//      XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
3810428d7b3dSmrg//
3811428d7b3dSmrg// Returns: Status
3812428d7b3dSmrg***************************************************************************/
3813428d7b3dSmrg_X_EXPORT Status XvMCBlendSubpicture(Display *display, XvMCSurface *target_surface,
3814428d7b3dSmrg                         XvMCSubpicture *subpicture,
3815428d7b3dSmrg                         short subx, short suby,
3816428d7b3dSmrg                         unsigned short subw, unsigned short subh,
3817428d7b3dSmrg                         short surfx, short surfy,
3818428d7b3dSmrg                         unsigned short surfw, unsigned short surfh) {
3819428d7b3dSmrg
3820428d7b3dSmrg  return BadMatch;
3821428d7b3dSmrg}
3822428d7b3dSmrg
3823428d7b3dSmrg
3824428d7b3dSmrg
3825428d7b3dSmrg/***************************************************************************
3826428d7b3dSmrg// Function: XvMCBlendSubpicture2
3827428d7b3dSmrg// Description:
3828428d7b3dSmrg//    The behavior of this function is different depending on whether
3829428d7b3dSmrg//    or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
3830428d7b3dSmrg//    i810 only supports frontend blending.
3831428d7b3dSmrg//
3832428d7b3dSmrg//    XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
3833428d7b3dSmrg//
3834428d7b3dSmrg//    XvMCBlendSubpicture2 blends the source_surface and subpicture and
3835428d7b3dSmrg//    puts it in the target_surface.  This does not effect the status of
3836428d7b3dSmrg//    the source surface but will cause the target_surface to query
3837428d7b3dSmrg//    XVMC_RENDERING until the blend is completed.
3838428d7b3dSmrg//
3839428d7b3dSmrg// Arguments:
3840428d7b3dSmrg//   display - Connection to the X server.
3841428d7b3dSmrg//   subpicture - The subpicture to be blended into the video.
3842428d7b3dSmrg//   target_surface - The surface to be displayed with the blended subpic.
3843428d7b3dSmrg//   source_surface - Source surface prior to blending.
3844428d7b3dSmrg//   subx, suby, subw, subh - The rectangle from the subpicture to use.
3845428d7b3dSmrg//   surfx, surfy, surfw, surfh - The rectangle in the surface to blend
3846428d7b3dSmrg//      blend the subpicture rectangle into. Scaling can ocure if
3847428d7b3dSmrg//      XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
3848428d7b3dSmrg//
3849428d7b3dSmrg// Returns: Status
3850428d7b3dSmrg***************************************************************************/
3851428d7b3dSmrg_X_EXPORT Status XvMCBlendSubpicture2(Display *display,
3852428d7b3dSmrg                          XvMCSurface *source_surface,
3853428d7b3dSmrg                          XvMCSurface *target_surface,
3854428d7b3dSmrg                          XvMCSubpicture *subpicture,
3855428d7b3dSmrg                          short subx, short suby,
3856428d7b3dSmrg                          unsigned short subw, unsigned short subh,
3857428d7b3dSmrg                          short surfx, short surfy,
3858428d7b3dSmrg                          unsigned short surfw, unsigned short surfh) {
3859428d7b3dSmrg  drmBufPtr pDMA;
3860428d7b3dSmrg  unsigned int *data;
3861428d7b3dSmrg  i810XvMCContext *pI810XvMC;
3862428d7b3dSmrg  i810XvMCSubpicture *privSubpicture;
3863428d7b3dSmrg  i810XvMCSurface *privTarget;
3864428d7b3dSmrg  i810XvMCSurface *privSource;
3865428d7b3dSmrg  drm_i810_mc_t mc;
3866428d7b3dSmrg  int i,j;
3867428d7b3dSmrg
3868428d7b3dSmrg  if(display == NULL) {
3869428d7b3dSmrg    return BadValue;
3870428d7b3dSmrg  }
3871428d7b3dSmrg
3872428d7b3dSmrg  if(subpicture == NULL) {
3873428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
3874428d7b3dSmrg  }
3875428d7b3dSmrg
3876428d7b3dSmrg  if((target_surface == NULL) || (source_surface == NULL)) {
3877428d7b3dSmrg    return (error_base + XvMCBadSurface);
3878428d7b3dSmrg  }
3879428d7b3dSmrg
3880428d7b3dSmrg  if((subpicture->xvimage_id != FOURCC_AI44) &&
3881428d7b3dSmrg     (subpicture->xvimage_id != FOURCC_IA44)) {
3882428d7b3dSmrg      return (error_base + XvMCBadSubpicture);
3883428d7b3dSmrg  }
3884428d7b3dSmrg
3885428d7b3dSmrg  if(!subpicture->privData) {
3886428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
3887428d7b3dSmrg  }
3888428d7b3dSmrg  privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
3889428d7b3dSmrg
3890428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)privSubpicture->privContext;
3891428d7b3dSmrg  if(pI810XvMC == NULL) {
3892428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
3893428d7b3dSmrg  }
3894428d7b3dSmrg
3895428d7b3dSmrg  if(!target_surface->privData) {
3896428d7b3dSmrg    return (error_base + XvMCBadSurface);
3897428d7b3dSmrg  }
3898428d7b3dSmrg  privTarget = (i810XvMCSurface *)target_surface->privData;
3899428d7b3dSmrg
3900428d7b3dSmrg  if(!source_surface->privData) {
3901428d7b3dSmrg    return (error_base + XvMCBadSurface);
3902428d7b3dSmrg  }
3903428d7b3dSmrg  privSource = (i810XvMCSurface *)source_surface->privData;
3904428d7b3dSmrg
3905428d7b3dSmrg
3906428d7b3dSmrg  /* Check that size isn't bigger than subpicture */
3907428d7b3dSmrg  if((subx + subw) > subpicture->width) {
3908428d7b3dSmrg    return BadValue;
3909428d7b3dSmrg  }
3910428d7b3dSmrg  if((suby + subh) > subpicture->height) {
3911428d7b3dSmrg    return BadValue;
3912428d7b3dSmrg  }
3913428d7b3dSmrg  /* Check that dest isn't bigger than surface */
3914428d7b3dSmrg  if((surfx + surfw) > target_surface->width) {
3915428d7b3dSmrg    return BadValue;
3916428d7b3dSmrg  }
3917428d7b3dSmrg  if((surfy + surfh) > target_surface->height) {
3918428d7b3dSmrg    return BadValue;
3919428d7b3dSmrg  }
3920428d7b3dSmrg  /* Make sure surfaces match */
3921428d7b3dSmrg  if(target_surface->width != source_surface->width) {
3922428d7b3dSmrg    return BadValue;
3923428d7b3dSmrg  }
3924428d7b3dSmrg  if(target_surface->height != source_surface->height) {
3925428d7b3dSmrg    return BadValue;
3926428d7b3dSmrg  }
3927428d7b3dSmrg
3928428d7b3dSmrg  /* Lock For DMA */
3929428d7b3dSmrg  I810_LOCK(pI810XvMC,0);
3930428d7b3dSmrg
3931428d7b3dSmrg  /* Allocate DMA buffer */
3932428d7b3dSmrg  pDMA = i810_get_free_buffer(pI810XvMC);
3933428d7b3dSmrg  data = pDMA->address;
3934428d7b3dSmrg
3935428d7b3dSmrg  /* Copy Y data first */
3936428d7b3dSmrg  /* SOURCE_COPY_BLT */
3937428d7b3dSmrg  *data++ = (2<<29) | (0x43<<22) | 0x4;
3938428d7b3dSmrg  *data++ = (0xcc<<16) | (1<<26) | (1<<privTarget->pitch);
3939428d7b3dSmrg  *data++ = (target_surface->height<<16) | target_surface->width;
3940428d7b3dSmrg  *data++ = privTarget->offset + privTarget->offsets[0];
3941428d7b3dSmrg  *data++ = (1<<privSource->pitch);
3942428d7b3dSmrg  *data++ = privSource->offset + privSource->offsets[0];
3943428d7b3dSmrg
3944428d7b3dSmrg  /* Select Context 1 for loading */
3945428d7b3dSmrg  *data++ = CMD_FLUSH;
3946428d7b3dSmrg  *data++ = (5<<23) | (1<<17) | (1<<8);
3947428d7b3dSmrg  *data++ = CMD_FLUSH;
3948428d7b3dSmrg
3949428d7b3dSmrg  /* Load Palette */
3950428d7b3dSmrg  *data++ = MAP_PALETTE_LOAD;
3951428d7b3dSmrg  /* 16 levels of alpha for each Y */
3952428d7b3dSmrg  switch(subpicture->xvimage_id) {
3953428d7b3dSmrg  case FOURCC_IA44:
3954428d7b3dSmrg    for(i=0; i<16; i++) {
3955428d7b3dSmrg      for(j=0; j<16; j++) {
3956428d7b3dSmrg        *data++ = (j<<12) | (j<<8) | privSubpicture->palette[0][i];
3957428d7b3dSmrg      }
3958428d7b3dSmrg    }
3959428d7b3dSmrg    break;
3960428d7b3dSmrg  case FOURCC_AI44:
3961428d7b3dSmrg    for(i=0; i<16; i++) {
3962428d7b3dSmrg      for(j=0; j<16; j++) {
3963428d7b3dSmrg        *data++ = (i<<12) | (i<<8) | privSubpicture->palette[0][j];
3964428d7b3dSmrg      }
3965428d7b3dSmrg    }
3966428d7b3dSmrg    break;
3967428d7b3dSmrg  }
3968428d7b3dSmrg  /* TARGET */
3969428d7b3dSmrg  /* *data++ = CMD_FLUSH; */
3970428d7b3dSmrg  /* *data++ = BOOLEAN_ENA_2; */
3971428d7b3dSmrg  *data++ = CMD_FLUSH;
3972428d7b3dSmrg  *data++ = DEST_BUFFER_INFO;
3973428d7b3dSmrg  *data++ = privTarget->dbi1y;
3974428d7b3dSmrg  *data++ = DEST_BUFFER_VAR;
3975428d7b3dSmrg  *data++ = privTarget->dbv1;
3976428d7b3dSmrg
3977428d7b3dSmrg  /* ALPHA */
3978428d7b3dSmrg  *data++ = CMD_MAP_INFO;
3979428d7b3dSmrg  *data++ = privSubpicture->mi1;
3980428d7b3dSmrg  *data++ = privSubpicture->mi2;
3981428d7b3dSmrg  *data++ = privSubpicture->mi3;
3982428d7b3dSmrg
3983428d7b3dSmrg  *data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
3984428d7b3dSmrg  *data++ = BOOLEAN_ENA_1;
3985428d7b3dSmrg  *data++ = SRC_DEST_BLEND_MONO | (0x940);
3986428d7b3dSmrg  /* Map Filter */
3987428d7b3dSmrg  *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (0x224);
3988428d7b3dSmrg
3989428d7b3dSmrg  /* Use context 1 */
3990428d7b3dSmrg  *data++ = CMD_FLUSH;
3991428d7b3dSmrg  *data++ = (5<<23) | (1<<16) | 1;
3992428d7b3dSmrg  *data++ = CMD_FLUSH;
3993428d7b3dSmrg
3994428d7b3dSmrg  /* Drawing Rect Info */
3995428d7b3dSmrg  *data++ = DRAWING_RECT_INFO;
3996428d7b3dSmrg  *data++ = 0x0;
3997428d7b3dSmrg  *data++ = 0x0;
3998428d7b3dSmrg  *data++ = 0x0;
3999428d7b3dSmrg  *data++ = 0x0;
4000428d7b3dSmrg  *data++ = 0x0;
4001428d7b3dSmrg
4002428d7b3dSmrg  /* GFXPRIMITIVE RECTANGLE */
4003428d7b3dSmrg  *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
4004428d7b3dSmrg  /* Bottom Right Vertex */
4005428d7b3dSmrg  *(float *)data++ = (float) (surfx + surfw);
4006428d7b3dSmrg  *(float *)data++ = (float) (surfy + surfh);
4007428d7b3dSmrg  *(float *)data++ = (float) (subx + subw);
4008428d7b3dSmrg  *(float *)data++ = (float) (suby + subh);
4009428d7b3dSmrg  /* Bottom Left Vertex */
4010428d7b3dSmrg  *(float *)data++ = (float) surfx;
4011428d7b3dSmrg  *(float *)data++ = (float) (surfy + surfh);
4012428d7b3dSmrg  *(float *)data++ = (float) subx;
4013428d7b3dSmrg  *(float *)data++ = (float) (suby + subh);
4014428d7b3dSmrg  /* Top Left Vertex */
4015428d7b3dSmrg  *(float *)data++ = (float) surfx;
4016428d7b3dSmrg  *(float *)data++ = (float) surfy;
4017428d7b3dSmrg  *(float *)data++ = (float) subx;
4018428d7b3dSmrg  *(float *)data++ = (float) suby;
4019428d7b3dSmrg
4020428d7b3dSmrg  /* Load and Use Context 0 */
4021428d7b3dSmrg  *data++ = CMD_FLUSH;
4022428d7b3dSmrg  *data++ = (5<<23) | (1<<17) | (1<<16);
4023428d7b3dSmrg  *data++ = CMD_FLUSH;
4024428d7b3dSmrg
4025428d7b3dSmrg  /* U data */
4026428d7b3dSmrg  /* SOURCE_COPY_BLT */
4027428d7b3dSmrg  *data++ = (2<<29) | (0x43<<22) | 0x4;
4028428d7b3dSmrg  *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1));
4029428d7b3dSmrg  *data++ = (target_surface->height<<15) | (target_surface->width>>1);
4030428d7b3dSmrg  *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[1];
4031428d7b3dSmrg  *data++ = (1<<(privSource->pitch - 1));
4032428d7b3dSmrg  *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[1];
4033428d7b3dSmrg
4034428d7b3dSmrg  /* Context 1 select */
4035428d7b3dSmrg  *data++ = CMD_FLUSH;
4036428d7b3dSmrg  *data++ = (5<<23) | (1<<17) | (1<<8);
4037428d7b3dSmrg  *data++ = CMD_FLUSH;
4038428d7b3dSmrg  /* ALPHA PALETTE */
4039428d7b3dSmrg  *data++ = MAP_PALETTE_LOAD;
4040428d7b3dSmrg  /* 16 levels of alpha for each Y */
4041428d7b3dSmrg  switch(subpicture->xvimage_id) {
4042428d7b3dSmrg  case FOURCC_IA44:
4043428d7b3dSmrg    for(i=0; i<16; i++) {
4044428d7b3dSmrg      for(j=0; j<16; j++) {
4045428d7b3dSmrg        *data++ = (j<<12) | (j<<8) | privSubpicture->palette[2][i];
4046428d7b3dSmrg      }
4047428d7b3dSmrg    }
4048428d7b3dSmrg    break;
4049428d7b3dSmrg  case FOURCC_AI44:
4050428d7b3dSmrg    for(i=0; i<16; i++) {
4051428d7b3dSmrg      for(j=0; j<16; j++) {
4052428d7b3dSmrg        *data++ = (i<<12) | (i<<8) | privSubpicture->palette[2][j];
4053428d7b3dSmrg      }
4054428d7b3dSmrg    }
4055428d7b3dSmrg    break;
4056428d7b3dSmrg  }
4057428d7b3dSmrg  /* TARGET */
4058428d7b3dSmrg  *data++ = CMD_FLUSH;
4059428d7b3dSmrg  *data++ = BOOLEAN_ENA_2;
4060428d7b3dSmrg  *data++ = CMD_FLUSH;
4061428d7b3dSmrg  *data++ = DEST_BUFFER_INFO;
4062428d7b3dSmrg  *data++ = privTarget->dbi1u;
4063428d7b3dSmrg  *data++ = DEST_BUFFER_VAR;
4064428d7b3dSmrg  *data++ = privTarget->dbv1;
4065428d7b3dSmrg
4066428d7b3dSmrg  /* ALPHA */
4067428d7b3dSmrg  *data++ = CMD_MAP_INFO;
4068428d7b3dSmrg  *data++ = privSubpicture->mi1;
4069428d7b3dSmrg  *data++ = privSubpicture->mi2;
4070428d7b3dSmrg  *data++ = privSubpicture->mi3;
4071428d7b3dSmrg
4072428d7b3dSmrg  *data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
4073428d7b3dSmrg  *data++ = BOOLEAN_ENA_1;
4074428d7b3dSmrg  *data++ = SRC_DEST_BLEND_MONO | (0x940);
4075428d7b3dSmrg  /* Map Filter */
4076428d7b3dSmrg  *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224);
4077428d7b3dSmrg
4078428d7b3dSmrg  /* Use context 1 */
4079428d7b3dSmrg  *data++ = CMD_FLUSH;
4080428d7b3dSmrg  *data++ = (5<<23) | (1<<16) | 1;
4081428d7b3dSmrg  *data++ = CMD_FLUSH;
4082428d7b3dSmrg
4083428d7b3dSmrg  /* Drawing Rect Info */
4084428d7b3dSmrg  *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3;
4085428d7b3dSmrg  *data++ = 0;
4086428d7b3dSmrg  *data++ = 0;
4087428d7b3dSmrg  *data++ = 0;
4088428d7b3dSmrg  *data++ = 0;
4089428d7b3dSmrg  *data++ = 0;
4090428d7b3dSmrg
4091428d7b3dSmrg  /* Rectangle */
4092428d7b3dSmrg  *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
4093428d7b3dSmrg  /* Bottom Right */
4094428d7b3dSmrg  *(float *)data++ = (float) ((surfx + surfw)>>1);
4095428d7b3dSmrg  *(float *)data++ = (float) ((surfy + surfh)>>1);
4096428d7b3dSmrg  *(float *)data++ = (float) subx + subw;
4097428d7b3dSmrg  *(float *)data++ = (float) suby + subh;
4098428d7b3dSmrg  /* Bottom Left */
4099428d7b3dSmrg  *(float *)data++ = (float) (surfx>>1);
4100428d7b3dSmrg  *(float *)data++ = (float) ((surfy + surfh)>>1);
4101428d7b3dSmrg  *(float *)data++ = (float) subx;
4102428d7b3dSmrg  *(float *)data++ = (float) suby + subh;
4103428d7b3dSmrg  /* Top Left */
4104428d7b3dSmrg  *(float *)data++ = (float) (surfx>>1);
4105428d7b3dSmrg  *(float *)data++ = (float) (surfy>>1);
4106428d7b3dSmrg  *(float *)data++ = (float) subx;
4107428d7b3dSmrg  *(float *)data++ = (float) suby;
4108428d7b3dSmrg
4109428d7b3dSmrg  /* Load and Use Context 0 */
4110428d7b3dSmrg  *data++ = CMD_FLUSH;
4111428d7b3dSmrg  *data++ = (5<<23) | (1<<17) | (1<<16);
4112428d7b3dSmrg  *data++ = CMD_FLUSH;
4113428d7b3dSmrg
4114428d7b3dSmrg  /* V data */
4115428d7b3dSmrg  /* SOURCE_COPY_BLT */
4116428d7b3dSmrg  *data++ = (2<<29) | (0x43<<22) | 0x4;
4117428d7b3dSmrg  *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1));
4118428d7b3dSmrg  *data++ = (target_surface->height<<15) | (target_surface->width>>1);
4119428d7b3dSmrg  *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[2];
4120428d7b3dSmrg  *data++ = (1<<(privSource->pitch - 1));
4121428d7b3dSmrg  *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[2];
4122428d7b3dSmrg
4123428d7b3dSmrg  /* Context 1 select */
4124428d7b3dSmrg  *data++ = CMD_FLUSH;
4125428d7b3dSmrg  *data++ = (5<<23) | (1<<17) | (1<<8);
4126428d7b3dSmrg  *data++ = CMD_FLUSH;
4127428d7b3dSmrg
4128428d7b3dSmrg  /* ALPHA PALETTE */
4129428d7b3dSmrg  *data++ = MAP_PALETTE_LOAD;
4130428d7b3dSmrg  /* 16 levels of alpha for each Y */
4131428d7b3dSmrg  switch(subpicture->xvimage_id) {
4132428d7b3dSmrg  case FOURCC_IA44:
4133428d7b3dSmrg    for(i=0; i<16; i++) {
4134428d7b3dSmrg      for(j=0; j<16; j++) {
4135428d7b3dSmrg        *data++ = (j<<12) | (j<<8) | privSubpicture->palette[1][i];
4136428d7b3dSmrg      }
4137428d7b3dSmrg    }
4138428d7b3dSmrg    break;
4139428d7b3dSmrg  case FOURCC_AI44:
4140428d7b3dSmrg    for(i=0; i<16; i++) {
4141428d7b3dSmrg      for(j=0; j<16; j++) {
4142428d7b3dSmrg        *data++ = (i<<12) | (i<<8) | privSubpicture->palette[1][j];
4143428d7b3dSmrg      }
4144428d7b3dSmrg    }
4145428d7b3dSmrg    break;
4146428d7b3dSmrg  }
4147428d7b3dSmrg  /* TARGET */
4148428d7b3dSmrg  *data++ = CMD_FLUSH;
4149428d7b3dSmrg  *data++ = BOOLEAN_ENA_2;
4150428d7b3dSmrg  *data++ = CMD_FLUSH;
4151428d7b3dSmrg  *data++ = DEST_BUFFER_INFO;
4152428d7b3dSmrg  *data++ = privTarget->dbi1v;
4153428d7b3dSmrg  *data++ = DEST_BUFFER_VAR;
4154428d7b3dSmrg  *data++ = privTarget->dbv1;
4155428d7b3dSmrg
4156428d7b3dSmrg  /* ALPHA */
4157428d7b3dSmrg  *data++ = CMD_MAP_INFO;
4158428d7b3dSmrg  *data++ = privSubpicture->mi1;
4159428d7b3dSmrg  *data++ = privSubpicture->mi2;
4160428d7b3dSmrg  *data++ = privSubpicture->mi3;
4161428d7b3dSmrg
4162428d7b3dSmrg  *data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
4163428d7b3dSmrg  *data++ = BOOLEAN_ENA_1;
4164428d7b3dSmrg  *data++ = SRC_DEST_BLEND_MONO | (0x940);
4165428d7b3dSmrg  /* Map Filter */
4166428d7b3dSmrg  *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224);
4167428d7b3dSmrg
4168428d7b3dSmrg  /* Use context 1 */
4169428d7b3dSmrg  *data++ = CMD_FLUSH;
4170428d7b3dSmrg  *data++ = (5<<23) | (1<<16) | 1;
4171428d7b3dSmrg  *data++ = CMD_FLUSH;
4172428d7b3dSmrg
4173428d7b3dSmrg  /* Drawing Rect Info */
4174428d7b3dSmrg  *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3;
4175428d7b3dSmrg  *data++ = 0;
4176428d7b3dSmrg  *data++ = 0;
4177428d7b3dSmrg  *data++ = 0;
4178428d7b3dSmrg  *data++ = 0;
4179428d7b3dSmrg  *data++ = 0;
4180428d7b3dSmrg
4181428d7b3dSmrg  /* Rectangle */
4182428d7b3dSmrg  *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
4183428d7b3dSmrg  /* Bottom Right */
4184428d7b3dSmrg  *(float *)data++ = (float) ((surfx + surfw)>>1);
4185428d7b3dSmrg  *(float *)data++ = (float) ((surfy + surfh)>>1);
4186428d7b3dSmrg  *(float *)data++ = (float) subx + subw;
4187428d7b3dSmrg  *(float *)data++ = (float) suby + subh;
4188428d7b3dSmrg  /* Bottom Left */
4189428d7b3dSmrg  *(float *)data++ = (float) (surfx>>1);
4190428d7b3dSmrg  *(float *)data++ = (float) ((surfy + surfh)>>1);
4191428d7b3dSmrg  *(float *)data++ = (float) subx;
4192428d7b3dSmrg  *(float *)data++ = (float) suby + subh;
4193428d7b3dSmrg  /* Top Left */
4194428d7b3dSmrg  *(float *)data++ = (float) (surfx>>1);
4195428d7b3dSmrg  *(float *)data++ = (float) (surfy>>1);
4196428d7b3dSmrg  *(float *)data++ = (float) subx;
4197428d7b3dSmrg  *(float *)data++ = (float) suby;
4198428d7b3dSmrg
4199428d7b3dSmrg  /* Load and Use Context 0 */
4200428d7b3dSmrg  *data++ = CMD_FLUSH;
4201428d7b3dSmrg  *data++ = (5<<23) | (1<<17) | (1<<16);
4202428d7b3dSmrg  *data++ = CMD_FLUSH;
4203428d7b3dSmrg
4204428d7b3dSmrg
4205428d7b3dSmrg  /* Dispatch */
4206428d7b3dSmrg  pDMA->used = (unsigned long)data - (unsigned long)pDMA->address;
4207428d7b3dSmrg  mc.idx = pDMA->idx;
4208428d7b3dSmrg  mc.used = pDMA->used;
4209428d7b3dSmrg  mc.last_render = ++pI810XvMC->last_render;
4210428d7b3dSmrg  privTarget->last_render = pI810XvMC->last_render;
4211428d7b3dSmrg  I810_MC(pI810XvMC,mc);
4212428d7b3dSmrg
4213428d7b3dSmrg  I810_UNLOCK(pI810XvMC);
4214428d7b3dSmrg  return Success;
4215428d7b3dSmrg}
4216428d7b3dSmrg
4217428d7b3dSmrg
4218428d7b3dSmrg
4219428d7b3dSmrg/***************************************************************************
4220428d7b3dSmrg// Function: XvMCSyncSubpicture
4221428d7b3dSmrg// Description: This function blocks until all composite/clear requests on
4222428d7b3dSmrg//              the subpicture have been complete.
4223428d7b3dSmrg// Arguments:
4224428d7b3dSmrg//   display - Connection to the X server.
4225428d7b3dSmrg//   subpicture - The subpicture to synchronize
4226428d7b3dSmrg//
4227428d7b3dSmrg// Returns: Status
4228428d7b3dSmrg***************************************************************************/
4229428d7b3dSmrg_X_EXPORT Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture) {
4230428d7b3dSmrg  Status ret;
4231428d7b3dSmrg  int stat=0;
4232428d7b3dSmrg  do {
4233428d7b3dSmrg    ret = XvMCGetSubpictureStatus(display,subpicture,&stat);
4234428d7b3dSmrg  }while(!ret && (stat & XVMC_RENDERING));
4235428d7b3dSmrg  return ret;
4236428d7b3dSmrg}
4237428d7b3dSmrg
4238428d7b3dSmrg
4239428d7b3dSmrg
4240428d7b3dSmrg/***************************************************************************
4241428d7b3dSmrg// Function: XvMCFlushSubpicture
4242428d7b3dSmrg// Description: This function commits pending composite/clear requests to
4243428d7b3dSmrg//              ensure that they will be completed in a finite amount of
4244428d7b3dSmrg//              time.
4245428d7b3dSmrg// Arguments:
4246428d7b3dSmrg//   display - Connection to the X server.
4247428d7b3dSmrg//   subpicture - The subpicture whos compsiting should be flushed
4248428d7b3dSmrg//
4249428d7b3dSmrg// Returns: Status
4250428d7b3dSmrg// NOTES: i810 always dispatches commands so flush is a no-op
4251428d7b3dSmrg***************************************************************************/
4252428d7b3dSmrg_X_EXPORT Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture) {
4253428d7b3dSmrg  if(display == NULL) {
4254428d7b3dSmrg    return BadValue;
4255428d7b3dSmrg  }
4256428d7b3dSmrg  if(subpicture == NULL) {
4257428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
4258428d7b3dSmrg  }
4259428d7b3dSmrg
4260428d7b3dSmrg  return Success;
4261428d7b3dSmrg}
4262428d7b3dSmrg
4263428d7b3dSmrg
4264428d7b3dSmrg
4265428d7b3dSmrg/***************************************************************************
4266428d7b3dSmrg// Function: XvMCGetSubpictureStatus
4267428d7b3dSmrg// Description: This function gets the current status of a subpicture
4268428d7b3dSmrg//
4269428d7b3dSmrg// Arguments:
4270428d7b3dSmrg//   display - Connection to the X server.
4271428d7b3dSmrg//   subpicture - The subpicture whos status is being queried
4272428d7b3dSmrg//   stat - The status of the subpicture. It can be any of the following
4273428d7b3dSmrg//          OR'd together:
4274428d7b3dSmrg//          XVMC_RENDERING  - Last composite or clear request not completed
4275428d7b3dSmrg//          XVMC_DISPLAYING - Suppicture currently being displayed.
4276428d7b3dSmrg//
4277428d7b3dSmrg// Returns: Status
4278428d7b3dSmrg// Notes: i810 always blends into a third surface so the subpicture is
4279428d7b3dSmrg//  never actually displaying, only a copy of it is displaying. We only
4280428d7b3dSmrg//  have to worry about the rendering case.
4281428d7b3dSmrg***************************************************************************/
4282428d7b3dSmrg_X_EXPORT Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture,
4283428d7b3dSmrg                             int *stat) {
4284428d7b3dSmrg
4285428d7b3dSmrg  i810XvMCSubpicture *privSubpicture;
4286428d7b3dSmrg  i810XvMCContext *pI810XvMC;
4287428d7b3dSmrg
4288428d7b3dSmrg  if((display == NULL) || (stat == NULL)) {
4289428d7b3dSmrg    return BadValue;
4290428d7b3dSmrg  }
4291428d7b3dSmrg  if((subpicture == NULL) || (subpicture->privData == NULL)) {
4292428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
4293428d7b3dSmrg  }
4294428d7b3dSmrg  *stat = 0;
4295428d7b3dSmrg  privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
4296428d7b3dSmrg
4297428d7b3dSmrg  pI810XvMC = (i810XvMCContext *)privSubpicture->privContext;
4298428d7b3dSmrg  if(pI810XvMC == NULL) {
4299428d7b3dSmrg    return (error_base + XvMCBadSubpicture);
4300428d7b3dSmrg  }
4301428d7b3dSmrg
4302428d7b3dSmrg  I810_LOCK(pI810XvMC,0);
4303428d7b3dSmrg
4304428d7b3dSmrg  if(privSubpicture->last_render &&
4305428d7b3dSmrg      (privSubpicture->last_render > GET_RSTATUS(pI810XvMC))) {
4306428d7b3dSmrg    *stat |= XVMC_RENDERING;
4307428d7b3dSmrg  }
4308428d7b3dSmrg  I810_UNLOCK(pI810XvMC);
4309428d7b3dSmrg
4310428d7b3dSmrg  return Success;
4311428d7b3dSmrg}
4312428d7b3dSmrg
4313428d7b3dSmrg#define NUM_XVMC_ATTRIBUTES 4
4314428d7b3dSmrgstatic XvAttribute I810_XVMC_ATTRIBUTES[] = {
4315428d7b3dSmrg  {XvGettable | XvSettable, 0, 0xffffff, "XV_COLORKEY"},
4316428d7b3dSmrg  {XvGettable | XvSettable, -127, +127, "XV_BRIGHTNESS"},
4317428d7b3dSmrg  {XvGettable | XvSettable, 0, 0x1ff, "XV_CONTRAST"},
4318428d7b3dSmrg  {XvGettable | XvSettable, 0, 0x3ff, "XV_SATURATION"}
4319428d7b3dSmrg};
4320428d7b3dSmrg
4321428d7b3dSmrg
4322428d7b3dSmrg/***************************************************************************
4323428d7b3dSmrg// Function: XvMCQueryAttributes
4324428d7b3dSmrg// Description: An array of XvAttributes of size "number" is returned by
4325428d7b3dSmrg//   this function. If there are no attributes, NULL is returned and number
4326428d7b3dSmrg//   is set to 0. The array may be freed with free().
4327428d7b3dSmrg//
4328428d7b3dSmrg// Arguments:
4329428d7b3dSmrg//   display - Connection to the X server.
4330428d7b3dSmrg//   context - The context whos attributes we are querying.
4331428d7b3dSmrg//   number - The number of returned atoms.
4332428d7b3dSmrg//
4333428d7b3dSmrg// Returns:
4334428d7b3dSmrg//  An array of XvAttributes.
4335428d7b3dSmrg// Notes:
4336428d7b3dSmrg//   For i810 we support these Attributes:
4337428d7b3dSmrg//    XV_COLORKEY: The colorkey value, initialized from the Xv value at
4338428d7b3dSmrg//                 context creation time.
4339428d7b3dSmrg//    XV_BRIGHTNESS
4340428d7b3dSmrg//    XV_CONTRAST
4341428d7b3dSmrg//    XV_SATURATION
4342428d7b3dSmrg***************************************************************************/
4343428d7b3dSmrg_X_EXPORT XvAttribute *XvMCQueryAttributes(Display *display, XvMCContext *context,
4344428d7b3dSmrg				 int *number) {
4345428d7b3dSmrg  i810XvMCContext *pI810XvMC;
4346428d7b3dSmrg  XvAttribute *attributes;
4347428d7b3dSmrg
4348428d7b3dSmrg  if(number == NULL) {
4349428d7b3dSmrg    return NULL;
4350428d7b3dSmrg  }
4351428d7b3dSmrg  if(display == NULL) {
4352428d7b3dSmrg    *number = 0;
4353428d7b3dSmrg    return NULL;
4354428d7b3dSmrg  }
4355428d7b3dSmrg  if(context == NULL) {
4356428d7b3dSmrg    *number = 0;
4357428d7b3dSmrg    return NULL;
4358428d7b3dSmrg  }
4359428d7b3dSmrg  pI810XvMC = context->privData;
4360428d7b3dSmrg  if(pI810XvMC == NULL) {
4361428d7b3dSmrg    *number = 0;
4362428d7b3dSmrg    return NULL;
4363428d7b3dSmrg  }
4364428d7b3dSmrg
4365428d7b3dSmrg  attributes = (XvAttribute *)malloc(NUM_XVMC_ATTRIBUTES *
4366428d7b3dSmrg				     sizeof(XvAttribute));
4367428d7b3dSmrg  if(attributes == NULL) {
4368428d7b3dSmrg    *number = 0;
4369428d7b3dSmrg    return NULL;
4370428d7b3dSmrg  }
4371428d7b3dSmrg
4372428d7b3dSmrg  memcpy(attributes,I810_XVMC_ATTRIBUTES,(NUM_XVMC_ATTRIBUTES *
4373428d7b3dSmrg					  sizeof(XvAttribute)));
4374428d7b3dSmrg
4375428d7b3dSmrg  *number = NUM_XVMC_ATTRIBUTES;
4376428d7b3dSmrg  return attributes;
4377428d7b3dSmrg}
4378428d7b3dSmrg
4379428d7b3dSmrg/***************************************************************************
4380428d7b3dSmrg// Function: XvMCSetAttribute
4381428d7b3dSmrg// Description: This function sets a context-specific attribute.
4382428d7b3dSmrg//
4383428d7b3dSmrg// Arguments:
4384428d7b3dSmrg//   display - Connection to the X server.
4385428d7b3dSmrg//   context - The context whos attributes we are querying.
4386428d7b3dSmrg//   attribute - The X atom of the attribute to be changed.
4387428d7b3dSmrg//   value - The new value for the attribute.
4388428d7b3dSmrg//
4389428d7b3dSmrg// Returns:
4390428d7b3dSmrg//  Status
4391428d7b3dSmrg// Notes:
4392428d7b3dSmrg//   For i810 we support these Attributes:
4393428d7b3dSmrg//    XV_COLORKEY: The colorkey value, initialized from the Xv value at
4394428d7b3dSmrg//                 context creation time.
4395428d7b3dSmrg//    XV_BRIGHTNESS
4396428d7b3dSmrg//    XV_CONTRAST
4397428d7b3dSmrg//    XV_SATURATION
4398428d7b3dSmrg***************************************************************************/
4399428d7b3dSmrg_X_EXPORT Status XvMCSetAttribute(Display *display, XvMCContext *context,
4400428d7b3dSmrg			Atom attribute, int value) {
4401428d7b3dSmrg  i810XvMCContext *pI810XvMC;
4402428d7b3dSmrg
4403428d7b3dSmrg  if(display == NULL) {
4404428d7b3dSmrg    return BadValue;
4405428d7b3dSmrg  }
4406428d7b3dSmrg  if(context == NULL) {
4407428d7b3dSmrg    return (error_base + XvMCBadContext);
4408428d7b3dSmrg  }
4409428d7b3dSmrg  pI810XvMC = context->privData;
4410428d7b3dSmrg  if(pI810XvMC == NULL) {
4411428d7b3dSmrg    return (error_base + XvMCBadContext);
4412428d7b3dSmrg  }
4413428d7b3dSmrg
4414428d7b3dSmrg  if(attribute == pI810XvMC->xv_colorkey) {
4415428d7b3dSmrg    if((value < I810_XVMC_ATTRIBUTES[0].min_value) ||
4416428d7b3dSmrg       (value > I810_XVMC_ATTRIBUTES[0].max_value)) {
4417428d7b3dSmrg      return BadValue;
4418428d7b3dSmrg    }
4419428d7b3dSmrg    pI810XvMC->colorkey = value;
4420428d7b3dSmrg    return Success;
4421428d7b3dSmrg  }
4422428d7b3dSmrg  if(attribute == pI810XvMC->xv_brightness) {
4423428d7b3dSmrg    if((value < I810_XVMC_ATTRIBUTES[1].min_value) ||
4424428d7b3dSmrg       (value > I810_XVMC_ATTRIBUTES[1].max_value)) {
4425428d7b3dSmrg      return BadValue;
4426428d7b3dSmrg    }
4427428d7b3dSmrg    pI810XvMC->brightness = value;
4428428d7b3dSmrg    return Success;
4429428d7b3dSmrg  }
4430428d7b3dSmrg  if(attribute == pI810XvMC->xv_saturation) {
4431428d7b3dSmrg    if((value < I810_XVMC_ATTRIBUTES[2].min_value) ||
4432428d7b3dSmrg       (value > I810_XVMC_ATTRIBUTES[2].max_value)) {
4433428d7b3dSmrg      return BadValue;
4434428d7b3dSmrg    }
4435428d7b3dSmrg    pI810XvMC->saturation = value;
4436428d7b3dSmrg    return Success;
4437428d7b3dSmrg  }
4438428d7b3dSmrg  if(attribute == pI810XvMC->xv_contrast) {
4439428d7b3dSmrg    if((value < I810_XVMC_ATTRIBUTES[3].min_value) ||
4440428d7b3dSmrg       (value > I810_XVMC_ATTRIBUTES[3].max_value)) {
4441428d7b3dSmrg      return BadValue;
4442428d7b3dSmrg    }
4443428d7b3dSmrg    pI810XvMC->contrast = value;
4444428d7b3dSmrg    return Success;
4445428d7b3dSmrg  }
4446428d7b3dSmrg  return BadValue;
4447428d7b3dSmrg}
4448428d7b3dSmrg
4449428d7b3dSmrg/***************************************************************************
4450428d7b3dSmrg// Function: XvMCGetAttribute
4451428d7b3dSmrg// Description: This function queries a context-specific attribute and
4452428d7b3dSmrg//   returns the value.
4453428d7b3dSmrg//
4454428d7b3dSmrg// Arguments:
4455428d7b3dSmrg//   display - Connection to the X server.
4456428d7b3dSmrg//   context - The context whos attributes we are querying.
4457428d7b3dSmrg//   attribute - The X atom of the attribute to be queried
4458428d7b3dSmrg//   value - The returned attribute value
4459428d7b3dSmrg//
4460428d7b3dSmrg// Returns:
4461428d7b3dSmrg//  Status
4462428d7b3dSmrg// Notes:
4463428d7b3dSmrg//   For i810 we support these Attributes:
4464428d7b3dSmrg//    XV_COLORKEY: The colorkey value, initialized from the Xv value at
4465428d7b3dSmrg//                 context creation time.
4466428d7b3dSmrg//    XV_BRIGHTNESS
4467428d7b3dSmrg//    XV_CONTRAST
4468428d7b3dSmrg//    XV_SATURATION
4469428d7b3dSmrg***************************************************************************/
4470428d7b3dSmrg_X_EXPORT Status XvMCGetAttribute(Display *display, XvMCContext *context,
4471428d7b3dSmrg			Atom attribute, int *value) {
4472428d7b3dSmrg  i810XvMCContext *pI810XvMC;
4473428d7b3dSmrg
4474428d7b3dSmrg  if(display == NULL) {
4475428d7b3dSmrg    return BadValue;
4476428d7b3dSmrg  }
4477428d7b3dSmrg  if(context == NULL) {
4478428d7b3dSmrg    return (error_base + XvMCBadContext);
4479428d7b3dSmrg  }
4480428d7b3dSmrg  pI810XvMC = context->privData;
4481428d7b3dSmrg  if(pI810XvMC == NULL) {
4482428d7b3dSmrg    return (error_base + XvMCBadContext);
4483428d7b3dSmrg  }
4484428d7b3dSmrg  if(value == NULL) {
4485428d7b3dSmrg    return BadValue;
4486428d7b3dSmrg  }
4487428d7b3dSmrg
4488428d7b3dSmrg  if(attribute == pI810XvMC->xv_colorkey) {
4489428d7b3dSmrg    *value = pI810XvMC->colorkey;
4490428d7b3dSmrg    return Success;
4491428d7b3dSmrg  }
4492428d7b3dSmrg  if(attribute == pI810XvMC->xv_brightness) {
4493428d7b3dSmrg    *value = pI810XvMC->brightness;
4494428d7b3dSmrg    return Success;
4495428d7b3dSmrg  }
4496428d7b3dSmrg  if(attribute == pI810XvMC->xv_saturation) {
4497428d7b3dSmrg    *value = pI810XvMC->saturation;
4498428d7b3dSmrg    return Success;
4499428d7b3dSmrg  }
4500428d7b3dSmrg  if(attribute == pI810XvMC->xv_contrast) {
4501428d7b3dSmrg    *value = pI810XvMC->contrast;
4502428d7b3dSmrg    return Success;
4503428d7b3dSmrg  }
4504428d7b3dSmrg  return BadValue;
4505428d7b3dSmrg}
4506428d7b3dSmrg
4507428d7b3dSmrg
4508428d7b3dSmrg
4509428d7b3dSmrg
4510