summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/xorg/xorg_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/xorg/xorg_driver.c')
-rw-r--r--src/gallium/state_trackers/xorg/xorg_driver.c695
1 files changed, 695 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c
new file mode 100644
index 00000000000..d166a365ac5
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_driver.c
@@ -0,0 +1,695 @@
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 "xf86RAC.h"
37#include "xf86PciInfo.h"
38#include "xf86Pci.h"
39#include "xf86Resources.h"
40#include "mipointer.h"
41#include "micmap.h"
42#include <X11/extensions/randr.h>
43#include "fb.h"
44#include "edid.h"
45#include "xf86i2c.h"
46#include "xf86Crtc.h"
47#include "miscstruct.h"
48#include "dixstruct.h"
49#include "xf86xv.h"
50#include <X11/extensions/Xv.h>
51#ifndef XSERVER_LIBPCIACCESS
52#error "libpciaccess needed"
53#endif
54
55#include <pciaccess.h>
56
57#include "xorg_tracker.h"
58#include "xorg_winsys.h"
59
60static void AdjustFrame(int scrnIndex, int x, int y, int flags);
61static Bool CloseScreen(int scrnIndex, ScreenPtr pScreen);
62static Bool EnterVT(int scrnIndex, int flags);
63static Bool SaveHWState(ScrnInfoPtr pScrn);
64static Bool RestoreHWState(ScrnInfoPtr pScrn);
65
66
67static ModeStatus ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose,
68 int flags);
69static void FreeScreen(int scrnIndex, int flags);
70static void LeaveVT(int scrnIndex, int flags);
71static Bool SwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
72static Bool ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
73 char **argv);
74static Bool PreInit(ScrnInfoPtr pScrn, int flags);
75
76typedef enum
77{
78 OPTION_SW_CURSOR,
79} modesettingOpts;
80
81static const OptionInfoRec Options[] = {
82 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
83 {-1, NULL, OPTV_NONE, {0}, FALSE}
84};
85
86/*
87 * Functions that might be needed
88 */
89
90static const char *exaSymbols[] = {
91 "exaGetVersion",
92 "exaDriverInit",
93 "exaDriverFini",
94 "exaOffscreenAlloc",
95 "exaOffscreenFree",
96 "exaWaitSync",
97 NULL
98};
99
100static const char *fbSymbols[] = {
101 "fbPictureInit",
102 "fbScreenInit",
103 NULL
104};
105
106static const char *ddcSymbols[] = {
107 "xf86PrintEDID",
108 "xf86SetDDCproperties",
109 NULL
110};
111
112/*
113 * Exported Xorg driver functions to winsys
114 */
115
116void
117xorg_tracker_loader_ref_sym_lists()
118{
119 LoaderRefSymLists(exaSymbols, fbSymbols, ddcSymbols, NULL);
120}
121
122const OptionInfoRec *
123xorg_tracker_available_options(int chipid, int busid)
124{
125 return Options;
126}
127
128void
129xorg_tracker_set_functions(ScrnInfoPtr scrn)
130{
131 scrn->PreInit = PreInit;
132 scrn->ScreenInit = ScreenInit;
133 scrn->SwitchMode = SwitchMode;
134 scrn->AdjustFrame = AdjustFrame;
135 scrn->EnterVT = EnterVT;
136 scrn->LeaveVT = LeaveVT;
137 scrn->FreeScreen = FreeScreen;
138 scrn->ValidMode = ValidMode;
139}
140
141/*
142 * Static Xorg funtctions
143 */
144
145static Bool
146GetRec(ScrnInfoPtr pScrn)
147{
148 if (pScrn->driverPrivate)
149 return TRUE;
150
151 pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1);
152
153 return TRUE;
154}
155
156static void
157FreeRec(ScrnInfoPtr pScrn)
158{
159 if (!pScrn)
160 return;
161
162 if (!pScrn->driverPrivate)
163 return;
164
165 xfree(pScrn->driverPrivate);
166
167 pScrn->driverPrivate = NULL;
168}
169
170static void
171ProbeDDC(ScrnInfoPtr pScrn, int index)
172{
173 ConfiguredMonitor = NULL;
174}
175
176static Bool
177CreateFrontBuffer(ScrnInfoPtr pScrn)
178{
179 modesettingPtr ms = modesettingPTR(pScrn);
180 ScreenPtr pScreen = pScrn->pScreen;
181 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
182
183 ms->noEvict = TRUE;
184 pScreen->ModifyPixmapHeader(rootPixmap,
185 pScrn->virtualX, pScrn->virtualY,
186 pScrn->depth, pScrn->bitsPerPixel,
187 pScrn->displayWidth * pScrn->bitsPerPixel / 8,
188 NULL);
189 ms->noEvict = FALSE;
190
191 drmModeAddFB(ms->fd,
192 pScrn->virtualX,
193 pScrn->virtualY,
194 pScrn->depth,
195 pScrn->bitsPerPixel,
196 pScrn->displayWidth * pScrn->bitsPerPixel / 8,
197 xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id);
198
199 pScrn->frameX0 = 0;
200 pScrn->frameY0 = 0;
201 AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
202
203 return TRUE;
204}
205
206static Bool
207crtc_resize(ScrnInfoPtr pScrn, int width, int height)
208{
209 modesettingPtr ms = modesettingPTR(pScrn);
210 //ScreenPtr pScreen = pScrn->pScreen;
211 //PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
212 //Bool fbAccessDisabled;
213 //CARD8 *fbstart;
214
215 if (width == pScrn->virtualX && height == pScrn->virtualY)
216 return TRUE;
217
218 ErrorF("RESIZING TO %dx%d\n", width, height);
219
220 pScrn->virtualX = width;
221 pScrn->virtualY = height;
222
223 /* HW dependent - FIXME */
224 pScrn->displayWidth = pScrn->virtualX;
225
226 drmModeRmFB(ms->fd, ms->fb_id);
227
228 /* now create new frontbuffer */
229 return CreateFrontBuffer(pScrn);
230}
231
232static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
233 crtc_resize
234};
235
236static Bool
237PreInit(ScrnInfoPtr pScrn, int flags)
238{
239 xf86CrtcConfigPtr xf86_config;
240 modesettingPtr ms;
241 rgb defaultWeight = { 0, 0, 0 };
242 EntityInfoPtr pEnt;
243 EntPtr msEnt = NULL;
244 char *BusID;
245 int max_width, max_height;
246
247 if (pScrn->numEntities != 1)
248 return FALSE;
249
250 pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
251
252 if (flags & PROBE_DETECT) {
253 ProbeDDC(pScrn, pEnt->index);
254 return TRUE;
255 }
256
257 /* Allocate driverPrivate */
258 if (!GetRec(pScrn))
259 return FALSE;
260
261 ms = modesettingPTR(pScrn);
262 ms->SaveGeneration = -1;
263 ms->pEnt = pEnt;
264
265 pScrn->displayWidth = 640; /* default it */
266
267 if (ms->pEnt->location.type != BUS_PCI)
268 return FALSE;
269
270 ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
271
272 /* Allocate an entity private if necessary */
273 if (xf86IsEntityShared(pScrn->entityList[0])) {
274 FatalError("Entity");
275#if 0
276 msEnt = xf86GetEntityPrivate(pScrn->entityList[0],
277 modesettingEntityIndex)->ptr;
278 ms->entityPrivate = msEnt;
279#else
280 (void)msEnt;
281#endif
282 } else
283 ms->entityPrivate = NULL;
284
285 if (xf86RegisterResources(ms->pEnt->index, NULL, ResNone)) {
286 return FALSE;
287 }
288
289 if (xf86IsEntityShared(pScrn->entityList[0])) {
290 if (xf86IsPrimInitDone(pScrn->entityList[0])) {
291 /* do something */
292 } else {
293 xf86SetPrimInitDone(pScrn->entityList[0]);
294 }
295 }
296
297 BusID = xalloc(64);
298 sprintf(BusID, "PCI:%d:%d:%d",
299 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
300 ms->PciInfo->dev, ms->PciInfo->func
301 );
302
303 ms->fd = drmOpen(NULL, BusID);
304
305 if (ms->fd < 0)
306 return FALSE;
307
308 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
309 pScrn->monitor = pScrn->confScreen->monitor;
310 pScrn->progClock = TRUE;
311 pScrn->rgbBits = 8;
312
313 if (!xf86SetDepthBpp
314 (pScrn, 0, 0, 0,
315 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb))
316 return FALSE;
317
318 switch (pScrn->depth) {
319 case 15:
320 case 16:
321 case 24:
322 break;
323 default:
324 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
325 "Given depth (%d) is not supported by the driver\n",
326 pScrn->depth);
327 return FALSE;
328 }
329 xf86PrintDepthBpp(pScrn);
330
331 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
332 return FALSE;
333 if (!xf86SetDefaultVisual(pScrn, -1))
334 return FALSE;
335
336 /* Process the options */
337 xf86CollectOptions(pScrn, NULL);
338 if (!(ms->Options = xalloc(sizeof(Options))))
339 return FALSE;
340 memcpy(ms->Options, Options, sizeof(Options));
341 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);
342
343 /* Allocate an xf86CrtcConfig */
344 xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
345 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
346
347 max_width = 8192;
348 max_height = 8192;
349 xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height);
350
351 if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
352 ms->SWCursor = TRUE;
353 }
354
355 SaveHWState(pScrn);
356
357 crtc_init(pScrn);
358 output_init(pScrn);
359
360 if (!xf86InitialConfiguration(pScrn, TRUE)) {
361 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
362 RestoreHWState(pScrn);
363 return FALSE;
364 }
365
366 RestoreHWState(pScrn);
367
368 /*
369 * If the driver can do gamma correction, it should call xf86SetGamma() here.
370 */
371 {
372 Gamma zeros = { 0.0, 0.0, 0.0 };
373
374 if (!xf86SetGamma(pScrn, zeros)) {
375 return FALSE;
376 }
377 }
378
379 if (pScrn->modes == NULL) {
380 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
381 return FALSE;
382 }
383
384 pScrn->currentMode = pScrn->modes;
385
386 /* Set display resolution */
387 xf86SetDpi(pScrn, 0, 0);
388
389 /* Load the required sub modules */
390 if (!xf86LoadSubModule(pScrn, "fb")) {
391 return FALSE;
392 }
393
394 xf86LoaderReqSymLists(fbSymbols, NULL);
395
396 xf86LoadSubModule(pScrn, "exa");
397
398#ifdef DRI2
399 xf86LoadSubModule(pScrn, "dri2");
400#endif
401
402 return TRUE;
403}
404
405static Bool
406SaveHWState(ScrnInfoPtr pScrn)
407{
408 /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
409
410 return TRUE;
411}
412
413static Bool
414RestoreHWState(ScrnInfoPtr pScrn)
415{
416 /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
417
418 return TRUE;
419}
420
421static Bool
422CreateScreenResources(ScreenPtr pScreen)
423{
424 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
425 modesettingPtr ms = modesettingPTR(pScrn);
426 PixmapPtr rootPixmap;
427 Bool ret;
428
429 ms->noEvict = TRUE;
430
431 pScreen->CreateScreenResources = ms->createScreenResources;
432 ret = pScreen->CreateScreenResources(pScreen);
433 pScreen->CreateScreenResources = CreateScreenResources;
434
435 rootPixmap = pScreen->GetScreenPixmap(pScreen);
436
437 if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
438 FatalError("Couldn't adjust screen pixmap\n");
439
440 ms->noEvict = FALSE;
441
442 drmModeAddFB(ms->fd,
443 pScrn->virtualX,
444 pScrn->virtualY,
445 pScrn->depth,
446 pScrn->bitsPerPixel,
447 pScrn->displayWidth * pScrn->bitsPerPixel / 8,
448 xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id);
449
450 AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
451
452 return ret;
453}
454
455static Bool
456ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
457{
458 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
459 modesettingPtr ms = modesettingPTR(pScrn);
460 VisualPtr visual;
461
462 /* deal with server regeneration */
463 if (ms->fd < 0) {
464 char *BusID;
465
466 BusID = xalloc(64);
467 sprintf(BusID, "PCI:%d:%d:%d",
468 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
469 ms->PciInfo->dev, ms->PciInfo->func
470 );
471
472 ms->fd = drmOpen(NULL, BusID);
473
474 if (ms->fd < 0)
475 return FALSE;
476 }
477
478 if (!ms->screen) {
479 ms->screen = drm_api_hocks.create_screen(ms->fd, ms->PciInfo->device_id);
480
481 if (!ms->screen) {
482 FatalError("Could not init pipe_screen\n");
483 return FALSE;
484 }
485 }
486
487 pScrn->pScreen = pScreen;
488
489 /* HW dependent - FIXME */
490 pScrn->displayWidth = pScrn->virtualX;
491
492 miClearVisualTypes();
493
494 if (!miSetVisualTypes(pScrn->depth,
495 miGetDefaultVisualMask(pScrn->depth),
496 pScrn->rgbBits, pScrn->defaultVisual))
497 return FALSE;
498
499 if (!miSetPixmapDepths())
500 return FALSE;
501
502 pScrn->memPhysBase = 0;
503 pScrn->fbOffset = 0;
504
505 if (!fbScreenInit(pScreen, NULL,
506 pScrn->virtualX, pScrn->virtualY,
507 pScrn->xDpi, pScrn->yDpi,
508 pScrn->displayWidth, pScrn->bitsPerPixel))
509 return FALSE;
510
511 if (pScrn->bitsPerPixel > 8) {
512 /* Fixup RGB ordering */
513 visual = pScreen->visuals + pScreen->numVisuals;
514 while (--visual >= pScreen->visuals) {
515 if ((visual->class | DynamicClass) == DirectColor) {
516 visual->offsetRed = pScrn->offset.red;
517 visual->offsetGreen = pScrn->offset.green;
518 visual->offsetBlue = pScrn->offset.blue;
519 visual->redMask = pScrn->mask.red;
520 visual->greenMask = pScrn->mask.green;
521 visual->blueMask = pScrn->mask.blue;
522 }
523 }
524 }
525
526 fbPictureInit(pScreen, NULL, 0);
527
528 ms->createScreenResources = pScreen->CreateScreenResources;
529 pScreen->CreateScreenResources = CreateScreenResources;
530
531 xf86SetBlackWhitePixels(pScreen);
532
533 ms->exa = xorg_exa_init(pScrn);
534
535 miInitializeBackingStore(pScreen);
536 xf86SetBackingStore(pScreen);
537 xf86SetSilkenMouse(pScreen);
538 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
539
540 /* Need to extend HWcursor support to handle mask interleave */
541 if (!ms->SWCursor)
542 xf86_cursors_init(pScreen, 64, 64,
543 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
544 HARDWARE_CURSOR_ARGB);
545
546 /* Must force it before EnterVT, so we are in control of VT and
547 * later memory should be bound when allocating, e.g rotate_mem */
548 pScrn->vtSema = TRUE;
549
550 pScreen->SaveScreen = xf86SaveScreen;
551 ms->CloseScreen = pScreen->CloseScreen;
552 pScreen->CloseScreen = CloseScreen;
553
554 if (!xf86CrtcScreenInit(pScreen))
555 return FALSE;
556
557 if (!miCreateDefColormap(pScreen))
558 return FALSE;
559
560 xf86DPMSInit(pScreen, xf86DPMSSet, 0);
561
562 if (serverGeneration == 1)
563 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
564
565#if 1
566#ifdef DRI2
567 driScreenInit(pScreen);
568#endif
569#endif
570
571 return EnterVT(scrnIndex, 1);
572}
573
574static void
575AdjustFrame(int scrnIndex, int x, int y, int flags)
576{
577 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
578 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
579 xf86OutputPtr output = config->output[config->compat_output];
580 xf86CrtcPtr crtc = output->crtc;
581
582 if (crtc && crtc->enabled) {
583 crtc->funcs->mode_set(crtc, pScrn->currentMode, pScrn->currentMode, x,
584 y);
585 crtc->x = output->initial_x + x;
586 crtc->y = output->initial_y + y;
587 }
588}
589
590static void
591FreeScreen(int scrnIndex, int flags)
592{
593 FreeRec(xf86Screens[scrnIndex]);
594}
595
596/* HACK */
597void
598cursor_destroy(xf86CrtcPtr crtc);
599
600static void
601LeaveVT(int scrnIndex, int flags)
602{
603 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
604 modesettingPtr ms = modesettingPTR(pScrn);
605 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
606 int o;
607
608 for (o = 0; o < config->num_crtc; o++) {
609 xf86CrtcPtr crtc = config->crtc[o];
610
611 cursor_destroy(crtc);
612
613 if (crtc->rotatedPixmap || crtc->rotatedData) {
614 crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
615 crtc->rotatedData);
616 crtc->rotatedPixmap = NULL;
617 crtc->rotatedData = NULL;
618 }
619 }
620
621 drmModeRmFB(ms->fd, ms->fb_id);
622
623 RestoreHWState(pScrn);
624
625 pScrn->vtSema = FALSE;
626}
627
628/*
629 * This gets called when gaining control of the VT, and from ScreenInit().
630 */
631static Bool
632EnterVT(int scrnIndex, int flags)
633{
634 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
635 modesettingPtr ms = modesettingPTR(pScrn);
636
637 /*
638 * Only save state once per server generation since that's what most
639 * drivers do. Could change this to save state at each VT enter.
640 */
641 if (ms->SaveGeneration != serverGeneration) {
642 ms->SaveGeneration = serverGeneration;
643 SaveHWState(pScrn);
644 }
645
646 if (!flags) /* signals startup as we'll do this in CreateScreenResources */
647 CreateFrontBuffer(pScrn);
648
649 if (!xf86SetDesiredModes(pScrn))
650 return FALSE;
651
652 return TRUE;
653}
654
655static Bool
656SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
657{
658 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
659
660 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
661}
662
663static Bool
664CloseScreen(int scrnIndex, ScreenPtr pScreen)
665{
666 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
667 modesettingPtr ms = modesettingPTR(pScrn);
668
669 if (pScrn->vtSema) {
670 LeaveVT(scrnIndex, 0);
671 }
672#ifdef DRI2
673 driCloseScreen(pScreen);
674#endif
675
676 pScreen->CreateScreenResources = ms->createScreenResources;
677
678 if (ms->exa)
679 xorg_exa_close(pScrn);
680
681 drmClose(ms->fd);
682 ms->fd = -1;
683
684 pScrn->vtSema = FALSE;
685 pScreen->CloseScreen = ms->CloseScreen;
686 return (*pScreen->CloseScreen) (scrnIndex, pScreen);
687}
688
689static ModeStatus
690ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
691{
692 return MODE_OK;
693}
694
695/* vim: set sw=4 ts=8 sts=4: */