st/xorg: Make sure we don't overrun the fence array in block handler
[mesa.git] / src / gallium / state_trackers / xorg / xorg_driver.c
1 /*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
28 *
29 */
30
31
32 #include "xorg-server.h"
33 #include "xf86.h"
34 #include "xf86_OSproc.h"
35 #include "compiler.h"
36 #include "xf86PciInfo.h"
37 #include "xf86Pci.h"
38 #include "mipointer.h"
39 #include "micmap.h"
40 #include <X11/extensions/randr.h>
41 #include "fb.h"
42 #include "edid.h"
43 #include "xf86i2c.h"
44 #include "xf86Crtc.h"
45 #include "miscstruct.h"
46 #include "dixstruct.h"
47 #include "xf86xv.h"
48 #include <X11/extensions/Xv.h>
49 #ifndef XSERVER_LIBPCIACCESS
50 #error "libpciaccess needed"
51 #endif
52
53 #include <pciaccess.h>
54
55 #include "pipe/p_context.h"
56 #include "xorg_tracker.h"
57 #include "xorg_winsys.h"
58
59 #ifdef HAVE_LIBKMS
60 #include "libkms.h"
61 #endif
62
63 /*
64 * Functions and symbols exported to Xorg via pointers.
65 */
66
67 static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags);
68 static Bool drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc,
69 char **argv);
70 static Bool drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags);
71 static void drv_adjust_frame(int scrnIndex, int x, int y, int flags);
72 static Bool drv_enter_vt(int scrnIndex, int flags);
73 static void drv_leave_vt(int scrnIndex, int flags);
74 static void drv_free_screen(int scrnIndex, int flags);
75 static ModeStatus drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose,
76 int flags);
77
78 typedef enum
79 {
80 OPTION_SW_CURSOR,
81 OPTION_2D_ACCEL,
82 } drv_option_enums;
83
84 static const OptionInfoRec drv_options[] = {
85 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
86 {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE},
87 {-1, NULL, OPTV_NONE, {0}, FALSE}
88 };
89
90
91 /*
92 * Exported Xorg driver functions to winsys
93 */
94
95 const OptionInfoRec *
96 xorg_tracker_available_options(int chipid, int busid)
97 {
98 return drv_options;
99 }
100
101 void
102 xorg_tracker_set_functions(ScrnInfoPtr scrn)
103 {
104 scrn->PreInit = drv_pre_init;
105 scrn->ScreenInit = drv_screen_init;
106 scrn->SwitchMode = drv_switch_mode;
107 scrn->AdjustFrame = drv_adjust_frame;
108 scrn->EnterVT = drv_enter_vt;
109 scrn->LeaveVT = drv_leave_vt;
110 scrn->FreeScreen = drv_free_screen;
111 scrn->ValidMode = drv_valid_mode;
112 }
113
114
115 /*
116 * Internal function definitions
117 */
118
119 static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn);
120 static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen);
121 static Bool drv_save_hw_state(ScrnInfoPtr pScrn);
122 static Bool drv_restore_hw_state(ScrnInfoPtr pScrn);
123
124
125 /*
126 * Internal functions
127 */
128
129 static Bool
130 drv_get_rec(ScrnInfoPtr pScrn)
131 {
132 if (pScrn->driverPrivate)
133 return TRUE;
134
135 pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1);
136
137 return TRUE;
138 }
139
140 static void
141 drv_free_rec(ScrnInfoPtr pScrn)
142 {
143 if (!pScrn)
144 return;
145
146 if (!pScrn->driverPrivate)
147 return;
148
149 xfree(pScrn->driverPrivate);
150
151 pScrn->driverPrivate = NULL;
152 }
153
154 static void
155 drv_probe_ddc(ScrnInfoPtr pScrn, int index)
156 {
157 ConfiguredMonitor = NULL;
158 }
159
160 static Bool
161 drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height)
162 {
163 modesettingPtr ms = modesettingPTR(pScrn);
164 PixmapPtr rootPixmap;
165 ScreenPtr pScreen = pScrn->pScreen;
166
167 if (width == pScrn->virtualX && height == pScrn->virtualY)
168 return TRUE;
169
170 pScrn->virtualX = width;
171 pScrn->virtualY = height;
172
173 /*
174 * Remove the old framebuffer & texture.
175 */
176 drmModeRmFB(ms->fd, ms->fb_id);
177 if (!ms->destroy_front_buffer(pScrn))
178 FatalError("failed to destroy front buffer\n");
179
180 rootPixmap = pScreen->GetScreenPixmap(pScreen);
181 if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL))
182 return FALSE;
183
184 /* HW dependent - FIXME */
185 pScrn->displayWidth = pScrn->virtualX;
186
187 /* now create new frontbuffer */
188 return ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn);
189 }
190
191 static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
192 .resize = drv_crtc_resize
193 };
194
195 static Bool
196 drv_init_drm(ScrnInfoPtr pScrn)
197 {
198 modesettingPtr ms = modesettingPTR(pScrn);
199
200 /* deal with server regeneration */
201 if (ms->fd < 0) {
202 char *BusID;
203
204 BusID = xalloc(64);
205 sprintf(BusID, "PCI:%d:%d:%d",
206 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
207 ms->PciInfo->dev, ms->PciInfo->func
208 );
209
210 ms->fd = drmOpen(NULL, BusID);
211
212 if (ms->fd < 0)
213 return FALSE;
214 }
215
216 return TRUE;
217 }
218
219 static Bool
220 drv_init_resource_management(ScrnInfoPtr pScrn)
221 {
222 modesettingPtr ms = modesettingPTR(pScrn);
223 /*
224 ScreenPtr pScreen = pScrn->pScreen;
225 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
226 Bool fbAccessDisabled;
227 CARD8 *fbstart;
228 */
229
230 if (ms->screen || ms->kms)
231 return TRUE;
232
233 ms->api = drm_api_create();
234 if (ms->api) {
235 ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL);
236
237 if (ms->screen)
238 return TRUE;
239
240 if (ms->api->destroy)
241 ms->api->destroy(ms->api);
242
243 ms->api = NULL;
244 }
245
246 #ifdef HAVE_LIBKMS
247 if (!kms_create(ms->fd, &ms->kms))
248 return TRUE;
249 #endif
250
251 return FALSE;
252 }
253
254 static Bool
255 drv_close_resource_management(ScrnInfoPtr pScrn)
256 {
257 modesettingPtr ms = modesettingPTR(pScrn);
258
259 if (ms->screen)
260 ms->screen->destroy(ms->screen);
261 ms->screen = NULL;
262
263 if (ms->api && ms->api->destroy)
264 ms->api->destroy(ms->api);
265 ms->api = NULL;
266
267 #ifdef HAVE_LIBKMS
268 if (ms->kms)
269 kms_destroy(&ms->kms);
270 #endif
271
272 return TRUE;
273 }
274
275 static Bool
276 drv_pre_init(ScrnInfoPtr pScrn, int flags)
277 {
278 xf86CrtcConfigPtr xf86_config;
279 modesettingPtr ms;
280 rgb defaultWeight = { 0, 0, 0 };
281 EntityInfoPtr pEnt;
282 EntPtr msEnt = NULL;
283 int max_width, max_height;
284
285 if (pScrn->numEntities != 1)
286 return FALSE;
287
288 pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
289
290 if (flags & PROBE_DETECT) {
291 drv_probe_ddc(pScrn, pEnt->index);
292 return TRUE;
293 }
294
295 /* Allocate driverPrivate */
296 if (!drv_get_rec(pScrn))
297 return FALSE;
298
299 ms = modesettingPTR(pScrn);
300 ms->SaveGeneration = -1;
301 ms->pEnt = pEnt;
302
303 pScrn->displayWidth = 640; /* default it */
304
305 if (ms->pEnt->location.type != BUS_PCI)
306 return FALSE;
307
308 ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
309
310 /* Allocate an entity private if necessary */
311 if (xf86IsEntityShared(pScrn->entityList[0])) {
312 FatalError("Entity");
313 #if 0
314 msEnt = xf86GetEntityPrivate(pScrn->entityList[0],
315 modesettingEntityIndex)->ptr;
316 ms->entityPrivate = msEnt;
317 #else
318 (void)msEnt;
319 #endif
320 } else
321 ms->entityPrivate = NULL;
322
323 if (xf86IsEntityShared(pScrn->entityList[0])) {
324 if (xf86IsPrimInitDone(pScrn->entityList[0])) {
325 /* do something */
326 } else {
327 xf86SetPrimInitDone(pScrn->entityList[0]);
328 }
329 }
330
331 ms->fd = -1;
332 ms->api = NULL;
333 if (!drv_init_drm(pScrn))
334 return FALSE;
335
336 pScrn->monitor = pScrn->confScreen->monitor;
337 pScrn->progClock = TRUE;
338 pScrn->rgbBits = 8;
339
340 if (!xf86SetDepthBpp
341 (pScrn, 0, 0, 0,
342 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb))
343 return FALSE;
344
345 switch (pScrn->depth) {
346 case 15:
347 case 16:
348 case 24:
349 break;
350 default:
351 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
352 "Given depth (%d) is not supported by the driver\n",
353 pScrn->depth);
354 return FALSE;
355 }
356 xf86PrintDepthBpp(pScrn);
357
358 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
359 return FALSE;
360 if (!xf86SetDefaultVisual(pScrn, -1))
361 return FALSE;
362
363 /* Process the options */
364 xf86CollectOptions(pScrn, NULL);
365 if (!(ms->Options = xalloc(sizeof(drv_options))))
366 return FALSE;
367 memcpy(ms->Options, drv_options, sizeof(drv_options));
368 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);
369
370 /* Allocate an xf86CrtcConfig */
371 xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
372 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
373
374 max_width = 8192;
375 max_height = 8192;
376 xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height);
377
378 if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
379 ms->SWCursor = TRUE;
380 }
381
382 drv_save_hw_state(pScrn);
383
384 xorg_crtc_init(pScrn);
385 xorg_output_init(pScrn);
386
387 if (!xf86InitialConfiguration(pScrn, TRUE)) {
388 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
389 drv_restore_hw_state(pScrn);
390 return FALSE;
391 }
392
393 drv_restore_hw_state(pScrn);
394
395 /*
396 * If the driver can do gamma correction, it should call xf86SetGamma() here.
397 */
398 {
399 Gamma zeros = { 0.0, 0.0, 0.0 };
400
401 if (!xf86SetGamma(pScrn, zeros)) {
402 return FALSE;
403 }
404 }
405
406 if (pScrn->modes == NULL) {
407 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
408 return FALSE;
409 }
410
411 pScrn->currentMode = pScrn->modes;
412
413 /* Set display resolution */
414 xf86SetDpi(pScrn, 0, 0);
415
416 /* Load the required sub modules */
417 if (!xf86LoadSubModule(pScrn, "fb"))
418 return FALSE;
419
420 /* XXX: these aren't needed when we are using libkms */
421 if (!xf86LoadSubModule(pScrn, "exa"))
422 return FALSE;
423
424 #ifdef DRI2
425 if (!xf86LoadSubModule(pScrn, "dri2"))
426 return FALSE;
427 #endif
428
429 return TRUE;
430 }
431
432 static Bool
433 drv_save_hw_state(ScrnInfoPtr pScrn)
434 {
435 /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
436
437 return TRUE;
438 }
439
440 static Bool
441 drv_restore_hw_state(ScrnInfoPtr pScrn)
442 {
443 /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
444
445 return TRUE;
446 }
447
448 static void drv_block_handler(int i, pointer blockData, pointer pTimeout,
449 pointer pReadmask)
450 {
451 ScreenPtr pScreen = screenInfo.screens[i];
452 modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]);
453
454 pScreen->BlockHandler = ms->blockHandler;
455 pScreen->BlockHandler(i, blockData, pTimeout, pReadmask);
456 pScreen->BlockHandler = drv_block_handler;
457
458 if (ms->ctx) {
459 int j;
460
461 ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, &ms->fence[XORG_NR_FENCES-1]);
462
463 if (ms->fence[0])
464 ms->ctx->screen->fence_finish(ms->ctx->screen, ms->fence[0], 0);
465
466 /* The amount of rendering generated by a block handler can be
467 * quite small. Let us get a fair way ahead of hardware before
468 * throttling.
469 */
470 for (j = 0; j < XORG_NR_FENCES - 1; j++)
471 ms->screen->fence_reference(ms->screen,
472 &ms->fence[j],
473 ms->fence[j+1]);
474
475 ms->screen->fence_reference(ms->screen,
476 &ms->fence[XORG_NR_FENCES-1],
477 NULL);
478 }
479
480
481 #ifdef DRM_MODE_FEATURE_DIRTYFB
482 {
483 RegionPtr dirty = DamageRegion(ms->damage);
484 unsigned num_cliprects = REGION_NUM_RECTS(dirty);
485
486 if (num_cliprects) {
487 drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip));
488 BoxPtr rect = REGION_RECTS(dirty);
489 int i, ret;
490
491 /* XXX no need for copy? */
492 for (i = 0; i < num_cliprects; i++, rect++) {
493 clip[i].x1 = rect->x1;
494 clip[i].y1 = rect->y1;
495 clip[i].x2 = rect->x2;
496 clip[i].y2 = rect->y2;
497 }
498
499 /* TODO query connector property to see if this is needed */
500 ret = drmModeDirtyFB(ms->fd, ms->fb_id, clip, num_cliprects);
501 if (ret) {
502 debug_printf("%s: failed to send dirty (%i, %s)\n",
503 __func__, ret, strerror(-ret));
504 }
505
506 DamageEmpty(ms->damage);
507 }
508 }
509 #endif
510 }
511
512 static Bool
513 drv_create_screen_resources(ScreenPtr pScreen)
514 {
515 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
516 modesettingPtr ms = modesettingPTR(pScrn);
517 PixmapPtr rootPixmap;
518 Bool ret;
519
520 ms->noEvict = TRUE;
521
522 pScreen->CreateScreenResources = ms->createScreenResources;
523 ret = pScreen->CreateScreenResources(pScreen);
524 pScreen->CreateScreenResources = drv_create_screen_resources;
525
526 ms->bind_front_buffer(pScrn);
527
528 ms->noEvict = FALSE;
529
530 drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
531
532 #ifdef DRM_MODE_FEATURE_DIRTYFB
533 rootPixmap = pScreen->GetScreenPixmap(pScreen);
534 ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
535 pScreen, rootPixmap);
536
537 if (ms->damage) {
538 DamageRegister(&rootPixmap->drawable, ms->damage);
539
540 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
541 } else {
542 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
543 "Failed to create screen damage record\n");
544 return FALSE;
545 }
546 #else
547 (void)rootPixmap;
548 #endif
549
550 return ret;
551 }
552
553 static Bool
554 drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
555 {
556 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
557 modesettingPtr ms = modesettingPTR(pScrn);
558 VisualPtr visual;
559
560 if (!drv_init_drm(pScrn)) {
561 FatalError("Could not init DRM");
562 return FALSE;
563 }
564
565 if (!drv_init_resource_management(pScrn)) {
566 FatalError("Could not init resource management (!pipe_screen && !libkms)");
567 return FALSE;
568 }
569
570 if (!drv_init_front_buffer_functions(pScrn)) {
571 FatalError("Could not init front buffer manager");
572 return FALSE;
573 }
574
575 pScrn->pScreen = pScreen;
576
577 /* HW dependent - FIXME */
578 pScrn->displayWidth = pScrn->virtualX;
579
580 miClearVisualTypes();
581
582 if (!miSetVisualTypes(pScrn->depth,
583 miGetDefaultVisualMask(pScrn->depth),
584 pScrn->rgbBits, pScrn->defaultVisual))
585 return FALSE;
586
587 if (!miSetPixmapDepths())
588 return FALSE;
589
590 pScrn->memPhysBase = 0;
591 pScrn->fbOffset = 0;
592
593 if (!fbScreenInit(pScreen, NULL,
594 pScrn->virtualX, pScrn->virtualY,
595 pScrn->xDpi, pScrn->yDpi,
596 pScrn->displayWidth, pScrn->bitsPerPixel))
597 return FALSE;
598
599 if (pScrn->bitsPerPixel > 8) {
600 /* Fixup RGB ordering */
601 visual = pScreen->visuals + pScreen->numVisuals;
602 while (--visual >= pScreen->visuals) {
603 if ((visual->class | DynamicClass) == DirectColor) {
604 visual->offsetRed = pScrn->offset.red;
605 visual->offsetGreen = pScrn->offset.green;
606 visual->offsetBlue = pScrn->offset.blue;
607 visual->redMask = pScrn->mask.red;
608 visual->greenMask = pScrn->mask.green;
609 visual->blueMask = pScrn->mask.blue;
610 }
611 }
612 }
613
614 fbPictureInit(pScreen, NULL, 0);
615
616 ms->blockHandler = pScreen->BlockHandler;
617 pScreen->BlockHandler = drv_block_handler;
618 ms->createScreenResources = pScreen->CreateScreenResources;
619 pScreen->CreateScreenResources = drv_create_screen_resources;
620
621 xf86SetBlackWhitePixels(pScreen);
622
623 if (ms->screen) {
624 ms->exa = xorg_exa_init(pScrn, xf86ReturnOptValBool(ms->Options,
625 OPTION_2D_ACCEL, TRUE));
626 ms->debug_fallback = debug_get_bool_option("XORG_DEBUG_FALLBACK", TRUE);
627
628 xorg_xv_init(pScreen);
629 #ifdef DRI2
630 xorg_dri2_init(pScreen);
631 #endif
632 }
633
634 miInitializeBackingStore(pScreen);
635 xf86SetBackingStore(pScreen);
636 xf86SetSilkenMouse(pScreen);
637 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
638
639 /* Need to extend HWcursor support to handle mask interleave */
640 if (!ms->SWCursor)
641 xf86_cursors_init(pScreen, 64, 64,
642 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
643 HARDWARE_CURSOR_ARGB);
644
645 /* Must force it before EnterVT, so we are in control of VT and
646 * later memory should be bound when allocating, e.g rotate_mem */
647 pScrn->vtSema = TRUE;
648
649 pScreen->SaveScreen = xf86SaveScreen;
650 ms->CloseScreen = pScreen->CloseScreen;
651 pScreen->CloseScreen = drv_close_screen;
652
653 if (!xf86CrtcScreenInit(pScreen))
654 return FALSE;
655
656 if (!miCreateDefColormap(pScreen))
657 return FALSE;
658
659 xf86DPMSInit(pScreen, xf86DPMSSet, 0);
660
661 if (serverGeneration == 1)
662 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
663
664 if (ms->winsys_screen_init)
665 ms->winsys_screen_init(pScrn);
666
667 return drv_enter_vt(scrnIndex, 1);
668 }
669
670 static void
671 drv_adjust_frame(int scrnIndex, int x, int y, int flags)
672 {
673 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
674 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
675 xf86OutputPtr output = config->output[config->compat_output];
676 xf86CrtcPtr crtc = output->crtc;
677
678 if (crtc && crtc->enabled) {
679 crtc->funcs->set_mode_major(crtc, pScrn->currentMode,
680 RR_Rotate_0, x, y);
681 crtc->x = output->initial_x + x;
682 crtc->y = output->initial_y + y;
683 }
684 }
685
686 static void
687 drv_free_screen(int scrnIndex, int flags)
688 {
689 drv_free_rec(xf86Screens[scrnIndex]);
690 }
691
692 static void
693 drv_leave_vt(int scrnIndex, int flags)
694 {
695 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
696 modesettingPtr ms = modesettingPTR(pScrn);
697 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
698 int o;
699
700 if (ms->winsys_leave_vt)
701 ms->winsys_leave_vt(pScrn);
702
703 for (o = 0; o < config->num_crtc; o++) {
704 xf86CrtcPtr crtc = config->crtc[o];
705
706 xorg_crtc_cursor_destroy(crtc);
707
708 if (crtc->rotatedPixmap || crtc->rotatedData) {
709 crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
710 crtc->rotatedData);
711 crtc->rotatedPixmap = NULL;
712 crtc->rotatedData = NULL;
713 }
714 }
715
716 drmModeRmFB(ms->fd, ms->fb_id);
717
718 drv_restore_hw_state(pScrn);
719
720 if (drmDropMaster(ms->fd))
721 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
722 "drmDropMaster failed: %s\n", strerror(errno));
723
724 pScrn->vtSema = FALSE;
725 }
726
727 /*
728 * This gets called when gaining control of the VT, and from ScreenInit().
729 */
730 static Bool
731 drv_enter_vt(int scrnIndex, int flags)
732 {
733 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
734 modesettingPtr ms = modesettingPTR(pScrn);
735
736 if (drmSetMaster(ms->fd)) {
737 if (errno == EINVAL) {
738 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
739 "drmSetMaster failed: 2.6.29 or newer kernel required for "
740 "multi-server DRI\n");
741 } else {
742 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
743 "drmSetMaster failed: %s\n", strerror(errno));
744 }
745 }
746
747 /*
748 * Only save state once per server generation since that's what most
749 * drivers do. Could change this to save state at each VT enter.
750 */
751 if (ms->SaveGeneration != serverGeneration) {
752 ms->SaveGeneration = serverGeneration;
753 drv_save_hw_state(pScrn);
754 }
755
756 if (!ms->create_front_buffer(pScrn))
757 return FALSE;
758
759 if (!flags && !ms->bind_front_buffer(pScrn))
760 return FALSE;
761
762 if (!xf86SetDesiredModes(pScrn))
763 return FALSE;
764
765 if (ms->winsys_enter_vt)
766 ms->winsys_enter_vt(pScrn);
767
768 return TRUE;
769 }
770
771 static Bool
772 drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags)
773 {
774 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
775
776 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
777 }
778
779 static Bool
780 drv_close_screen(int scrnIndex, ScreenPtr pScreen)
781 {
782 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
783 modesettingPtr ms = modesettingPTR(pScrn);
784
785 if (pScrn->vtSema) {
786 drv_leave_vt(scrnIndex, 0);
787 }
788
789 if (ms->winsys_screen_close)
790 ms->winsys_screen_close(pScrn);
791
792 #ifdef DRI2
793 if (ms->screen)
794 xorg_dri2_close(pScreen);
795 #endif
796
797 pScreen->BlockHandler = ms->blockHandler;
798 pScreen->CreateScreenResources = ms->createScreenResources;
799
800 #ifdef DRM_MODE_FEATURE_DIRTYFB
801 if (ms->damage) {
802 DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage);
803 DamageDestroy(ms->damage);
804 ms->damage = NULL;
805 }
806 #endif
807
808 drmModeRmFB(ms->fd, ms->fb_id);
809 ms->destroy_front_buffer(pScrn);
810
811 if (ms->exa)
812 xorg_exa_close(pScrn);
813 ms->exa = NULL;
814
815 drv_close_resource_management(pScrn);
816
817 drmClose(ms->fd);
818 ms->fd = -1;
819
820 pScrn->vtSema = FALSE;
821 pScreen->CloseScreen = ms->CloseScreen;
822 return (*pScreen->CloseScreen) (scrnIndex, pScreen);
823 }
824
825 static ModeStatus
826 drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
827 {
828 return MODE_OK;
829 }
830
831
832 /*
833 * Front buffer backing store functions.
834 */
835
836 static Bool
837 drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn)
838 {
839 modesettingPtr ms = modesettingPTR(pScrn);
840 pipe_texture_reference(&ms->root_texture, NULL);
841 return TRUE;
842 }
843
844 static Bool
845 drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn)
846 {
847 modesettingPtr ms = modesettingPTR(pScrn);
848 unsigned handle, stride;
849 struct pipe_texture *tex;
850 int ret;
851
852 ms->noEvict = TRUE;
853
854 tex = xorg_exa_create_root_texture(pScrn, pScrn->virtualX, pScrn->virtualY,
855 pScrn->depth, pScrn->bitsPerPixel);
856
857 if (!tex)
858 return FALSE;
859
860 if (!ms->api->local_handle_from_texture(ms->api, ms->screen,
861 tex,
862 &stride,
863 &handle))
864 goto err_destroy;
865
866 ret = drmModeAddFB(ms->fd,
867 pScrn->virtualX,
868 pScrn->virtualY,
869 pScrn->depth,
870 pScrn->bitsPerPixel,
871 stride,
872 handle,
873 &ms->fb_id);
874 if (ret) {
875 debug_printf("%s: failed to create framebuffer (%i, %s)",
876 __func__, ret, strerror(-ret));
877 goto err_destroy;
878 }
879
880 pScrn->frameX0 = 0;
881 pScrn->frameY0 = 0;
882 drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
883
884 pipe_texture_reference(&ms->root_texture, tex);
885 pipe_texture_reference(&tex, NULL);
886
887 return TRUE;
888
889 err_destroy:
890 pipe_texture_reference(&tex, NULL);
891 return FALSE;
892 }
893
894 static Bool
895 drv_bind_front_buffer_ga3d(ScrnInfoPtr pScrn)
896 {
897 modesettingPtr ms = modesettingPTR(pScrn);
898 ScreenPtr pScreen = pScrn->pScreen;
899 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
900 struct pipe_texture *check;
901
902 xorg_exa_set_displayed_usage(rootPixmap);
903 xorg_exa_set_shared_usage(rootPixmap);
904 xorg_exa_set_texture(rootPixmap, ms->root_texture);
905 if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
906 FatalError("Couldn't adjust screen pixmap\n");
907
908 check = xorg_exa_get_texture(rootPixmap);
909 if (ms->root_texture != check)
910 FatalError("Created new root texture\n");
911
912 pipe_texture_reference(&check, NULL);
913 return TRUE;
914 }
915
916 #ifdef HAVE_LIBKMS
917 static Bool
918 drv_destroy_front_buffer_kms(ScrnInfoPtr pScrn)
919 {
920 modesettingPtr ms = modesettingPTR(pScrn);
921 ScreenPtr pScreen = pScrn->pScreen;
922 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
923
924 if (!ms->root_bo)
925 return TRUE;
926
927 kms_bo_unmap(ms->root_bo);
928 kms_bo_destroy(&ms->root_bo);
929 return TRUE;
930 }
931
932 static Bool
933 drv_create_front_buffer_kms(ScrnInfoPtr pScrn)
934 {
935 modesettingPtr ms = modesettingPTR(pScrn);
936 unsigned handle, stride;
937 struct kms_bo *bo;
938 unsigned attr[8];
939 int ret;
940
941 attr[0] = KMS_BO_TYPE;
942 attr[1] = KMS_BO_TYPE_SCANOUT;
943 attr[2] = KMS_WIDTH;
944 attr[3] = pScrn->virtualX;
945 attr[4] = KMS_HEIGHT;
946 attr[5] = pScrn->virtualY;
947 attr[6] = 0;
948
949 if (kms_bo_create(ms->kms, attr, &bo))
950 return FALSE;
951
952 if (kms_bo_get_prop(bo, KMS_PITCH, &stride))
953 goto err_destroy;
954
955 if (kms_bo_get_prop(bo, KMS_HANDLE, &handle))
956 goto err_destroy;
957
958 ret = drmModeAddFB(ms->fd,
959 pScrn->virtualX,
960 pScrn->virtualY,
961 pScrn->depth,
962 pScrn->bitsPerPixel,
963 stride,
964 handle,
965 &ms->fb_id);
966 if (ret) {
967 debug_printf("%s: failed to create framebuffer (%i, %s)",
968 __func__, ret, strerror(-ret));
969 goto err_destroy;
970 }
971
972 pScrn->frameX0 = 0;
973 pScrn->frameY0 = 0;
974 drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
975 ms->root_bo = bo;
976
977 return TRUE;
978
979 err_destroy:
980 kms_bo_destroy(&bo);
981 return FALSE;
982 }
983
984 static Bool
985 drv_bind_front_buffer_kms(ScrnInfoPtr pScrn)
986 {
987 modesettingPtr ms = modesettingPTR(pScrn);
988 ScreenPtr pScreen = pScrn->pScreen;
989 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
990 unsigned stride;
991 void *ptr;
992
993 if (kms_bo_get_prop(ms->root_bo, KMS_PITCH, &stride))
994 return FALSE;
995
996 if (kms_bo_map(ms->root_bo, &ptr))
997 goto err_destroy;
998
999 pScreen->ModifyPixmapHeader(rootPixmap,
1000 pScreen->width,
1001 pScreen->height,
1002 pScreen->rootDepth,
1003 pScrn->bitsPerPixel,
1004 stride,
1005 ptr);
1006 return TRUE;
1007
1008 err_destroy:
1009 kms_bo_destroy(&ms->root_bo);
1010 return FALSE;
1011 }
1012 #endif /* HAVE_LIBKMS */
1013
1014 static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn)
1015 {
1016 modesettingPtr ms = modesettingPTR(pScrn);
1017 if (ms->screen) {
1018 ms->destroy_front_buffer = drv_destroy_front_buffer_ga3d;
1019 ms->create_front_buffer = drv_create_front_buffer_ga3d;
1020 ms->bind_front_buffer = drv_bind_front_buffer_ga3d;
1021 #ifdef HAVE_LIBKMS
1022 } else if (ms->kms) {
1023 ms->destroy_front_buffer = drv_destroy_front_buffer_kms;
1024 ms->create_front_buffer = drv_create_front_buffer_kms;
1025 ms->bind_front_buffer = drv_bind_front_buffer_kms;
1026 #endif
1027 } else
1028 return FALSE;
1029
1030 return TRUE;
1031 }
1032
1033 /* vim: set sw=4 ts=8 sts=4: */