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