savage_dri.c revision ab47cfaa
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#ifdef XF86DRI
30
31#include "xf86.h"
32#include "xf86_OSproc.h"
33#include "xf86Priv.h"
34
35#include "xaalocal.h"
36#include "xaarop.h"
37
38#include "xf86PciInfo.h"
39#include "xf86Pci.h"
40#include "xf86fbman.h"
41
42#include "miline.h"
43
44
45/*#include "savage_vbe.h"*/
46#include "savage_regs.h"
47#include "savage_driver.h"
48#include "savage_bci.h"
49#include "savage_streams.h"
50#include "savage_common.h"
51
52#define _XF86DRI_SERVER_
53#include "GL/glxtokens.h"
54#include "sarea.h"
55#include "savage_dri.h"
56#include "savage_sarea.h"
57
58static char SAVAGEKernelDriverName[] = "savage";
59static char SAVAGEClientDriverName[] = "savage";
60
61static Bool SAVAGEDRIOpenFullScreen(ScreenPtr pScreen);
62static Bool SAVAGEDRICloseFullScreen(ScreenPtr pScreen);
63/* DRI buffer management
64 */
65void SAVAGEDRIInitBuffers( WindowPtr pWin, RegionPtr prgn,
66				CARD32 index );
67void SAVAGEDRIMoveBuffers( WindowPtr pParent, DDXPointRec ptOldOrg,
68				RegionPtr prgnSrc, CARD32 index );
69
70/*        almost the same besides set src/desc to */
71/*        Primary Bitmap Description              */
72
73static void
74SAVAGEDRISetupForScreenToScreenCopy(
75    ScrnInfoPtr pScrn, int xdir, int ydir,
76    int rop, unsigned planemask, int transparency_color);
77
78
79static void
80SAVAGEDRISubsequentScreenToScreenCopy(
81    ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
82    int w, int h);
83
84
85/* Initialize the visual configs that are supported by the hardware.
86 * These are combined with the visual configs that the indirect
87 * rendering core supports, and the intersection is exported to the
88 * client.
89 */
90static Bool SAVAGEInitVisualConfigs( ScreenPtr pScreen )
91{
92   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
93   SavagePtr psav = SAVPTR(pScrn);
94   int numConfigs = 0;
95   __GLXvisualConfig *pConfigs = 0;
96   SAVAGEConfigPrivPtr pSAVAGEConfigs = 0;
97   SAVAGEConfigPrivPtr *pSAVAGEConfigPtrs = 0;
98   int i, db, depth, stencil, accum;
99
100   switch ( pScrn->bitsPerPixel ) {
101   case 8:
102   case 24:
103      break;
104
105   case 16:
106      numConfigs = 8;
107
108      pConfigs = (__GLXvisualConfig*)xcalloc( sizeof(__GLXvisualConfig),
109						numConfigs );
110      if ( !pConfigs ) {
111	 return FALSE;
112      }
113
114      pSAVAGEConfigs = (SAVAGEConfigPrivPtr)xcalloc( sizeof(SAVAGEConfigPrivRec),
115						 numConfigs );
116      if ( !pSAVAGEConfigs ) {
117	 xfree( pConfigs );
118	 return FALSE;
119      }
120
121      pSAVAGEConfigPtrs = (SAVAGEConfigPrivPtr*)xcalloc( sizeof(SAVAGEConfigPrivPtr),
122						     numConfigs );
123      if ( !pSAVAGEConfigPtrs ) {
124	 xfree( pConfigs );
125	 xfree( pSAVAGEConfigs );
126	 return FALSE;
127      }
128
129      for ( i = 0 ; i < numConfigs ; i++ ) {
130	 pSAVAGEConfigPtrs[i] = &pSAVAGEConfigs[i];
131      }
132
133      i = 0;
134      depth = 1;
135      for ( accum = 0 ; accum <= 1 ; accum++ ) {
136         for ( stencil = 0 ; stencil <= 1 ; stencil++ ) {
137            for ( db = 1 ; db >= 0 ; db-- ) {
138               pConfigs[i].vid			= -1;
139               pConfigs[i].class		= -1;
140               pConfigs[i].rgba			= TRUE;
141               pConfigs[i].redSize		= 5;
142               pConfigs[i].greenSize		= 6;
143               pConfigs[i].blueSize		= 5;
144               pConfigs[i].alphaSize		= 0;
145               pConfigs[i].redMask		= 0x0000F800;
146               pConfigs[i].greenMask		= 0x000007E0;
147               pConfigs[i].blueMask		= 0x0000001F;
148               pConfigs[i].alphaMask		= 0;
149               if ( accum ) {
150                  pConfigs[i].accumRedSize	= 16;
151                  pConfigs[i].accumGreenSize	= 16;
152                  pConfigs[i].accumBlueSize	= 16;
153                  pConfigs[i].accumAlphaSize	= 0;
154               } else {
155                  pConfigs[i].accumRedSize	= 0;
156                  pConfigs[i].accumGreenSize	= 0;
157                  pConfigs[i].accumBlueSize	= 0;
158                  pConfigs[i].accumAlphaSize	= 0;
159               }
160               if ( db ) {
161                  pConfigs[i].doubleBuffer	= TRUE;
162               } else {
163                  pConfigs[i].doubleBuffer	= FALSE;
164	       }
165               pConfigs[i].stereo		= FALSE;
166               pConfigs[i].bufferSize		= 16;
167               if ( depth ) {
168                  pConfigs[i].depthSize		= 16;
169               } else {
170                  pConfigs[i].depthSize		= 0;
171	       }
172               if ( stencil ) {
173                  pConfigs[i].stencilSize	= 8;
174               } else {
175                  pConfigs[i].stencilSize	= 0;
176	       }
177               pConfigs[i].auxBuffers		= 0;
178               pConfigs[i].level		= 0;
179               if ( accum || stencil ) {
180		  pConfigs[i].visualRating	= GLX_SLOW_CONFIG;
181               } else {
182                  pConfigs[i].visualRating	= GLX_NONE;
183	       }
184               pConfigs[i].transparentPixel	= GLX_NONE;
185               pConfigs[i].transparentRed	= 0;
186               pConfigs[i].transparentGreen	= 0;
187               pConfigs[i].transparentBlue	= 0;
188               pConfigs[i].transparentAlpha	= 0;
189               pConfigs[i].transparentIndex	= 0;
190               i++;
191            }
192         }
193      }
194      if ( i != numConfigs ) {
195         xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
196		     "[drm] Incorrect initialization of visuals\n" );
197         return FALSE;
198      }
199      break;
200
201   case 32:
202      numConfigs = 8;
203
204      pConfigs = (__GLXvisualConfig*)xcalloc( sizeof(__GLXvisualConfig),
205						numConfigs );
206      if ( !pConfigs ) {
207	 return FALSE;
208      }
209
210      pSAVAGEConfigs = (SAVAGEConfigPrivPtr)xcalloc( sizeof(SAVAGEConfigPrivRec),
211						 numConfigs );
212      if ( !pSAVAGEConfigs ) {
213	 xfree( pConfigs );
214	 return FALSE;
215      }
216
217      pSAVAGEConfigPtrs = (SAVAGEConfigPrivPtr*)xcalloc( sizeof(SAVAGEConfigPrivPtr),
218						     numConfigs );
219      if ( !pSAVAGEConfigPtrs ) {
220	 xfree( pConfigs );
221	 xfree( pSAVAGEConfigs );
222	 return FALSE;
223      }
224
225      for ( i = 0 ; i < numConfigs ; i++ ) {
226	 pSAVAGEConfigPtrs[i] = &pSAVAGEConfigs[i];
227      }
228
229      i = 0;
230      for ( accum = 0 ; accum <= 1 ; accum++ ) {
231         for ( stencil = 0 ; stencil <= 1 ; stencil++ ) {
232            for ( db = 1 ; db >= 0 ; db-- ) {
233               pConfigs[i].vid			= -1;
234               pConfigs[i].class		= -1;
235               pConfigs[i].rgba			= TRUE;
236               pConfigs[i].redSize		= 8;
237               pConfigs[i].greenSize		= 8;
238               pConfigs[i].blueSize		= 8;
239               pConfigs[i].alphaSize		= 0;
240               pConfigs[i].redMask		= 0x00FF0000;
241               pConfigs[i].greenMask		= 0x0000FF00;
242               pConfigs[i].blueMask		= 0x000000FF;
243               pConfigs[i].alphaMask		= 0;
244               if ( accum ) {
245                  pConfigs[i].accumRedSize	= 16;
246                  pConfigs[i].accumGreenSize	= 16;
247                  pConfigs[i].accumBlueSize	= 16;
248                  pConfigs[i].accumAlphaSize	= 0;
249               } else {
250                  pConfigs[i].accumRedSize	= 0;
251                  pConfigs[i].accumGreenSize	= 0;
252                  pConfigs[i].accumBlueSize	= 0;
253                  pConfigs[i].accumAlphaSize	= 0;
254               }
255               if ( db ) {
256                  pConfigs[i].doubleBuffer	= TRUE;
257               } else {
258                  pConfigs[i].doubleBuffer	= FALSE;
259	       }
260               pConfigs[i].stereo		= FALSE;
261               pConfigs[i].bufferSize		= 32;
262               if ( stencil ) {
263		     pConfigs[i].depthSize	= 24;
264                     pConfigs[i].stencilSize	= 8;
265               }
266               else {
267                     pConfigs[i].depthSize	= 24;
268                     pConfigs[i].stencilSize	= 0;
269               }
270               pConfigs[i].auxBuffers		= 0;
271               pConfigs[i].level		= 0;
272               if ( accum ) {
273                  pConfigs[i].visualRating	= GLX_SLOW_VISUAL_EXT;
274               } else {
275                  pConfigs[i].visualRating	= GLX_NONE;
276	       }
277               pConfigs[i].transparentPixel	= GLX_NONE;
278               pConfigs[i].transparentRed	= 0;
279               pConfigs[i].transparentGreen	= 0;
280               pConfigs[i].transparentBlue	= 0;
281               pConfigs[i].transparentAlpha	= 0;
282               pConfigs[i].transparentIndex	= 0;
283               i++;
284            }
285         }
286      }
287      if ( i != numConfigs ) {
288         xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
289		     "[drm] Incorrect initialization of visuals\n" );
290         return FALSE;
291      }
292      break;
293
294   default:
295      /* Unexpected bits/pixels */
296      break;
297   }
298
299   psav->numVisualConfigs = numConfigs;
300   psav->pVisualConfigs = pConfigs;
301   psav->pVisualConfigsPriv = pSAVAGEConfigs;
302
303   GlxSetVisualConfigs( numConfigs, pConfigs, (void **)pSAVAGEConfigPtrs );
304
305   return TRUE;
306}
307
308static Bool SAVAGECreateContext( ScreenPtr pScreen, VisualPtr visual,
309			      drm_context_t hwContext, void *pVisualConfigPriv,
310			      DRIContextType contextStore )
311{
312    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
313    SavagePtr psav = SAVPTR(pScrn);
314
315    if(psav->xvmcContext)
316        return FALSE;
317    else
318    {
319        psav->DRIrunning++;
320    }
321
322    return TRUE;
323}
324
325static void SAVAGEDestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
326			       DRIContextType contextStore )
327{
328    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
329    SavagePtr psav = SAVPTR(pScrn);
330
331    psav->DRIrunning--;
332}
333
334static void SAVAGEWakeupHandler( int screenNum, pointer wakeupData,
335				 unsigned long result, pointer pReadmask )
336{
337   ScreenPtr pScreen = screenInfo.screens[screenNum];
338   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
339   SavagePtr psav = SAVPTR(pScrn);
340
341   psav->pDRIInfo->wrap.WakeupHandler = psav->coreWakeupHandler;
342   (*psav->pDRIInfo->wrap.WakeupHandler) (screenNum, wakeupData, result, pReadmask);
343   psav->pDRIInfo->wrap.WakeupHandler = SAVAGEWakeupHandler;
344   psav->LockHeld = 1;
345   if (psav->ShadowStatus) {
346      /* fetch the global shadow counter */
347#if 0
348      if (psav->ShadowCounter != (psav->ShadowVirtual[1023] & 0xffff))
349	 xf86DrvMsg( pScrn->scrnIndex, X_INFO,
350		     "[dri] WakeupHandler: shadowCounter adjusted from %04x to %04lx\n",
351		     psav->ShadowCounter, psav->ShadowVirtual[1023] & 0xffff);
352#endif
353      psav->ShadowCounter = psav->ShadowVirtual[1023] & 0xffff;
354   }
355   if (psav->useEXA)
356	exaMarkSync(pScreen);
357   else
358	psav->AccelInfoRec->NeedToSync = TRUE;
359   /* FK: this flag doesn't seem to be used. */
360}
361
362static void SAVAGEBlockHandler( int screenNum, pointer blockData,
363				pointer pTimeout, pointer pReadmask)
364{
365   ScreenPtr pScreen = screenInfo.screens[screenNum];
366   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
367   SavagePtr psav = SAVPTR(pScrn);
368
369   if (psav->ShadowStatus) {
370      /* update the global shadow counter */
371      CARD32 globalShadowCounter = psav->ShadowVirtual[1023];
372      globalShadowCounter = (globalShadowCounter & 0xffff0000) |
373	  ((CARD32)psav->ShadowCounter & 0x0000ffff);
374
375#if 0
376      if (globalShadowCounter != psav->ShadowVirtual[1023])
377	 xf86DrvMsg( pScrn->scrnIndex, X_INFO,
378		     "[dri] BlockHandler: shadowCounter adjusted from %08lx to %08x\n",
379		     psav->ShadowVirtual[1023], globalShadowCounter);
380#endif
381      psav->ShadowVirtual[1023] = globalShadowCounter;
382   }
383   psav->LockHeld = 0;
384   psav->pDRIInfo->wrap.BlockHandler = psav->coreBlockHandler;
385   (*psav->pDRIInfo->wrap.BlockHandler) (screenNum, blockData, pTimeout, pReadmask);
386   psav->pDRIInfo->wrap.BlockHandler = SAVAGEBlockHandler;
387}
388
389void SAVAGESelectBuffer( ScrnInfoPtr pScrn, int which )
390{
391   SavagePtr psav = SAVPTR(pScrn);
392   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
393
394   psav->WaitIdleEmpty(psav);
395
396   OUTREG(0x48C18,INREG(0x48C18)&(~0x00000008));
397
398   switch ( which ) {
399   case SAVAGE_BACK:
400      OUTREG( 0x8170, pSAVAGEDRIServer->backOffset );
401      OUTREG( 0x8174, pSAVAGEDRIServer->backBitmapDesc );
402      break;
403   case SAVAGE_DEPTH:
404      OUTREG( 0x8170, pSAVAGEDRIServer->depthOffset );
405      OUTREG( 0x8174, pSAVAGEDRIServer->depthBitmapDesc );
406      break;
407   default:
408   case SAVAGE_FRONT:
409      OUTREG( 0x8170, pSAVAGEDRIServer->frontOffset );
410      OUTREG( 0x8174, pSAVAGEDRIServer->frontBitmapDesc );
411      break;
412   }
413   OUTREG(0x48C18,INREG(0x48C18)|(0x00000008));
414   psav->WaitIdleEmpty(psav);
415
416}
417
418
419static unsigned int mylog2( unsigned int n )
420{
421   unsigned int log2 = 1;
422
423   n--;
424   while ( n > 1 ) n >>= 1, log2++;
425
426   return log2;
427}
428
429static Bool SAVAGEDRIAgpInit(ScreenPtr pScreen)
430{
431   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
432   SavagePtr psav = SAVPTR(pScrn);
433   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
434   unsigned long mode;
435   unsigned int vendor, device;
436   unsigned int offset;
437   int ret;
438
439   if (psav->agpSize < 2) psav->agpSize = 2; /* at least 2MB for DMA buffers */
440
441   pSAVAGEDRIServer->agp.size = psav->agpSize * 1024 * 1024;
442   pSAVAGEDRIServer->agp.offset = pSAVAGEDRIServer->agp.size; /* ? */
443
444   if ( drmAgpAcquire( psav->drmFD ) < 0 ) {
445      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not available\n" );
446      return FALSE;
447   }
448
449   mode   = drmAgpGetMode( psav->drmFD );        /* Default mode */
450   vendor = drmAgpVendorId( psav->drmFD );
451   device = drmAgpDeviceId( psav->drmFD );
452
453   mode &= ~SAVAGE_AGP_MODE_MASK;
454
455   switch ( psav->agpMode ) {
456   case 4:
457      mode |= SAVAGE_AGP_4X_MODE;
458   case 2:
459      mode |= SAVAGE_AGP_2X_MODE;
460   case 1:
461   default:
462      mode |= SAVAGE_AGP_1X_MODE;
463   }
464
465   /*   mode |= SAVAGE_AGP_1X_MODE;*/
466
467   xf86DrvMsg( pScreen->myNum, X_INFO,
468	       "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
469	       mode, vendor, device,
470	       psav->PciInfo->vendor,
471	       psav->PciInfo->chipType );
472
473   if ( drmAgpEnable( psav->drmFD, mode ) < 0 ) {
474      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
475      drmAgpRelease( psav->drmFD );
476      pSAVAGEDRIServer->agp.handle = 0; /* indicate that AGP init failed */
477      return FALSE;
478   }
479
480   ret = drmAgpAlloc( psav->drmFD, pSAVAGEDRIServer->agp.size,
481		      0, NULL, &pSAVAGEDRIServer->agp.handle );
482   if ( ret < 0 ) {
483      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
484      drmAgpRelease( psav->drmFD );
485      pSAVAGEDRIServer->agp.handle = 0; /* indicate that AGP init failed */
486      return FALSE;
487   }
488   xf86DrvMsg( pScreen->myNum, X_INFO,
489	       "[agp] %d kB allocated with handle 0x%08lx\n",
490	       pSAVAGEDRIServer->agp.size/1024, pSAVAGEDRIServer->agp.handle );
491
492   if ( drmAgpBind( psav->drmFD, pSAVAGEDRIServer->agp.handle, 0 ) < 0 ) {
493      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind memory\n" );
494      drmAgpFree( psav->drmFD, pSAVAGEDRIServer->agp.handle );
495      drmAgpRelease( psav->drmFD );
496      pSAVAGEDRIServer->agp.handle = 0; /* indicate that AGP init failed */
497      return FALSE;
498   }
499
500   /* AGP initialization failures above are not fatal, we can fall
501    * back to PCI mode. Failures while adding AGP mappings below are
502    * fatal though. DRI must be disabled in that case.
503    * pSAVAGEDRIServer->agp.handle can be used to distinguish these
504    * two cases.
505    */
506
507   /* AGP memory layout
508    */
509   offset = 0;
510
511   if ( psav->AgpDMA ) {
512       if ( psav->CommandDMA ) {
513	   pSAVAGEDRIServer->cmdDma.offset = offset;
514	   pSAVAGEDRIServer->cmdDma.size = SAVAGE_CMDDMA_SIZE;
515	   offset += pSAVAGEDRIServer->cmdDma.size;
516       } else if ( psav->VertexDMA ) {
517	   pSAVAGEDRIServer->buffers.offset = 0;
518	   pSAVAGEDRIServer->buffers.size = SAVAGE_NUM_BUFFERS * SAVAGE_BUFFER_SIZE;
519	   offset += pSAVAGEDRIServer->buffers.size;
520       }
521   }
522
523   pSAVAGEDRIServer->agpTextures.offset = offset;
524   pSAVAGEDRIServer->agpTextures.size = (pSAVAGEDRIServer->agp.size - offset);
525
526   /* DMA buffers
527    */
528   if ( psav->AgpDMA ) {
529       if ( psav->CommandDMA ) {
530	   if ( drmAddMap( psav->drmFD,
531			   pSAVAGEDRIServer->cmdDma.offset,
532			   pSAVAGEDRIServer->cmdDma.size,
533			   DRM_AGP, DRM_RESTRICTED | DRM_KERNEL,
534			   &pSAVAGEDRIServer->cmdDma.handle ) < 0 ) {
535	       xf86DrvMsg( pScreen->myNum, X_ERROR,
536			   "[agp] Could not add command DMA mapping\n" );
537	       return FALSE;
538	   }
539	   xf86DrvMsg( pScreen->myNum, X_INFO,
540		       "[agp] command DMA handle = 0x%08lx\n",
541		       pSAVAGEDRIServer->cmdDma.handle );
542	   /* not needed in the server
543	   if ( drmMap( psav->drmFD,
544			pSAVAGEDRIServer->cmdDma.handle,
545			pSAVAGEDRIServer->cmdDma.size,
546			&pSAVAGEDRIServer->cmdDma.map ) < 0 ) {
547	       xf86DrvMsg( pScreen->myNum, X_ERROR,
548			   "[agp] Could not map command DMA\n" );
549	       return FALSE;
550	   }
551	   xf86DrvMsg( pScreen->myNum, X_INFO,
552		       "[agp] command DMA mapped at 0x%08lx\n",
553		       (unsigned long)pSAVAGEDRIServer->cmdDma.map );
554	   */
555       } else if ( psav->VertexDMA ) {
556	   if ( drmAddMap( psav->drmFD,
557			   pSAVAGEDRIServer->buffers.offset,
558			   pSAVAGEDRIServer->buffers.size,
559			   DRM_AGP, 0,
560			   &pSAVAGEDRIServer->buffers.handle ) < 0 ) {
561	       xf86DrvMsg( pScreen->myNum, X_ERROR,
562			   "[agp] Could not add DMA buffers mapping\n" );
563	       return FALSE;
564	   }
565	   xf86DrvMsg( pScreen->myNum, X_INFO,
566		       "[agp] DMA buffers handle = 0x%08lx\n",
567		       pSAVAGEDRIServer->buffers.handle );
568	   /* not needed in the server
569	   if ( drmMap( psav->drmFD,
570			pSAVAGEDRIServer->buffers.handle,
571			pSAVAGEDRIServer->buffers.size,
572			&pSAVAGEDRIServer->buffers.map ) < 0 ) {
573	       xf86DrvMsg( pScreen->myNum, X_ERROR,
574			   "[agp] Could not map DMA buffers\n" );
575	       return FALSE;
576	   }
577	   xf86DrvMsg( pScreen->myNum, X_INFO,
578		       "[agp] DMA buffers mapped at 0x%08lx\n",
579		       (unsigned long)pSAVAGEDRIServer->buffers.map );
580	   */
581       }
582   }
583
584   /* AGP textures
585    */
586   if ( drmAddMap( psav->drmFD,
587		   pSAVAGEDRIServer->agpTextures.offset,
588		   pSAVAGEDRIServer->agpTextures.size,
589		   DRM_AGP, 0,
590		   &pSAVAGEDRIServer->agpTextures.handle ) < 0 ) {
591      xf86DrvMsg( pScreen->myNum, X_ERROR,
592		  "[agp] Could not add agpTextures \n" );
593      return FALSE;
594   }
595   /*   pSAVAGEDRIServer->agp_offset=pSAVAGEDRIServer->agpTexture.size;*/
596   xf86DrvMsg( pScreen->myNum, X_INFO,
597	       "[agp] agpTextures handle = 0x%08lx\n",
598	       pSAVAGEDRIServer->agpTextures.handle );
599
600   /* not needed in the server
601   if ( drmMap( psav->drmFD,
602		pSAVAGEDRIServer->agpTextures.handle,
603		pSAVAGEDRIServer->agpTextures.size,
604		&pSAVAGEDRIServer->agpTextures.map ) < 0 ) {
605      xf86DrvMsg( pScreen->myNum, X_ERROR,
606		  "[agp] Could not map agpTextures \n" );
607      return FALSE;
608   }
609
610   xf86DrvMsg( pScreen->myNum, X_INFO,
611	       "[agp] agpTextures mapped at 0x%08lx\n",
612	       (unsigned long)pSAVAGEDRIServer->agpTextures.map );
613   */
614
615   return TRUE;
616}
617
618static Bool SAVAGEDRIMapInit( ScreenPtr pScreen )
619{
620   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
621   SavagePtr psav = SAVPTR(pScrn);
622   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
623
624   pSAVAGEDRIServer->registers.size = SAVAGEIOMAPSIZE;
625
626   if ( drmAddMap( psav->drmFD,
627		   (drm_handle_t)psav->MmioBase,
628		   pSAVAGEDRIServer->registers.size,
629		   DRM_REGISTERS,0,
630		   &pSAVAGEDRIServer->registers.handle ) < 0 ) {
631      xf86DrvMsg( pScreen->myNum, X_ERROR,
632		  "[drm] Could not add MMIO registers mapping\n" );
633      return FALSE;
634   }
635
636   pSAVAGEDRIServer->aperture.size = 5 * 0x01000000;
637
638   if ( drmAddMap( psav->drmFD,
639		   (drm_handle_t)(psav->ApertureBase),
640		   pSAVAGEDRIServer->aperture.size,
641		   DRM_FRAME_BUFFER,0,
642		   &pSAVAGEDRIServer->aperture.handle ) < 0 ) {
643      xf86DrvMsg( pScreen->myNum, X_ERROR,
644		  "[drm] Could not add aperture mapping\n" );
645      return FALSE;
646   }
647
648   xf86DrvMsg( pScreen->myNum, X_INFO,
649	       "[drm] aperture handle = 0x%08lx\n",
650	       pSAVAGEDRIServer->aperture.handle );
651
652   /*if(drmMap(psav->drmFD,
653          pSAVAGEDRIServer->registers.handle,
654          pSAVAGEDRIServer->registers.size,
655          &pSAVAGEDRIServer->registers.map)<0)
656   {
657         xf86DrvMsg( pScreen->myNum, X_ERROR,
658		  "[drm] Could not map MMIO registers region to virtual\n" );
659      return FALSE;
660
661   }*/
662
663   if ( !psav->AgpDMA && psav->CommandDMA ) {
664       pSAVAGEDRIServer->cmdDma.size = SAVAGE_CMDDMA_SIZE;
665       if ( drmAddMap( psav->drmFD, 0, pSAVAGEDRIServer->cmdDma.size,
666		       DRM_CONSISTENT, DRM_RESTRICTED | DRM_LOCKED |
667		       DRM_KERNEL | DRM_WRITE_COMBINING,
668		       &pSAVAGEDRIServer->cmdDma.handle ) < 0 ) {
669	   psav->CommandDMA = FALSE;
670	   xf86DrvMsg( pScreen->myNum, X_WARNING,
671		       "[drm] Could not add PCI command DMA mapping\n" );
672       } else
673	   xf86DrvMsg( pScreen->myNum, X_INFO,
674		       "[drm] PCI command DMA handle = 0x%08lx\n",
675		       pSAVAGEDRIServer->cmdDma.handle );
676   }
677
678   /* Enable ShadowStatus by default for direct rendering. */
679   if ( !psav->ShadowStatus && !psav->ForceShadowStatus ) {
680       psav->ShadowStatus = TRUE;
681       xf86DrvMsg( pScreen->myNum, X_INFO,
682		   "[drm] Enabling ShadowStatus for DRI.\n" );
683   }
684
685   /* If shadow status is manually or automatically enabled, use a
686    * page in system memory. */
687   if ( psav->ShadowStatus ) {
688       pSAVAGEDRIServer->status.size = 4096; /* 1 page */
689
690       if ( drmAddMap( psav->drmFD, 0, pSAVAGEDRIServer->status.size,
691		       DRM_CONSISTENT, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL,
692		       &pSAVAGEDRIServer->status.handle ) < 0 ) {
693	   xf86DrvMsg( pScreen->myNum, X_ERROR,
694		       "[drm] Could not add status page mapping\n" );
695	   return FALSE;
696       }
697       xf86DrvMsg( pScreen->myNum, X_INFO,
698		   "[drm] Status handle = 0x%08lx\n",
699		   pSAVAGEDRIServer->status.handle );
700
701       if ( drmMap( psav->drmFD,
702		    pSAVAGEDRIServer->status.handle,
703		    pSAVAGEDRIServer->status.size,
704		    &pSAVAGEDRIServer->status.map ) < 0 ) {
705	   xf86DrvMsg( pScreen->myNum, X_ERROR,
706		       "[drm] Could not map status page\n" );
707	   return FALSE;
708       }
709       xf86DrvMsg( pScreen->myNum, X_INFO,
710		   "[drm] Status page mapped at 0x%08lx\n",
711		   (unsigned long)pSAVAGEDRIServer->status.map );
712
713       psav->ShadowPhysical = pSAVAGEDRIServer->status.handle;
714       psav->ShadowVirtual = pSAVAGEDRIServer->status.map;
715   }
716
717   return TRUE;
718}
719
720static Bool SAVAGEDRIBuffersInit( ScreenPtr pScreen )
721{
722   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
723   SavagePtr psav = SAVPTR(pScrn);
724   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
725   int count;
726
727   if ( !psav->VertexDMA || psav->CommandDMA ) {
728       /* At this point psav->CommandDMA == TRUE means that CommandDMA
729	* allocation was actually successful. */
730       psav->VertexDMA = FALSE;
731       return TRUE;
732   }
733
734   if ( psav->AgpDMA ) {
735       count = drmAddBufs( psav->drmFD,
736			   SAVAGE_NUM_BUFFERS, SAVAGE_BUFFER_SIZE,
737			   DRM_AGP_BUFFER, pSAVAGEDRIServer->buffers.offset );
738   } else {
739       count = drmAddBufs( psav->drmFD,
740			   SAVAGE_NUM_BUFFERS, SAVAGE_BUFFER_SIZE,
741			   0, 0 );
742   }
743   if ( count <= 0 ) {
744       xf86DrvMsg( pScrn->scrnIndex, X_INFO,
745		   "[drm] failure adding %d %d byte DMA buffers (%d)\n",
746		   SAVAGE_NUM_BUFFERS, SAVAGE_BUFFER_SIZE, count );
747       return FALSE;
748   }
749   xf86DrvMsg( pScreen->myNum, X_INFO,
750	       "[drm] Added %d %d byte DMA buffers\n",
751	       count, SAVAGE_BUFFER_SIZE );
752
753   /* not needed in the server
754   pSAVAGEDRIServer->drmBuffers = drmMapBufs( psav->drmFD );
755   if ( !pSAVAGEDRIServer->drmBuffers ) {
756	xf86DrvMsg( pScreen->myNum, X_ERROR,
757		    "[drm] Failed to map DMA buffers list\n" );
758	return FALSE;
759    }
760    xf86DrvMsg( pScreen->myNum, X_INFO,
761		"[drm] Mapped %d DMA buffers\n",
762		pSAVAGEDRIServer->drmBuffers->count );
763   */
764
765    return TRUE;
766}
767
768static Bool SAVAGEDRIKernelInit( ScreenPtr pScreen )
769{
770   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
771   SavagePtr psav = SAVPTR(pScrn);
772   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
773   drmSAVAGEInit init;
774   int ret;
775
776   memset( &init, 0, sizeof(drmSAVAGEInit) );
777
778   init.func = SAVAGE_INIT_BCI;
779   init.sarea_priv_offset = sizeof(XF86DRISAREARec);
780
781   init.cob_size = psav->cobSize/4; /* size in 32-bit entries */
782   init.bci_threshold_lo = psav->bciThresholdLo;
783   init.bci_threshold_hi = psav->bciThresholdHi;
784   init.dma_type = psav->AgpDMA ? SAVAGE_DMA_AGP : SAVAGE_DMA_PCI;
785
786   init.fb_bpp		= pScrn->bitsPerPixel;
787   init.front_offset	= pSAVAGEDRIServer->frontOffset;
788   init.front_pitch	= pSAVAGEDRIServer->frontPitch;
789   init.back_offset	= pSAVAGEDRIServer->backOffset;
790   init.back_pitch	= pSAVAGEDRIServer->backPitch;
791
792   init.depth_bpp	= pScrn->bitsPerPixel;
793   init.depth_offset	= pSAVAGEDRIServer->depthOffset;
794   init.depth_pitch	= pSAVAGEDRIServer->depthPitch;
795
796   init.texture_offset  = pSAVAGEDRIServer->textureOffset;
797   init.texture_size    = pSAVAGEDRIServer->textureSize;
798
799   init.status_offset   = pSAVAGEDRIServer->status.handle;
800   init.agp_textures_offset = pSAVAGEDRIServer->agpTextures.handle;
801
802   /* Savage4-based chips with DRM version >= 2.4 support command DMA,
803    * which is preferred because it works with all vertex
804    * formats. Command DMA and vertex DMA don't work at the same
805    * time. */
806   init.buffers_offset = 0;
807   init.cmd_dma_offset = 0;
808   if ( psav->CommandDMA )
809       init.cmd_dma_offset = pSAVAGEDRIServer->cmdDma.handle;
810   else if ( psav->VertexDMA )
811       init.buffers_offset = pSAVAGEDRIServer->buffers.handle;
812
813   ret = drmCommandWrite( psav->drmFD, DRM_SAVAGE_BCI_INIT, &init, sizeof(init) );
814   if ( ret < 0 ) {
815      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
816		  "[drm] Failed to initialize BCI! (%d)\n", ret );
817      return FALSE;
818   }
819
820   return TRUE;
821}
822
823Bool SAVAGEDRIScreenInit( ScreenPtr pScreen )
824{
825   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
826   SavagePtr psav = SAVPTR(pScrn);
827   DRIInfoPtr pDRIInfo;
828   SAVAGEDRIPtr pSAVAGEDRI;
829   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer;
830
831   /* Check that the GLX, DRI, and DRM modules have been loaded by testing
832    * for canonical symbols in each module.
833    */
834   if ( !xf86LoaderCheckSymbol( "GlxSetVisualConfigs" ) )	return FALSE;
835   if ( !xf86LoaderCheckSymbol( "drmAvailable" ) )		return FALSE;
836   if ( !xf86LoaderCheckSymbol( "DRIQueryVersion" ) ) {
837      xf86DrvMsg( pScreen->myNum, X_ERROR,
838		  "[dri] SAVAGEDRIScreenInit failed (libdri.a too old)\n" );
839      return FALSE;
840   }
841
842   /* Check the DRI version */
843   {
844      int major, minor, patch;
845      DRIQueryVersion( &major, &minor, &patch );
846      if ( major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ) {
847         xf86DrvMsg( pScreen->myNum, X_ERROR,
848		     "[dri] SAVAGEDRIScreenInit failed because of a version mismatch.\n"
849		     "[dri] libdri version = %d.%d.%d but version %d.%d.x is needed.\n"
850		     "[dri] Disabling the DRI.\n",
851		     major, minor, patch,
852                     DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION );
853         return FALSE;
854      }
855   }
856
857   xf86DrvMsg( pScreen->myNum, X_INFO,
858	       "[drm] bpp: %d depth: %d\n",
859	       pScrn->bitsPerPixel, pScrn->depth );
860
861   if ( (pScrn->bitsPerPixel / 8) != 2 &&
862	(pScrn->bitsPerPixel / 8) != 4 ) {
863      xf86DrvMsg( pScreen->myNum, X_ERROR,
864		  "[dri] Direct rendering only supported in 16 and 32 bpp modes\n" );
865      return FALSE;
866   }
867
868   pDRIInfo = DRICreateInfoRec();
869   if ( !pDRIInfo ) {
870      xf86DrvMsg( pScreen->myNum, X_ERROR,
871		  "[dri] DRICreateInfoRec() failed\n" );
872      return FALSE;
873   }
874   psav->pDRIInfo = pDRIInfo;
875
876   pDRIInfo->drmDriverName = SAVAGEKernelDriverName;
877   pDRIInfo->clientDriverName = SAVAGEClientDriverName;
878   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
879      pDRIInfo->busIdString = DRICreatePCIBusID(psav->PciInfo);
880   } else {
881      pDRIInfo->busIdString            = xalloc(64);
882      sprintf(pDRIInfo->busIdString,
883              "PCI:%d:%d:%d",
884              psav->PciInfo->bus,
885              psav->PciInfo->device,
886              psav->PciInfo->func);
887   }
888   pDRIInfo->ddxDriverMajorVersion = SAVAGE_VERSION_MAJOR;
889   pDRIInfo->ddxDriverMinorVersion = SAVAGE_VERSION_MINOR;
890   pDRIInfo->ddxDriverPatchVersion = SAVAGE_PATCHLEVEL;
891
892   pDRIInfo->frameBufferPhysicalAddress = (pointer) psav->FrameBufferBase;
893   pDRIInfo->frameBufferSize = psav->videoRambytes;
894   pDRIInfo->frameBufferStride = pScrn->displayWidth*(pScrn->bitsPerPixel/8);
895   pDRIInfo->ddxDrawableTableEntry = SAVAGE_MAX_DRAWABLES;
896
897   /* override default DRI block and wakeup handler */
898   psav->coreBlockHandler = pDRIInfo->wrap.BlockHandler;
899   pDRIInfo->wrap.BlockHandler = SAVAGEBlockHandler;
900   psav->coreWakeupHandler = pDRIInfo->wrap.WakeupHandler;
901   pDRIInfo->wrap.WakeupHandler = SAVAGEWakeupHandler;
902
903   pDRIInfo->wrap.ValidateTree = NULL;
904   pDRIInfo->wrap.PostValidateTree = NULL;
905
906   pDRIInfo->createDummyCtx = TRUE;
907   pDRIInfo->createDummyCtxPriv = FALSE;
908
909   if ( SAREA_MAX_DRAWABLES < SAVAGE_MAX_DRAWABLES ) {
910      pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
911   } else {
912      pDRIInfo->maxDrawableTableEntry = SAVAGE_MAX_DRAWABLES;
913   }
914
915   /* For now the mapping works by using a fixed size defined
916    * in the SAREA header.
917    */
918   if ( sizeof(XF86DRISAREARec) + sizeof(SAVAGESAREAPrivRec) > SAREA_MAX ) {
919      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
920		  "[drm] Data does not fit in SAREA\n" );
921      return FALSE;
922   }
923
924   xf86DrvMsg( pScrn->scrnIndex, X_INFO,
925	       "[drm] Sarea %d+%d: %d\n",
926	       sizeof(XF86DRISAREARec), sizeof(SAVAGESAREAPrivRec),
927	       sizeof(XF86DRISAREARec) + sizeof(SAVAGESAREAPrivRec) );
928
929   pDRIInfo->SAREASize = SAREA_MAX;
930
931   pSAVAGEDRI = (SAVAGEDRIPtr)xcalloc( sizeof(SAVAGEDRIRec), 1 );
932   if ( !pSAVAGEDRI ) {
933      DRIDestroyInfoRec( psav->pDRIInfo );
934      psav->pDRIInfo = 0;
935      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
936		  "[drm] Failed to allocate memory for private record\n" );
937      return FALSE;
938   }
939
940   pSAVAGEDRIServer = (SAVAGEDRIServerPrivatePtr)
941      xcalloc( sizeof(SAVAGEDRIServerPrivateRec), 1 );
942   if ( !pSAVAGEDRIServer ) {
943      xfree( pSAVAGEDRI );
944      DRIDestroyInfoRec( psav->pDRIInfo );
945      psav->pDRIInfo = 0;
946      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
947		  "[drm] Failed to allocate memory for private record\n" );
948      return FALSE;
949   }
950   psav->DRIServerInfo = pSAVAGEDRIServer;
951
952   pDRIInfo->devPrivate = pSAVAGEDRI;
953   pDRIInfo->devPrivateSize = sizeof(SAVAGEDRIRec);
954   pDRIInfo->contextSize = sizeof(SAVAGEDRIContextRec);
955
956   pDRIInfo->CreateContext = SAVAGECreateContext;
957   pDRIInfo->DestroyContext = SAVAGEDestroyContext;
958
959   /* FK: SwapContext is not used with KERNEL_SWAP. */
960   pDRIInfo->SwapContext = NULL;
961
962   pDRIInfo->InitBuffers = SAVAGEDRIInitBuffers;
963   pDRIInfo->MoveBuffers = SAVAGEDRIMoveBuffers;
964   pDRIInfo->OpenFullScreen = SAVAGEDRIOpenFullScreen;
965   pDRIInfo->CloseFullScreen = SAVAGEDRICloseFullScreen;
966   pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
967
968   if ( !DRIScreenInit( pScreen, pDRIInfo, &psav->drmFD ) ) {
969      xfree( pSAVAGEDRIServer );
970      psav->DRIServerInfo = 0;
971      xfree( pDRIInfo->devPrivate );
972      pDRIInfo->devPrivate = 0;
973      DRIDestroyInfoRec( psav->pDRIInfo );
974      psav->pDRIInfo = 0;
975      xf86DrvMsg( pScreen->myNum, X_ERROR,
976		  "[drm] DRIScreenInit failed.  Disabling DRI.\n" );
977      return FALSE;
978   }
979
980   /* Check the SAVAGE DRM version */
981   {
982      drmVersionPtr version = drmGetVersion(psav->drmFD);
983      if ( version ) {
984         if ( version->version_major != 2 ||
985	      version->version_minor < 0 ) {
986            /* incompatible drm version */
987            xf86DrvMsg( pScreen->myNum, X_ERROR,
988			"[dri] SAVAGEDRIScreenInit failed because of a version mismatch.\n"
989			"[dri] savage.ko kernel module version is %d.%d.%d but version 2.0.x is needed.\n"
990			"[dri] Disabling DRI.\n",
991			version->version_major,
992			version->version_minor,
993			version->version_patchlevel );
994            drmFreeVersion( version );
995	    SAVAGEDRICloseScreen( pScreen );		/* FIXME: ??? */
996            return FALSE;
997         }
998	 if ( psav->CommandDMA && version->version_minor < 4 ) {
999	    xf86DrvMsg( pScreen->myNum, X_WARNING,
1000			"[drm] DRM version < 2.4.0 does not support command DMA.\n");
1001	    psav->CommandDMA = FALSE;
1002	 }
1003	 if ( !psav->VertexDMA && version->version_minor < 4 ) {
1004	    xf86DrvMsg( pScreen->myNum, X_ERROR,
1005			"[drm] DRM version < 2.4.0 requires vertex DMA.\n");
1006	    drmFreeVersion( version );
1007	    SAVAGEDRICloseScreen( pScreen );
1008	    return FALSE;
1009	 }
1010         drmFreeVersion( version );
1011      }
1012   }
1013
1014   if ( !psav->IsPCI && !SAVAGEDRIAgpInit( pScreen ) ) {
1015       if (pSAVAGEDRIServer->agp.handle != 0) {
1016	   /* AGP initialization succeeded, but adding AGP mappings failed. */
1017	   SAVAGEDRICloseScreen( pScreen );
1018	   return FALSE;
1019       }
1020       /* AGP initialization failed, fall back to PCI mode. */
1021       psav->IsPCI = TRUE;
1022       psav->AgpDMA = FALSE;
1023       xf86DrvMsg( pScrn->scrnIndex, X_WARNING,
1024		   "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
1025       xf86DrvMsg( pScrn->scrnIndex, X_WARNING,
1026		   "[agp] Make sure you have the agpgart kernel module loaded.\n");
1027   }
1028
1029   if ( !SAVAGEDRIMapInit( pScreen ) ) {
1030      SAVAGEDRICloseScreen( pScreen );
1031      return FALSE;
1032   }
1033
1034   if ( !SAVAGEDRIBuffersInit( pScreen ) ) {
1035      SAVAGEDRICloseScreen( pScreen );
1036      return FALSE;
1037   }
1038
1039   if ( !SAVAGEInitVisualConfigs( pScreen ) ) {
1040      SAVAGEDRICloseScreen( pScreen );
1041      return FALSE;
1042   }
1043   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n" );
1044
1045   return TRUE;
1046}
1047
1048
1049Bool SAVAGEDRIFinishScreenInit( ScreenPtr pScreen )
1050{
1051   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1052   SavagePtr psav = SAVPTR(pScrn);
1053   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
1054   SAVAGEDRIPtr pSAVAGEDRI = (SAVAGEDRIPtr)psav->pDRIInfo->devPrivate;
1055   int i;
1056
1057   if ( !psav->pDRIInfo )
1058      return FALSE;
1059
1060   psav->pDRIInfo->driverSwapMethod = DRI_KERNEL_SWAP;
1061
1062   /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
1063    * because *DRIKernelInit requires that the hardware lock is held by
1064    * the X server, and the first time the hardware lock is grabbed is
1065    * in DRIFinishScreenInit.
1066    */
1067   if ( !DRIFinishScreenInit( pScreen ) ) {
1068      SAVAGEDRICloseScreen( pScreen );
1069      return FALSE;
1070   }
1071   psav->LockHeld = 1;
1072
1073   if ( !SAVAGEDRIKernelInit( pScreen ) ) {
1074      SAVAGEDRICloseScreen( pScreen );
1075      return FALSE;
1076   }
1077
1078   pSAVAGEDRI->chipset          = psav->Chipset;
1079   pSAVAGEDRI->width		= pScrn->virtualX;
1080   pSAVAGEDRI->height		= pScrn->virtualY;
1081   pSAVAGEDRI->mem		= pScrn->videoRam * 1024;
1082   pSAVAGEDRI->cpp		= pScrn->bitsPerPixel / 8;
1083   pSAVAGEDRI->zpp		= pSAVAGEDRI->cpp;
1084
1085   pSAVAGEDRI->agpMode		= psav->IsPCI ? 0 : psav->agpMode;
1086
1087   pSAVAGEDRI->bufferSize       = SAVAGE_BUFFER_SIZE;
1088
1089   pSAVAGEDRI->frontOffset		= pSAVAGEDRIServer->frontOffset;
1090   pSAVAGEDRI->frontbufferSize		= pSAVAGEDRIServer->frontbufferSize;
1091
1092   pSAVAGEDRI->backOffset		= pSAVAGEDRIServer->backOffset;
1093   pSAVAGEDRI->backbufferSize		= pSAVAGEDRIServer->backbufferSize;
1094
1095   pSAVAGEDRI->depthOffset		= pSAVAGEDRIServer->depthOffset;
1096   pSAVAGEDRI->depthbufferSize		= pSAVAGEDRIServer->depthbufferSize;
1097
1098   pSAVAGEDRI->textureOffset	= pSAVAGEDRIServer->textureOffset;
1099
1100   i = mylog2( pSAVAGEDRIServer->textureSize / SAVAGE_NR_TEX_REGIONS );
1101   if ( i < SAVAGE_LOG_MIN_TEX_REGION_SIZE )
1102      i = SAVAGE_LOG_MIN_TEX_REGION_SIZE;
1103
1104   pSAVAGEDRI->logTextureGranularity = i;
1105   pSAVAGEDRI->textureSize = (pSAVAGEDRIServer->textureSize >> i) << i; /* truncate */
1106
1107   pSAVAGEDRI->agpTextureHandle = pSAVAGEDRIServer->agpTextures.handle;
1108
1109   i = mylog2( pSAVAGEDRIServer->agpTextures.size / SAVAGE_NR_TEX_REGIONS );
1110   if ( i < SAVAGE_LOG_MIN_TEX_REGION_SIZE )
1111      i = SAVAGE_LOG_MIN_TEX_REGION_SIZE;
1112
1113   pSAVAGEDRI->logAgpTextureGranularity = i;
1114   pSAVAGEDRI->agpTextureSize = (pSAVAGEDRIServer->agpTextures.size >> i) << i; /* truncate */
1115
1116   pSAVAGEDRI->apertureHandle	= pSAVAGEDRIServer->aperture.handle;
1117   pSAVAGEDRI->apertureSize	= pSAVAGEDRIServer->aperture.size;
1118   {
1119      unsigned int shift = 0;
1120
1121      if(pSAVAGEDRI->width > 1024)
1122        shift = 1;
1123
1124      pSAVAGEDRI->aperturePitch = psav->ulAperturePitch;
1125   }
1126
1127   {
1128      unsigned int value = 0;
1129
1130      OUTREG(0x850C,(INREG(0x850C) | 0x00008000)); /* AGD: I don't think this does anything on 3D/MX/IX */
1131						   /* maybe savage4 too... */
1132      /* we don't use Y range flag,so comment it */
1133      /*
1134        if(pSAVAGEDRI->width <= 1024)
1135            value |= (1<<29);
1136      */
1137      if ((psav->Chipset == S3_SAVAGE_MX) /* 3D/MX/IX seem to set up the tile stride differently */
1138	|| (psav->Chipset == S3_SAVAGE3D)) {
1139      	    if(pSAVAGEDRI->cpp == 2)
1140      	    {
1141         	value |=  ((psav->lDelta / 4) >> 5) << 24;
1142         	value |= 2<<30;
1143      	    } else {
1144         	value |=  ((psav->lDelta / 4) >> 5) << 24;
1145         	value |= 3<<30;
1146      	    }
1147
1148	    OUTREG(TILED_SURFACE_REGISTER_0, value|(pSAVAGEDRI->frontOffset) ); /* front */
1149	    OUTREG(TILED_SURFACE_REGISTER_1, value|(pSAVAGEDRI->backOffset) ); /* back  */
1150	    OUTREG(TILED_SURFACE_REGISTER_2, value|(pSAVAGEDRI->depthOffset) ); /* depth */
1151      } else {
1152	    int offset_shift = 5;
1153      	    if(pSAVAGEDRI->cpp == 2)
1154      	    {
1155         	value |=  (((pSAVAGEDRI->width + 0x3F) & 0xFFC0) >> 6) << 20;
1156         	value |= 2<<30;
1157      	    } else {
1158         	value |=  (((pSAVAGEDRI->width + 0x1F) & 0xFFE0) >> 5) << 20;
1159         	value |= 3<<30;
1160      	    }
1161	    if (psav->Chipset == S3_SUPERSAVAGE) /* supersavages have a different shift */
1162		offset_shift = 6;
1163	    OUTREG(TILED_SURFACE_REGISTER_0, value|(pSAVAGEDRI->frontOffset >> offset_shift) ); /* front */
1164	    OUTREG(TILED_SURFACE_REGISTER_1, value|(pSAVAGEDRI->backOffset >> offset_shift) ); /* back  */
1165	    OUTREG(TILED_SURFACE_REGISTER_2, value|(pSAVAGEDRI->depthOffset >> offset_shift) ); /* depth */
1166      }
1167   }
1168
1169   pSAVAGEDRI->statusHandle	= pSAVAGEDRIServer->status.handle;
1170   pSAVAGEDRI->statusSize	= pSAVAGEDRIServer->status.size;
1171
1172   pSAVAGEDRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
1173
1174   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]pSAVAGEDRIServer:\n" );
1175   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	reserved_map_agpstart:0x%08x\n",pSAVAGEDRIServer->reserved_map_agpstart);
1176   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	reserved_map_idx:0x%08x\n",pSAVAGEDRIServer->reserved_map_idx);
1177   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	sarea_priv_offset:0x%08x\n",pSAVAGEDRIServer->sarea_priv_offset);
1178   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	chipset:0x%08x\n",pSAVAGEDRIServer->chipset);
1179   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	sgram:0x%08x\n",pSAVAGEDRIServer->sgram);
1180   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontbufferSize:0x%08x\n",pSAVAGEDRIServer->frontbufferSize);
1181   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontOffset:0x%08x\n",pSAVAGEDRIServer->frontOffset);
1182   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontPitch:0x%08x\n",pSAVAGEDRIServer->frontPitch);
1183   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backbufferSize:0x%08x\n",pSAVAGEDRIServer->backbufferSize);
1184   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backOffset:0x%08x\n",pSAVAGEDRIServer->backOffset);
1185   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backPitch:0x%08x\n",pSAVAGEDRIServer->backPitch);
1186   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthbufferSize:0x%08x\n",pSAVAGEDRIServer->depthbufferSize);
1187   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthOffset:0x%08x\n",pSAVAGEDRIServer->depthOffset);
1188   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthPitch:0x%08x\n",pSAVAGEDRIServer->depthPitch);
1189   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureOffset:0x%08x\n",pSAVAGEDRIServer->textureOffset);
1190   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureSize:0x%08x\n",pSAVAGEDRIServer->textureSize);
1191   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureSize:0x%08x\n",pSAVAGEDRIServer->textureSize);
1192   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	logTextureGranularity:0x%08x\n",pSAVAGEDRIServer->logTextureGranularity);
1193
1194   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agp:handle:0x%08lx\n",pSAVAGEDRIServer->agp.handle);
1195   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agp:offset:0x%08x\n",pSAVAGEDRIServer->agp.offset);
1196   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agp:size:0x%08x\n",pSAVAGEDRIServer->agp.size);
1197   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agp:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->agp.map);
1198
1199   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	registers:handle:0x%08lx\n",pSAVAGEDRIServer->registers.handle);
1200   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	registers:offset:0x%08x\n",pSAVAGEDRIServer->registers.offset);
1201   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	registers:size:0x%08x\n",pSAVAGEDRIServer->registers.size);
1202   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	registers:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->registers.map);
1203
1204   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	status:handle:0x%08lx\n",pSAVAGEDRIServer->status.handle);
1205   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	status:offset:0x%08x\n",pSAVAGEDRIServer->status.offset);
1206   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	status:size:0x%08x\n",pSAVAGEDRIServer->status.size);
1207   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	status:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->status.map);
1208
1209   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextures:handle:0x%08lx\n",pSAVAGEDRIServer->agpTextures.handle);
1210   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextures:offset:0x%08x\n",pSAVAGEDRIServer->agpTextures.offset);
1211   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextures:size:0x%08x\n",pSAVAGEDRIServer->agpTextures.size);
1212   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	apgTextures:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->agpTextures.map);
1213
1214   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	logAgpTextureGranularity:0x%08x\n",pSAVAGEDRIServer->logAgpTextureGranularity);
1215
1216   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cmdDma:handle:0x%08lx\n",pSAVAGEDRIServer->cmdDma.handle);
1217   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cmdDma:offset:0x%08x\n",pSAVAGEDRIServer->cmdDma.offset);
1218   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cmdDma:size:0x%08x\n",pSAVAGEDRIServer->cmdDma.size);
1219   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cmdDma:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->cmdDma.map);
1220
1221   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]pSAVAGEDRI:\n" );
1222   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	chipset:0x%08x\n",pSAVAGEDRI->chipset );
1223   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	width:0x%08x\n",pSAVAGEDRI->width );
1224   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	height:0x%08x\n",pSAVAGEDRI->height );
1225   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	mem:0x%08x\n",pSAVAGEDRI->mem );
1226   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cpp:%d\n",pSAVAGEDRI->cpp );
1227   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	zpp:%d\n",pSAVAGEDRI->zpp );
1228
1229   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpMode:%d\n",pSAVAGEDRI->agpMode );
1230
1231   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	bufferSize:%u\n",pSAVAGEDRI->bufferSize );
1232
1233   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontbufferSize:0x%08x\n",pSAVAGEDRI->frontbufferSize);
1234   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontOffset:0x%08x\n",pSAVAGEDRI->frontOffset );
1235
1236   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backbufferSize:0x%08x\n",pSAVAGEDRI->backbufferSize);
1237   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backOffset:0x%08x\n",pSAVAGEDRI->backOffset );
1238
1239   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthbufferSize:0x%08x\n",pSAVAGEDRI->depthbufferSize);
1240   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthOffset:0x%08x\n",pSAVAGEDRI->depthOffset );
1241
1242   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureOffset:0x%08x\n",pSAVAGEDRI->textureOffset );
1243   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureSize:0x%08x\n",pSAVAGEDRI->textureSize );
1244   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	logTextureGranularity:0x%08x\n",pSAVAGEDRI->logTextureGranularity );
1245
1246   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextureHandle:0x%08lx\n",pSAVAGEDRI->agpTextureHandle );
1247   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextureSize:0x%08x\n",pSAVAGEDRI->agpTextureSize );
1248   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	logAgpTextureGranularity:0x%08x\n",pSAVAGEDRI->logAgpTextureGranularity );
1249
1250   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	apertureHandle:0x%08lx\n",pSAVAGEDRI->apertureHandle);
1251   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	apertureSize:0x%08x\n",pSAVAGEDRI->apertureSize);
1252   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	aperturePitch:0x%08x\n",pSAVAGEDRI->aperturePitch);
1253
1254   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	statusHandle:0x%08lx\n",pSAVAGEDRI->statusHandle);
1255   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	statusSize:0x%08x\n",pSAVAGEDRI->statusSize);
1256
1257   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	sarea_priv_offset:0x%08x\n",pSAVAGEDRI->sarea_priv_offset);
1258
1259   return TRUE;
1260}
1261
1262
1263void SAVAGEDRICloseScreen( ScreenPtr pScreen )
1264{
1265   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1266   SavagePtr psav = SAVPTR(pScrn);
1267   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
1268
1269   if ( pSAVAGEDRIServer->status.map ) {
1270      drmUnmap( pSAVAGEDRIServer->status.map, pSAVAGEDRIServer->status.size );
1271      pSAVAGEDRIServer->status.map = NULL;
1272   }
1273
1274   if ( pSAVAGEDRIServer->registers.map ) {
1275      drmUnmap( pSAVAGEDRIServer->registers.map, pSAVAGEDRIServer->registers.size );
1276      pSAVAGEDRIServer->registers.map = NULL;
1277   }
1278
1279   if ( pSAVAGEDRIServer->aperture.map ) {
1280      drmUnmap( pSAVAGEDRIServer->aperture.map, pSAVAGEDRIServer->aperture.size );
1281      pSAVAGEDRIServer->aperture.map = NULL;
1282   }
1283
1284   if ( pSAVAGEDRIServer->agpTextures.map ) {
1285      drmUnmap( pSAVAGEDRIServer->agpTextures.map,
1286                pSAVAGEDRIServer->agpTextures.size );
1287      pSAVAGEDRIServer->agpTextures.map = NULL;
1288   }
1289
1290   if (pSAVAGEDRIServer->status.handle)
1291       drmRmMap(psav->drmFD,pSAVAGEDRIServer->status.handle);
1292
1293   if (pSAVAGEDRIServer->registers.handle)
1294       drmRmMap(psav->drmFD,pSAVAGEDRIServer->registers.handle);
1295
1296   if (pSAVAGEDRIServer->aperture.handle)
1297       drmRmMap(psav->drmFD,pSAVAGEDRIServer->registers.handle);
1298
1299   if (pSAVAGEDRIServer->agpTextures.handle)
1300       drmRmMap(psav->drmFD,pSAVAGEDRIServer->agpTextures.handle);
1301
1302   if (pSAVAGEDRIServer->cmdDma.handle)
1303       drmRmMap(psav->drmFD,pSAVAGEDRIServer->cmdDma.handle);
1304
1305   if ( pSAVAGEDRIServer->buffers.map ) {
1306      drmUnmap( pSAVAGEDRIServer->buffers.map, pSAVAGEDRIServer->buffers.size );
1307      pSAVAGEDRIServer->buffers.map = NULL;
1308   }
1309
1310   if ( pSAVAGEDRIServer->agp.handle ) {
1311      drmAgpUnbind( psav->drmFD, pSAVAGEDRIServer->agp.handle );
1312      drmAgpFree( psav->drmFD, pSAVAGEDRIServer->agp.handle );
1313      pSAVAGEDRIServer->agp.handle = 0;
1314      drmAgpRelease( psav->drmFD );
1315   }
1316
1317   DRICloseScreen( pScreen );
1318
1319   /* Don't use shadow status any more. If this happens due to failed
1320    * DRI initialization then SavageScreenInit will do the real
1321    * cleanup and restore ShadowStatus to sane settings. */
1322   psav->ShadowVirtual = NULL;
1323   psav->ShadowPhysical = 0;
1324
1325   if(psav->reserved)
1326      xf86FreeOffscreenLinear(psav->reserved);
1327
1328   if ( psav->pDRIInfo ) {
1329      if ( psav->pDRIInfo->devPrivate ) {
1330	 xfree( psav->pDRIInfo->devPrivate );
1331	 psav->pDRIInfo->devPrivate = 0;
1332      }
1333      DRIDestroyInfoRec( psav->pDRIInfo );
1334      psav->pDRIInfo = 0;
1335   }
1336   if ( psav->DRIServerInfo ) {
1337      xfree( psav->DRIServerInfo );
1338      psav->DRIServerInfo = 0;
1339   }
1340   if ( psav->pVisualConfigs ) {
1341      xfree( psav->pVisualConfigs );
1342   }
1343   if ( psav->pVisualConfigsPriv ) {
1344      xfree( psav->pVisualConfigsPriv );
1345   }
1346}
1347
1348void
1349SAVAGEDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
1350{
1351    ScreenPtr pScreen = pWin->drawable.pScreen;
1352    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1353    SavagePtr psav = SAVPTR(pScrn);
1354    BoxPtr pbox = REGION_RECTS(prgn);
1355    int nbox  = REGION_NUM_RECTS(prgn);
1356    drmSAVAGECmdHeader cmd[2];
1357    drmSAVAGECmdbuf cmdBuf;
1358    int ret;
1359
1360    if (!psav->LockHeld) {
1361	xf86DrvMsg( pScrn->scrnIndex, X_WARNING,
1362		    "Not holding the lock in InitBuffers.\n");
1363	return;
1364    }
1365
1366    cmd[0].clear0.cmd = SAVAGE_CMD_CLEAR;
1367    cmd[0].clear0.flags = SAVAGE_BACK|SAVAGE_DEPTH;
1368    cmd[1].clear1.mask = 0xffffffff;
1369    cmd[1].clear1.value = 0;
1370
1371    cmdBuf.cmd_addr = cmd;
1372    cmdBuf.size = 2;
1373    cmdBuf.dma_idx = 0;
1374    cmdBuf.discard = 0;
1375    cmdBuf.vb_addr = NULL;
1376    cmdBuf.vb_size = 0;
1377    cmdBuf.vb_stride = 0;
1378    cmdBuf.box_addr = (drm_clip_rect_t*)pbox;
1379    cmdBuf.nbox = nbox;
1380
1381    ret = drmCommandWrite(psav->drmFD, DRM_SAVAGE_BCI_CMDBUF,
1382			  &cmdBuf, sizeof(cmdBuf));
1383    if (ret < 0) {
1384	xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
1385		    "SAVAGEDRIInitBuffers: drmCommandWrite returned %d.\n",
1386		    ret);
1387    }
1388}
1389
1390/*
1391  This routine is a modified form of XAADoBitBlt with the calls to
1392  ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
1393  instead of destination. My origin is upside down so the ydir cases
1394  are reversed.
1395*/
1396
1397void
1398SAVAGEDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
1399		   RegionPtr prgnSrc, CARD32 index)
1400{
1401    ScreenPtr pScreen = pParent->drawable.pScreen;
1402    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1403    SavagePtr psav = SAVPTR(pScrn);
1404    int nbox;
1405    BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
1406    DDXPointPtr pptTmp, pptNew1, pptNew2;
1407    int xdir, ydir;
1408    int dx, dy;
1409    DDXPointPtr pptSrc;
1410    int screenwidth = pScrn->virtualX;
1411    int screenheight = pScrn->virtualY;
1412    BCI_GET_PTR;
1413
1414    if (!psav->LockHeld) {
1415	xf86DrvMsg( pScrn->scrnIndex, X_INFO, "Not holding lock in MoveBuffers\n");
1416    }
1417
1418    pbox = REGION_RECTS(prgnSrc);
1419    nbox = REGION_NUM_RECTS(prgnSrc);
1420    pboxNew1 = 0;
1421    pptNew1 = 0;
1422    pboxNew2 = 0;
1423    pboxNew2 = 0;
1424    pptSrc = &ptOldOrg;
1425
1426    dx = pParent->drawable.x - ptOldOrg.x;
1427    dy = pParent->drawable.y - ptOldOrg.y;
1428
1429    /* If the copy will overlap in Y, reverse the order */
1430    if (dy>0) {
1431        ydir = -1;
1432
1433        if (nbox>1) {
1434	    /* Keep ordering in each band, reverse order of bands */
1435	    pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
1436	    if (!pboxNew1) return;
1437	    pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
1438	    if (!pptNew1) {
1439	        DEALLOCATE_LOCAL(pboxNew1);
1440	        return;
1441	    }
1442	    pboxBase = pboxNext = pbox+nbox-1;
1443	    while (pboxBase >= pbox) {
1444	        while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
1445		  pboxNext--;
1446	        pboxTmp = pboxNext+1;
1447	        pptTmp = pptSrc + (pboxTmp - pbox);
1448	        while (pboxTmp <= pboxBase) {
1449		    *pboxNew1++ = *pboxTmp++;
1450		    *pptNew1++ = *pptTmp++;
1451		}
1452	        pboxBase = pboxNext;
1453	    }
1454	    pboxNew1 -= nbox;
1455	    pbox = pboxNew1;
1456	    pptNew1 -= nbox;
1457	    pptSrc = pptNew1;
1458	}
1459    } else {
1460        /* No changes required */
1461        ydir = 1;
1462    }
1463
1464    /* If the regions will overlap in X, reverse the order */
1465    if (dx>0) {
1466        xdir = -1;
1467
1468        if (nbox > 1) {
1469	    /*reverse orderof rects in each band */
1470	    pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
1471	    pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
1472	    if (!pboxNew2 || !pptNew2) {
1473	        if (pptNew2) DEALLOCATE_LOCAL(pptNew2);
1474	        if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2);
1475	        if (pboxNew1) {
1476		    DEALLOCATE_LOCAL(pptNew1);
1477		    DEALLOCATE_LOCAL(pboxNew1);
1478		}
1479	       return;
1480	    }
1481	    pboxBase = pboxNext = pbox;
1482	    while (pboxBase < pbox+nbox) {
1483	        while ((pboxNext < pbox+nbox) &&
1484		       (pboxNext->y1 == pboxBase->y1))
1485		  pboxNext++;
1486	        pboxTmp = pboxNext;
1487	        pptTmp = pptSrc + (pboxTmp - pbox);
1488	        while (pboxTmp != pboxBase) {
1489		    *pboxNew2++ = *--pboxTmp;
1490		    *pptNew2++ = *--pptTmp;
1491		}
1492	        pboxBase = pboxNext;
1493	    }
1494	    pboxNew2 -= nbox;
1495	    pbox = pboxNew2;
1496	    pptNew2 -= nbox;
1497	    pptSrc = pptNew2;
1498	}
1499    } else {
1500        /* No changes are needed */
1501        xdir = 1;
1502    }
1503
1504    BCI_SEND(0xc0030000); /* wait for 2D+3D idle */
1505    SAVAGEDRISetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);
1506    for ( ; nbox-- ; pbox++)
1507     {
1508	 int x1 = pbox->x1;
1509	 int y1 = pbox->y1;
1510	 int destx = x1 + dx;
1511	 int desty = y1 + dy;
1512	 int w = pbox->x2 - x1 + 1;
1513	 int h = pbox->y2 - y1 + 1;
1514
1515	 if ( destx < 0 ) x1 -= destx, w += destx, destx = 0;
1516	 if ( desty < 0 ) y1 -= desty, h += desty, desty = 0;
1517	 if ( destx + w > screenwidth ) w = screenwidth - destx;
1518	 if ( desty + h > screenheight ) h = screenheight - desty;
1519	 if ( w <= 0 ) continue;
1520	 if ( h <= 0 ) continue;
1521
1522	 SAVAGESelectBuffer(pScrn, SAVAGE_BACK);
1523	 SAVAGEDRISubsequentScreenToScreenCopy(pScrn, x1, y1,
1524					       destx,desty, w, h);
1525	 SAVAGESelectBuffer(pScrn, SAVAGE_DEPTH);
1526	 SAVAGEDRISubsequentScreenToScreenCopy(pScrn, x1,y1,
1527					       destx,desty, w, h);
1528     }
1529    SAVAGESelectBuffer(pScrn, SAVAGE_FRONT);
1530
1531    if (pboxNew2) {
1532        DEALLOCATE_LOCAL(pptNew2);
1533        DEALLOCATE_LOCAL(pboxNew2);
1534    }
1535    if (pboxNew1) {
1536        DEALLOCATE_LOCAL(pptNew1);
1537        DEALLOCATE_LOCAL(pboxNew1);
1538    }
1539
1540    BCI_SEND(0xc0020000); /* wait for 2D idle */
1541    if (psav->useEXA)
1542	exaMarkSync(pScreen);
1543    else
1544	psav->AccelInfoRec->NeedToSync = TRUE;
1545}
1546
1547static void
1548SAVAGEDRISetupForScreenToScreenCopy(
1549    ScrnInfoPtr pScrn,
1550    int xdir,
1551    int ydir,
1552    int rop,
1553    unsigned planemask,
1554    int transparency_color)
1555{
1556    SavagePtr psav = SAVPTR(pScrn);
1557    int cmd =0;
1558
1559    cmd = BCI_CMD_RECT | BCI_CMD_DEST_PBD | BCI_CMD_SRC_PBD_COLOR;
1560    BCI_CMD_SET_ROP( cmd, XAAGetCopyROP(rop) );
1561    if (transparency_color != -1)
1562        cmd |= BCI_CMD_SEND_COLOR | BCI_CMD_SRC_TRANSPARENT;
1563
1564    if (xdir == 1 ) cmd |= BCI_CMD_RECT_XP;
1565    if (ydir == 1 ) cmd |= BCI_CMD_RECT_YP;
1566
1567    psav->SavedBciCmd = cmd;
1568    psav->SavedBgColor = transparency_color;
1569
1570}
1571
1572static void
1573SAVAGEDRISubsequentScreenToScreenCopy(
1574    ScrnInfoPtr pScrn,
1575    int x1,
1576    int y1,
1577    int x2,
1578    int y2,
1579    int w,
1580    int h)
1581{
1582    SavagePtr psav = SAVPTR(pScrn);
1583    BCI_GET_PTR;
1584
1585    if (!w || !h) return;
1586    if (!(psav->SavedBciCmd & BCI_CMD_RECT_XP)) {
1587        w --;
1588        x1 += w;
1589        x2 += w;
1590        w ++;
1591    }
1592    if (!(psav->SavedBciCmd & BCI_CMD_RECT_YP)) {
1593        h --;
1594        y1 += h;
1595        y2 += h;
1596        h ++;
1597    }
1598
1599    psav->WaitQueue(psav,6);
1600    BCI_SEND(psav->SavedBciCmd);
1601    if (psav->SavedBgColor != -1)
1602	BCI_SEND(psav->SavedBgColor);
1603    BCI_SEND(BCI_X_Y(x1, y1));
1604    BCI_SEND(BCI_X_Y(x2, y2));
1605    BCI_SEND(BCI_W_H(w, h));
1606
1607}
1608
1609/*
1610 * the FullScreen DRI code is dead, this is just left in place to show how
1611 * to set up pageflipping.
1612 */
1613static Bool
1614SAVAGEDRIOpenFullScreen(ScreenPtr pScreen)
1615{
1616  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1617  vgaHWPtr hwp = VGAHWPTR(pScrn);
1618  SavagePtr psav = SAVPTR(pScrn);
1619  unsigned int vgaCRIndex = hwp->IOBase + 4;
1620  unsigned int vgaCRReg = hwp->IOBase + 5;
1621  SAVAGEDRIPtr pSAVAGEDRI = (SAVAGEDRIPtr)psav->pDRIInfo->devPrivate;
1622  unsigned int TileStride;
1623  unsigned int WidthinTiles;
1624  unsigned int depth;
1625
1626  OUTREG(0x48C18, INREG(0x48C18) & 0xFFFFFFF7);
1627  /*VGAOUT8(vgaCRIndex,0x66);
1628  VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg)|0x10);*/
1629  VGAOUT8(vgaCRIndex,0x69);
1630  VGAOUT8(vgaCRReg, 0x80);
1631
1632  depth = pScrn->bitsPerPixel;
1633
1634  if(depth == 16)
1635  {
1636      WidthinTiles = (pSAVAGEDRI->width+63)>>6;
1637      TileStride = (pSAVAGEDRI->width+63)&(~63);
1638
1639  }
1640  else
1641  {
1642      WidthinTiles = (pSAVAGEDRI->width+31)>>5;
1643      TileStride = (pSAVAGEDRI->width+31)&(~31);
1644
1645  }
1646
1647
1648  /* set primary stream stride */
1649  {
1650      unsigned int value;
1651
1652      /*value = 0x80000000|(WidthinTiles<<24)|(TileStride*depth/8);*/
1653      value = 0x80000000|(WidthinTiles<<24);
1654      if(depth == 32)
1655          value |= 0x40000000;
1656
1657      OUTREG(PRI_STREAM_STRIDE, value);
1658
1659  }
1660
1661  /* set global bitmap descriptor */
1662  {
1663      unsigned int value;
1664      value = 0x10000000|
1665              0x00000009|
1666              0x01000000|
1667              (depth<<16)  | TileStride;
1668
1669      OUTREG(0x816C,value);
1670
1671  }
1672
1673   OUTREG(0x48C18, INREG(0x48C18) | 0x8);
1674
1675  return TRUE;
1676}
1677
1678static Bool
1679SAVAGEDRICloseFullScreen(ScreenPtr pScreen)
1680{
1681  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1682  SavagePtr psav = SAVPTR(pScrn);
1683  BCI_GET_PTR;
1684
1685  BCI_SEND(0xC0FF0000);
1686  psav->WaitIdleEmpty(psav);
1687  OUTREG(0x48C18, INREG(0x48C18) & 0xFFFFFFF7);
1688  /* set primary stream stride */
1689  {
1690      /* MM81C0 and 81C4 are used to control primary stream. */
1691      OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000);
1692      OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000);
1693
1694      /* FIFO control */
1695      OUTREG32(0X81EC,0Xffffffff);
1696
1697      if (!psav->bTiled) {
1698          OUTREG32(PRI_STREAM_STRIDE,
1699                   (((psav->lDelta * 2) << 16) & 0x3FFFE000) |
1700                   (psav->lDelta & 0x00001fff));
1701      }
1702      else if (pScrn->bitsPerPixel == 16) {
1703          /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
1704          OUTREG32(PRI_STREAM_STRIDE,
1705                   (((psav->lDelta * 2) << 16) & 0x3FFFE000)
1706                   | 0x80000000 | (psav->lDelta & 0x00001fff));
1707      }
1708      else if (pScrn->bitsPerPixel == 32) {
1709          OUTREG32(PRI_STREAM_STRIDE,
1710                   (((psav->lDelta * 2) << 16) & 0x3FFFE000)
1711                   | 0xC0000000 | (psav->lDelta & 0x00001fff));
1712      }
1713
1714
1715  }
1716
1717  /* set global bitmap descriptor */
1718      {
1719          OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart );
1720          OUTREG32(S3_GLB_BD_HIGH,psav->GlobalBD.bd2.HiPart | BCI_ENABLE | S3_LITTLE_ENDIAN | S3_BD64);
1721
1722      }
1723
1724  OUTREG(0x48C18, INREG(0x48C18) | 0x8);
1725  return TRUE;
1726}
1727
1728#endif
1729