1301ea0f4Smrg/*
2301ea0f4Smrg * Copyright 2001 by Patrick LERDA
3301ea0f4Smrg * Portions Copyright by Stephen Blackheath
4301ea0f4Smrg *
5301ea0f4Smrg * Permission to use, copy, modify, distribute, and sell this software and its
6301ea0f4Smrg * documentation for any purpose is hereby granted without fee, provided that
7301ea0f4Smrg * the above copyright notice appear in all copies and that both that
8301ea0f4Smrg * copyright notice and this permission notice appear in supporting
9301ea0f4Smrg * documentation, and that the name of Patrick LERDA not be used in
10301ea0f4Smrg * advertising or publicity pertaining to distribution of the software without
11301ea0f4Smrg * specific, written prior permission.  Patrick LERDA makes no representations
12301ea0f4Smrg * about the suitability of this software for any purpose.  It is provided
13301ea0f4Smrg * "as is" without express or implied warranty.
14301ea0f4Smrg *
15301ea0f4Smrg * PATRICK LERDA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16301ea0f4Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17301ea0f4Smrg * EVENT SHALL PATRICK LERDA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18301ea0f4Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19301ea0f4Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20301ea0f4Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21301ea0f4Smrg * PERFORMANCE OF THIS SOFTWARE.
22301ea0f4Smrg *
23301ea0f4Smrg * Authors:  Patrick LERDA
24301ea0f4Smrg *           with modifications by Stephen Blackheath (Aug 2002)
25301ea0f4Smrg *
26301ea0f4Smrg * REVISION HISTORY:
27301ea0f4Smrg *   December 2001 - Patrick LERDA's original i740fb project on SourceForge.
28301ea0f4Smrg *   27 August 2002 - Patrick's version would run for an hour or two on my
29301ea0f4Smrg *     machine, then the screen would go blank (no signal to monitor) and for
30301ea0f4Smrg *     some reason I sometimes couldn't even log in through the network.  I had
31301ea0f4Smrg *     to re-boot my machine.  This version fixes that and makes a few other
32301ea0f4Smrg *     unnecessary tweaks.  I am not certain, but I think the problem is that
33301ea0f4Smrg *     Patrick's code was reading a value from XRX register 0xD0, and or'ing
34301ea0f4Smrg *     with 0x10.  When I removed this from the main loop, it became reliable.
35301ea0f4Smrg *     I suspect the hardware (whether just my cheap clone board only I'm not
36301ea0f4Smrg *     sure) was sometimes returning bogus values, which were then programmed
37301ea0f4Smrg *     back in - but I never checked this.  This register is related to
38301ea0f4Smrg *     powering on or off certain subsystems of the i740 chip, so that might
39301ea0f4Smrg *     explain the blank screen.  - Stephen Blackheath
40301ea0f4Smrg *   3 September 2002 - Added software scaling in the situation where the
41301ea0f4Smrg *     screen size is smaller than the original video size, since scaling down
42301ea0f4Smrg *     is not supported by the hardware.  The implementation of this is not
43301ea0f4Smrg *     quite complete.
44301ea0f4Smrg *   12 September 2002 - Better software scaling with some averaging, giving a
45301ea0f4Smrg *     nicer picture.
46301ea0f4Smrg */
47301ea0f4Smrg
48301ea0f4Smrg
49301ea0f4Smrg/*
50301ea0f4Smrg * i740_video.c: i740 Xv driver. Based on the mga Xv driver by Mark Vojkovich.
51301ea0f4Smrg */
52301ea0f4Smrg#ifdef HAVE_CONFIG_H
53301ea0f4Smrg#include "config.h"
54301ea0f4Smrg#endif
55301ea0f4Smrg
56301ea0f4Smrg#include <stdio.h>
57301ea0f4Smrg#include <string.h>
585c69f917Smrg#include <unistd.h>
59301ea0f4Smrg
60301ea0f4Smrg#include "xf86.h"
61301ea0f4Smrg#include "xf86_OSproc.h"
62301ea0f4Smrg#include "compiler.h"
63301ea0f4Smrg#include "xf86Pci.h"
64301ea0f4Smrg#include "xf86fbman.h"
65301ea0f4Smrg#include "regionstr.h"
66301ea0f4Smrg
67301ea0f4Smrg#include "xf86xv.h"
68301ea0f4Smrg#include <X11/extensions/Xv.h>
69301ea0f4Smrg#include "dixstruct.h"
70301ea0f4Smrg#include "fourcc.h"
71301ea0f4Smrg
72301ea0f4Smrg#include "vgaHW.h"
73301ea0f4Smrg#include "i740.h"
74301ea0f4Smrg
75301ea0f4Smrg
76301ea0f4Smrg#define FOURCC_RV15     0x35315652
77301ea0f4Smrg#define FOURCC_RV16     0x36315652
78301ea0f4Smrg
79301ea0f4Smrg/*-*/
80301ea0f4Smrg#define i740_wc(fb,z,r,v) (pI740->writeControl(pI740,(z),(r),(v)))
81301ea0f4Smrg#define i740_rc(fb,z,r)   (pI740->readControl(pI740,(z),(r)))
82301ea0f4Smrg/*-*/
83301ea0f4Smrg
84301ea0f4Smrg#define OFF_DELAY 	250  /* milliseconds */
85301ea0f4Smrg#define FREE_DELAY 	15000
86301ea0f4Smrg
87301ea0f4Smrg#define OFF_TIMER 	0x01
88301ea0f4Smrg#define FREE_TIMER	0x02
89301ea0f4Smrg#define CLIENT_VIDEO_ON	0x04
90301ea0f4Smrg
91301ea0f4Smrg#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
92301ea0f4Smrg
93301ea0f4Smrg
94301ea0f4Smrg
95301ea0f4Smrg
96301ea0f4Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
97301ea0f4Smrg
98301ea0f4Smrgstatic Atom xvBrightness, xvContrast, xvColorKey;
99301ea0f4Smrg
100301ea0f4Smrg
101301ea0f4Smrg
102301ea0f4Smrg#define IMAGE_MAX_PHY_WIDTH		1024 /*720*/
103301ea0f4Smrg#define IMAGE_MAX_PHY_HEIGHT	1024 /*576*/
104301ea0f4Smrg
105301ea0f4Smrg
106301ea0f4Smrg#define IMAGE_MAX_LOG_WIDTH         1024 /*720*/
107301ea0f4Smrg#define IMAGE_MAX_LOG_HEIGHT        1024 /*576*/
108301ea0f4Smrg
109301ea0f4Smrg
110301ea0f4Smrgtypedef struct {
111301ea0f4Smrg	CARD32       YBuf0offset;
112301ea0f4Smrg	CARD32       YBuf1offset;
113301ea0f4Smrg
114301ea0f4Smrg	unsigned char currentBuf;
115301ea0f4Smrg
116301ea0f4Smrg	int          brightness;
117301ea0f4Smrg	int          contrast;
118301ea0f4Smrg
119301ea0f4Smrg	RegionRec    clip;
120301ea0f4Smrg	CARD32       colorKey;
121301ea0f4Smrg
122301ea0f4Smrg	CARD32       videoStatus;
123301ea0f4Smrg	Time         offTime;
124301ea0f4Smrg	Time         freeTime;
125301ea0f4Smrg	FBLinearPtr  linear;
126301ea0f4Smrg
127301ea0f4Smrg} I740PortPrivRec, *I740PortPrivPtr;
128301ea0f4Smrg
129301ea0f4Smrgtypedef struct {
130301ea0f4Smrg    CARD32 OBUF_0Y;
131301ea0f4Smrg    CARD32 OBUF_1Y;
132301ea0f4Smrg    CARD32 OBUF_0U;
133301ea0f4Smrg    CARD32 OBUF_0V;
134301ea0f4Smrg    CARD32 OBUF_1U;
135301ea0f4Smrg    CARD32 OBUF_1V;
136301ea0f4Smrg    CARD32 OV0STRIDE;
137301ea0f4Smrg    CARD32 YRGB_VPH;
138301ea0f4Smrg    CARD32 UV_VPH;
139301ea0f4Smrg    CARD32 HORZ_PH;
140301ea0f4Smrg    CARD32 INIT_PH;
141301ea0f4Smrg    CARD32 DWINPOS;
142301ea0f4Smrg    CARD32 DWINSZ;
143301ea0f4Smrg    CARD32 SWID;
144301ea0f4Smrg    CARD32 SWIDQW;
145301ea0f4Smrg    CARD32 SHEIGHT;
146301ea0f4Smrg    CARD32 YRGBSCALE;
147301ea0f4Smrg    CARD32 UVSCALE;
148301ea0f4Smrg    CARD32 OV0CLRC0;
149301ea0f4Smrg    CARD32 OV0CLRC1;
150301ea0f4Smrg    CARD32 DCLRKV;
151301ea0f4Smrg    CARD32 DCLRKM;
152301ea0f4Smrg    CARD32 SCLRKVH;
153301ea0f4Smrg    CARD32 SCLRKVL;
154301ea0f4Smrg    CARD32 SCLRKM;
155301ea0f4Smrg    CARD32 OV0CONF;
156301ea0f4Smrg    CARD32 OV0CMD;
157301ea0f4Smrg} I740OverlayRegRec, *I740OverlayRegPtr;
158301ea0f4Smrg
159301ea0f4Smrg#define GET_PORT_PRIVATE(pScrn) \
160301ea0f4Smrg   (I740PortPrivPtr)((I740PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
161301ea0f4Smrg
162301ea0f4Smrg
163301ea0f4Smrg/*-----------------------------------------------------------------------------------------*/
164301ea0f4Smrg__inline__ static void i740fb_overlay_off(ScrnInfoPtr pScrn)
165301ea0f4Smrg{
166301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
167301ea0f4Smrg
168301ea0f4Smrg    /* 0x3C = COL_KEY_CNTL_1 */
169301ea0f4Smrg  i740_wc(fb_p, MRX, 0x3C, (i740_rc(fb_p, MRX, 0x3C) |  0x02));
170301ea0f4Smrg  usleep(50000);
171301ea0f4Smrg  /*i740_wc(fb_p, XRX, 0xD0, (i740_rc(fb_p, XRX, 0xD0) & ~0x10));
172301ea0f4Smrg  usleep(50000);*/
173301ea0f4Smrg  i740_wc(fb_p, XRX, 0xD0, 0x2F);
174301ea0f4Smrg}
175301ea0f4Smrg
176301ea0f4Smrg__inline__ static void i740fb_overlay_set(ScrnInfoPtr pScrn, I740PortPrivPtr pPriv, unsigned long mem1,unsigned long mem2,
177301ea0f4Smrg					  unsigned long isrc_w,unsigned long isrc_h, /* source      image size */
178301ea0f4Smrg					  unsigned long idst_w,unsigned long idst_h, /* destination image size */
179301ea0f4Smrg					  unsigned long ddst_x,unsigned long ddst_y, /* destination image pos to display */
180301ea0f4Smrg					  unsigned long ddst_w,unsigned long ddst_h, /* destination image size to display allows trunc... */
181301ea0f4Smrg					  unsigned long pitch,int flip,
182301ea0f4Smrg					  unsigned char vd_mod)
183301ea0f4Smrg{
184301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
185301ea0f4Smrg  const int f_dbl=pScrn->currentMode->Flags & V_DBLSCAN;
186301ea0f4Smrg
187301ea0f4Smrg  if(f_dbl) { idst_h*=2; ddst_y*=2; ddst_h*=2;  }
188301ea0f4Smrg
189301ea0f4Smrg  ddst_x+=pI740->ov_offset_x;
190301ea0f4Smrg  ddst_y+=pI740->ov_offset_y;
191301ea0f4Smrg
192301ea0f4Smrg      /* Program the i740 overlay to use the new image dimensions. */
193301ea0f4Smrg
194301ea0f4Smrg    i740_wc(fb_p, MRX, 0x24, mem1>>16);
195301ea0f4Smrg    i740_wc(fb_p, MRX, 0x23, mem1>> 8);
196301ea0f4Smrg    i740_wc(fb_p, MRX, 0x22, mem1>> 0);
197301ea0f4Smrg
198301ea0f4Smrg    i740_wc(fb_p, MRX, 0x27, mem2>>16);
199301ea0f4Smrg    i740_wc(fb_p, MRX, 0x26, mem2>> 8);
200301ea0f4Smrg    i740_wc(fb_p, MRX, 0x25, mem2>> 0);
201301ea0f4Smrg
202301ea0f4Smrg    i740_wc(fb_p, MRX, 0x28, (( pitch  >>3)-1)    );
203301ea0f4Smrg
204301ea0f4Smrg    { unsigned short v=ddst_x;          i740_wc(fb_p, MRX, 0x2B, v>> 8); i740_wc(fb_p, MRX, 0x2A, v>> 0); }
205301ea0f4Smrg    { unsigned short v=ddst_x+ddst_w-1; i740_wc(fb_p, MRX, 0x2D, v>> 8); i740_wc(fb_p, MRX, 0x2C, v>> 0); }
206301ea0f4Smrg    { unsigned short v=ddst_y;          i740_wc(fb_p, MRX, 0x2F, v>> 8); i740_wc(fb_p, MRX, 0x2E, v>> 0); }
207301ea0f4Smrg    { unsigned short v=ddst_y+ddst_h-1; i740_wc(fb_p, MRX, 0x31, v>> 8); i740_wc(fb_p, MRX, 0x30, v>> 0); }
208301ea0f4Smrg
209301ea0f4Smrg    i740_wc(fb_p, MRX, 0x32, (isrc_w<<8)/(idst_w));
210301ea0f4Smrg    i740_wc(fb_p, MRX, 0x33, (isrc_h<<8)/(idst_h));
211301ea0f4Smrg
212301ea0f4Smrg    i740_wc(fb_p, MRX, 0x50, 0);
213301ea0f4Smrg    i740_wc(fb_p, MRX, 0x51, 0);
214301ea0f4Smrg
215301ea0f4Smrg    i740_wc(fb_p, MRX, 0x1E, ( idst_w > isrc_w ? 0x04 : 0x00 ) | ( idst_h > isrc_h ? 0x08 : 0x00 ));
216301ea0f4Smrg    i740_wc(fb_p, MRX, 0x1F, ( idst_w > isrc_w ? 0x20 : 0x00 ) | ( (idst_h > isrc_h) && (pitch <= 720*2)  ? 0xC0 : 0x00 ) | (vd_mod & 0x1F));
217301ea0f4Smrg
218301ea0f4Smrg    /*i740_wc(fb_p, MRX, 0x20, 0);*/
219301ea0f4Smrg
220301ea0f4Smrg    i740_wc(fb_p, MRX, 0x19, 0x00);
221301ea0f4Smrg
222301ea0f4Smrg    /*i740_wc(fb_p, XRX, 0xD0, i740_rc(fb_p, XRX, 0xD0) | 0x10 );*/
223301ea0f4Smrg    i740_wc(fb_p, XRX, 0xD0, 0x3F);
224301ea0f4Smrg      /* 0x3C = COL_KEY_CNTL_1 */
225301ea0f4Smrg    i740_wc(fb_p, MRX, 0x3C, 0x05 | 0x02);
226301ea0f4Smrg
227301ea0f4Smrg  /*i740_wc(fb_p, MRX, 0x20, (flip ? 0x14 : 0x04));*/
228301ea0f4Smrg  /*i740_wc(fb_p, MRX, 0x20, 0);*/
229301ea0f4Smrg  /*i740_wc(fb_p, XRX, 0xD0, i740_rc(fb_p, XRX, 0xD0) | 0x10 );*/
230301ea0f4Smrg  /*i740_wc(fb_p, MRX, 0x19, 0x00);*/
231301ea0f4Smrg  i740_wc(fb_p, MRX, 0x20, (flip ? 0x34 : 0x24)); /*SB*/
232301ea0f4Smrg}
233301ea0f4Smrg
234301ea0f4Smrg__inline__ static void i740fb_colorkey(ScrnInfoPtr pScrn,unsigned long key)
235301ea0f4Smrg{
236301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
237301ea0f4Smrg  unsigned char r,g,b,rm,gm,bm;
238301ea0f4Smrg
239301ea0f4Smrg  /*//xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"colorkey=%04x depth=%d\n",key,pScrn->depth);*/
240301ea0f4Smrg
241301ea0f4Smrg  switch(pScrn->depth)
242301ea0f4Smrg    {
243301ea0f4Smrg    case  4:           r=0x00;            g=0x00;              b=key;               rm=0xFF; gm=0xFF; bm=0xF0;   break;
244301ea0f4Smrg    case  8:           r=0x00;            g=0x00;              b=key;               rm=0xFF; gm=0xFF; bm=0x00;   break;
245301ea0f4Smrg    case 15:           r=(key&0x7C00)>>7; g=(key&0x03E0)>>2;   b=(key&0x001F)<<3;   rm=0x07; gm=0x07; bm=0x07;   break;
246301ea0f4Smrg    case 16:           r=(key&0xF800)>>8; g=(key&0x07E0)>>3;   b=(key&0x001F)<<3;   rm=0x07; gm=0x03; bm=0x07;   break;
247301ea0f4Smrg    default:  /*24*/   r=(key&0xFF00)>>8; g=(key&0xFF00)>>3;   b=(key&0xFF00)<<3;   rm=0x00; gm=0x00; bm=0x00;   break;
248301ea0f4Smrg    }
249301ea0f4Smrg
250301ea0f4Smrg  i740_wc(fb_p, MRX, 0x3D, r);
251301ea0f4Smrg  i740_wc(fb_p, MRX, 0x3E, g);
252301ea0f4Smrg  i740_wc(fb_p, MRX, 0x3F, b);
253301ea0f4Smrg
254301ea0f4Smrg  i740_wc(fb_p, MRX, 0x40, rm);
255301ea0f4Smrg  i740_wc(fb_p, MRX, 0x41, gm);
256301ea0f4Smrg  i740_wc(fb_p, MRX, 0x42, bm);
257301ea0f4Smrg}
258301ea0f4Smrg
259301ea0f4Smrg/*-----------------------------------------------------------------------------------------*/
260301ea0f4Smrg
261301ea0f4Smrg
262301ea0f4Smrg
263301ea0f4Smrgstatic void I740ResetVideo(ScrnInfoPtr pScrn)
264301ea0f4Smrg{
265301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
266301ea0f4Smrg  I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
267301ea0f4Smrg
268301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740ResetVideo entered\n");  /* ### */
269301ea0f4Smrg
270301ea0f4Smrg  /*
271301ea0f4Smrg   * Enable destination color keying
272301ea0f4Smrg   */
273301ea0f4Smrg
274301ea0f4Smrg  i740fb_colorkey(pScrn,pPriv->colorKey);
275301ea0f4Smrg}
276301ea0f4Smrg
277301ea0f4Smrg
278301ea0f4Smrg
279301ea0f4Smrg/* I740ClipVideo -
280301ea0f4Smrg
281301ea0f4Smrg   Takes the dst box in standard X BoxRec form (top and left
282301ea0f4Smrg   edges inclusive, bottom and right exclusive).  The new dst
283301ea0f4Smrg   box is returned.  The source boundaries are given (x1, y1
284301ea0f4Smrg   inclusive, x2, y2 exclusive) and returned are the new source
285301ea0f4Smrg   boundaries in 16.16 fixed point.
286301ea0f4Smrg*/
287301ea0f4Smrg
288301ea0f4Smrgstatic void I740ClipVideo(
289301ea0f4Smrg  BoxPtr dst,
290301ea0f4Smrg  INT32 *x1,
291301ea0f4Smrg  INT32 *x2,
292301ea0f4Smrg  INT32 *y1,
293301ea0f4Smrg  INT32 *y2,
294301ea0f4Smrg  BoxPtr extents,            /* extents of the clip region */
295301ea0f4Smrg  INT32 width,
296301ea0f4Smrg  INT32 height
297301ea0f4Smrg){
298301ea0f4Smrg    INT32 vscale, hscale, delta;
299301ea0f4Smrg    int diff;
300301ea0f4Smrg
301301ea0f4Smrg    hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
302301ea0f4Smrg    vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
303301ea0f4Smrg
304301ea0f4Smrg    *x1 <<= 16; *x2 <<= 16;
305301ea0f4Smrg    *y1 <<= 16; *y2 <<= 16;
306301ea0f4Smrg
307301ea0f4Smrg    diff = extents->x1 - dst->x1;
308301ea0f4Smrg    if(diff > 0) {
309301ea0f4Smrg	dst->x1 = extents->x1;
310301ea0f4Smrg	*x1 += diff * hscale;
311301ea0f4Smrg    }
312301ea0f4Smrg    diff = dst->x2 - extents->x2;
313301ea0f4Smrg    if(diff > 0) {
314301ea0f4Smrg	dst->x2 = extents->x2;
315301ea0f4Smrg	*x2 -= diff * hscale;
316301ea0f4Smrg    }
317301ea0f4Smrg    diff = extents->y1 - dst->y1;
318301ea0f4Smrg    if(diff > 0) {
319301ea0f4Smrg	dst->y1 = extents->y1;
320301ea0f4Smrg	*y1 += diff * vscale;
321301ea0f4Smrg    }
322301ea0f4Smrg    diff = dst->y2 - extents->y2;
323301ea0f4Smrg    if(diff > 0) {
324301ea0f4Smrg	dst->y2 = extents->y2;
325301ea0f4Smrg	*y2 -= diff * vscale;
326301ea0f4Smrg    }
327301ea0f4Smrg
328301ea0f4Smrg    if(*x1 < 0) {
329301ea0f4Smrg	diff =  (- *x1 + hscale - 1)/ hscale;
330301ea0f4Smrg	dst->x1 += diff;
331301ea0f4Smrg	*x1 += diff * hscale;
332301ea0f4Smrg    }
333301ea0f4Smrg    delta = *x2 - (width << 16);
334301ea0f4Smrg    if(delta > 0) {
335301ea0f4Smrg	diff = (delta + hscale - 1)/ hscale;
336301ea0f4Smrg	dst->x2 -= diff;
337301ea0f4Smrg	*x2 -= diff * hscale;
338301ea0f4Smrg    }
339301ea0f4Smrg    if(*y1 < 0) {
340301ea0f4Smrg	diff =  (- *y1 + vscale - 1)/ vscale;
341301ea0f4Smrg	dst->y1 += diff;
342301ea0f4Smrg	*y1 += diff * vscale;
343301ea0f4Smrg    }
344301ea0f4Smrg    delta = *y2 - (height << 16);
345301ea0f4Smrg    if(delta > 0) {
346301ea0f4Smrg	diff = (delta + vscale - 1)/ vscale;
347301ea0f4Smrg	dst->y2 -= diff;
348301ea0f4Smrg	*y2 -= diff * vscale;
349301ea0f4Smrg    }
350301ea0f4Smrg}
351301ea0f4Smrg
352301ea0f4Smrgstatic void I740StopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
353301ea0f4Smrg{
354301ea0f4Smrg  I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
355301ea0f4Smrg  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740StopVideo entered %p %d\n", (void*)data, (int)exit);*/  /* ### */
356301ea0f4Smrg
357301ea0f4Smrg  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
358301ea0f4Smrg
359301ea0f4Smrg  if(exit)
360301ea0f4Smrg    {
361301ea0f4Smrg      if(pPriv->videoStatus & CLIENT_VIDEO_ON)
362301ea0f4Smrg	i740fb_overlay_off(pScrn);
363301ea0f4Smrg
364301ea0f4Smrg      if(pPriv->linear)
365301ea0f4Smrg	{
366301ea0f4Smrg	  xf86FreeOffscreenLinear(pPriv->linear);
367301ea0f4Smrg	  pPriv->linear = NULL;
368301ea0f4Smrg	}
369301ea0f4Smrg      pPriv->videoStatus = 0;
370301ea0f4Smrg    }
371301ea0f4Smrg  else
372301ea0f4Smrg    {
373301ea0f4Smrg      if(pPriv->videoStatus & CLIENT_VIDEO_ON)
374301ea0f4Smrg	{
375301ea0f4Smrg	  pPriv->videoStatus |= OFF_TIMER;
376301ea0f4Smrg	  pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
377301ea0f4Smrg	}
378301ea0f4Smrg    }
379301ea0f4Smrg
380301ea0f4Smrg}
381301ea0f4Smrg
382301ea0f4Smrgstatic int I740SetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data)
383301ea0f4Smrg{
384301ea0f4Smrg  I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
385301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
386301ea0f4Smrg  I740OverlayRegPtr overlay = (I740OverlayRegPtr) (pI740->FbBase + pI740->OverlayStart);
387301ea0f4Smrg
388301ea0f4Smrg  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740SetPortAttribute entered %d\n", (int) value);*/  /* ### */
389301ea0f4Smrg
390301ea0f4Smrg  if(attribute == xvBrightness)
391301ea0f4Smrg    {
392301ea0f4Smrg      if((value < -128) || (value > 127))
393301ea0f4Smrg	return BadValue;
394301ea0f4Smrg      pPriv->brightness = value;
395301ea0f4Smrg      overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
396301ea0f4Smrg      /*//OVERLAY_UPDATE(pI740->OverlayPhysical);*/
397301ea0f4Smrg    }
398301ea0f4Smrg  else
399301ea0f4Smrg    if(attribute == xvContrast)
400301ea0f4Smrg      {
401301ea0f4Smrg	if((value < 0) || (value > 255))
402301ea0f4Smrg	  return BadValue;
403301ea0f4Smrg	pPriv->contrast = value;
404301ea0f4Smrg	overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
405301ea0f4Smrg	/*//OVERLAY_UPDATE(pI740->OverlayPhysical);*/
406301ea0f4Smrg      }
407301ea0f4Smrg    else
408301ea0f4Smrg      if(attribute == xvColorKey)
409301ea0f4Smrg	{
410301ea0f4Smrg	  pPriv->colorKey = value;
411301ea0f4Smrg
412301ea0f4Smrg	  i740fb_colorkey(pScrn,pPriv->colorKey);
413301ea0f4Smrg
414301ea0f4Smrg	  /*//OVERLAY_UPDATE(pI740->OverlayPhysical);*/
415301ea0f4Smrg	  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
416301ea0f4Smrg	}
417301ea0f4Smrg      else
418301ea0f4Smrg	return BadMatch;
419301ea0f4Smrg
420301ea0f4Smrg  return Success;
421301ea0f4Smrg}
422301ea0f4Smrg
423301ea0f4Smrgstatic int I740GetPortAttribute(
424301ea0f4Smrg  ScrnInfoPtr pScrn,
425301ea0f4Smrg  Atom attribute,
426301ea0f4Smrg  INT32 *value,
427301ea0f4Smrg  pointer data
428301ea0f4Smrg){
429301ea0f4Smrg  I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
430301ea0f4Smrg
431301ea0f4Smrg  if(attribute == xvBrightness) {
432301ea0f4Smrg	*value = pPriv->brightness;
433301ea0f4Smrg  } else
434301ea0f4Smrg  if(attribute == xvContrast) {
435301ea0f4Smrg	*value = pPriv->contrast;
436301ea0f4Smrg  } else
437301ea0f4Smrg  if(attribute == xvColorKey) {
438301ea0f4Smrg	*value = pPriv->colorKey;
439301ea0f4Smrg  } else return BadMatch;
440301ea0f4Smrg
441301ea0f4Smrg  return Success;
442301ea0f4Smrg}
443301ea0f4Smrg
444301ea0f4Smrgstatic void I740QueryBestSize(
445301ea0f4Smrg  ScrnInfoPtr pScrn,
446301ea0f4Smrg  Bool motion,
447301ea0f4Smrg  short vid_w, short vid_h,
448301ea0f4Smrg  short drw_w, short drw_h,
449301ea0f4Smrg  unsigned int *p_w, unsigned int *p_h,
450301ea0f4Smrg  pointer data
451301ea0f4Smrg){
452301ea0f4Smrg   if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1;
453301ea0f4Smrg   if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1;
454301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740QueryBestSize entered %d %d %d %d\n", (int) vid_w, (int) vid_h, (int) drw_w, (int) drw_h);  /* ### */
455301ea0f4Smrg  fprintf(stderr, "fprintf - I740QueryBestSize entered %d %d %d %d\n", (int) vid_w, (int) vid_h, (int) drw_w, (int) drw_h);  /* ### */
456301ea0f4Smrg
457301ea0f4Smrg  *p_w = drw_w;
458301ea0f4Smrg  *p_h = drw_h;
459301ea0f4Smrg}
460301ea0f4Smrg
461301ea0f4Smrgstatic void I740CopyMungedData(ScrnInfoPtr pScrn,
462301ea0f4Smrg   unsigned char *src1, unsigned char *src2, unsigned char *src3,
463301ea0f4Smrg   int srcPitch,
464301ea0f4Smrg   int srcPitch2,
465301ea0f4Smrg   int dstPitch,
466301ea0f4Smrg   int h,
467301ea0f4Smrg   int w,
468301ea0f4Smrg   long scalex,
469301ea0f4Smrg   long scaley)
470301ea0f4Smrg{
471301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
472301ea0f4Smrg  I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
473301ea0f4Smrg  CARD32 *dst;
474301ea0f4Smrg  int i, j;
475301ea0f4Smrg
476301ea0f4Smrg  if (pPriv->currentBuf == 0)
477301ea0f4Smrg    dst = (CARD32 *)(pI740->FbBase + pPriv->YBuf0offset);
478301ea0f4Smrg  else
479301ea0f4Smrg    dst = (CARD32 *)(pI740->FbBase + pPriv->YBuf1offset);
480301ea0f4Smrg
481301ea0f4Smrg  dstPitch >>= 2;
482301ea0f4Smrg  w >>= 1;
483301ea0f4Smrg
484301ea0f4Smrg    /* If the space on the screen is smaller than the source image, then we use
485301ea0f4Smrg     * software scaling to make it smaller. */
486301ea0f4Smrg  if (scalex > 0x10000 || scaley > 0x10000) {
487301ea0f4Smrg    int dsth = ((long) h * 0x10000L + scaley - 1) / scaley;
488301ea0f4Smrg    long halfx = scalex/2;
489301ea0f4Smrg    long dstj = 0;
490301ea0f4Smrg    for(j = 0; j < dsth; j++) {
491301ea0f4Smrg      int dstj_rnd = dstj >> 16;
492301ea0f4Smrg      unsigned char* src1_ = src1 + (dstj_rnd * srcPitch);
493301ea0f4Smrg      unsigned char* src2_ = src2 + ((dstj_rnd/2) * srcPitch2);
494301ea0f4Smrg      unsigned char* src3_ = src3 + ((dstj_rnd/2) * srcPitch2);
495301ea0f4Smrg      int dstw = ((long) w * 0x10000L + halfx - 1) / scalex;
496301ea0f4Smrg      long srci = 0;
497301ea0f4Smrg      for(i = 0; i < dstw; i++) {
498301ea0f4Smrg	long srci_rnd = srci >> 16;
499301ea0f4Smrg	long srci2_rnd = (srci + halfx) >> 16;
500301ea0f4Smrg	dst[i] =
501301ea0f4Smrg	  (((src1_[srci_rnd << 1] | (src1_[(srci_rnd << 1) + 1] << 16) |
502301ea0f4Smrg	  (src3_[srci_rnd] << 8) | (src2_[srci_rnd] << 24))) >> 1 & 0x7F7F7F7FL)
503301ea0f4Smrg	    +
504301ea0f4Smrg	  (((src1_[srci2_rnd << 1] | (src1_[(srci2_rnd << 1) + 1] << 16) |
505301ea0f4Smrg	  (src3_[srci2_rnd] << 8) | (src2_[srci2_rnd] << 24))) >> 1 & 0x7F7F7F7FL);
506301ea0f4Smrg	srci += scalex;
507301ea0f4Smrg      }
508301ea0f4Smrg      dst += dstPitch;
509301ea0f4Smrg      dstj += scaley;
510301ea0f4Smrg    }
511301ea0f4Smrg  }
512301ea0f4Smrg  else {
513301ea0f4Smrg    for(j = 0; j < h; j++) {
514301ea0f4Smrg      for(i = 0; i < w; i++) {
515301ea0f4Smrg	dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
516301ea0f4Smrg	  (src3[i] << 8) | (src2[i] << 24);
517301ea0f4Smrg      }
518301ea0f4Smrg      dst += dstPitch;
519301ea0f4Smrg      src1 += srcPitch;
520301ea0f4Smrg      if(j & 1) {
521301ea0f4Smrg	src2 += srcPitch2;
522301ea0f4Smrg	src3 += srcPitch2;
523301ea0f4Smrg      }
524301ea0f4Smrg    }
525301ea0f4Smrg  }
526301ea0f4Smrg}
527301ea0f4Smrg
528301ea0f4Smrg
529301ea0f4Smrg__inline__ static void I740CopyPackedData(ScrnInfoPtr pScrn,
530301ea0f4Smrg					  unsigned char *buf,
531301ea0f4Smrg					  int srcPitch,
532301ea0f4Smrg					  int dstPitch,
533301ea0f4Smrg					  int top,
534301ea0f4Smrg					  int left,
535301ea0f4Smrg					  int h,
536301ea0f4Smrg					  int w
537301ea0f4Smrg					  )
538301ea0f4Smrg{
539301ea0f4Smrg    I740Ptr pI740 = I740PTR(pScrn);
540301ea0f4Smrg    I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
541301ea0f4Smrg    unsigned char *src, *dst;
542301ea0f4Smrg
543301ea0f4Smrg    src = buf + (top*srcPitch) + (left<<1);
544301ea0f4Smrg
545301ea0f4Smrg    if (pPriv->currentBuf == 0)
546301ea0f4Smrg	dst = pI740->FbBase + pPriv->YBuf0offset;
547301ea0f4Smrg    else
548301ea0f4Smrg	dst = pI740->FbBase + pPriv->YBuf1offset;
549301ea0f4Smrg
550301ea0f4Smrg    w <<= 1;
551301ea0f4Smrg    while(h--) {
552301ea0f4Smrg	memcpy(dst, src, w);
553301ea0f4Smrg	src += srcPitch;
554301ea0f4Smrg	dst += dstPitch;
555301ea0f4Smrg    }
556301ea0f4Smrg}
557301ea0f4Smrg
558301ea0f4Smrg
559301ea0f4Smrg__inline__ static void I740DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
560301ea0f4Smrg					int dstPitch,  /* of chroma for 4:2:0 */
561301ea0f4Smrg					int x1, int y1, int x2, int y2,
562301ea0f4Smrg					BoxPtr dstBox,
563301ea0f4Smrg					short src_w, short src_h, short drw_w, short drw_h,
564301ea0f4Smrg					unsigned char vd_mod
565301ea0f4Smrg					)
566301ea0f4Smrg{
567301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
568301ea0f4Smrg  I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
569301ea0f4Smrg
570301ea0f4Smrg  i740fb_overlay_set(pScrn,pPriv,pPriv->YBuf0offset,pPriv->YBuf1offset,
571301ea0f4Smrg		     src_w,src_h,                                        /* source      image size */
572301ea0f4Smrg		     drw_w,drw_h,                                        /* destination image size */
573301ea0f4Smrg		     dstBox->x1,dstBox->y1,                              /* destination image pos to display */
574301ea0f4Smrg		     dstBox->x2 - dstBox->x1,dstBox->y2 - dstBox->y1,    /* destination image size to display allows trunc... */
575301ea0f4Smrg		     dstPitch,(pPriv->currentBuf != 0),
576301ea0f4Smrg		     vd_mod);
577301ea0f4Smrg
578301ea0f4Smrg  i740fb_colorkey(pScrn,pPriv->colorKey);                                /* needed to reset properly the i740 board after switching from framebuffer */
579301ea0f4Smrg}
580301ea0f4Smrg
581301ea0f4Smrgstatic FBLinearPtr I740AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
582301ea0f4Smrg{
583301ea0f4Smrg  ScreenPtr pScreen;
584301ea0f4Smrg  FBLinearPtr new_linear;
585301ea0f4Smrg
586301ea0f4Smrg  if(linear)
587301ea0f4Smrg    {
588301ea0f4Smrg      if(linear->size >= size)
589301ea0f4Smrg	return linear;
590301ea0f4Smrg
591301ea0f4Smrg      if(xf86ResizeOffscreenLinear(linear, size)) {
592301ea0f4Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory resized to %d - %p\n", (int) size, (void *)linear);  /* ### */
593301ea0f4Smrg	return linear;
594301ea0f4Smrg      }
595301ea0f4Smrg
596301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory free %p - %d < %d\n", (void *)linear, (int) linear->size, (int) size);  /* ### */
597301ea0f4Smrg      xf86FreeOffscreenLinear(linear);
598301ea0f4Smrg    }
599301ea0f4Smrg
6005c69f917Smrg  pScreen = xf86ScrnToScreen(pScrn);
601301ea0f4Smrg
602301ea0f4Smrg  new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
603301ea0f4Smrg
604301ea0f4Smrg  if(!new_linear)
605301ea0f4Smrg    {
606301ea0f4Smrg      int max_size;
607301ea0f4Smrg
608301ea0f4Smrg      xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME);
609301ea0f4Smrg
610301ea0f4Smrg      if(max_size < size) {
611301ea0f4Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory can't purge %d < %d\n", (int) max_size, (int) size);  /* ### */
612301ea0f4Smrg	return NULL;
613301ea0f4Smrg      }
614301ea0f4Smrg
615301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory purged %d\n", (int) max_size);  /* ### */
616301ea0f4Smrg      xf86PurgeUnlockedOffscreenAreas(pScreen);
617301ea0f4Smrg      new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
618301ea0f4Smrg					       NULL, NULL, NULL);
619301ea0f4Smrg    }
620301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory allocated %d - %p\n", (int) size, (void *)new_linear);  /* ### */
621301ea0f4Smrg
622301ea0f4Smrg  return new_linear;
623301ea0f4Smrg}
624301ea0f4Smrg
625301ea0f4Smrgstatic int I740PutImage(ScrnInfoPtr pScrn,
626301ea0f4Smrg			short src_x, short src_y, short drw_x, short drw_y,
627301ea0f4Smrg			short src_w, short src_h, short drw_w, short drw_h,
628301ea0f4Smrg			int id, unsigned char* buf,
629301ea0f4Smrg			short width, short height,
630301ea0f4Smrg			Bool sync, RegionPtr clipBoxes, pointer data,
631301ea0f4Smrg			DrawablePtr pDraw
632301ea0f4Smrg			)
633301ea0f4Smrg{
634301ea0f4Smrg  ScreenPtr pScreen = pScrn->pScreen;
635301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
636301ea0f4Smrg  I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
637301ea0f4Smrg  INT32 x1, x2, y1, y2;
638301ea0f4Smrg  int srcPitch, dstPitch, srcPitch2=0;
639301ea0f4Smrg  int top, left, npixels, nlines, size;
640301ea0f4Smrg  BoxRec dstBox;
641301ea0f4Smrg  int offset2=0, offset3=0;
642301ea0f4Smrg
643301ea0f4Smrg  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740PutImage entered %d %d\n", (int) width, (int) height, id);*/  /* ### */
644301ea0f4Smrg
645301ea0f4Smrg  /* Clip */
646301ea0f4Smrg  x1 = src_x;
647301ea0f4Smrg  x2 = src_x + src_w;
648301ea0f4Smrg  y1 = src_y;
649301ea0f4Smrg  y2 = src_y + src_h;
650301ea0f4Smrg
651301ea0f4Smrg  dstBox.x1 = drw_x;
652301ea0f4Smrg  dstBox.x2 = drw_x + drw_w;
653301ea0f4Smrg  dstBox.y1 = drw_y;
654301ea0f4Smrg  dstBox.y2 = drw_y + drw_h;
655301ea0f4Smrg
656301ea0f4Smrg  I740ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
657301ea0f4Smrg		REGION_EXTENTS(pScreen, clipBoxes), width, height);
658301ea0f4Smrg
659301ea0f4Smrg  if((x1 >= x2) || (y1 >= y2)) {
660301ea0f4Smrg    return Success;
661301ea0f4Smrg  }
662301ea0f4Smrg
663301ea0f4Smrg  dstBox.x1 -= pScrn->frameX0;
664301ea0f4Smrg  dstBox.x2 -= pScrn->frameX0;
665301ea0f4Smrg  dstBox.y1 -= pScrn->frameY0;
666301ea0f4Smrg  dstBox.y2 -= pScrn->frameY0;
667301ea0f4Smrg
668301ea0f4Smrg  switch(id)
669301ea0f4Smrg    {
670301ea0f4Smrg    case FOURCC_YV12:
671301ea0f4Smrg    case FOURCC_I420:
672301ea0f4Smrg      srcPitch = (width + 3) & ~3;
673301ea0f4Smrg      offset2 = srcPitch * height;
674301ea0f4Smrg      srcPitch2 = ((width >> 1) + 3) & ~3;
675301ea0f4Smrg      offset3 = (srcPitch2 * (height >> 1)) + offset2;
676301ea0f4Smrg      dstPitch = ((width << 1) + 15) & ~15;
677301ea0f4Smrg      size = dstPitch * height;
678301ea0f4Smrg      break;
679301ea0f4Smrg    case FOURCC_UYVY:
680301ea0f4Smrg    case FOURCC_YUY2:
681301ea0f4Smrg    default:
682301ea0f4Smrg      srcPitch = (width << 1);
683301ea0f4Smrg      dstPitch = (srcPitch + 7) & ~7;
684301ea0f4Smrg      size = dstPitch * height;
685301ea0f4Smrg      break;
686301ea0f4Smrg    }
687301ea0f4Smrg
688301ea0f4Smrg  {
689301ea0f4Smrg    FBLinearPtr new_linear = I740AllocateMemory(pScrn, pPriv->linear, size);
690301ea0f4Smrg    if (new_linear != pPriv->linear) {
691301ea0f4Smrg      pPriv->linear = new_linear;
692301ea0f4Smrg    }
693301ea0f4Smrg  }
694301ea0f4Smrg  if(!pPriv->linear)
695301ea0f4Smrg    return BadAlloc;
696301ea0f4Smrg
697301ea0f4Smrg  /* fixup pointers */
698301ea0f4Smrg  pPriv->YBuf0offset = pPriv->linear->offset*pI740->cpp;
699301ea0f4Smrg  pPriv->YBuf1offset = (pPriv->linear->offset*pI740->cpp) + size;
700301ea0f4Smrg
701301ea0f4Smrg
702301ea0f4Smrg#if 0 /*???*/
703301ea0f4Smrg  /* wait for the last rendered buffer to be flipped in */
704301ea0f4Smrg  while (((INREG(DOV0STA)&0x00100000)>>20) != pPriv->currentBuf);
705301ea0f4Smrg#endif
706301ea0f4Smrg
707301ea0f4Smrg  /* buffer swap */
708301ea0f4Smrg  pPriv->currentBuf ^= 1;
709301ea0f4Smrg
710301ea0f4Smrg  /* copy data */
711301ea0f4Smrg  top = y1 >> 16;
712301ea0f4Smrg  left = (x1 >> 16) & ~1;
713301ea0f4Smrg  npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
714301ea0f4Smrg
715301ea0f4Smrg  switch(id) {
716301ea0f4Smrg  case FOURCC_YV12:
717301ea0f4Smrg  case FOURCC_I420:
718301ea0f4Smrg    {
719301ea0f4Smrg      CARD32 tmp;
720301ea0f4Smrg
721301ea0f4Smrg      top &= ~1;
722301ea0f4Smrg      tmp = ((top >> 1) * srcPitch2) + (left >> 1);
723301ea0f4Smrg      offset2 += tmp;
724301ea0f4Smrg      offset3 += tmp;
725301ea0f4Smrg
726301ea0f4Smrg      if(id == FOURCC_I420)
727301ea0f4Smrg	{
728301ea0f4Smrg	  tmp = offset2;
729301ea0f4Smrg	  offset2 = offset3;
730301ea0f4Smrg	  offset3 = tmp;
731301ea0f4Smrg	}
732301ea0f4Smrg
733301ea0f4Smrg      nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
734301ea0f4Smrg
735301ea0f4Smrg        /* If the screen image size is smaller than the video image size, then
736301ea0f4Smrg	 * we use software scaling to make it smaller.  The hardware takes care
737301ea0f4Smrg	 * of scaling up - see i740fb_overlay_set.
738301ea0f4Smrg	 */
739301ea0f4Smrg      {
740301ea0f4Smrg	long scalex = 0x10000, scaley = 0x10000;
741301ea0f4Smrg	if (drw_w < src_w)
742301ea0f4Smrg	  scalex = (0x10000L * (long) src_w) / (long) drw_w;
743301ea0f4Smrg	if (drw_h < src_h)
744301ea0f4Smrg	  scaley = (0x10000L * (long) src_h) / (long) drw_h;
745301ea0f4Smrg
746301ea0f4Smrg	I740CopyMungedData(pScrn, buf + (top * srcPitch) + left,
747301ea0f4Smrg			   buf + offset2, buf + offset3,
748301ea0f4Smrg			   srcPitch, srcPitch2, dstPitch, nlines, npixels, scalex, scaley);
749301ea0f4Smrg      }
750301ea0f4Smrg    }
751301ea0f4Smrg    break;
752301ea0f4Smrg
753301ea0f4Smrg  case FOURCC_UYVY: case FOURCC_YUY2: default:
754301ea0f4Smrg    {
755301ea0f4Smrg      nlines = ((y2 + 0xffff) >> 16) - top;
756301ea0f4Smrg        /* Add software scaling as above. */
757301ea0f4Smrg      I740CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines,
758301ea0f4Smrg			 npixels);
759301ea0f4Smrg    }
760301ea0f4Smrg    break;
761301ea0f4Smrg  }
762301ea0f4Smrg
763301ea0f4Smrg  /* update cliplist */
764301ea0f4Smrg  if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes))
765301ea0f4Smrg    {
766301ea0f4Smrg      REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
767301ea0f4Smrg      /* draw these */
768301ea0f4Smrg      xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes);
769301ea0f4Smrg    }
770301ea0f4Smrg
771301ea0f4Smrg  {
772301ea0f4Smrg    unsigned char vd_mod;
773301ea0f4Smrg
774301ea0f4Smrg    switch(id)
775301ea0f4Smrg      {
776301ea0f4Smrg      case FOURCC_RV15: vd_mod=0x09; break;
777301ea0f4Smrg      case FOURCC_RV16: vd_mod=0x08; break;
778301ea0f4Smrg      default:          vd_mod=0x00; break;
779301ea0f4Smrg      }
780301ea0f4Smrg
781301ea0f4Smrg    I740DisplayVideo(pScrn, id, width, height, dstPitch,
782301ea0f4Smrg		     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h,
783301ea0f4Smrg		     vd_mod);
784301ea0f4Smrg  }
785301ea0f4Smrg
786301ea0f4Smrg  pPriv->videoStatus = CLIENT_VIDEO_ON;
787301ea0f4Smrg
788301ea0f4Smrg  return Success;
789301ea0f4Smrg}
790301ea0f4Smrg
791301ea0f4Smrg
792301ea0f4Smrgstatic int I740QueryImageAttributes(ScrnInfoPtr pScrn, int id, unsigned short *w, unsigned short *h, int *pitches, int *offsets )
793301ea0f4Smrg{
794301ea0f4Smrg  int size,tmp;
795301ea0f4Smrg
796301ea0f4Smrg  if(*w > IMAGE_MAX_PHY_WIDTH) *w = IMAGE_MAX_PHY_WIDTH;
797301ea0f4Smrg  if(*h > IMAGE_MAX_PHY_HEIGHT) *h = IMAGE_MAX_PHY_HEIGHT;
798301ea0f4Smrg
799301ea0f4Smrg  *w = (*w + 1) & ~1;
800301ea0f4Smrg  if(offsets) offsets[0] = 0;
801301ea0f4Smrg
802301ea0f4Smrg  switch(id)
803301ea0f4Smrg    {
804301ea0f4Smrg    case FOURCC_YV12:
805301ea0f4Smrg    case FOURCC_I420:
806301ea0f4Smrg      *h = (*h + 1) & ~1;
807301ea0f4Smrg      size = (*w + 3) & ~3;
808301ea0f4Smrg      if(pitches) pitches[0] = size;
809301ea0f4Smrg      size *= *h;
810301ea0f4Smrg      if(offsets) offsets[1] = size;
811301ea0f4Smrg      tmp = ((*w >> 1) + 3) & ~3;
812301ea0f4Smrg      if(pitches) pitches[1] = pitches[2] = tmp;
813301ea0f4Smrg      tmp *= (*h >> 1);
814301ea0f4Smrg      size += tmp;
815301ea0f4Smrg      if(offsets) offsets[2] = size;
816301ea0f4Smrg      size += tmp;
817301ea0f4Smrg      break;
818301ea0f4Smrg    case FOURCC_UYVY:
819301ea0f4Smrg    case FOURCC_YUY2:
820301ea0f4Smrg    default:
821301ea0f4Smrg      size = *w << 1;
822301ea0f4Smrg      if(pitches) pitches[0] = size;
823301ea0f4Smrg      size *= *h;
824301ea0f4Smrg      break;
825301ea0f4Smrg    }
826301ea0f4Smrg
827301ea0f4Smrg  return size;
828301ea0f4Smrg}
829301ea0f4Smrg
8305c69f917Smrgstatic void I740BlockHandler(BLOCKHANDLER_ARGS_DECL)
831301ea0f4Smrg{
8325c69f917Smrg  SCREEN_PTR(arg);
8335c69f917Smrg  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
834301ea0f4Smrg  I740Ptr      pI740 = I740PTR(pScrn);
835301ea0f4Smrg  I740PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
836301ea0f4Smrg
837301ea0f4Smrg  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740BlockHandler entered\n"); */  /* ### */
838301ea0f4Smrg
839301ea0f4Smrg  pScreen->BlockHandler = pI740->BlockHandler;
840301ea0f4Smrg
8415c69f917Smrg  (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
842301ea0f4Smrg
843301ea0f4Smrg  pScreen->BlockHandler = I740BlockHandler;
844301ea0f4Smrg
845301ea0f4Smrg  if(pPriv->videoStatus & TIMER_MASK)
846301ea0f4Smrg    {
847301ea0f4Smrg      UpdateCurrentTime();
848301ea0f4Smrg      if(pPriv->videoStatus & OFF_TIMER)
849301ea0f4Smrg	{
850301ea0f4Smrg	  if(pPriv->offTime < currentTime.milliseconds)
851301ea0f4Smrg	    {
852301ea0f4Smrg              /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740BlockHandler: OFF_TIMER expired\n");*/  /* ### */
853301ea0f4Smrg	      /* Turn off the overlay */
854301ea0f4Smrg	      i740fb_overlay_off(pScrn);
855301ea0f4Smrg
856301ea0f4Smrg	      pPriv->videoStatus = FREE_TIMER;
857301ea0f4Smrg	      pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
858301ea0f4Smrg	    }
859301ea0f4Smrg	}
860301ea0f4Smrg      else
861301ea0f4Smrg	{  /* FREE_TIMER */
862301ea0f4Smrg	  if(pPriv->freeTime < currentTime.milliseconds)
863301ea0f4Smrg	    {
864301ea0f4Smrg	      if(pPriv->linear)
865301ea0f4Smrg		{
866301ea0f4Smrg                  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740BlockHandler: FREE_TIMER expired\n");*/  /* ### */
867301ea0f4Smrg		  xf86FreeOffscreenLinear(pPriv->linear);
868301ea0f4Smrg		  pPriv->linear = NULL;
869301ea0f4Smrg		}
870301ea0f4Smrg	      pPriv->videoStatus = 0;
871301ea0f4Smrg	    }
872301ea0f4Smrg        }
873301ea0f4Smrg    }
874301ea0f4Smrg}
875301ea0f4Smrg
876301ea0f4Smrg
877301ea0f4Smrg/***************************************************************************
878301ea0f4Smrg * Offscreen Images
879301ea0f4Smrg ***************************************************************************/
880301ea0f4Smrg
881301ea0f4Smrgtypedef struct {
882301ea0f4Smrg  FBLinearPtr linear;
883301ea0f4Smrg  Bool isOn;
884301ea0f4Smrg} OffscreenPrivRec, * OffscreenPrivPtr;
885301ea0f4Smrg
886301ea0f4Smrgstatic int I740AllocateSurface(
887301ea0f4Smrg    ScrnInfoPtr pScrn,
888301ea0f4Smrg    int id,
889301ea0f4Smrg    unsigned short w,
890301ea0f4Smrg    unsigned short h,
891301ea0f4Smrg    XF86SurfacePtr surface
892301ea0f4Smrg){
893301ea0f4Smrg    FBLinearPtr linear;
894301ea0f4Smrg    int pitch, size;
895301ea0f4Smrg    OffscreenPrivPtr pPriv;
896301ea0f4Smrg    I740Ptr pI740 = I740PTR(pScrn);
897301ea0f4Smrg
898301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateSurface entered %d %d\n", (int) w, (int) h);  /* ### */
899301ea0f4Smrg
900301ea0f4Smrg    if((w > IMAGE_MAX_LOG_WIDTH) || (h > IMAGE_MAX_LOG_HEIGHT))
901301ea0f4Smrg	return BadAlloc;
902301ea0f4Smrg
903301ea0f4Smrg    w = (w + 1) & ~1;
904301ea0f4Smrg    pitch = ((w << 1) + 15) & ~15;
905301ea0f4Smrg    size = pitch * h;
906301ea0f4Smrg
907301ea0f4Smrg    if(!(linear = I740AllocateMemory(pScrn, NULL, size)))
908301ea0f4Smrg	return BadAlloc;
909301ea0f4Smrg
910301ea0f4Smrg    surface->width = w;
911301ea0f4Smrg    surface->height = h;
912301ea0f4Smrg
9135c69f917Smrg    if(!(surface->pitches = malloc(sizeof(int)))) {
914301ea0f4Smrg	xf86FreeOffscreenLinear(linear);
915301ea0f4Smrg	return BadAlloc;
916301ea0f4Smrg    }
9175c69f917Smrg    if(!(surface->offsets = malloc(sizeof(int)))) {
9185c69f917Smrg	free(surface->pitches);
919301ea0f4Smrg	xf86FreeOffscreenLinear(linear);
920301ea0f4Smrg	return BadAlloc;
921301ea0f4Smrg    }
9225c69f917Smrg    if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
9235c69f917Smrg	free(surface->pitches);
9245c69f917Smrg	free(surface->offsets);
925301ea0f4Smrg	xf86FreeOffscreenLinear(linear);
926301ea0f4Smrg	return BadAlloc;
927301ea0f4Smrg    }
928301ea0f4Smrg
929301ea0f4Smrg    pPriv->linear = linear;
930301ea0f4Smrg    pPriv->isOn = FALSE;
931301ea0f4Smrg
932301ea0f4Smrg    surface->pScrn = pScrn;
933301ea0f4Smrg    surface->id = id;
934301ea0f4Smrg    surface->pitches[0] = pitch;
935301ea0f4Smrg    surface->offsets[0] = linear->offset*pI740->cpp;
936301ea0f4Smrg    surface->devPrivate.ptr = (pointer)pPriv;
937301ea0f4Smrg
938301ea0f4Smrg    /*//memset(pI740->FbBase + surface->offsets[0],0,size);*/
939301ea0f4Smrg
940301ea0f4Smrg    return Success;
941301ea0f4Smrg}
942301ea0f4Smrg
943301ea0f4Smrgstatic int I740StopSurface(XF86SurfacePtr surface)
944301ea0f4Smrg{
945301ea0f4Smrg  OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
946301ea0f4Smrg
947301ea0f4Smrg  if(pPriv->isOn)
948301ea0f4Smrg    {
949301ea0f4Smrg      /*//i740fb_overlay_off(pScrn);*/
950301ea0f4Smrg
951301ea0f4Smrg      pPriv->isOn = FALSE;
952301ea0f4Smrg    }
953301ea0f4Smrg
954301ea0f4Smrg  return Success;
955301ea0f4Smrg}
956301ea0f4Smrg
957301ea0f4Smrg
958301ea0f4Smrgstatic int I740FreeSurface(XF86SurfacePtr surface)
959301ea0f4Smrg{
960301ea0f4Smrg  OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
961301ea0f4Smrg
962301ea0f4Smrg  if(pPriv->isOn)
963301ea0f4Smrg    {
964301ea0f4Smrg      I740StopSurface(surface);
965301ea0f4Smrg    }
966301ea0f4Smrg
967301ea0f4Smrg  xf86FreeOffscreenLinear(pPriv->linear);
9685c69f917Smrg  free(surface->pitches);
9695c69f917Smrg  free(surface->offsets);
9705c69f917Smrg  free(surface->devPrivate.ptr);
971301ea0f4Smrg
972301ea0f4Smrg  return Success;
973301ea0f4Smrg}
974301ea0f4Smrg
975301ea0f4Smrgstatic int I740GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
976301ea0f4Smrg{
977301ea0f4Smrg  return I740GetPortAttribute(pScrn, attribute, value, 0);
978301ea0f4Smrg}
979301ea0f4Smrg
980301ea0f4Smrgstatic int I740SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
981301ea0f4Smrg{
982301ea0f4Smrg  return I740SetPortAttribute(pScrn, attribute, value, 0);
983301ea0f4Smrg}
984301ea0f4Smrg
985301ea0f4Smrg
986301ea0f4Smrgstatic int I740DisplaySurface(XF86SurfacePtr surface, short src_x, short src_y,
987301ea0f4Smrg			      short drw_x, short drw_y,
988301ea0f4Smrg			      short src_w, short src_h,
989301ea0f4Smrg			      short drw_w, short drw_h,
990301ea0f4Smrg			      RegionPtr clipBoxes)
991301ea0f4Smrg{
992301ea0f4Smrg  OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
993301ea0f4Smrg  ScrnInfoPtr pScrn = surface->pScrn;
994301ea0f4Smrg  I740PortPrivPtr pI740Priv =  GET_PORT_PRIVATE(pScrn);
995301ea0f4Smrg
996301ea0f4Smrg  INT32 x1, y1, x2, y2;
997301ea0f4Smrg  BoxRec dstBox;
998301ea0f4Smrg
999301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740DisplaySurface entered\n");  /* ### */
1000301ea0f4Smrg  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"I740DisplaySurface-----------------------------------\n");*/
1001301ea0f4Smrg  /*//fprintf(stderr, "I740DisplaySurface-----------------------------------\n");*/
1002301ea0f4Smrg
1003301ea0f4Smrg
1004301ea0f4Smrg  x1 = src_x;
1005301ea0f4Smrg  x2 = src_x + src_w;
1006301ea0f4Smrg  y1 = src_y;
1007301ea0f4Smrg  y2 = src_y + src_h;
1008301ea0f4Smrg
1009301ea0f4Smrg  dstBox.x1 = drw_x;
1010301ea0f4Smrg  dstBox.x2 = drw_x + drw_w;
1011301ea0f4Smrg  dstBox.y1 = drw_y;
1012301ea0f4Smrg  dstBox.y2 = drw_y + drw_h;
1013301ea0f4Smrg
1014301ea0f4Smrg  I740ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
1015301ea0f4Smrg		REGION_EXTENTS(screenInfo.screens[0], clipBoxes),
1016301ea0f4Smrg		surface->width, surface->height);
1017301ea0f4Smrg
1018301ea0f4Smrg  dstBox.x1 -= pScrn->frameX0;
1019301ea0f4Smrg  dstBox.x2 -= pScrn->frameX0;
1020301ea0f4Smrg  dstBox.y1 -= pScrn->frameY0;
1021301ea0f4Smrg  dstBox.y2 -= pScrn->frameY0;
1022301ea0f4Smrg
1023301ea0f4Smrg  /* fixup pointers */
1024301ea0f4Smrg  pI740Priv->YBuf0offset = surface->offsets[0];
1025301ea0f4Smrg  pI740Priv->YBuf1offset = pI740Priv->YBuf0offset;
1026301ea0f4Smrg
1027301ea0f4Smrg#if 0 /*???*/
1028301ea0f4Smrg  /* wait for the last rendered buffer to be flipped in */
1029301ea0f4Smrg  while (((INREG(DOV0STA)&0x00100000)>>20) != pI740Priv->currentBuf) {
1030301ea0f4Smrg    if(loops == 200000) {
1031301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");
1032301ea0f4Smrg      break;
1033301ea0f4Smrg    }
1034301ea0f4Smrg    loops++;
1035301ea0f4Smrg  }
1036301ea0f4Smrg#endif
1037301ea0f4Smrg
1038301ea0f4Smrg  /* buffer swap */
1039301ea0f4Smrg  if (pI740Priv->currentBuf == 0)
1040301ea0f4Smrg    pI740Priv->currentBuf = 1;
1041301ea0f4Smrg  else
1042301ea0f4Smrg    pI740Priv->currentBuf = 0;
1043301ea0f4Smrg
1044301ea0f4Smrg  I740ResetVideo(pScrn);
1045301ea0f4Smrg
1046301ea0f4Smrg  I740DisplayVideo(pScrn, surface->id, surface->width, surface->height,
1047301ea0f4Smrg		   surface->pitches[0], x1, y1, x2, y2, &dstBox,
1048301ea0f4Smrg		   src_w, src_h, drw_w, drw_h,
1049301ea0f4Smrg		   0x00);
1050301ea0f4Smrg
1051301ea0f4Smrg  xf86XVFillKeyHelper(pScrn->pScreen, pI740Priv->colorKey, clipBoxes);
1052301ea0f4Smrg
1053301ea0f4Smrg  pPriv->isOn = TRUE;
1054301ea0f4Smrg  /* we've prempted the XvImage stream so set its free timer */
1055301ea0f4Smrg  if(pI740Priv->videoStatus & CLIENT_VIDEO_ON) {
1056301ea0f4Smrg    REGION_EMPTY(pScrn->pScreen, & pI740Priv->clip);
1057301ea0f4Smrg    UpdateCurrentTime();
1058301ea0f4Smrg    pI740Priv->videoStatus = FREE_TIMER;
1059301ea0f4Smrg    pI740Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
1060301ea0f4Smrg    pScrn->pScreen->BlockHandler = I740BlockHandler;
1061301ea0f4Smrg  }
1062301ea0f4Smrg
1063301ea0f4Smrg  return Success;
1064301ea0f4Smrg}
1065301ea0f4Smrg
1066301ea0f4Smrg/*-------------------------------------------------------------------------------------------*/
1067301ea0f4Smrg#define NUM_IMAGES (sizeof(i740vid_Images)/sizeof(XF86ImageRec))
1068301ea0f4Smrgstatic XF86ImageRec i740vid_Images[] =
1069301ea0f4Smrg{
1070301ea0f4Smrg  XVIMAGE_YUY2,
1071301ea0f4Smrg  XVIMAGE_UYVY,
1072301ea0f4Smrg  XVIMAGE_YV12, /* converted to YUV2 while copying */
1073301ea0f4Smrg  XVIMAGE_I420, /* converted to YUV2 while copying */
1074301ea0f4Smrg  {
1075301ea0f4Smrg    FOURCC_RV15,
1076301ea0f4Smrg    XvRGB,
1077301ea0f4Smrg    LSBFirst,
1078301ea0f4Smrg    {'R','V','1','5',
1079301ea0f4Smrg     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
1080301ea0f4Smrg    16,
1081301ea0f4Smrg    XvPacked,
1082301ea0f4Smrg    1,
1083301ea0f4Smrg    15, 0x001F, 0x03E0, 0x7C00,
1084301ea0f4Smrg    0, 0, 0,
1085301ea0f4Smrg    0, 0, 0,
1086301ea0f4Smrg    0, 0, 0,
1087301ea0f4Smrg    {'R','V','B',0,
1088301ea0f4Smrg     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},
1089301ea0f4Smrg    XvTopToBottom
1090301ea0f4Smrg  },
1091301ea0f4Smrg  {
1092301ea0f4Smrg    FOURCC_RV16,
1093301ea0f4Smrg    XvRGB,
1094301ea0f4Smrg    LSBFirst,
1095301ea0f4Smrg    {'R','V','1','6',
1096301ea0f4Smrg     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
1097301ea0f4Smrg    16,
1098301ea0f4Smrg    XvPacked,
1099301ea0f4Smrg    1,
1100301ea0f4Smrg    16, 0x001F, 0x07E0, 0xF800,
1101301ea0f4Smrg    0, 0, 0,
1102301ea0f4Smrg    0, 0, 0,
1103301ea0f4Smrg    0, 0, 0,
1104301ea0f4Smrg    {'R','V','B',0,
1105301ea0f4Smrg     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},
1106301ea0f4Smrg    XvTopToBottom
1107301ea0f4Smrg  },
1108301ea0f4Smrg};
1109301ea0f4Smrg
1110301ea0f4Smrg#define NUM_ATTRIBUTES (sizeof(i740vid_Attributes)/sizeof(XF86AttributeRec))
1111301ea0f4Smrg
1112301ea0f4Smrgstatic XF86AttributeRec i740vid_Attributes[] =
1113301ea0f4Smrg{
1114301ea0f4Smrg   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
1115301ea0f4Smrg   {XvSettable | XvGettable, -128, 127,        "XV_BRIGHTNESS"},
1116301ea0f4Smrg   {XvSettable | XvGettable, 0, 255,           "XV_CONTRAST"}
1117301ea0f4Smrg};
1118301ea0f4Smrg
1119301ea0f4Smrg
1120301ea0f4Smrgstatic void I740InitOffscreenImages(ScreenPtr pScreen)
1121301ea0f4Smrg{
1122301ea0f4Smrg  XF86OffscreenImagePtr offscreenImages;
1123301ea0f4Smrg  {
11245c69f917Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1125301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740InitOffscreenImages entered\n");  /* ### */
1126301ea0f4Smrg  }
1127301ea0f4Smrg
1128301ea0f4Smrg  /* need to free this someplace */
11295c69f917Smrg  if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
1130301ea0f4Smrg    {
1131301ea0f4Smrg      return;
1132301ea0f4Smrg    }
1133301ea0f4Smrg
1134301ea0f4Smrg  offscreenImages[0].image          = &i740vid_Images[0];
1135301ea0f4Smrg  offscreenImages[0].flags          = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1136301ea0f4Smrg  offscreenImages[0].alloc_surface  = I740AllocateSurface;
1137301ea0f4Smrg  offscreenImages[0].free_surface   = I740FreeSurface;
1138301ea0f4Smrg  offscreenImages[0].display        = I740DisplaySurface;
1139301ea0f4Smrg  offscreenImages[0].stop           = I740StopSurface;
1140301ea0f4Smrg  offscreenImages[0].setAttribute   = I740SetSurfaceAttribute;
1141301ea0f4Smrg  offscreenImages[0].getAttribute   = I740GetSurfaceAttribute;
1142301ea0f4Smrg  offscreenImages[0].max_width      = IMAGE_MAX_LOG_WIDTH;
1143301ea0f4Smrg  offscreenImages[0].max_height     = IMAGE_MAX_LOG_HEIGHT;
1144301ea0f4Smrg  offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
1145301ea0f4Smrg  offscreenImages[0].attributes     = i740vid_Attributes;
1146301ea0f4Smrg
1147301ea0f4Smrg  xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
1148301ea0f4Smrg}
1149301ea0f4Smrg
1150301ea0f4Smrg
1151301ea0f4Smrg
1152301ea0f4Smrgstatic XF86VideoAdaptorPtr I740SetupImageVideo(ScreenPtr pScreen)
1153301ea0f4Smrg{
1154301ea0f4Smrg  /* client libraries expect an encoding */
1155301ea0f4Smrg  static XF86VideoEncodingRec DummyEncoding[1] =
1156301ea0f4Smrg  {
1157301ea0f4Smrg    {
1158301ea0f4Smrg      0,
1159301ea0f4Smrg      "XV_IMAGE",
1160301ea0f4Smrg      IMAGE_MAX_PHY_WIDTH, IMAGE_MAX_PHY_HEIGHT,
1161301ea0f4Smrg      {1, 1}
1162301ea0f4Smrg    }
1163301ea0f4Smrg  };
1164301ea0f4Smrg
1165301ea0f4Smrg#define NUM_FORMATS (sizeof(i740vid_Formats)/sizeof(XF86VideoFormatRec))
1166301ea0f4Smrg  static XF86VideoFormatRec i740vid_Formats[] =
1167301ea0f4Smrg  {
1168301ea0f4Smrg    {15, TrueColor}, {16, TrueColor}, {24, TrueColor},  {8, PseudoColor}
1169301ea0f4Smrg  };
1170301ea0f4Smrg
11715c69f917Smrg  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1172301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
1173301ea0f4Smrg  XF86VideoAdaptorPtr adapt;
1174301ea0f4Smrg  I740PortPrivPtr pPriv;
1175301ea0f4Smrg
1176301ea0f4Smrg  /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740SetupImageVideo entered\n");*/  /* ### */
1177301ea0f4Smrg  {
1178301ea0f4Smrg    const int n=sizeof(XF86VideoAdaptorRec)+sizeof(I740PortPrivRec)+sizeof(DevUnion);
1179301ea0f4Smrg
11805c69f917Smrg    if(!(adapt = calloc(1, n)))
1181301ea0f4Smrg      return NULL;
1182301ea0f4Smrg
1183301ea0f4Smrg    /*//memset(adapt,0,n);*/
1184301ea0f4Smrg  }
1185301ea0f4Smrg
1186301ea0f4Smrg  adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1187301ea0f4Smrg  adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1188301ea0f4Smrg  adapt->name = "I740 Video Overlay";
1189301ea0f4Smrg  adapt->nEncodings = 1;
1190301ea0f4Smrg  adapt->pEncodings = DummyEncoding;
1191301ea0f4Smrg  adapt->nFormats = NUM_FORMATS;
1192301ea0f4Smrg  adapt->pFormats = i740vid_Formats;
1193301ea0f4Smrg  adapt->nPorts = 1;
1194301ea0f4Smrg  adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1195301ea0f4Smrg
1196301ea0f4Smrg  pPriv = (I740PortPrivPtr)((unsigned char *)(&adapt[1])+sizeof(sizeof(DevUnion)));
1197301ea0f4Smrg
1198301ea0f4Smrg  adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1199301ea0f4Smrg  adapt->pAttributes          = i740vid_Attributes;
1200301ea0f4Smrg  adapt->nImages              = NUM_IMAGES;
1201301ea0f4Smrg  adapt->nAttributes          = NUM_ATTRIBUTES;
1202301ea0f4Smrg  adapt->pImages              = i740vid_Images;
1203301ea0f4Smrg  adapt->PutVideo             = NULL;
1204301ea0f4Smrg  adapt->PutStill             = NULL;
1205301ea0f4Smrg  adapt->GetVideo             = NULL;
1206301ea0f4Smrg  adapt->GetStill             = NULL;
1207301ea0f4Smrg  adapt->StopVideo            = I740StopVideo;
1208301ea0f4Smrg  adapt->SetPortAttribute     = I740SetPortAttribute;
1209301ea0f4Smrg  adapt->GetPortAttribute     = I740GetPortAttribute;
1210301ea0f4Smrg  adapt->QueryBestSize        = I740QueryBestSize;
1211301ea0f4Smrg  adapt->PutImage             = I740PutImage;
1212301ea0f4Smrg  adapt->QueryImageAttributes = I740QueryImageAttributes;
1213301ea0f4Smrg
1214301ea0f4Smrg  pPriv->colorKey    = pI740->colorKey & ((1 << pScrn->depth) - 1);
1215301ea0f4Smrg  pPriv->videoStatus = 0;
1216301ea0f4Smrg  pPriv->brightness  = 0;
1217301ea0f4Smrg  pPriv->contrast    = 64;
1218301ea0f4Smrg  pPriv->linear      = NULL;
1219301ea0f4Smrg  pPriv->currentBuf  = 0;
1220301ea0f4Smrg
1221301ea0f4Smrg  /* gotta uninit this someplace */
1222301ea0f4Smrg  REGION_NULL(pScreen, &pPriv->clip);
1223301ea0f4Smrg
1224301ea0f4Smrg  pI740->adaptor = adapt;
1225301ea0f4Smrg
1226301ea0f4Smrg  pI740->BlockHandler = pScreen->BlockHandler;
1227301ea0f4Smrg  pScreen->BlockHandler = I740BlockHandler;
1228301ea0f4Smrg
1229301ea0f4Smrg  xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
1230301ea0f4Smrg  xvContrast   = MAKE_ATOM("XV_CONTRAST");
1231301ea0f4Smrg  xvColorKey   = MAKE_ATOM("XV_COLORKEY");
1232301ea0f4Smrg
1233301ea0f4Smrg  I740ResetVideo(pScrn);
1234301ea0f4Smrg
1235301ea0f4Smrg  return adapt;
1236301ea0f4Smrg}
1237301ea0f4Smrg
1238301ea0f4Smrgvoid I740InitVideo(ScreenPtr pScreen)
1239301ea0f4Smrg{
12405c69f917Smrg  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1241301ea0f4Smrg  XF86VideoAdaptorPtr newAdaptor = NULL;
1242301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740InitVideo entered\n");  /* ### */
1243301ea0f4Smrg
1244301ea0f4Smrg#if 0 /*disable!*/
1245301ea0f4Smrg  {
1246301ea0f4Smrg    XF86VideoAdaptorPtr *ptr;
1247301ea0f4Smrg    int n;
1248301ea0f4Smrg
1249301ea0f4Smrg    n = xf86XVListGenericAdaptors(pScrn,&ptr);
1250301ea0f4Smrg    if (n) {
1251301ea0f4Smrg      xf86XVScreenInit(pScreen, ptr, n);
1252301ea0f4Smrg    }
1253301ea0f4Smrg
1254301ea0f4Smrg    return;
1255301ea0f4Smrg  }
1256301ea0f4Smrg#endif
1257301ea0f4Smrg
1258301ea0f4Smrg  {
1259301ea0f4Smrg    newAdaptor = I740SetupImageVideo(pScreen);
1260301ea0f4Smrg    I740InitOffscreenImages(pScreen);
1261301ea0f4Smrg  }
1262301ea0f4Smrg
1263301ea0f4Smrg  {
1264301ea0f4Smrg    XF86VideoAdaptorPtr *adaptors_oldptrs, *adaptors_newptrs = NULL;
1265301ea0f4Smrg    int num_adaptors;
1266301ea0f4Smrg
1267301ea0f4Smrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors_oldptrs);
1268301ea0f4Smrg
1269301ea0f4Smrg    if(newAdaptor)
1270301ea0f4Smrg      {
1271301ea0f4Smrg	if(!num_adaptors)
1272301ea0f4Smrg	  {
1273301ea0f4Smrg	    xf86XVScreenInit(pScreen, &newAdaptor, 1);
1274301ea0f4Smrg	  }
1275301ea0f4Smrg	else
1276301ea0f4Smrg	  {
12775c69f917Smrg	    if((adaptors_newptrs = malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr))))
1278301ea0f4Smrg	      {
1279301ea0f4Smrg		memcpy(adaptors_newptrs, adaptors_oldptrs, num_adaptors * sizeof(XF86VideoAdaptorPtr));
1280301ea0f4Smrg		adaptors_newptrs[num_adaptors] = newAdaptor;
1281301ea0f4Smrg
1282301ea0f4Smrg		/*//xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"num--- %d [%d] %08x %08x\n",num_adaptors,num_adaptors * sizeof(XF86VideoAdaptorPtr),*/
1283301ea0f4Smrg		/*//	   adaptors_newptrs[0],adaptors_newptrs[1]);*/
1284301ea0f4Smrg
1285301ea0f4Smrg
1286301ea0f4Smrg		xf86XVScreenInit(pScreen, adaptors_newptrs, num_adaptors+1);
12875c69f917Smrg		free(adaptors_newptrs);
1288301ea0f4Smrg	      }
1289301ea0f4Smrg	  }
1290301ea0f4Smrg      }
1291301ea0f4Smrg
1292301ea0f4Smrg  }
1293301ea0f4Smrg}
1294