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