i740_video.c revision 301ea0f4
1/*
2 * Copyright 2001 by Patrick LERDA
3 * Portions Copyright by Stephen Blackheath
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Patrick LERDA not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  Patrick LERDA makes no representations
12 * about the suitability of this software for any purpose.  It is provided
13 * "as is" without express or implied warranty.
14 *
15 * PATRICK LERDA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL PATRICK LERDA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authors:  Patrick LERDA
24 *           with modifications by Stephen Blackheath (Aug 2002)
25 *
26 * REVISION HISTORY:
27 *   December 2001 - Patrick LERDA's original i740fb project on SourceForge.
28 *   27 August 2002 - Patrick's version would run for an hour or two on my
29 *     machine, then the screen would go blank (no signal to monitor) and for
30 *     some reason I sometimes couldn't even log in through the network.  I had
31 *     to re-boot my machine.  This version fixes that and makes a few other
32 *     unnecessary tweaks.  I am not certain, but I think the problem is that
33 *     Patrick's code was reading a value from XRX register 0xD0, and or'ing
34 *     with 0x10.  When I removed this from the main loop, it became reliable.
35 *     I suspect the hardware (whether just my cheap clone board only I'm not
36 *     sure) was sometimes returning bogus values, which were then programmed
37 *     back in - but I never checked this.  This register is related to
38 *     powering on or off certain subsystems of the i740 chip, so that might
39 *     explain the blank screen.  - Stephen Blackheath
40 *   3 September 2002 - Added software scaling in the situation where the
41 *     screen size is smaller than the original video size, since scaling down
42 *     is not supported by the hardware.  The implementation of this is not
43 *     quite complete.
44 *   12 September 2002 - Better software scaling with some averaging, giving a
45 *     nicer picture.
46 */
47/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_video.c,v 1.5tsi Exp $ */
48
49
50/*
51 * i740_video.c: i740 Xv driver. Based on the mga Xv driver by Mark Vojkovich.
52 */
53#ifdef HAVE_CONFIG_H
54#include "config.h"
55#endif
56
57#include <stdio.h>
58#include <string.h>
59
60#include "xf86.h"
61#include "xf86_OSproc.h"
62#include "xf86Resources.h"
63#include "compiler.h"
64#include "xf86PciInfo.h"
65#include "xf86Pci.h"
66#include "xf86fbman.h"
67#include "regionstr.h"
68
69#include "xf86xv.h"
70#include <X11/extensions/Xv.h>
71#include "xaa.h"
72#include "xaalocal.h"
73#include "dixstruct.h"
74#include "fourcc.h"
75
76#include "vgaHW.h"
77#include "i740.h"
78
79
80#define FOURCC_RV15     0x35315652
81#define FOURCC_RV16     0x36315652
82
83/*-*/
84#define i740_wc(fb,z,r,v) (pI740->writeControl(pI740,(z),(r),(v)))
85#define i740_rc(fb,z,r)   (pI740->readControl(pI740,(z),(r)))
86/*-*/
87
88#define OFF_DELAY 	250  /* milliseconds */
89#define FREE_DELAY 	15000
90
91#define OFF_TIMER 	0x01
92#define FREE_TIMER	0x02
93#define CLIENT_VIDEO_ON	0x04
94
95#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
96
97
98
99
100#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
101
102static Atom xvBrightness, xvContrast, xvColorKey;
103
104
105
106#define IMAGE_MAX_PHY_WIDTH		1024 /*720*/
107#define IMAGE_MAX_PHY_HEIGHT	1024 /*576*/
108
109
110#define IMAGE_MAX_LOG_WIDTH         1024 /*720*/
111#define IMAGE_MAX_LOG_HEIGHT        1024 /*576*/
112
113
114typedef struct {
115	CARD32       YBuf0offset;
116	CARD32       YBuf1offset;
117
118	unsigned char currentBuf;
119
120	int          brightness;
121	int          contrast;
122
123	RegionRec    clip;
124	CARD32       colorKey;
125
126	CARD32       videoStatus;
127	Time         offTime;
128	Time         freeTime;
129	FBLinearPtr  linear;
130
131} I740PortPrivRec, *I740PortPrivPtr;
132
133typedef struct {
134    CARD32 OBUF_0Y;
135    CARD32 OBUF_1Y;
136    CARD32 OBUF_0U;
137    CARD32 OBUF_0V;
138    CARD32 OBUF_1U;
139    CARD32 OBUF_1V;
140    CARD32 OV0STRIDE;
141    CARD32 YRGB_VPH;
142    CARD32 UV_VPH;
143    CARD32 HORZ_PH;
144    CARD32 INIT_PH;
145    CARD32 DWINPOS;
146    CARD32 DWINSZ;
147    CARD32 SWID;
148    CARD32 SWIDQW;
149    CARD32 SHEIGHT;
150    CARD32 YRGBSCALE;
151    CARD32 UVSCALE;
152    CARD32 OV0CLRC0;
153    CARD32 OV0CLRC1;
154    CARD32 DCLRKV;
155    CARD32 DCLRKM;
156    CARD32 SCLRKVH;
157    CARD32 SCLRKVL;
158    CARD32 SCLRKM;
159    CARD32 OV0CONF;
160    CARD32 OV0CMD;
161} I740OverlayRegRec, *I740OverlayRegPtr;
162
163#define GET_PORT_PRIVATE(pScrn) \
164   (I740PortPrivPtr)((I740PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
165
166
167/*-----------------------------------------------------------------------------------------*/
168__inline__ static void i740fb_overlay_off(ScrnInfoPtr pScrn)
169{
170  I740Ptr pI740 = I740PTR(pScrn);
171
172    /* 0x3C = COL_KEY_CNTL_1 */
173  i740_wc(fb_p, MRX, 0x3C, (i740_rc(fb_p, MRX, 0x3C) |  0x02));
174  usleep(50000);
175  /*i740_wc(fb_p, XRX, 0xD0, (i740_rc(fb_p, XRX, 0xD0) & ~0x10));
176  usleep(50000);*/
177  i740_wc(fb_p, XRX, 0xD0, 0x2F);
178}
179
180__inline__ static void i740fb_overlay_set(ScrnInfoPtr pScrn, I740PortPrivPtr pPriv, unsigned long mem1,unsigned long mem2,
181					  unsigned long isrc_w,unsigned long isrc_h, /* source      image size */
182					  unsigned long idst_w,unsigned long idst_h, /* destination image size */
183					  unsigned long ddst_x,unsigned long ddst_y, /* destination image pos to display */
184					  unsigned long ddst_w,unsigned long ddst_h, /* destination image size to display allows trunc... */
185					  unsigned long pitch,int flip,
186					  unsigned char vd_mod)
187{
188  I740Ptr pI740 = I740PTR(pScrn);
189  const int f_dbl=pScrn->currentMode->Flags & V_DBLSCAN;
190
191  if(f_dbl) { idst_h*=2; ddst_y*=2; ddst_h*=2;  }
192
193  ddst_x+=pI740->ov_offset_x;
194  ddst_y+=pI740->ov_offset_y;
195
196      /* Program the i740 overlay to use the new image dimensions. */
197
198    i740_wc(fb_p, MRX, 0x24, mem1>>16);
199    i740_wc(fb_p, MRX, 0x23, mem1>> 8);
200    i740_wc(fb_p, MRX, 0x22, mem1>> 0);
201
202    i740_wc(fb_p, MRX, 0x27, mem2>>16);
203    i740_wc(fb_p, MRX, 0x26, mem2>> 8);
204    i740_wc(fb_p, MRX, 0x25, mem2>> 0);
205
206    i740_wc(fb_p, MRX, 0x28, (( pitch  >>3)-1)    );
207
208    { unsigned short v=ddst_x;          i740_wc(fb_p, MRX, 0x2B, v>> 8); i740_wc(fb_p, MRX, 0x2A, v>> 0); }
209    { unsigned short v=ddst_x+ddst_w-1; i740_wc(fb_p, MRX, 0x2D, v>> 8); i740_wc(fb_p, MRX, 0x2C, v>> 0); }
210    { unsigned short v=ddst_y;          i740_wc(fb_p, MRX, 0x2F, v>> 8); i740_wc(fb_p, MRX, 0x2E, v>> 0); }
211    { unsigned short v=ddst_y+ddst_h-1; i740_wc(fb_p, MRX, 0x31, v>> 8); i740_wc(fb_p, MRX, 0x30, v>> 0); }
212
213    i740_wc(fb_p, MRX, 0x32, (isrc_w<<8)/(idst_w));
214    i740_wc(fb_p, MRX, 0x33, (isrc_h<<8)/(idst_h));
215
216    i740_wc(fb_p, MRX, 0x50, 0);
217    i740_wc(fb_p, MRX, 0x51, 0);
218
219    i740_wc(fb_p, MRX, 0x1E, ( idst_w > isrc_w ? 0x04 : 0x00 ) | ( idst_h > isrc_h ? 0x08 : 0x00 ));
220    i740_wc(fb_p, MRX, 0x1F, ( idst_w > isrc_w ? 0x20 : 0x00 ) | ( (idst_h > isrc_h) && (pitch <= 720*2)  ? 0xC0 : 0x00 ) | (vd_mod & 0x1F));
221
222    /*i740_wc(fb_p, MRX, 0x20, 0);*/
223
224    i740_wc(fb_p, MRX, 0x19, 0x00);
225
226    /*i740_wc(fb_p, XRX, 0xD0, i740_rc(fb_p, XRX, 0xD0) | 0x10 );*/
227    i740_wc(fb_p, XRX, 0xD0, 0x3F);
228      /* 0x3C = COL_KEY_CNTL_1 */
229    i740_wc(fb_p, MRX, 0x3C, 0x05 | 0x02);
230
231  /*i740_wc(fb_p, MRX, 0x20, (flip ? 0x14 : 0x04));*/
232  /*i740_wc(fb_p, MRX, 0x20, 0);*/
233  /*i740_wc(fb_p, XRX, 0xD0, i740_rc(fb_p, XRX, 0xD0) | 0x10 );*/
234  /*i740_wc(fb_p, MRX, 0x19, 0x00);*/
235  i740_wc(fb_p, MRX, 0x20, (flip ? 0x34 : 0x24)); /*SB*/
236}
237
238__inline__ static void i740fb_colorkey(ScrnInfoPtr pScrn,unsigned long key)
239{
240  I740Ptr pI740 = I740PTR(pScrn);
241  unsigned char r,g,b,rm,gm,bm;
242
243  /*//xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"colorkey=%04x depth=%d\n",key,pScrn->depth);*/
244
245  switch(pScrn->depth)
246    {
247    case  4:           r=0x00;            g=0x00;              b=key;               rm=0xFF; gm=0xFF; bm=0xF0;   break;
248    case  8:           r=0x00;            g=0x00;              b=key;               rm=0xFF; gm=0xFF; bm=0x00;   break;
249    case 15:           r=(key&0x7C00)>>7; g=(key&0x03E0)>>2;   b=(key&0x001F)<<3;   rm=0x07; gm=0x07; bm=0x07;   break;
250    case 16:           r=(key&0xF800)>>8; g=(key&0x07E0)>>3;   b=(key&0x001F)<<3;   rm=0x07; gm=0x03; bm=0x07;   break;
251    default:  /*24*/   r=(key&0xFF00)>>8; g=(key&0xFF00)>>3;   b=(key&0xFF00)<<3;   rm=0x00; gm=0x00; bm=0x00;   break;
252    }
253
254  i740_wc(fb_p, MRX, 0x3D, r);
255  i740_wc(fb_p, MRX, 0x3E, g);
256  i740_wc(fb_p, MRX, 0x3F, b);
257
258  i740_wc(fb_p, MRX, 0x40, rm);
259  i740_wc(fb_p, MRX, 0x41, gm);
260  i740_wc(fb_p, MRX, 0x42, bm);
261}
262
263/*-----------------------------------------------------------------------------------------*/
264
265
266
267static void I740ResetVideo(ScrnInfoPtr pScrn)
268{
269  I740Ptr pI740 = I740PTR(pScrn);
270  I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
271
272  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740ResetVideo entered\n");  /* ### */
273
274  /*
275   * Enable destination color keying
276   */
277
278  i740fb_colorkey(pScrn,pPriv->colorKey);
279}
280
281
282
283/* I740ClipVideo -
284
285   Takes the dst box in standard X BoxRec form (top and left
286   edges inclusive, bottom and right exclusive).  The new dst
287   box is returned.  The source boundaries are given (x1, y1
288   inclusive, x2, y2 exclusive) and returned are the new source
289   boundaries in 16.16 fixed point.
290*/
291
292static void I740ClipVideo(
293  BoxPtr dst,
294  INT32 *x1,
295  INT32 *x2,
296  INT32 *y1,
297  INT32 *y2,
298  BoxPtr extents,            /* extents of the clip region */
299  INT32 width,
300  INT32 height
301){
302    INT32 vscale, hscale, delta;
303    int diff;
304
305    hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
306    vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
307
308    *x1 <<= 16; *x2 <<= 16;
309    *y1 <<= 16; *y2 <<= 16;
310
311    diff = extents->x1 - dst->x1;
312    if(diff > 0) {
313	dst->x1 = extents->x1;
314	*x1 += diff * hscale;
315    }
316    diff = dst->x2 - extents->x2;
317    if(diff > 0) {
318	dst->x2 = extents->x2;
319	*x2 -= diff * hscale;
320    }
321    diff = extents->y1 - dst->y1;
322    if(diff > 0) {
323	dst->y1 = extents->y1;
324	*y1 += diff * vscale;
325    }
326    diff = dst->y2 - extents->y2;
327    if(diff > 0) {
328	dst->y2 = extents->y2;
329	*y2 -= diff * vscale;
330    }
331
332    if(*x1 < 0) {
333	diff =  (- *x1 + hscale - 1)/ hscale;
334	dst->x1 += diff;
335	*x1 += diff * hscale;
336    }
337    delta = *x2 - (width << 16);
338    if(delta > 0) {
339	diff = (delta + hscale - 1)/ hscale;
340	dst->x2 -= diff;
341	*x2 -= diff * hscale;
342    }
343    if(*y1 < 0) {
344	diff =  (- *y1 + vscale - 1)/ vscale;
345	dst->y1 += diff;
346	*y1 += diff * vscale;
347    }
348    delta = *y2 - (height << 16);
349    if(delta > 0) {
350	diff = (delta + vscale - 1)/ vscale;
351	dst->y2 -= diff;
352	*y2 -= diff * vscale;
353    }
354}
355
356static void I740StopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
357{
358  I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
359  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740StopVideo entered %p %d\n", (void*)data, (int)exit);*/  /* ### */
360
361  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
362
363  if(exit)
364    {
365      if(pPriv->videoStatus & CLIENT_VIDEO_ON)
366	i740fb_overlay_off(pScrn);
367
368      if(pPriv->linear)
369	{
370	  xf86FreeOffscreenLinear(pPriv->linear);
371	  pPriv->linear = NULL;
372	}
373      pPriv->videoStatus = 0;
374    }
375  else
376    {
377      if(pPriv->videoStatus & CLIENT_VIDEO_ON)
378	{
379	  pPriv->videoStatus |= OFF_TIMER;
380	  pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
381	}
382    }
383
384}
385
386static int I740SetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data)
387{
388  I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
389  I740Ptr pI740 = I740PTR(pScrn);
390  I740OverlayRegPtr overlay = (I740OverlayRegPtr) (pI740->FbBase + pI740->OverlayStart);
391
392  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740SetPortAttribute entered %d\n", (int) value);*/  /* ### */
393
394  if(attribute == xvBrightness)
395    {
396      if((value < -128) || (value > 127))
397	return BadValue;
398      pPriv->brightness = value;
399      overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
400      /*//OVERLAY_UPDATE(pI740->OverlayPhysical);*/
401    }
402  else
403    if(attribute == xvContrast)
404      {
405	if((value < 0) || (value > 255))
406	  return BadValue;
407	pPriv->contrast = value;
408	overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
409	/*//OVERLAY_UPDATE(pI740->OverlayPhysical);*/
410      }
411    else
412      if(attribute == xvColorKey)
413	{
414	  pPriv->colorKey = value;
415
416	  i740fb_colorkey(pScrn,pPriv->colorKey);
417
418	  /*//OVERLAY_UPDATE(pI740->OverlayPhysical);*/
419	  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
420	}
421      else
422	return BadMatch;
423
424  return Success;
425}
426
427static int I740GetPortAttribute(
428  ScrnInfoPtr pScrn,
429  Atom attribute,
430  INT32 *value,
431  pointer data
432){
433  I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
434
435  if(attribute == xvBrightness) {
436	*value = pPriv->brightness;
437  } else
438  if(attribute == xvContrast) {
439	*value = pPriv->contrast;
440  } else
441  if(attribute == xvColorKey) {
442	*value = pPriv->colorKey;
443  } else return BadMatch;
444
445  return Success;
446}
447
448static void I740QueryBestSize(
449  ScrnInfoPtr pScrn,
450  Bool motion,
451  short vid_w, short vid_h,
452  short drw_w, short drw_h,
453  unsigned int *p_w, unsigned int *p_h,
454  pointer data
455){
456   if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1;
457   if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1;
458  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740QueryBestSize entered %d %d %d %d\n", (int) vid_w, (int) vid_h, (int) drw_w, (int) drw_h);  /* ### */
459  fprintf(stderr, "fprintf - I740QueryBestSize entered %d %d %d %d\n", (int) vid_w, (int) vid_h, (int) drw_w, (int) drw_h);  /* ### */
460
461  *p_w = drw_w;
462  *p_h = drw_h;
463}
464
465static void I740CopyMungedData(ScrnInfoPtr pScrn,
466   unsigned char *src1, unsigned char *src2, unsigned char *src3,
467   int srcPitch,
468   int srcPitch2,
469   int dstPitch,
470   int h,
471   int w,
472   long scalex,
473   long scaley)
474{
475  I740Ptr pI740 = I740PTR(pScrn);
476  I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
477  CARD32 *dst;
478  int i, j;
479
480  if (pPriv->currentBuf == 0)
481    dst = (CARD32 *)(pI740->FbBase + pPriv->YBuf0offset);
482  else
483    dst = (CARD32 *)(pI740->FbBase + pPriv->YBuf1offset);
484
485  dstPitch >>= 2;
486  w >>= 1;
487
488    /* If the space on the screen is smaller than the source image, then we use
489     * software scaling to make it smaller. */
490  if (scalex > 0x10000 || scaley > 0x10000) {
491    int dsth = ((long) h * 0x10000L + scaley - 1) / scaley;
492    long halfx = scalex/2;
493    long dstj = 0;
494    for(j = 0; j < dsth; j++) {
495      int dstj_rnd = dstj >> 16;
496      unsigned char* src1_ = src1 + (dstj_rnd * srcPitch);
497      unsigned char* src2_ = src2 + ((dstj_rnd/2) * srcPitch2);
498      unsigned char* src3_ = src3 + ((dstj_rnd/2) * srcPitch2);
499      int dstw = ((long) w * 0x10000L + halfx - 1) / scalex;
500      long srci = 0;
501      for(i = 0; i < dstw; i++) {
502	long srci_rnd = srci >> 16;
503	long srci2_rnd = (srci + halfx) >> 16;
504	dst[i] =
505	  (((src1_[srci_rnd << 1] | (src1_[(srci_rnd << 1) + 1] << 16) |
506	  (src3_[srci_rnd] << 8) | (src2_[srci_rnd] << 24))) >> 1 & 0x7F7F7F7FL)
507	    +
508	  (((src1_[srci2_rnd << 1] | (src1_[(srci2_rnd << 1) + 1] << 16) |
509	  (src3_[srci2_rnd] << 8) | (src2_[srci2_rnd] << 24))) >> 1 & 0x7F7F7F7FL);
510	srci += scalex;
511      }
512      dst += dstPitch;
513      dstj += scaley;
514    }
515  }
516  else {
517    for(j = 0; j < h; j++) {
518      for(i = 0; i < w; i++) {
519	dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
520	  (src3[i] << 8) | (src2[i] << 24);
521      }
522      dst += dstPitch;
523      src1 += srcPitch;
524      if(j & 1) {
525	src2 += srcPitch2;
526	src3 += srcPitch2;
527      }
528    }
529  }
530}
531
532
533__inline__ static void I740CopyPackedData(ScrnInfoPtr pScrn,
534					  unsigned char *buf,
535					  int srcPitch,
536					  int dstPitch,
537					  int top,
538					  int left,
539					  int h,
540					  int w
541					  )
542{
543    I740Ptr pI740 = I740PTR(pScrn);
544    I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
545    unsigned char *src, *dst;
546
547    src = buf + (top*srcPitch) + (left<<1);
548
549    if (pPriv->currentBuf == 0)
550	dst = pI740->FbBase + pPriv->YBuf0offset;
551    else
552	dst = pI740->FbBase + pPriv->YBuf1offset;
553
554    w <<= 1;
555    while(h--) {
556	memcpy(dst, src, w);
557	src += srcPitch;
558	dst += dstPitch;
559    }
560}
561
562
563__inline__ static void I740DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
564					int dstPitch,  /* of chroma for 4:2:0 */
565					int x1, int y1, int x2, int y2,
566					BoxPtr dstBox,
567					short src_w, short src_h, short drw_w, short drw_h,
568					unsigned char vd_mod
569					)
570{
571  I740Ptr pI740 = I740PTR(pScrn);
572  I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
573
574  i740fb_overlay_set(pScrn,pPriv,pPriv->YBuf0offset,pPriv->YBuf1offset,
575		     src_w,src_h,                                        /* source      image size */
576		     drw_w,drw_h,                                        /* destination image size */
577		     dstBox->x1,dstBox->y1,                              /* destination image pos to display */
578		     dstBox->x2 - dstBox->x1,dstBox->y2 - dstBox->y1,    /* destination image size to display allows trunc... */
579		     dstPitch,(pPriv->currentBuf != 0),
580		     vd_mod);
581
582  i740fb_colorkey(pScrn,pPriv->colorKey);                                /* needed to reset properly the i740 board after switching from framebuffer */
583}
584
585static FBLinearPtr I740AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
586{
587  ScreenPtr pScreen;
588  FBLinearPtr new_linear;
589
590  if(linear)
591    {
592      if(linear->size >= size)
593	return linear;
594
595      if(xf86ResizeOffscreenLinear(linear, size)) {
596        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory resized to %d - %p\n", (int) size, (void *)linear);  /* ### */
597	return linear;
598      }
599
600      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory free %p - %d < %d\n", (void *)linear, (int) linear->size, (int) size);  /* ### */
601      xf86FreeOffscreenLinear(linear);
602    }
603
604  pScreen = screenInfo.screens[pScrn->scrnIndex];
605
606  new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
607
608  if(!new_linear)
609    {
610      int max_size;
611
612      xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME);
613
614      if(max_size < size) {
615	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory can't purge %d < %d\n", (int) max_size, (int) size);  /* ### */
616	return NULL;
617      }
618
619      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory purged %d\n", (int) max_size);  /* ### */
620      xf86PurgeUnlockedOffscreenAreas(pScreen);
621      new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
622					       NULL, NULL, NULL);
623    }
624  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory allocated %d - %p\n", (int) size, (void *)new_linear);  /* ### */
625
626  return new_linear;
627}
628
629static int I740PutImage(ScrnInfoPtr pScrn,
630			short src_x, short src_y, short drw_x, short drw_y,
631			short src_w, short src_h, short drw_w, short drw_h,
632			int id, unsigned char* buf,
633			short width, short height,
634			Bool sync, RegionPtr clipBoxes, pointer data,
635			DrawablePtr pDraw
636			)
637{
638  ScreenPtr pScreen = pScrn->pScreen;
639  I740Ptr pI740 = I740PTR(pScrn);
640  I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
641  INT32 x1, x2, y1, y2;
642  int srcPitch, dstPitch, srcPitch2=0;
643  int top, left, npixels, nlines, size;
644  BoxRec dstBox;
645  int offset2=0, offset3=0;
646
647  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740PutImage entered %d %d\n", (int) width, (int) height, id);*/  /* ### */
648
649  /* Clip */
650  x1 = src_x;
651  x2 = src_x + src_w;
652  y1 = src_y;
653  y2 = src_y + src_h;
654
655  dstBox.x1 = drw_x;
656  dstBox.x2 = drw_x + drw_w;
657  dstBox.y1 = drw_y;
658  dstBox.y2 = drw_y + drw_h;
659
660  I740ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
661		REGION_EXTENTS(pScreen, clipBoxes), width, height);
662
663  if((x1 >= x2) || (y1 >= y2)) {
664    return Success;
665  }
666
667  dstBox.x1 -= pScrn->frameX0;
668  dstBox.x2 -= pScrn->frameX0;
669  dstBox.y1 -= pScrn->frameY0;
670  dstBox.y2 -= pScrn->frameY0;
671
672  switch(id)
673    {
674    case FOURCC_YV12:
675    case FOURCC_I420:
676      srcPitch = (width + 3) & ~3;
677      offset2 = srcPitch * height;
678      srcPitch2 = ((width >> 1) + 3) & ~3;
679      offset3 = (srcPitch2 * (height >> 1)) + offset2;
680      dstPitch = ((width << 1) + 15) & ~15;
681      size = dstPitch * height;
682      break;
683    case FOURCC_UYVY:
684    case FOURCC_YUY2:
685    default:
686      srcPitch = (width << 1);
687      dstPitch = (srcPitch + 7) & ~7;
688      size = dstPitch * height;
689      break;
690    }
691
692  {
693    FBLinearPtr new_linear = I740AllocateMemory(pScrn, pPriv->linear, size);
694    if (new_linear != pPriv->linear) {
695      pPriv->linear = new_linear;
696    }
697  }
698  if(!pPriv->linear)
699    return BadAlloc;
700
701  /* fixup pointers */
702  pPriv->YBuf0offset = pPriv->linear->offset*pI740->cpp;
703  pPriv->YBuf1offset = (pPriv->linear->offset*pI740->cpp) + size;
704
705
706#if 0 /*???*/
707  /* wait for the last rendered buffer to be flipped in */
708  while (((INREG(DOV0STA)&0x00100000)>>20) != pPriv->currentBuf);
709#endif
710
711  /* buffer swap */
712  pPriv->currentBuf ^= 1;
713
714  /* copy data */
715  top = y1 >> 16;
716  left = (x1 >> 16) & ~1;
717  npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
718
719  switch(id) {
720  case FOURCC_YV12:
721  case FOURCC_I420:
722    {
723      CARD32 tmp;
724
725      top &= ~1;
726      tmp = ((top >> 1) * srcPitch2) + (left >> 1);
727      offset2 += tmp;
728      offset3 += tmp;
729
730      if(id == FOURCC_I420)
731	{
732	  tmp = offset2;
733	  offset2 = offset3;
734	  offset3 = tmp;
735	}
736
737      nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
738
739        /* If the screen image size is smaller than the video image size, then
740	 * we use software scaling to make it smaller.  The hardware takes care
741	 * of scaling up - see i740fb_overlay_set.
742	 */
743      {
744	long scalex = 0x10000, scaley = 0x10000;
745	if (drw_w < src_w)
746	  scalex = (0x10000L * (long) src_w) / (long) drw_w;
747	if (drw_h < src_h)
748	  scaley = (0x10000L * (long) src_h) / (long) drw_h;
749
750	I740CopyMungedData(pScrn, buf + (top * srcPitch) + left,
751			   buf + offset2, buf + offset3,
752			   srcPitch, srcPitch2, dstPitch, nlines, npixels, scalex, scaley);
753      }
754    }
755    break;
756
757  case FOURCC_UYVY: case FOURCC_YUY2: default:
758    {
759      nlines = ((y2 + 0xffff) >> 16) - top;
760        /* Add software scaling as above. */
761      I740CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines,
762			 npixels);
763    }
764    break;
765  }
766
767  /* update cliplist */
768  if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes))
769    {
770      REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
771      /* draw these */
772      xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes);
773    }
774
775  {
776    unsigned char vd_mod;
777
778    switch(id)
779      {
780      case FOURCC_RV15: vd_mod=0x09; break;
781      case FOURCC_RV16: vd_mod=0x08; break;
782      default:          vd_mod=0x00; break;
783      }
784
785    I740DisplayVideo(pScrn, id, width, height, dstPitch,
786		     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h,
787		     vd_mod);
788  }
789
790  pPriv->videoStatus = CLIENT_VIDEO_ON;
791
792  return Success;
793}
794
795
796static int I740QueryImageAttributes(ScrnInfoPtr pScrn, int id, unsigned short *w, unsigned short *h, int *pitches, int *offsets )
797{
798  int size,tmp;
799
800  if(*w > IMAGE_MAX_PHY_WIDTH) *w = IMAGE_MAX_PHY_WIDTH;
801  if(*h > IMAGE_MAX_PHY_HEIGHT) *h = IMAGE_MAX_PHY_HEIGHT;
802
803  *w = (*w + 1) & ~1;
804  if(offsets) offsets[0] = 0;
805
806  switch(id)
807    {
808    case FOURCC_YV12:
809    case FOURCC_I420:
810      *h = (*h + 1) & ~1;
811      size = (*w + 3) & ~3;
812      if(pitches) pitches[0] = size;
813      size *= *h;
814      if(offsets) offsets[1] = size;
815      tmp = ((*w >> 1) + 3) & ~3;
816      if(pitches) pitches[1] = pitches[2] = tmp;
817      tmp *= (*h >> 1);
818      size += tmp;
819      if(offsets) offsets[2] = size;
820      size += tmp;
821      break;
822    case FOURCC_UYVY:
823    case FOURCC_YUY2:
824    default:
825      size = *w << 1;
826      if(pitches) pitches[0] = size;
827      size *= *h;
828      break;
829    }
830
831  return size;
832}
833
834static void I740BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
835{
836  ScreenPtr   pScreen = screenInfo.screens[i];
837  ScrnInfoPtr pScrn = xf86Screens[i];
838  I740Ptr      pI740 = I740PTR(pScrn);
839  I740PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
840
841  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740BlockHandler entered\n"); */  /* ### */
842
843  pScreen->BlockHandler = pI740->BlockHandler;
844
845  (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
846
847  pScreen->BlockHandler = I740BlockHandler;
848
849  if(pPriv->videoStatus & TIMER_MASK)
850    {
851      UpdateCurrentTime();
852      if(pPriv->videoStatus & OFF_TIMER)
853	{
854	  if(pPriv->offTime < currentTime.milliseconds)
855	    {
856              /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740BlockHandler: OFF_TIMER expired\n");*/  /* ### */
857	      /* Turn off the overlay */
858	      i740fb_overlay_off(pScrn);
859
860	      pPriv->videoStatus = FREE_TIMER;
861	      pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
862	    }
863	}
864      else
865	{  /* FREE_TIMER */
866	  if(pPriv->freeTime < currentTime.milliseconds)
867	    {
868	      if(pPriv->linear)
869		{
870                  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740BlockHandler: FREE_TIMER expired\n");*/  /* ### */
871		  xf86FreeOffscreenLinear(pPriv->linear);
872		  pPriv->linear = NULL;
873		}
874	      pPriv->videoStatus = 0;
875	    }
876        }
877    }
878}
879
880
881/***************************************************************************
882 * Offscreen Images
883 ***************************************************************************/
884
885typedef struct {
886  FBLinearPtr linear;
887  Bool isOn;
888} OffscreenPrivRec, * OffscreenPrivPtr;
889
890static int I740AllocateSurface(
891    ScrnInfoPtr pScrn,
892    int id,
893    unsigned short w,
894    unsigned short h,
895    XF86SurfacePtr surface
896){
897    FBLinearPtr linear;
898    int pitch, size;
899    OffscreenPrivPtr pPriv;
900    I740Ptr pI740 = I740PTR(pScrn);
901
902    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateSurface entered %d %d\n", (int) w, (int) h);  /* ### */
903
904    if((w > IMAGE_MAX_LOG_WIDTH) || (h > IMAGE_MAX_LOG_HEIGHT))
905	return BadAlloc;
906
907    w = (w + 1) & ~1;
908    pitch = ((w << 1) + 15) & ~15;
909    size = pitch * h;
910
911    if(!(linear = I740AllocateMemory(pScrn, NULL, size)))
912	return BadAlloc;
913
914    surface->width = w;
915    surface->height = h;
916
917    if(!(surface->pitches = xalloc(sizeof(int)))) {
918	xf86FreeOffscreenLinear(linear);
919	return BadAlloc;
920    }
921    if(!(surface->offsets = xalloc(sizeof(int)))) {
922	xfree(surface->pitches);
923	xf86FreeOffscreenLinear(linear);
924	return BadAlloc;
925    }
926    if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
927	xfree(surface->pitches);
928	xfree(surface->offsets);
929	xf86FreeOffscreenLinear(linear);
930	return BadAlloc;
931    }
932
933    pPriv->linear = linear;
934    pPriv->isOn = FALSE;
935
936    surface->pScrn = pScrn;
937    surface->id = id;
938    surface->pitches[0] = pitch;
939    surface->offsets[0] = linear->offset*pI740->cpp;
940    surface->devPrivate.ptr = (pointer)pPriv;
941
942    /*//memset(pI740->FbBase + surface->offsets[0],0,size);*/
943
944    return Success;
945}
946
947static int I740StopSurface(XF86SurfacePtr surface)
948{
949  OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
950
951  if(pPriv->isOn)
952    {
953      /*//i740fb_overlay_off(pScrn);*/
954
955      pPriv->isOn = FALSE;
956    }
957
958  return Success;
959}
960
961
962static int I740FreeSurface(XF86SurfacePtr surface)
963{
964  OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
965
966  if(pPriv->isOn)
967    {
968      I740StopSurface(surface);
969    }
970
971  xf86FreeOffscreenLinear(pPriv->linear);
972  xfree(surface->pitches);
973  xfree(surface->offsets);
974  xfree(surface->devPrivate.ptr);
975
976  return Success;
977}
978
979static int I740GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
980{
981  return I740GetPortAttribute(pScrn, attribute, value, 0);
982}
983
984static int I740SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
985{
986  return I740SetPortAttribute(pScrn, attribute, value, 0);
987}
988
989
990static int I740DisplaySurface(XF86SurfacePtr surface, short src_x, short src_y,
991			      short drw_x, short drw_y,
992			      short src_w, short src_h,
993			      short drw_w, short drw_h,
994			      RegionPtr clipBoxes)
995{
996  OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
997  ScrnInfoPtr pScrn = surface->pScrn;
998  I740PortPrivPtr pI740Priv =  GET_PORT_PRIVATE(pScrn);
999
1000  INT32 x1, y1, x2, y2;
1001  BoxRec dstBox;
1002
1003  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740DisplaySurface entered\n");  /* ### */
1004  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"I740DisplaySurface-----------------------------------\n");*/
1005  /*//fprintf(stderr, "I740DisplaySurface-----------------------------------\n");*/
1006
1007
1008  x1 = src_x;
1009  x2 = src_x + src_w;
1010  y1 = src_y;
1011  y2 = src_y + src_h;
1012
1013  dstBox.x1 = drw_x;
1014  dstBox.x2 = drw_x + drw_w;
1015  dstBox.y1 = drw_y;
1016  dstBox.y2 = drw_y + drw_h;
1017
1018  I740ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
1019		REGION_EXTENTS(screenInfo.screens[0], clipBoxes),
1020		surface->width, surface->height);
1021
1022  dstBox.x1 -= pScrn->frameX0;
1023  dstBox.x2 -= pScrn->frameX0;
1024  dstBox.y1 -= pScrn->frameY0;
1025  dstBox.y2 -= pScrn->frameY0;
1026
1027  /* fixup pointers */
1028  pI740Priv->YBuf0offset = surface->offsets[0];
1029  pI740Priv->YBuf1offset = pI740Priv->YBuf0offset;
1030
1031#if 0 /*???*/
1032  /* wait for the last rendered buffer to be flipped in */
1033  while (((INREG(DOV0STA)&0x00100000)>>20) != pI740Priv->currentBuf) {
1034    if(loops == 200000) {
1035      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");
1036      break;
1037    }
1038    loops++;
1039  }
1040#endif
1041
1042  /* buffer swap */
1043  if (pI740Priv->currentBuf == 0)
1044    pI740Priv->currentBuf = 1;
1045  else
1046    pI740Priv->currentBuf = 0;
1047
1048  I740ResetVideo(pScrn);
1049
1050  I740DisplayVideo(pScrn, surface->id, surface->width, surface->height,
1051		   surface->pitches[0], x1, y1, x2, y2, &dstBox,
1052		   src_w, src_h, drw_w, drw_h,
1053		   0x00);
1054
1055  xf86XVFillKeyHelper(pScrn->pScreen, pI740Priv->colorKey, clipBoxes);
1056
1057  pPriv->isOn = TRUE;
1058  /* we've prempted the XvImage stream so set its free timer */
1059  if(pI740Priv->videoStatus & CLIENT_VIDEO_ON) {
1060    REGION_EMPTY(pScrn->pScreen, & pI740Priv->clip);
1061    UpdateCurrentTime();
1062    pI740Priv->videoStatus = FREE_TIMER;
1063    pI740Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
1064    pScrn->pScreen->BlockHandler = I740BlockHandler;
1065  }
1066
1067  return Success;
1068}
1069
1070/*-------------------------------------------------------------------------------------------*/
1071#define NUM_IMAGES (sizeof(i740vid_Images)/sizeof(XF86ImageRec))
1072static XF86ImageRec i740vid_Images[] =
1073{
1074  XVIMAGE_YUY2,
1075  XVIMAGE_UYVY,
1076  XVIMAGE_YV12, /* converted to YUV2 while copying */
1077  XVIMAGE_I420, /* converted to YUV2 while copying */
1078  {
1079    FOURCC_RV15,
1080    XvRGB,
1081    LSBFirst,
1082    {'R','V','1','5',
1083     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
1084    16,
1085    XvPacked,
1086    1,
1087    15, 0x001F, 0x03E0, 0x7C00,
1088    0, 0, 0,
1089    0, 0, 0,
1090    0, 0, 0,
1091    {'R','V','B',0,
1092     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
1093    XvTopToBottom
1094  },
1095  {
1096    FOURCC_RV16,
1097    XvRGB,
1098    LSBFirst,
1099    {'R','V','1','6',
1100     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
1101    16,
1102    XvPacked,
1103    1,
1104    16, 0x001F, 0x07E0, 0xF800,
1105    0, 0, 0,
1106    0, 0, 0,
1107    0, 0, 0,
1108    {'R','V','B',0,
1109     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
1110    XvTopToBottom
1111  },
1112};
1113
1114#define NUM_ATTRIBUTES (sizeof(i740vid_Attributes)/sizeof(XF86AttributeRec))
1115
1116static XF86AttributeRec i740vid_Attributes[] =
1117{
1118   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
1119   {XvSettable | XvGettable, -128, 127,        "XV_BRIGHTNESS"},
1120   {XvSettable | XvGettable, 0, 255,           "XV_CONTRAST"}
1121};
1122
1123
1124static void I740InitOffscreenImages(ScreenPtr pScreen)
1125{
1126  XF86OffscreenImagePtr offscreenImages;
1127  {
1128    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1129    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740InitOffscreenImages entered\n");  /* ### */
1130  }
1131
1132  /* need to free this someplace */
1133  if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
1134    {
1135      return;
1136    }
1137
1138  offscreenImages[0].image          = &i740vid_Images[0];
1139  offscreenImages[0].flags          = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1140  offscreenImages[0].alloc_surface  = I740AllocateSurface;
1141  offscreenImages[0].free_surface   = I740FreeSurface;
1142  offscreenImages[0].display        = I740DisplaySurface;
1143  offscreenImages[0].stop           = I740StopSurface;
1144  offscreenImages[0].setAttribute   = I740SetSurfaceAttribute;
1145  offscreenImages[0].getAttribute   = I740GetSurfaceAttribute;
1146  offscreenImages[0].max_width      = IMAGE_MAX_LOG_WIDTH;
1147  offscreenImages[0].max_height     = IMAGE_MAX_LOG_HEIGHT;
1148  offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
1149  offscreenImages[0].attributes     = i740vid_Attributes;
1150
1151  xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
1152}
1153
1154
1155
1156static XF86VideoAdaptorPtr I740SetupImageVideo(ScreenPtr pScreen)
1157{
1158  /* client libraries expect an encoding */
1159  static XF86VideoEncodingRec DummyEncoding[1] =
1160  {
1161    {
1162      0,
1163      "XV_IMAGE",
1164      IMAGE_MAX_PHY_WIDTH, IMAGE_MAX_PHY_HEIGHT,
1165      {1, 1}
1166    }
1167  };
1168
1169#define NUM_FORMATS (sizeof(i740vid_Formats)/sizeof(XF86VideoFormatRec))
1170  static XF86VideoFormatRec i740vid_Formats[] =
1171  {
1172    {15, TrueColor}, {16, TrueColor}, {24, TrueColor},  {8, PseudoColor}
1173  };
1174
1175  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1176  I740Ptr pI740 = I740PTR(pScrn);
1177  XF86VideoAdaptorPtr adapt;
1178  I740PortPrivPtr pPriv;
1179
1180  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740SetupImageVideo entered\n");*/  /* ### */
1181  {
1182    const int n=sizeof(XF86VideoAdaptorRec)+sizeof(I740PortPrivRec)+sizeof(DevUnion);
1183
1184    if(!(adapt = xcalloc(1, n)))
1185      return NULL;
1186
1187    /*//memset(adapt,0,n);*/
1188  }
1189
1190  adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1191  adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1192  adapt->name = "I740 Video Overlay";
1193  adapt->nEncodings = 1;
1194  adapt->pEncodings = DummyEncoding;
1195  adapt->nFormats = NUM_FORMATS;
1196  adapt->pFormats = i740vid_Formats;
1197  adapt->nPorts = 1;
1198  adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1199
1200  pPriv = (I740PortPrivPtr)((unsigned char *)(&adapt[1])+sizeof(sizeof(DevUnion)));
1201
1202  adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1203  adapt->pAttributes          = i740vid_Attributes;
1204  adapt->nImages              = NUM_IMAGES;
1205  adapt->nAttributes          = NUM_ATTRIBUTES;
1206  adapt->pImages              = i740vid_Images;
1207  adapt->PutVideo             = NULL;
1208  adapt->PutStill             = NULL;
1209  adapt->GetVideo             = NULL;
1210  adapt->GetStill             = NULL;
1211  adapt->StopVideo            = I740StopVideo;
1212  adapt->SetPortAttribute     = I740SetPortAttribute;
1213  adapt->GetPortAttribute     = I740GetPortAttribute;
1214  adapt->QueryBestSize        = I740QueryBestSize;
1215  adapt->PutImage             = I740PutImage;
1216  adapt->QueryImageAttributes = I740QueryImageAttributes;
1217
1218  pPriv->colorKey    = pI740->colorKey & ((1 << pScrn->depth) - 1);
1219  pPriv->videoStatus = 0;
1220  pPriv->brightness  = 0;
1221  pPriv->contrast    = 64;
1222  pPriv->linear      = NULL;
1223  pPriv->currentBuf  = 0;
1224
1225  /* gotta uninit this someplace */
1226  REGION_NULL(pScreen, &pPriv->clip);
1227
1228  pI740->adaptor = adapt;
1229
1230  pI740->BlockHandler = pScreen->BlockHandler;
1231  pScreen->BlockHandler = I740BlockHandler;
1232
1233  xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1234  xvContrast   = MAKE_ATOM("XV_CONTRAST");
1235  xvColorKey   = MAKE_ATOM("XV_COLORKEY");
1236
1237  I740ResetVideo(pScrn);
1238
1239  return adapt;
1240}
1241
1242void I740InitVideo(ScreenPtr pScreen)
1243{
1244  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1245  XF86VideoAdaptorPtr newAdaptor = NULL;
1246  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740InitVideo entered\n");  /* ### */
1247
1248#if 0 /*disable!*/
1249  {
1250    XF86VideoAdaptorPtr *ptr;
1251    int n;
1252
1253    n = xf86XVListGenericAdaptors(pScrn,&ptr);
1254    if (n) {
1255      xf86XVScreenInit(pScreen, ptr, n);
1256    }
1257
1258    return;
1259  }
1260#endif
1261
1262  {
1263    newAdaptor = I740SetupImageVideo(pScreen);
1264    I740InitOffscreenImages(pScreen);
1265  }
1266
1267  {
1268    XF86VideoAdaptorPtr *adaptors_oldptrs, *adaptors_newptrs = NULL;
1269    int num_adaptors;
1270
1271    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors_oldptrs);
1272
1273    if(newAdaptor)
1274      {
1275	if(!num_adaptors)
1276	  {
1277	    xf86XVScreenInit(pScreen, &newAdaptor, 1);
1278	  }
1279	else
1280	  {
1281	    if((adaptors_newptrs = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr))))
1282	      {
1283		memcpy(adaptors_newptrs, adaptors_oldptrs, num_adaptors * sizeof(XF86VideoAdaptorPtr));
1284		adaptors_newptrs[num_adaptors] = newAdaptor;
1285
1286		/*//xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"num--- %d [%d] %08x %08x\n",num_adaptors,num_adaptors * sizeof(XF86VideoAdaptorPtr),*/
1287		/*//	   adaptors_newptrs[0],adaptors_newptrs[1]);*/
1288
1289
1290		xf86XVScreenInit(pScreen, adaptors_newptrs, num_adaptors+1);
1291		xfree(adaptors_newptrs);
1292	      }
1293	  }
1294      }
1295
1296  }
1297}
1298