1428d7b3dSmrg#ifdef HAVE_CONFIG_H
2428d7b3dSmrg#include "config.h"
3428d7b3dSmrg#endif
4428d7b3dSmrg
5428d7b3dSmrg#include <errno.h>
6428d7b3dSmrg#include <stdio.h>
7428d7b3dSmrg#include <string.h>
8428d7b3dSmrg#include <assert.h>
9428d7b3dSmrg
10428d7b3dSmrg#include "xorg-server.h"
11428d7b3dSmrg#include "xf86.h"
12428d7b3dSmrg#include "xf86_OSproc.h"
13428d7b3dSmrg
14428d7b3dSmrg#include "xf86Pci.h"
15428d7b3dSmrg
16428d7b3dSmrg#include "windowstr.h"
17428d7b3dSmrg#include "shadow.h"
18428d7b3dSmrg#include "shadowfb.h"
19428d7b3dSmrg
20428d7b3dSmrg#include "i810.h"
21428d7b3dSmrg#include "i810_dri.h"
22428d7b3dSmrg
23428d7b3dSmrgstatic char I810KernelDriverName[] = "i810";
24428d7b3dSmrgstatic char I810ClientDriverName[] = "i810";
25428d7b3dSmrg
26428d7b3dSmrgstatic Bool I810CreateContext(ScreenPtr pScreen, VisualPtr visual,
27428d7b3dSmrg			      drm_context_t hwContext, void *pVisualConfigPriv,
28428d7b3dSmrg			      DRIContextType contextStore);
29428d7b3dSmrgstatic void I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
30428d7b3dSmrg			       DRIContextType contextStore);
31428d7b3dSmrgstatic void I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
32428d7b3dSmrg			       DRIContextType readContextType,
33428d7b3dSmrg			       void *readContextStore,
34428d7b3dSmrg			       DRIContextType writeContextType,
35428d7b3dSmrg			       void *writeContextStore);
36428d7b3dSmrgstatic void I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
37428d7b3dSmrgstatic void I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
38428d7b3dSmrg			       RegionPtr prgnSrc, CARD32 index);
39428d7b3dSmrg
40428d7b3dSmrg
41428d7b3dSmrgstatic void I810EnablePageFlip(ScreenPtr pScreen);
42428d7b3dSmrgstatic void I810DisablePageFlip(ScreenPtr pScreen);
43428d7b3dSmrgstatic void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen);
44428d7b3dSmrgstatic void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen);
45428d7b3dSmrgstatic void I810DRITransitionTo3d(ScreenPtr pScreen);
46428d7b3dSmrgstatic void I810DRITransitionTo2d(ScreenPtr pScreen);
47428d7b3dSmrg
48428d7b3dSmrgstatic void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
49428d7b3dSmrg
50428d7b3dSmrgstatic int i810_pitches[] = {
51428d7b3dSmrg   512,
52428d7b3dSmrg   1024,
53428d7b3dSmrg   2048,
54428d7b3dSmrg   4096,
55428d7b3dSmrg   0
56428d7b3dSmrg};
57428d7b3dSmrg
58428d7b3dSmrgstatic int i810_pitch_flags[] = {
59428d7b3dSmrg   0x0,
60428d7b3dSmrg   0x1,
61428d7b3dSmrg   0x2,
62428d7b3dSmrg   0x3,
63428d7b3dSmrg   0
64428d7b3dSmrg};
65428d7b3dSmrg
66428d7b3dSmrgstatic unsigned int i810_drm_version = 0;
67428d7b3dSmrg
68428d7b3dSmrgBool
69428d7b3dSmrgI810CleanupDma(ScrnInfoPtr pScrn)
70428d7b3dSmrg{
71428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
72428d7b3dSmrg   drmI810Init info;
73428d7b3dSmrg
74428d7b3dSmrg   memset(&info, 0, sizeof(drmI810Init));
75428d7b3dSmrg   info.func = I810_CLEANUP_DMA;
76428d7b3dSmrg
77428d7b3dSmrg   if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
78428d7b3dSmrg		       &info, sizeof(drmI810Init))) {
79428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
80428d7b3dSmrg		 "[dri] I810 Dma Cleanup Failed\n");
81428d7b3dSmrg      return FALSE;
82428d7b3dSmrg   }
83428d7b3dSmrg
84428d7b3dSmrg   return TRUE;
85428d7b3dSmrg}
86428d7b3dSmrg
87428d7b3dSmrgBool
88428d7b3dSmrgI810InitDma(ScrnInfoPtr pScrn)
89428d7b3dSmrg{
90428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
91428d7b3dSmrg   I810RingBuffer *ring = pI810->LpRing;
92428d7b3dSmrg   I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
93428d7b3dSmrg   drmI810Init info;
94428d7b3dSmrg
95428d7b3dSmrg   memset(&info, 0, sizeof(drmI810Init));
96428d7b3dSmrg
97428d7b3dSmrg   info.ring_start = ring->mem.Start;
98428d7b3dSmrg   info.ring_end = ring->mem.End;
99428d7b3dSmrg   info.ring_size = ring->mem.Size;
100428d7b3dSmrg   info.mmio_offset = (unsigned int)pI810DRI->regs;
101428d7b3dSmrg   info.buffers_offset = (unsigned int)pI810->buffer_map;
102428d7b3dSmrg   info.sarea_priv_offset = sizeof(XF86DRISAREARec);
103428d7b3dSmrg
104428d7b3dSmrg   info.front_offset = 0;
105428d7b3dSmrg   info.back_offset = pI810->BackBuffer.Start;
106428d7b3dSmrg   info.depth_offset = pI810->DepthBuffer.Start;
107428d7b3dSmrg   info.overlay_offset = pI810->OverlayStart;
108428d7b3dSmrg   info.overlay_physical = pI810->OverlayPhysical;
109428d7b3dSmrg   info.w = pScrn->virtualX;
110428d7b3dSmrg   info.h = pScrn->virtualY;
111428d7b3dSmrg   info.pitch = pI810->auxPitch;
112428d7b3dSmrg   info.pitch_bits = pI810->auxPitchBits;
113428d7b3dSmrg
114428d7b3dSmrg   /* We require DRM v1.2 or greater. Since DRM v1.2 broke compatibility
115428d7b3dSmrg    * we created a new v1.4 that supports a new init function. Eventually the
116428d7b3dSmrg    * old init function will go away. If you change the drm interface, make a
117428d7b3dSmrg    * new init type too so that we can detect the new client.
118428d7b3dSmrg    */
119428d7b3dSmrg   switch(i810_drm_version) {
120428d7b3dSmrg   case ((1<<16) | 0):
121428d7b3dSmrg   case ((1<<16) | 1):
122428d7b3dSmrg   case ((1<<16) | 2):
123428d7b3dSmrg   case ((1<<16) | 3):
124428d7b3dSmrg      /* Use OLD drm < 1.4 init */
125428d7b3dSmrg      info.func = I810_INIT_DMA;
126428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init PRE v1.4 interface.\n");
127428d7b3dSmrg      break;
128428d7b3dSmrg   default:
129428d7b3dSmrg   case ((1<<16) | 4):
130428d7b3dSmrg      /*  DRM version 1.3 or greater init */
131428d7b3dSmrg      info.func = I810_INIT_DMA_1_4;
132428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init v1.4 interface.\n");
133428d7b3dSmrg      break;
134428d7b3dSmrg   }
135428d7b3dSmrg
136428d7b3dSmrg   if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
137428d7b3dSmrg		       &info, sizeof(drmI810Init))) {
138428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
139428d7b3dSmrg		 "[drm] I810 Dma Initialization failed.\n");
140428d7b3dSmrg      return FALSE;
141428d7b3dSmrg   }
142428d7b3dSmrg
143428d7b3dSmrg   return TRUE;
144428d7b3dSmrg}
145428d7b3dSmrg
146428d7b3dSmrgstatic unsigned int
147428d7b3dSmrgmylog2(unsigned int n)
148428d7b3dSmrg{
149428d7b3dSmrg   unsigned int log2 = 1;
150428d7b3dSmrg
151428d7b3dSmrg   while (n > 1)
152428d7b3dSmrg      n >>= 1, log2++;
153428d7b3dSmrg   return log2;
154428d7b3dSmrg}
155428d7b3dSmrg
156428d7b3dSmrgBool
157428d7b3dSmrgI810DRIScreenInit(ScreenPtr pScreen)
158428d7b3dSmrg{
159428d7b3dSmrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
160428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
161428d7b3dSmrg   DRIInfoPtr pDRIInfo;
162428d7b3dSmrg   I810DRIPtr pI810DRI;
163428d7b3dSmrg   unsigned long tom;
164428d7b3dSmrg   drm_handle_t agpHandle;
165428d7b3dSmrg   drm_handle_t dcacheHandle;
166428d7b3dSmrg   int sysmem_size = 0;
167428d7b3dSmrg   int back_size = 0;
168428d7b3dSmrg   unsigned int pitch_idx = 0;
169428d7b3dSmrg   int bufs;
170428d7b3dSmrg   int width = pScrn->displayWidth * pI810->cpp;
171428d7b3dSmrg   int i;
172428d7b3dSmrg
173428d7b3dSmrg   /* Hardware 3D rendering only implemented for 16bpp */
174428d7b3dSmrg   /* And it only works for 5:6:5 (Mark) */
175428d7b3dSmrg   if (pScrn->depth != 16)
176428d7b3dSmrg      return FALSE;
177428d7b3dSmrg
178428d7b3dSmrg   /* Check that the DRI, and DRM modules have been loaded by testing
179428d7b3dSmrg    * for known symbols in each module. */
180428d7b3dSmrg   if (!xf86LoaderCheckSymbol("drmAvailable"))
181428d7b3dSmrg      return FALSE;
182428d7b3dSmrg   if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
183428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
184428d7b3dSmrg		 "[dri] I810DRIScreenInit failed (libdri.a too old)\n");
185428d7b3dSmrg      return FALSE;
186428d7b3dSmrg   }
187428d7b3dSmrg
188428d7b3dSmrg   /* adjust width first */
189428d7b3dSmrg#define Elements(x) sizeof(x)/sizeof(*x)
190428d7b3dSmrg   for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++)
191428d7b3dSmrg      if (width <= i810_pitches[pitch_idx])
192428d7b3dSmrg	 break;
193428d7b3dSmrg
194428d7b3dSmrg   if (pitch_idx == Elements(i810_pitches)) {
195428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
196428d7b3dSmrg		 "[dri] Couldn't find depth/back buffer pitch");
197428d7b3dSmrg      DRICloseScreen(pScreen);
198428d7b3dSmrg      return FALSE;
199428d7b3dSmrg   } else {
200428d7b3dSmrg      /* for tiled memory to work, the buffer needs to have the
201428d7b3dSmrg       * number of lines as a multiple of 16 (the tile size),
202428d7b3dSmrg       *  - airlied */
203428d7b3dSmrg      int lines = (pScrn->virtualY + 15) / 16 * 16;
204428d7b3dSmrg      back_size = i810_pitches[pitch_idx] * lines;
205428d7b3dSmrg      back_size = ((back_size + 4096 - 1) / 4096) * 4096;
206428d7b3dSmrg   }
207428d7b3dSmrg
208428d7b3dSmrg   pScrn->displayWidth = i810_pitches[pitch_idx] / pI810->cpp;
209428d7b3dSmrg
210428d7b3dSmrg   /* Check the DRI version */
211428d7b3dSmrg   {
212428d7b3dSmrg      int major, minor, patch;
213428d7b3dSmrg
214428d7b3dSmrg      DRIQueryVersion(&major, &minor, &patch);
215428d7b3dSmrg      if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
216428d7b3dSmrg	 xf86DrvMsg(pScreen->myNum, X_ERROR,
217428d7b3dSmrg		    "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
218428d7b3dSmrg		    "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n"
219428d7b3dSmrg		    "[dri] Disabling DRI.\n", major, minor, patch,
220428d7b3dSmrg                    DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
221428d7b3dSmrg	 return FALSE;
222428d7b3dSmrg      }
223428d7b3dSmrg   }
224428d7b3dSmrg
225428d7b3dSmrg   pDRIInfo = DRICreateInfoRec();
226428d7b3dSmrg   if (!pDRIInfo) {
227428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
228428d7b3dSmrg		 "[dri] DRICreateInfoRec failed.  Disabling DRI.\n");
229428d7b3dSmrg      return FALSE;
230428d7b3dSmrg   }
231428d7b3dSmrg
232428d7b3dSmrg/*     pDRIInfo->wrap.ValidateTree = 0;    */
233428d7b3dSmrg/*     pDRIInfo->wrap.PostValidateTree = 0;    */
234428d7b3dSmrg
235428d7b3dSmrg   pI810->pDRIInfo = pDRIInfo;
236428d7b3dSmrg   pI810->LockHeld = 0;
237428d7b3dSmrg
238428d7b3dSmrg   pDRIInfo->drmDriverName = I810KernelDriverName;
239428d7b3dSmrg   pDRIInfo->clientDriverName = I810ClientDriverName;
240428d7b3dSmrg   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
241428d7b3dSmrg      pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo);
242428d7b3dSmrg   } else {
243428d7b3dSmrg      pDRIInfo->busIdString = malloc(64);
244428d7b3dSmrg      if (pDRIInfo->busIdString)
245428d7b3dSmrg	 sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
246428d7b3dSmrg		 ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus),
247428d7b3dSmrg		 pI810->PciInfo->dev, pI810->PciInfo->func
248428d7b3dSmrg		);
249428d7b3dSmrg   }
250428d7b3dSmrg   if (!pDRIInfo->busIdString) {
251428d7b3dSmrg      DRIDestroyInfoRec(pI810->pDRIInfo);
252428d7b3dSmrg      pI810->pDRIInfo = NULL;
253428d7b3dSmrg      return FALSE;
254428d7b3dSmrg   }
255428d7b3dSmrg   pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION;
256428d7b3dSmrg   pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION;
257428d7b3dSmrg   pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL;
258428d7b3dSmrg   pDRIInfo->frameBufferPhysicalAddress = (pointer) pI810->LinearAddr;
259428d7b3dSmrg   pDRIInfo->frameBufferSize = (((pScrn->displayWidth *
260428d7b3dSmrg				  pScrn->virtualY * pI810->cpp) +
261428d7b3dSmrg				 4096 - 1) / 4096) * 4096;
262428d7b3dSmrg
263428d7b3dSmrg   pDRIInfo->frameBufferStride = pScrn->displayWidth * pI810->cpp;
264428d7b3dSmrg   pDRIInfo->ddxDrawableTableEntry = I810_MAX_DRAWABLES;
265428d7b3dSmrg
266428d7b3dSmrg   if (SAREA_MAX_DRAWABLES < I810_MAX_DRAWABLES)
267428d7b3dSmrg      pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
268428d7b3dSmrg   else
269428d7b3dSmrg      pDRIInfo->maxDrawableTableEntry = I810_MAX_DRAWABLES;
270428d7b3dSmrg
271428d7b3dSmrg   /* For now the mapping works by using a fixed size defined
272428d7b3dSmrg    * in the SAREA header
273428d7b3dSmrg    */
274428d7b3dSmrg   if (sizeof(XF86DRISAREARec) + sizeof(I810SAREARec) > SAREA_MAX) {
275428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
276428d7b3dSmrg		 "[dri] Data does not fit in SAREA\n");
277428d7b3dSmrg      return FALSE;
278428d7b3dSmrg   }
279428d7b3dSmrg   pDRIInfo->SAREASize = SAREA_MAX;
280428d7b3dSmrg
281428d7b3dSmrg   if (!(pI810DRI = (I810DRIPtr) calloc(sizeof(I810DRIRec), 1))) {
282428d7b3dSmrg      DRIDestroyInfoRec(pI810->pDRIInfo);
283428d7b3dSmrg      pI810->pDRIInfo = NULL;
284428d7b3dSmrg      return FALSE;
285428d7b3dSmrg   }
286428d7b3dSmrg   pDRIInfo->devPrivate = pI810DRI;
287428d7b3dSmrg   pDRIInfo->devPrivateSize = sizeof(I810DRIRec);
288428d7b3dSmrg   pDRIInfo->contextSize = sizeof(I810DRIContextRec);
289428d7b3dSmrg
290428d7b3dSmrg   pDRIInfo->CreateContext = I810CreateContext;
291428d7b3dSmrg   pDRIInfo->DestroyContext = I810DestroyContext;
292428d7b3dSmrg   pDRIInfo->SwapContext = I810DRISwapContext;
293428d7b3dSmrg   pDRIInfo->InitBuffers = I810DRIInitBuffers;
294428d7b3dSmrg   pDRIInfo->MoveBuffers = I810DRIMoveBuffers;
295428d7b3dSmrg   pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
296428d7b3dSmrg   pDRIInfo->TransitionTo2d = I810DRITransitionTo2d;
297428d7b3dSmrg   pDRIInfo->TransitionTo3d = I810DRITransitionTo3d;
298428d7b3dSmrg   pDRIInfo->TransitionSingleToMulti3D = I810DRITransitionSingleToMulti3d;
299428d7b3dSmrg   pDRIInfo->TransitionMultiToSingle3D = I810DRITransitionMultiToSingle3d;
300428d7b3dSmrg
301428d7b3dSmrg   pDRIInfo->createDummyCtx = TRUE;
302428d7b3dSmrg   pDRIInfo->createDummyCtxPriv = FALSE;
303428d7b3dSmrg
304428d7b3dSmrg   /* This adds the framebuffer as a drm map *before* we have asked agp
305428d7b3dSmrg    * to allocate it.  Scary stuff, hold on...
306428d7b3dSmrg    */
307428d7b3dSmrg   if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) {
308428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
309428d7b3dSmrg		 "[dri] DRIScreenInit failed.  Disabling DRI.\n");
310428d7b3dSmrg      free(pDRIInfo->devPrivate);
311428d7b3dSmrg      pDRIInfo->devPrivate = NULL;
312428d7b3dSmrg      DRIDestroyInfoRec(pI810->pDRIInfo);
313428d7b3dSmrg      pI810->pDRIInfo = NULL;
314428d7b3dSmrg      return FALSE;
315428d7b3dSmrg   }
316428d7b3dSmrg
317428d7b3dSmrg   /* Check the i810 DRM versioning */
318428d7b3dSmrg   {
319428d7b3dSmrg      drmVersionPtr version;
320428d7b3dSmrg
321428d7b3dSmrg      /* Check the DRM lib version.
322428d7b3dSmrg       * drmGetLibVersion was not supported in version 1.0, so check for
323428d7b3dSmrg       * symbol first to avoid possible crash or hang.
324428d7b3dSmrg       */
325428d7b3dSmrg      if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
326428d7b3dSmrg	 version = drmGetLibVersion(pI810->drmSubFD);
327428d7b3dSmrg      } else
328428d7b3dSmrg      {
329428d7b3dSmrg	 /* drmlib version 1.0.0 didn't have the drmGetLibVersion
330428d7b3dSmrg	  * entry point.  Fake it by allocating a version record
331428d7b3dSmrg	  * via drmGetVersion and changing it to version 1.0.0
332428d7b3dSmrg	  */
333428d7b3dSmrg	 version = drmGetVersion(pI810->drmSubFD);
334428d7b3dSmrg	 version->version_major = 1;
335428d7b3dSmrg	 version->version_minor = 0;
336428d7b3dSmrg	 version->version_patchlevel = 0;
337428d7b3dSmrg      }
338428d7b3dSmrg
339428d7b3dSmrg#define REQ_MAJ 1
340428d7b3dSmrg#define REQ_MIN 1
341428d7b3dSmrg      if (version) {
342428d7b3dSmrg	 if (version->version_major != REQ_MAJ ||
343428d7b3dSmrg	     version->version_minor < REQ_MIN) {
344428d7b3dSmrg	    /* incompatible drm library version */
345428d7b3dSmrg	    xf86DrvMsg(pScreen->myNum, X_ERROR,
346428d7b3dSmrg		       "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
347428d7b3dSmrg		       "[dri] libdrm.a module version is %d.%d.%d but version %d.%d.x is needed.\n"
348428d7b3dSmrg		       "[dri] Disabling DRI.\n",
349428d7b3dSmrg		       version->version_major,
350428d7b3dSmrg		       version->version_minor, version->version_patchlevel,
351428d7b3dSmrg		       REQ_MAJ, REQ_MIN);
352428d7b3dSmrg	    drmFreeVersion(version);
353428d7b3dSmrg	    I810DRICloseScreen(pScreen);
354428d7b3dSmrg	    return FALSE;
355428d7b3dSmrg	 }
356428d7b3dSmrg	 drmFreeVersion(version);
357428d7b3dSmrg      }
358428d7b3dSmrg
359428d7b3dSmrg      /* Check the i810 DRM version */
360428d7b3dSmrg      version = drmGetVersion(pI810->drmSubFD);
361428d7b3dSmrg      if (version) {
362428d7b3dSmrg	i810_drm_version = (version->version_major<<16) |
363428d7b3dSmrg	                    version->version_minor;
364428d7b3dSmrg	 if (version->version_major != 1 || version->version_minor < 2) {
365428d7b3dSmrg	    /* incompatible drm version */
366428d7b3dSmrg	    xf86DrvMsg(pScreen->myNum, X_ERROR,
367428d7b3dSmrg		       "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
368428d7b3dSmrg		       "[dri] i810.o kernel module version is %d.%d.%d but version 1.2.0 or greater is needed.\n"
369428d7b3dSmrg		       "[dri] Disabling DRI.\n",
370428d7b3dSmrg		       version->version_major,
371428d7b3dSmrg		       version->version_minor, version->version_patchlevel);
372428d7b3dSmrg	    I810DRICloseScreen(pScreen);
373428d7b3dSmrg	    drmFreeVersion(version);
374428d7b3dSmrg	    return FALSE;
375428d7b3dSmrg	 }
376428d7b3dSmrg         pI810->drmMinor = version->version_minor;
377428d7b3dSmrg	 drmFreeVersion(version);
378428d7b3dSmrg      }
379428d7b3dSmrg   }
380428d7b3dSmrg
381428d7b3dSmrg   pI810DRI->regsSize = I810_REG_SIZE;
382428d7b3dSmrg   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->MMIOAddr,
383428d7b3dSmrg		 pI810DRI->regsSize, DRM_REGISTERS, 0,
384428d7b3dSmrg		 (drmAddress) &pI810DRI->regs) < 0) {
385428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n");
386428d7b3dSmrg      DRICloseScreen(pScreen);
387428d7b3dSmrg      return FALSE;
388428d7b3dSmrg   }
389428d7b3dSmrg   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
390428d7b3dSmrg	      (int)pI810DRI->regs);
391428d7b3dSmrg
392428d7b3dSmrg   pI810->backHandle = DRM_AGP_NO_HANDLE;
393428d7b3dSmrg   pI810->zHandle = DRM_AGP_NO_HANDLE;
394428d7b3dSmrg   pI810->cursorHandle = DRM_AGP_NO_HANDLE;
395428d7b3dSmrg   pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
396428d7b3dSmrg   pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
397428d7b3dSmrg   pI810->agpAcquired = FALSE;
398428d7b3dSmrg   pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
399428d7b3dSmrg
400428d7b3dSmrg   /* Agp Support - Need this just to get the framebuffer.
401428d7b3dSmrg    */
402428d7b3dSmrg   if (drmAgpAcquire(pI810->drmSubFD) < 0) {
403428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpAquire failed\n");
404428d7b3dSmrg      DRICloseScreen(pScreen);
405428d7b3dSmrg      return FALSE;
406428d7b3dSmrg   }
407428d7b3dSmrg   pI810->agpAcquired = TRUE;
408428d7b3dSmrg
409428d7b3dSmrg   if (drmAgpEnable(pI810->drmSubFD, 0) < 0) {
410428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpEnable failed\n");
411428d7b3dSmrg      DRICloseScreen(pScreen);
412428d7b3dSmrg      return FALSE;
413428d7b3dSmrg   }
414428d7b3dSmrg
415428d7b3dSmrg   memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
416428d7b3dSmrg   memset(&pI810->BackBuffer, 0, sizeof(I810MemRange));
417428d7b3dSmrg   memset(&pI810->DepthBuffer, 0, sizeof(I810MemRange));
418428d7b3dSmrg   pI810->CursorPhysical = 0;
419428d7b3dSmrg   pI810->CursorARGBPhysical = 0;
420428d7b3dSmrg
421428d7b3dSmrg   /* Dcache - half the speed of normal ram, but has use as a Z buffer
422428d7b3dSmrg    * under the DRI.
423428d7b3dSmrg    */
424428d7b3dSmrg
425428d7b3dSmrg   drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL,
426428d7b3dSmrg	       (drmAddress) &dcacheHandle);
427428d7b3dSmrg   pI810->dcacheHandle = dcacheHandle;
428428d7b3dSmrg
429428d7b3dSmrg   xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : 0x%x\n",
430428d7b3dSmrg	      (int)dcacheHandle);
431428d7b3dSmrg
432428d7b3dSmrg   sysmem_size = pScrn->videoRam * 1024;
433428d7b3dSmrg   if (dcacheHandle != DRM_AGP_NO_HANDLE) {
434428d7b3dSmrg      if (back_size > 4 * 1024 * 1024) {
435428d7b3dSmrg	 xf86DrvMsg(pScreen->myNum, X_INFO,
436428d7b3dSmrg		    "[dri] Backsize is larger then 4 meg\n");
437428d7b3dSmrg	 sysmem_size = sysmem_size - 2 * back_size;
438428d7b3dSmrg	 drmAgpFree(pI810->drmSubFD, dcacheHandle);
439428d7b3dSmrg	 pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
440428d7b3dSmrg      } else {
441428d7b3dSmrg	 sysmem_size = sysmem_size - back_size;
442428d7b3dSmrg      }
443428d7b3dSmrg   } else {
444428d7b3dSmrg      sysmem_size = sysmem_size - 2 * back_size;
445428d7b3dSmrg   }
446428d7b3dSmrg
447428d7b3dSmrg   /* Max size is 48 without XvMC, 41 with 6 surfaces, 40 with 7 surfaces */
448428d7b3dSmrg   if (pI810->numSurfaces && (pI810->numSurfaces == 6)) {
449428d7b3dSmrg      if (sysmem_size > (pI810->FbMapSize - 7 * 1024 * 1024)) {
450428d7b3dSmrg	 sysmem_size = (pI810->FbMapSize - 7 * 1024 * 1024);
451428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
452428d7b3dSmrg		    "User requested more memory then fits in the agp aperture\n"
453428d7b3dSmrg		    "Truncating to %d bytes of memory\n", sysmem_size);
454428d7b3dSmrg      }
455428d7b3dSmrg   }
456428d7b3dSmrg   if (pI810->numSurfaces && (pI810->numSurfaces == 7)) {
457428d7b3dSmrg      if (sysmem_size > (pI810->FbMapSize - 8 * 1024 * 1024)) {
458428d7b3dSmrg	 sysmem_size = (pI810->FbMapSize - 8 * 1024 * 1024);
459428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
460428d7b3dSmrg		    "User requested more memory then fits in the agp aperture\n"
461428d7b3dSmrg		    "Truncating to %d bytes of memory\n", sysmem_size);
462428d7b3dSmrg      }
463428d7b3dSmrg   }
464428d7b3dSmrg
465428d7b3dSmrg   if (sysmem_size > pI810->FbMapSize) {
466428d7b3dSmrg      sysmem_size = pI810->FbMapSize;
467428d7b3dSmrg
468428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
469428d7b3dSmrg		 "[dri] User requested more memory then fits in the agp"
470428d7b3dSmrg		 " aperture\n\tTruncating to %d bytes of memory\n",
471428d7b3dSmrg		 sysmem_size);
472428d7b3dSmrg   }
473428d7b3dSmrg
474428d7b3dSmrg   sysmem_size -= 4096;			/* remove 4k for the hw cursor */
475428d7b3dSmrg   sysmem_size -= 16384;		/* remove 16k for the ARGB hw cursor */
476428d7b3dSmrg
477428d7b3dSmrg   pI810->SysMem.Start = 0;
478428d7b3dSmrg   pI810->SysMem.Size = sysmem_size;
479428d7b3dSmrg   pI810->SysMem.End = sysmem_size;
480428d7b3dSmrg   tom = sysmem_size;
481428d7b3dSmrg
482428d7b3dSmrg   pI810->SavedSysMem = pI810->SysMem;
483428d7b3dSmrg
484428d7b3dSmrg   if (dcacheHandle != DRM_AGP_NO_HANDLE) {
485428d7b3dSmrg      if (drmAgpBind(pI810->drmSubFD, dcacheHandle, pI810->DepthOffset) == 0) {
486428d7b3dSmrg	 memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
487428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
488428d7b3dSmrg		    "[agp] GART: Found 4096K Z buffer memory\n");
489428d7b3dSmrg	 pI810->DcacheMem.Start = pI810->DepthOffset;
490428d7b3dSmrg	 pI810->DcacheMem.Size = 1024 * 4096;
491428d7b3dSmrg	 pI810->DcacheMem.End =
492428d7b3dSmrg	       pI810->DcacheMem.Start + pI810->DcacheMem.Size;
493428d7b3dSmrg	 if (!I810AllocLow
494428d7b3dSmrg	     (&(pI810->DepthBuffer), &(pI810->DcacheMem), back_size)) {
495428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
496428d7b3dSmrg		       "[agp] Depth buffer allocation failed\n");
497428d7b3dSmrg	    DRICloseScreen(pScreen);
498428d7b3dSmrg	    return FALSE;
499428d7b3dSmrg	 }
500428d7b3dSmrg      } else {
501428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
502428d7b3dSmrg		    "[agp] GART: dcache bind failed\n");
503428d7b3dSmrg	 drmAgpFree(pI810->drmSubFD, dcacheHandle);
504428d7b3dSmrg	 pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
505428d7b3dSmrg      }
506428d7b3dSmrg   } else {
507428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
508428d7b3dSmrg		 "[agp] GART: no dcache memory found\n");
509428d7b3dSmrg   }
510428d7b3dSmrg
511428d7b3dSmrg   drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL,
512428d7b3dSmrg	       (drmAddress) &agpHandle);
513428d7b3dSmrg   pI810->backHandle = agpHandle;
514428d7b3dSmrg
515428d7b3dSmrg   if (agpHandle != DRM_AGP_NO_HANDLE) {
516428d7b3dSmrg      if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->BackOffset) == 0) {
517428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
518428d7b3dSmrg		    "[agp] Bound backbuffer memory\n");
519428d7b3dSmrg
520428d7b3dSmrg	 pI810->BackBuffer.Start = pI810->BackOffset;
521428d7b3dSmrg	 pI810->BackBuffer.Size = back_size;
522428d7b3dSmrg	 pI810->BackBuffer.End = (pI810->BackBuffer.Start +
523428d7b3dSmrg				  pI810->BackBuffer.Size);
524428d7b3dSmrg      } else {
525428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
526428d7b3dSmrg		    "[agp] Unable to bind backbuffer.  Disabling DRI.\n");
527428d7b3dSmrg	 DRICloseScreen(pScreen);
528428d7b3dSmrg	 return FALSE;
529428d7b3dSmrg      }
530428d7b3dSmrg   } else {
531428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
532428d7b3dSmrg		 "[dri] Unable to allocate backbuffer memory.  Disabling DRI.\n");
533428d7b3dSmrg      DRICloseScreen(pScreen);
534428d7b3dSmrg      return FALSE;
535428d7b3dSmrg   }
536428d7b3dSmrg
537428d7b3dSmrg   if (dcacheHandle == DRM_AGP_NO_HANDLE) {
538428d7b3dSmrg     drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL,
539428d7b3dSmrg		 (drmAddress) &agpHandle);
540428d7b3dSmrg
541428d7b3dSmrg      pI810->zHandle = agpHandle;
542428d7b3dSmrg
543428d7b3dSmrg      if (agpHandle != DRM_AGP_NO_HANDLE) {
544428d7b3dSmrg	 if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->DepthOffset) == 0) {
545428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
546428d7b3dSmrg		       "[agp] Bound depthbuffer memory\n");
547428d7b3dSmrg	    pI810->DepthBuffer.Start = pI810->DepthOffset;
548428d7b3dSmrg	    pI810->DepthBuffer.Size = back_size;
549428d7b3dSmrg	    pI810->DepthBuffer.End = (pI810->DepthBuffer.Start +
550428d7b3dSmrg				      pI810->DepthBuffer.Size);
551428d7b3dSmrg	 } else {
552428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
553428d7b3dSmrg		       "[agp] Unable to bind depthbuffer.  Disabling DRI.\n");
554428d7b3dSmrg	    DRICloseScreen(pScreen);
555428d7b3dSmrg	    return FALSE;
556428d7b3dSmrg	 }
557428d7b3dSmrg      } else {
558428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
559428d7b3dSmrg		    "[agp] Unable to allocate depthbuffer memory.  Disabling DRI.\n");
560428d7b3dSmrg	 DRICloseScreen(pScreen);
561428d7b3dSmrg	 return FALSE;
562428d7b3dSmrg      }
563428d7b3dSmrg   }
564428d7b3dSmrg
565428d7b3dSmrg   /* Now allocate and bind the agp space.  This memory will include the
566428d7b3dSmrg    * regular framebuffer as well as texture memory.
567428d7b3dSmrg    */
568428d7b3dSmrg   drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL,
569428d7b3dSmrg	       (drmAddress)&agpHandle);
570428d7b3dSmrg   pI810->sysmemHandle = agpHandle;
571428d7b3dSmrg
572428d7b3dSmrg   if (agpHandle != DRM_AGP_NO_HANDLE) {
573428d7b3dSmrg      if (drmAgpBind(pI810->drmSubFD, agpHandle, 0) == 0) {
574428d7b3dSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
575428d7b3dSmrg		   "[agp] Bound System Texture Memory\n");
576428d7b3dSmrg      } else {
577428d7b3dSmrg          xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to bind system texture memory. Disabling DRI.\n");
578428d7b3dSmrg	  DRICloseScreen(pScreen);
579428d7b3dSmrg	  return FALSE;
580428d7b3dSmrg      }
581428d7b3dSmrg   } else {
582428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to allocate system texture memory. Disabling DRI.\n");
583428d7b3dSmrg      DRICloseScreen(pScreen);
584428d7b3dSmrg      return FALSE;
585428d7b3dSmrg   }
586428d7b3dSmrg
587428d7b3dSmrg/* Allocate 7 or 8MB for XvMC this is setup as follows to best use tiled
588428d7b3dSmrg   regions and required surface pitches. (Numbers are adjusted if the
589428d7b3dSmrg   AGP region is only 32MB
590428d7b3dSmrg   For numSurfaces == 6
591428d7b3dSmrg   44 - 48MB = 4MB Fence, 8 Tiles wide
592428d7b3dSmrg   43 - 44MB = 1MB Fence, 8 Tiles wide
593428d7b3dSmrg   42 - 43MB = 1MB Fence, 4 Tiles wide
594428d7b3dSmrg   41 - 42MB = 1MB Fence, 4 Tiles wide
595428d7b3dSmrg   For numSurfaces == 7
596428d7b3dSmrg   44 - 48MB   = 4MB Fence, 8 Tiles wide
597428d7b3dSmrg   43 - 44MB   = 1MB Fence, 8 Tiles wide
598428d7b3dSmrg   42.5 - 43MB = 0.5MB Fence, 8 Tiles wide
599428d7b3dSmrg   42 - 42.5MB = 0.5MB Fence, 4 Tiles wide
600428d7b3dSmrg   40 - 42MB   = 2MB Fence, 4 Tiles wide
601428d7b3dSmrg */
602428d7b3dSmrg   if (pI810->numSurfaces) {
603428d7b3dSmrg      if (pI810->numSurfaces == 6) {
604428d7b3dSmrg	 pI810->MC.Size = 7 * 1024 * 1024;
605428d7b3dSmrg	 pI810->MC.Start = pI810->FbMapSize - 7 * 1024 * 1024;
606428d7b3dSmrg
607428d7b3dSmrg      }
608428d7b3dSmrg      if (pI810->numSurfaces == 7) {
609428d7b3dSmrg	 pI810->MC.Size = 8 * 1024 * 1024;
610428d7b3dSmrg	 pI810->MC.Start = pI810->FbMapSize - 8 * 1024 * 1024;
611428d7b3dSmrg      }
612428d7b3dSmrg      drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL,
613428d7b3dSmrg		  (drmAddress) &agpHandle);
614428d7b3dSmrg
615428d7b3dSmrg      pI810->xvmcHandle = agpHandle;
616428d7b3dSmrg
617428d7b3dSmrg      if (agpHandle != DRM_AGP_NO_HANDLE) {
618428d7b3dSmrg	 if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->MC.Start) == 0) {
619428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
620428d7b3dSmrg		       "GART: Allocated 7MB for HWMC\n");
621428d7b3dSmrg	    pI810->MC.End = pI810->MC.Start + pI810->MC.Size;
622428d7b3dSmrg	 } else {
623428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC bind failed\n");
624428d7b3dSmrg	    pI810->MC.Start = 0;
625428d7b3dSmrg	    pI810->MC.Size = 0;
626428d7b3dSmrg	    pI810->MC.End = 0;
627428d7b3dSmrg	 }
628428d7b3dSmrg      } else {
629428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC alloc failed\n");
630428d7b3dSmrg	 pI810->MC.Start = 0;
631428d7b3dSmrg	 pI810->MC.Size = 0;
632428d7b3dSmrg	 pI810->MC.End = 0;
633428d7b3dSmrg      }
634428d7b3dSmrg      pI810->xvmcContext = 0;
635428d7b3dSmrg   }
636428d7b3dSmrg
637428d7b3dSmrg   drmAgpAlloc(pI810->drmSubFD, 4096, 2,
638428d7b3dSmrg	       (unsigned long *)&pI810->CursorPhysical,
639428d7b3dSmrg	       (drmAddress) &agpHandle);
640428d7b3dSmrg
641428d7b3dSmrg   pI810->cursorHandle = agpHandle;
642428d7b3dSmrg
643428d7b3dSmrg   if (agpHandle != DRM_AGP_NO_HANDLE) {
644428d7b3dSmrg      tom = sysmem_size;
645428d7b3dSmrg
646428d7b3dSmrg      if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) {
647428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
648428d7b3dSmrg		    "[agp] GART: Allocated 4K for mouse cursor image\n");
649428d7b3dSmrg	 pI810->CursorStart = tom;
650428d7b3dSmrg	 tom += 4096;
651428d7b3dSmrg      } else {
652428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
653428d7b3dSmrg		    "[agp] GART: cursor bind failed\n");
654428d7b3dSmrg	 pI810->CursorPhysical = 0;
655428d7b3dSmrg      }
656428d7b3dSmrg   } else {
657428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
658428d7b3dSmrg		 "[agp] GART: cursor alloc failed\n");
659428d7b3dSmrg      pI810->CursorPhysical = 0;
660428d7b3dSmrg   }
661428d7b3dSmrg
662428d7b3dSmrg   drmAgpAlloc(pI810->drmSubFD, 16384, 2,
663428d7b3dSmrg	       (unsigned long *)&pI810->CursorARGBPhysical,
664428d7b3dSmrg	       (drmAddress) &agpHandle);
665428d7b3dSmrg
666428d7b3dSmrg   pI810->cursorARGBHandle = agpHandle;
667428d7b3dSmrg
668428d7b3dSmrg   if (agpHandle != DRM_AGP_NO_HANDLE) {
669428d7b3dSmrg      if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) {
670428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
671428d7b3dSmrg		    "[agp] GART: Allocated 16K for ARGB mouse cursor image\n");
672428d7b3dSmrg	 pI810->CursorARGBStart = tom;
673428d7b3dSmrg	 tom += 16384;
674428d7b3dSmrg      } else {
675428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
676428d7b3dSmrg		    "[agp] GART: ARGB cursor bind failed\n");
677428d7b3dSmrg	 pI810->CursorARGBPhysical = 0;
678428d7b3dSmrg      }
679428d7b3dSmrg   } else {
680428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
681428d7b3dSmrg		 "[agp] GART: ARGB cursor alloc failed\n");
682428d7b3dSmrg      pI810->CursorARGBPhysical = 0;
683428d7b3dSmrg   }
684428d7b3dSmrg
685428d7b3dSmrg   /* Steal some of the excess cursor space for the overlay regs.
686428d7b3dSmrg    */
687428d7b3dSmrg   pI810->OverlayPhysical = pI810->CursorPhysical + 1024;
688428d7b3dSmrg   pI810->OverlayStart = pI810->CursorStart + 1024;
689428d7b3dSmrg
690428d7b3dSmrg   I810SetTiledMemory(pScrn, 1,
691428d7b3dSmrg		      pI810->DepthBuffer.Start,
692428d7b3dSmrg		      i810_pitches[pitch_idx], 8 * 1024 * 1024);
693428d7b3dSmrg
694428d7b3dSmrg   I810SetTiledMemory(pScrn, 2,
695428d7b3dSmrg		      pI810->BackBuffer.Start,
696428d7b3dSmrg		      i810_pitches[pitch_idx], 8 * 1024 * 1024);
697428d7b3dSmrg
698428d7b3dSmrg   /* These are for HWMC surfaces */
699428d7b3dSmrg   if (pI810->numSurfaces == 6) {
700428d7b3dSmrg      I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 1024 * 1024);
701428d7b3dSmrg
702428d7b3dSmrg      I810SetTiledMemory(pScrn, 4,
703428d7b3dSmrg			 pI810->MC.Start + 1024 * 1024, 512, 1024 * 1024);
704428d7b3dSmrg
705428d7b3dSmrg      I810SetTiledMemory(pScrn, 5,
706428d7b3dSmrg			 pI810->MC.Start + 1024 * 1024 * 2,
707428d7b3dSmrg			 1024, 1024 * 1024);
708428d7b3dSmrg
709428d7b3dSmrg      I810SetTiledMemory(pScrn, 6,
710428d7b3dSmrg			 pI810->MC.Start + 1024 * 1024 * 3,
711428d7b3dSmrg			 1024, 4 * 1024 * 1024);
712428d7b3dSmrg   }
713428d7b3dSmrg   if (pI810->numSurfaces == 7) {
714428d7b3dSmrg      I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 2 * 1024 * 1024);
715428d7b3dSmrg
716428d7b3dSmrg      I810SetTiledMemory(pScrn, 4,
717428d7b3dSmrg			 pI810->MC.Start + 2 * 1024 * 1024, 512, 512 * 1024);
718428d7b3dSmrg
719428d7b3dSmrg      I810SetTiledMemory(pScrn, 5,
720428d7b3dSmrg			 pI810->MC.Start + 2 * 1024 * 1024 + 512 * 1024,
721428d7b3dSmrg			 1024, 512 * 1024);
722428d7b3dSmrg
723428d7b3dSmrg      I810SetTiledMemory(pScrn, 6,
724428d7b3dSmrg			 pI810->MC.Start + 3 * 1024 * 1024,
725428d7b3dSmrg			 1024, 1 * 1024 * 1024);
726428d7b3dSmrg
727428d7b3dSmrg      I810SetTiledMemory(pScrn, 7,
728428d7b3dSmrg			 pI810->MC.Start + 4 * 1024 * 1024,
729428d7b3dSmrg			 1024, 4 * 1024 * 1024);
730428d7b3dSmrg
731428d7b3dSmrg   }
732428d7b3dSmrg
733428d7b3dSmrg   pI810->auxPitch = i810_pitches[pitch_idx];
734428d7b3dSmrg   pI810->auxPitchBits = i810_pitch_flags[pitch_idx];
735428d7b3dSmrg   pI810->SavedDcacheMem = pI810->DcacheMem;
736428d7b3dSmrg   pI810DRI->backbufferSize = pI810->BackBuffer.Size;
737428d7b3dSmrg
738428d7b3dSmrg   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BackBuffer.Start,
739428d7b3dSmrg		 pI810->BackBuffer.Size, DRM_AGP, 0,
740428d7b3dSmrg		 (drmAddress) &pI810DRI->backbuffer) < 0) {
741428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
742428d7b3dSmrg		 "[drm] drmAddMap(backbuffer) failed.  Disabling DRI\n");
743428d7b3dSmrg      DRICloseScreen(pScreen);
744428d7b3dSmrg      return FALSE;
745428d7b3dSmrg   }
746428d7b3dSmrg
747428d7b3dSmrg   pI810DRI->depthbufferSize = pI810->DepthBuffer.Size;
748428d7b3dSmrg   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->DepthBuffer.Start,
749428d7b3dSmrg		 pI810->DepthBuffer.Size, DRM_AGP, 0,
750428d7b3dSmrg		 (drmAddress) &pI810DRI->depthbuffer) < 0) {
751428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
752428d7b3dSmrg		 "[drm] drmAddMap(depthbuffer) failed.  Disabling DRI.\n");
753428d7b3dSmrg      DRICloseScreen(pScreen);
754428d7b3dSmrg      return FALSE;
755428d7b3dSmrg   }
756428d7b3dSmrg
757428d7b3dSmrg   /* Allocate FrontBuffer etc. */
758428d7b3dSmrg   if (!I810AllocateFront(pScrn)) {
759428d7b3dSmrg      DRICloseScreen(pScreen);
760428d7b3dSmrg      return FALSE;
761428d7b3dSmrg   }
762428d7b3dSmrg
763428d7b3dSmrg   /* Allocate buffer memory */
764428d7b3dSmrg   I810AllocHigh(&(pI810->BufferMem), &(pI810->SysMem),
765428d7b3dSmrg		 I810_DMA_BUF_NR * I810_DMA_BUF_SZ);
766428d7b3dSmrg
767428d7b3dSmrg   xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Buffer map : %lx\n",
768428d7b3dSmrg	      pI810->BufferMem.Start);
769428d7b3dSmrg
770428d7b3dSmrg   if (pI810->BufferMem.Start == 0 ||
771428d7b3dSmrg       pI810->BufferMem.End - pI810->BufferMem.Start >
772428d7b3dSmrg       I810_DMA_BUF_NR * I810_DMA_BUF_SZ) {
773428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
774428d7b3dSmrg		 "[dri] Not enough memory for dma buffers.  Disabling DRI.\n");
775428d7b3dSmrg      DRICloseScreen(pScreen);
776428d7b3dSmrg      return FALSE;
777428d7b3dSmrg   }
778428d7b3dSmrg   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BufferMem.Start,
779428d7b3dSmrg		 pI810->BufferMem.Size, DRM_AGP, 0,
780428d7b3dSmrg		 (drmAddress) &pI810->buffer_map) < 0) {
781428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
782428d7b3dSmrg		 "[drm] drmAddMap(buffer_map) failed.  Disabling DRI.\n");
783428d7b3dSmrg      DRICloseScreen(pScreen);
784428d7b3dSmrg      return FALSE;
785428d7b3dSmrg   }
786428d7b3dSmrg
787428d7b3dSmrg   pI810DRI->agp_buffers = pI810->buffer_map;
788428d7b3dSmrg   pI810DRI->agp_buf_size = pI810->BufferMem.Size;
789428d7b3dSmrg
790428d7b3dSmrg   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing->mem.Start,
791428d7b3dSmrg		 pI810->LpRing->mem.Size, DRM_AGP, 0,
792428d7b3dSmrg		 (drmAddress) &pI810->ring_map) < 0) {
793428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
794428d7b3dSmrg		 "[drm] drmAddMap(ring_map) failed.  Disabling DRI.\n");
795428d7b3dSmrg      DRICloseScreen(pScreen);
796428d7b3dSmrg      return FALSE;
797428d7b3dSmrg   }
798428d7b3dSmrg
799428d7b3dSmrg   /* Use the rest of memory for textures. */
800428d7b3dSmrg   pI810DRI->textureSize = pI810->SysMem.Size;
801428d7b3dSmrg
802428d7b3dSmrg   i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS);
803428d7b3dSmrg
804428d7b3dSmrg   if (i < I810_LOG_MIN_TEX_REGION_SIZE)
805428d7b3dSmrg      i = I810_LOG_MIN_TEX_REGION_SIZE;
806428d7b3dSmrg
807428d7b3dSmrg   pI810DRI->logTextureGranularity = i;
808428d7b3dSmrg   pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i;	/* truncate */
809428d7b3dSmrg
810428d7b3dSmrg   if (pI810DRI->textureSize < 512 * 1024) {
811428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
812428d7b3dSmrg		 "[drm] Less then 512k memory left for textures.  Disabling DRI.\n");
813428d7b3dSmrg      DRICloseScreen(pScreen);
814428d7b3dSmrg      return FALSE;
815428d7b3dSmrg   }
816428d7b3dSmrg
817428d7b3dSmrg   if (!I810AllocLow(&(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize)) {
818428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
819428d7b3dSmrg		 "[agp] Texure memory allocation failed\n");
820428d7b3dSmrg      DRICloseScreen(pScreen);
821428d7b3dSmrg      return FALSE;
822428d7b3dSmrg   }
823428d7b3dSmrg
824428d7b3dSmrg   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->TexMem.Start,
825428d7b3dSmrg		 pI810->TexMem.Size, DRM_AGP, 0,
826428d7b3dSmrg		 (drmAddress) &pI810DRI->textures) < 0) {
827428d7b3dSmrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
828428d7b3dSmrg		 "[drm] drmAddMap(textures) failed.  Disabling DRI.\n");
829428d7b3dSmrg      DRICloseScreen(pScreen);
830428d7b3dSmrg      return FALSE;
831428d7b3dSmrg   }
832428d7b3dSmrg
833428d7b3dSmrg   if ((bufs = drmAddBufs(pI810->drmSubFD,
834428d7b3dSmrg			  I810_DMA_BUF_NR,
835428d7b3dSmrg			  I810_DMA_BUF_SZ,
836428d7b3dSmrg			  DRM_AGP_BUFFER, pI810->BufferMem.Start)) <= 0) {
837428d7b3dSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
838428d7b3dSmrg		 "[drm] failure adding %d %d byte DMA buffers.  Disabling DRI.\n",
839428d7b3dSmrg		 I810_DMA_BUF_NR, I810_DMA_BUF_SZ);
840428d7b3dSmrg      DRICloseScreen(pScreen);
841428d7b3dSmrg      return FALSE;
842428d7b3dSmrg   }
843428d7b3dSmrg
844428d7b3dSmrg   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
845428d7b3dSmrg	      "[drm] added %d %d byte DMA buffers\n", bufs, I810_DMA_BUF_SZ);
846428d7b3dSmrg
847428d7b3dSmrg   I810InitDma(pScrn);
848428d7b3dSmrg
849428d7b3dSmrg   /* Okay now initialize the dma engine */
850428d7b3dSmrg
851428d7b3dSmrg   if (!pI810DRI->irq) {
852428d7b3dSmrg      pI810DRI->irq = drmGetInterruptFromBusID(pI810->drmSubFD,
853428d7b3dSmrg					       ((pI810->PciInfo->domain << 8) |
854428d7b3dSmrg						pI810->PciInfo->bus),
855428d7b3dSmrg					       pI810->PciInfo->dev,
856428d7b3dSmrg					       pI810->PciInfo->func
857428d7b3dSmrg					       );
858428d7b3dSmrg      if ((drmCtlInstHandler(pI810->drmSubFD, pI810DRI->irq)) != 0) {
859428d7b3dSmrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
860428d7b3dSmrg		    "[drm] failure adding irq handler, there is a device "
861428d7b3dSmrg		    "already using that irq\n Consider rearranging your "
862428d7b3dSmrg		    "PCI cards.  Disabling DRI.\n");
863428d7b3dSmrg	 DRICloseScreen(pScreen);
864428d7b3dSmrg	 return FALSE;
865428d7b3dSmrg      }
866428d7b3dSmrg   }
867428d7b3dSmrg
868428d7b3dSmrg   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
869428d7b3dSmrg	      "[drm] dma control initialized, using IRQ %d\n", pI810DRI->irq);
870428d7b3dSmrg
871428d7b3dSmrg   pI810DRI->deviceID = pI810->PciInfo->device_id;
872428d7b3dSmrg   pI810DRI->width = pScrn->virtualX;
873428d7b3dSmrg   pI810DRI->height = pScrn->virtualY;
874428d7b3dSmrg   pI810DRI->mem = pScrn->videoRam * 1024;
875428d7b3dSmrg   pI810DRI->cpp = pI810->cpp;
876428d7b3dSmrg
877428d7b3dSmrg   pI810DRI->fbOffset = pI810->FrontBuffer.Start;
878428d7b3dSmrg   pI810DRI->fbStride = pI810->auxPitch;
879428d7b3dSmrg
880428d7b3dSmrg   pI810DRI->bitsPerPixel = pScrn->bitsPerPixel;
881428d7b3dSmrg
882428d7b3dSmrg   pI810DRI->textureOffset = pI810->TexMem.Start;
883428d7b3dSmrg
884428d7b3dSmrg   pI810DRI->backOffset = pI810->BackBuffer.Start;
885428d7b3dSmrg   pI810DRI->depthOffset = pI810->DepthBuffer.Start;
886428d7b3dSmrg
887428d7b3dSmrg   pI810DRI->ringOffset = pI810->LpRing->mem.Start;
888428d7b3dSmrg   pI810DRI->ringSize = pI810->LpRing->mem.Size;
889428d7b3dSmrg
890428d7b3dSmrg   pI810DRI->auxPitch = pI810->auxPitch;
891428d7b3dSmrg   pI810DRI->auxPitchBits = pI810->auxPitchBits;
892428d7b3dSmrg   pI810DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
893428d7b3dSmrg
894428d7b3dSmrg   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
895428d7b3dSmrg	      "[dri] visual configs initialized.\n");
896428d7b3dSmrg   pI810->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
897428d7b3dSmrg
898428d7b3dSmrg   return TRUE;
899428d7b3dSmrg}
900428d7b3dSmrg
901428d7b3dSmrgvoid
902428d7b3dSmrgI810DRICloseScreen(ScreenPtr pScreen)
903428d7b3dSmrg{
904428d7b3dSmrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
905428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
906428d7b3dSmrg
907428d7b3dSmrg   if (pI810->pDRIInfo) {
908428d7b3dSmrg       I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
909428d7b3dSmrg
910428d7b3dSmrg       if (pI810DRI) {
911428d7b3dSmrg	   if (pI810DRI->irq) {
912428d7b3dSmrg	       drmCtlUninstHandler(pI810->drmSubFD);
913428d7b3dSmrg	       pI810DRI->irq = 0;
914428d7b3dSmrg	   }
915428d7b3dSmrg
916428d7b3dSmrg	   free(pI810->pDRIInfo->devPrivate);
917428d7b3dSmrg	   pI810->pDRIInfo->devPrivate = NULL;
918428d7b3dSmrg       }
919428d7b3dSmrg
920428d7b3dSmrg       I810CleanupDma(pScrn);
921428d7b3dSmrg
922428d7b3dSmrg       DRICloseScreen(pScreen);
923428d7b3dSmrg       DRIDestroyInfoRec(pI810->pDRIInfo);
924428d7b3dSmrg       pI810->pDRIInfo = NULL;
925428d7b3dSmrg   }
926428d7b3dSmrg
927428d7b3dSmrg   if (pI810->dcacheHandle!=DRM_AGP_NO_HANDLE)
928428d7b3dSmrg       drmAgpFree(pI810->drmSubFD, pI810->dcacheHandle);
929428d7b3dSmrg   if (pI810->backHandle!=DRM_AGP_NO_HANDLE)
930428d7b3dSmrg       drmAgpFree(pI810->drmSubFD, pI810->backHandle);
931428d7b3dSmrg   if (pI810->zHandle!=DRM_AGP_NO_HANDLE)
932428d7b3dSmrg       drmAgpFree(pI810->drmSubFD, pI810->zHandle);
933428d7b3dSmrg   if (pI810->cursorHandle!=DRM_AGP_NO_HANDLE)
934428d7b3dSmrg       drmAgpFree(pI810->drmSubFD, pI810->cursorHandle);
935428d7b3dSmrg   if (pI810->xvmcHandle!=DRM_AGP_NO_HANDLE)
936428d7b3dSmrg       drmAgpFree(pI810->drmSubFD, pI810->xvmcHandle);
937428d7b3dSmrg   if (pI810->sysmemHandle!=DRM_AGP_NO_HANDLE)
938428d7b3dSmrg       drmAgpFree(pI810->drmSubFD, pI810->sysmemHandle);
939428d7b3dSmrg
940428d7b3dSmrg   if (pI810->agpAcquired == TRUE)
941428d7b3dSmrg       drmAgpRelease(pI810->drmSubFD);
942428d7b3dSmrg
943428d7b3dSmrg   pI810->backHandle = DRM_AGP_NO_HANDLE;
944428d7b3dSmrg   pI810->zHandle = DRM_AGP_NO_HANDLE;
945428d7b3dSmrg   pI810->cursorHandle = DRM_AGP_NO_HANDLE;
946428d7b3dSmrg   pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
947428d7b3dSmrg   pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
948428d7b3dSmrg   pI810->agpAcquired = FALSE;
949428d7b3dSmrg   pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
950428d7b3dSmrg}
951428d7b3dSmrg
952428d7b3dSmrgstatic Bool
953428d7b3dSmrgI810CreateContext(ScreenPtr pScreen, VisualPtr visual,
954428d7b3dSmrg		  drm_context_t hwContext, void *pVisualConfigPriv,
955428d7b3dSmrg		  DRIContextType contextStore)
956428d7b3dSmrg{
957428d7b3dSmrg   return TRUE;
958428d7b3dSmrg}
959428d7b3dSmrg
960428d7b3dSmrgstatic void
961428d7b3dSmrgI810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
962428d7b3dSmrg		   DRIContextType contextStore)
963428d7b3dSmrg{
964428d7b3dSmrg}
965428d7b3dSmrg
966428d7b3dSmrgBool
967428d7b3dSmrgI810DRIFinishScreenInit(ScreenPtr pScreen)
968428d7b3dSmrg{
969428d7b3dSmrg   I810SAREARec *sPriv = (I810SAREARec *) DRIGetSAREAPrivate(pScreen);
970428d7b3dSmrg   ScrnInfoPtr        pScrn = xf86ScreenToScrn(pScreen);
971428d7b3dSmrg   I810Ptr info  = I810PTR(pScrn);
972428d7b3dSmrg
973428d7b3dSmrg   memset(sPriv, 0, sizeof(*sPriv));
974428d7b3dSmrg
975428d7b3dSmrg   /* Have shadow run only while there is 3d active.
976428d7b3dSmrg    */
977428d7b3dSmrg   if (info->allowPageFlip && info->drmMinor >= 3) {
978428d7b3dSmrg     ShadowFBInit( pScreen, I810DRIRefreshArea );
979428d7b3dSmrg   }
980428d7b3dSmrg   else
981428d7b3dSmrg     info->allowPageFlip = 0;
982428d7b3dSmrg   return DRIFinishScreenInit(pScreen);
983428d7b3dSmrg}
984428d7b3dSmrg
985428d7b3dSmrgvoid
986428d7b3dSmrgI810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
987428d7b3dSmrg		   DRIContextType oldContextType, void *oldContext,
988428d7b3dSmrg		   DRIContextType newContextType, void *newContext)
989428d7b3dSmrg{
990428d7b3dSmrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
991428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
992428d7b3dSmrg
993428d7b3dSmrg   if (syncType == DRI_3D_SYNC &&
994428d7b3dSmrg       oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) {
995428d7b3dSmrg      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
996428d7b3dSmrg	 ErrorF("I810DRISwapContext (in)\n");
997428d7b3dSmrg
998428d7b3dSmrg      if (!pScrn->vtSema)
999428d7b3dSmrg	  return;
1000428d7b3dSmrg      pI810->LockHeld = 1;
1001428d7b3dSmrg      I810RefreshRing(pScrn);
1002428d7b3dSmrg   } else if (syncType == DRI_2D_SYNC &&
1003428d7b3dSmrg	      oldContextType == DRI_NO_CONTEXT &&
1004428d7b3dSmrg	      newContextType == DRI_2D_CONTEXT) {
1005428d7b3dSmrg      pI810->LockHeld = 0;
1006428d7b3dSmrg      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1007428d7b3dSmrg	 ErrorF("I810DRISwapContext (out)\n");
1008428d7b3dSmrg   } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1009428d7b3dSmrg      ErrorF("I810DRISwapContext (other)\n");
1010428d7b3dSmrg}
1011428d7b3dSmrg
1012428d7b3dSmrgstatic void
1013428d7b3dSmrgI810DRISetNeedSync(ScrnInfoPtr pScrn)
1014428d7b3dSmrg{
1015428d7b3dSmrg#ifdef HAVE_XAA_H
1016428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
1017428d7b3dSmrg   if (pI810->AccelInfoRec)
1018428d7b3dSmrg	pI810->AccelInfoRec->NeedToSync = TRUE;
1019428d7b3dSmrg#endif
1020428d7b3dSmrg}
1021428d7b3dSmrg
1022428d7b3dSmrgstatic void
1023428d7b3dSmrgI810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
1024428d7b3dSmrg{
1025428d7b3dSmrg   ScreenPtr pScreen = pWin->drawable.pScreen;
1026428d7b3dSmrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1027428d7b3dSmrg   BoxPtr pbox = REGION_RECTS(prgn);
1028428d7b3dSmrg   int nbox = REGION_NUM_RECTS(prgn);
1029428d7b3dSmrg
1030428d7b3dSmrg   if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1031428d7b3dSmrg      ErrorF("I810DRIInitBuffers\n");
1032428d7b3dSmrg
1033428d7b3dSmrg   I810SetupForSolidFill(pScrn, 0, GXcopy, -1);
1034428d7b3dSmrg   while (nbox--) {
1035428d7b3dSmrg      I810SelectBuffer(pScrn, I810_SELECT_BACK);
1036428d7b3dSmrg      I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
1037428d7b3dSmrg				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
1038428d7b3dSmrg      pbox++;
1039428d7b3dSmrg   }
1040428d7b3dSmrg
1041428d7b3dSmrg   /* Clear the depth buffer - uses 0xffff rather than 0.
1042428d7b3dSmrg    */
1043428d7b3dSmrg   pbox = REGION_RECTS(prgn);
1044428d7b3dSmrg   nbox = REGION_NUM_RECTS(prgn);
1045428d7b3dSmrg   I810SelectBuffer(pScrn, I810_SELECT_DEPTH);
1046428d7b3dSmrg   I810SetupForSolidFill(pScrn, 0xffff, GXcopy, -1);
1047428d7b3dSmrg   while (nbox--) {
1048428d7b3dSmrg      I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
1049428d7b3dSmrg				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
1050428d7b3dSmrg      pbox++;
1051428d7b3dSmrg   }
1052428d7b3dSmrg   I810SelectBuffer(pScrn, I810_SELECT_FRONT);
1053428d7b3dSmrg
1054428d7b3dSmrg   I810DRISetNeedSync(pScrn);
1055428d7b3dSmrg}
1056428d7b3dSmrg
1057428d7b3dSmrg/* This routine is a modified form of XAADoBitBlt with the calls to
1058428d7b3dSmrg * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
1059428d7b3dSmrg * instead of destination. My origin is upside down so the ydir cases
1060428d7b3dSmrg * are reversed.
1061428d7b3dSmrg *
1062428d7b3dSmrg * KW: can you believe that this is called even when a 2d window moves?
1063428d7b3dSmrg */
1064428d7b3dSmrgstatic void
1065428d7b3dSmrgI810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
1066428d7b3dSmrg		   RegionPtr prgnSrc, CARD32 index)
1067428d7b3dSmrg{
1068428d7b3dSmrg   ScreenPtr pScreen = pParent->drawable.pScreen;
1069428d7b3dSmrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1070428d7b3dSmrg   BoxPtr pboxTmp, pboxNext, pboxBase;
1071428d7b3dSmrg   DDXPointPtr pptTmp, pptNew2 = NULL;
1072428d7b3dSmrg   int xdir, ydir;
1073428d7b3dSmrg
1074428d7b3dSmrg   int screenwidth = pScrn->virtualX;
1075428d7b3dSmrg   int screenheight = pScrn->virtualY;
1076428d7b3dSmrg
1077428d7b3dSmrg   BoxPtr pbox = REGION_RECTS(prgnSrc);
1078428d7b3dSmrg   int nbox = REGION_NUM_RECTS(prgnSrc);
1079428d7b3dSmrg
1080428d7b3dSmrg   BoxPtr pboxNew1 = NULL;
1081428d7b3dSmrg   BoxPtr pboxNew2 = NULL;
1082428d7b3dSmrg   DDXPointPtr pptNew1 = NULL;
1083428d7b3dSmrg   DDXPointPtr pptSrc = &ptOldOrg;
1084428d7b3dSmrg
1085428d7b3dSmrg   int dx = pParent->drawable.x - ptOldOrg.x;
1086428d7b3dSmrg   int dy = pParent->drawable.y - ptOldOrg.y;
1087428d7b3dSmrg
1088428d7b3dSmrg   /* If the copy will overlap in Y, reverse the order */
1089428d7b3dSmrg   if (dy > 0) {
1090428d7b3dSmrg      ydir = -1;
1091428d7b3dSmrg
1092428d7b3dSmrg      if (nbox > 1) {
1093428d7b3dSmrg	 /* Keep ordering in each band, reverse order of bands */
1094428d7b3dSmrg	 pboxNew1 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
1095428d7b3dSmrg	 if (!pboxNew1)
1096428d7b3dSmrg	    return;
1097428d7b3dSmrg	 pptNew1 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox);
1098428d7b3dSmrg	 if (!pptNew1) {
1099428d7b3dSmrg	    free(pboxNew1);
1100428d7b3dSmrg	    return;
1101428d7b3dSmrg	 }
1102428d7b3dSmrg	 pboxBase = pboxNext = pbox + nbox - 1;
1103428d7b3dSmrg	 while (pboxBase >= pbox) {
1104428d7b3dSmrg	    while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
1105428d7b3dSmrg	       pboxNext--;
1106428d7b3dSmrg	    pboxTmp = pboxNext + 1;
1107428d7b3dSmrg	    if (pptSrc == &ptOldOrg) {
1108428d7b3dSmrg		if (pboxTmp <= pboxBase) {
1109428d7b3dSmrg	          *pboxNew1++ = *pboxTmp;
1110428d7b3dSmrg	          *pptNew1++ = *pptSrc;
1111428d7b3dSmrg		}
1112428d7b3dSmrg	    } else {
1113428d7b3dSmrg	       pptTmp = pptSrc + (pboxTmp - pbox);
1114428d7b3dSmrg	       while (pboxTmp <= pboxBase) {
1115428d7b3dSmrg	          *pboxNew1++ = *pboxTmp++;
1116428d7b3dSmrg	          *pptNew1++ = *pptTmp++;
1117428d7b3dSmrg	       }
1118428d7b3dSmrg	    }
1119428d7b3dSmrg	    pboxBase = pboxNext;
1120428d7b3dSmrg	 }
1121428d7b3dSmrg	 pboxNew1 -= nbox;
1122428d7b3dSmrg	 pbox = pboxNew1;
1123428d7b3dSmrg	 pptNew1 -= nbox;
1124428d7b3dSmrg	 pptSrc = pptNew1;
1125428d7b3dSmrg      }
1126428d7b3dSmrg   } else {
1127428d7b3dSmrg      /* No changes required */
1128428d7b3dSmrg      ydir = 1;
1129428d7b3dSmrg   }
1130428d7b3dSmrg
1131428d7b3dSmrg   /* If the regions will overlap in X, reverse the order */
1132428d7b3dSmrg   if (dx > 0) {
1133428d7b3dSmrg      xdir = -1;
1134428d7b3dSmrg
1135428d7b3dSmrg      if (nbox > 1) {
1136428d7b3dSmrg	 /*reverse orderof rects in each band */
1137428d7b3dSmrg	 pboxNew2 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
1138428d7b3dSmrg	 pptNew2 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox);
1139428d7b3dSmrg	 if (!pboxNew2 || !pptNew2) {
1140428d7b3dSmrg	    if (pptNew2)
1141428d7b3dSmrg	       free(pptNew2);
1142428d7b3dSmrg	    if (pboxNew2)
1143428d7b3dSmrg	       free(pboxNew2);
1144428d7b3dSmrg	    if (pboxNew1) {
1145428d7b3dSmrg	       free(pptNew1);
1146428d7b3dSmrg	       free(pboxNew1);
1147428d7b3dSmrg	    }
1148428d7b3dSmrg	    return;
1149428d7b3dSmrg	 }
1150428d7b3dSmrg	 pboxBase = pboxNext = pbox;
1151428d7b3dSmrg	 while (pboxBase < pbox + nbox) {
1152428d7b3dSmrg	    while ((pboxNext < pbox + nbox) && (pboxNext->y1 == pboxBase->y1))
1153428d7b3dSmrg	       pboxNext++;
1154428d7b3dSmrg	    pboxTmp = pboxNext;
1155428d7b3dSmrg	    pptTmp = pptSrc + (pboxTmp - pbox);
1156428d7b3dSmrg	    while (pboxTmp != pboxBase) {
1157428d7b3dSmrg	       *pboxNew2++ = *--pboxTmp;
1158428d7b3dSmrg	       *pptNew2++ = *--pptTmp;
1159428d7b3dSmrg	    }
1160428d7b3dSmrg	    pboxBase = pboxNext;
1161428d7b3dSmrg	 }
1162428d7b3dSmrg	 pboxNew2 -= nbox;
1163428d7b3dSmrg	 pbox = pboxNew2;
1164428d7b3dSmrg	 pptNew2 -= nbox;
1165428d7b3dSmrg	 pptSrc = pptNew2;
1166428d7b3dSmrg      }
1167428d7b3dSmrg   } else {
1168428d7b3dSmrg      /* No changes are needed */
1169428d7b3dSmrg      xdir = 1;
1170428d7b3dSmrg   }
1171428d7b3dSmrg
1172428d7b3dSmrg   /* SelectBuffer isn't really a good concept for the i810.
1173428d7b3dSmrg    */
1174428d7b3dSmrg   I810EmitFlush(pScrn);
1175428d7b3dSmrg   I810SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);
1176428d7b3dSmrg   for (; nbox--; pbox++) {
1177428d7b3dSmrg
1178428d7b3dSmrg      int x1 = pbox->x1;
1179428d7b3dSmrg      int y1 = pbox->y1;
1180428d7b3dSmrg      int destx = x1 + dx;
1181428d7b3dSmrg      int desty = y1 + dy;
1182428d7b3dSmrg      int w = pbox->x2 - x1 + 1;
1183428d7b3dSmrg      int h = pbox->y2 - y1 + 1;
1184428d7b3dSmrg
1185428d7b3dSmrg      if (destx < 0)
1186428d7b3dSmrg	 x1 -= destx, w += destx, destx = 0;
1187428d7b3dSmrg      if (desty < 0)
1188428d7b3dSmrg	 y1 -= desty, h += desty, desty = 0;
1189428d7b3dSmrg      if (destx + w > screenwidth)
1190428d7b3dSmrg	 w = screenwidth - destx;
1191428d7b3dSmrg      if (desty + h > screenheight)
1192428d7b3dSmrg	 h = screenheight - desty;
1193428d7b3dSmrg      if (w <= 0)
1194428d7b3dSmrg	 continue;
1195428d7b3dSmrg      if (h <= 0)
1196428d7b3dSmrg	 continue;
1197428d7b3dSmrg
1198428d7b3dSmrg      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1199428d7b3dSmrg	 ErrorF("MoveBuffers %d,%d %dx%d dx: %d dy: %d\n",
1200428d7b3dSmrg		x1, y1, w, h, dx, dy);
1201428d7b3dSmrg
1202428d7b3dSmrg      I810SelectBuffer(pScrn, I810_SELECT_BACK);
1203428d7b3dSmrg      I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
1204428d7b3dSmrg      I810SelectBuffer(pScrn, I810_SELECT_DEPTH);
1205428d7b3dSmrg      I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
1206428d7b3dSmrg   }
1207428d7b3dSmrg   I810SelectBuffer(pScrn, I810_SELECT_FRONT);
1208428d7b3dSmrg   I810EmitFlush(pScrn);
1209428d7b3dSmrg
1210428d7b3dSmrg   if (pboxNew2) {
1211428d7b3dSmrg      free(pptNew2);
1212428d7b3dSmrg      free(pboxNew2);
1213428d7b3dSmrg   }
1214428d7b3dSmrg   if (pboxNew1) {
1215428d7b3dSmrg      free(pptNew1);
1216428d7b3dSmrg      free(pboxNew1);
1217428d7b3dSmrg   }
1218428d7b3dSmrg
1219428d7b3dSmrg   I810DRISetNeedSync(pScrn);
1220428d7b3dSmrg}
1221428d7b3dSmrg
1222428d7b3dSmrg
1223428d7b3dSmrg/* Use the miext/shadow module to maintain a list of dirty rectangles.
1224428d7b3dSmrg * These are blitted to the back buffer to keep both buffers clean
1225428d7b3dSmrg * during page-flipping when the 3d application isn't fullscreen.
1226428d7b3dSmrg *
1227428d7b3dSmrg * Unlike most use of the shadow code, both buffers are in video memory.
1228428d7b3dSmrg *
1229428d7b3dSmrg * An alternative to this would be to organize for all on-screen drawing
1230428d7b3dSmrg * operations to be duplicated for the two buffers.  That might be
1231428d7b3dSmrg * faster, but seems like a lot more work...
1232428d7b3dSmrg */
1233428d7b3dSmrg
1234428d7b3dSmrg
1235428d7b3dSmrg/* This should be done *before* XAA syncs or fires its buffer.
1236428d7b3dSmrg * Otherwise will have to fire it again???
1237428d7b3dSmrg */
1238428d7b3dSmrgstatic void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
1239428d7b3dSmrg{
1240428d7b3dSmrg    I810Ptr pI810 = I810PTR(pScrn);
1241428d7b3dSmrg    int i;
1242428d7b3dSmrg    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
1243428d7b3dSmrg    unsigned int br13;
1244428d7b3dSmrg    int cpp=2;
1245428d7b3dSmrg
1246428d7b3dSmrg
1247428d7b3dSmrg    /* Don't want to do this when no 3d is active and pages are
1248428d7b3dSmrg     * right-way-round
1249428d7b3dSmrg     */
1250428d7b3dSmrg    if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
1251428d7b3dSmrg      return;
1252428d7b3dSmrg
1253428d7b3dSmrg    br13 = (pI810->auxPitch) | (0xcc << 16);
1254428d7b3dSmrg
1255428d7b3dSmrg    for (i = 0 ; i < num ; i++, pbox++) {
1256428d7b3dSmrg      unsigned int w = min(pbox->y2, pScrn->virtualY-1) - max(pbox->y1, 0) + 1;
1257428d7b3dSmrg      unsigned int h = min(pbox->x2, pScrn->virtualX-1) - max(pbox->x1, 0) + 1;
1258428d7b3dSmrg      unsigned int dst = max(pbox->x1, 0)*cpp + (max(pbox->y1, 0)*pI810->auxPitch);
1259428d7b3dSmrg
1260428d7b3dSmrg      BEGIN_LP_RING(6);
1261428d7b3dSmrg
1262428d7b3dSmrg      OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
1263428d7b3dSmrg      OUT_RING(br13);
1264428d7b3dSmrg      OUT_RING( (h<<16) | (w*cpp) );
1265428d7b3dSmrg      OUT_RING(pI810->BackBuffer.Start + dst);
1266428d7b3dSmrg      OUT_RING(br13 & 0xffff);
1267428d7b3dSmrg      OUT_RING(dst);
1268428d7b3dSmrg
1269428d7b3dSmrg      ADVANCE_LP_RING();
1270428d7b3dSmrg    }
1271428d7b3dSmrg
1272428d7b3dSmrg}
1273428d7b3dSmrg
1274428d7b3dSmrgstatic void I810EnablePageFlip(ScreenPtr pScreen)
1275428d7b3dSmrg{
1276428d7b3dSmrg    ScrnInfoPtr         pScrn      = xf86ScreenToScrn(pScreen);
1277428d7b3dSmrg    I810Ptr       pI810       = I810PTR(pScrn);
1278428d7b3dSmrg    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
1279428d7b3dSmrg    int cpp=2;
1280428d7b3dSmrg    pSAREAPriv->pf_enabled = pI810->allowPageFlip;
1281428d7b3dSmrg    pSAREAPriv->pf_active = 0;
1282428d7b3dSmrg
1283428d7b3dSmrg   if (pI810->allowPageFlip) {
1284428d7b3dSmrg      unsigned int br13 = pI810->auxPitch | (0xcc << 16);
1285428d7b3dSmrg
1286428d7b3dSmrg      BEGIN_LP_RING(6);
1287428d7b3dSmrg
1288428d7b3dSmrg      OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
1289428d7b3dSmrg      OUT_RING(br13);
1290428d7b3dSmrg      OUT_RING((pScrn->virtualY << 16) | (pScrn->virtualX*cpp));
1291428d7b3dSmrg      OUT_RING(pI810->BackBuffer.Start);
1292428d7b3dSmrg      OUT_RING(br13 & 0xFFFF);
1293428d7b3dSmrg      OUT_RING(0);
1294428d7b3dSmrg      ADVANCE_LP_RING();
1295428d7b3dSmrg
1296428d7b3dSmrg      pSAREAPriv->pf_active = 1;
1297428d7b3dSmrg   }
1298428d7b3dSmrg
1299428d7b3dSmrg}
1300428d7b3dSmrg
1301428d7b3dSmrgstatic void I810DisablePageFlip(ScreenPtr pScreen)
1302428d7b3dSmrg{
1303428d7b3dSmrg    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
1304428d7b3dSmrg
1305428d7b3dSmrg    pSAREAPriv->pf_active=0;
1306428d7b3dSmrg}
1307428d7b3dSmrg
1308428d7b3dSmrgstatic void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen)
1309428d7b3dSmrg{
1310428d7b3dSmrg    /* Tell the clients not to pageflip.  How?
1311428d7b3dSmrg     *   -- Field in sarea, plus bumping the window counters.
1312428d7b3dSmrg     *   -- DRM needs to cope with Front-to-Back swapbuffers.
1313428d7b3dSmrg     */
1314428d7b3dSmrg    I810DisablePageFlip(pScreen);
1315428d7b3dSmrg}
1316428d7b3dSmrg
1317428d7b3dSmrgstatic void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen)
1318428d7b3dSmrg{
1319428d7b3dSmrg    /* Let the remaining 3d app start page flipping again */
1320428d7b3dSmrg    I810EnablePageFlip(pScreen);
1321428d7b3dSmrg}
1322428d7b3dSmrg
1323428d7b3dSmrgstatic void I810DRITransitionTo3d(ScreenPtr pScreen)
1324428d7b3dSmrg{
1325428d7b3dSmrg    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
1326428d7b3dSmrg    I810Ptr  pI810  = I810PTR(pScrn);
1327428d7b3dSmrg
1328428d7b3dSmrg    I810EnablePageFlip(pScreen);
1329428d7b3dSmrg    pI810->have3DWindows = 1;
1330428d7b3dSmrg}
1331428d7b3dSmrg
1332428d7b3dSmrgstatic void I810DRITransitionTo2d(ScreenPtr pScreen)
1333428d7b3dSmrg{
1334428d7b3dSmrg    ScrnInfoPtr         pScrn      = xf86ScreenToScrn(pScreen);
1335428d7b3dSmrg    I810Ptr       pI810       = I810PTR(pScrn);
1336428d7b3dSmrg    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
1337428d7b3dSmrg
1338428d7b3dSmrg    /* Try flipping back to the front page if necessary */
1339428d7b3dSmrg    if (pSAREAPriv->pf_current_page == 1)
1340428d7b3dSmrg	drmCommandNone(pI810->drmSubFD, DRM_I810_FLIP);
1341428d7b3dSmrg
1342428d7b3dSmrg    /* Shut down shadowing if we've made it back to the front page */
1343428d7b3dSmrg    if (pSAREAPriv->pf_current_page == 0) {
1344428d7b3dSmrg	I810DisablePageFlip(pScreen);
1345428d7b3dSmrg    }
1346428d7b3dSmrg    pI810->have3DWindows = 0;
1347428d7b3dSmrg}
1348428d7b3dSmrg
1349428d7b3dSmrgBool
1350428d7b3dSmrgI810DRILeave(ScrnInfoPtr pScrn)
1351428d7b3dSmrg{
1352428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
1353428d7b3dSmrg
1354428d7b3dSmrg   if (pI810->directRenderingEnabled) {
1355428d7b3dSmrg      if (pI810->dcacheHandle != 0)
1356428d7b3dSmrg	 if (drmAgpUnbind(pI810->drmSubFD, pI810->dcacheHandle) != 0) {
1357428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1358428d7b3dSmrg	    return FALSE;
1359428d7b3dSmrg	 }
1360428d7b3dSmrg      if (pI810->backHandle != 0)
1361428d7b3dSmrg	 if (drmAgpUnbind(pI810->drmSubFD, pI810->backHandle) != 0) {
1362428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1363428d7b3dSmrg 	    return FALSE;
1364428d7b3dSmrg	 }
1365428d7b3dSmrg      if (pI810->zHandle != 0)
1366428d7b3dSmrg	 if (drmAgpUnbind(pI810->drmSubFD, pI810->zHandle) != 0) {
1367428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1368428d7b3dSmrg  	    return FALSE;
1369428d7b3dSmrg	 }
1370428d7b3dSmrg      if (pI810->sysmemHandle != 0)
1371428d7b3dSmrg	 if (drmAgpUnbind(pI810->drmSubFD, pI810->sysmemHandle) != 0) {
1372428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1373428d7b3dSmrg  	    return FALSE;
1374428d7b3dSmrg	 }
1375428d7b3dSmrg      if (pI810->xvmcHandle != 0)
1376428d7b3dSmrg	 if (drmAgpUnbind(pI810->drmSubFD, pI810->xvmcHandle) != 0) {
1377428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1378428d7b3dSmrg  	    return FALSE;
1379428d7b3dSmrg	 }
1380428d7b3dSmrg      if (pI810->cursorHandle != 0)
1381428d7b3dSmrg	 if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorHandle) != 0) {
1382428d7b3dSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1383428d7b3dSmrg	    return FALSE;
1384428d7b3dSmrg	 }
1385428d7b3dSmrg      if (pI810->cursorARGBHandle != 0)
1386428d7b3dSmrg	  if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorARGBHandle) != 0) {
1387428d7b3dSmrg	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
1388428d7b3dSmrg	      return FALSE;
1389428d7b3dSmrg	  }
1390428d7b3dSmrg      if (pI810->agpAcquired == TRUE)
1391428d7b3dSmrg	 drmAgpRelease(pI810->drmSubFD);
1392428d7b3dSmrg      pI810->agpAcquired = FALSE;
1393428d7b3dSmrg   }
1394428d7b3dSmrg   return TRUE;
1395428d7b3dSmrg}
1396428d7b3dSmrg
1397428d7b3dSmrgBool
1398428d7b3dSmrgI810DRIEnter(ScrnInfoPtr pScrn)
1399428d7b3dSmrg{
1400428d7b3dSmrg   I810Ptr pI810 = I810PTR(pScrn);
1401428d7b3dSmrg
1402428d7b3dSmrg   if (pI810->directRenderingEnabled) {
1403428d7b3dSmrg
1404428d7b3dSmrg      if (pI810->agpAcquired == FALSE)
1405428d7b3dSmrg	 drmAgpAcquire(pI810->drmSubFD);
1406428d7b3dSmrg      pI810->agpAcquired = TRUE;
1407428d7b3dSmrg      if (pI810->dcacheHandle != 0)
1408428d7b3dSmrg	 if (drmAgpBind(pI810->drmSubFD, pI810->dcacheHandle,
1409428d7b3dSmrg			pI810->DepthOffset) != 0)
1410428d7b3dSmrg	    return FALSE;
1411428d7b3dSmrg      if (pI810->backHandle != 0)
1412428d7b3dSmrg	 if (drmAgpBind(pI810->drmSubFD, pI810->backHandle,
1413428d7b3dSmrg			pI810->BackOffset) != 0)
1414428d7b3dSmrg	    return FALSE;
1415428d7b3dSmrg      if (pI810->zHandle != 0)
1416428d7b3dSmrg	 if (drmAgpBind(pI810->drmSubFD, pI810->zHandle,
1417428d7b3dSmrg			pI810->DepthOffset) != 0)
1418428d7b3dSmrg	    return FALSE;
1419428d7b3dSmrg      if (pI810->sysmemHandle != 0)
1420428d7b3dSmrg	 if (drmAgpBind(pI810->drmSubFD, pI810->sysmemHandle, 0) != 0)
1421428d7b3dSmrg	    return FALSE;
1422428d7b3dSmrg      if (pI810->xvmcHandle != 0)
1423428d7b3dSmrg	 if (drmAgpBind(pI810->drmSubFD, pI810->xvmcHandle,
1424428d7b3dSmrg			pI810->MC.Start) != 0)
1425428d7b3dSmrg	    return FALSE;
1426428d7b3dSmrg      if (pI810->cursorHandle != 0)
1427428d7b3dSmrg	 if (drmAgpBind(pI810->drmSubFD, pI810->cursorHandle,
1428428d7b3dSmrg			pI810->CursorStart) != 0)
1429428d7b3dSmrg	    return FALSE;
1430428d7b3dSmrg      if (pI810->cursorARGBHandle != 0)
1431428d7b3dSmrg	 if (drmAgpBind(pI810->drmSubFD, pI810->cursorARGBHandle,
1432428d7b3dSmrg			pI810->CursorARGBStart) != 0)
1433428d7b3dSmrg	    return FALSE;
1434428d7b3dSmrg   }
1435428d7b3dSmrg
1436428d7b3dSmrg   I810SelectBuffer(pScrn, I810_SELECT_FRONT);
1437428d7b3dSmrg   return TRUE;
1438428d7b3dSmrg}
1439