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