2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
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.
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
32 #include "xorg-server.h"
34 #include "xf86_OSproc.h"
37 #include "xf86PciInfo.h"
39 #include "xf86Resources.h"
40 #include "mipointer.h"
42 #include <X11/extensions/randr.h>
47 #include "miscstruct.h"
48 #include "dixstruct.h"
50 #include <X11/extensions/Xv.h>
51 #ifndef XSERVER_LIBPCIACCESS
52 #error "libpciaccess needed"
55 #include <pciaccess.h>
57 #include "pipe/p_context.h"
58 #include "xorg_tracker.h"
59 #include "xorg_winsys.h"
61 static void AdjustFrame(int scrnIndex
, int x
, int y
, int flags
);
62 static Bool
CloseScreen(int scrnIndex
, ScreenPtr pScreen
);
63 static Bool
EnterVT(int scrnIndex
, int flags
);
64 static Bool
SaveHWState(ScrnInfoPtr pScrn
);
65 static Bool
RestoreHWState(ScrnInfoPtr pScrn
);
68 static ModeStatus
ValidMode(int scrnIndex
, DisplayModePtr mode
, Bool verbose
,
70 static void FreeScreen(int scrnIndex
, int flags
);
71 static void LeaveVT(int scrnIndex
, int flags
);
72 static Bool
SwitchMode(int scrnIndex
, DisplayModePtr mode
, int flags
);
73 static Bool
ScreenInit(int scrnIndex
, ScreenPtr pScreen
, int argc
,
75 static Bool
PreInit(ScrnInfoPtr pScrn
, int flags
);
82 static const OptionInfoRec Options
[] = {
83 {OPTION_SW_CURSOR
, "SWcursor", OPTV_BOOLEAN
, {0}, FALSE
},
84 {-1, NULL
, OPTV_NONE
, {0}, FALSE
}
88 * Functions that might be needed
91 static const char *exaSymbols
[] = {
101 static const char *fbSymbols
[] = {
107 static const char *ddcSymbols
[] = {
109 "xf86SetDDCproperties",
114 * Exported Xorg driver functions to winsys
118 xorg_tracker_loader_ref_sym_lists()
120 LoaderRefSymLists(exaSymbols
, fbSymbols
, ddcSymbols
, NULL
);
123 const OptionInfoRec
*
124 xorg_tracker_available_options(int chipid
, int busid
)
130 xorg_tracker_set_functions(ScrnInfoPtr scrn
)
132 scrn
->PreInit
= PreInit
;
133 scrn
->ScreenInit
= ScreenInit
;
134 scrn
->SwitchMode
= SwitchMode
;
135 scrn
->AdjustFrame
= AdjustFrame
;
136 scrn
->EnterVT
= EnterVT
;
137 scrn
->LeaveVT
= LeaveVT
;
138 scrn
->FreeScreen
= FreeScreen
;
139 scrn
->ValidMode
= ValidMode
;
143 * Static Xorg funtctions
147 GetRec(ScrnInfoPtr pScrn
)
149 if (pScrn
->driverPrivate
)
152 pScrn
->driverPrivate
= xnfcalloc(sizeof(modesettingRec
), 1);
158 FreeRec(ScrnInfoPtr pScrn
)
163 if (!pScrn
->driverPrivate
)
166 xfree(pScrn
->driverPrivate
);
168 pScrn
->driverPrivate
= NULL
;
172 ProbeDDC(ScrnInfoPtr pScrn
, int index
)
174 ConfiguredMonitor
= NULL
;
178 CreateFrontBuffer(ScrnInfoPtr pScrn
)
180 modesettingPtr ms
= modesettingPTR(pScrn
);
181 ScreenPtr pScreen
= pScrn
->pScreen
;
182 PixmapPtr rootPixmap
= pScreen
->GetScreenPixmap(pScreen
);
183 unsigned handle
, stride
;
186 xorg_exa_set_displayed_usage(rootPixmap
);
187 pScreen
->ModifyPixmapHeader(rootPixmap
,
188 pScrn
->virtualX
, pScrn
->virtualY
,
189 pScrn
->depth
, pScrn
->bitsPerPixel
,
190 pScrn
->displayWidth
* pScrn
->bitsPerPixel
/ 8,
194 handle
= xorg_exa_get_pixmap_handle(rootPixmap
, &stride
);
207 AdjustFrame(pScrn
->scrnIndex
, pScrn
->frameX0
, pScrn
->frameY0
, 0);
213 crtc_resize(ScrnInfoPtr pScrn
, int width
, int height
)
215 modesettingPtr ms
= modesettingPTR(pScrn
);
216 //ScreenPtr pScreen = pScrn->pScreen;
217 //PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
218 //Bool fbAccessDisabled;
221 if (width
== pScrn
->virtualX
&& height
== pScrn
->virtualY
)
224 ErrorF("RESIZING TO %dx%d\n", width
, height
);
226 pScrn
->virtualX
= width
;
227 pScrn
->virtualY
= height
;
229 /* HW dependent - FIXME */
230 pScrn
->displayWidth
= pScrn
->virtualX
;
232 drmModeRmFB(ms
->fd
, ms
->fb_id
);
234 /* now create new frontbuffer */
235 return CreateFrontBuffer(pScrn
);
238 static const xf86CrtcConfigFuncsRec crtc_config_funcs
= {
243 PreInit(ScrnInfoPtr pScrn
, int flags
)
245 xf86CrtcConfigPtr xf86_config
;
247 rgb defaultWeight
= { 0, 0, 0 };
251 int max_width
, max_height
;
253 if (pScrn
->numEntities
!= 1)
256 pEnt
= xf86GetEntityInfo(pScrn
->entityList
[0]);
258 if (flags
& PROBE_DETECT
) {
259 ProbeDDC(pScrn
, pEnt
->index
);
263 /* Allocate driverPrivate */
267 ms
= modesettingPTR(pScrn
);
268 ms
->SaveGeneration
= -1;
271 pScrn
->displayWidth
= 640; /* default it */
273 if (ms
->pEnt
->location
.type
!= BUS_PCI
)
276 ms
->PciInfo
= xf86GetPciInfoForEntity(ms
->pEnt
->index
);
278 /* Allocate an entity private if necessary */
279 if (xf86IsEntityShared(pScrn
->entityList
[0])) {
280 FatalError("Entity");
282 msEnt
= xf86GetEntityPrivate(pScrn
->entityList
[0],
283 modesettingEntityIndex
)->ptr
;
284 ms
->entityPrivate
= msEnt
;
289 ms
->entityPrivate
= NULL
;
291 if (xf86RegisterResources(ms
->pEnt
->index
, NULL
, ResNone
)) {
295 if (xf86IsEntityShared(pScrn
->entityList
[0])) {
296 if (xf86IsPrimInitDone(pScrn
->entityList
[0])) {
299 xf86SetPrimInitDone(pScrn
->entityList
[0]);
304 sprintf(BusID
, "PCI:%d:%d:%d",
305 ((ms
->PciInfo
->domain
<< 8) | ms
->PciInfo
->bus
),
306 ms
->PciInfo
->dev
, ms
->PciInfo
->func
309 ms
->api
= drm_api_create();
310 ms
->fd
= drmOpen(NULL
, BusID
);
315 pScrn
->racMemFlags
= RAC_FB
| RAC_COLORMAP
;
316 pScrn
->monitor
= pScrn
->confScreen
->monitor
;
317 pScrn
->progClock
= TRUE
;
322 PreferConvert24to32
| SupportConvert24to32
| Support32bppFb
))
325 switch (pScrn
->depth
) {
331 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
332 "Given depth (%d) is not supported by the driver\n",
336 xf86PrintDepthBpp(pScrn
);
338 if (!xf86SetWeight(pScrn
, defaultWeight
, defaultWeight
))
340 if (!xf86SetDefaultVisual(pScrn
, -1))
343 /* Process the options */
344 xf86CollectOptions(pScrn
, NULL
);
345 if (!(ms
->Options
= xalloc(sizeof(Options
))))
347 memcpy(ms
->Options
, Options
, sizeof(Options
));
348 xf86ProcessOptions(pScrn
->scrnIndex
, pScrn
->options
, ms
->Options
);
350 /* Allocate an xf86CrtcConfig */
351 xf86CrtcConfigInit(pScrn
, &crtc_config_funcs
);
352 xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
356 xf86CrtcSetSizeRange(pScrn
, 320, 200, max_width
, max_height
);
358 if (xf86ReturnOptValBool(ms
->Options
, OPTION_SW_CURSOR
, FALSE
)) {
367 if (!xf86InitialConfiguration(pScrn
, TRUE
)) {
368 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "No valid modes.\n");
369 RestoreHWState(pScrn
);
373 RestoreHWState(pScrn
);
376 * If the driver can do gamma correction, it should call xf86SetGamma() here.
379 Gamma zeros
= { 0.0, 0.0, 0.0 };
381 if (!xf86SetGamma(pScrn
, zeros
)) {
386 if (pScrn
->modes
== NULL
) {
387 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "No modes.\n");
391 pScrn
->currentMode
= pScrn
->modes
;
393 /* Set display resolution */
394 xf86SetDpi(pScrn
, 0, 0);
396 /* Load the required sub modules */
397 if (!xf86LoadSubModule(pScrn
, "fb")) {
401 xf86LoaderReqSymLists(fbSymbols
, NULL
);
403 xf86LoadSubModule(pScrn
, "exa");
406 xf86LoadSubModule(pScrn
, "dri2");
413 SaveHWState(ScrnInfoPtr pScrn
)
415 /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
421 RestoreHWState(ScrnInfoPtr pScrn
)
423 /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
428 static void xorgBlockHandler(int i
, pointer blockData
, pointer pTimeout
,
431 ScreenPtr pScreen
= screenInfo
.screens
[i
];
432 modesettingPtr ms
= modesettingPTR(xf86Screens
[pScreen
->myNum
]);
434 pScreen
->BlockHandler
= ms
->blockHandler
;
435 pScreen
->BlockHandler(i
, blockData
, pTimeout
, pReadmask
);
436 pScreen
->BlockHandler
= xorgBlockHandler
;
438 ms
->ctx
->flush(ms
->ctx
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
440 #ifdef DRM_MODE_FEATURE_DIRTYFB
442 RegionPtr dirty
= DamageRegion(ms
->damage
);
443 unsigned num_cliprects
= REGION_NUM_RECTS(dirty
);
446 drmModeClip
*clip
= alloca(num_cliprects
* sizeof(drmModeClip
));
447 BoxPtr rect
= REGION_RECTS(dirty
);
450 for (i
= 0; i
< num_cliprects
; i
++, rect
++) {
451 clip
[i
].x
= rect
->x1
;
452 clip
[i
].y
= rect
->y1
;
453 clip
[i
].width
= rect
->x2
- rect
->x1
;
454 clip
[i
].height
= rect
->y2
- rect
->y1
;
457 /* TODO query connector property to see if this is needed */
458 drmModeDirtyFB(ms
->fd
, ms
->fb_id
, clip
, num_cliprects
);
460 DamageEmpty(ms
->damage
);
467 CreateScreenResources(ScreenPtr pScreen
)
469 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
470 modesettingPtr ms
= modesettingPTR(pScrn
);
471 PixmapPtr rootPixmap
;
473 unsigned handle
, stride
;
477 pScreen
->CreateScreenResources
= ms
->createScreenResources
;
478 ret
= pScreen
->CreateScreenResources(pScreen
);
479 pScreen
->CreateScreenResources
= CreateScreenResources
;
481 rootPixmap
= pScreen
->GetScreenPixmap(pScreen
);
483 xorg_exa_set_displayed_usage(rootPixmap
);
484 xorg_exa_set_shared_usage(rootPixmap
);
485 if (!pScreen
->ModifyPixmapHeader(rootPixmap
, -1, -1, -1, -1, -1, NULL
))
486 FatalError("Couldn't adjust screen pixmap\n");
490 handle
= xorg_exa_get_pixmap_handle(rootPixmap
, &stride
);
501 AdjustFrame(pScrn
->scrnIndex
, pScrn
->frameX0
, pScrn
->frameY0
, 0);
503 #ifdef DRM_MODE_FEATURE_DIRTYFB
504 ms
->damage
= DamageCreate(NULL
, NULL
, DamageReportNone
, TRUE
,
505 pScreen
, rootPixmap
);
508 DamageRegister(&rootPixmap
->drawable
, ms
->damage
);
510 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "Damage tracking initialized\n");
512 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
513 "Failed to create screen damage record\n");
522 ScreenInit(int scrnIndex
, ScreenPtr pScreen
, int argc
, char **argv
)
524 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
525 modesettingPtr ms
= modesettingPTR(pScrn
);
528 /* deal with server regeneration */
533 sprintf(BusID
, "PCI:%d:%d:%d",
534 ((ms
->PciInfo
->domain
<< 8) | ms
->PciInfo
->bus
),
535 ms
->PciInfo
->dev
, ms
->PciInfo
->func
538 ms
->fd
= drmOpen(NULL
, BusID
);
545 ms
->screen
= ms
->api
->create_screen(ms
->api
, ms
->fd
, NULL
);
548 FatalError("Could not init pipe_screen\n");
553 pScrn
->pScreen
= pScreen
;
555 /* HW dependent - FIXME */
556 pScrn
->displayWidth
= pScrn
->virtualX
;
558 miClearVisualTypes();
560 if (!miSetVisualTypes(pScrn
->depth
,
561 miGetDefaultVisualMask(pScrn
->depth
),
562 pScrn
->rgbBits
, pScrn
->defaultVisual
))
565 if (!miSetPixmapDepths())
568 pScrn
->memPhysBase
= 0;
571 if (!fbScreenInit(pScreen
, NULL
,
572 pScrn
->virtualX
, pScrn
->virtualY
,
573 pScrn
->xDpi
, pScrn
->yDpi
,
574 pScrn
->displayWidth
, pScrn
->bitsPerPixel
))
577 if (pScrn
->bitsPerPixel
> 8) {
578 /* Fixup RGB ordering */
579 visual
= pScreen
->visuals
+ pScreen
->numVisuals
;
580 while (--visual
>= pScreen
->visuals
) {
581 if ((visual
->class | DynamicClass
) == DirectColor
) {
582 visual
->offsetRed
= pScrn
->offset
.red
;
583 visual
->offsetGreen
= pScrn
->offset
.green
;
584 visual
->offsetBlue
= pScrn
->offset
.blue
;
585 visual
->redMask
= pScrn
->mask
.red
;
586 visual
->greenMask
= pScrn
->mask
.green
;
587 visual
->blueMask
= pScrn
->mask
.blue
;
592 fbPictureInit(pScreen
, NULL
, 0);
594 ms
->blockHandler
= pScreen
->BlockHandler
;
595 pScreen
->BlockHandler
= xorgBlockHandler
;
596 ms
->createScreenResources
= pScreen
->CreateScreenResources
;
597 pScreen
->CreateScreenResources
= CreateScreenResources
;
599 xf86SetBlackWhitePixels(pScreen
);
601 ms
->exa
= xorg_exa_init(pScrn
);
603 miInitializeBackingStore(pScreen
);
604 xf86SetBackingStore(pScreen
);
605 xf86SetSilkenMouse(pScreen
);
606 miDCInitialize(pScreen
, xf86GetPointerScreenFuncs());
608 /* Need to extend HWcursor support to handle mask interleave */
610 xf86_cursors_init(pScreen
, 64, 64,
611 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
|
612 HARDWARE_CURSOR_ARGB
);
614 /* Must force it before EnterVT, so we are in control of VT and
615 * later memory should be bound when allocating, e.g rotate_mem */
616 pScrn
->vtSema
= TRUE
;
618 pScreen
->SaveScreen
= xf86SaveScreen
;
619 ms
->CloseScreen
= pScreen
->CloseScreen
;
620 pScreen
->CloseScreen
= CloseScreen
;
622 if (!xf86CrtcScreenInit(pScreen
))
625 if (!miCreateDefColormap(pScreen
))
628 xf86DPMSInit(pScreen
, xf86DPMSSet
, 0);
630 if (serverGeneration
== 1)
631 xf86ShowUnusedOptions(pScrn
->scrnIndex
, pScrn
->options
);
635 driScreenInit(pScreen
);
639 return EnterVT(scrnIndex
, 1);
643 AdjustFrame(int scrnIndex
, int x
, int y
, int flags
)
645 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
646 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
647 xf86OutputPtr output
= config
->output
[config
->compat_output
];
648 xf86CrtcPtr crtc
= output
->crtc
;
650 if (crtc
&& crtc
->enabled
) {
651 crtc
->funcs
->mode_set(crtc
, pScrn
->currentMode
, pScrn
->currentMode
, x
,
653 crtc
->x
= output
->initial_x
+ x
;
654 crtc
->y
= output
->initial_y
+ y
;
659 FreeScreen(int scrnIndex
, int flags
)
661 FreeRec(xf86Screens
[scrnIndex
]);
665 LeaveVT(int scrnIndex
, int flags
)
667 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
668 modesettingPtr ms
= modesettingPTR(pScrn
);
669 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
672 for (o
= 0; o
< config
->num_crtc
; o
++) {
673 xf86CrtcPtr crtc
= config
->crtc
[o
];
675 crtc_cursor_destroy(crtc
);
677 if (crtc
->rotatedPixmap
|| crtc
->rotatedData
) {
678 crtc
->funcs
->shadow_destroy(crtc
, crtc
->rotatedPixmap
,
680 crtc
->rotatedPixmap
= NULL
;
681 crtc
->rotatedData
= NULL
;
685 drmModeRmFB(ms
->fd
, ms
->fb_id
);
687 RestoreHWState(pScrn
);
689 if (drmDropMaster(ms
->fd
))
690 xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
691 "drmDropMaster failed: %s\n", strerror(errno
));
693 pScrn
->vtSema
= FALSE
;
697 * This gets called when gaining control of the VT, and from ScreenInit().
700 EnterVT(int scrnIndex
, int flags
)
702 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
703 modesettingPtr ms
= modesettingPTR(pScrn
);
705 if (drmSetMaster(ms
->fd
)) {
706 if (errno
== EINVAL
) {
707 xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
708 "drmSetMaster failed: 2.6.29 or newer kernel required for "
709 "multi-server DRI\n");
711 xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
712 "drmSetMaster failed: %s\n", strerror(errno
));
717 * Only save state once per server generation since that's what most
718 * drivers do. Could change this to save state at each VT enter.
720 if (ms
->SaveGeneration
!= serverGeneration
) {
721 ms
->SaveGeneration
= serverGeneration
;
725 if (!flags
) /* signals startup as we'll do this in CreateScreenResources */
726 CreateFrontBuffer(pScrn
);
728 if (!xf86SetDesiredModes(pScrn
))
735 SwitchMode(int scrnIndex
, DisplayModePtr mode
, int flags
)
737 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
739 return xf86SetSingleMode(pScrn
, mode
, RR_Rotate_0
);
743 CloseScreen(int scrnIndex
, ScreenPtr pScreen
)
745 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
746 modesettingPtr ms
= modesettingPTR(pScrn
);
749 LeaveVT(scrnIndex
, 0);
752 driCloseScreen(pScreen
);
755 pScreen
->BlockHandler
= ms
->blockHandler
;
756 pScreen
->CreateScreenResources
= ms
->createScreenResources
;
758 #ifdef DRM_MODE_FEATURE_DIRTYFB
760 DamageUnregister(&pScreen
->GetScreenPixmap(pScreen
)->drawable
, ms
->damage
);
761 DamageDestroy(ms
->damage
);
767 xorg_exa_close(pScrn
);
769 ms
->api
->destroy(ms
->api
);
774 pScrn
->vtSema
= FALSE
;
775 pScreen
->CloseScreen
= ms
->CloseScreen
;
776 return (*pScreen
->CloseScreen
) (scrnIndex
, pScreen
);
780 ValidMode(int scrnIndex
, DisplayModePtr mode
, Bool verbose
, int flags
)
785 /* vim: set sw=4 ts=8 sts=4: */