sis_shadow.c revision 72b676d7
1/* $XFree86$ */
2/* $XdotOrg$ */
3/*
4 * Copyright (C) 1999-2004 by The XFree86 Project, Inc.
5 * based on code written by Mark Vojkovich
6 * Copyright (C) 2003-2005 Thomas Winischhofer
7 *
8 * Licensed under the following terms:
9 *
10 * Permission to use, copy, modify, distribute, and sell this software and its
11 * documentation for any purpose is hereby granted without fee, provided that
12 * the above copyright notice appears in all copies and that both that copyright
13 * notice and this permission notice appear in supporting documentation, and
14 * and that the name of the copyright holder not be used in advertising
15 * or publicity pertaining to distribution of the software without specific,
16 * written prior permission. The copyright holder makes no representations
17 * about the suitability of this software for any purpose.  It is provided
18 * "as is" without expressed or implied warranty.
19 *
20 * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
22 * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
23 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
24 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
25 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26 * PERFORMANCE OF THIS SOFTWARE.
27 *
28 * This module doesn't use CurrentLayout, because it is never
29 * active when DGA is active and vice versa.
30 */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include "sis.h"
37#include "servermd.h"
38
39void SISPointerMoved(int index, int x, int y);
40void SISPointerMovedReflect(int index, int x, int y);
41void SISRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
42void SISRefreshAreaReflect(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
43void SISRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
44void SISRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
45void SISRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
46void SISRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
47
48void
49SISPointerMoved(int index, int x, int y)
50{
51    ScrnInfoPtr pScrn = xf86Screens[index];
52    SISPtr pSiS = SISPTR(pScrn);
53
54    if(pSiS->Rotate == 1) {
55       (*pSiS->PointerMoved)(index, pScrn->pScreen->height - y - 1, x);
56    } else {
57       (*pSiS->PointerMoved)(index, y, pScrn->pScreen->width - x - 1);
58    }
59}
60
61void
62SISPointerMovedReflect(int index, int x, int y)
63{
64    ScrnInfoPtr pScrn = xf86Screens[index];
65    SISPtr pSiS = SISPTR(pScrn);
66
67    switch(pSiS->Reflect) {
68    case 1: /* x */
69       (*pSiS->PointerMoved)(index, pScrn->pScreen->width - x - 1, y);
70       break;
71    case 2: /* y */
72       (*pSiS->PointerMoved)(index, x, pScrn->pScreen->height - y - 1);
73       break;
74    case 3: /* x + y */
75       (*pSiS->PointerMoved)(index, pScrn->pScreen->width - x - 1, pScrn->pScreen->height - y - 1);
76    }
77}
78
79/* Refresh area (unreflected, unrotated) */
80
81void
82SISRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
83{
84    SISPtr pSiS = SISPTR(pScrn);
85    int    width, height, Bpp, FBPitch;
86    CARD8  *src, *dst;
87
88    Bpp = pScrn->bitsPerPixel >> 3;
89    FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
90
91    while(num--) {
92
93       width = (pbox->x2 - pbox->x1) * Bpp;
94       height = pbox->y2 - pbox->y1;
95       src = pSiS->ShadowPtr + (pbox->y1 * pSiS->ShadowPitch) +  (pbox->x1 * Bpp);
96       dst = pSiS->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
97
98       while(height--) {
99          SiSMemCopyToVideoRam(pSiS, dst, src, width);
100	  dst += FBPitch;
101	  src += pSiS->ShadowPitch;
102       }
103
104       pbox++;
105    }
106}
107
108/* RefreshArea for reflection */
109
110void
111SISRefreshAreaReflect(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
112{
113    SISPtr pSiS = SISPTR(pScrn);
114    int    width, height, Bpp, FBPitch, twidth;
115    CARD8  *src, *dst, *tdst, *tsrc;
116    CARD16 *tdst16, *tsrc16;
117    CARD32 *tdst32, *tsrc32;
118
119    Bpp = pScrn->bitsPerPixel >> 3;
120    FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
121
122    while(num--) {
123       width = (pbox->x2 - pbox->x1) * Bpp;
124       height = pbox->y2 - pbox->y1;
125       src = pSiS->ShadowPtr + (pbox->y1 * pSiS->ShadowPitch) +  (pbox->x1 * Bpp);
126       dst = pSiS->FbBase;
127       switch(pSiS->Reflect) {
128       case 1:	/* x */
129	  dst += (pbox->y1 * FBPitch) + ((pScrn->displayWidth - pbox->x1 - 1) * Bpp);
130	  switch(Bpp) {
131	     case 1:
132		while(height--) {
133		   tdst = dst;
134		   tsrc = src;
135		   twidth = width;
136		   while(twidth--) *tdst-- = *tsrc++;
137		   dst += FBPitch;
138		   src += pSiS->ShadowPitch;
139		}
140		break;
141	     case 2:
142		width >>= 1;
143		while(height--) {
144		   tdst16 = (CARD16 *)dst;
145		   tsrc16 = (CARD16 *)src;
146		   twidth = width;
147		   while(twidth--) *tdst16-- = *tsrc16++;
148		   dst += FBPitch;
149		   src += pSiS->ShadowPitch;
150		}
151		break;
152	     case 4:
153		width >>= 2;
154		while(height--) {
155		   tdst32 = (CARD32 *)dst;
156		   tsrc32 = (CARD32 *)src;
157		   twidth = width;
158		   while(twidth--) *tdst32-- = *tsrc32++;
159		   dst += FBPitch;
160		   src += pSiS->ShadowPitch;
161		}
162	  }
163	  break;
164       case 2:	/* y */
165	  dst += ((pScrn->virtualY - pbox->y1 - 1) * FBPitch) + (pbox->x1 * Bpp);
166	  while(height--) {
167	     SiSMemCopyToVideoRam(pSiS, dst, src, width);
168	     dst -= FBPitch;
169	     src += pSiS->ShadowPitch;
170	  }
171	  break;
172       case 3:	/* x + y */
173	  dst += ((pScrn->virtualY - pbox->y1 - 1) * FBPitch) + ((pScrn->displayWidth - pbox->x1 - 1) * Bpp);
174	  switch(Bpp) {
175	     case 1:
176		while(height--) {
177		   tdst = dst;
178		   tsrc = src;
179		   twidth = width;
180		   while(twidth--) *tdst-- = *tsrc++;
181		   dst -= FBPitch;
182		   src += pSiS->ShadowPitch;
183		}
184		break;
185	     case 2:
186	        width >>= 1;
187		while(height--) {
188		   tdst16 = (CARD16 *)dst;
189		   tsrc16 = (CARD16 *)src;
190		   twidth = width;
191		   while(twidth--) *tdst16-- = *tsrc16++;
192		   dst -= FBPitch;
193		   src += pSiS->ShadowPitch;
194		}
195		break;
196	     case 4:
197		width >>= 2;
198		while(height--) {
199		   tdst32 = (CARD32 *)dst;
200		   tsrc32 = (CARD32 *)src;
201		   twidth = width;
202		   while(twidth--) *tdst32-- = *tsrc32++;
203		   dst -= FBPitch;
204		   src += pSiS->ShadowPitch;
205		}
206		break;
207	  }
208       }
209       pbox++;
210    }
211}
212
213/* RefreshArea()s for rotation */
214
215void
216SISRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
217{
218    SISPtr pSiS = SISPTR(pScrn);
219    int    count, width, height, y1, y2, dstPitch, srcPitch;
220    CARD8  *dstPtr, *srcPtr, *src;
221    CARD32 *dst;
222
223    dstPitch = pScrn->displayWidth;
224    srcPitch = -pSiS->Rotate * pSiS->ShadowPitch;
225
226    while(num--) {
227       width = pbox->x2 - pbox->x1;
228       y1 = pbox->y1 & ~3;
229       y2 = (pbox->y2 + 3) & ~3;
230       height = (y2 - y1) >> 2;  /* in dwords */
231
232       if(pSiS->Rotate == 1) {
233	  dstPtr = pSiS->FbBase + (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
234	  srcPtr = pSiS->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
235       } else {
236	  dstPtr = pSiS->FbBase +  ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
237	  srcPtr = pSiS->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
238       }
239
240       while(width--) {
241	  src = srcPtr;
242	  dst = (CARD32 *)dstPtr;
243	  count = height;
244	  while(count--) {
245	     *(dst++) = src[0]                    |
246		        (src[srcPitch]     <<  8) |
247		        (src[srcPitch * 2] << 16) |
248			(src[srcPitch * 3] << 24);
249	     src += (srcPitch * 4);
250	  }
251	  srcPtr += pSiS->Rotate;
252	  dstPtr += dstPitch;
253       }
254
255       pbox++;
256    }
257}
258
259void
260SISRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
261{
262    SISPtr pSiS = SISPTR(pScrn);
263    int count, width, height, y1, y2, dstPitch, srcPitch;
264    CARD16 *dstPtr, *srcPtr, *src;
265    CARD32 *dst;
266
267    dstPitch = pScrn->displayWidth;
268    srcPitch = -pSiS->Rotate * pSiS->ShadowPitch >> 1;
269
270    while(num--) {
271       width = pbox->x2 - pbox->x1;
272       y1 = pbox->y1 & ~1;
273       y2 = (pbox->y2 + 1) & ~1;
274       height = (y2 - y1) >> 1;  /* in dwords */
275
276       if(pSiS->Rotate == 1) {
277	  dstPtr = (CARD16 *)pSiS->FbBase + (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
278	  srcPtr = (CARD16 *)pSiS->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
279       } else {
280	  dstPtr = (CARD16 *)pSiS->FbBase + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
281	  srcPtr = (CARD16 *)pSiS->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
282       }
283
284       while(width--) {
285	  src = srcPtr;
286	  dst = (CARD32 *)dstPtr;
287	  count = height;
288	  while(count--) {
289	     *(dst++) = src[0] | (src[srcPitch] << 16);
290	     src += (srcPitch * 2);
291	  }
292	  srcPtr += pSiS->Rotate;
293	  dstPtr += dstPitch;
294       }
295
296       pbox++;
297    }
298}
299
300/* this one could be faster */
301void
302SISRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
303{
304    SISPtr pSiS = SISPTR(pScrn);
305    int    count, width, height, y1, y2, dstPitch, srcPitch;
306    CARD8  *dstPtr, *srcPtr, *src;
307    CARD32 *dst;
308
309    dstPitch = BitmapBytePad(pScrn->displayWidth * 24);
310    srcPitch = -pSiS->Rotate * pSiS->ShadowPitch;
311
312    while(num--) {
313       width = pbox->x2 - pbox->x1;
314       y1 = pbox->y1 & ~3;
315       y2 = (pbox->y2 + 3) & ~3;
316       height = (y2 - y1) >> 2;  /* blocks of 3 dwords */
317
318       if(pSiS->Rotate == 1) {
319	  dstPtr = pSiS->FbBase + (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
320	  srcPtr = pSiS->ShadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3);
321       } else {
322	  dstPtr = pSiS->FbBase + ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3);
323	  srcPtr = pSiS->ShadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3;
324       }
325
326       while(width--) {
327	  src = srcPtr;
328	  dst = (CARD32 *)dstPtr;
329	  count = height;
330	  while(count--) {
331	     dst[0] = src[0]         |
332		      (src[1] << 8)  |
333		      (src[2] << 16) |
334		      (src[srcPitch] << 24);
335	     dst[1] = src[srcPitch + 1]         |
336		      (src[srcPitch + 2] << 8)  |
337		      (src[srcPitch * 2] << 16) |
338		      (src[(srcPitch * 2) + 1] << 24);
339	     dst[2] = src[(srcPitch * 2) + 2]         |
340		      (src[srcPitch * 3] << 8)        |
341		      (src[(srcPitch * 3) + 1] << 16) |
342		      (src[(srcPitch * 3) + 2] << 24);
343	     dst += 3;
344	     src += (srcPitch << 2);
345	  }
346	  srcPtr += pSiS->Rotate * 3;
347	  dstPtr += dstPitch;
348       }
349
350       pbox++;
351    }
352}
353
354void
355SISRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
356{
357    SISPtr pSiS = SISPTR(pScrn);
358    int    count, width, height, dstPitch, srcPitch;
359    CARD32 *dstPtr, *srcPtr, *src, *dst;
360
361    dstPitch = pScrn->displayWidth;
362    srcPitch = -pSiS->Rotate * pSiS->ShadowPitch >> 2;
363
364    while(num--) {
365       width = pbox->x2 - pbox->x1;
366       height = pbox->y2 - pbox->y1;
367
368       if(pSiS->Rotate == 1) {
369	  dstPtr = (CARD32 *)pSiS->FbBase + (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2;
370	  srcPtr = (CARD32 *)pSiS->ShadowPtr + ((1 - pbox->y2) * srcPitch) + pbox->x1;
371       } else {
372	  dstPtr = (CARD32 *)pSiS->FbBase + ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1;
373	  srcPtr = (CARD32 *)pSiS->ShadowPtr + (pbox->y1 * srcPitch) + pbox->x2 - 1;
374       }
375
376       while(width--) {
377	  src = srcPtr;
378	  dst = dstPtr;
379	  count = height;
380	  while(count--) {
381	     *(dst++) = *src;
382	     src += srcPitch;
383	  }
384	  srcPtr += pSiS->Rotate;
385	  dstPtr += dstPitch;
386       }
387
388       pbox++;
389    }
390}
391