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