1/*
2Copyright (C) 1994-2000 The XFree86 Project, Inc.  All Rights Reserved.
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
16NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of the XFree86 Project shall not
22be used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from the XFree86 Project.
24*/
25
26/*
27   Copyright (c) 1999,2000  The XFree86 Project Inc.
28   based on code written by Mark Vojkovich <markv@valinux.com>
29*/
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include "xf86.h"
36#include "xf86_OSproc.h"
37#include "xf86Pci.h"
38#include "shadowfb.h"
39#include "servermd.h"
40#include "s3.h"
41
42
43void
44S3RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
45{
46    S3Ptr pS3 = S3PTR(pScrn);
47    int width, height, Bpp, FBPitch;
48    unsigned char *src, *dst;
49
50    Bpp = pScrn->bitsPerPixel >> 3;
51    FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
52
53    while(num--) {
54	width = (pbox->x2 - pbox->x1) * Bpp;
55	height = pbox->y2 - pbox->y1;
56	src = pS3->ShadowPtr + (pbox->y1 * pS3->ShadowPitch) +
57		(pbox->x1 * Bpp);
58	dst = pS3->FBBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
59
60	while(height--) {
61	    memcpy(dst, src, width);
62	    dst += FBPitch;
63	    src += pS3->ShadowPitch;
64	}
65
66	pbox++;
67    }
68}
69
70void
71S3PointerMoved(SCRN_ARG_TYPE arg, int x, int y)
72{
73    SCRN_INFO_PTR(arg);
74    S3Ptr pS3 = S3PTR(pScrn);
75    int newX, newY;
76
77    if(pS3->rotate == 1) {
78	newX = pScrn->pScreen->height - y - 1;
79	newY = x;
80    } else {
81	newX = y;
82	newY = pScrn->pScreen->width - x - 1;
83    }
84
85    (*pS3->PointerMoved)(arg, newX, newY);
86}
87
88void
89S3RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
90{
91    S3Ptr pS3 = S3PTR(pScrn);
92    int count, width, height, y1, y2, dstPitch, srcPitch;
93    CARD8 *dstPtr, *srcPtr, *src;
94    CARD32 *dst;
95
96    dstPitch = pScrn->displayWidth;
97    srcPitch = -pS3->rotate * pS3->ShadowPitch;
98
99    while(num--) {
100	width = pbox->x2 - pbox->x1;
101	y1 = pbox->y1 & ~3;
102	y2 = (pbox->y2 + 3) & ~3;
103	height = (y2 - y1) >> 2;  /* in dwords */
104
105	if(pS3->rotate == 1) {
106	    dstPtr = pS3->FBBase +
107			(pbox->x1 * dstPitch) + pScrn->virtualX - y2;
108	    srcPtr = pS3->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
109	} else {
110	    dstPtr = pS3->FBBase +
111			((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
112	    srcPtr = pS3->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
113	}
114
115	while(width--) {
116	    src = srcPtr;
117	    dst = (CARD32*)dstPtr;
118	    count = height;
119	    while(count--) {
120		*(dst++) = src[0] | (src[srcPitch] << 8) |
121					(src[srcPitch * 2] << 16) |
122					(src[srcPitch * 3] << 24);
123		src += srcPitch * 4;
124	    }
125	    srcPtr += pS3->rotate;
126	    dstPtr += dstPitch;
127	}
128
129	pbox++;
130    }
131}
132
133
134void
135S3RefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
136{
137    S3Ptr pS3 = S3PTR(pScrn);
138    int count, width, height, y1, y2, dstPitch, srcPitch;
139    CARD16 *dstPtr, *srcPtr, *src;
140    CARD32 *dst;
141
142    dstPitch = pScrn->displayWidth;
143    srcPitch = -pS3->rotate * pS3->ShadowPitch >> 1;
144
145    while(num--) {
146	width = pbox->x2 - pbox->x1;
147	y1 = pbox->y1 & ~1;
148	y2 = (pbox->y2 + 1) & ~1;
149	height = (y2 - y1) >> 1;  /* in dwords */
150
151	if(pS3->rotate == 1) {
152	    dstPtr = (CARD16*)pS3->FBBase +
153			(pbox->x1 * dstPitch) + pScrn->virtualX - y2;
154	    srcPtr = (CARD16*)pS3->ShadowPtr +
155			((1 - y2) * srcPitch) + pbox->x1;
156	} else {
157	    dstPtr = (CARD16*)pS3->FBBase +
158			((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
159	    srcPtr = (CARD16*)pS3->ShadowPtr +
160			(y1 * srcPitch) + pbox->x2 - 1;
161	}
162
163	while(width--) {
164	    src = srcPtr;
165	    dst = (CARD32*)dstPtr;
166	    count = height;
167	    while(count--) {
168		*(dst++) = src[0] | (src[srcPitch] << 16);
169		src += srcPitch * 2;
170	    }
171	    srcPtr += pS3->rotate;
172	    dstPtr += dstPitch;
173	}
174
175	pbox++;
176    }
177}
178
179
180/* this one could be faster */
181void
182S3RefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
183{
184    S3Ptr pS3 = S3PTR(pScrn);
185    int count, width, height, y1, y2, dstPitch, srcPitch;
186    CARD8 *dstPtr, *srcPtr, *src;
187    CARD32 *dst;
188
189    dstPitch = BitmapBytePad(pScrn->displayWidth * 24);
190    srcPitch = -pS3->rotate * pS3->ShadowPitch;
191
192    while(num--) {
193        width = pbox->x2 - pbox->x1;
194        y1 = pbox->y1 & ~3;
195        y2 = (pbox->y2 + 3) & ~3;
196        height = (y2 - y1) >> 2;  /* blocks of 3 dwords */
197
198	if(pS3->rotate == 1) {
199	    dstPtr = pS3->FBBase +
200			(pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
201	    srcPtr = pS3->ShadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3);
202	} else {
203	    dstPtr = pS3->FBBase +
204			((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3);
205	    srcPtr = pS3->ShadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3;
206	}
207
208	while(width--) {
209	    src = srcPtr;
210	    dst = (CARD32*)dstPtr;
211	    count = height;
212	    while(count--) {
213		dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) |
214				(src[srcPitch] << 24);
215		dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) |
216				(src[srcPitch * 2] << 16) |
217				(src[(srcPitch * 2) + 1] << 24);
218		dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) |
219				(src[(srcPitch * 3) + 1] << 16) |
220				(src[(srcPitch * 3) + 2] << 24);
221		dst += 3;
222		src += srcPitch * 4;
223	    }
224	    srcPtr += pS3->rotate * 3;
225	    dstPtr += dstPitch;
226	}
227
228	pbox++;
229    }
230}
231
232void
233S3RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
234{
235    S3Ptr pS3 = S3PTR(pScrn);
236    int count, width, height, dstPitch, srcPitch;
237    CARD32 *dstPtr, *srcPtr, *src, *dst;
238
239    dstPitch = pScrn->displayWidth;
240    srcPitch = -pS3->rotate * pS3->ShadowPitch >> 2;
241
242    while(num--) {
243	width = pbox->x2 - pbox->x1;
244	height = pbox->y2 - pbox->y1;
245
246	if(pS3->rotate == 1) {
247	    dstPtr = (CARD32*)pS3->FBBase +
248			(pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2;
249	    srcPtr = (CARD32*)pS3->ShadowPtr +
250			((1 - pbox->y2) * srcPitch) + pbox->x1;
251	} else {
252	    dstPtr = (CARD32*)pS3->FBBase +
253			((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1;
254	    srcPtr = (CARD32*)pS3->ShadowPtr +
255			(pbox->y1 * srcPitch) + pbox->x2 - 1;
256	}
257
258	while(width--) {
259	    src = srcPtr;
260	    dst = dstPtr;
261	    count = height;
262	    while(count--) {
263		*(dst++) = *src;
264		src += srcPitch;
265	    }
266	    srcPtr += pS3->rotate;
267	    dstPtr += dstPitch;
268	}
269
270	pbox++;
271    }
272}
273