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