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