1fa225cbcSrjs#ifdef HAVE_CONFIG_H
2fa225cbcSrjs#include "config.h"
3fa225cbcSrjs#endif
4fa225cbcSrjs
5fa225cbcSrjs#include <errno.h>
6fa225cbcSrjs#include <stdio.h>
7fa225cbcSrjs#include <string.h>
8fa225cbcSrjs#include <assert.h>
9fa225cbcSrjs
10fa225cbcSrjs#include "xf86.h"
11fa225cbcSrjs#include "xf86_OSproc.h"
12fa225cbcSrjs#include "xf86Priv.h"
13fa225cbcSrjs
14fa225cbcSrjs#include "xf86PciInfo.h"
15fa225cbcSrjs#include "xf86Pci.h"
16fa225cbcSrjs
17fa225cbcSrjs#include "windowstr.h"
18fa225cbcSrjs#include "shadow.h"
19fa225cbcSrjs#include "shadowfb.h"
20fa225cbcSrjs
21fa225cbcSrjs#include "GL/glxtokens.h"
22fa225cbcSrjs
23fa225cbcSrjs#include "i810.h"
24fa225cbcSrjs#include "i810_dri.h"
25fa225cbcSrjs
26fa225cbcSrjsstatic char I810KernelDriverName[] = "i810";
27fa225cbcSrjsstatic char I810ClientDriverName[] = "i810";
28fa225cbcSrjs
29fa225cbcSrjsstatic Bool I810InitVisualConfigs(ScreenPtr pScreen);
30fa225cbcSrjsstatic Bool I810CreateContext(ScreenPtr pScreen, VisualPtr visual,
31fa225cbcSrjs			      drm_context_t hwContext, void *pVisualConfigPriv,
32fa225cbcSrjs			      DRIContextType contextStore);
33fa225cbcSrjsstatic void I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
34fa225cbcSrjs			       DRIContextType contextStore);
35fa225cbcSrjsstatic void I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
36fa225cbcSrjs			       DRIContextType readContextType,
37fa225cbcSrjs			       void *readContextStore,
38fa225cbcSrjs			       DRIContextType writeContextType,
39fa225cbcSrjs			       void *writeContextStore);
40fa225cbcSrjsstatic void I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
41fa225cbcSrjsstatic void I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
42fa225cbcSrjs			       RegionPtr prgnSrc, CARD32 index);
43fa225cbcSrjs
44fa225cbcSrjs
45fa225cbcSrjsstatic void I810EnablePageFlip(ScreenPtr pScreen);
46fa225cbcSrjsstatic void I810DisablePageFlip(ScreenPtr pScreen);
47fa225cbcSrjsstatic void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen);
48fa225cbcSrjsstatic void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen);
49fa225cbcSrjsstatic void I810DRITransitionTo3d(ScreenPtr pScreen);
50fa225cbcSrjsstatic void I810DRITransitionTo2d(ScreenPtr pScreen);
51fa225cbcSrjs
52fa225cbcSrjsstatic void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
53fa225cbcSrjs
54fa225cbcSrjsextern void GlxSetVisualConfigs(int nconfigs,
55fa225cbcSrjs				__GLXvisualConfig * configs,
56fa225cbcSrjs				void **configprivs);
57fa225cbcSrjs
58fa225cbcSrjsstatic int i810_pitches[] = {
59fa225cbcSrjs   512,
60fa225cbcSrjs   1024,
61fa225cbcSrjs   2048,
62fa225cbcSrjs   4096,
63fa225cbcSrjs   0
64fa225cbcSrjs};
65fa225cbcSrjs
66fa225cbcSrjsstatic int i810_pitch_flags[] = {
67fa225cbcSrjs   0x0,
68fa225cbcSrjs   0x1,
69fa225cbcSrjs   0x2,
70fa225cbcSrjs   0x3,
71fa225cbcSrjs   0
72fa225cbcSrjs};
73fa225cbcSrjs
74fa225cbcSrjsstatic unsigned int i810_drm_version = 0;
75fa225cbcSrjs
76fa225cbcSrjsBool
77fa225cbcSrjsI810CleanupDma(ScrnInfoPtr pScrn)
78fa225cbcSrjs{
79fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
80fa225cbcSrjs   drmI810Init info;
81fa225cbcSrjs
82fa225cbcSrjs   memset(&info, 0, sizeof(drmI810Init));
83fa225cbcSrjs   info.func = I810_CLEANUP_DMA;
84fa225cbcSrjs
85fa225cbcSrjs   if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
86fa225cbcSrjs		       &info, sizeof(drmI810Init))) {
87fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
88fa225cbcSrjs		 "[dri] I810 Dma Cleanup Failed\n");
89fa225cbcSrjs      return FALSE;
90fa225cbcSrjs   }
91fa225cbcSrjs
92fa225cbcSrjs   return TRUE;
93fa225cbcSrjs}
94fa225cbcSrjs
95fa225cbcSrjsBool
96fa225cbcSrjsI810InitDma(ScrnInfoPtr pScrn)
97fa225cbcSrjs{
98fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
99fa225cbcSrjs   I810RingBuffer *ring = pI810->LpRing;
100fa225cbcSrjs   I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
101fa225cbcSrjs   drmI810Init info;
102fa225cbcSrjs
103fa225cbcSrjs   memset(&info, 0, sizeof(drmI810Init));
104fa225cbcSrjs
105fa225cbcSrjs   info.ring_start = ring->mem.Start;
106fa225cbcSrjs   info.ring_end = ring->mem.End;
107fa225cbcSrjs   info.ring_size = ring->mem.Size;
108fa225cbcSrjs   info.mmio_offset = (unsigned int)pI810DRI->regs;
109fa225cbcSrjs   info.buffers_offset = (unsigned int)pI810->buffer_map;
110fa225cbcSrjs   info.sarea_priv_offset = sizeof(XF86DRISAREARec);
111fa225cbcSrjs
112fa225cbcSrjs   info.front_offset = 0;
113fa225cbcSrjs   info.back_offset = pI810->BackBuffer.Start;
114fa225cbcSrjs   info.depth_offset = pI810->DepthBuffer.Start;
115fa225cbcSrjs   info.overlay_offset = pI810->OverlayStart;
116fa225cbcSrjs   info.overlay_physical = pI810->OverlayPhysical;
117fa225cbcSrjs   info.w = pScrn->virtualX;
118fa225cbcSrjs   info.h = pScrn->virtualY;
119fa225cbcSrjs   info.pitch = pI810->auxPitch;
120fa225cbcSrjs   info.pitch_bits = pI810->auxPitchBits;
121fa225cbcSrjs
122fa225cbcSrjs   /* We require DRM v1.2 or greater. Since DRM v1.2 broke compatibility
123fa225cbcSrjs    * we created a new v1.4 that supports a new init function. Eventually the
124fa225cbcSrjs    * old init function will go away. If you change the drm interface, make a
125fa225cbcSrjs    * new init type too so that we can detect the new client.
126fa225cbcSrjs    */
127fa225cbcSrjs   switch(i810_drm_version) {
128fa225cbcSrjs   case ((1<<16) | 0):
129fa225cbcSrjs   case ((1<<16) | 1):
130fa225cbcSrjs   case ((1<<16) | 2):
131fa225cbcSrjs   case ((1<<16) | 3):
132fa225cbcSrjs      /* Use OLD drm < 1.4 init */
133fa225cbcSrjs      info.func = I810_INIT_DMA;
134fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init PRE v1.4 interface.\n");
135fa225cbcSrjs      break;
136fa225cbcSrjs   default:
137fa225cbcSrjs   case ((1<<16) | 4):
138fa225cbcSrjs      /*  DRM version 1.3 or greater init */
139fa225cbcSrjs      info.func = I810_INIT_DMA_1_4;
140fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init v1.4 interface.\n");
141fa225cbcSrjs      break;
142fa225cbcSrjs   }
143fa225cbcSrjs
144fa225cbcSrjs   if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
145fa225cbcSrjs		       &info, sizeof(drmI810Init))) {
146fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
147fa225cbcSrjs		 "[drm] I810 Dma Initialization failed.\n");
148fa225cbcSrjs      return FALSE;
149fa225cbcSrjs   }
150fa225cbcSrjs
151fa225cbcSrjs   return TRUE;
152fa225cbcSrjs}
153fa225cbcSrjs
154fa225cbcSrjsstatic Bool
155fa225cbcSrjsI810InitVisualConfigs(ScreenPtr pScreen)
156fa225cbcSrjs{
157fa225cbcSrjs   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
158fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
159fa225cbcSrjs   int numConfigs = 0;
160fa225cbcSrjs   __GLXvisualConfig *pConfigs = NULL;
161fa225cbcSrjs   I810ConfigPrivPtr pI810Configs = NULL;
162fa225cbcSrjs   I810ConfigPrivPtr *pI810ConfigPtrs = NULL;
163fa225cbcSrjs   int accum, stencil, db, depth;
164fa225cbcSrjs   int i;
165fa225cbcSrjs
166fa225cbcSrjs   switch (pScrn->bitsPerPixel) {
167fa225cbcSrjs   case 8:
168fa225cbcSrjs   case 24:
169fa225cbcSrjs   case 32:
170fa225cbcSrjs      break;
171fa225cbcSrjs   case 16:
172fa225cbcSrjs      numConfigs = 8;
173fa225cbcSrjs
174fa225cbcSrjs      pConfigs =
175fa225cbcSrjs	    (__GLXvisualConfig *) xcalloc(sizeof(__GLXvisualConfig),
176fa225cbcSrjs					  numConfigs);
177fa225cbcSrjs      if (!pConfigs)
178fa225cbcSrjs	 return FALSE;
179fa225cbcSrjs
180fa225cbcSrjs      pI810Configs =
181fa225cbcSrjs	    (I810ConfigPrivPtr) xcalloc(sizeof(I810ConfigPrivRec),
182fa225cbcSrjs					numConfigs);
183fa225cbcSrjs      if (!pI810Configs) {
184fa225cbcSrjs	 xfree(pConfigs);
185fa225cbcSrjs	 return FALSE;
186fa225cbcSrjs      }
187fa225cbcSrjs
188fa225cbcSrjs      pI810ConfigPtrs =
189fa225cbcSrjs	    (I810ConfigPrivPtr *) xcalloc(sizeof(I810ConfigPrivPtr),
190fa225cbcSrjs					  numConfigs);
191fa225cbcSrjs      if (!pI810ConfigPtrs) {
192fa225cbcSrjs	 xfree(pConfigs);
193fa225cbcSrjs	 xfree(pI810Configs);
194fa225cbcSrjs	 return FALSE;
195fa225cbcSrjs      }
196fa225cbcSrjs
197fa225cbcSrjs      for (i = 0; i < numConfigs; i++)
198fa225cbcSrjs	 pI810ConfigPtrs[i] = &pI810Configs[i];
199fa225cbcSrjs
200fa225cbcSrjs      i = 0;
201fa225cbcSrjs      depth = 1;
202fa225cbcSrjs      for (accum = 0; accum <= 1; accum++) {
203fa225cbcSrjs	 for (stencil = 0; stencil <= 1; stencil++) {
204fa225cbcSrjs	    for (db = 1; db >= 0; db--) {
205fa225cbcSrjs	       pConfigs[i].vid = -1;
206fa225cbcSrjs	       pConfigs[i].class = -1;
207fa225cbcSrjs	       pConfigs[i].rgba = TRUE;
208fa225cbcSrjs	       pConfigs[i].redSize = 5;
209fa225cbcSrjs	       pConfigs[i].greenSize = 6;
210fa225cbcSrjs	       pConfigs[i].blueSize = 5;
211fa225cbcSrjs	       pConfigs[i].alphaSize = 0;
212fa225cbcSrjs	       pConfigs[i].redMask = 0x0000F800;
213fa225cbcSrjs	       pConfigs[i].greenMask = 0x000007E0;
214fa225cbcSrjs	       pConfigs[i].blueMask = 0x0000001F;
215fa225cbcSrjs	       pConfigs[i].alphaMask = 0;
216fa225cbcSrjs	       if (accum) {
217fa225cbcSrjs		  pConfigs[i].accumRedSize = 16;
218fa225cbcSrjs		  pConfigs[i].accumGreenSize = 16;
219fa225cbcSrjs		  pConfigs[i].accumBlueSize = 16;
220fa225cbcSrjs		  pConfigs[i].accumAlphaSize = 0;
221fa225cbcSrjs	       } else {
222fa225cbcSrjs		  pConfigs[i].accumRedSize = 0;
223fa225cbcSrjs		  pConfigs[i].accumGreenSize = 0;
224fa225cbcSrjs		  pConfigs[i].accumBlueSize = 0;
225fa225cbcSrjs		  pConfigs[i].accumAlphaSize = 0;
226fa225cbcSrjs	       }
227fa225cbcSrjs	       pConfigs[i].doubleBuffer = db ? TRUE : FALSE;
228fa225cbcSrjs	       pConfigs[i].stereo = FALSE;
229fa225cbcSrjs	       pConfigs[i].bufferSize = 16;
230fa225cbcSrjs	       if (depth)
231fa225cbcSrjs		  pConfigs[i].depthSize = 16;
232fa225cbcSrjs	       else
233fa225cbcSrjs		  pConfigs[i].depthSize = 0;
234fa225cbcSrjs	       if (stencil)
235fa225cbcSrjs		  pConfigs[i].stencilSize = 8;
236fa225cbcSrjs	       else
237fa225cbcSrjs		  pConfigs[i].stencilSize = 0;
238fa225cbcSrjs	       pConfigs[i].auxBuffers = 0;
239fa225cbcSrjs	       pConfigs[i].level = 0;
240fa225cbcSrjs	       if (stencil || accum)
241fa225cbcSrjs		  pConfigs[i].visualRating = GLX_SLOW_CONFIG;
242fa225cbcSrjs	       else
243fa225cbcSrjs		  pConfigs[i].visualRating = GLX_NONE;
244fa225cbcSrjs	       pConfigs[i].transparentPixel = GLX_NONE;
245fa225cbcSrjs	       pConfigs[i].transparentRed = 0;
246fa225cbcSrjs	       pConfigs[i].transparentGreen = 0;
247fa225cbcSrjs	       pConfigs[i].transparentBlue = 0;
248fa225cbcSrjs	       pConfigs[i].transparentAlpha = 0;
249fa225cbcSrjs	       pConfigs[i].transparentIndex = 0;
250fa225cbcSrjs	       i++;
251fa225cbcSrjs	    }
252fa225cbcSrjs	 }
253fa225cbcSrjs      }
254fa225cbcSrjs      assert(i == numConfigs);
255fa225cbcSrjs      break;
256fa225cbcSrjs   }
257fa225cbcSrjs   pI810->numVisualConfigs = numConfigs;
258fa225cbcSrjs   pI810->pVisualConfigs = pConfigs;
259fa225cbcSrjs   pI810->pVisualConfigsPriv = pI810Configs;
260fa225cbcSrjs   GlxSetVisualConfigs(numConfigs, pConfigs, (void **)pI810ConfigPtrs);
261fa225cbcSrjs   return TRUE;
262fa225cbcSrjs}
263fa225cbcSrjs
264fa225cbcSrjsstatic unsigned int
265fa225cbcSrjsmylog2(unsigned int n)
266fa225cbcSrjs{
267fa225cbcSrjs   unsigned int log2 = 1;
268fa225cbcSrjs
269fa225cbcSrjs   while (n > 1)
270fa225cbcSrjs      n >>= 1, log2++;
271fa225cbcSrjs   return log2;
272fa225cbcSrjs}
273fa225cbcSrjs
274fa225cbcSrjsBool
275fa225cbcSrjsI810DRIScreenInit(ScreenPtr pScreen)
276fa225cbcSrjs{
277fa225cbcSrjs   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
278fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
279fa225cbcSrjs   DRIInfoPtr pDRIInfo;
280fa225cbcSrjs   I810DRIPtr pI810DRI;
281fa225cbcSrjs   unsigned long tom;
282fa225cbcSrjs   drm_handle_t agpHandle;
283fa225cbcSrjs   drm_handle_t dcacheHandle;
284fa225cbcSrjs   int sysmem_size = 0;
285fa225cbcSrjs   int back_size = 0;
286fa225cbcSrjs   unsigned int pitch_idx = 0;
287fa225cbcSrjs   int bufs;
288fa225cbcSrjs   int width = pScrn->displayWidth * pI810->cpp;
289fa225cbcSrjs   int i;
290fa225cbcSrjs
291fa225cbcSrjs   /* Hardware 3D rendering only implemented for 16bpp */
292fa225cbcSrjs   /* And it only works for 5:6:5 (Mark) */
293fa225cbcSrjs   if (pScrn->depth != 16)
294fa225cbcSrjs      return FALSE;
295fa225cbcSrjs
296fa225cbcSrjs   /* Check that the GLX, DRI, and DRM modules have been loaded by testing
297fa225cbcSrjs    * for known symbols in each module. */
298fa225cbcSrjs   if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs"))
299fa225cbcSrjs      return FALSE;
300fa225cbcSrjs   if (!xf86LoaderCheckSymbol("drmAvailable"))
301fa225cbcSrjs      return FALSE;
302fa225cbcSrjs   if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
303fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
304fa225cbcSrjs		 "[dri] I810DRIScreenInit failed (libdri.a too old)\n");
305fa225cbcSrjs      return FALSE;
306fa225cbcSrjs   }
307fa225cbcSrjs
308fa225cbcSrjs   /* Check the DRI version */
309fa225cbcSrjs   {
310fa225cbcSrjs      int major, minor, patch;
311fa225cbcSrjs
312fa225cbcSrjs      DRIQueryVersion(&major, &minor, &patch);
313fa225cbcSrjs      if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
314fa225cbcSrjs	 xf86DrvMsg(pScreen->myNum, X_ERROR,
315fa225cbcSrjs		    "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
316fa225cbcSrjs		    "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n"
317fa225cbcSrjs		    "[dri] Disabling DRI.\n", major, minor, patch,
318fa225cbcSrjs                    DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
319fa225cbcSrjs	 return FALSE;
320fa225cbcSrjs      }
321fa225cbcSrjs   }
322fa225cbcSrjs
323fa225cbcSrjs   pDRIInfo = DRICreateInfoRec();
324fa225cbcSrjs   if (!pDRIInfo) {
325fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
326fa225cbcSrjs		 "[dri] DRICreateInfoRec failed.  Disabling DRI.\n");
327fa225cbcSrjs      return FALSE;
328fa225cbcSrjs   }
329fa225cbcSrjs
330fa225cbcSrjs/*     pDRIInfo->wrap.ValidateTree = 0;    */
331fa225cbcSrjs/*     pDRIInfo->wrap.PostValidateTree = 0;    */
332fa225cbcSrjs
333fa225cbcSrjs   pI810->pDRIInfo = pDRIInfo;
334fa225cbcSrjs   pI810->LockHeld = 0;
335fa225cbcSrjs
336fa225cbcSrjs   pDRIInfo->drmDriverName = I810KernelDriverName;
337fa225cbcSrjs   pDRIInfo->clientDriverName = I810ClientDriverName;
338fa225cbcSrjs   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
339fa225cbcSrjs      pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo);
340fa225cbcSrjs   } else {
341fa225cbcSrjs      pDRIInfo->busIdString = xalloc(64);
342fa225cbcSrjs      sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
343fa225cbcSrjs	      ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus),
344fa225cbcSrjs	      pI810->PciInfo->dev, pI810->PciInfo->func
345fa225cbcSrjs	      );
346fa225cbcSrjs   }
347fa225cbcSrjs   pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION;
348fa225cbcSrjs   pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION;
349fa225cbcSrjs   pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL;
350fa225cbcSrjs   pDRIInfo->frameBufferPhysicalAddress = (pointer) pI810->LinearAddr;
351fa225cbcSrjs   pDRIInfo->frameBufferSize = (((pScrn->displayWidth *
352fa225cbcSrjs				  pScrn->virtualY * pI810->cpp) +
353fa225cbcSrjs				 4096 - 1) / 4096) * 4096;
354fa225cbcSrjs
355fa225cbcSrjs   pDRIInfo->frameBufferStride = pScrn->displayWidth * pI810->cpp;
356fa225cbcSrjs   pDRIInfo->ddxDrawableTableEntry = I810_MAX_DRAWABLES;
357fa225cbcSrjs
358fa225cbcSrjs   if (SAREA_MAX_DRAWABLES < I810_MAX_DRAWABLES)
359fa225cbcSrjs      pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
360fa225cbcSrjs   else
361fa225cbcSrjs      pDRIInfo->maxDrawableTableEntry = I810_MAX_DRAWABLES;
362fa225cbcSrjs
363fa225cbcSrjs   /* For now the mapping works by using a fixed size defined
364fa225cbcSrjs    * in the SAREA header
365fa225cbcSrjs    */
366fa225cbcSrjs   if (sizeof(XF86DRISAREARec) + sizeof(I810SAREARec) > SAREA_MAX) {
367fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
368fa225cbcSrjs		 "[dri] Data does not fit in SAREA\n");
369fa225cbcSrjs      return FALSE;
370fa225cbcSrjs   }
371fa225cbcSrjs   pDRIInfo->SAREASize = SAREA_MAX;
372fa225cbcSrjs
373fa225cbcSrjs   if (!(pI810DRI = (I810DRIPtr) xcalloc(sizeof(I810DRIRec), 1))) {
374fa225cbcSrjs      DRIDestroyInfoRec(pI810->pDRIInfo);
375fa225cbcSrjs      pI810->pDRIInfo = NULL;
376fa225cbcSrjs      return FALSE;
377fa225cbcSrjs   }
378fa225cbcSrjs   pDRIInfo->devPrivate = pI810DRI;
379fa225cbcSrjs   pDRIInfo->devPrivateSize = sizeof(I810DRIRec);
380fa225cbcSrjs   pDRIInfo->contextSize = sizeof(I810DRIContextRec);
381fa225cbcSrjs
382fa225cbcSrjs   pDRIInfo->CreateContext = I810CreateContext;
383fa225cbcSrjs   pDRIInfo->DestroyContext = I810DestroyContext;
384fa225cbcSrjs   pDRIInfo->SwapContext = I810DRISwapContext;
385fa225cbcSrjs   pDRIInfo->InitBuffers = I810DRIInitBuffers;
386fa225cbcSrjs   pDRIInfo->MoveBuffers = I810DRIMoveBuffers;
387fa225cbcSrjs   pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
388fa225cbcSrjs   pDRIInfo->TransitionTo2d = I810DRITransitionTo2d;
389fa225cbcSrjs   pDRIInfo->TransitionTo3d = I810DRITransitionTo3d;
390fa225cbcSrjs   pDRIInfo->TransitionSingleToMulti3D = I810DRITransitionSingleToMulti3d;
391fa225cbcSrjs   pDRIInfo->TransitionMultiToSingle3D = I810DRITransitionMultiToSingle3d;
392fa225cbcSrjs
393fa225cbcSrjs   pDRIInfo->createDummyCtx = TRUE;
394fa225cbcSrjs   pDRIInfo->createDummyCtxPriv = FALSE;
395fa225cbcSrjs
396fa225cbcSrjs   /* This adds the framebuffer as a drm map *before* we have asked agp
397fa225cbcSrjs    * to allocate it.  Scary stuff, hold on...
398fa225cbcSrjs    */
399fa225cbcSrjs   if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) {
400fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
401fa225cbcSrjs		 "[dri] DRIScreenInit failed.  Disabling DRI.\n");
402fa225cbcSrjs      xfree(pDRIInfo->devPrivate);
403fa225cbcSrjs      pDRIInfo->devPrivate = NULL;
404fa225cbcSrjs      DRIDestroyInfoRec(pI810->pDRIInfo);
405fa225cbcSrjs      pI810->pDRIInfo = NULL;
406fa225cbcSrjs      return FALSE;
407fa225cbcSrjs   }
408fa225cbcSrjs
409fa225cbcSrjs   /* Check the i810 DRM versioning */
410fa225cbcSrjs   {
411fa225cbcSrjs      drmVersionPtr version;
412fa225cbcSrjs
413fa225cbcSrjs      /* Check the DRM lib version.
414fa225cbcSrjs       * drmGetLibVersion was not supported in version 1.0, so check for
415fa225cbcSrjs       * symbol first to avoid possible crash or hang.
416fa225cbcSrjs       */
417fa225cbcSrjs      if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
418fa225cbcSrjs	 version = drmGetLibVersion(pI810->drmSubFD);
419fa225cbcSrjs      } else
420fa225cbcSrjs      {
421fa225cbcSrjs	 /* drmlib version 1.0.0 didn't have the drmGetLibVersion
422fa225cbcSrjs	  * entry point.  Fake it by allocating a version record
423fa225cbcSrjs	  * via drmGetVersion and changing it to version 1.0.0
424fa225cbcSrjs	  */
425fa225cbcSrjs	 version = drmGetVersion(pI810->drmSubFD);
426fa225cbcSrjs	 version->version_major = 1;
427fa225cbcSrjs	 version->version_minor = 0;
428fa225cbcSrjs	 version->version_patchlevel = 0;
429fa225cbcSrjs      }
430fa225cbcSrjs
431fa225cbcSrjs#define REQ_MAJ 1
432fa225cbcSrjs#define REQ_MIN 1
433fa225cbcSrjs      if (version) {
434fa225cbcSrjs	 if (version->version_major != REQ_MAJ ||
435fa225cbcSrjs	     version->version_minor < REQ_MIN) {
436fa225cbcSrjs	    /* incompatible drm library version */
437fa225cbcSrjs	    xf86DrvMsg(pScreen->myNum, X_ERROR,
438fa225cbcSrjs		       "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
439fa225cbcSrjs		       "[dri] libdrm.a module version is %d.%d.%d but version %d.%d.x is needed.\n"
440fa225cbcSrjs		       "[dri] Disabling DRI.\n",
441fa225cbcSrjs		       version->version_major,
442fa225cbcSrjs		       version->version_minor, version->version_patchlevel,
443fa225cbcSrjs		       REQ_MAJ, REQ_MIN);
444fa225cbcSrjs	    drmFreeVersion(version);
445fa225cbcSrjs	    I810DRICloseScreen(pScreen);
446fa225cbcSrjs	    return FALSE;
447fa225cbcSrjs	 }
448fa225cbcSrjs	 drmFreeVersion(version);
449fa225cbcSrjs      }
450fa225cbcSrjs
451fa225cbcSrjs      /* Check the i810 DRM version */
452fa225cbcSrjs      version = drmGetVersion(pI810->drmSubFD);
453fa225cbcSrjs      if (version) {
454fa225cbcSrjs	i810_drm_version = (version->version_major<<16) |
455fa225cbcSrjs	                    version->version_minor;
456fa225cbcSrjs	 if (version->version_major != 1 || version->version_minor < 2) {
457fa225cbcSrjs	    /* incompatible drm version */
458fa225cbcSrjs	    xf86DrvMsg(pScreen->myNum, X_ERROR,
459fa225cbcSrjs		       "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
460fa225cbcSrjs		       "[dri] i810.o kernel module version is %d.%d.%d but version 1.2.0 or greater is needed.\n"
461fa225cbcSrjs		       "[dri] Disabling DRI.\n",
462fa225cbcSrjs		       version->version_major,
463fa225cbcSrjs		       version->version_minor, version->version_patchlevel);
464fa225cbcSrjs	    I810DRICloseScreen(pScreen);
465fa225cbcSrjs	    drmFreeVersion(version);
466fa225cbcSrjs	    return FALSE;
467fa225cbcSrjs	 }
468fa225cbcSrjs         pI810->drmMinor = version->version_minor;
469fa225cbcSrjs	 drmFreeVersion(version);
470fa225cbcSrjs      }
471fa225cbcSrjs   }
472fa225cbcSrjs
473fa225cbcSrjs   pI810DRI->regsSize = I810_REG_SIZE;
474fa225cbcSrjs   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->MMIOAddr,
475fa225cbcSrjs		 pI810DRI->regsSize, DRM_REGISTERS, 0,
476fa225cbcSrjs		 (drmAddress) &pI810DRI->regs) < 0) {
477fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n");
478fa225cbcSrjs      DRICloseScreen(pScreen);
479fa225cbcSrjs      return FALSE;
480fa225cbcSrjs   }
481fa225cbcSrjs   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
482fa225cbcSrjs	      (int)pI810DRI->regs);
483fa225cbcSrjs
484fa225cbcSrjs   pI810->backHandle = DRM_AGP_NO_HANDLE;
485fa225cbcSrjs   pI810->zHandle = DRM_AGP_NO_HANDLE;
486fa225cbcSrjs   pI810->cursorHandle = DRM_AGP_NO_HANDLE;
487fa225cbcSrjs   pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
488fa225cbcSrjs   pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
489fa225cbcSrjs   pI810->agpAcquired = FALSE;
490fa225cbcSrjs   pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
491fa225cbcSrjs
492fa225cbcSrjs   /* Agp Support - Need this just to get the framebuffer.
493fa225cbcSrjs    */
494fa225cbcSrjs   if (drmAgpAcquire(pI810->drmSubFD) < 0) {
495fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpAquire failed\n");
496fa225cbcSrjs      DRICloseScreen(pScreen);
497fa225cbcSrjs      return FALSE;
498fa225cbcSrjs   }
499fa225cbcSrjs   pI810->agpAcquired = TRUE;
500fa225cbcSrjs
501fa225cbcSrjs   if (drmAgpEnable(pI810->drmSubFD, 0) < 0) {
502fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpEnable failed\n");
503fa225cbcSrjs      DRICloseScreen(pScreen);
504fa225cbcSrjs      return FALSE;
505fa225cbcSrjs   }
506fa225cbcSrjs
507fa225cbcSrjs   memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
508fa225cbcSrjs   memset(&pI810->BackBuffer, 0, sizeof(I810MemRange));
509fa225cbcSrjs   memset(&pI810->DepthBuffer, 0, sizeof(I810MemRange));
510fa225cbcSrjs   pI810->CursorPhysical = 0;
511fa225cbcSrjs   pI810->CursorARGBPhysical = 0;
512fa225cbcSrjs
513fa225cbcSrjs   /* Dcache - half the speed of normal ram, but has use as a Z buffer
514fa225cbcSrjs    * under the DRI.
515fa225cbcSrjs    */
516fa225cbcSrjs
517fa225cbcSrjs   drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL,
518fa225cbcSrjs	       (drmAddress) &dcacheHandle);
519fa225cbcSrjs   pI810->dcacheHandle = dcacheHandle;
520fa225cbcSrjs
521fa225cbcSrjs   xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : 0x%x\n",
522fa225cbcSrjs	      (int)dcacheHandle);
523fa225cbcSrjs
524fa225cbcSrjs#define Elements(x) sizeof(x)/sizeof(*x)
525fa225cbcSrjs   for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++)
526fa225cbcSrjs      if (width <= i810_pitches[pitch_idx])
527fa225cbcSrjs	 break;
528fa225cbcSrjs
529fa225cbcSrjs   if (pitch_idx == Elements(i810_pitches)) {
530fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
531fa225cbcSrjs		 "[dri] Couldn't find depth/back buffer pitch");
532fa225cbcSrjs      DRICloseScreen(pScreen);
533fa225cbcSrjs      return FALSE;
534fa225cbcSrjs   } else {
535fa225cbcSrjs      /* for tiled memory to work, the buffer needs to have the
536fa225cbcSrjs       * number of lines as a multiple of 16 (the tile size),
537fa225cbcSrjs       *  - airlied */
538fa225cbcSrjs      int lines = (pScrn->virtualY + 15) / 16 * 16;
539fa225cbcSrjs      back_size = i810_pitches[pitch_idx] * lines;
540fa225cbcSrjs      back_size = ((back_size + 4096 - 1) / 4096) * 4096;
541fa225cbcSrjs   }
542fa225cbcSrjs
543fa225cbcSrjs   sysmem_size = pScrn->videoRam * 1024;
544fa225cbcSrjs   if (dcacheHandle != DRM_AGP_NO_HANDLE) {
545fa225cbcSrjs      if (back_size > 4 * 1024 * 1024) {
546fa225cbcSrjs	 xf86DrvMsg(pScreen->myNum, X_INFO,
547fa225cbcSrjs		    "[dri] Backsize is larger then 4 meg\n");
548fa225cbcSrjs	 sysmem_size = sysmem_size - 2 * back_size;
549fa225cbcSrjs	 drmAgpFree(pI810->drmSubFD, dcacheHandle);
550fa225cbcSrjs	 pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
551fa225cbcSrjs      } else {
552fa225cbcSrjs	 sysmem_size = sysmem_size - back_size;
553fa225cbcSrjs      }
554fa225cbcSrjs   } else {
555fa225cbcSrjs      sysmem_size = sysmem_size - 2 * back_size;
556fa225cbcSrjs   }
557fa225cbcSrjs
558fa225cbcSrjs   /* Max size is 48 without XvMC, 41 with 6 surfaces, 40 with 7 surfaces */
559fa225cbcSrjs   if (pI810->numSurfaces && (pI810->numSurfaces == 6)) {
560fa225cbcSrjs      if (sysmem_size > (pI810->FbMapSize - 7 * 1024 * 1024)) {
561fa225cbcSrjs	 sysmem_size = (pI810->FbMapSize - 7 * 1024 * 1024);
562fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
563fa225cbcSrjs		    "User requested more memory then fits in the agp aperture\n"
564fa225cbcSrjs		    "Truncating to %d bytes of memory\n", sysmem_size);
565fa225cbcSrjs      }
566fa225cbcSrjs   }
567fa225cbcSrjs   if (pI810->numSurfaces && (pI810->numSurfaces == 7)) {
568fa225cbcSrjs      if (sysmem_size > (pI810->FbMapSize - 8 * 1024 * 1024)) {
569fa225cbcSrjs	 sysmem_size = (pI810->FbMapSize - 8 * 1024 * 1024);
570fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
571fa225cbcSrjs		    "User requested more memory then fits in the agp aperture\n"
572fa225cbcSrjs		    "Truncating to %d bytes of memory\n", sysmem_size);
573fa225cbcSrjs      }
574fa225cbcSrjs   }
575fa225cbcSrjs
576fa225cbcSrjs   if (sysmem_size > pI810->FbMapSize) {
577fa225cbcSrjs      sysmem_size = pI810->FbMapSize;
578fa225cbcSrjs
579fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
580fa225cbcSrjs		 "[dri] User requested more memory then fits in the agp"
581fa225cbcSrjs		 " aperture\n\tTruncating to %d bytes of memory\n",
582fa225cbcSrjs		 sysmem_size);
583fa225cbcSrjs   }
584fa225cbcSrjs
585fa225cbcSrjs   sysmem_size -= 4096;			/* remove 4k for the hw cursor */
586fa225cbcSrjs   sysmem_size -= 16384;		/* remove 16k for the ARGB hw cursor */
587fa225cbcSrjs
588fa225cbcSrjs   pI810->SysMem.Start = 0;
589fa225cbcSrjs   pI810->SysMem.Size = sysmem_size;
590fa225cbcSrjs   pI810->SysMem.End = sysmem_size;
591fa225cbcSrjs   tom = sysmem_size;
592fa225cbcSrjs
593fa225cbcSrjs   pI810->SavedSysMem = pI810->SysMem;
594fa225cbcSrjs
595fa225cbcSrjs   if (dcacheHandle != DRM_AGP_NO_HANDLE) {
596fa225cbcSrjs      if (drmAgpBind(pI810->drmSubFD, dcacheHandle, pI810->DepthOffset) == 0) {
597fa225cbcSrjs	 memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
598fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
599fa225cbcSrjs		    "[agp] GART: Found 4096K Z buffer memory\n");
600fa225cbcSrjs	 pI810->DcacheMem.Start = pI810->DepthOffset;
601fa225cbcSrjs	 pI810->DcacheMem.Size = 1024 * 4096;
602fa225cbcSrjs	 pI810->DcacheMem.End =
603fa225cbcSrjs	       pI810->DcacheMem.Start + pI810->DcacheMem.Size;
604fa225cbcSrjs	 if (!I810AllocLow
605fa225cbcSrjs	     (&(pI810->DepthBuffer), &(pI810->DcacheMem), back_size)) {
606fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
607fa225cbcSrjs		       "[agp] Depth buffer allocation failed\n");
608fa225cbcSrjs	    DRICloseScreen(pScreen);
609fa225cbcSrjs	    return FALSE;
610fa225cbcSrjs	 }
611fa225cbcSrjs      } else {
612fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
613fa225cbcSrjs		    "[agp] GART: dcache bind failed\n");
614fa225cbcSrjs	 drmAgpFree(pI810->drmSubFD, dcacheHandle);
615fa225cbcSrjs	 pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
616fa225cbcSrjs      }
617fa225cbcSrjs   } else {
618fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
619fa225cbcSrjs		 "[agp] GART: no dcache memory found\n");
620fa225cbcSrjs   }
621fa225cbcSrjs
622fa225cbcSrjs   drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL,
623fa225cbcSrjs	       (drmAddress) &agpHandle);
624fa225cbcSrjs   pI810->backHandle = agpHandle;
625fa225cbcSrjs
626fa225cbcSrjs   if (agpHandle != DRM_AGP_NO_HANDLE) {
627fa225cbcSrjs      if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->BackOffset) == 0) {
628fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
629fa225cbcSrjs		    "[agp] Bound backbuffer memory\n");
630fa225cbcSrjs
631fa225cbcSrjs	 pI810->BackBuffer.Start = pI810->BackOffset;
632fa225cbcSrjs	 pI810->BackBuffer.Size = back_size;
633fa225cbcSrjs	 pI810->BackBuffer.End = (pI810->BackBuffer.Start +
634fa225cbcSrjs				  pI810->BackBuffer.Size);
635fa225cbcSrjs      } else {
636fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
637fa225cbcSrjs		    "[agp] Unable to bind backbuffer.  Disabling DRI.\n");
638fa225cbcSrjs	 DRICloseScreen(pScreen);
639fa225cbcSrjs	 return FALSE;
640fa225cbcSrjs      }
641fa225cbcSrjs   } else {
642fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
643fa225cbcSrjs		 "[dri] Unable to allocate backbuffer memory.  Disabling DRI.\n");
644fa225cbcSrjs      DRICloseScreen(pScreen);
645fa225cbcSrjs      return FALSE;
646fa225cbcSrjs   }
647fa225cbcSrjs
648fa225cbcSrjs   if (dcacheHandle == DRM_AGP_NO_HANDLE) {
649fa225cbcSrjs     drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL,
650fa225cbcSrjs		 (drmAddress) &agpHandle);
651fa225cbcSrjs
652fa225cbcSrjs      pI810->zHandle = agpHandle;
653fa225cbcSrjs
654fa225cbcSrjs      if (agpHandle != DRM_AGP_NO_HANDLE) {
655fa225cbcSrjs	 if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->DepthOffset) == 0) {
656fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
657fa225cbcSrjs		       "[agp] Bound depthbuffer memory\n");
658fa225cbcSrjs	    pI810->DepthBuffer.Start = pI810->DepthOffset;
659fa225cbcSrjs	    pI810->DepthBuffer.Size = back_size;
660fa225cbcSrjs	    pI810->DepthBuffer.End = (pI810->DepthBuffer.Start +
661fa225cbcSrjs				      pI810->DepthBuffer.Size);
662fa225cbcSrjs	 } else {
663fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
664fa225cbcSrjs		       "[agp] Unable to bind depthbuffer.  Disabling DRI.\n");
665fa225cbcSrjs	    DRICloseScreen(pScreen);
666fa225cbcSrjs	    return FALSE;
667fa225cbcSrjs	 }
668fa225cbcSrjs      } else {
669fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
670fa225cbcSrjs		    "[agp] Unable to allocate depthbuffer memory.  Disabling DRI.\n");
671fa225cbcSrjs	 DRICloseScreen(pScreen);
672fa225cbcSrjs	 return FALSE;
673fa225cbcSrjs      }
674fa225cbcSrjs   }
675fa225cbcSrjs
676fa225cbcSrjs   /* Now allocate and bind the agp space.  This memory will include the
677fa225cbcSrjs    * regular framebuffer as well as texture memory.
678fa225cbcSrjs    */
679fa225cbcSrjs   drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL,
680fa225cbcSrjs	       (drmAddress)&agpHandle);
681fa225cbcSrjs   pI810->sysmemHandle = agpHandle;
682fa225cbcSrjs
683fa225cbcSrjs   if (agpHandle != DRM_AGP_NO_HANDLE) {
684fa225cbcSrjs      if (drmAgpBind(pI810->drmSubFD, agpHandle, 0) == 0) {
685fa225cbcSrjs	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
686fa225cbcSrjs		   "[agp] Bound System Texture Memory\n");
687fa225cbcSrjs      } else {
688fa225cbcSrjs          xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to bind system texture memory. Disabling DRI.\n");
689fa225cbcSrjs	  DRICloseScreen(pScreen);
690fa225cbcSrjs	  return FALSE;
691fa225cbcSrjs      }
692fa225cbcSrjs   } else {
693fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to allocate system texture memory. Disabling DRI.\n");
694fa225cbcSrjs      DRICloseScreen(pScreen);
695fa225cbcSrjs      return FALSE;
696fa225cbcSrjs   }
697fa225cbcSrjs
698fa225cbcSrjs/* Allocate 7 or 8MB for XvMC this is setup as follows to best use tiled
699fa225cbcSrjs   regions and required surface pitches. (Numbers are adjusted if the
700fa225cbcSrjs   AGP region is only 32MB
701fa225cbcSrjs   For numSurfaces == 6
702fa225cbcSrjs   44 - 48MB = 4MB Fence, 8 Tiles wide
703fa225cbcSrjs   43 - 44MB = 1MB Fence, 8 Tiles wide
704fa225cbcSrjs   42 - 43MB = 1MB Fence, 4 Tiles wide
705fa225cbcSrjs   41 - 42MB = 1MB Fence, 4 Tiles wide
706fa225cbcSrjs   For numSurfaces == 7
707fa225cbcSrjs   44 - 48MB   = 4MB Fence, 8 Tiles wide
708fa225cbcSrjs   43 - 44MB   = 1MB Fence, 8 Tiles wide
709fa225cbcSrjs   42.5 - 43MB = 0.5MB Fence, 8 Tiles wide
710fa225cbcSrjs   42 - 42.5MB = 0.5MB Fence, 4 Tiles wide
711fa225cbcSrjs   40 - 42MB   = 2MB Fence, 4 Tiles wide
712fa225cbcSrjs */
713fa225cbcSrjs   if (pI810->numSurfaces) {
714fa225cbcSrjs      if (pI810->numSurfaces == 6) {
715fa225cbcSrjs	 pI810->MC.Size = 7 * 1024 * 1024;
716fa225cbcSrjs	 pI810->MC.Start = pI810->FbMapSize - 7 * 1024 * 1024;
717fa225cbcSrjs
718fa225cbcSrjs      }
719fa225cbcSrjs      if (pI810->numSurfaces == 7) {
720fa225cbcSrjs	 pI810->MC.Size = 8 * 1024 * 1024;
721fa225cbcSrjs	 pI810->MC.Start = pI810->FbMapSize - 8 * 1024 * 1024;
722fa225cbcSrjs      }
723fa225cbcSrjs      drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL,
724fa225cbcSrjs		  (drmAddress) &agpHandle);
725fa225cbcSrjs
726fa225cbcSrjs      pI810->xvmcHandle = agpHandle;
727fa225cbcSrjs
728fa225cbcSrjs      if (agpHandle != DRM_AGP_NO_HANDLE) {
729fa225cbcSrjs	 if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->MC.Start) == 0) {
730fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
731fa225cbcSrjs		       "GART: Allocated 7MB for HWMC\n");
732fa225cbcSrjs	    pI810->MC.End = pI810->MC.Start + pI810->MC.Size;
733fa225cbcSrjs	 } else {
734fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC bind failed\n");
735fa225cbcSrjs	    pI810->MC.Start = 0;
736fa225cbcSrjs	    pI810->MC.Size = 0;
737fa225cbcSrjs	    pI810->MC.End = 0;
738fa225cbcSrjs	 }
739fa225cbcSrjs      } else {
740fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC alloc failed\n");
741fa225cbcSrjs	 pI810->MC.Start = 0;
742fa225cbcSrjs	 pI810->MC.Size = 0;
743fa225cbcSrjs	 pI810->MC.End = 0;
744fa225cbcSrjs      }
745fa225cbcSrjs      pI810->xvmcContext = 0;
746fa225cbcSrjs   }
747fa225cbcSrjs
748fa225cbcSrjs   drmAgpAlloc(pI810->drmSubFD, 4096, 2,
749fa225cbcSrjs	       (unsigned long *)&pI810->CursorPhysical,
750fa225cbcSrjs	       (drmAddress) &agpHandle);
751fa225cbcSrjs
752fa225cbcSrjs   pI810->cursorHandle = agpHandle;
753fa225cbcSrjs
754fa225cbcSrjs   if (agpHandle != DRM_AGP_NO_HANDLE) {
755fa225cbcSrjs      tom = sysmem_size;
756fa225cbcSrjs
757fa225cbcSrjs      if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) {
758fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
759fa225cbcSrjs		    "[agp] GART: Allocated 4K for mouse cursor image\n");
760fa225cbcSrjs	 pI810->CursorStart = tom;
761fa225cbcSrjs	 tom += 4096;
762fa225cbcSrjs      } else {
763fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
764fa225cbcSrjs		    "[agp] GART: cursor bind failed\n");
765fa225cbcSrjs	 pI810->CursorPhysical = 0;
766fa225cbcSrjs      }
767fa225cbcSrjs   } else {
768fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
769fa225cbcSrjs		 "[agp] GART: cursor alloc failed\n");
770fa225cbcSrjs      pI810->CursorPhysical = 0;
771fa225cbcSrjs   }
772fa225cbcSrjs
773fa225cbcSrjs   drmAgpAlloc(pI810->drmSubFD, 16384, 2,
774fa225cbcSrjs	       (unsigned long *)&pI810->CursorARGBPhysical,
775fa225cbcSrjs	       (drmAddress) &agpHandle);
776fa225cbcSrjs
777fa225cbcSrjs   pI810->cursorARGBHandle = agpHandle;
778fa225cbcSrjs
779fa225cbcSrjs   if (agpHandle != DRM_AGP_NO_HANDLE) {
780fa225cbcSrjs 	int r;
781fa225cbcSrjs
782fa225cbcSrjs      if ((r = drmAgpBind(pI810->drmSubFD, agpHandle, tom)) == 0) {
783fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
784fa225cbcSrjs		    "[agp] GART: Allocated 16K for ARGB mouse cursor image\n");
785fa225cbcSrjs	 pI810->CursorARGBStart = tom;
786fa225cbcSrjs	 tom += 16384;
787fa225cbcSrjs      } else {
788fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
789fa225cbcSrjs		    "[agp] GART: ARGB cursor bind failed\n");
790fa225cbcSrjs	 pI810->CursorARGBPhysical = 0;
791fa225cbcSrjs      }
792fa225cbcSrjs   } else {
793fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
794fa225cbcSrjs		 "[agp] GART: ARGB cursor alloc failed\n");
795fa225cbcSrjs      pI810->CursorARGBPhysical = 0;
796fa225cbcSrjs   }
797fa225cbcSrjs
798fa225cbcSrjs   /* Steal some of the excess cursor space for the overlay regs.
799fa225cbcSrjs    */
800fa225cbcSrjs   pI810->OverlayPhysical = pI810->CursorPhysical + 1024;
801fa225cbcSrjs   pI810->OverlayStart = pI810->CursorStart + 1024;
802fa225cbcSrjs
803fa225cbcSrjs   I810SetTiledMemory(pScrn, 1,
804fa225cbcSrjs		      pI810->DepthBuffer.Start,
805fa225cbcSrjs		      i810_pitches[pitch_idx], 8 * 1024 * 1024);
806fa225cbcSrjs
807fa225cbcSrjs   I810SetTiledMemory(pScrn, 2,
808fa225cbcSrjs		      pI810->BackBuffer.Start,
809fa225cbcSrjs		      i810_pitches[pitch_idx], 8 * 1024 * 1024);
810fa225cbcSrjs
811fa225cbcSrjs   /* These are for HWMC surfaces */
812fa225cbcSrjs   if (pI810->numSurfaces == 6) {
813fa225cbcSrjs      I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 1024 * 1024);
814fa225cbcSrjs
815fa225cbcSrjs      I810SetTiledMemory(pScrn, 4,
816fa225cbcSrjs			 pI810->MC.Start + 1024 * 1024, 512, 1024 * 1024);
817fa225cbcSrjs
818fa225cbcSrjs      I810SetTiledMemory(pScrn, 5,
819fa225cbcSrjs			 pI810->MC.Start + 1024 * 1024 * 2,
820fa225cbcSrjs			 1024, 1024 * 1024);
821fa225cbcSrjs
822fa225cbcSrjs      I810SetTiledMemory(pScrn, 6,
823fa225cbcSrjs			 pI810->MC.Start + 1024 * 1024 * 3,
824fa225cbcSrjs			 1024, 4 * 1024 * 1024);
825fa225cbcSrjs   }
826fa225cbcSrjs   if (pI810->numSurfaces == 7) {
827fa225cbcSrjs      I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 2 * 1024 * 1024);
828fa225cbcSrjs
829fa225cbcSrjs      I810SetTiledMemory(pScrn, 4,
830fa225cbcSrjs			 pI810->MC.Start + 2 * 1024 * 1024, 512, 512 * 1024);
831fa225cbcSrjs
832fa225cbcSrjs      I810SetTiledMemory(pScrn, 5,
833fa225cbcSrjs			 pI810->MC.Start + 2 * 1024 * 1024 + 512 * 1024,
834fa225cbcSrjs			 1024, 512 * 1024);
835fa225cbcSrjs
836fa225cbcSrjs      I810SetTiledMemory(pScrn, 6,
837fa225cbcSrjs			 pI810->MC.Start + 3 * 1024 * 1024,
838fa225cbcSrjs			 1024, 1 * 1024 * 1024);
839fa225cbcSrjs
840fa225cbcSrjs      I810SetTiledMemory(pScrn, 7,
841fa225cbcSrjs			 pI810->MC.Start + 4 * 1024 * 1024,
842fa225cbcSrjs			 1024, 4 * 1024 * 1024);
843fa225cbcSrjs
844fa225cbcSrjs   }
845fa225cbcSrjs
846fa225cbcSrjs   pI810->auxPitch = i810_pitches[pitch_idx];
847fa225cbcSrjs   pI810->auxPitchBits = i810_pitch_flags[pitch_idx];
848fa225cbcSrjs   pI810->SavedDcacheMem = pI810->DcacheMem;
849fa225cbcSrjs   pI810DRI->backbufferSize = pI810->BackBuffer.Size;
850fa225cbcSrjs
851fa225cbcSrjs   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BackBuffer.Start,
852fa225cbcSrjs		 pI810->BackBuffer.Size, DRM_AGP, 0,
853fa225cbcSrjs		 (drmAddress) &pI810DRI->backbuffer) < 0) {
854fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
855fa225cbcSrjs		 "[drm] drmAddMap(backbuffer) failed.  Disabling DRI\n");
856fa225cbcSrjs      DRICloseScreen(pScreen);
857fa225cbcSrjs      return FALSE;
858fa225cbcSrjs   }
859fa225cbcSrjs
860fa225cbcSrjs   pI810DRI->depthbufferSize = pI810->DepthBuffer.Size;
861fa225cbcSrjs   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->DepthBuffer.Start,
862fa225cbcSrjs		 pI810->DepthBuffer.Size, DRM_AGP, 0,
863fa225cbcSrjs		 (drmAddress) &pI810DRI->depthbuffer) < 0) {
864fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
865fa225cbcSrjs		 "[drm] drmAddMap(depthbuffer) failed.  Disabling DRI.\n");
866fa225cbcSrjs      DRICloseScreen(pScreen);
867fa225cbcSrjs      return FALSE;
868fa225cbcSrjs   }
869fa225cbcSrjs
870fa225cbcSrjs   /* Allocate FrontBuffer etc. */
871fa225cbcSrjs   if (!I810AllocateFront(pScrn)) {
872fa225cbcSrjs      DRICloseScreen(pScreen);
873fa225cbcSrjs      return FALSE;
874fa225cbcSrjs   }
875fa225cbcSrjs
876fa225cbcSrjs   /* Allocate buffer memory */
877fa225cbcSrjs   I810AllocHigh(&(pI810->BufferMem), &(pI810->SysMem),
878fa225cbcSrjs		 I810_DMA_BUF_NR * I810_DMA_BUF_SZ);
879fa225cbcSrjs
880fa225cbcSrjs   xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Buffer map : %lx\n",
881fa225cbcSrjs	      pI810->BufferMem.Start);
882fa225cbcSrjs
883fa225cbcSrjs   if (pI810->BufferMem.Start == 0 ||
884fa225cbcSrjs       pI810->BufferMem.End - pI810->BufferMem.Start >
885fa225cbcSrjs       I810_DMA_BUF_NR * I810_DMA_BUF_SZ) {
886fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
887fa225cbcSrjs		 "[dri] Not enough memory for dma buffers.  Disabling DRI.\n");
888fa225cbcSrjs      DRICloseScreen(pScreen);
889fa225cbcSrjs      return FALSE;
890fa225cbcSrjs   }
891fa225cbcSrjs   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BufferMem.Start,
892fa225cbcSrjs		 pI810->BufferMem.Size, DRM_AGP, 0,
893fa225cbcSrjs		 (drmAddress) &pI810->buffer_map) < 0) {
894fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
895fa225cbcSrjs		 "[drm] drmAddMap(buffer_map) failed.  Disabling DRI.\n");
896fa225cbcSrjs      DRICloseScreen(pScreen);
897fa225cbcSrjs      return FALSE;
898fa225cbcSrjs   }
899fa225cbcSrjs
900fa225cbcSrjs   pI810DRI->agp_buffers = pI810->buffer_map;
901fa225cbcSrjs   pI810DRI->agp_buf_size = pI810->BufferMem.Size;
902fa225cbcSrjs
903fa225cbcSrjs   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing->mem.Start,
904fa225cbcSrjs		 pI810->LpRing->mem.Size, DRM_AGP, 0,
905fa225cbcSrjs		 (drmAddress) &pI810->ring_map) < 0) {
906fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
907fa225cbcSrjs		 "[drm] drmAddMap(ring_map) failed.  Disabling DRI.\n");
908fa225cbcSrjs      DRICloseScreen(pScreen);
909fa225cbcSrjs      return FALSE;
910fa225cbcSrjs   }
911fa225cbcSrjs
912fa225cbcSrjs   /* Use the rest of memory for textures. */
913fa225cbcSrjs   pI810DRI->textureSize = pI810->SysMem.Size;
914fa225cbcSrjs
915fa225cbcSrjs   i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS);
916fa225cbcSrjs
917fa225cbcSrjs   if (i < I810_LOG_MIN_TEX_REGION_SIZE)
918fa225cbcSrjs      i = I810_LOG_MIN_TEX_REGION_SIZE;
919fa225cbcSrjs
920fa225cbcSrjs   pI810DRI->logTextureGranularity = i;
921fa225cbcSrjs   pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i;	/* truncate */
922fa225cbcSrjs
923fa225cbcSrjs   if (pI810DRI->textureSize < 512 * 1024) {
924fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
925fa225cbcSrjs		 "[drm] Less then 512k memory left for textures.  Disabling DRI.\n");
926fa225cbcSrjs      DRICloseScreen(pScreen);
927fa225cbcSrjs      return FALSE;
928fa225cbcSrjs   }
929fa225cbcSrjs
930fa225cbcSrjs   I810AllocLow(&(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize);
931fa225cbcSrjs
932fa225cbcSrjs   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->TexMem.Start,
933fa225cbcSrjs		 pI810->TexMem.Size, DRM_AGP, 0,
934fa225cbcSrjs		 (drmAddress) &pI810DRI->textures) < 0) {
935fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
936fa225cbcSrjs		 "[drm] drmAddMap(textures) failed.  Disabling DRI.\n");
937fa225cbcSrjs      DRICloseScreen(pScreen);
938fa225cbcSrjs      return FALSE;
939fa225cbcSrjs   }
940fa225cbcSrjs
941fa225cbcSrjs   if ((bufs = drmAddBufs(pI810->drmSubFD,
942fa225cbcSrjs			  I810_DMA_BUF_NR,
943fa225cbcSrjs			  I810_DMA_BUF_SZ,
944fa225cbcSrjs			  DRM_AGP_BUFFER, pI810->BufferMem.Start)) <= 0) {
945fa225cbcSrjs      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
946fa225cbcSrjs		 "[drm] failure adding %d %d byte DMA buffers.  Disabling DRI.\n",
947fa225cbcSrjs		 I810_DMA_BUF_NR, I810_DMA_BUF_SZ);
948fa225cbcSrjs      DRICloseScreen(pScreen);
949fa225cbcSrjs      return FALSE;
950fa225cbcSrjs   }
951fa225cbcSrjs
952fa225cbcSrjs   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
953fa225cbcSrjs	      "[drm] added %d %d byte DMA buffers\n", bufs, I810_DMA_BUF_SZ);
954fa225cbcSrjs
955fa225cbcSrjs   I810InitDma(pScrn);
956fa225cbcSrjs
957fa225cbcSrjs   /* Okay now initialize the dma engine */
958fa225cbcSrjs
959fa225cbcSrjs   if (!pI810DRI->irq) {
960fa225cbcSrjs      pI810DRI->irq = drmGetInterruptFromBusID(pI810->drmSubFD,
961fa225cbcSrjs					       ((pI810->PciInfo->domain << 8) |
962fa225cbcSrjs						pI810->PciInfo->bus),
963fa225cbcSrjs					       pI810->PciInfo->dev,
964fa225cbcSrjs					       pI810->PciInfo->func
965fa225cbcSrjs					       );
966fa225cbcSrjs      if ((drmCtlInstHandler(pI810->drmSubFD, pI810DRI->irq)) != 0) {
967fa225cbcSrjs	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
968fa225cbcSrjs		    "[drm] failure adding irq handler, there is a device "
969fa225cbcSrjs		    "already using that irq\n Consider rearranging your "
970fa225cbcSrjs		    "PCI cards.  Disabling DRI.\n");
971fa225cbcSrjs	 DRICloseScreen(pScreen);
972fa225cbcSrjs	 return FALSE;
973fa225cbcSrjs      }
974fa225cbcSrjs   }
975fa225cbcSrjs
976fa225cbcSrjs   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
977fa225cbcSrjs	      "[drm] dma control initialized, using IRQ %d\n", pI810DRI->irq);
978fa225cbcSrjs
979fa225cbcSrjs   pI810DRI->deviceID = DEVICE_ID(pI810->PciInfo);
980fa225cbcSrjs   pI810DRI->width = pScrn->virtualX;
981fa225cbcSrjs   pI810DRI->height = pScrn->virtualY;
982fa225cbcSrjs   pI810DRI->mem = pScrn->videoRam * 1024;
983fa225cbcSrjs   pI810DRI->cpp = pI810->cpp;
984fa225cbcSrjs
985fa225cbcSrjs   pI810DRI->fbOffset = pI810->FrontBuffer.Start;
986fa225cbcSrjs   pI810DRI->fbStride = pI810->auxPitch;
987fa225cbcSrjs
988fa225cbcSrjs   pI810DRI->bitsPerPixel = pScrn->bitsPerPixel;
989fa225cbcSrjs
990fa225cbcSrjs   pI810DRI->textureOffset = pI810->TexMem.Start;
991fa225cbcSrjs
992fa225cbcSrjs   pI810DRI->backOffset = pI810->BackBuffer.Start;
993fa225cbcSrjs   pI810DRI->depthOffset = pI810->DepthBuffer.Start;
994fa225cbcSrjs
995fa225cbcSrjs   pI810DRI->ringOffset = pI810->LpRing->mem.Start;
996fa225cbcSrjs   pI810DRI->ringSize = pI810->LpRing->mem.Size;
997fa225cbcSrjs
998fa225cbcSrjs   pI810DRI->auxPitch = pI810->auxPitch;
999fa225cbcSrjs   pI810DRI->auxPitchBits = pI810->auxPitchBits;
1000fa225cbcSrjs   pI810DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
1001fa225cbcSrjs
1002fa225cbcSrjs   if (!(I810InitVisualConfigs(pScreen))) {
1003fa225cbcSrjs      xf86DrvMsg(pScreen->myNum, X_ERROR,
1004fa225cbcSrjs		 "[dri] I810InitVisualConfigs failed.  Disabling DRI.\n");
1005fa225cbcSrjs      DRICloseScreen(pScreen);
1006fa225cbcSrjs      return FALSE;
1007fa225cbcSrjs   }
1008fa225cbcSrjs
1009fa225cbcSrjs   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1010fa225cbcSrjs	      "[dri] visual configs initialized.\n");
1011fa225cbcSrjs   pI810->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
1012fa225cbcSrjs
1013fa225cbcSrjs   return TRUE;
1014fa225cbcSrjs}
1015fa225cbcSrjs
1016fa225cbcSrjsvoid
1017fa225cbcSrjsI810DRICloseScreen(ScreenPtr pScreen)
1018fa225cbcSrjs{
1019fa225cbcSrjs   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1020fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
1021fa225cbcSrjs   I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
1022fa225cbcSrjs
1023fa225cbcSrjs   if (pI810DRI->irq) {
1024fa225cbcSrjs       drmCtlUninstHandler(pI810->drmSubFD);
1025fa225cbcSrjs       pI810DRI->irq = 0;
1026fa225cbcSrjs   }
1027fa225cbcSrjs
1028fa225cbcSrjs   I810CleanupDma(pScrn);
1029fa225cbcSrjs
1030fa225cbcSrjs   if (pI810->dcacheHandle!=DRM_AGP_NO_HANDLE)
1031fa225cbcSrjs      drmAgpFree(pI810->drmSubFD, pI810->dcacheHandle);
1032fa225cbcSrjs   if (pI810->backHandle!=DRM_AGP_NO_HANDLE)
1033fa225cbcSrjs      drmAgpFree(pI810->drmSubFD, pI810->backHandle);
1034fa225cbcSrjs   if (pI810->zHandle!=DRM_AGP_NO_HANDLE)
1035fa225cbcSrjs      drmAgpFree(pI810->drmSubFD, pI810->zHandle);
1036fa225cbcSrjs   if (pI810->cursorHandle!=DRM_AGP_NO_HANDLE)
1037fa225cbcSrjs      drmAgpFree(pI810->drmSubFD, pI810->cursorHandle);
1038fa225cbcSrjs   if (pI810->xvmcHandle!=DRM_AGP_NO_HANDLE)
1039fa225cbcSrjs      drmAgpFree(pI810->drmSubFD, pI810->xvmcHandle);
1040fa225cbcSrjs   if (pI810->sysmemHandle!=DRM_AGP_NO_HANDLE)
1041fa225cbcSrjs      drmAgpFree(pI810->drmSubFD, pI810->sysmemHandle);
1042fa225cbcSrjs
1043fa225cbcSrjs   if (pI810->agpAcquired == TRUE)
1044fa225cbcSrjs      drmAgpRelease(pI810->drmSubFD);
1045fa225cbcSrjs
1046fa225cbcSrjs   pI810->backHandle = DRM_AGP_NO_HANDLE;
1047fa225cbcSrjs   pI810->zHandle = DRM_AGP_NO_HANDLE;
1048fa225cbcSrjs   pI810->cursorHandle = DRM_AGP_NO_HANDLE;
1049fa225cbcSrjs   pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
1050fa225cbcSrjs   pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
1051fa225cbcSrjs   pI810->agpAcquired = FALSE;
1052fa225cbcSrjs   pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
1053fa225cbcSrjs
1054fa225cbcSrjs   DRICloseScreen(pScreen);
1055fa225cbcSrjs
1056fa225cbcSrjs   if (pI810->pDRIInfo) {
1057fa225cbcSrjs      if (pI810->pDRIInfo->devPrivate) {
1058fa225cbcSrjs	 xfree(pI810->pDRIInfo->devPrivate);
1059fa225cbcSrjs	 pI810->pDRIInfo->devPrivate = NULL;
1060fa225cbcSrjs      }
1061fa225cbcSrjs      DRIDestroyInfoRec(pI810->pDRIInfo);
1062fa225cbcSrjs      pI810->pDRIInfo = NULL;
1063fa225cbcSrjs   }
1064fa225cbcSrjs   if (pI810->pVisualConfigs)
1065fa225cbcSrjs      xfree(pI810->pVisualConfigs);
1066fa225cbcSrjs   if (pI810->pVisualConfigsPriv)
1067fa225cbcSrjs      xfree(pI810->pVisualConfigsPriv);
1068fa225cbcSrjs}
1069fa225cbcSrjs
1070fa225cbcSrjsstatic Bool
1071fa225cbcSrjsI810CreateContext(ScreenPtr pScreen, VisualPtr visual,
1072fa225cbcSrjs		  drm_context_t hwContext, void *pVisualConfigPriv,
1073fa225cbcSrjs		  DRIContextType contextStore)
1074fa225cbcSrjs{
1075fa225cbcSrjs   return TRUE;
1076fa225cbcSrjs}
1077fa225cbcSrjs
1078fa225cbcSrjsstatic void
1079fa225cbcSrjsI810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
1080fa225cbcSrjs		   DRIContextType contextStore)
1081fa225cbcSrjs{
1082fa225cbcSrjs}
1083fa225cbcSrjs
1084fa225cbcSrjsBool
1085fa225cbcSrjsI810DRIFinishScreenInit(ScreenPtr pScreen)
1086fa225cbcSrjs{
1087fa225cbcSrjs   I810SAREARec *sPriv = (I810SAREARec *) DRIGetSAREAPrivate(pScreen);
1088fa225cbcSrjs   ScrnInfoPtr        pScrn = xf86Screens[pScreen->myNum];
1089fa225cbcSrjs   I810Ptr info  = I810PTR(pScrn);
1090fa225cbcSrjs
1091638e3f96Sjoerg   memset(sPriv, 0, sizeof(*sPriv));
1092fa225cbcSrjs
1093fa225cbcSrjs   /* Have shadow run only while there is 3d active.
1094fa225cbcSrjs    */
1095fa225cbcSrjs   if (info->allowPageFlip && info->drmMinor >= 3) {
1096fa225cbcSrjs     ShadowFBInit( pScreen, I810DRIRefreshArea );
1097fa225cbcSrjs   }
1098fa225cbcSrjs   else
1099fa225cbcSrjs     info->allowPageFlip = 0;
1100fa225cbcSrjs   return DRIFinishScreenInit(pScreen);
1101fa225cbcSrjs}
1102fa225cbcSrjs
1103fa225cbcSrjsvoid
1104fa225cbcSrjsI810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
1105fa225cbcSrjs		   DRIContextType oldContextType, void *oldContext,
1106fa225cbcSrjs		   DRIContextType newContextType, void *newContext)
1107fa225cbcSrjs{
1108fa225cbcSrjs   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1109fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
1110fa225cbcSrjs
1111fa225cbcSrjs   if (syncType == DRI_3D_SYNC &&
1112fa225cbcSrjs       oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) {
1113fa225cbcSrjs      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1114fa225cbcSrjs	 ErrorF("I810DRISwapContext (in)\n");
1115fa225cbcSrjs
1116fa225cbcSrjs      if (!pScrn->vtSema)
1117fa225cbcSrjs	  return;
1118fa225cbcSrjs      pI810->LockHeld = 1;
1119fa225cbcSrjs      I810RefreshRing(pScrn);
1120fa225cbcSrjs   } else if (syncType == DRI_2D_SYNC &&
1121fa225cbcSrjs	      oldContextType == DRI_NO_CONTEXT &&
1122fa225cbcSrjs	      newContextType == DRI_2D_CONTEXT) {
1123fa225cbcSrjs      pI810->LockHeld = 0;
1124fa225cbcSrjs      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1125fa225cbcSrjs	 ErrorF("I810DRISwapContext (out)\n");
1126fa225cbcSrjs   } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1127fa225cbcSrjs      ErrorF("I810DRISwapContext (other)\n");
1128fa225cbcSrjs}
1129fa225cbcSrjs
1130fa225cbcSrjsstatic void
1131fa225cbcSrjsI810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
1132fa225cbcSrjs{
1133fa225cbcSrjs   ScreenPtr pScreen = pWin->drawable.pScreen;
1134fa225cbcSrjs   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1135fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
1136fa225cbcSrjs   BoxPtr pbox = REGION_RECTS(prgn);
1137fa225cbcSrjs   int nbox = REGION_NUM_RECTS(prgn);
1138fa225cbcSrjs
1139fa225cbcSrjs   if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1140fa225cbcSrjs      ErrorF("I810DRIInitBuffers\n");
1141fa225cbcSrjs
1142fa225cbcSrjs   I810SetupForSolidFill(pScrn, 0, GXcopy, -1);
1143fa225cbcSrjs   while (nbox--) {
1144fa225cbcSrjs      I810SelectBuffer(pScrn, I810_SELECT_BACK);
1145fa225cbcSrjs      I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
1146fa225cbcSrjs				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
1147fa225cbcSrjs      pbox++;
1148fa225cbcSrjs   }
1149fa225cbcSrjs
1150fa225cbcSrjs   /* Clear the depth buffer - uses 0xffff rather than 0.
1151fa225cbcSrjs    */
1152fa225cbcSrjs   pbox = REGION_RECTS(prgn);
1153fa225cbcSrjs   nbox = REGION_NUM_RECTS(prgn);
1154fa225cbcSrjs   I810SelectBuffer(pScrn, I810_SELECT_DEPTH);
1155fa225cbcSrjs   I810SetupForSolidFill(pScrn, 0xffff, GXcopy, -1);
1156fa225cbcSrjs   while (nbox--) {
1157fa225cbcSrjs      I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
1158fa225cbcSrjs				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
1159fa225cbcSrjs      pbox++;
1160fa225cbcSrjs   }
1161fa225cbcSrjs   I810SelectBuffer(pScrn, I810_SELECT_FRONT);
1162fa225cbcSrjs
1163fa225cbcSrjs   if (pI810->AccelInfoRec)
1164fa225cbcSrjs   	pI810->AccelInfoRec->NeedToSync = TRUE;
1165fa225cbcSrjs}
1166fa225cbcSrjs
1167fa225cbcSrjs/* This routine is a modified form of XAADoBitBlt with the calls to
1168fa225cbcSrjs * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
1169fa225cbcSrjs * instead of destination. My origin is upside down so the ydir cases
1170fa225cbcSrjs * are reversed.
1171fa225cbcSrjs *
1172fa225cbcSrjs * KW: can you believe that this is called even when a 2d window moves?
1173fa225cbcSrjs */
1174fa225cbcSrjsstatic void
1175fa225cbcSrjsI810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
1176fa225cbcSrjs		   RegionPtr prgnSrc, CARD32 index)
1177fa225cbcSrjs{
1178fa225cbcSrjs   ScreenPtr pScreen = pParent->drawable.pScreen;
1179fa225cbcSrjs   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1180fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
1181fa225cbcSrjs   BoxPtr pboxTmp, pboxNext, pboxBase;
1182fa225cbcSrjs   DDXPointPtr pptTmp, pptNew2 = NULL;
1183fa225cbcSrjs   int xdir, ydir;
1184fa225cbcSrjs
1185fa225cbcSrjs   int screenwidth = pScrn->virtualX;
1186fa225cbcSrjs   int screenheight = pScrn->virtualY;
1187fa225cbcSrjs
1188fa225cbcSrjs   BoxPtr pbox = REGION_RECTS(prgnSrc);
1189fa225cbcSrjs   int nbox = REGION_NUM_RECTS(prgnSrc);
1190fa225cbcSrjs
1191fa225cbcSrjs   BoxPtr pboxNew1 = NULL;
1192fa225cbcSrjs   BoxPtr pboxNew2 = NULL;
1193fa225cbcSrjs   DDXPointPtr pptNew1 = NULL;
1194fa225cbcSrjs   DDXPointPtr pptSrc = &ptOldOrg;
1195fa225cbcSrjs
1196fa225cbcSrjs   int dx = pParent->drawable.x - ptOldOrg.x;
1197fa225cbcSrjs   int dy = pParent->drawable.y - ptOldOrg.y;
1198fa225cbcSrjs
1199fa225cbcSrjs   /* If the copy will overlap in Y, reverse the order */
1200fa225cbcSrjs   if (dy > 0) {
1201fa225cbcSrjs      ydir = -1;
1202fa225cbcSrjs
1203fa225cbcSrjs      if (nbox > 1) {
1204fa225cbcSrjs	 /* Keep ordering in each band, reverse order of bands */
1205fa225cbcSrjs	 pboxNew1 = (BoxPtr) xalloc(sizeof(BoxRec) * nbox);
1206fa225cbcSrjs	 if (!pboxNew1)
1207fa225cbcSrjs	    return;
1208fa225cbcSrjs	 pptNew1 = (DDXPointPtr) xalloc(sizeof(DDXPointRec) * nbox);
1209fa225cbcSrjs	 if (!pptNew1) {
1210fa225cbcSrjs	    xfree(pboxNew1);
1211fa225cbcSrjs	    return;
1212fa225cbcSrjs	 }
1213fa225cbcSrjs	 pboxBase = pboxNext = pbox + nbox - 1;
1214fa225cbcSrjs	 while (pboxBase >= pbox) {
1215fa225cbcSrjs	    while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
1216fa225cbcSrjs	       pboxNext--;
1217fa225cbcSrjs	    pboxTmp = pboxNext + 1;
1218fa225cbcSrjs	    pptTmp = pptSrc + (pboxTmp - pbox);
1219fa225cbcSrjs	    while (pboxTmp <= pboxBase) {
1220fa225cbcSrjs	       *pboxNew1++ = *pboxTmp++;
1221fa225cbcSrjs	       *pptNew1++ = *pptTmp++;
1222fa225cbcSrjs	    }
1223fa225cbcSrjs	    pboxBase = pboxNext;
1224fa225cbcSrjs	 }
1225fa225cbcSrjs	 pboxNew1 -= nbox;
1226fa225cbcSrjs	 pbox = pboxNew1;
1227fa225cbcSrjs	 pptNew1 -= nbox;
1228fa225cbcSrjs	 pptSrc = pptNew1;
1229fa225cbcSrjs      }
1230fa225cbcSrjs   } else {
1231fa225cbcSrjs      /* No changes required */
1232fa225cbcSrjs      ydir = 1;
1233fa225cbcSrjs   }
1234fa225cbcSrjs
1235fa225cbcSrjs   /* If the regions will overlap in X, reverse the order */
1236fa225cbcSrjs   if (dx > 0) {
1237fa225cbcSrjs      xdir = -1;
1238fa225cbcSrjs
1239fa225cbcSrjs      if (nbox > 1) {
1240fa225cbcSrjs	 /*reverse orderof rects in each band */
1241fa225cbcSrjs	 pboxNew2 = (BoxPtr) xalloc(sizeof(BoxRec) * nbox);
1242fa225cbcSrjs	 pptNew2 = (DDXPointPtr) xalloc(sizeof(DDXPointRec) * nbox);
1243fa225cbcSrjs	 if (!pboxNew2 || !pptNew2) {
1244fa225cbcSrjs	    if (pptNew2)
1245fa225cbcSrjs	       xfree(pptNew2);
1246fa225cbcSrjs	    if (pboxNew2)
1247fa225cbcSrjs	       xfree(pboxNew2);
1248fa225cbcSrjs	    if (pboxNew1) {
1249fa225cbcSrjs	       xfree(pptNew1);
1250fa225cbcSrjs	       xfree(pboxNew1);
1251fa225cbcSrjs	    }
1252fa225cbcSrjs	    return;
1253fa225cbcSrjs	 }
1254fa225cbcSrjs	 pboxBase = pboxNext = pbox;
1255fa225cbcSrjs	 while (pboxBase < pbox + nbox) {
1256fa225cbcSrjs	    while ((pboxNext < pbox + nbox) && (pboxNext->y1 == pboxBase->y1))
1257fa225cbcSrjs	       pboxNext++;
1258fa225cbcSrjs	    pboxTmp = pboxNext;
1259fa225cbcSrjs	    pptTmp = pptSrc + (pboxTmp - pbox);
1260fa225cbcSrjs	    while (pboxTmp != pboxBase) {
1261fa225cbcSrjs	       *pboxNew2++ = *--pboxTmp;
1262fa225cbcSrjs	       *pptNew2++ = *--pptTmp;
1263fa225cbcSrjs	    }
1264fa225cbcSrjs	    pboxBase = pboxNext;
1265fa225cbcSrjs	 }
1266fa225cbcSrjs	 pboxNew2 -= nbox;
1267fa225cbcSrjs	 pbox = pboxNew2;
1268fa225cbcSrjs	 pptNew2 -= nbox;
1269fa225cbcSrjs	 pptSrc = pptNew2;
1270fa225cbcSrjs      }
1271fa225cbcSrjs   } else {
1272fa225cbcSrjs      /* No changes are needed */
1273fa225cbcSrjs      xdir = 1;
1274fa225cbcSrjs   }
1275fa225cbcSrjs
1276fa225cbcSrjs   /* SelectBuffer isn't really a good concept for the i810.
1277fa225cbcSrjs    */
1278fa225cbcSrjs   I810EmitFlush(pScrn);
1279fa225cbcSrjs   I810SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);
1280fa225cbcSrjs   for (; nbox--; pbox++) {
1281fa225cbcSrjs
1282fa225cbcSrjs      int x1 = pbox->x1;
1283fa225cbcSrjs      int y1 = pbox->y1;
1284fa225cbcSrjs      int destx = x1 + dx;
1285fa225cbcSrjs      int desty = y1 + dy;
1286fa225cbcSrjs      int w = pbox->x2 - x1 + 1;
1287fa225cbcSrjs      int h = pbox->y2 - y1 + 1;
1288fa225cbcSrjs
1289fa225cbcSrjs      if (destx < 0)
1290fa225cbcSrjs	 x1 -= destx, w += destx, destx = 0;
1291fa225cbcSrjs      if (desty < 0)
1292fa225cbcSrjs	 y1 -= desty, h += desty, desty = 0;
1293fa225cbcSrjs      if (destx + w > screenwidth)
1294fa225cbcSrjs	 w = screenwidth - destx;
1295fa225cbcSrjs      if (desty + h > screenheight)
1296fa225cbcSrjs	 h = screenheight - desty;
1297fa225cbcSrjs      if (w <= 0)
1298fa225cbcSrjs	 continue;
1299fa225cbcSrjs      if (h <= 0)
1300fa225cbcSrjs	 continue;
1301fa225cbcSrjs
1302fa225cbcSrjs      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1303fa225cbcSrjs	 ErrorF("MoveBuffers %d,%d %dx%d dx: %d dy: %d\n",
1304fa225cbcSrjs		x1, y1, w, h, dx, dy);
1305fa225cbcSrjs
1306fa225cbcSrjs      I810SelectBuffer(pScrn, I810_SELECT_BACK);
1307fa225cbcSrjs      I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
1308fa225cbcSrjs      I810SelectBuffer(pScrn, I810_SELECT_DEPTH);
1309fa225cbcSrjs      I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
1310fa225cbcSrjs   }
1311fa225cbcSrjs   I810SelectBuffer(pScrn, I810_SELECT_FRONT);
1312fa225cbcSrjs   I810EmitFlush(pScrn);
1313fa225cbcSrjs
1314fa225cbcSrjs   if (pboxNew2) {
1315fa225cbcSrjs      xfree(pptNew2);
1316fa225cbcSrjs      xfree(pboxNew2);
1317fa225cbcSrjs   }
1318fa225cbcSrjs   if (pboxNew1) {
1319fa225cbcSrjs      xfree(pptNew1);
1320fa225cbcSrjs      xfree(pboxNew1);
1321fa225cbcSrjs   }
1322fa225cbcSrjs
1323fa225cbcSrjs   if (pI810->AccelInfoRec)
1324fa225cbcSrjs	pI810->AccelInfoRec->NeedToSync = TRUE;
1325fa225cbcSrjs}
1326fa225cbcSrjs
1327fa225cbcSrjs
1328fa225cbcSrjs/* Use the miext/shadow module to maintain a list of dirty rectangles.
1329fa225cbcSrjs * These are blitted to the back buffer to keep both buffers clean
1330fa225cbcSrjs * during page-flipping when the 3d application isn't fullscreen.
1331fa225cbcSrjs *
1332fa225cbcSrjs * Unlike most use of the shadow code, both buffers are in video memory.
1333fa225cbcSrjs *
1334fa225cbcSrjs * An alternative to this would be to organize for all on-screen drawing
1335fa225cbcSrjs * operations to be duplicated for the two buffers.  That might be
1336fa225cbcSrjs * faster, but seems like a lot more work...
1337fa225cbcSrjs */
1338fa225cbcSrjs
1339fa225cbcSrjs
1340fa225cbcSrjs/* This should be done *before* XAA syncs or fires its buffer.
1341fa225cbcSrjs * Otherwise will have to fire it again???
1342fa225cbcSrjs */
1343fa225cbcSrjsstatic void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
1344fa225cbcSrjs{
1345fa225cbcSrjs    I810Ptr pI810 = I810PTR(pScrn);
1346fa225cbcSrjs    int i;
1347fa225cbcSrjs    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
1348fa225cbcSrjs    unsigned int br13;
1349fa225cbcSrjs    int cpp=2;
1350fa225cbcSrjs
1351fa225cbcSrjs
1352fa225cbcSrjs    /* Don't want to do this when no 3d is active and pages are
1353fa225cbcSrjs     * right-way-round
1354fa225cbcSrjs     */
1355fa225cbcSrjs    if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
1356fa225cbcSrjs      return;
1357fa225cbcSrjs
1358fa225cbcSrjs    br13 = (pI810->auxPitch) | (0xcc << 16);
1359fa225cbcSrjs
1360fa225cbcSrjs    for (i = 0 ; i < num ; i++, pbox++) {
1361fa225cbcSrjs      unsigned int w = min(pbox->y2, pScrn->virtualY-1) - max(pbox->y1, 0) + 1;
1362fa225cbcSrjs      unsigned int h = min(pbox->x2, pScrn->virtualX-1) - max(pbox->x1, 0) + 1;
1363fa225cbcSrjs      unsigned int dst = max(pbox->x1, 0)*cpp + (max(pbox->y1, 0)*pI810->auxPitch);
1364fa225cbcSrjs
1365fa225cbcSrjs      BEGIN_LP_RING(6);
1366fa225cbcSrjs
1367fa225cbcSrjs      OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
1368fa225cbcSrjs      OUT_RING(br13);
1369fa225cbcSrjs      OUT_RING( (h<<16) | (w*cpp) );
1370fa225cbcSrjs      OUT_RING(pI810->BackBuffer.Start + dst);
1371fa225cbcSrjs      OUT_RING(br13 & 0xffff);
1372fa225cbcSrjs      OUT_RING(dst);
1373fa225cbcSrjs
1374fa225cbcSrjs      ADVANCE_LP_RING();
1375fa225cbcSrjs    }
1376fa225cbcSrjs
1377fa225cbcSrjs}
1378fa225cbcSrjs
1379fa225cbcSrjsstatic void I810EnablePageFlip(ScreenPtr pScreen)
1380fa225cbcSrjs{
1381fa225cbcSrjs    ScrnInfoPtr         pScrn      = xf86Screens[pScreen->myNum];
1382fa225cbcSrjs    I810Ptr       pI810       = I810PTR(pScrn);
1383fa225cbcSrjs    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
1384fa225cbcSrjs    int cpp=2;
1385fa225cbcSrjs    pSAREAPriv->pf_enabled = pI810->allowPageFlip;
1386fa225cbcSrjs    pSAREAPriv->pf_active = 0;
1387fa225cbcSrjs
1388fa225cbcSrjs   if (pI810->allowPageFlip) {
1389fa225cbcSrjs      unsigned int br13 = pI810->auxPitch | (0xcc << 16);
1390fa225cbcSrjs
1391fa225cbcSrjs      BEGIN_LP_RING(6);
1392fa225cbcSrjs
1393fa225cbcSrjs      OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
1394fa225cbcSrjs      OUT_RING(br13);
1395fa225cbcSrjs      OUT_RING((pScrn->virtualY << 16) | (pScrn->virtualX*cpp));
1396fa225cbcSrjs      OUT_RING(pI810->BackBuffer.Start);
1397fa225cbcSrjs      OUT_RING(br13 & 0xFFFF);
1398fa225cbcSrjs      OUT_RING(0);
1399fa225cbcSrjs      ADVANCE_LP_RING();
1400fa225cbcSrjs
1401fa225cbcSrjs      pSAREAPriv->pf_active = 1;
1402fa225cbcSrjs   }
1403fa225cbcSrjs
1404fa225cbcSrjs}
1405fa225cbcSrjs
1406fa225cbcSrjsstatic void I810DisablePageFlip(ScreenPtr pScreen)
1407fa225cbcSrjs{
1408fa225cbcSrjs    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
1409fa225cbcSrjs
1410fa225cbcSrjs    pSAREAPriv->pf_active=0;
1411fa225cbcSrjs}
1412fa225cbcSrjs
1413fa225cbcSrjsstatic void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen)
1414fa225cbcSrjs{
1415fa225cbcSrjs    /* Tell the clients not to pageflip.  How?
1416fa225cbcSrjs     *   -- Field in sarea, plus bumping the window counters.
1417fa225cbcSrjs     *   -- DRM needs to cope with Front-to-Back swapbuffers.
1418fa225cbcSrjs     */
1419fa225cbcSrjs    I810DisablePageFlip(pScreen);
1420fa225cbcSrjs}
1421fa225cbcSrjs
1422fa225cbcSrjsstatic void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen)
1423fa225cbcSrjs{
1424fa225cbcSrjs    /* Let the remaining 3d app start page flipping again */
1425fa225cbcSrjs    I810EnablePageFlip(pScreen);
1426fa225cbcSrjs}
1427fa225cbcSrjs
1428fa225cbcSrjsstatic void I810DRITransitionTo3d(ScreenPtr pScreen)
1429fa225cbcSrjs{
1430fa225cbcSrjs    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
1431fa225cbcSrjs    I810Ptr  pI810  = I810PTR(pScrn);
1432fa225cbcSrjs
1433fa225cbcSrjs    I810EnablePageFlip(pScreen);
1434fa225cbcSrjs    pI810->have3DWindows = 1;
1435fa225cbcSrjs}
1436fa225cbcSrjs
1437fa225cbcSrjsstatic void I810DRITransitionTo2d(ScreenPtr pScreen)
1438fa225cbcSrjs{
1439fa225cbcSrjs    ScrnInfoPtr         pScrn      = xf86Screens[pScreen->myNum];
1440fa225cbcSrjs    I810Ptr       pI810       = I810PTR(pScrn);
1441fa225cbcSrjs    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
1442fa225cbcSrjs
1443fa225cbcSrjs    /* Try flipping back to the front page if necessary */
1444fa225cbcSrjs    if (pSAREAPriv->pf_current_page == 1)
1445fa225cbcSrjs	drmCommandNone(pI810->drmSubFD, DRM_I810_FLIP);
1446fa225cbcSrjs
1447fa225cbcSrjs    /* Shut down shadowing if we've made it back to the front page */
1448fa225cbcSrjs    if (pSAREAPriv->pf_current_page == 0) {
1449fa225cbcSrjs	I810DisablePageFlip(pScreen);
1450fa225cbcSrjs    }
1451fa225cbcSrjs    pI810->have3DWindows = 0;
1452fa225cbcSrjs}
1453fa225cbcSrjs
1454fa225cbcSrjsBool
1455fa225cbcSrjsI810DRILeave(ScrnInfoPtr pScrn)
1456fa225cbcSrjs{
1457fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
1458fa225cbcSrjs
1459fa225cbcSrjs   if (pI810->directRenderingEnabled) {
1460fa225cbcSrjs      if (pI810->dcacheHandle != 0)
1461fa225cbcSrjs	 if (drmAgpUnbind(pI810->drmSubFD, pI810->dcacheHandle) != 0) {
1462fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1463fa225cbcSrjs	    return FALSE;
1464fa225cbcSrjs	 }
1465fa225cbcSrjs      if (pI810->backHandle != 0)
1466fa225cbcSrjs	 if (drmAgpUnbind(pI810->drmSubFD, pI810->backHandle) != 0) {
1467fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1468fa225cbcSrjs 	    return FALSE;
1469fa225cbcSrjs	 }
1470fa225cbcSrjs      if (pI810->zHandle != 0)
1471fa225cbcSrjs	 if (drmAgpUnbind(pI810->drmSubFD, pI810->zHandle) != 0) {
1472fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1473fa225cbcSrjs  	    return FALSE;
1474fa225cbcSrjs	 }
1475fa225cbcSrjs      if (pI810->sysmemHandle != 0)
1476fa225cbcSrjs	 if (drmAgpUnbind(pI810->drmSubFD, pI810->sysmemHandle) != 0) {
1477fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1478fa225cbcSrjs  	    return FALSE;
1479fa225cbcSrjs	 }
1480fa225cbcSrjs      if (pI810->xvmcHandle != 0)
1481fa225cbcSrjs	 if (drmAgpUnbind(pI810->drmSubFD, pI810->xvmcHandle) != 0) {
1482fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1483fa225cbcSrjs  	    return FALSE;
1484fa225cbcSrjs	 }
1485fa225cbcSrjs      if (pI810->cursorHandle != 0)
1486fa225cbcSrjs	 if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorHandle) != 0) {
1487fa225cbcSrjs	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1488fa225cbcSrjs	    return FALSE;
1489fa225cbcSrjs	 }
1490fa225cbcSrjs      if (pI810->cursorARGBHandle != 0)
1491fa225cbcSrjs	  if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorARGBHandle) != 0) {
1492fa225cbcSrjs	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1493fa225cbcSrjs	      return FALSE;
1494fa225cbcSrjs	  }
1495fa225cbcSrjs      if (pI810->agpAcquired == TRUE)
1496fa225cbcSrjs	 drmAgpRelease(pI810->drmSubFD);
1497fa225cbcSrjs      pI810->agpAcquired = FALSE;
1498fa225cbcSrjs   }
1499fa225cbcSrjs   return TRUE;
1500fa225cbcSrjs}
1501fa225cbcSrjs
1502fa225cbcSrjsBool
1503fa225cbcSrjsI810DRIEnter(ScrnInfoPtr pScrn)
1504fa225cbcSrjs{
1505fa225cbcSrjs   I810Ptr pI810 = I810PTR(pScrn);
1506fa225cbcSrjs
1507fa225cbcSrjs   if (pI810->directRenderingEnabled) {
1508fa225cbcSrjs
1509fa225cbcSrjs      if (pI810->agpAcquired == FALSE)
1510fa225cbcSrjs	 drmAgpAcquire(pI810->drmSubFD);
1511fa225cbcSrjs      pI810->agpAcquired = TRUE;
1512fa225cbcSrjs      if (pI810->dcacheHandle != 0)
1513fa225cbcSrjs	 if (drmAgpBind(pI810->drmSubFD, pI810->dcacheHandle,
1514fa225cbcSrjs			pI810->DepthOffset) != 0)
1515fa225cbcSrjs	    return FALSE;
1516fa225cbcSrjs      if (pI810->backHandle != 0)
1517fa225cbcSrjs	 if (drmAgpBind(pI810->drmSubFD, pI810->backHandle,
1518fa225cbcSrjs			pI810->BackOffset) != 0)
1519fa225cbcSrjs	    return FALSE;
1520fa225cbcSrjs      if (pI810->zHandle != 0)
1521fa225cbcSrjs	 if (drmAgpBind(pI810->drmSubFD, pI810->zHandle,
1522fa225cbcSrjs			pI810->DepthOffset) != 0)
1523fa225cbcSrjs	    return FALSE;
1524fa225cbcSrjs      if (pI810->sysmemHandle != 0)
1525fa225cbcSrjs	 if (drmAgpBind(pI810->drmSubFD, pI810->sysmemHandle, 0) != 0)
1526fa225cbcSrjs	    return FALSE;
1527fa225cbcSrjs      if (pI810->xvmcHandle != 0)
1528fa225cbcSrjs	 if (drmAgpBind(pI810->drmSubFD, pI810->xvmcHandle,
1529fa225cbcSrjs			pI810->MC.Start) != 0)
1530fa225cbcSrjs	    return FALSE;
1531fa225cbcSrjs      if (pI810->cursorHandle != 0)
1532fa225cbcSrjs	 if (drmAgpBind(pI810->drmSubFD, pI810->cursorHandle,
1533fa225cbcSrjs			pI810->CursorStart) != 0)
1534fa225cbcSrjs	    return FALSE;
1535fa225cbcSrjs      if (pI810->cursorARGBHandle != 0)
1536fa225cbcSrjs	 if (drmAgpBind(pI810->drmSubFD, pI810->cursorARGBHandle,
1537fa225cbcSrjs			pI810->CursorARGBStart) != 0)
1538fa225cbcSrjs	    return FALSE;
1539fa225cbcSrjs   }
1540fa225cbcSrjs   return TRUE;
1541fa225cbcSrjs}
1542