From 24bc15a386e37908396c3f6088f6fc98ceaa0f46 Mon Sep 17 00:00:00 2001 From: marha Date: Wed, 24 Feb 2010 18:34:17 +0000 Subject: Git update 24/2/2010" --- xorg-server/Xext/xselinux.h | 8 +- xorg-server/Xext/xselinux_ext.c | 41 +- xorg-server/Xext/xselinux_hooks.c | 73 +- xorg-server/Xext/xselinux_label.c | 23 +- xorg-server/Xi/exevents.c | 40 +- xorg-server/Xi/setmode.c | 10 + xorg-server/composite/compwindow.c | 2 +- xorg-server/configure.ac | 11 +- xorg-server/dix/devices.c | 8 - xorg-server/dix/events.c | 92 +- xorg-server/exa/exa_migration_mixed.c | 48 +- xorg-server/glx/glthread.c | 2 +- xorg-server/glx/glxdri2.c | 1617 ++--- xorg-server/hw/dmx/examples/xinput.c | 2 +- xorg-server/hw/kdrive/src/kdrive.c | 2 +- xorg-server/hw/xfree86/common/xf86Init.c | 2 +- xorg-server/hw/xfree86/modes/xf86Crtc.c | 6397 ++++++++++---------- .../hw/xfree86/os-support/solaris/sun_bell.c | 5 +- xorg-server/hw/xfree86/parser/scan.c | 16 +- xorg-server/hw/xfree86/x86emu/validate.c | 2 +- .../hw/xfree86/x86emu/x86emu/prim_x86_gcc.h | 6 +- xorg-server/hw/xquartz/GL/capabilities.c | 2 +- xorg-server/hw/xquartz/GL/indirect.c | 2 +- xorg-server/hw/xquartz/GL/visualConfigs.c | 3 +- xorg-server/hw/xquartz/X11Application.m | 18 +- xorg-server/hw/xquartz/darwinXinput.c | 6 + xorg-server/hw/xquartz/mach-startup/bundle-main.c | 30 +- xorg-server/hw/xquartz/mach-startup/stub.c | 7 - xorg-server/hw/xquartz/pbproxy/x-selection.h | 9 - xorg-server/hw/xquartz/quartzAudio.c | 35 +- xorg-server/hw/xquartz/quartzKeyboard.c | 2 +- xorg-server/include/dix-config.h.in | 900 ++- xorg-server/include/dix.h | 6 +- xorg-server/include/eventconvert.h | 6 +- xorg-server/include/os.h | 2 + xorg-server/miext/damage/damage.c | 10 +- xorg-server/miext/rootless/rootlessWindow.c | 2 +- xorg-server/os/log.c | 1206 ++-- xorg-server/os/utils.c | 12 + xorg-server/record/record.c | 115 +- 40 files changed, 5378 insertions(+), 5402 deletions(-) (limited to 'xorg-server') diff --git a/xorg-server/Xext/xselinux.h b/xorg-server/Xext/xselinux.h index dcd250e76..57239821e 100644 --- a/xorg-server/Xext/xselinux.h +++ b/xorg-server/Xext/xselinux.h @@ -23,7 +23,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Extension info */ #define SELINUX_EXTENSION_NAME "SELinux" #define SELINUX_MAJOR_VERSION 1 -#define SELINUX_MINOR_VERSION 0 +#define SELINUX_MINOR_VERSION 1 #define SELinuxNumberEvents 0 #define SELinuxNumberErrors 0 @@ -33,9 +33,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define X_SELinuxGetDeviceCreateContext 2 #define X_SELinuxSetDeviceContext 3 #define X_SELinuxGetDeviceContext 4 -#define X_SELinuxSetWindowCreateContext 5 -#define X_SELinuxGetWindowCreateContext 6 -#define X_SELinuxGetWindowContext 7 +#define X_SELinuxSetDrawableCreateContext 5 +#define X_SELinuxGetDrawableCreateContext 6 +#define X_SELinuxGetDrawableContext 7 #define X_SELinuxSetPropertyCreateContext 8 #define X_SELinuxGetPropertyCreateContext 9 #define X_SELinuxSetPropertyUseContext 10 diff --git a/xorg-server/Xext/xselinux_ext.c b/xorg-server/Xext/xselinux_ext.c index b36fb13eb..aa5573455 100644 --- a/xorg-server/Xext/xselinux_ext.c +++ b/xorg-server/Xext/xselinux_ext.c @@ -132,7 +132,6 @@ ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) ptr = dixLookupPrivate(privPtr, subjectKey); pSid = (security_id_t *)(ptr + offset); - sidput(*pSid); *pSid = NULL; rc = Success; @@ -193,11 +192,9 @@ ProcSELinuxSetDeviceContext(ClientPtr client) } subj = dixLookupPrivate(&dev->devPrivates, subjectKey); - sidput(subj->sid); subj->sid = sid; obj = dixLookupPrivate(&dev->devPrivates, objectKey); - sidput(obj->sid); - sidget(obj->sid = sid); + obj->sid = sid; rc = Success; out: @@ -224,20 +221,28 @@ ProcSELinuxGetDeviceContext(ClientPtr client) } static int -ProcSELinuxGetWindowContext(ClientPtr client) +ProcSELinuxGetDrawableContext(ClientPtr client) { - WindowPtr pWin; + DrawablePtr pDraw; + PrivateRec **privatePtr; SELinuxObjectRec *obj; int rc; REQUEST(SELinuxGetContextReq); REQUEST_SIZE_MATCH(SELinuxGetContextReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); + rc = dixLookupDrawable(&pDraw, stuff->id, client, + M_WINDOW | M_DRAWABLE_PIXMAP, + DixGetAttrAccess); if (rc != Success) return rc; - obj = dixLookupPrivate(&pWin->devPrivates, objectKey); + if (pDraw->type == M_DRAWABLE_PIXMAP) + privatePtr = &((PixmapPtr)pDraw)->devPrivates; + else + privatePtr = &((WindowPtr)pDraw)->devPrivates; + + obj = dixLookupPrivate(privatePtr, objectKey); return SELinuxSendContextReply(client, obj->sid); } @@ -481,12 +486,12 @@ ProcSELinuxDispatch(ClientPtr client) return ProcSELinuxSetDeviceContext(client); case X_SELinuxGetDeviceContext: return ProcSELinuxGetDeviceContext(client); - case X_SELinuxSetWindowCreateContext: + case X_SELinuxSetDrawableCreateContext: return ProcSELinuxSetCreateContext(client, CTX_WIN); - case X_SELinuxGetWindowCreateContext: + case X_SELinuxGetDrawableCreateContext: return ProcSELinuxGetCreateContext(client, CTX_WIN); - case X_SELinuxGetWindowContext: - return ProcSELinuxGetWindowContext(client); + case X_SELinuxGetDrawableContext: + return ProcSELinuxGetDrawableContext(client); case X_SELinuxSetPropertyCreateContext: return ProcSELinuxSetCreateContext(client, CTX_PRP); case X_SELinuxGetPropertyCreateContext: @@ -569,14 +574,14 @@ SProcSELinuxGetDeviceContext(ClientPtr client) } static int -SProcSELinuxGetWindowContext(ClientPtr client) +SProcSELinuxGetDrawableContext(ClientPtr client) { REQUEST(SELinuxGetContextReq); int n; REQUEST_SIZE_MATCH(SELinuxGetContextReq); swapl(&stuff->id, n); - return ProcSELinuxGetWindowContext(client); + return ProcSELinuxGetDrawableContext(client); } static int @@ -643,12 +648,12 @@ SProcSELinuxDispatch(ClientPtr client) return SProcSELinuxSetDeviceContext(client); case X_SELinuxGetDeviceContext: return SProcSELinuxGetDeviceContext(client); - case X_SELinuxSetWindowCreateContext: + case X_SELinuxSetDrawableCreateContext: return SProcSELinuxSetCreateContext(client, CTX_WIN); - case X_SELinuxGetWindowCreateContext: + case X_SELinuxGetDrawableCreateContext: return ProcSELinuxGetCreateContext(client, CTX_WIN); - case X_SELinuxGetWindowContext: - return SProcSELinuxGetWindowContext(client); + case X_SELinuxGetDrawableContext: + return SProcSELinuxGetDrawableContext(client); case X_SELinuxSetPropertyCreateContext: return SProcSELinuxSetCreateContext(client, CTX_PRP); case X_SELinuxGetPropertyCreateContext: diff --git a/xorg-server/Xext/xselinux_hooks.c b/xorg-server/Xext/xselinux_hooks.c index 43683ff24..6c8c8cdbe 100644 --- a/xorg-server/Xext/xselinux_hooks.c +++ b/xorg-server/Xext/xselinux_hooks.c @@ -69,9 +69,6 @@ DevPrivateKey dataKey = &dataKeyIndex; /* audit file descriptor */ static int audit_fd; -/* whether AVC is active */ -static int avc_active; - /* atoms for window label properties */ static Atom atom_ctx; static Atom atom_client_ctx; @@ -125,9 +122,7 @@ SELinuxLabelClient(ClientPtr client) security_context_t ctx; subj = dixLookupPrivate(&client->devPrivates, subjectKey); - sidput(subj->sid); obj = dixLookupPrivate(&client->devPrivates, objectKey); - sidput(obj->sid); /* Try to get a context from the socket */ if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { @@ -170,7 +165,7 @@ finish: FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", client->index, ctx); - sidget(obj->sid = subj->sid); + obj->sid = subj->sid; freecon(ctx); } @@ -191,7 +186,6 @@ SELinuxLabelInitial(void) subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); subj->privileged = 1; - sidput(subj->sid); /* Use the context of the X server process for the serverClient */ if (getcon_raw(&ctx) < 0) @@ -201,7 +195,7 @@ SELinuxLabelInitial(void) if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); - sidget(obj->sid = subj->sid); + obj->sid = subj->sid; freecon(ctx); srec.client = serverClient; @@ -230,8 +224,8 @@ SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, security_id_t tsid; /* Check for a create context */ - if (rec->rtype == RT_WINDOW && subj->win_create_sid) { - sidget(obj->sid = subj->win_create_sid); + if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) { + obj->sid = subj->win_create_sid; return Success; } @@ -359,17 +353,14 @@ SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxSubjectRec *dsubj; dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); - sidput(dsubj->sid); - sidput(obj->sid); - if (subj->dev_create_sid) { /* Label the device with the create context */ - sidget(obj->sid = subj->dev_create_sid); - sidget(dsubj->sid = subj->dev_create_sid); + obj->sid = subj->dev_create_sid; + dsubj->sid = subj->dev_create_sid; } else { /* Label the device directly with the process SID */ - sidget(obj->sid = subj->sid); - sidget(dsubj->sid = subj->sid); + obj->sid = subj->sid; + dsubj->sid = subj->sid; } } @@ -483,8 +474,6 @@ SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) return; } - sidput(obj->sid); - /* Perform a transition to obtain the final SID */ if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, &obj->sid) < 0) { @@ -520,7 +509,6 @@ SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) /* If this is a new object that needs labeling, do it now */ if (access_mode & DixCreateAccess) { - sidput(obj->sid); rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); if (rc != Success) obj->sid = unlabeled_sid; @@ -538,7 +526,6 @@ SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) break; obj = dixLookupPrivate(&pSel->devPrivates, objectKey); } - sidput(tsid); if (pSel) *rec->ppSel = pSel; @@ -557,11 +544,10 @@ SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) /* Label the content (advisory only) */ if (access_mode & DixSetAttrAccess) { data = dixLookupPrivate(&pSel->devPrivates, dataKey); - sidput(data->sid); if (subj->sel_create_sid) - sidget(data->sid = subj->sel_create_sid); + data->sid = subj->sel_create_sid; else - sidget(data->sid = obj->sid); + data->sid = obj->sid; } } @@ -586,7 +572,6 @@ SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) /* If this is a new object that needs labeling, do it now */ if (rec->access_mode & DixCreateAccess) { - sidput(obj->sid); rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); if (rc != Success) { rec->status = rc; @@ -605,7 +590,6 @@ SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) break; obj = dixLookupPrivate(&pProp->devPrivates, objectKey); } - sidput(tsid); if (pProp) *rec->ppProp = pProp; @@ -624,11 +608,10 @@ SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) /* Label the content (advisory only) */ if (rec->access_mode & DixWriteAccess) { data = dixLookupPrivate(&pProp->devPrivates, dataKey); - sidput(data->sid); if (subj->prp_create_sid) - sidget(data->sid = subj->prp_create_sid); + data->sid = subj->prp_create_sid; else - sidget(data->sid = obj->sid); + data->sid = obj->sid; } } @@ -705,8 +688,6 @@ SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) /* If this is a new object that needs labeling, do it now */ if (access_mode & DixCreateAccess) { - sidput(obj->sid); - /* Perform a transition to obtain the final SID */ if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, &obj->sid) < 0) { @@ -838,7 +819,6 @@ SELinuxSubjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata) PrivateCallbackRec *rec = calldata; SELinuxSubjectRec *subj = *rec->value; - sidget(unlabeled_sid); subj->sid = unlabeled_sid; avc_entry_ref_init(&subj->aeref); @@ -851,14 +831,6 @@ SELinuxSubjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxSubjectRec *subj = *rec->value; xfree(subj->command); - - if (avc_active) { - sidput(subj->sid); - sidput(subj->dev_create_sid); - sidput(subj->win_create_sid); - sidput(subj->sel_create_sid); - sidput(subj->prp_create_sid); - } } static void @@ -867,21 +839,9 @@ SELinuxObjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata) PrivateCallbackRec *rec = calldata; SELinuxObjectRec *obj = *rec->value; - sidget(unlabeled_sid); obj->sid = unlabeled_sid; } -static void -SELinuxObjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - PrivateCallbackRec *rec = calldata; - SELinuxObjectRec *obj = *rec->value; - - if (avc_active) - sidput(obj->sid); -} - -#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD static int netlink_fd; static void @@ -895,7 +855,6 @@ SELinuxWakeupHandler(void *data, int err, void *read_mask) if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) avc_netlink_check_nb(); } -#endif void SELinuxFlaskReset(void) @@ -919,15 +878,12 @@ SELinuxFlaskReset(void) /* Tear down SELinux stuff */ audit_close(audit_fd); -#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD avc_netlink_release_fd(); RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, NULL); RemoveGeneralSocket(netlink_fd); -#endif avc_destroy(); - avc_active = 0; } void @@ -965,7 +921,6 @@ SELinuxFlaskInit(void) if (avc_open(&avc_option, 1) < 0) FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); - avc_active = 1; if (security_get_initial_context_raw("unlabeled", &ctx) < 0) FatalError("SELinux: Failed to look up unlabeled context\n"); @@ -992,20 +947,16 @@ SELinuxFlaskInit(void) if (atom_client_ctx == BAD_RESOURCE) FatalError("SELinux: Failed to create atom\n"); -#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD netlink_fd = avc_netlink_acquire_fd(); AddGeneralSocket(netlink_fd); RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, NULL); -#endif /* Register callbacks */ ret &= dixRegisterPrivateInitFunc(subjectKey, SELinuxSubjectInit, NULL); ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL); ret &= dixRegisterPrivateInitFunc(objectKey, SELinuxObjectInit, NULL); - ret &= dixRegisterPrivateDeleteFunc(objectKey, SELinuxObjectFree, NULL); ret &= dixRegisterPrivateInitFunc(dataKey, SELinuxObjectInit, NULL); - ret &= dixRegisterPrivateDeleteFunc(dataKey, SELinuxObjectFree, NULL); ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); diff --git a/xorg-server/Xext/xselinux_label.c b/xorg-server/Xext/xselinux_label.c index 239536cf3..9b5023a53 100644 --- a/xorg-server/Xext/xselinux_label.c +++ b/xorg-server/Xext/xselinux_label.c @@ -177,20 +177,17 @@ SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj, /* Check for an override context next */ if (subj->sel_use_sid) { - sidget(tsid = subj->sel_use_sid); + tsid = subj->sel_use_sid; goto out; } - sidget(tsid = obj->sid); + tsid = obj->sid; /* Polyinstantiate if necessary to obtain the final SID */ - if (obj->poly) { - sidput(tsid); - if (avc_compute_member(subj->sid, obj->sid, - SECCLASS_X_SELECTION, &tsid) < 0) { - ErrorF("SELinux: a compute_member call failed!\n"); - return BadValue; - } + if (obj->poly && avc_compute_member(subj->sid, obj->sid, + SECCLASS_X_SELECTION, &tsid) < 0) { + ErrorF("SELinux: a compute_member call failed!\n"); + return BadValue; } out: *sid_rtn = tsid; @@ -217,7 +214,7 @@ SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, /* Check for an override context next */ if (subj->prp_use_sid) { - sidget(tsid = subj->prp_use_sid); + tsid = subj->prp_use_sid; goto out; } @@ -234,10 +231,8 @@ SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, if (avc_compute_member(subj->sid, tsid2, SECCLASS_X_PROPERTY, &tsid) < 0) { ErrorF("SELinux: a compute_member call failed!\n"); - sidput(tsid2); return BadValue; } - sidput(tsid2); } out: *sid_rtn = tsid; @@ -273,10 +268,8 @@ SELinuxEventToSID(unsigned type, security_id_t sid_of_window, } freecon(ctx); /* Cache the SID value */ - if (!SELinuxArraySet(&arr_events, type, sid)) { - sidput(sid); + if (!SELinuxArraySet(&arr_events, type, sid)) return BadAlloc; - } } /* Perform a transition to obtain the final SID */ diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c index 7c105eb94..a63b65b6b 100644 --- a/xorg-server/Xi/exevents.c +++ b/xorg-server/Xi/exevents.c @@ -1052,38 +1052,18 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) } if (DeviceEventCallback) { - DeviceEventInfoRec eventinfo; - SpritePtr pSprite = device->spriteInfo->sprite; - xEvent *xi_events = NULL; - int count; - - /* see comment in EnqueueEvents regarding the next three lines */ - if (ev->any.type == ET_Motion) - ev->device_event.root = - WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; - - /* SDs send XI events only. MDs send both an XI event and a core - * event. - */ - EventToXI(ev, &xi_events, &count); - - eventinfo.events = (xEventPtr)xi_events; - eventinfo.count = count; - ErrorF("POE xi root is %lx\n", xi_events->u.keyButtonPointer.root); - CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); - xfree(xi_events); - - if (IsMaster(device)) - { - xEvent core; - EventToCore(ev, &core); - eventinfo.events = (xEventPtr)&core; - eventinfo.count = 1; - ErrorF("POE core root is %lx\n", core.u.keyButtonPointer.root); - CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); - } + DeviceEventInfoRec eventinfo; + SpritePtr pSprite = device->spriteInfo->sprite; + /* see comment in EnqueueEvents regarding the next three lines */ + if (ev->any.type == ET_Motion) + ev->device_event.root = WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; + + eventinfo.device = device; + eventinfo.event = ev; + CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); } + grab = device->deviceGrab.grab; switch(event->type) diff --git a/xorg-server/Xi/setmode.c b/xorg-server/Xi/setmode.c index 51e57675f..ce2ad47c7 100644 --- a/xorg-server/Xi/setmode.c +++ b/xorg-server/Xi/setmode.c @@ -112,7 +112,17 @@ ProcXSetDeviceMode(ClientPtr client) if (rep.status == Success) dev->valuator->mode = stuff->mode; else if (rep.status != AlreadyGrabbed) + { + switch(rep.status) { + case BadMatch: + case BadImplementation: + case BadAlloc: + break; + default: + rep.status = BadMode; + } return rep.status; + } WriteReplyToClient(client, sizeof(xSetDeviceModeReply), &rep); return Success; diff --git a/xorg-server/composite/compwindow.c b/xorg-server/composite/compwindow.c index c10cb9ee9..f2f6ea3cd 100644 --- a/xorg-server/composite/compwindow.c +++ b/xorg-server/composite/compwindow.c @@ -205,7 +205,7 @@ compPositionWindow (WindowPtr pWin, int x, int y) #ifdef COMPOSITE_DEBUG if ((pWin->redirectDraw != RedirectDrawNone) != (pWin->viewable && (GetCompWindow(pWin) != NULL))) - abort (); + OsAbort (); #endif if (pWin->redirectDraw != RedirectDrawNone) { diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index de252f323..b9c75742a 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -1056,16 +1056,11 @@ if test "x$XSELINUX" = xyes; then if test "x$XACE" != xyes; then AC_MSG_ERROR([cannot build SELinux extension without X-ACE]) fi - AC_CHECK_HEADERS([selinux/selinux.h selinux/avc.h], [], AC_MSG_ERROR([SELinux include files not found])) - AC_CHECK_LIB(selinux, avc_init, [], AC_MSG_ERROR([SELinux library not found])) AC_CHECK_HEADERS([libaudit.h], [], AC_MSG_ERROR([SELinux extension requires audit system headers])) AC_CHECK_LIB(audit, audit_open, [], AC_MSG_ERROR([SELinux extension requires audit system library])) - AC_CHECK_DECL(avc_netlink_acquire_fd, - [AC_DEFINE(HAVE_AVC_NETLINK_ACQUIRE_FD, 1, "Have avc_netlink_acquire_fd")], - [], - [#include ]) + PKG_CHECK_MODULES([SELINUX], [libselinux >= 2.0.86]) + SELINUX_LIBS="$SELINUX_LIBS -laudit" AC_DEFINE(XSELINUX, 1, [Build SELinux extension]) - SELINUX_LIB="-lselinux -laudit" fi AM_CONDITIONAL(XCSECURITY, [test "x$XCSECURITY" = xyes]) @@ -1584,7 +1579,7 @@ if test "x$XORG" = xyes; then AC_CHECK_FUNCS([pci_device_vgaarb_init]) LIBS=$SAVE_LIBS CFLAGS=$SAVE_CFLAGS - XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS $SELINUX_LIB" + XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS $SELINUX_LIBS" XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS" case $host_os in diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c index b002150d0..6119dcebb 100644 --- a/xorg-server/dix/devices.c +++ b/xorg-server/dix/devices.c @@ -2020,14 +2020,6 @@ ProcBell(ClientPtr client) return BadValue; } - /* Seems like no keyboard actually has the BellProc set. Returning - * BadDevice (previous code) will make apps crash badly. The man pages - * doesn't say anything about a BadDevice being returned either. - * So just quietly do nothing and pretend everything has worked. - */ - if (!keybd->kbdfeed->BellProc) - return Success; - newpercent = (base * stuff->percent) / 100; if (stuff->percent < 0) newpercent = base + newpercent; diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c index b5c88802c..8af8c5ac7 100644 --- a/xorg-server/dix/events.c +++ b/xorg-server/dix/events.c @@ -1134,8 +1134,6 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device) if (DeviceEventCallback) { DeviceEventInfoRec eventinfo; - xEvent *xi_events = NULL; - int count; /* The RECORD spec says that the root window field of motion events * must be valid. At this point, it hasn't been filled in yet, so @@ -1146,27 +1144,12 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device) * the data that GetCurrentRootWindow relies on hasn't been * updated yet. */ - if (ev->any.type == ET_Motion) - ev->device_event.root = - WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; - - EventToXI(ev, &xi_events, &count); - - eventinfo.events = (xEventPtr)xi_events; - eventinfo.count = count; - CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); - xfree(xi_events); - - if (IsMaster(device)) - { - xEvent core; - EventToCore(ev, &core); - eventinfo.events = (xEventPtr)&core; - eventinfo.count = 1; - CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); - } + ev->device_event.root = WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; + eventinfo.event = ev; + eventinfo.device = device; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); } if (event->type == ET_Motion) @@ -1431,11 +1414,6 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) thisDev->deviceGrab.sync.other = NullGrab; } - /* - XXX: Direct slave grab won't freeze the paired master device. - The correct thing to do would be to freeze all SDs attached to the - paired master device. - */ if (IsMaster(thisDev)) { dev = GetPairedDevice(thisDev); @@ -2502,32 +2480,36 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, if (mask & XI_MASK) { rc = EventToXI(event, &xE, &count); - if (rc == Success && - XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) - { - filter = GetEventFilter(dev, xE); - FixUpEventFromWindow(dev, xE, pWin, child, FALSE); - deliveries = DeliverEventsToWindow(dev, pWin, xE, count, - filter, grab); - if (deliveries > 0) - goto unwind; - } + if (rc == Success) { + if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) { + filter = GetEventFilter(dev, xE); + FixUpEventFromWindow(dev, xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(dev, pWin, xE, count, + filter, grab); + if (deliveries > 0) + goto unwind; + } + } else if (rc != BadMatch) + ErrorF("[dix] %s: XI conversion failed in DDE (%d, %d). Skipping delivery.\n", + dev->name, event->any.type, rc); } /* Core event */ if ((mask & CORE_MASK) && IsMaster(dev) && dev->coreEvents) { rc = EventToCore(event, &core); - if (rc == Success && - XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) - { - filter = GetEventFilter(dev, &core); - FixUpEventFromWindow(dev, &core, pWin, child, FALSE); - deliveries = DeliverEventsToWindow(dev, pWin, &core, 1, - filter, grab); - if (deliveries > 0) - goto unwind; - } + if (rc == Success) { + if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) { + filter = GetEventFilter(dev, &core); + FixUpEventFromWindow(dev, &core, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(dev, pWin, &core, 1, + filter, grab); + if (deliveries > 0) + goto unwind; + } + } else if (rc != BadMatch) + ErrorF("[dix] %s: Core conversion failed in DDE (%d, %d).\n", + dev->name, event->any.type, rc); } if ((deliveries < 0) || (pWin == stopAt) || @@ -3804,14 +3786,16 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) if (sendCore) { rc = EventToCore(event, &core); - if (rc == Success && - XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) - { - FixUpEventFromWindow(keybd, &core, focus, None, FALSE); - deliveries = DeliverEventsToWindow(keybd, focus, &core, 1, - GetEventFilter(keybd, &core), - NullGrab); - } + if (rc == Success) { + if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) { + FixUpEventFromWindow(keybd, &core, focus, None, FALSE); + deliveries = DeliverEventsToWindow(keybd, focus, &core, 1, + GetEventFilter(keybd, &core), + NullGrab); + } + } else if (rc != BadMatch) + ErrorF("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n", + keybd->name, event->any.type, rc); } unwind: diff --git a/xorg-server/exa/exa_migration_mixed.c b/xorg-server/exa/exa_migration_mixed.c index 6816e6c9b..fb4715135 100644 --- a/xorg-server/exa/exa_migration_mixed.c +++ b/xorg-server/exa/exa_migration_mixed.c @@ -165,9 +165,37 @@ void exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg) { ExaPixmapPriv(pPixmap); + Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); + Bool success; + + success = ExaDoPrepareAccess(pPixmap, index); + + if (success && has_gpu_copy && pExaPixmap->pDamage) { + /* You cannot do accelerated operations while a buffer is mapped. */ + exaFinishAccess(&pPixmap->drawable, index); + /* Update the gpu view of both deferred destination pixmaps and of + * source pixmaps that were migrated with a bounding region. + */ + exaMoveInPixmap_mixed(pPixmap); + success = ExaDoPrepareAccess(pPixmap, index); + + if (success) { + /* We have a gpu pixmap that can be accessed, we don't need the cpu + * copy anymore. Drivers that prefer DFS, should fail prepare + * access. + */ + DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage); + DamageDestroy(pExaPixmap->pDamage); + pExaPixmap->pDamage = NULL; + + free(pExaPixmap->sys_ptr); + pExaPixmap->sys_ptr = NULL; + + return; + } + } - if (!ExaDoPrepareAccess(pPixmap, index)) { - Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); + if (!success) { ExaMigrationRec pixmaps[1]; /* Do we need to allocate our system buffer? */ @@ -228,22 +256,6 @@ exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg) pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; pPixmap->devKind = pExaPixmap->sys_pitch; pExaPixmap->use_gpu_copy = FALSE; - /* We have a gpu pixmap that can be accessed, we don't need the cpu copy - * anymore. Drivers that prefer DFS, should fail prepare access. */ - } else if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) { - ExaScreenPriv(pPixmap->drawable.pScreen); - - /* Copy back any deferred content if needed. */ - if (pExaScr->deferred_mixed_pixmap && - pExaScr->deferred_mixed_pixmap == pPixmap) - exaMoveInPixmap_mixed(pPixmap); - - DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage); - DamageDestroy(pExaPixmap->pDamage); - pExaPixmap->pDamage = NULL; - - free(pExaPixmap->sys_ptr); - pExaPixmap->sys_ptr = NULL; } } diff --git a/xorg-server/glx/glthread.c b/xorg-server/glx/glthread.c index 4caaea110..8b9f61885 100644 --- a/xorg-server/glx/glthread.c +++ b/xorg-server/glx/glthread.c @@ -129,7 +129,7 @@ _glthread_SetTSD(_glthread_TSD *tsd, void *ptr) _X_EXPORT unsigned long _glthread_GetID(void) { - abort(); /* XXX not implemented yet */ + OsAbort(); /* XXX not implemented yet */ return (unsigned long) 0; } diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c index cf1d43452..edd29b0e1 100644 --- a/xorg-server/glx/glxdri2.c +++ b/xorg-server/glx/glxdri2.c @@ -1,805 +1,812 @@ -/* - * Copyright © 2007 Red Hat, Inc - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of Red Hat, - * Inc not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. Red Hat, Inc makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN - * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#define _XF86DRI_SERVER_ -#include -#include -#include - -#include "glxserver.h" -#include "glxutil.h" -#include "glxdricommon.h" - -#include "g_disptab.h" -#include "glapitable.h" -#include "glapi.h" -#include "glthread.h" -#include "dispatch.h" -#include "extension_string.h" - -typedef struct __GLXDRIscreen __GLXDRIscreen; -typedef struct __GLXDRIcontext __GLXDRIcontext; -typedef struct __GLXDRIdrawable __GLXDRIdrawable; - -struct __GLXDRIscreen { - __GLXscreen base; - __DRIscreen *driScreen; - void *driver; - int fd; - - xf86EnterVTProc *enterVT; - xf86LeaveVTProc *leaveVT; - - const __DRIcoreExtension *core; - const __DRIdri2Extension *dri2; - const __DRI2flushExtension *flush; - const __DRIcopySubBufferExtension *copySubBuffer; - const __DRIswapControlExtension *swapControl; - const __DRItexBufferExtension *texBuffer; - - unsigned char glx_enable_bits[__GLX_EXT_BYTES]; -}; - -struct __GLXDRIcontext { - __GLXcontext base; - __DRIcontext *driContext; -}; - -#define MAX_DRAWABLE_BUFFERS 5 - -struct __GLXDRIdrawable { - __GLXdrawable base; - __DRIdrawable *driDrawable; - __GLXDRIscreen *screen; - - /* Dimensions as last reported by DRI2GetBuffers. */ - int width; - int height; - __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS]; - int count; -}; - -static void -__glXDRIdrawableDestroy(__GLXdrawable *drawable) -{ - __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; - const __DRIcoreExtension *core = private->screen->core; - - (*core->destroyDrawable)(private->driDrawable); - - /* If the X window was destroyed, the dri DestroyWindow hook will - * aready have taken care of this, so only call if pDraw isn't NULL. */ - if (drawable->pDraw != NULL) - DRI2DestroyDrawable(drawable->pDraw); - - __glXDrawableRelease(drawable); - - xfree(private); -} - -static void -__glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable, - int x, int y, int w, int h) -{ - __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; - BoxRec box; - RegionRec region; - - box.x1 = x; - box.y1 = private->height - y - h; - box.x2 = x + w; - box.y2 = private->height - y; - REGION_INIT(drawable->pDraw->pScreen, ®ion, &box, 0); - - DRI2CopyRegion(drawable->pDraw, ®ion, - DRI2BufferFrontLeft, DRI2BufferBackLeft); -} - -static void -__glXDRIdrawableWaitX(__GLXdrawable *drawable) -{ - __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; - BoxRec box; - RegionRec region; - - box.x1 = 0; - box.y1 = 0; - box.x2 = private->width; - box.y2 = private->height; - REGION_INIT(drawable->pDraw->pScreen, ®ion, &box, 0); - - DRI2CopyRegion(drawable->pDraw, ®ion, - DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); -} - -static void -__glXDRIdrawableWaitGL(__GLXdrawable *drawable) -{ - __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; - BoxRec box; - RegionRec region; - - box.x1 = 0; - box.y1 = 0; - box.x2 = private->width; - box.y2 = private->height; - REGION_INIT(drawable->pDraw->pScreen, ®ion, &box, 0); - - DRI2CopyRegion(drawable->pDraw, ®ion, - DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); -} - -static void -__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust, - CARD64 msc, CARD64 sbc) -{ - __GLXdrawable *drawable = data; - xGLXBufferSwapComplete wire; - - if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)) - return; - - wire.type = __glXEventBase + GLX_BufferSwapComplete; - switch (type) { - case DRI2_EXCHANGE_COMPLETE: - wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL; - break; - case DRI2_BLIT_COMPLETE: - wire.event_type = GLX_BLIT_COMPLETE_INTEL; - break; - case DRI2_FLIP_COMPLETE: - wire.event_type = GLX_FLIP_COMPLETE_INTEL; - break; - default: - /* unknown swap completion type */ - break; - } - wire.sequenceNumber = client->sequence; - wire.drawable = drawable->drawId; - wire.ust_hi = ust >> 32; - wire.ust_lo = ust & 0xffffffff; - wire.msc_hi = msc >> 32; - wire.msc_lo = msc & 0xffffffff; - wire.sbc_hi = sbc >> 32; - wire.sbc_lo = sbc & 0xffffffff; - - WriteEventsToClient(client, 1, (xEvent *) &wire); -} - -/* - * Copy or flip back to front, honoring the swap interval if possible. - * - * If the kernel supports it, we request an event for the frame when the - * swap should happen, then perform the copy when we receive it. - */ -static GLboolean -__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable) -{ - __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable; - __GLXDRIscreen *screen = priv->screen; - CARD64 unused; - - if (screen->flush) - (*screen->flush->flushInvalidate)(priv->driDrawable); - - if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused, - __glXdriSwapEvent, drawable->pDraw) != Success) - return FALSE; - - return TRUE; -} - -static int -__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval) -{ - if (interval <= 0) /* || interval > BIGNUM? */ - return GLX_BAD_VALUE; - - DRI2SwapInterval(drawable->pDraw, interval); - - return 0; -} - -static void -__glXDRIcontextDestroy(__GLXcontext *baseContext) -{ - __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; - __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; - - (*screen->core->destroyContext)(context->driContext); - __glXContextDestroy(&context->base); - xfree(context); -} - -static int -__glXDRIcontextMakeCurrent(__GLXcontext *baseContext) -{ - __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; - __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv; - __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv; - __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; - - return (*screen->core->bindContext)(context->driContext, - draw->driDrawable, - read->driDrawable); -} - -static int -__glXDRIcontextLoseCurrent(__GLXcontext *baseContext) -{ - __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; - __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; - - return (*screen->core->unbindContext)(context->driContext); -} - -static int -__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc, - unsigned long mask) -{ - __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst; - __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc; - __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen; - - return (*screen->core->copyContext)(dst->driContext, - src->driContext, mask); -} - -static int -__glXDRIcontextForceCurrent(__GLXcontext *baseContext) -{ - __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; - __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv; - __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv; - __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; - - return (*screen->core->bindContext)(context->driContext, - draw->driDrawable, - read->driDrawable); -} - -static Bool -__glXDRIcontextWait(__GLXcontext *baseContext, - __GLXclientState *cl, int *error) -{ - if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) { - *error = cl->client->noClientException; - return TRUE; - } - - return FALSE; -} - -#ifdef __DRI_TEX_BUFFER - -static int -__glXDRIbindTexImage(__GLXcontext *baseContext, - int buffer, - __GLXdrawable *glxPixmap) -{ - __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap; - const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer; - __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; - - if (texBuffer == NULL) - return Success; - -#if __DRI_TEX_BUFFER_VERSION >= 2 - if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) { - (*texBuffer->setTexBuffer2)(context->driContext, - glxPixmap->target, - glxPixmap->format, - drawable->driDrawable); - } else -#endif - { - texBuffer->setTexBuffer(context->driContext, - glxPixmap->target, - drawable->driDrawable); - } - - return Success; -} - -static int -__glXDRIreleaseTexImage(__GLXcontext *baseContext, - int buffer, - __GLXdrawable *pixmap) -{ - /* FIXME: Just unbind the texture? */ - return Success; -} - -#else - -static int -__glXDRIbindTexImage(__GLXcontext *baseContext, - int buffer, - __GLXdrawable *glxPixmap) -{ - return Success; -} - -static int -__glXDRIreleaseTexImage(__GLXcontext *baseContext, - int buffer, - __GLXdrawable *pixmap) -{ - return Success; -} - -#endif - -static __GLXtextureFromPixmap __glXDRItextureFromPixmap = { - __glXDRIbindTexImage, - __glXDRIreleaseTexImage -}; - -static void -__glXDRIscreenDestroy(__GLXscreen *baseScreen) -{ - __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; - - (*screen->core->destroyScreen)(screen->driScreen); - - dlclose(screen->driver); - - __glXScreenDestroy(baseScreen); - - xfree(screen); -} - -static __GLXcontext * -__glXDRIscreenCreateContext(__GLXscreen *baseScreen, - __GLXconfig *glxConfig, - __GLXcontext *baseShareContext) -{ - __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; - __GLXDRIcontext *context, *shareContext; - __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig; - __DRIcontext *driShare; - - shareContext = (__GLXDRIcontext *) baseShareContext; - if (shareContext) - driShare = shareContext->driContext; - else - driShare = NULL; - - context = xcalloc(1, sizeof *context); - if (context == NULL) - return NULL; - - context->base.destroy = __glXDRIcontextDestroy; - context->base.makeCurrent = __glXDRIcontextMakeCurrent; - context->base.loseCurrent = __glXDRIcontextLoseCurrent; - context->base.copy = __glXDRIcontextCopy; - context->base.forceCurrent = __glXDRIcontextForceCurrent; - context->base.textureFromPixmap = &__glXDRItextureFromPixmap; - context->base.wait = __glXDRIcontextWait; - - context->driContext = - (*screen->dri2->createNewContext)(screen->driScreen, - config->driConfig, - driShare, context); - if (context->driContext == NULL) { - xfree(context); - return NULL; - } - - return &context->base; -} - -static __GLXdrawable * -__glXDRIscreenCreateDrawable(__GLXscreen *screen, - DrawablePtr pDraw, - int type, - XID drawId, - __GLXconfig *glxConfig) -{ - __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; - __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig; - __GLXDRIdrawable *private; - - private = xcalloc(1, sizeof *private); - if (private == NULL) - return NULL; - - private->screen = driScreen; - if (!__glXDrawableInit(&private->base, screen, - pDraw, type, drawId, glxConfig)) { - xfree(private); - return NULL; - } - - private->base.destroy = __glXDRIdrawableDestroy; - private->base.swapBuffers = __glXDRIdrawableSwapBuffers; - private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer; - private->base.waitGL = __glXDRIdrawableWaitGL; - private->base.waitX = __glXDRIdrawableWaitX; - - if (DRI2CreateDrawable(pDraw)) { - xfree(private); - return NULL; - } - - private->driDrawable = - (*driScreen->dri2->createNewDrawable)(driScreen->driScreen, - config->driConfig, private); - - return &private->base; -} - -static __DRIbuffer * -dri2GetBuffers(__DRIdrawable *driDrawable, - int *width, int *height, - unsigned int *attachments, int count, - int *out_count, void *loaderPrivate) -{ - __GLXDRIdrawable *private = loaderPrivate; - DRI2BufferPtr *buffers; - int i; - int j; - - buffers = DRI2GetBuffers(private->base.pDraw, - width, height, attachments, count, out_count); - if (*out_count > MAX_DRAWABLE_BUFFERS) { - *out_count = 0; - return NULL; - } - - private->width = *width; - private->height = *height; - - /* This assumes the DRI2 buffer attachment tokens matches the - * __DRIbuffer tokens. */ - j = 0; - for (i = 0; i < *out_count; i++) { - /* Do not send the real front buffer of a window to the client. - */ - if ((private->base.pDraw->type == DRAWABLE_WINDOW) - && (buffers[i]->attachment == DRI2BufferFrontLeft)) { - continue; - } - - private->buffers[j].attachment = buffers[i]->attachment; - private->buffers[j].name = buffers[i]->name; - private->buffers[j].pitch = buffers[i]->pitch; - private->buffers[j].cpp = buffers[i]->cpp; - private->buffers[j].flags = buffers[i]->flags; - j++; - } - - *out_count = j; - return private->buffers; -} - -static __DRIbuffer * -dri2GetBuffersWithFormat(__DRIdrawable *driDrawable, - int *width, int *height, - unsigned int *attachments, int count, - int *out_count, void *loaderPrivate) -{ - __GLXDRIdrawable *private = loaderPrivate; - DRI2BufferPtr *buffers; - int i; - int j = 0; - - buffers = DRI2GetBuffersWithFormat(private->base.pDraw, - width, height, attachments, count, - out_count); - if (*out_count > MAX_DRAWABLE_BUFFERS) { - *out_count = 0; - return NULL; - } - - private->width = *width; - private->height = *height; - - /* This assumes the DRI2 buffer attachment tokens matches the - * __DRIbuffer tokens. */ - for (i = 0; i < *out_count; i++) { - /* Do not send the real front buffer of a window to the client. - */ - if ((private->base.pDraw->type == DRAWABLE_WINDOW) - && (buffers[i]->attachment == DRI2BufferFrontLeft)) { - continue; - } - - private->buffers[j].attachment = buffers[i]->attachment; - private->buffers[j].name = buffers[i]->name; - private->buffers[j].pitch = buffers[i]->pitch; - private->buffers[j].cpp = buffers[i]->cpp; - private->buffers[j].flags = buffers[i]->flags; - j++; - } - - *out_count = j; - return private->buffers; -} - -static void -dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) -{ - (void) driDrawable; - __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate); -} - -static const __DRIdri2LoaderExtension loaderExtension = { - { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION }, - dri2GetBuffers, - dri2FlushFrontBuffer, - dri2GetBuffersWithFormat, -}; - -static const __DRIextension *loader_extensions[] = { - &systemTimeExtension.base, - &loaderExtension.base, - NULL -}; - -static const char dri_driver_path[] = DRI_DRIVER_PATH; - -static Bool -glxDRIEnterVT (int index, int flags) -{ - __GLXDRIscreen *screen = (__GLXDRIscreen *) - glxGetScreen(screenInfo.screens[index]); - - LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n"); - - if (!(*screen->enterVT) (index, flags)) - return FALSE; - - glxResumeClients(); - - return TRUE; -} - -static void -glxDRILeaveVT (int index, int flags) -{ - __GLXDRIscreen *screen = (__GLXDRIscreen *) - glxGetScreen(screenInfo.screens[index]); - - LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n"); - - glxSuspendClients(); - - return (*screen->leaveVT) (index, flags); -} - -static void -initializeExtensions(__GLXDRIscreen *screen) -{ - const __DRIextension **extensions; - int i; - - extensions = screen->core->getExtensions(screen->driScreen); - - __glXEnableExtension(screen->glx_enable_bits, - "GLX_MESA_copy_sub_buffer"); - LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n"); - - /* FIXME: only if DDX supports it */ - __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event"); - LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n"); - - for (i = 0; extensions[i]; i++) { -#ifdef __DRI_READ_DRAWABLE - if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { - __glXEnableExtension(screen->glx_enable_bits, - "GLX_SGI_make_current_read"); - - LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n"); - } -#endif - -#ifdef __DRI_SWAP_CONTROL - if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) { - screen->swapControl = - (const __DRIswapControlExtension *) extensions[i]; - __glXEnableExtension(screen->glx_enable_bits, - "GLX_SGI_swap_control"); - __glXEnableExtension(screen->glx_enable_bits, - "GLX_MESA_swap_control"); - - LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n"); - } -#endif - -#ifdef __DRI_TEX_BUFFER - if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) { - screen->texBuffer = - (const __DRItexBufferExtension *) extensions[i]; - /* GLX_EXT_texture_from_pixmap is always enabled. */ - LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n"); - } -#endif - -#ifdef __DRI2_FLUSH - if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 && - extensions[i]->version >= __DRI2_FLUSH_VERSION) { - screen->flush = (__DRI2flushExtension *) extensions[i]; - } -#endif - - /* Ignore unknown extensions */ - } -} - -static __GLXscreen * -__glXDRIscreenProbe(ScreenPtr pScreen) -{ - const char *driverName, *deviceName; - __GLXDRIscreen *screen; - char filename[128]; - size_t buffer_size; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - const __DRIextension **extensions; - const __DRIconfig **driConfigs; - int i; - - screen = xcalloc(1, sizeof *screen); - if (screen == NULL) - return NULL; - - if (!xf86LoaderCheckSymbol("DRI2Connect") || - !DRI2Connect(pScreen, DRI2DriverDRI, - &screen->fd, &driverName, &deviceName)) { - LogMessage(X_INFO, - "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum); - return NULL; - } - - screen->base.destroy = __glXDRIscreenDestroy; - screen->base.createContext = __glXDRIscreenCreateContext; - screen->base.createDrawable = __glXDRIscreenCreateDrawable; - screen->base.swapInterval = __glXDRIdrawableSwapInterval; - screen->base.pScreen = pScreen; - - __glXInitExtensionEnableBits(screen->glx_enable_bits); - - snprintf(filename, sizeof filename, - "%s/%s_dri.so", dri_driver_path, driverName); - - screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); - if (screen->driver == NULL) { - LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n", - filename, dlerror()); - goto handle_error; - } - - extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS); - if (extensions == NULL) { - LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n", - driverName, dlerror()); - goto handle_error; - } - - for (i = 0; extensions[i]; i++) { - if (strcmp(extensions[i]->name, __DRI_CORE) == 0 && - extensions[i]->version >= __DRI_CORE_VERSION) { - screen->core = (const __DRIcoreExtension *) extensions[i]; - } - if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 && - extensions[i]->version >= __DRI_DRI2_VERSION) { - screen->dri2 = (const __DRIdri2Extension *) extensions[i]; - } - } - - if (screen->core == NULL || screen->dri2 == NULL) { - LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n", - driverName); - goto handle_error; - } - - screen->driScreen = - (*screen->dri2->createNewScreen)(pScreen->myNum, - screen->fd, - loader_extensions, - &driConfigs, - screen); - - if (screen->driScreen == NULL) { - LogMessage(X_ERROR, - "AIGLX error: Calling driver entry point failed\n"); - goto handle_error; - } - - initializeExtensions(screen); - - screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs); - - __glXScreenInit(&screen->base, pScreen); - - /* The first call simply determines the length of the extension string. - * This allows us to allocate some memory to hold the extension string, - * but it requires that we call __glXGetExtensionString a second time. - */ - buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL); - if (buffer_size > 0) { - if (screen->base.GLXextensions != NULL) { - xfree(screen->base.GLXextensions); - } - - screen->base.GLXextensions = xnfalloc(buffer_size); - (void) __glXGetExtensionString(screen->glx_enable_bits, - screen->base.GLXextensions); - } - - /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled - * drivers support the required extensions for GLX 1.4. The extensions - * we're assuming are: - * - * - GLX_SGI_make_current_read (1.3) - * - GLX_SGIX_fbconfig (1.3) - * - GLX_SGIX_pbuffer (1.3) - * - GLX_ARB_multisample (1.4) - */ - screen->base.GLXmajor = 1; - screen->base.GLXminor = 4; - - screen->enterVT = pScrn->EnterVT; - pScrn->EnterVT = glxDRIEnterVT; - screen->leaveVT = pScrn->LeaveVT; - pScrn->LeaveVT = glxDRILeaveVT; - - LogMessage(X_INFO, - "AIGLX: Loaded and initialized %s\n", filename); - - return &screen->base; - - handle_error: - if (screen->driver) - dlclose(screen->driver); - - xfree(screen); - - LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n"); - - return NULL; -} - -_X_EXPORT __GLXprovider __glXDRI2Provider = { - __glXDRIscreenProbe, - "DRI2", - NULL -}; +/* + * Copyright © 2007 Red Hat, Inc + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Red Hat, + * Inc not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Red Hat, Inc makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define _XF86DRI_SERVER_ +#include +#include +#include + +#include "glxserver.h" +#include "glxutil.h" +#include "glxdricommon.h" + +#include "g_disptab.h" +#include "glapitable.h" +#include "glapi.h" +#include "glthread.h" +#include "dispatch.h" +#include "extension_string.h" + +typedef struct __GLXDRIscreen __GLXDRIscreen; +typedef struct __GLXDRIcontext __GLXDRIcontext; +typedef struct __GLXDRIdrawable __GLXDRIdrawable; + +struct __GLXDRIscreen { + __GLXscreen base; + __DRIscreen *driScreen; + void *driver; + int fd; + + xf86EnterVTProc *enterVT; + xf86LeaveVTProc *leaveVT; + + const __DRIcoreExtension *core; + const __DRIdri2Extension *dri2; + const __DRI2flushExtension *flush; + const __DRIcopySubBufferExtension *copySubBuffer; + const __DRIswapControlExtension *swapControl; + const __DRItexBufferExtension *texBuffer; + + unsigned char glx_enable_bits[__GLX_EXT_BYTES]; +}; + +struct __GLXDRIcontext { + __GLXcontext base; + __DRIcontext *driContext; +}; + +#define MAX_DRAWABLE_BUFFERS 5 + +struct __GLXDRIdrawable { + __GLXdrawable base; + __DRIdrawable *driDrawable; + __GLXDRIscreen *screen; + + /* Dimensions as last reported by DRI2GetBuffers. */ + int width; + int height; + __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS]; + int count; +}; + +static void +__glXDRIdrawableDestroy(__GLXdrawable *drawable) +{ + __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; + const __DRIcoreExtension *core = private->screen->core; + + (*core->destroyDrawable)(private->driDrawable); + + /* If the X window was destroyed, the dri DestroyWindow hook will + * aready have taken care of this, so only call if pDraw isn't NULL. */ + if (drawable->pDraw != NULL) + DRI2DestroyDrawable(drawable->pDraw); + + __glXDrawableRelease(drawable); + + xfree(private); +} + +static void +__glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable, + int x, int y, int w, int h) +{ + __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; + BoxRec box; + RegionRec region; + + box.x1 = x; + box.y1 = private->height - y - h; + box.x2 = x + w; + box.y2 = private->height - y; + REGION_INIT(drawable->pDraw->pScreen, ®ion, &box, 0); + + DRI2CopyRegion(drawable->pDraw, ®ion, + DRI2BufferFrontLeft, DRI2BufferBackLeft); +} + +static void +__glXDRIdrawableWaitX(__GLXdrawable *drawable) +{ + __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; + BoxRec box; + RegionRec region; + + box.x1 = 0; + box.y1 = 0; + box.x2 = private->width; + box.y2 = private->height; + REGION_INIT(drawable->pDraw->pScreen, ®ion, &box, 0); + + DRI2CopyRegion(drawable->pDraw, ®ion, + DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); +} + +static void +__glXDRIdrawableWaitGL(__GLXdrawable *drawable) +{ + __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; + BoxRec box; + RegionRec region; + + box.x1 = 0; + box.y1 = 0; + box.x2 = private->width; + box.y2 = private->height; + REGION_INIT(drawable->pDraw->pScreen, ®ion, &box, 0); + + DRI2CopyRegion(drawable->pDraw, ®ion, + DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); +} + +static void +__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust, + CARD64 msc, CARD64 sbc) +{ + __GLXdrawable *drawable = data; + xGLXBufferSwapComplete wire; + + if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)) + return; + + wire.type = __glXEventBase + GLX_BufferSwapComplete; + switch (type) { + case DRI2_EXCHANGE_COMPLETE: + wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL; + break; + case DRI2_BLIT_COMPLETE: + wire.event_type = GLX_BLIT_COMPLETE_INTEL; + break; + case DRI2_FLIP_COMPLETE: + wire.event_type = GLX_FLIP_COMPLETE_INTEL; + break; + default: + /* unknown swap completion type */ + break; + } + wire.sequenceNumber = client->sequence; + wire.drawable = drawable->drawId; + wire.ust_hi = ust >> 32; + wire.ust_lo = ust & 0xffffffff; + wire.msc_hi = msc >> 32; + wire.msc_lo = msc & 0xffffffff; + wire.sbc_hi = sbc >> 32; + wire.sbc_lo = sbc & 0xffffffff; + + WriteEventsToClient(client, 1, (xEvent *) &wire); +} + +/* + * Copy or flip back to front, honoring the swap interval if possible. + * + * If the kernel supports it, we request an event for the frame when the + * swap should happen, then perform the copy when we receive it. + */ +static GLboolean +__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable) +{ + __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable; + __GLXDRIscreen *screen = priv->screen; + CARD64 unused; + +#if __DRI2_FLUSH_VERSION >= 3 + if (screen->flush) { + (*screen->flush->flush)(priv->driDrawable); + (*screen->flush->invalidate)(priv->driDrawable); + } +#else + if (screen->flush) + (*screen->flush->flushInvalidate)(priv->driDrawable); +#endif + + if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused, + __glXdriSwapEvent, drawable->pDraw) != Success) + return FALSE; + + return TRUE; +} + +static int +__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval) +{ + if (interval <= 0) /* || interval > BIGNUM? */ + return GLX_BAD_VALUE; + + DRI2SwapInterval(drawable->pDraw, interval); + + return 0; +} + +static void +__glXDRIcontextDestroy(__GLXcontext *baseContext) +{ + __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; + __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; + + (*screen->core->destroyContext)(context->driContext); + __glXContextDestroy(&context->base); + xfree(context); +} + +static int +__glXDRIcontextMakeCurrent(__GLXcontext *baseContext) +{ + __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; + __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv; + __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv; + __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; + + return (*screen->core->bindContext)(context->driContext, + draw->driDrawable, + read->driDrawable); +} + +static int +__glXDRIcontextLoseCurrent(__GLXcontext *baseContext) +{ + __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; + __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; + + return (*screen->core->unbindContext)(context->driContext); +} + +static int +__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc, + unsigned long mask) +{ + __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst; + __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc; + __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen; + + return (*screen->core->copyContext)(dst->driContext, + src->driContext, mask); +} + +static int +__glXDRIcontextForceCurrent(__GLXcontext *baseContext) +{ + __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; + __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv; + __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv; + __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen; + + return (*screen->core->bindContext)(context->driContext, + draw->driDrawable, + read->driDrawable); +} + +static Bool +__glXDRIcontextWait(__GLXcontext *baseContext, + __GLXclientState *cl, int *error) +{ + if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) { + *error = cl->client->noClientException; + return TRUE; + } + + return FALSE; +} + +#ifdef __DRI_TEX_BUFFER + +static int +__glXDRIbindTexImage(__GLXcontext *baseContext, + int buffer, + __GLXdrawable *glxPixmap) +{ + __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap; + const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer; + __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; + + if (texBuffer == NULL) + return Success; + +#if __DRI_TEX_BUFFER_VERSION >= 2 + if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) { + (*texBuffer->setTexBuffer2)(context->driContext, + glxPixmap->target, + glxPixmap->format, + drawable->driDrawable); + } else +#endif + { + texBuffer->setTexBuffer(context->driContext, + glxPixmap->target, + drawable->driDrawable); + } + + return Success; +} + +static int +__glXDRIreleaseTexImage(__GLXcontext *baseContext, + int buffer, + __GLXdrawable *pixmap) +{ + /* FIXME: Just unbind the texture? */ + return Success; +} + +#else + +static int +__glXDRIbindTexImage(__GLXcontext *baseContext, + int buffer, + __GLXdrawable *glxPixmap) +{ + return Success; +} + +static int +__glXDRIreleaseTexImage(__GLXcontext *baseContext, + int buffer, + __GLXdrawable *pixmap) +{ + return Success; +} + +#endif + +static __GLXtextureFromPixmap __glXDRItextureFromPixmap = { + __glXDRIbindTexImage, + __glXDRIreleaseTexImage +}; + +static void +__glXDRIscreenDestroy(__GLXscreen *baseScreen) +{ + __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; + + (*screen->core->destroyScreen)(screen->driScreen); + + dlclose(screen->driver); + + __glXScreenDestroy(baseScreen); + + xfree(screen); +} + +static __GLXcontext * +__glXDRIscreenCreateContext(__GLXscreen *baseScreen, + __GLXconfig *glxConfig, + __GLXcontext *baseShareContext) +{ + __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; + __GLXDRIcontext *context, *shareContext; + __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig; + __DRIcontext *driShare; + + shareContext = (__GLXDRIcontext *) baseShareContext; + if (shareContext) + driShare = shareContext->driContext; + else + driShare = NULL; + + context = xcalloc(1, sizeof *context); + if (context == NULL) + return NULL; + + context->base.destroy = __glXDRIcontextDestroy; + context->base.makeCurrent = __glXDRIcontextMakeCurrent; + context->base.loseCurrent = __glXDRIcontextLoseCurrent; + context->base.copy = __glXDRIcontextCopy; + context->base.forceCurrent = __glXDRIcontextForceCurrent; + context->base.textureFromPixmap = &__glXDRItextureFromPixmap; + context->base.wait = __glXDRIcontextWait; + + context->driContext = + (*screen->dri2->createNewContext)(screen->driScreen, + config->driConfig, + driShare, context); + if (context->driContext == NULL) { + xfree(context); + return NULL; + } + + return &context->base; +} + +static __GLXdrawable * +__glXDRIscreenCreateDrawable(__GLXscreen *screen, + DrawablePtr pDraw, + int type, + XID drawId, + __GLXconfig *glxConfig) +{ + __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; + __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig; + __GLXDRIdrawable *private; + + private = xcalloc(1, sizeof *private); + if (private == NULL) + return NULL; + + private->screen = driScreen; + if (!__glXDrawableInit(&private->base, screen, + pDraw, type, drawId, glxConfig)) { + xfree(private); + return NULL; + } + + private->base.destroy = __glXDRIdrawableDestroy; + private->base.swapBuffers = __glXDRIdrawableSwapBuffers; + private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer; + private->base.waitGL = __glXDRIdrawableWaitGL; + private->base.waitX = __glXDRIdrawableWaitX; + + if (DRI2CreateDrawable(pDraw)) { + xfree(private); + return NULL; + } + + private->driDrawable = + (*driScreen->dri2->createNewDrawable)(driScreen->driScreen, + config->driConfig, private); + + return &private->base; +} + +static __DRIbuffer * +dri2GetBuffers(__DRIdrawable *driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + __GLXDRIdrawable *private = loaderPrivate; + DRI2BufferPtr *buffers; + int i; + int j; + + buffers = DRI2GetBuffers(private->base.pDraw, + width, height, attachments, count, out_count); + if (*out_count > MAX_DRAWABLE_BUFFERS) { + *out_count = 0; + return NULL; + } + + private->width = *width; + private->height = *height; + + /* This assumes the DRI2 buffer attachment tokens matches the + * __DRIbuffer tokens. */ + j = 0; + for (i = 0; i < *out_count; i++) { + /* Do not send the real front buffer of a window to the client. + */ + if ((private->base.pDraw->type == DRAWABLE_WINDOW) + && (buffers[i]->attachment == DRI2BufferFrontLeft)) { + continue; + } + + private->buffers[j].attachment = buffers[i]->attachment; + private->buffers[j].name = buffers[i]->name; + private->buffers[j].pitch = buffers[i]->pitch; + private->buffers[j].cpp = buffers[i]->cpp; + private->buffers[j].flags = buffers[i]->flags; + j++; + } + + *out_count = j; + return private->buffers; +} + +static __DRIbuffer * +dri2GetBuffersWithFormat(__DRIdrawable *driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + __GLXDRIdrawable *private = loaderPrivate; + DRI2BufferPtr *buffers; + int i; + int j = 0; + + buffers = DRI2GetBuffersWithFormat(private->base.pDraw, + width, height, attachments, count, + out_count); + if (*out_count > MAX_DRAWABLE_BUFFERS) { + *out_count = 0; + return NULL; + } + + private->width = *width; + private->height = *height; + + /* This assumes the DRI2 buffer attachment tokens matches the + * __DRIbuffer tokens. */ + for (i = 0; i < *out_count; i++) { + /* Do not send the real front buffer of a window to the client. + */ + if ((private->base.pDraw->type == DRAWABLE_WINDOW) + && (buffers[i]->attachment == DRI2BufferFrontLeft)) { + continue; + } + + private->buffers[j].attachment = buffers[i]->attachment; + private->buffers[j].name = buffers[i]->name; + private->buffers[j].pitch = buffers[i]->pitch; + private->buffers[j].cpp = buffers[i]->cpp; + private->buffers[j].flags = buffers[i]->flags; + j++; + } + + *out_count = j; + return private->buffers; +} + +static void +dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) +{ + (void) driDrawable; + __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate); +} + +static const __DRIdri2LoaderExtension loaderExtension = { + { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION }, + dri2GetBuffers, + dri2FlushFrontBuffer, + dri2GetBuffersWithFormat, +}; + +static const __DRIextension *loader_extensions[] = { + &systemTimeExtension.base, + &loaderExtension.base, + NULL +}; + +static const char dri_driver_path[] = DRI_DRIVER_PATH; + +static Bool +glxDRIEnterVT (int index, int flags) +{ + __GLXDRIscreen *screen = (__GLXDRIscreen *) + glxGetScreen(screenInfo.screens[index]); + + LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n"); + + if (!(*screen->enterVT) (index, flags)) + return FALSE; + + glxResumeClients(); + + return TRUE; +} + +static void +glxDRILeaveVT (int index, int flags) +{ + __GLXDRIscreen *screen = (__GLXDRIscreen *) + glxGetScreen(screenInfo.screens[index]); + + LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n"); + + glxSuspendClients(); + + return (*screen->leaveVT) (index, flags); +} + +static void +initializeExtensions(__GLXDRIscreen *screen) +{ + const __DRIextension **extensions; + int i; + + extensions = screen->core->getExtensions(screen->driScreen); + + __glXEnableExtension(screen->glx_enable_bits, + "GLX_MESA_copy_sub_buffer"); + LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n"); + + /* FIXME: only if DDX supports it */ + __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event"); + LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n"); + + for (i = 0; extensions[i]; i++) { +#ifdef __DRI_READ_DRAWABLE + if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { + __glXEnableExtension(screen->glx_enable_bits, + "GLX_SGI_make_current_read"); + + LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n"); + } +#endif + +#ifdef __DRI_SWAP_CONTROL + if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) { + screen->swapControl = + (const __DRIswapControlExtension *) extensions[i]; + __glXEnableExtension(screen->glx_enable_bits, + "GLX_SGI_swap_control"); + __glXEnableExtension(screen->glx_enable_bits, + "GLX_MESA_swap_control"); + + LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n"); + } +#endif + +#ifdef __DRI_TEX_BUFFER + if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) { + screen->texBuffer = + (const __DRItexBufferExtension *) extensions[i]; + /* GLX_EXT_texture_from_pixmap is always enabled. */ + LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n"); + } +#endif + +#ifdef __DRI2_FLUSH + if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 && + extensions[i]->version >= __DRI2_FLUSH_VERSION) { + screen->flush = (__DRI2flushExtension *) extensions[i]; + } +#endif + + /* Ignore unknown extensions */ + } +} + +static __GLXscreen * +__glXDRIscreenProbe(ScreenPtr pScreen) +{ + const char *driverName, *deviceName; + __GLXDRIscreen *screen; + char filename[128]; + size_t buffer_size; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + const __DRIextension **extensions; + const __DRIconfig **driConfigs; + int i; + + screen = xcalloc(1, sizeof *screen); + if (screen == NULL) + return NULL; + + if (!xf86LoaderCheckSymbol("DRI2Connect") || + !DRI2Connect(pScreen, DRI2DriverDRI, + &screen->fd, &driverName, &deviceName)) { + LogMessage(X_INFO, + "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum); + return NULL; + } + + screen->base.destroy = __glXDRIscreenDestroy; + screen->base.createContext = __glXDRIscreenCreateContext; + screen->base.createDrawable = __glXDRIscreenCreateDrawable; + screen->base.swapInterval = __glXDRIdrawableSwapInterval; + screen->base.pScreen = pScreen; + + __glXInitExtensionEnableBits(screen->glx_enable_bits); + + snprintf(filename, sizeof filename, + "%s/%s_dri.so", dri_driver_path, driverName); + + screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); + if (screen->driver == NULL) { + LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n", + filename, dlerror()); + goto handle_error; + } + + extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS); + if (extensions == NULL) { + LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n", + driverName, dlerror()); + goto handle_error; + } + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_CORE) == 0 && + extensions[i]->version >= __DRI_CORE_VERSION) { + screen->core = (const __DRIcoreExtension *) extensions[i]; + } + if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 && + extensions[i]->version >= __DRI_DRI2_VERSION) { + screen->dri2 = (const __DRIdri2Extension *) extensions[i]; + } + } + + if (screen->core == NULL || screen->dri2 == NULL) { + LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n", + driverName); + goto handle_error; + } + + screen->driScreen = + (*screen->dri2->createNewScreen)(pScreen->myNum, + screen->fd, + loader_extensions, + &driConfigs, + screen); + + if (screen->driScreen == NULL) { + LogMessage(X_ERROR, + "AIGLX error: Calling driver entry point failed\n"); + goto handle_error; + } + + initializeExtensions(screen); + + screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs); + + __glXScreenInit(&screen->base, pScreen); + + /* The first call simply determines the length of the extension string. + * This allows us to allocate some memory to hold the extension string, + * but it requires that we call __glXGetExtensionString a second time. + */ + buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL); + if (buffer_size > 0) { + if (screen->base.GLXextensions != NULL) { + xfree(screen->base.GLXextensions); + } + + screen->base.GLXextensions = xnfalloc(buffer_size); + (void) __glXGetExtensionString(screen->glx_enable_bits, + screen->base.GLXextensions); + } + + /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled + * drivers support the required extensions for GLX 1.4. The extensions + * we're assuming are: + * + * - GLX_SGI_make_current_read (1.3) + * - GLX_SGIX_fbconfig (1.3) + * - GLX_SGIX_pbuffer (1.3) + * - GLX_ARB_multisample (1.4) + */ + screen->base.GLXmajor = 1; + screen->base.GLXminor = 4; + + screen->enterVT = pScrn->EnterVT; + pScrn->EnterVT = glxDRIEnterVT; + screen->leaveVT = pScrn->LeaveVT; + pScrn->LeaveVT = glxDRILeaveVT; + + LogMessage(X_INFO, + "AIGLX: Loaded and initialized %s\n", filename); + + return &screen->base; + + handle_error: + if (screen->driver) + dlclose(screen->driver); + + xfree(screen); + + LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n"); + + return NULL; +} + +_X_EXPORT __GLXprovider __glXDRI2Provider = { + __glXDRIscreenProbe, + "DRI2", + NULL +}; diff --git a/xorg-server/hw/dmx/examples/xinput.c b/xorg-server/hw/dmx/examples/xinput.c index 74353a93b..7421be337 100644 --- a/xorg-server/hw/dmx/examples/xinput.c +++ b/xorg-server/hw/dmx/examples/xinput.c @@ -233,7 +233,7 @@ int main(int argc, char **argv) int total = 0; #define ADD(type) \ - if (cnt >= MAX_EVENTS) abort(); \ + if (cnt >= MAX_EVENTS) OsAbort(); \ names[cnt] = #type; \ type(dev, event_type[cnt], event_list[cnt]); \ if (event_type[cnt]) ++cnt diff --git a/xorg-server/hw/kdrive/src/kdrive.c b/xorg-server/hw/kdrive/src/kdrive.c index 7675c1e86..1902ab885 100644 --- a/xorg-server/hw/kdrive/src/kdrive.c +++ b/xorg-server/hw/kdrive/src/kdrive.c @@ -335,7 +335,7 @@ AbortDDX(void) } if (kdCaughtSignal) - abort(); + OsAbort(); } void diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index 2c206ff47..72241a776 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -1235,7 +1235,7 @@ ddxGiveUp(void) /* If an unexpected signal was caught, dump a core for debugging */ if (xf86Info.caughtSignal) - abort(); + OsAbort(); } diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index cfe808e3e..9b1ff280b 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -1,3198 +1,3199 @@ -/* - * Copyright © 2006 Keith Packard - * Copyright © 2008 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#else -#ifdef HAVE_CONFIG_H -#include -#endif -#endif - -#include -#include -#include - -#include "xf86.h" -#include "xf86DDC.h" -#include "xf86Crtc.h" -#include "xf86Modes.h" -#include "xf86Priv.h" -#include "xf86RandR12.h" -#include "X11/extensions/render.h" -#include "X11/extensions/dpmsconst.h" -#include "X11/Xatom.h" -#ifdef RENDER -#include "picturestr.h" -#endif - -#include "xf86xv.h" - -/* - * Initialize xf86CrtcConfig structure - */ - -int xf86CrtcConfigPrivateIndex = -1; - -void -xf86CrtcConfigInit (ScrnInfoPtr scrn, - const xf86CrtcConfigFuncsRec *funcs) -{ - xf86CrtcConfigPtr config; - - if (xf86CrtcConfigPrivateIndex == -1) - xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); - - config->funcs = funcs; - - scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; -} - -void -xf86CrtcSetSizeRange (ScrnInfoPtr scrn, - int minWidth, int minHeight, - int maxWidth, int maxHeight) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - config->minWidth = minWidth; - config->minHeight = minHeight; - config->maxWidth = maxWidth; - config->maxHeight = maxHeight; -} - -/* - * Crtc functions - */ -xf86CrtcPtr -xf86CrtcCreate (ScrnInfoPtr scrn, - const xf86CrtcFuncsRec *funcs) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc, *crtcs; - - crtc = xcalloc (sizeof (xf86CrtcRec), 1); - if (!crtc) - return NULL; - crtc->version = XF86_CRTC_VERSION; - crtc->scrn = scrn; - crtc->funcs = funcs; -#ifdef RANDR_12_INTERFACE - crtc->randr_crtc = NULL; -#endif - crtc->rotation = RR_Rotate_0; - crtc->desiredRotation = RR_Rotate_0; - pixman_transform_init_identity (&crtc->crtc_to_framebuffer); - pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); - pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); - crtc->filter = NULL; - crtc->params = NULL; - crtc->nparams = 0; - crtc->filter_width = 0; - crtc->filter_height = 0; - crtc->transform_in_use = FALSE; - crtc->transformPresent = FALSE; - crtc->desiredTransformPresent = FALSE; - memset (&crtc->bounds, '\0', sizeof (crtc->bounds)); - - /* Preallocate gamma at a sensible size. */ - crtc->gamma_size = 256; - crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16)); - if (!crtc->gamma_red) { - xfree (crtc); - return NULL; - } - crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; - crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; - - if (xf86_config->crtc) - crtcs = xrealloc (xf86_config->crtc, - (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); - else - crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); - if (!crtcs) - { - xfree (crtc); - return NULL; - } - xf86_config->crtc = crtcs; - xf86_config->crtc[xf86_config->num_crtc++] = crtc; - return crtc; -} - -void -xf86CrtcDestroy (xf86CrtcPtr crtc) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); - int c; - - (*crtc->funcs->destroy) (crtc); - for (c = 0; c < xf86_config->num_crtc; c++) - if (xf86_config->crtc[c] == crtc) - { - memmove (&xf86_config->crtc[c], - &xf86_config->crtc[c+1], - ((xf86_config->num_crtc - (c + 1)) * sizeof(void*))); - xf86_config->num_crtc--; - break; - } - if (crtc->params) - xfree (crtc->params); - free(crtc->gamma_red); - xfree (crtc); -} - - -/** - * Return whether any outputs are connected to the specified pipe - */ - -Bool -xf86CrtcInUse (xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int o; - - for (o = 0; o < xf86_config->num_output; o++) - if (xf86_config->output[o]->crtc == crtc) - return TRUE; - return FALSE; -} - -void -xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen) -{ -#ifdef RENDER - int subpixel_order = SubPixelUnknown; - Bool has_none = FALSE; - ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - for (o = 0; o < xf86_config->num_output; o++) - { - xf86OutputPtr output = xf86_config->output[o]; - - if (output->crtc == crtc) - { - switch (output->subpixel_order) { - case SubPixelNone: - has_none = TRUE; - break; - case SubPixelUnknown: - break; - default: - subpixel_order = output->subpixel_order; - break; - } - } - if (subpixel_order != SubPixelUnknown) - break; - } - if (subpixel_order != SubPixelUnknown) - { - static const int circle[4] = { - SubPixelHorizontalRGB, - SubPixelVerticalRGB, - SubPixelHorizontalBGR, - SubPixelVerticalBGR, - }; - int rotate; - int c; - for (rotate = 0; rotate < 4; rotate++) - if (crtc->rotation & (1 << rotate)) - break; - for (c = 0; c < 4; c++) - if (circle[c] == subpixel_order) - break; - c = (c + rotate) & 0x3; - if ((crtc->rotation & RR_Reflect_X) && !(c & 1)) - c ^= 2; - if ((crtc->rotation & RR_Reflect_Y) && (c & 1)) - c ^= 2; - subpixel_order = circle[c]; - break; - } - } - if (subpixel_order == SubPixelUnknown && has_none) - subpixel_order = SubPixelNone; - PictureSetSubpixelOrder (pScreen, subpixel_order); -#endif -} - -/** - * Sets the given video mode on the given crtc - */ -Bool -xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, - RRTransformPtr transform, int x, int y) -{ - ScrnInfoPtr scrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int i; - Bool ret = FALSE; - Bool didLock = FALSE; - DisplayModePtr adjusted_mode; - DisplayModeRec saved_mode; - int saved_x, saved_y; - Rotation saved_rotation; - RRTransformRec saved_transform; - Bool saved_transform_present; - - crtc->enabled = xf86CrtcInUse (crtc); - - /* We only hit this if someone explicitly sends a "disabled" modeset. */ - if (!crtc->enabled) - { - /* Check everything for stuff that should be off. */ - xf86DisableUnusedFunctions(scrn); - return TRUE; - } - - adjusted_mode = xf86DuplicateMode(mode); - - - saved_mode = crtc->mode; - saved_x = crtc->x; - saved_y = crtc->y; - saved_rotation = crtc->rotation; - if (crtc->transformPresent) { - RRTransformInit (&saved_transform); - RRTransformCopy (&saved_transform, &crtc->transform); - } - saved_transform_present = crtc->transformPresent; - - /* Update crtc values up front so the driver can rely on them for mode - * setting. - */ - crtc->mode = *mode; - crtc->x = x; - crtc->y = y; - crtc->rotation = rotation; - if (transform) { - RRTransformCopy (&crtc->transform, transform); - crtc->transformPresent = TRUE; - } else - crtc->transformPresent = FALSE; - - if (crtc->funcs->set_mode_major) { - ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y); - goto done; - } - - didLock = crtc->funcs->lock (crtc); - /* Pass our mode to the outputs and the CRTC to give them a chance to - * adjust it according to limitations or output properties, and also - * a chance to reject the mode entirely. - */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { - goto done; - } - } - - if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { - goto done; - } - - if (!xf86CrtcRotate (crtc)) - goto done; - - /* Prepare the outputs and CRTCs before setting the mode. */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - /* Disable the output as the first thing we do. */ - output->funcs->prepare(output); - } - - crtc->funcs->prepare(crtc); - - /* Set up the DPLL and any output state that needs to adjust or depend - * on the DPLL. - */ - crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y); - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->mode_set(output, mode, adjusted_mode); - } - - /* Only upload when needed, to avoid unneeded delays. */ - if (!crtc->active && crtc->funcs->gamma_set) - crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); - - /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ - crtc->funcs->commit(crtc); - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->commit(output); - } - - ret = TRUE; - -done: - if (ret) { - crtc->active = TRUE; - if (scrn->pScreen) - xf86CrtcSetScreenSubpixelOrder (scrn->pScreen); - } else { - crtc->x = saved_x; - crtc->y = saved_y; - crtc->rotation = saved_rotation; - crtc->mode = saved_mode; - if (saved_transform_present) - RRTransformCopy (&crtc->transform, &saved_transform); - crtc->transformPresent = saved_transform_present; - } - - if (adjusted_mode->name) - xfree(adjusted_mode->name); - xfree(adjusted_mode); - - if (didLock) - crtc->funcs->unlock (crtc); - - return ret; -} - -/** - * Sets the given video mode on the given crtc, but without providing - * a transform - */ -Bool -xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, - int x, int y) -{ - return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y); -} - -/** - * Pans the screen, does not change the mode - */ -void -xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y) -{ - crtc->x = x; - crtc->y = y; - if (crtc->funcs->set_origin) { - if (!xf86CrtcRotate (crtc)) - return; - crtc->funcs->set_origin (crtc, x, y); - } - else - xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y); -} - -/* - * Output functions - */ - -extern XF86ConfigPtr xf86configptr; - -typedef enum { - OPTION_PREFERRED_MODE, - OPTION_POSITION, - OPTION_BELOW, - OPTION_RIGHT_OF, - OPTION_ABOVE, - OPTION_LEFT_OF, - OPTION_ENABLE, - OPTION_DISABLE, - OPTION_MIN_CLOCK, - OPTION_MAX_CLOCK, - OPTION_IGNORE, - OPTION_ROTATE, - OPTION_PANNING, - OPTION_PRIMARY, -} OutputOpts; - -static OptionInfoRec xf86OutputOptions[] = { - {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, - {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, - {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, - {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, - {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, - {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, - {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, - {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, - {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, - {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE }, - {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE }, - {-1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -enum { - OPTION_MODEDEBUG, -}; - -static OptionInfoRec xf86DeviceOptions[] = { - {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE }, - {-1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -static void -xf86OutputSetMonitor (xf86OutputPtr output) -{ - char *option_name; - static const char monitor_prefix[] = "monitor-"; - char *monitor; - - if (!output->name) - return; - - if (output->options) - xfree (output->options); - - output->options = xnfalloc (sizeof (xf86OutputOptions)); - memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); - - option_name = xnfalloc (strlen (monitor_prefix) + - strlen (output->name) + 1); - strcpy (option_name, monitor_prefix); - strcat (option_name, output->name); - monitor = xf86findOptionValue (output->scrn->options, option_name); - if (!monitor) - monitor = output->name; - else - xf86MarkOptionUsedByName (output->scrn->options, option_name); - xfree (option_name); - output->conf_monitor = xf86findMonitor (monitor, - xf86configptr->conf_monitor_lst); - /* - * Find the monitor section of the screen and use that - */ - if (!output->conf_monitor && output->use_screen_monitor) - output->conf_monitor = xf86findMonitor (output->scrn->monitor->id, - xf86configptr->conf_monitor_lst); - if (output->conf_monitor) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s using monitor section %s\n", - output->name, output->conf_monitor->mon_identifier); - xf86ProcessOptions (output->scrn->scrnIndex, - output->conf_monitor->mon_option_lst, - output->options); - } - else - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s has no monitor section\n", - output->name); -} - -static Bool -xf86OutputEnabled (xf86OutputPtr output, Bool strict) -{ - Bool enable, disable; - - /* check to see if this output was enabled in the config file */ - if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s enabled by config file\n", output->name); - return TRUE; - } - /* or if this output was disabled in the config file */ - if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s disabled by config file\n", output->name); - return FALSE; - } - - /* If not, try to only light up the ones we know are connected */ - if (strict) { - enable = output->status == XF86OutputStatusConnected; - } - /* But if that fails, try to light up even outputs we're unsure of */ - else { - enable = output->status != XF86OutputStatusDisconnected; - } - - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s %sconnected\n", output->name, enable ? "" : "dis"); - return enable; -} - -static Bool -xf86OutputIgnored (xf86OutputPtr output) -{ - return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE); -} - -static char *direction[4] = { - "normal", - "left", - "inverted", - "right" -}; - -static Rotation -xf86OutputInitialRotation (xf86OutputPtr output) -{ - char *rotate_name = xf86GetOptValString (output->options, - OPTION_ROTATE); - int i; - - if (!rotate_name) - return RR_Rotate_0; - - for (i = 0; i < 4; i++) - if (xf86nameCompare (direction[i], rotate_name) == 0) - return (1 << i); - return RR_Rotate_0; -} - -xf86OutputPtr -xf86OutputCreate (ScrnInfoPtr scrn, - const xf86OutputFuncsRec *funcs, - const char *name) -{ - xf86OutputPtr output, *outputs; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int len; - Bool primary; - - if (name) - len = strlen (name) + 1; - else - len = 0; - - output = xcalloc (sizeof (xf86OutputRec) + len, 1); - if (!output) - return NULL; - output->scrn = scrn; - output->funcs = funcs; - if (name) - { - output->name = (char *) (output + 1); - strcpy (output->name, name); - } - output->subpixel_order = SubPixelUnknown; - /* - * Use the old per-screen monitor section for the first output - */ - output->use_screen_monitor = (xf86_config->num_output == 0); -#ifdef RANDR_12_INTERFACE - output->randr_output = NULL; -#endif - if (name) - { - xf86OutputSetMonitor (output); - if (xf86OutputIgnored (output)) - { - xfree (output); - return FALSE; - } - } - - - if (xf86_config->output) - outputs = xrealloc (xf86_config->output, - (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); - else - outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); - if (!outputs) - { - xfree (output); - return NULL; - } - - xf86_config->output = outputs; - - if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary) - { - memmove(xf86_config->output + 1, xf86_config->output, - xf86_config->num_output * sizeof (xf86OutputPtr)); - xf86_config->output[0] = output; - } - else - { - xf86_config->output[xf86_config->num_output] = output; - } - - xf86_config->num_output++; - - return output; -} - -Bool -xf86OutputRename (xf86OutputPtr output, const char *name) -{ - int len = strlen(name) + 1; - char *newname = xalloc (len); - - if (!newname) - return FALSE; /* so sorry... */ - - strcpy (newname, name); - if (output->name && output->name != (char *) (output + 1)) - xfree (output->name); - output->name = newname; - xf86OutputSetMonitor (output); - if (xf86OutputIgnored (output)) - return FALSE; - return TRUE; -} - -void -xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor) -{ - if (use_screen_monitor != output->use_screen_monitor) - { - output->use_screen_monitor = use_screen_monitor; - xf86OutputSetMonitor (output); - } -} - -void -xf86OutputDestroy (xf86OutputPtr output) -{ - ScrnInfoPtr scrn = output->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - (*output->funcs->destroy) (output); - while (output->probed_modes) - xf86DeleteMode (&output->probed_modes, output->probed_modes); - for (o = 0; o < xf86_config->num_output; o++) - if (xf86_config->output[o] == output) - { - memmove (&xf86_config->output[o], - &xf86_config->output[o+1], - ((xf86_config->num_output - (o + 1)) * sizeof(void*))); - xf86_config->num_output--; - break; - } - if (output->name && output->name != (char *) (output + 1)) - xfree (output->name); - xfree (output); -} - -/* - * Called during CreateScreenResources to hook up RandR - */ -static Bool -xf86CrtcCreateScreenResources (ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - screen->CreateScreenResources = config->CreateScreenResources; - - if (!(*screen->CreateScreenResources)(screen)) - return FALSE; - - if (!xf86RandR12CreateScreenResources (screen)) - return FALSE; - - return TRUE; -} - -/* - * Clean up config on server reset - */ -static Bool -xf86CrtcCloseScreen (int index, ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o, c; - - screen->CloseScreen = config->CloseScreen; - - xf86RotateCloseScreen (screen); - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->randr_output = NULL; - } - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->randr_crtc = NULL; - } - return screen->CloseScreen (index, screen); -} - -/* - * Called at ScreenInit time to set up - */ -#ifdef RANDR_13_INTERFACE -int -#else -Bool -#endif -xf86CrtcScreenInit (ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c; - - /* Rotation */ - xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n"); - xf86DisableRandR(); /* Disable old RandR extension support */ - xf86RandR12Init (screen); - - /* support all rotations if every crtc has the shadow alloc funcs */ - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create) - break; - } - if (c == config->num_crtc) - { - xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 | - RR_Rotate_180 | RR_Rotate_270 | - RR_Reflect_X | RR_Reflect_Y); - xf86RandR12SetTransformSupport (screen, TRUE); - } - else - { - xf86RandR12SetRotations (screen, RR_Rotate_0); - xf86RandR12SetTransformSupport (screen, FALSE); - } - - /* Wrap CreateScreenResources so we can initialize the RandR code */ - config->CreateScreenResources = screen->CreateScreenResources; - screen->CreateScreenResources = xf86CrtcCreateScreenResources; - - config->CloseScreen = screen->CloseScreen; - screen->CloseScreen = xf86CrtcCloseScreen; - -#ifdef XFreeXDGA - _xf86_di_dga_init_internal(screen); -#endif -#ifdef RANDR_13_INTERFACE - return RANDR_INTERFACE_VERSION; -#else - return TRUE; -#endif -} - -static DisplayModePtr -xf86DefaultMode (xf86OutputPtr output, int width, int height) -{ - DisplayModePtr target_mode = NULL; - DisplayModePtr mode; - int target_diff = 0; - int target_preferred = 0; - int mm_height; - - mm_height = output->mm_height; - if (!mm_height) - mm_height = (768 * 25.4) / DEFAULT_DPI; - /* - * Pick a mode closest to DEFAULT_DPI - */ - for (mode = output->probed_modes; mode; mode = mode->next) - { - int dpi; - int preferred = (((mode->type & M_T_PREFERRED) != 0) + - ((mode->type & M_T_USERPREF) != 0)); - int diff; - - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - /* yes, use VDisplay here, not xf86ModeHeight */ - dpi = (mode->VDisplay * 254) / (mm_height * 10); - diff = dpi - DEFAULT_DPI; - diff = diff < 0 ? -diff : diff; - if (target_mode == NULL || (preferred > target_preferred) || - (preferred == target_preferred && diff < target_diff)) - { - target_mode = mode; - target_diff = diff; - target_preferred = preferred; - } - } - return target_mode; -} - -static DisplayModePtr -xf86ClosestMode (xf86OutputPtr output, - DisplayModePtr match, Rotation match_rotation, - int width, int height) -{ - DisplayModePtr target_mode = NULL; - DisplayModePtr mode; - int target_diff = 0; - - /* - * Pick a mode closest to the specified mode - */ - for (mode = output->probed_modes; mode; mode = mode->next) - { - int dx, dy; - int diff; - - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - /* exact matches are preferred */ - if (output->initial_rotation == match_rotation && - xf86ModesEqual (mode, match)) - return mode; - - dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation); - dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation); - diff = dx * dx + dy * dy; - if (target_mode == NULL || diff < target_diff) - { - target_mode = mode; - target_diff = diff; - } - } - return target_mode; -} - -static DisplayModePtr -xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height) -{ - DisplayModePtr mode; - - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - if (mode->type & M_T_PREFERRED) - return mode; - } - return NULL; -} - -static DisplayModePtr -xf86OutputHasUserPreferredMode (xf86OutputPtr output) -{ - DisplayModePtr mode, first = output->probed_modes; - - for (mode = first; mode && mode->next != first; mode = mode->next) - if (mode->type & M_T_USERPREF) - return mode; - - return NULL; -} - -static int -xf86PickCrtcs (ScrnInfoPtr scrn, - xf86CrtcPtr *best_crtcs, - DisplayModePtr *modes, - int n, - int width, - int height) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; - xf86OutputPtr output; - xf86CrtcPtr crtc; - xf86CrtcPtr *crtcs; - xf86CrtcPtr best_crtc; - int best_score; - int score; - int my_score; - - if (n == config->num_output) - return 0; - output = config->output[n]; - - /* - * Compute score with this output disabled - */ - best_crtcs[n] = NULL; - best_crtc = NULL; - best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height); - if (modes[n] == NULL) - return best_score; - - crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr)); - if (!crtcs) - return best_score; - - my_score = 1; - /* Score outputs that are known to be connected higher */ - if (output->status == XF86OutputStatusConnected) - my_score++; - /* Score outputs with preferred modes higher */ - if (xf86OutputHasPreferredMode (output, width, height)) - my_score++; - /* - * Select a crtc for this output and - * then attempt to configure the remaining - * outputs - */ - for (c = 0; c < config->num_crtc; c++) - { - if ((output->possible_crtcs & (1 << c)) == 0) - continue; - - crtc = config->crtc[c]; - /* - * Check to see if some other output is - * using this crtc - */ - for (o = 0; o < n; o++) - if (best_crtcs[o] == crtc) - break; - if (o < n) - { - /* - * If the two outputs desire the same mode, - * see if they can be cloned - */ - if (xf86ModesEqual (modes[o], modes[n]) && - config->output[o]->initial_rotation == config->output[n]->initial_rotation && - config->output[o]->initial_x == config->output[n]->initial_x && - config->output[o]->initial_y == config->output[n]->initial_y) - { - if ((output->possible_clones & (1 << o)) == 0) - continue; /* nope, try next CRTC */ - } - else - continue; /* different modes, can't clone */ - } - crtcs[n] = crtc; - memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); - score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height); - if (score > best_score) - { - best_crtc = crtc; - best_score = score; - memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); - } - } - xfree (crtcs); - return best_score; -} - - -/* - * Compute the virtual size necessary to place all of the available - * crtcs in the specified configuration. - * - * canGrow indicates that the driver can make the screen larger than its initial - * configuration. If FALSE, this function will enlarge the screen to include - * the largest available mode. - */ - -static void -xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp, - Bool canGrow) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int width = 0, height = 0; - int o; - int c; - int s; - - for (c = 0; c < config->num_crtc; c++) - { - int crtc_width = 0, crtc_height = 0; - xf86CrtcPtr crtc = config->crtc[c]; - - if (crtc->enabled) - { - crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation); - crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation); - } - if (!canGrow) { - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - for (s = 0; s < config->num_crtc; s++) - if (output->possible_crtcs & (1 << s)) - { - DisplayModePtr mode; - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (mode->HDisplay > crtc_width) - crtc_width = mode->HDisplay; - if (mode->VDisplay > crtc_width) - crtc_width = mode->VDisplay; - if (mode->VDisplay > crtc_height) - crtc_height = mode->VDisplay; - if (mode->HDisplay > crtc_height) - crtc_height = mode->HDisplay; - } - } - } - } - if (crtc_width > width) - width = crtc_width; - if (crtc_height > height) - height = crtc_height; - } - if (config->maxWidth && width > config->maxWidth) width = config->maxWidth; - if (config->maxHeight && height > config->maxHeight) height = config->maxHeight; - if (config->minWidth && width < config->minWidth) width = config->minWidth; - if (config->minHeight && height < config->minHeight) height = config->minHeight; - *widthp = width; - *heightp = height; -} - -#define POSITION_UNSET -100000 - -/* - * check if the user configured any outputs at all - * with either a position or a relative setting or a mode. - */ -static Bool -xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - Bool user_conf = FALSE; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - char *position; - char *relative_name; - OutputOpts relation; - int r; - static const OutputOpts relations[] = { - OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF - }; - - position = xf86GetOptValString (output->options, - OPTION_POSITION); - if (position) - user_conf = TRUE; - - relation = 0; - relative_name = NULL; - for (r = 0; r < 4; r++) - { - relation = relations[r]; - relative_name = xf86GetOptValString (output->options, - relation); - if (relative_name) - break; - } - if (relative_name) - user_conf = TRUE; - - modes[o] = xf86OutputHasUserPreferredMode(output); - if (modes[o]) - user_conf = TRUE; - } - - return user_conf; -} - -static Bool -xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - int min_x, min_y; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->initial_x = output->initial_y = POSITION_UNSET; - } - - /* - * Loop until all outputs are set - */ - for (;;) - { - Bool any_set = FALSE; - Bool keep_going = FALSE; - - for (o = 0; o < config->num_output; o++) - { - static const OutputOpts relations[] = { - OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF - }; - xf86OutputPtr output = config->output[o]; - xf86OutputPtr relative; - char *relative_name; - char *position; - OutputOpts relation; - int r; - - if (output->initial_x != POSITION_UNSET) - continue; - position = xf86GetOptValString (output->options, - OPTION_POSITION); - /* - * Absolute position wins - */ - if (position) - { - int x, y; - if (sscanf (position, "%d %d", &x, &y) == 2) - { - output->initial_x = x; - output->initial_y = y; - } - else - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output %s position not of form \"x y\"\n", - output->name); - output->initial_x = output->initial_y = 0; - } - any_set = TRUE; - continue; - } - /* - * Next comes relative positions - */ - relation = 0; - relative_name = NULL; - for (r = 0; r < 4; r++) - { - relation = relations[r]; - relative_name = xf86GetOptValString (output->options, - relation); - if (relative_name) - break; - } - if (relative_name) - { - int or; - relative = NULL; - for (or = 0; or < config->num_output; or++) - { - xf86OutputPtr out_rel = config->output[or]; - XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; - - if (rel_mon) - { - if (xf86nameCompare (rel_mon->mon_identifier, - relative_name) == 0) - { - relative = config->output[or]; - break; - } - } - if (strcmp (out_rel->name, relative_name) == 0) - { - relative = config->output[or]; - break; - } - } - if (!relative) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Cannot position output %s relative to unknown output %s\n", - output->name, relative_name); - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - continue; - } - if (!modes[or]) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Cannot position output %s relative to output %s without modes\n", - output->name, relative_name); - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - continue; - } - if (relative->initial_x == POSITION_UNSET) - { - keep_going = TRUE; - continue; - } - output->initial_x = relative->initial_x; - output->initial_y = relative->initial_y; - switch (relation) { - case OPTION_BELOW: - output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation); - break; - case OPTION_RIGHT_OF: - output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation); - break; - case OPTION_ABOVE: - if (modes[o]) - output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation); - break; - case OPTION_LEFT_OF: - if (modes[o]) - output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation); - break; - default: - break; - } - any_set = TRUE; - continue; - } - - /* Nothing set, just stick them at 0,0 */ - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - } - if (!keep_going) - break; - if (!any_set) - { - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - if (output->initial_x == POSITION_UNSET) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output position loop. Moving %s to 0,0\n", - output->name); - output->initial_x = output->initial_y = 0; - break; - } - } - } - } - - /* - * normalize positions - */ - min_x = 1000000; - min_y = 1000000; - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - if (output->initial_x < min_x) - min_x = output->initial_x; - if (output->initial_y < min_y) - min_y = output->initial_y; - } - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->initial_x -= min_x; - output->initial_y -= min_y; - } - return TRUE; -} - -static void -xf86InitialPanning (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - char *panning = xf86GetOptValString (output->options, OPTION_PANNING); - int width, height, left, top; - int track_width, track_height, track_left, track_top; - int brdr[4]; - - memset (&output->initialTotalArea, 0, sizeof(BoxRec)); - memset (&output->initialTrackingArea, 0, sizeof(BoxRec)); - memset (output->initialBorder, 0, 4*sizeof(INT16)); - - if (! panning) - continue; - - switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", - &width, &height, &left, &top, - &track_width, &track_height, &track_left, &track_top, - &brdr[0], &brdr[1], &brdr[2], &brdr[3])) { - case 12: - output->initialBorder[0] = brdr[0]; - output->initialBorder[1] = brdr[1]; - output->initialBorder[2] = brdr[2]; - output->initialBorder[3] = brdr[3]; - /* fall through */ - case 8: - output->initialTrackingArea.x1 = track_left; - output->initialTrackingArea.y1 = track_top; - output->initialTrackingArea.x2 = track_left + track_width; - output->initialTrackingArea.y2 = track_top + track_height; - /* fall through */ - case 4: - output->initialTotalArea.x1 = left; - output->initialTotalArea.y1 = top; - /* fall through */ - case 2: - output->initialTotalArea.x2 = output->initialTotalArea.x1 + width; - output->initialTotalArea.y2 = output->initialTotalArea.y1 + height; - break; - default: - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Broken panning specification '%s' for output %s in config file\n", - panning, output->name); - } - } -} - -/** Return - 0 + if a should be earlier, same or later than b in list - */ -static int -xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) -{ - int diff; - - diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); - if (diff) - return diff; - diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; - if (diff) - return diff; - diff = b->Clock - a->Clock; - return diff; -} - -/** - * Insertion sort input in-place and return the resulting head - */ -static DisplayModePtr -xf86SortModes (DisplayModePtr input) -{ - DisplayModePtr output = NULL, i, o, n, *op, prev; - - /* sort by preferred status and pixel area */ - while (input) - { - i = input; - input = input->next; - for (op = &output; (o = *op); op = &o->next) - if (xf86ModeCompare (o, i) > 0) - break; - i->next = *op; - *op = i; - } - /* prune identical modes */ - for (o = output; o && (n = o->next); o = n) - { - if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) - { - o->next = n->next; - xfree (n->name); - xfree (n); - n = o; - } - } - /* hook up backward links */ - prev = NULL; - for (o = output; o; o = o->next) - { - o->prev = prev; - prev = o; - } - return output; -} - -static char * -preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) -{ - char *preferred_mode = NULL; - - /* Check for a configured preference for a particular mode */ - preferred_mode = xf86GetOptValString (output->options, - OPTION_PREFERRED_MODE); - if (preferred_mode) - return preferred_mode; - - if (pScrn->display->modes && *pScrn->display->modes) - preferred_mode = *pScrn->display->modes; - - return preferred_mode; -} - -static void -GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) -{ - if (!mon || !mode) - return; - - mon->nHsync = 1; - mon->hsync[0].lo = 1024.0; - mon->hsync[0].hi = 0.0; - - mon->nVrefresh = 1; - mon->vrefresh[0].lo = 1024.0; - mon->vrefresh[0].hi = 0.0; - - while (mode) { - if (!mode->HSync) - mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal); - - if (!mode->VRefresh) - mode->VRefresh = (1000.0 * ((float) mode->Clock)) / - ((float) (mode->HTotal * mode->VTotal)); - - if (mode->HSync < mon->hsync[0].lo) - mon->hsync[0].lo = mode->HSync; - - if (mode->HSync > mon->hsync[0].hi) - mon->hsync[0].hi = mode->HSync; - - if (mode->VRefresh < mon->vrefresh[0].lo) - mon->vrefresh[0].lo = mode->VRefresh; - - if (mode->VRefresh > mon->vrefresh[0].hi) - mon->vrefresh[0].hi = mode->VRefresh; - - mode = mode->next; - } - - /* stretch out the bottom to fit 640x480@60 */ - if (mon->hsync[0].lo > 31.0) - mon->hsync[0].lo = 31.0; - if (mon->vrefresh[0].lo > 58.0) - mon->vrefresh[0].lo = 58.0; -} - -struct det_monrec_parameter { - MonRec *mon_rec; - int *max_clock; - Bool set_hsync; - Bool set_vrefresh; - enum { sync_config, sync_edid, sync_default } *sync_source; -}; - -static void handle_detailed_monrec(struct detailed_monitor_section *det_mon, - void *data) -{ - enum { sync_config, sync_edid, sync_default }; - struct det_monrec_parameter *p; - p = (struct det_monrec_parameter *)data; - - if (det_mon->type == DS_RANGES) { - struct monitor_ranges *ranges = &det_mon->section.ranges; - if (p->set_hsync && ranges->max_h) { - p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h; - p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h; - p->mon_rec->nHsync++; - if (*p->sync_source == sync_default) - *p->sync_source = sync_edid; - } - if (p->set_vrefresh && ranges->max_v) { - p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v; - p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v; - p->mon_rec->nVrefresh++; - if (*p->sync_source == sync_default) - *p->sync_source = sync_edid; - } - if (ranges->max_clock * 1000 > *p->max_clock) - *p->max_clock = ranges->max_clock * 1000; - } -} - -void -xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - /* When canGrow was TRUE in the initial configuration we have to - * compare against the maximum values so that we don't drop modes. - * When canGrow was FALSE, the maximum values would have been clamped - * anyway. - */ - if (maxX == 0 || maxY == 0) { - maxX = config->maxWidth; - maxY = config->maxHeight; - } - - /* Probe the list of modes for each output. */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode; - DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL; - char *preferred_mode; - xf86MonPtr edid_monitor; - XF86ConfMonitorPtr conf_monitor; - MonRec mon_rec; - int min_clock = 0; - int max_clock = 0; - double clock; - Bool add_default_modes = TRUE; - Bool debug_modes = config->debug_modes || - xf86Initialising; - enum { sync_config, sync_edid, sync_default } sync_source = sync_default; - - while (output->probed_modes != NULL) - xf86DeleteMode(&output->probed_modes, output->probed_modes); - - /* - * Check connection status - */ - output->status = (*output->funcs->detect)(output); - - if (output->status == XF86OutputStatusDisconnected) - { - xf86OutputSetEDID (output, NULL); - continue; - } - - memset (&mon_rec, '\0', sizeof (mon_rec)); - - conf_monitor = output->conf_monitor; - - if (conf_monitor) - { - int i; - - for (i = 0; i < conf_monitor->mon_n_hsync; i++) - { - mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; - mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; - mon_rec.nHsync++; - sync_source = sync_config; - } - for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) - { - mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; - mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; - mon_rec.nVrefresh++; - sync_source = sync_config; - } - config_modes = xf86GetMonitorModes (scrn, conf_monitor); - } - - output_modes = (*output->funcs->get_modes) (output); - - edid_monitor = output->MonInfo; - - if (edid_monitor) - { - struct det_monrec_parameter p; - struct disp_features *features = &edid_monitor->features; - - /* if display is not continuous-frequency, don't add default modes */ - if (!GTF_SUPPORTED(features->msc)) - add_default_modes = FALSE; - - p.mon_rec = &mon_rec; - p.max_clock = &max_clock; - p.set_hsync = mon_rec.nHsync == 0; - p.set_vrefresh = mon_rec.nVrefresh == 0; - p.sync_source = &sync_source; - - xf86ForEachDetailedBlock(edid_monitor, - handle_detailed_monrec, - &p); - } - - if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, - OPTUNITS_KHZ, &clock)) - min_clock = (int) clock; - if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, - OPTUNITS_KHZ, &clock)) - max_clock = (int) clock; - - /* If we still don't have a sync range, guess wildly */ - if (!mon_rec.nHsync || !mon_rec.nVrefresh) - GuessRangeFromModes(&mon_rec, output_modes); - - /* - * These limits will end up setting a 1024x768@60Hz mode by default, - * which seems like a fairly good mode to use when nothing else is - * specified - */ - if (mon_rec.nHsync == 0) - { - mon_rec.hsync[0].lo = 31.0; - mon_rec.hsync[0].hi = 55.0; - mon_rec.nHsync = 1; - } - if (mon_rec.nVrefresh == 0) - { - mon_rec.vrefresh[0].lo = 58.0; - mon_rec.vrefresh[0].hi = 62.0; - mon_rec.nVrefresh = 1; - } - - if (add_default_modes) - default_modes = xf86GetDefaultModes (); - - /* - * If this is not an RB monitor, remove RB modes from the default - * pool. RB modes from the config or the monitor itself are fine. - */ - if (!mon_rec.reducedblanking) - xf86ValidateModesReducedBlanking (scrn, default_modes); - - if (sync_source == sync_config) - { - /* - * Check output and config modes against sync range from config file - */ - xf86ValidateModesSync (scrn, output_modes, &mon_rec); - xf86ValidateModesSync (scrn, config_modes, &mon_rec); - } - /* - * Check default modes against sync range - */ - xf86ValidateModesSync (scrn, default_modes, &mon_rec); - /* - * Check default modes against monitor max clock - */ - if (max_clock) { - xf86ValidateModesClocks(scrn, default_modes, - &min_clock, &max_clock, 1); - xf86ValidateModesClocks(scrn, output_modes, - &min_clock, &max_clock, 1); - } - - output->probed_modes = NULL; - output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); - output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); - output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); - - /* - * Check all modes against max size, interlace, and doublescan - */ - if (maxX && maxY) - xf86ValidateModesSize (scrn, output->probed_modes, - maxX, maxY, 0); - - { - int flags = (output->interlaceAllowed ? V_INTERLACE : 0) | - (output->doubleScanAllowed ? V_DBLSCAN : 0); - xf86ValidateModesFlags (scrn, output->probed_modes, flags); - } - - /* - * Check all modes against output - */ - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - if (mode->status == MODE_OK) - mode->status = (*output->funcs->mode_valid)(output, mode); - - xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes); - - output->probed_modes = xf86SortModes (output->probed_modes); - - /* Check for a configured preference for a particular mode */ - preferred_mode = preferredMode(scrn, output); - - if (preferred_mode) - { - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (!strcmp (preferred_mode, mode->name)) - { - if (mode != output->probed_modes) - { - if (mode->prev) - mode->prev->next = mode->next; - if (mode->next) - mode->next->prev = mode->prev; - mode->next = output->probed_modes; - output->probed_modes->prev = mode; - mode->prev = NULL; - output->probed_modes = mode; - } - mode->type |= (M_T_PREFERRED|M_T_USERPREF); - break; - } - } - } - - output->initial_rotation = xf86OutputInitialRotation (output); - - if (debug_modes) { - if (output->probed_modes != NULL) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "Printing probed modes for output %s\n", - output->name); - } else { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "No remaining probed modes for output %s\n", - output->name); - } - } - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - { - /* The code to choose the best mode per pipe later on will require - * VRefresh to be set. - */ - mode->VRefresh = xf86ModeVRefresh(mode); - xf86SetModeCrtc(mode, INTERLACE_HALVE_V); - - if (debug_modes) - xf86PrintModeline(scrn->scrnIndex, mode); - } - } -} - - -/** - * Copy one of the output mode lists to the ScrnInfo record - */ - -/* XXX where does this function belong? Here? */ -void -xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y); - -static DisplayModePtr -biggestMode(DisplayModePtr a, DisplayModePtr b) -{ - int A, B; - - if (!a) - return b; - if (!b) - return a; - - A = a->HDisplay * a->VDisplay; - B = b->HDisplay * b->VDisplay; - - if (A > B) - return a; - - return b; -} - -static xf86OutputPtr -SetCompatOutput(xf86CrtcConfigPtr config) -{ - xf86OutputPtr output = NULL, test = NULL; - DisplayModePtr maxmode = NULL, testmode, mode; - int o, compat = -1, count, mincount = 0; - - /* Look for one that's definitely connected */ - for (o = 0; o < config->num_output; o++) - { - test = config->output[o]; - if (!test->crtc) - continue; - if (test->status != XF86OutputStatusConnected) - continue; - if (!test->probed_modes) - continue; - - testmode = mode = test->probed_modes; - for (count = 0; mode; mode = mode->next, count++) - testmode = biggestMode(testmode, mode); - - if (!output) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } else if (maxmode == biggestMode(maxmode, testmode)) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } else if ((maxmode->HDisplay == testmode->HDisplay) && - (maxmode->VDisplay == testmode->VDisplay) && - count <= mincount) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } - } - - /* If we didn't find one, take anything we can get */ - if (!output) - { - for (o = 0; o < config->num_output; o++) - { - test = config->output[o]; - if (!test->crtc) - continue; - if (!test->probed_modes) - continue; - - if (!output) { - output = test; - compat = o; - } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) { - output = test; - compat = o; - } - } - } - - if (compat >= 0) { - config->compat_output = compat; - } else { - /* Don't change the compat output when no valid outputs found */ - output = config->output[config->compat_output]; - } - - return output; -} - -void -xf86SetScrnInfoModes (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86OutputPtr output; - xf86CrtcPtr crtc; - DisplayModePtr last, mode = NULL; - - output = SetCompatOutput(config); - - if (!output) - return; /* punt */ - - crtc = output->crtc; - - /* Clear any existing modes from scrn->modes */ - while (scrn->modes != NULL) - xf86DeleteMode(&scrn->modes, scrn->modes); - - /* Set scrn->modes to the mode list for the 'compat' output */ - scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); - - if (crtc) { - for (mode = scrn->modes; mode; mode = mode->next) - if (xf86ModesEqual (mode, &crtc->desiredMode)) - break; - } - - if (scrn->modes != NULL) { - /* For some reason, scrn->modes is circular, unlike the other mode - * lists. How great is that? - */ - for (last = scrn->modes; last && last->next; last = last->next) - ; - last->next = scrn->modes; - scrn->modes->prev = last; - if (mode) { - while (scrn->modes != mode) - scrn->modes = scrn->modes->next; - } - } - scrn->currentMode = scrn->modes; -#ifdef XFreeXDGA - if (scrn->pScreen) - _xf86_di_dga_reinit_internal(scrn->pScreen); -#endif -} - -static void -xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - Bool *enabled) -{ - Bool any_enabled = FALSE; - int o; - - for (o = 0; o < config->num_output; o++) - any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE); - - if (!any_enabled) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "No outputs definitely connected, trying again...\n"); - - for (o = 0; o < config->num_output; o++) - enabled[o] = xf86OutputEnabled(config->output[o], FALSE); - } -} - -static Bool -nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index) -{ - int o = *index; - - for (o++; o < config->num_output; o++) { - if (enabled[o]) { - *index = o; - return TRUE; - } - } - - return FALSE; -} - -static Bool -aspectMatch(float a, float b) -{ - return fabs(1 - (a / b)) < 0.05; -} - -static DisplayModePtr -nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) -{ - DisplayModePtr m = NULL; - - if (!o) - return NULL; - - if (!last) - m = o->probed_modes; - else - m = last->next; - - for (; m; m = m->next) - if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay)) - return m; - - return NULL; -} - -static DisplayModePtr -bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) -{ - int o = -1, p; - DisplayModePtr mode = NULL, test = NULL, match = NULL; - - if (!nextEnabledOutput(config, enabled, &o)) - return NULL; - while ((mode = nextAspectMode(config->output[o], mode, aspect))) { - test = mode; - for (p = o; nextEnabledOutput(config, enabled, &p); ) { - test = xf86OutputFindClosestMode(config->output[p], mode); - if (!test) - break; - if (test->HDisplay != mode->HDisplay || - test->VDisplay != mode->VDisplay) { - test = NULL; - break; - } - } - - /* if we didn't match it on all outputs, try the next one */ - if (!test) - continue; - - /* if it's bigger than the last one, save it */ - if (!match || (test->HDisplay > match->HDisplay)) - match = test; - } - - /* return the biggest one found */ - return match; -} - -static Bool -xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o, p; - int max_pref_width = 0, max_pref_height = 0; - DisplayModePtr *preferred, *preferred_match; - Bool ret = FALSE; - - preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); - preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); - - /* Check if the preferred mode is available on all outputs */ - for (p = -1; nextEnabledOutput(config, enabled, &p); ) { - Rotation r = config->output[p]->initial_rotation; - DisplayModePtr mode; - if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p], - width, height))) { - int pref_width = xf86ModeWidth(preferred[p], r); - int pref_height = xf86ModeHeight(preferred[p], r); - Bool all_match = TRUE; - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - Bool match = FALSE; - xf86OutputPtr output = config->output[o]; - if (o == p) - continue; - - for (mode = output->probed_modes; mode; mode = mode->next) { - Rotation r = output->initial_rotation; - if (xf86ModeWidth(mode, r) == pref_width && - xf86ModeHeight(mode, r) == pref_height) { - preferred[o] = mode; - match = TRUE; - } - } - - all_match &= match; - } - - if (all_match && - (pref_width*pref_height > max_pref_width*max_pref_height)) { - for (o = -1; nextEnabledOutput(config, enabled, &o); ) - preferred_match[o] = preferred[o]; - max_pref_width = pref_width; - max_pref_height = pref_height; - ret = TRUE; - } - } - } - - /* - * If there's no preferred mode, but only one monitor, pick the - * biggest mode for its aspect ratio, assuming one exists. - */ - if (!ret) do { - int i = 0; - float aspect = 0.0; - - /* count the number of enabled outputs */ - for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; - - if (i != 1) - break; - - p = -1; - nextEnabledOutput(config, enabled, &p); - if (config->output[p]->mm_height) - aspect = (float)config->output[p]->mm_width / - (float)config->output[p]->mm_height; - - if (aspect) - preferred_match[p] = bestModeForAspect(config, enabled, aspect); - - if (preferred_match[p]) - ret = TRUE; - - } while (0); - - if (ret) { - /* oh good, there is a match. stash the selected modes and return. */ - memcpy(modes, preferred_match, - config->num_output * sizeof(DisplayModePtr)); - } - - xfree(preferred); - xfree(preferred_match); - return ret; -} - -static Bool -xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o; - float aspect = 0.0, *aspects; - xf86OutputPtr output; - Bool ret = FALSE; - DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL; - - aspects = xnfcalloc(config->num_output, sizeof(float)); - - /* collect the aspect ratios */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - output = config->output[o]; - if (output->mm_height) - aspects[o] = (float)output->mm_width / (float)output->mm_height; - else - aspects[o] = 4.0 / 3.0; - } - - /* check that they're all the same */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - output = config->output[o]; - if (!aspect) { - aspect = aspects[o]; - } else if (!aspectMatch(aspect, aspects[o])) { - goto no_aspect_match; - } - } - - /* if they're all 4:3, just skip ahead and save effort */ - if (!aspectMatch(aspect, 4.0/3.0)) - aspect_guess = bestModeForAspect(config, enabled, aspect); - -no_aspect_match: - base_guess = bestModeForAspect(config, enabled, 4.0/3.0); - - guess = biggestMode(base_guess, aspect_guess); - - if (!guess) - goto out; - - /* found a mode that works everywhere, now apply it */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - modes[o] = xf86OutputFindClosestMode(config->output[o], guess); - } - ret = TRUE; - -out: - xfree(aspects); - return ret; -} - -static Bool -xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - DisplayModePtr target_mode = NULL; - Rotation target_rotation = RR_Rotate_0; - DisplayModePtr default_mode; - int default_preferred, target_preferred = 0, o; - - /* User preferred > preferred > other modes */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - default_mode = xf86DefaultMode (config->output[o], width, height); - if (!default_mode) - continue; - - default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) + - ((default_mode->type & M_T_USERPREF) != 0)); - - if (default_preferred > target_preferred || !target_mode) { - target_mode = default_mode; - target_preferred = default_preferred; - target_rotation = config->output[o]->initial_rotation; - config->compat_output = o; - } - } - - if (target_mode) - modes[config->compat_output] = target_mode; - - /* Fill in other output modes */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - if (!modes[o]) - modes[o] = xf86ClosestMode(config->output[o], target_mode, - target_rotation, width, height); - } - - return (target_mode != NULL); -} - -static Bool -xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o; - - if (xf86UserConfiguredOutputs(scrn, modes)) - return xf86TargetFallback(scrn, config, modes, enabled, width, height); - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) - if (xf86OutputHasUserPreferredMode(config->output[o])) - return - xf86TargetFallback(scrn, config, modes, enabled, width, height); - - return FALSE; -} - -static Bool -xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, - float gamma_blue) -{ - int i, size = 256; - CARD16 *red, *green, *blue; - - red = malloc(3 * size * sizeof(CARD16)); - green = red + size; - blue = green + size; - - /* Only cause warning if user wanted gamma to be set. */ - if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) { - free(red); - return FALSE; - } else if (!crtc->funcs->gamma_set) { - free(red); - return TRUE; - } - - /* At this early stage none of the randr-interface stuff is up. - * So take the default gamma size for lack of something better. - */ - for (i = 0; i < size; i++) { - if (gamma_red == 1.0) - red[i] = i << 8; - else - red[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_red) * (double)(size - 1) * 256); - - if (gamma_green == 1.0) - green[i] = i << 8; - else - green[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_green) * (double)(size - 1) * 256); - - if (gamma_blue == 1.0) - blue[i] = i << 8; - else - blue[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_blue) * (double)(size - 1) * 256); - } - - /* Default size is 256, so anything else is failure. */ - if (size != crtc->gamma_size) { - free(red); - return FALSE; - } - - crtc->gamma_size = size; - memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16)); - - /* Do not set gamma now, delay until the crtc is activated. */ - - free(red); - - return TRUE; -} - -static Bool -xf86OutputSetInitialGamma(xf86OutputPtr output) -{ - XF86ConfMonitorPtr mon = output->conf_monitor; - float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; - - if (!mon) - return TRUE; - - if (!output->crtc) - return FALSE; - - /* Get configured values, where they exist. */ - if (mon->mon_gamma_red >= GAMMA_MIN && - mon->mon_gamma_red <= GAMMA_MAX) - gamma_red = mon->mon_gamma_red; - - if (mon->mon_gamma_green >= GAMMA_MIN && - mon->mon_gamma_green <= GAMMA_MAX) - gamma_green = mon->mon_gamma_green; - - if (mon->mon_gamma_blue >= GAMMA_MIN && - mon->mon_gamma_blue <= GAMMA_MAX) - gamma_blue = mon->mon_gamma_blue; - - /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */ - if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { - xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue); - return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue); - }else - return TRUE; -} - -/** - * Construct default screen configuration - * - * Given auto-detected (and, eventually, configured) values, - * construct a usable configuration for the system - * - * canGrow indicates that the driver can resize the screen to larger than its - * initially configured size via the config->funcs->resize hook. If TRUE, this - * function will set virtualX and virtualY to match the initial configuration - * and leave config->max{Width,Height} alone. If FALSE, it will bloat - * virtual[XY] to include the largest modes and set config->max{Width,Height} - * accordingly. - */ - -Bool -xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o, c; - xf86CrtcPtr *crtcs; - DisplayModePtr *modes; - Bool *enabled; - int width, height; - int i = scrn->scrnIndex; - - /* Set up the device options */ - config->options = xnfalloc (sizeof (xf86DeviceOptions)); - memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions)); - xf86ProcessOptions (scrn->scrnIndex, - scrn->options, - config->options); - config->debug_modes = xf86ReturnOptValBool (config->options, - OPTION_MODEDEBUG, FALSE); - - if (scrn->display->virtualX) - width = scrn->display->virtualX; - else - width = config->maxWidth; - if (scrn->display->virtualY) - height = scrn->display->virtualY; - else - height = config->maxHeight; - - xf86ProbeOutputModes (scrn, width, height); - - crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); - modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); - enabled = xnfcalloc (config->num_output, sizeof (Bool)); - - xf86CollectEnabledOutputs(scrn, config, enabled); - - if (xf86TargetUserpref(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n"); - else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n"); - else if (xf86TargetAspect(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n"); - else if (xf86TargetFallback(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n"); - else - xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n"); - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - if (!modes[o]) - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output %s enabled but has no modes\n", - config->output[o]->name); - else - xf86DrvMsg (scrn->scrnIndex, X_INFO, - "Output %s using initial mode %s\n", - config->output[o]->name, modes[o]->name); - } - - /* - * Set the position of each output - */ - if (!xf86InitialOutputPositions (scrn, modes)) - { - xfree (crtcs); - xfree (modes); - return FALSE; - } - - /* - * Set initial panning of each output - */ - xf86InitialPanning (scrn); - - /* - * Assign CRTCs to fit output configuration - */ - if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height)) - { - xfree (crtcs); - xfree (modes); - return FALSE; - } - - /* XXX override xf86 common frame computation code */ - - scrn->display->frameX0 = 0; - scrn->display->frameY0 = 0; - - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->enabled = FALSE; - memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); - /* Set default gamma for all crtc's. */ - /* This is done to avoid problems later on with cloned outputs. */ - xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0); - } - - if (xf86_crtc_supports_gamma(scrn)) - xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n"); - - /* - * Set initial configuration - */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode = modes[o]; - xf86CrtcPtr crtc = crtcs[o]; - - if (mode && crtc) - { - crtc->desiredMode = *mode; - crtc->desiredRotation = output->initial_rotation; - crtc->desiredX = output->initial_x; - crtc->desiredY = output->initial_y; - crtc->desiredTransformPresent = FALSE; - crtc->enabled = TRUE; - memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec)); - memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec)); - memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16)); - output->crtc = crtc; - if (!xf86OutputSetInitialGamma(output)) - xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name); - } else { - output->crtc = NULL; - } - } - - if (scrn->display->virtualX == 0) - { - /* - * Expand virtual size to cover the current config and potential mode - * switches, if the driver can't enlarge the screen later. - */ - xf86DefaultScreenLimits (scrn, &width, &height, canGrow); - - scrn->display->virtualX = width; - scrn->display->virtualY = height; - } - - if (width > scrn->virtualX) - scrn->virtualX = width; - if (height > scrn->virtualY) - scrn->virtualY = height; - - /* - * Make sure the configuration isn't too small. - */ - if (width < config->minWidth || height < config->minHeight) - return FALSE; - - /* - * Limit the crtc config to virtual[XY] if the driver can't grow the - * desktop. - */ - if (!canGrow) - { - xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight, - width, height); - } - - /* Mirror output modes to scrn mode list */ - xf86SetScrnInfoModes (scrn); - - xfree (crtcs); - xfree (modes); - return TRUE; -} - -/* - * Check the CRTC we're going to map each output to vs. it's current - * CRTC. If they don't match, we have to disable the output and the CRTC - * since the driver will have to re-route things. - */ -static void -xf86PrepareOutputs (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = config->output[o]; -#if RANDR_GET_CRTC_INTERFACE - /* Disable outputs that are unused or will be re-routed */ - if (!output->funcs->get_crtc || - output->crtc != (*output->funcs->get_crtc)(output) || - output->crtc == NULL) -#endif - (*output->funcs->dpms)(output, DPMSModeOff); - } -} - -static void -xf86PrepareCrtcs (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c; - - for (c = 0; c < config->num_crtc; c++) { -#if RANDR_GET_CRTC_INTERFACE - xf86CrtcPtr crtc = config->crtc[c]; - xf86OutputPtr output = NULL; - uint32_t desired_outputs = 0, current_outputs = 0; - int o; - - for (o = 0; o < config->num_output; o++) { - output = config->output[o]; - if (output->crtc == crtc) - desired_outputs |= (1<funcs->get_crtc) { - desired_outputs = 0; - break; - } - if ((*output->funcs->get_crtc)(output) == crtc) - current_outputs |= (1<funcs->dpms)(crtc, DPMSModeOff); -#else - (*crtc->funcs->dpms)(crtc, DPMSModeOff); -#endif - } -} - -/* - * Using the desired mode information in each crtc, set - * modes (used in EnterVT functions, or at server startup) - */ - -Bool -xf86SetDesiredModes (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc = config->crtc[0]; - int c; - - /* A driver with this hook will take care of this */ - if (!crtc->funcs->set_mode_major) { - xf86PrepareOutputs(scrn); - xf86PrepareCrtcs(scrn); - } - - for (c = 0; c < config->num_crtc; c++) - { - xf86OutputPtr output = NULL; - int o; - RRTransformPtr transform; - - crtc = config->crtc[c]; - - /* Skip disabled CRTCs */ - if (!crtc->enabled) - continue; - - if (config->output[config->compat_output]->crtc == crtc) - output = config->output[config->compat_output]; - else - { - for (o = 0; o < config->num_output; o++) - if (config->output[o]->crtc == crtc) - { - output = config->output[o]; - break; - } - } - /* paranoia */ - if (!output) - continue; - - /* Mark that we'll need to re-set the mode for sure */ - memset(&crtc->mode, 0, sizeof(crtc->mode)); - if (!crtc->desiredMode.CrtcHDisplay) - { - DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode); - - if (!mode) - return FALSE; - crtc->desiredMode = *mode; - crtc->desiredRotation = RR_Rotate_0; - crtc->desiredTransformPresent = FALSE; - crtc->desiredX = 0; - crtc->desiredY = 0; - } - - if (crtc->desiredTransformPresent) - transform = &crtc->desiredTransform; - else - transform = NULL; - if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation, - transform, crtc->desiredX, crtc->desiredY)) - return FALSE; - } - - xf86DisableUnusedFunctions(scrn); - return TRUE; -} - -/** - * In the current world order, there are lists of modes per output, which may - * or may not include the mode that was asked to be set by XFree86's mode - * selection. Find the closest one, in the following preference order: - * - * - Equality - * - Closer in size to the requested mode, but no larger - * - Closer in refresh rate to the requested mode. - */ - -DisplayModePtr -xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired) -{ - DisplayModePtr best = NULL, scan = NULL; - - for (scan = output->probed_modes; scan != NULL; scan = scan->next) - { - /* If there's an exact match, we're done. */ - if (xf86ModesEqual(scan, desired)) { - best = desired; - break; - } - - /* Reject if it's larger than the desired mode. */ - if (scan->HDisplay > desired->HDisplay || - scan->VDisplay > desired->VDisplay) - { - continue; - } - - /* - * If we haven't picked a best mode yet, use the first - * one in the size range - */ - if (best == NULL) - { - best = scan; - continue; - } - - /* Find if it's closer to the right size than the current best - * option. - */ - if ((scan->HDisplay > best->HDisplay && - scan->VDisplay >= best->VDisplay) || - (scan->HDisplay >= best->HDisplay && - scan->VDisplay > best->VDisplay)) - { - best = scan; - continue; - } - - /* Find if it's still closer to the right refresh than the current - * best resolution. - */ - if (scan->HDisplay == best->HDisplay && - scan->VDisplay == best->VDisplay && - (fabs(scan->VRefresh - desired->VRefresh) < - fabs(best->VRefresh - desired->VRefresh))) { - best = scan; - } - } - return best; -} - -/** - * When setting a mode through XFree86-VidModeExtension or XFree86-DGA, - * take the specified mode and apply it to the crtc connected to the compat - * output. Then, find similar modes for the other outputs, as with the - * InitialConfiguration code above. The goal is to clone the desired - * mode across all outputs that are currently active. - */ - -Bool -xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - Bool ok = TRUE; - xf86OutputPtr compat_output = config->output[config->compat_output]; - DisplayModePtr compat_mode; - int c; - - /* - * Let the compat output drive the final mode selection - */ - compat_mode = xf86OutputFindClosestMode (compat_output, desired); - if (compat_mode) - desired = compat_mode; - - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - DisplayModePtr crtc_mode = NULL; - int o; - - if (!crtc->enabled) - continue; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr output_mode; - - /* skip outputs not on this crtc */ - if (output->crtc != crtc) - continue; - - if (crtc_mode) - { - output_mode = xf86OutputFindClosestMode (output, crtc_mode); - if (output_mode != crtc_mode) - output->crtc = NULL; - } - else - crtc_mode = xf86OutputFindClosestMode (output, desired); - } - if (!crtc_mode) - { - crtc->enabled = FALSE; - continue; - } - if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0)) - ok = FALSE; - else - { - crtc->desiredMode = *crtc_mode; - crtc->desiredRotation = rotation; - crtc->desiredTransformPresent = FALSE; - crtc->desiredX = 0; - crtc->desiredY = 0; - } - } - xf86DisableUnusedFunctions(pScrn); -#ifdef RANDR_12_INTERFACE - xf86RandR12TellChanged (pScrn->pScreen); -#endif - return ok; -} - - -/** - * Set the DPMS power mode of all outputs and CRTCs. - * - * If the new mode is off, it will turn off outputs and then CRTCs. - * Otherwise, it will affect CRTCs before outputs. - */ -void -xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int i; - - if (!scrn->vtSema) - return; - - if (mode == DPMSModeOff) { - for (i = 0; i < config->num_output; i++) { - xf86OutputPtr output = config->output[i]; - if (output->crtc != NULL) - (*output->funcs->dpms) (output, mode); - } - } - - for (i = 0; i < config->num_crtc; i++) { - xf86CrtcPtr crtc = config->crtc[i]; - if (crtc->enabled) - (*crtc->funcs->dpms) (crtc, mode); - } - - if (mode != DPMSModeOff) { - for (i = 0; i < config->num_output; i++) { - xf86OutputPtr output = config->output[i]; - if (output->crtc != NULL) - (*output->funcs->dpms) (output, mode); - } - } -} - -/** - * Implement the screensaver by just calling down into the driver DPMS hooks. - * - * Even for monitors with no DPMS support, by the definition of our DPMS hooks, - * the outputs will still get disabled (blanked). - */ -Bool -xf86SaveScreen(ScreenPtr pScreen, int mode) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if (xf86IsUnblank(mode)) - xf86DPMSSet(pScrn, DPMSModeOn, 0); - else - xf86DPMSSet(pScrn, DPMSModeOff, 0); - - return TRUE; -} - -/** - * Disable all inactive crtcs and outputs - */ -void -xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int o, c; - - for (o = 0; o < xf86_config->num_output; o++) - { - xf86OutputPtr output = xf86_config->output[o]; - if (!output->crtc) - (*output->funcs->dpms)(output, DPMSModeOff); - } - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - if (!crtc->enabled) - { - crtc->funcs->dpms(crtc, DPMSModeOff); - memset(&crtc->mode, 0, sizeof(crtc->mode)); - xf86RotateDestroy(crtc); - crtc->active = FALSE; - } - } - if (pScrn->pScreen) - xf86_crtc_notify(pScrn->pScreen); -} - -#ifdef RANDR_12_INTERFACE - -#define EDID_ATOM_NAME "EDID" - -/** - * Set the RandR EDID property - */ -static void -xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) -{ - Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE); - - /* This may get called before the RandR resources have been created */ - if (output->randr_output == NULL) - return; - - if (data_len != 0) { - RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, - PropModeReplace, data_len, data, FALSE, TRUE); - } else { - RRDeleteOutputProperty(output->randr_output, edid_atom); - } -} - -#endif - -/* Pull out a phyiscal size from a detailed timing if available. */ -struct det_phySize_parameter { - xf86OutputPtr output; - ddc_quirk_t quirks; - Bool ret; -}; - -static void handle_detailed_physical_size(struct detailed_monitor_section - *det_mon, void *data) -{ - struct det_phySize_parameter *p; - p = (struct det_phySize_parameter *)data; - - if (p->ret == TRUE ) - return ; - - xf86DetTimingApplyQuirks(det_mon, p->quirks, - p->output->MonInfo->features.hsize, - p->output->MonInfo->features.vsize); - if (det_mon->type == DT && - det_mon->section.d_timings.h_size != 0 && - det_mon->section.d_timings.v_size != 0) { - - p->output->mm_width = det_mon->section.d_timings.h_size; - p->output->mm_height = det_mon->section.d_timings.v_size; - p->ret = TRUE; - } -} - -/** - * Set the EDID information for the specified output - */ -void -xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) -{ - ScrnInfoPtr scrn = output->scrn; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - Bool debug_modes = config->debug_modes || xf86Initialising; -#ifdef RANDR_12_INTERFACE - int size; -#endif - - if (output->MonInfo != NULL) - xfree(output->MonInfo); - - output->MonInfo = edid_mon; - - if (debug_modes) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", - output->name); - xf86PrintEDID(edid_mon); - } - - /* Set the DDC properties for the 'compat' output */ - if (output == config->output[config->compat_output]) - xf86SetDDCproperties(scrn, edid_mon); - -#ifdef RANDR_12_INTERFACE - /* Set the RandR output properties */ - size = 0; - if (edid_mon) - { - if (edid_mon->ver.version == 1) { - size = 128; - if (edid_mon->flags & EDID_COMPLETE_RAWDATA) - size += edid_mon->no_sections * 128; - } else if (edid_mon->ver.version == 2) - size = 256; - } - xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); -#endif - - if (edid_mon) { - - struct det_phySize_parameter p; - p.output = output; - p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE); - p.ret = FALSE; - xf86ForEachDetailedBlock(edid_mon, - handle_detailed_physical_size, &p); - - /* if no mm size is available from a detailed timing, check the max size field */ - if ((!output->mm_width || !output->mm_height) && - (edid_mon->features.hsize && edid_mon->features.vsize)) - { - output->mm_width = edid_mon->features.hsize * 10; - output->mm_height = edid_mon->features.vsize * 10; - } - } -} - -/** - * Return the list of modes supported by the EDID information - * stored in 'output' - */ -DisplayModePtr -xf86OutputGetEDIDModes (xf86OutputPtr output) -{ - ScrnInfoPtr scrn = output->scrn; - xf86MonPtr edid_mon = output->MonInfo; - - if (!edid_mon) - return NULL; - return xf86DDCGetModes(scrn->scrnIndex, edid_mon); -} - -/* maybe we should care about DDC1? meh. */ -xf86MonPtr -xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) -{ - ScrnInfoPtr scrn = output->scrn; - xf86MonPtr mon; - - mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE); - if (mon) - xf86DDCApplyQuirks(scrn->scrnIndex, mon); - - return mon; -} - -static char *_xf86ConnectorNames[] = { - "None", "VGA", "DVI-I", "DVI-D", - "DVI-A", "Composite", "S-Video", - "Component", "LFP", "Proprietary", - "HDMI", "DisplayPort", - }; -char * -xf86ConnectorGetName(xf86ConnectorType connector) -{ - return _xf86ConnectorNames[connector]; -} - -static void -x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) -{ - dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; - dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; - dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; - dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; - - if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) - dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; -} - -static void -x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) -{ - if (crtc->enabled) { - crtc_box->x1 = crtc->x; - crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); - crtc_box->y1 = crtc->y; - crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); - } else - crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; -} - -static int -xf86_crtc_box_area(BoxPtr box) -{ - return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); -} - -/* - * Return the crtc covering 'box'. If two crtcs cover a portion of - * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc - * with greater coverage - */ - -static xf86CrtcPtr -xf86_covering_crtc(ScrnInfoPtr pScrn, - BoxPtr box, - xf86CrtcPtr desired, - BoxPtr crtc_box_ret) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc, best_crtc; - int coverage, best_coverage; - int c; - BoxRec crtc_box, cover_box; - - best_crtc = NULL; - best_coverage = 0; - crtc_box_ret->x1 = 0; - crtc_box_ret->x2 = 0; - crtc_box_ret->y1 = 0; - crtc_box_ret->y2 = 0; - for (c = 0; c < xf86_config->num_crtc; c++) { - crtc = xf86_config->crtc[c]; - x86_crtc_box(crtc, &crtc_box); - x86_crtc_box_intersect(&cover_box, &crtc_box, box); - coverage = xf86_crtc_box_area(&cover_box); - if (coverage && crtc == desired) { - *crtc_box_ret = crtc_box; - return crtc; - } else if (coverage > best_coverage) { - *crtc_box_ret = crtc_box; - best_crtc = crtc; - best_coverage = coverage; - } - } - return best_crtc; -} - -/* - * For overlay video, compute the relevant CRTC and - * clip video to that. - * - * returning FALSE means there was a memory failure of some kind, - * not that the video shouldn't be displayed - */ - -Bool -xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, - xf86CrtcPtr *crtc_ret, - xf86CrtcPtr desired_crtc, - BoxPtr dst, - INT32 *xa, - INT32 *xb, - INT32 *ya, - INT32 *yb, - RegionPtr reg, - INT32 width, - INT32 height) -{ - Bool ret; - RegionRec crtc_region_local; - RegionPtr crtc_region = reg; - - if (crtc_ret) { - BoxRec crtc_box; - xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst, - desired_crtc, - &crtc_box); - - if (crtc) { - REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1); - crtc_region = &crtc_region_local; - REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg); - } - *crtc_ret = crtc; - } - - ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, - crtc_region, width, height); - - if (crtc_region != reg) - REGION_UNINIT (pScreen, &crtc_region_local); - - return ret; -} - -xf86_crtc_notify_proc_ptr -xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new) -{ - if (xf86CrtcConfigPrivateIndex != -1) - { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86_crtc_notify_proc_ptr old; - - old = config->xf86_crtc_notify; - config->xf86_crtc_notify = new; - return old; - } - return NULL; -} - -void -xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old) -{ - if (xf86CrtcConfigPrivateIndex != -1) - { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - config->xf86_crtc_notify = old; - } -} - -void -xf86_crtc_notify(ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - if (config->xf86_crtc_notify) - config->xf86_crtc_notify(screen); -} - -Bool -xf86_crtc_supports_gamma(ScrnInfoPtr pScrn) -{ - if (xf86CrtcConfigPrivateIndex != -1) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc; - - /* for multiple drivers loaded we need this */ - if (!xf86_config) - return FALSE; - if (xf86_config->num_crtc == 0) - return FALSE; - crtc = xf86_config->crtc[0]; - - return (crtc->funcs->gamma_set != NULL); - } - - return FALSE; -} +/* + * Copyright © 2006 Keith Packard + * Copyright © 2008 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#else +#ifdef HAVE_CONFIG_H +#include +#endif +#endif + +#include +#include +#include + +#include "xf86.h" +#include "xf86DDC.h" +#include "xf86Crtc.h" +#include "xf86Modes.h" +#include "xf86Priv.h" +#include "xf86RandR12.h" +#include "X11/extensions/render.h" +#include "X11/extensions/dpmsconst.h" +#include "X11/Xatom.h" +#ifdef RENDER +#include "picturestr.h" +#endif + +#include "xf86xv.h" + +/* + * Initialize xf86CrtcConfig structure + */ + +int xf86CrtcConfigPrivateIndex = -1; + +void +xf86CrtcConfigInit (ScrnInfoPtr scrn, + const xf86CrtcConfigFuncsRec *funcs) +{ + xf86CrtcConfigPtr config; + + if (xf86CrtcConfigPrivateIndex == -1) + xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); + + config->funcs = funcs; + + scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; +} + +void +xf86CrtcSetSizeRange (ScrnInfoPtr scrn, + int minWidth, int minHeight, + int maxWidth, int maxHeight) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + config->minWidth = minWidth; + config->minHeight = minHeight; + config->maxWidth = maxWidth; + config->maxHeight = maxHeight; +} + +/* + * Crtc functions + */ +xf86CrtcPtr +xf86CrtcCreate (ScrnInfoPtr scrn, + const xf86CrtcFuncsRec *funcs) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc, *crtcs; + + crtc = xcalloc (sizeof (xf86CrtcRec), 1); + if (!crtc) + return NULL; + crtc->version = XF86_CRTC_VERSION; + crtc->scrn = scrn; + crtc->funcs = funcs; +#ifdef RANDR_12_INTERFACE + crtc->randr_crtc = NULL; +#endif + crtc->rotation = RR_Rotate_0; + crtc->desiredRotation = RR_Rotate_0; + pixman_transform_init_identity (&crtc->crtc_to_framebuffer); + pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); + pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); + crtc->filter = NULL; + crtc->params = NULL; + crtc->nparams = 0; + crtc->filter_width = 0; + crtc->filter_height = 0; + crtc->transform_in_use = FALSE; + crtc->transformPresent = FALSE; + crtc->desiredTransformPresent = FALSE; + memset (&crtc->bounds, '\0', sizeof (crtc->bounds)); + + /* Preallocate gamma at a sensible size. */ + crtc->gamma_size = 256; + crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16)); + if (!crtc->gamma_red) { + xfree (crtc); + return NULL; + } + crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; + crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; + + if (xf86_config->crtc) + crtcs = xrealloc (xf86_config->crtc, + (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + else + crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + if (!crtcs) + { + xfree (crtc); + return NULL; + } + xf86_config->crtc = crtcs; + xf86_config->crtc[xf86_config->num_crtc++] = crtc; + return crtc; +} + +void +xf86CrtcDestroy (xf86CrtcPtr crtc) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + int c; + + (*crtc->funcs->destroy) (crtc); + for (c = 0; c < xf86_config->num_crtc; c++) + if (xf86_config->crtc[c] == crtc) + { + memmove (&xf86_config->crtc[c], + &xf86_config->crtc[c+1], + ((xf86_config->num_crtc - (c + 1)) * sizeof(void*))); + xf86_config->num_crtc--; + break; + } + if (crtc->params) + xfree (crtc->params); + free(crtc->gamma_red); + xfree (crtc); +} + + +/** + * Return whether any outputs are connected to the specified pipe + */ + +Bool +xf86CrtcInUse (xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int o; + + for (o = 0; o < xf86_config->num_output; o++) + if (xf86_config->output[o]->crtc == crtc) + return TRUE; + return FALSE; +} + +void +xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen) +{ +#ifdef RENDER + int subpixel_order = SubPixelUnknown; + Bool has_none = FALSE; + ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int c, o; + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + for (o = 0; o < xf86_config->num_output; o++) + { + xf86OutputPtr output = xf86_config->output[o]; + + if (output->crtc == crtc) + { + switch (output->subpixel_order) { + case SubPixelNone: + has_none = TRUE; + break; + case SubPixelUnknown: + break; + default: + subpixel_order = output->subpixel_order; + break; + } + } + if (subpixel_order != SubPixelUnknown) + break; + } + if (subpixel_order != SubPixelUnknown) + { + static const int circle[4] = { + SubPixelHorizontalRGB, + SubPixelVerticalRGB, + SubPixelHorizontalBGR, + SubPixelVerticalBGR, + }; + int rotate; + int c; + for (rotate = 0; rotate < 4; rotate++) + if (crtc->rotation & (1 << rotate)) + break; + for (c = 0; c < 4; c++) + if (circle[c] == subpixel_order) + break; + c = (c + rotate) & 0x3; + if ((crtc->rotation & RR_Reflect_X) && !(c & 1)) + c ^= 2; + if ((crtc->rotation & RR_Reflect_Y) && (c & 1)) + c ^= 2; + subpixel_order = circle[c]; + break; + } + } + if (subpixel_order == SubPixelUnknown && has_none) + subpixel_order = SubPixelNone; + PictureSetSubpixelOrder (pScreen, subpixel_order); +#endif +} + +/** + * Sets the given video mode on the given crtc + */ +Bool +xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + RRTransformPtr transform, int x, int y) +{ + ScrnInfoPtr scrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int i; + Bool ret = FALSE; + Bool didLock = FALSE; + DisplayModePtr adjusted_mode; + DisplayModeRec saved_mode; + int saved_x, saved_y; + Rotation saved_rotation; + RRTransformRec saved_transform; + Bool saved_transform_present; + + crtc->enabled = xf86CrtcInUse (crtc); + + /* We only hit this if someone explicitly sends a "disabled" modeset. */ + if (!crtc->enabled) + { + /* Check everything for stuff that should be off. */ + xf86DisableUnusedFunctions(scrn); + return TRUE; + } + + adjusted_mode = xf86DuplicateMode(mode); + + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + saved_rotation = crtc->rotation; + if (crtc->transformPresent) { + RRTransformInit (&saved_transform); + RRTransformCopy (&saved_transform, &crtc->transform); + } + saved_transform_present = crtc->transformPresent; + + /* Update crtc values up front so the driver can rely on them for mode + * setting. + */ + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + crtc->rotation = rotation; + if (transform) { + RRTransformCopy (&crtc->transform, transform); + crtc->transformPresent = TRUE; + } else + crtc->transformPresent = FALSE; + + if (crtc->funcs->set_mode_major) { + ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y); + goto done; + } + + didLock = crtc->funcs->lock (crtc); + /* Pass our mode to the outputs and the CRTC to give them a chance to + * adjust it according to limitations or output properties, and also + * a chance to reject the mode entirely. + */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { + goto done; + } + } + + if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { + goto done; + } + + if (!xf86CrtcRotate (crtc)) + goto done; + + /* Prepare the outputs and CRTCs before setting the mode. */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + /* Disable the output as the first thing we do. */ + output->funcs->prepare(output); + } + + crtc->funcs->prepare(crtc); + + /* Set up the DPLL and any output state that needs to adjust or depend + * on the DPLL. + */ + crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y); + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc) + output->funcs->mode_set(output, mode, adjusted_mode); + } + + /* Only upload when needed, to avoid unneeded delays. */ + if (!crtc->active && crtc->funcs->gamma_set) + crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, + crtc->gamma_blue, crtc->gamma_size); + + /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ + crtc->funcs->commit(crtc); + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc) + output->funcs->commit(output); + } + + ret = TRUE; + +done: + if (ret) { + crtc->active = TRUE; + if (scrn->pScreen) + xf86CrtcSetScreenSubpixelOrder (scrn->pScreen); + } else { + crtc->x = saved_x; + crtc->y = saved_y; + crtc->rotation = saved_rotation; + crtc->mode = saved_mode; + if (saved_transform_present) + RRTransformCopy (&crtc->transform, &saved_transform); + crtc->transformPresent = saved_transform_present; + } + + if (adjusted_mode->name) + xfree(adjusted_mode->name); + xfree(adjusted_mode); + + if (didLock) + crtc->funcs->unlock (crtc); + + return ret; +} + +/** + * Sets the given video mode on the given crtc, but without providing + * a transform + */ +Bool +xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + int x, int y) +{ + return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y); +} + +/** + * Pans the screen, does not change the mode + */ +void +xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y) +{ + crtc->x = x; + crtc->y = y; + if (crtc->funcs->set_origin) { + if (!xf86CrtcRotate (crtc)) + return; + crtc->funcs->set_origin (crtc, x, y); + } + else + xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y); +} + +/* + * Output functions + */ + +extern XF86ConfigPtr xf86configptr; + +typedef enum { + OPTION_PREFERRED_MODE, + OPTION_POSITION, + OPTION_BELOW, + OPTION_RIGHT_OF, + OPTION_ABOVE, + OPTION_LEFT_OF, + OPTION_ENABLE, + OPTION_DISABLE, + OPTION_MIN_CLOCK, + OPTION_MAX_CLOCK, + OPTION_IGNORE, + OPTION_ROTATE, + OPTION_PANNING, + OPTION_PRIMARY, +} OutputOpts; + +static OptionInfoRec xf86OutputOptions[] = { + {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, + {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, + {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, + {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, + {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, + {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, + {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, + {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE }, + {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE }, + {-1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +enum { + OPTION_MODEDEBUG, +}; + +static OptionInfoRec xf86DeviceOptions[] = { + {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE }, + {-1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +static void +xf86OutputSetMonitor (xf86OutputPtr output) +{ + char *option_name; + static const char monitor_prefix[] = "monitor-"; + char *monitor; + + if (!output->name) + return; + + if (output->options) + xfree (output->options); + + output->options = xnfalloc (sizeof (xf86OutputOptions)); + memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); + + option_name = xnfalloc (strlen (monitor_prefix) + + strlen (output->name) + 1); + strcpy (option_name, monitor_prefix); + strcat (option_name, output->name); + monitor = xf86findOptionValue (output->scrn->options, option_name); + if (!monitor) + monitor = output->name; + else + xf86MarkOptionUsedByName (output->scrn->options, option_name); + xfree (option_name); + output->conf_monitor = xf86findMonitor (monitor, + xf86configptr->conf_monitor_lst); + /* + * Find the monitor section of the screen and use that + */ + if (!output->conf_monitor && output->use_screen_monitor) + output->conf_monitor = xf86findMonitor (output->scrn->monitor->id, + xf86configptr->conf_monitor_lst); + if (output->conf_monitor) + { + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s using monitor section %s\n", + output->name, output->conf_monitor->mon_identifier); + xf86ProcessOptions (output->scrn->scrnIndex, + output->conf_monitor->mon_option_lst, + output->options); + } + else + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s has no monitor section\n", + output->name); +} + +static Bool +xf86OutputEnabled (xf86OutputPtr output, Bool strict) +{ + Bool enable, disable; + + /* check to see if this output was enabled in the config file */ + if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable) + { + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s enabled by config file\n", output->name); + return TRUE; + } + /* or if this output was disabled in the config file */ + if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable) + { + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s disabled by config file\n", output->name); + return FALSE; + } + + /* If not, try to only light up the ones we know are connected */ + if (strict) { + enable = output->status == XF86OutputStatusConnected; + } + /* But if that fails, try to light up even outputs we're unsure of */ + else { + enable = output->status != XF86OutputStatusDisconnected; + } + + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s %sconnected\n", output->name, enable ? "" : "dis"); + return enable; +} + +static Bool +xf86OutputIgnored (xf86OutputPtr output) +{ + return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE); +} + +static char *direction[4] = { + "normal", + "left", + "inverted", + "right" +}; + +static Rotation +xf86OutputInitialRotation (xf86OutputPtr output) +{ + char *rotate_name = xf86GetOptValString (output->options, + OPTION_ROTATE); + int i; + + if (!rotate_name) + return RR_Rotate_0; + + for (i = 0; i < 4; i++) + if (xf86nameCompare (direction[i], rotate_name) == 0) + return (1 << i); + return RR_Rotate_0; +} + +xf86OutputPtr +xf86OutputCreate (ScrnInfoPtr scrn, + const xf86OutputFuncsRec *funcs, + const char *name) +{ + xf86OutputPtr output, *outputs; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int len; + Bool primary; + + if (name) + len = strlen (name) + 1; + else + len = 0; + + output = xcalloc (sizeof (xf86OutputRec) + len, 1); + if (!output) + return NULL; + output->scrn = scrn; + output->funcs = funcs; + if (name) + { + output->name = (char *) (output + 1); + strcpy (output->name, name); + } + output->subpixel_order = SubPixelUnknown; + /* + * Use the old per-screen monitor section for the first output + */ + output->use_screen_monitor = (xf86_config->num_output == 0); +#ifdef RANDR_12_INTERFACE + output->randr_output = NULL; +#endif + if (name) + { + xf86OutputSetMonitor (output); + if (xf86OutputIgnored (output)) + { + xfree (output); + return FALSE; + } + } + + + if (xf86_config->output) + outputs = xrealloc (xf86_config->output, + (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + else + outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + if (!outputs) + { + xfree (output); + return NULL; + } + + xf86_config->output = outputs; + + if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary) + { + memmove(xf86_config->output + 1, xf86_config->output, + xf86_config->num_output * sizeof (xf86OutputPtr)); + xf86_config->output[0] = output; + } + else + { + xf86_config->output[xf86_config->num_output] = output; + } + + xf86_config->num_output++; + + return output; +} + +Bool +xf86OutputRename (xf86OutputPtr output, const char *name) +{ + int len = strlen(name) + 1; + char *newname = xalloc (len); + + if (!newname) + return FALSE; /* so sorry... */ + + strcpy (newname, name); + if (output->name && output->name != (char *) (output + 1)) + xfree (output->name); + output->name = newname; + xf86OutputSetMonitor (output); + if (xf86OutputIgnored (output)) + return FALSE; + return TRUE; +} + +void +xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor) +{ + if (use_screen_monitor != output->use_screen_monitor) + { + output->use_screen_monitor = use_screen_monitor; + xf86OutputSetMonitor (output); + } +} + +void +xf86OutputDestroy (xf86OutputPtr output) +{ + ScrnInfoPtr scrn = output->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + (*output->funcs->destroy) (output); + while (output->probed_modes) + xf86DeleteMode (&output->probed_modes, output->probed_modes); + for (o = 0; o < xf86_config->num_output; o++) + if (xf86_config->output[o] == output) + { + memmove (&xf86_config->output[o], + &xf86_config->output[o+1], + ((xf86_config->num_output - (o + 1)) * sizeof(void*))); + xf86_config->num_output--; + break; + } + if (output->name && output->name != (char *) (output + 1)) + xfree (output->name); + xfree (output); +} + +/* + * Called during CreateScreenResources to hook up RandR + */ +static Bool +xf86CrtcCreateScreenResources (ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + screen->CreateScreenResources = config->CreateScreenResources; + + if (!(*screen->CreateScreenResources)(screen)) + return FALSE; + + if (!xf86RandR12CreateScreenResources (screen)) + return FALSE; + + return TRUE; +} + +/* + * Clean up config on server reset + */ +static Bool +xf86CrtcCloseScreen (int index, ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o, c; + + screen->CloseScreen = config->CloseScreen; + + xf86RotateCloseScreen (screen); + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->randr_output = NULL; + } + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->randr_crtc = NULL; + } + return screen->CloseScreen (index, screen); +} + +/* + * Called at ScreenInit time to set up + */ +#ifdef RANDR_13_INTERFACE +int +#else +Bool +#endif +xf86CrtcScreenInit (ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + /* Rotation */ + xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n"); + xf86DisableRandR(); /* Disable old RandR extension support */ + xf86RandR12Init (screen); + + /* support all rotations if every crtc has the shadow alloc funcs */ + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create) + break; + } + if (c == config->num_crtc) + { + xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 | + RR_Rotate_180 | RR_Rotate_270 | + RR_Reflect_X | RR_Reflect_Y); + xf86RandR12SetTransformSupport (screen, TRUE); + } + else + { + xf86RandR12SetRotations (screen, RR_Rotate_0); + xf86RandR12SetTransformSupport (screen, FALSE); + } + + /* Wrap CreateScreenResources so we can initialize the RandR code */ + config->CreateScreenResources = screen->CreateScreenResources; + screen->CreateScreenResources = xf86CrtcCreateScreenResources; + + config->CloseScreen = screen->CloseScreen; + screen->CloseScreen = xf86CrtcCloseScreen; + +#ifdef XFreeXDGA + _xf86_di_dga_init_internal(screen); +#endif +#ifdef RANDR_13_INTERFACE + return RANDR_INTERFACE_VERSION; +#else + return TRUE; +#endif +} + +static DisplayModePtr +xf86DefaultMode (xf86OutputPtr output, int width, int height) +{ + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + int target_preferred = 0; + int mm_height; + + mm_height = output->mm_height; + if (!mm_height) + mm_height = (768 * 25.4) / DEFAULT_DPI; + /* + * Pick a mode closest to DEFAULT_DPI + */ + for (mode = output->probed_modes; mode; mode = mode->next) + { + int dpi; + int preferred = (((mode->type & M_T_PREFERRED) != 0) + + ((mode->type & M_T_USERPREF) != 0)); + int diff; + + if (xf86ModeWidth (mode, output->initial_rotation) > width || + xf86ModeHeight (mode, output->initial_rotation) > height) + continue; + + /* yes, use VDisplay here, not xf86ModeHeight */ + dpi = (mode->VDisplay * 254) / (mm_height * 10); + diff = dpi - DEFAULT_DPI; + diff = diff < 0 ? -diff : diff; + if (target_mode == NULL || (preferred > target_preferred) || + (preferred == target_preferred && diff < target_diff)) + { + target_mode = mode; + target_diff = diff; + target_preferred = preferred; + } + } + return target_mode; +} + +static DisplayModePtr +xf86ClosestMode (xf86OutputPtr output, + DisplayModePtr match, Rotation match_rotation, + int width, int height) +{ + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + + /* + * Pick a mode closest to the specified mode + */ + for (mode = output->probed_modes; mode; mode = mode->next) + { + int dx, dy; + int diff; + + if (xf86ModeWidth (mode, output->initial_rotation) > width || + xf86ModeHeight (mode, output->initial_rotation) > height) + continue; + + /* exact matches are preferred */ + if (output->initial_rotation == match_rotation && + xf86ModesEqual (mode, match)) + return mode; + + dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation); + dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation); + diff = dx * dx + dy * dy; + if (target_mode == NULL || diff < target_diff) + { + target_mode = mode; + target_diff = diff; + } + } + return target_mode; +} + +static DisplayModePtr +xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height) +{ + DisplayModePtr mode; + + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (xf86ModeWidth (mode, output->initial_rotation) > width || + xf86ModeHeight (mode, output->initial_rotation) > height) + continue; + + if (mode->type & M_T_PREFERRED) + return mode; + } + return NULL; +} + +static DisplayModePtr +xf86OutputHasUserPreferredMode (xf86OutputPtr output) +{ + DisplayModePtr mode, first = output->probed_modes; + + for (mode = first; mode && mode->next != first; mode = mode->next) + if (mode->type & M_T_USERPREF) + return mode; + + return NULL; +} + +static int +xf86PickCrtcs (ScrnInfoPtr scrn, + xf86CrtcPtr *best_crtcs, + DisplayModePtr *modes, + int n, + int width, + int height) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c, o; + xf86OutputPtr output; + xf86CrtcPtr crtc; + xf86CrtcPtr *crtcs; + xf86CrtcPtr best_crtc; + int best_score; + int score; + int my_score; + + if (n == config->num_output) + return 0; + output = config->output[n]; + + /* + * Compute score with this output disabled + */ + best_crtcs[n] = NULL; + best_crtc = NULL; + best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height); + if (modes[n] == NULL) + return best_score; + + crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr)); + if (!crtcs) + return best_score; + + my_score = 1; + /* Score outputs that are known to be connected higher */ + if (output->status == XF86OutputStatusConnected) + my_score++; + /* Score outputs with preferred modes higher */ + if (xf86OutputHasPreferredMode (output, width, height)) + my_score++; + /* + * Select a crtc for this output and + * then attempt to configure the remaining + * outputs + */ + for (c = 0; c < config->num_crtc; c++) + { + if ((output->possible_crtcs & (1 << c)) == 0) + continue; + + crtc = config->crtc[c]; + /* + * Check to see if some other output is + * using this crtc + */ + for (o = 0; o < n; o++) + if (best_crtcs[o] == crtc) + break; + if (o < n) + { + /* + * If the two outputs desire the same mode, + * see if they can be cloned + */ + if (xf86ModesEqual (modes[o], modes[n]) && + config->output[o]->initial_rotation == config->output[n]->initial_rotation && + config->output[o]->initial_x == config->output[n]->initial_x && + config->output[o]->initial_y == config->output[n]->initial_y) + { + if ((output->possible_clones & (1 << o)) == 0) + continue; /* nope, try next CRTC */ + } + else + continue; /* different modes, can't clone */ + } + crtcs[n] = crtc; + memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); + score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height); + if (score > best_score) + { + best_crtc = crtc; + best_score = score; + memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); + } + } + xfree (crtcs); + return best_score; +} + + +/* + * Compute the virtual size necessary to place all of the available + * crtcs in the specified configuration. + * + * canGrow indicates that the driver can make the screen larger than its initial + * configuration. If FALSE, this function will enlarge the screen to include + * the largest available mode. + */ + +static void +xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp, + Bool canGrow) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int width = 0, height = 0; + int o; + int c; + int s; + + for (c = 0; c < config->num_crtc; c++) + { + int crtc_width = 0, crtc_height = 0; + xf86CrtcPtr crtc = config->crtc[c]; + + if (crtc->enabled) + { + crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation); + crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation); + } + if (!canGrow) { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + for (s = 0; s < config->num_crtc; s++) + if (output->possible_crtcs & (1 << s)) + { + DisplayModePtr mode; + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (mode->HDisplay > crtc_width) + crtc_width = mode->HDisplay; + if (mode->VDisplay > crtc_width) + crtc_width = mode->VDisplay; + if (mode->VDisplay > crtc_height) + crtc_height = mode->VDisplay; + if (mode->HDisplay > crtc_height) + crtc_height = mode->HDisplay; + } + } + } + } + if (crtc_width > width) + width = crtc_width; + if (crtc_height > height) + height = crtc_height; + } + if (config->maxWidth && width > config->maxWidth) width = config->maxWidth; + if (config->maxHeight && height > config->maxHeight) height = config->maxHeight; + if (config->minWidth && width < config->minWidth) width = config->minWidth; + if (config->minHeight && height < config->minHeight) height = config->minHeight; + *widthp = width; + *heightp = height; +} + +#define POSITION_UNSET -100000 + +/* + * check if the user configured any outputs at all + * with either a position or a relative setting or a mode. + */ +static Bool +xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + Bool user_conf = FALSE; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + char *position; + char *relative_name; + OutputOpts relation; + int r; + static const OutputOpts relations[] = { + OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF + }; + + position = xf86GetOptValString (output->options, + OPTION_POSITION); + if (position) + user_conf = TRUE; + + relation = 0; + relative_name = NULL; + for (r = 0; r < 4; r++) + { + relation = relations[r]; + relative_name = xf86GetOptValString (output->options, + relation); + if (relative_name) + break; + } + if (relative_name) + user_conf = TRUE; + + modes[o] = xf86OutputHasUserPreferredMode(output); + if (modes[o]) + user_conf = TRUE; + } + + return user_conf; +} + +static Bool +xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + int min_x, min_y; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x = output->initial_y = POSITION_UNSET; + } + + /* + * Loop until all outputs are set + */ + for (;;) + { + Bool any_set = FALSE; + Bool keep_going = FALSE; + + for (o = 0; o < config->num_output; o++) + { + static const OutputOpts relations[] = { + OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF + }; + xf86OutputPtr output = config->output[o]; + xf86OutputPtr relative; + char *relative_name; + char *position; + OutputOpts relation; + int r; + + if (output->initial_x != POSITION_UNSET) + continue; + position = xf86GetOptValString (output->options, + OPTION_POSITION); + /* + * Absolute position wins + */ + if (position) + { + int x, y; + if (sscanf (position, "%d %d", &x, &y) == 2) + { + output->initial_x = x; + output->initial_y = y; + } + else + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Output %s position not of form \"x y\"\n", + output->name); + output->initial_x = output->initial_y = 0; + } + any_set = TRUE; + continue; + } + /* + * Next comes relative positions + */ + relation = 0; + relative_name = NULL; + for (r = 0; r < 4; r++) + { + relation = relations[r]; + relative_name = xf86GetOptValString (output->options, + relation); + if (relative_name) + break; + } + if (relative_name) + { + int or; + relative = NULL; + for (or = 0; or < config->num_output; or++) + { + xf86OutputPtr out_rel = config->output[or]; + XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; + + if (rel_mon) + { + if (xf86nameCompare (rel_mon->mon_identifier, + relative_name) == 0) + { + relative = config->output[or]; + break; + } + } + if (strcmp (out_rel->name, relative_name) == 0) + { + relative = config->output[or]; + break; + } + } + if (!relative) + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Cannot position output %s relative to unknown output %s\n", + output->name, relative_name); + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + continue; + } + if (!modes[or]) + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Cannot position output %s relative to output %s without modes\n", + output->name, relative_name); + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + continue; + } + if (relative->initial_x == POSITION_UNSET) + { + keep_going = TRUE; + continue; + } + output->initial_x = relative->initial_x; + output->initial_y = relative->initial_y; + switch (relation) { + case OPTION_BELOW: + output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation); + break; + case OPTION_RIGHT_OF: + output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation); + break; + case OPTION_ABOVE: + if (modes[o]) + output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation); + break; + case OPTION_LEFT_OF: + if (modes[o]) + output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation); + break; + default: + break; + } + any_set = TRUE; + continue; + } + + /* Nothing set, just stick them at 0,0 */ + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + } + if (!keep_going) + break; + if (!any_set) + { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + if (output->initial_x == POSITION_UNSET) + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Output position loop. Moving %s to 0,0\n", + output->name); + output->initial_x = output->initial_y = 0; + break; + } + } + } + } + + /* + * normalize positions + */ + min_x = 1000000; + min_y = 1000000; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + if (output->initial_x < min_x) + min_x = output->initial_x; + if (output->initial_y < min_y) + min_y = output->initial_y; + } + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x -= min_x; + output->initial_y -= min_y; + } + return TRUE; +} + +static void +xf86InitialPanning (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + char *panning = xf86GetOptValString (output->options, OPTION_PANNING); + int width, height, left, top; + int track_width, track_height, track_left, track_top; + int brdr[4]; + + memset (&output->initialTotalArea, 0, sizeof(BoxRec)); + memset (&output->initialTrackingArea, 0, sizeof(BoxRec)); + memset (output->initialBorder, 0, 4*sizeof(INT16)); + + if (! panning) + continue; + + switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", + &width, &height, &left, &top, + &track_width, &track_height, &track_left, &track_top, + &brdr[0], &brdr[1], &brdr[2], &brdr[3])) { + case 12: + output->initialBorder[0] = brdr[0]; + output->initialBorder[1] = brdr[1]; + output->initialBorder[2] = brdr[2]; + output->initialBorder[3] = brdr[3]; + /* fall through */ + case 8: + output->initialTrackingArea.x1 = track_left; + output->initialTrackingArea.y1 = track_top; + output->initialTrackingArea.x2 = track_left + track_width; + output->initialTrackingArea.y2 = track_top + track_height; + /* fall through */ + case 4: + output->initialTotalArea.x1 = left; + output->initialTotalArea.y1 = top; + /* fall through */ + case 2: + output->initialTotalArea.x2 = output->initialTotalArea.x1 + width; + output->initialTotalArea.y2 = output->initialTotalArea.y1 + height; + break; + default: + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Broken panning specification '%s' for output %s in config file\n", + panning, output->name); + } + } +} + +/** Return - 0 + if a should be earlier, same or later than b in list + */ +static int +xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) +{ + int diff; + + diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); + if (diff) + return diff; + diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; + if (diff) + return diff; + diff = b->Clock - a->Clock; + return diff; +} + +/** + * Insertion sort input in-place and return the resulting head + */ +static DisplayModePtr +xf86SortModes (DisplayModePtr input) +{ + DisplayModePtr output = NULL, i, o, n, *op, prev; + + /* sort by preferred status and pixel area */ + while (input) + { + i = input; + input = input->next; + for (op = &output; (o = *op); op = &o->next) + if (xf86ModeCompare (o, i) > 0) + break; + i->next = *op; + *op = i; + } + /* prune identical modes */ + for (o = output; o && (n = o->next); o = n) + { + if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) + { + o->next = n->next; + xfree (n->name); + xfree (n); + n = o; + } + } + /* hook up backward links */ + prev = NULL; + for (o = output; o; o = o->next) + { + o->prev = prev; + prev = o; + } + return output; +} + +static char * +preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + char *preferred_mode = NULL; + + /* Check for a configured preference for a particular mode */ + preferred_mode = xf86GetOptValString (output->options, + OPTION_PREFERRED_MODE); + if (preferred_mode) + return preferred_mode; + + if (pScrn->display->modes && *pScrn->display->modes) + preferred_mode = *pScrn->display->modes; + + return preferred_mode; +} + +static void +GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) +{ + if (!mon || !mode) + return; + + mon->nHsync = 1; + mon->hsync[0].lo = 1024.0; + mon->hsync[0].hi = 0.0; + + mon->nVrefresh = 1; + mon->vrefresh[0].lo = 1024.0; + mon->vrefresh[0].hi = 0.0; + + while (mode) { + if (!mode->HSync) + mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal); + + if (!mode->VRefresh) + mode->VRefresh = (1000.0 * ((float) mode->Clock)) / + ((float) (mode->HTotal * mode->VTotal)); + + if (mode->HSync < mon->hsync[0].lo) + mon->hsync[0].lo = mode->HSync; + + if (mode->HSync > mon->hsync[0].hi) + mon->hsync[0].hi = mode->HSync; + + if (mode->VRefresh < mon->vrefresh[0].lo) + mon->vrefresh[0].lo = mode->VRefresh; + + if (mode->VRefresh > mon->vrefresh[0].hi) + mon->vrefresh[0].hi = mode->VRefresh; + + mode = mode->next; + } + + /* stretch out the bottom to fit 640x480@60 */ + if (mon->hsync[0].lo > 31.0) + mon->hsync[0].lo = 31.0; + if (mon->vrefresh[0].lo > 58.0) + mon->vrefresh[0].lo = 58.0; +} + +struct det_monrec_parameter { + MonRec *mon_rec; + int *max_clock; + Bool set_hsync; + Bool set_vrefresh; + enum { sync_config, sync_edid, sync_default } *sync_source; +}; + +static void handle_detailed_monrec(struct detailed_monitor_section *det_mon, + void *data) +{ + enum { sync_config, sync_edid, sync_default }; + struct det_monrec_parameter *p; + p = (struct det_monrec_parameter *)data; + + if (det_mon->type == DS_RANGES) { + struct monitor_ranges *ranges = &det_mon->section.ranges; + if (p->set_hsync && ranges->max_h) { + p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h; + p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h; + p->mon_rec->nHsync++; + if (*p->sync_source == sync_default) + *p->sync_source = sync_edid; + } + if (p->set_vrefresh && ranges->max_v) { + p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v; + p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v; + p->mon_rec->nVrefresh++; + if (*p->sync_source == sync_default) + *p->sync_source = sync_edid; + } + if (ranges->max_clock * 1000 > *p->max_clock) + *p->max_clock = ranges->max_clock * 1000; + } +} + +void +xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + /* When canGrow was TRUE in the initial configuration we have to + * compare against the maximum values so that we don't drop modes. + * When canGrow was FALSE, the maximum values would have been clamped + * anyway. + */ + if (maxX == 0 || maxY == 0) { + maxX = config->maxWidth; + maxY = config->maxHeight; + } + + /* Probe the list of modes for each output. */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode; + DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL; + char *preferred_mode; + xf86MonPtr edid_monitor; + XF86ConfMonitorPtr conf_monitor; + MonRec mon_rec; + int min_clock = 0; + int max_clock = 0; + double clock; + Bool add_default_modes = TRUE; + Bool debug_modes = config->debug_modes || + xf86Initialising; + enum { sync_config, sync_edid, sync_default } sync_source = sync_default; + + while (output->probed_modes != NULL) + xf86DeleteMode(&output->probed_modes, output->probed_modes); + + /* + * Check connection status + */ + output->status = (*output->funcs->detect)(output); + + if (output->status == XF86OutputStatusDisconnected && + !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE)) + { + xf86OutputSetEDID (output, NULL); + continue; + } + + memset (&mon_rec, '\0', sizeof (mon_rec)); + + conf_monitor = output->conf_monitor; + + if (conf_monitor) + { + int i; + + for (i = 0; i < conf_monitor->mon_n_hsync; i++) + { + mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; + mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; + mon_rec.nHsync++; + sync_source = sync_config; + } + for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) + { + mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; + mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; + mon_rec.nVrefresh++; + sync_source = sync_config; + } + config_modes = xf86GetMonitorModes (scrn, conf_monitor); + } + + output_modes = (*output->funcs->get_modes) (output); + + edid_monitor = output->MonInfo; + + if (edid_monitor) + { + struct det_monrec_parameter p; + struct disp_features *features = &edid_monitor->features; + + /* if display is not continuous-frequency, don't add default modes */ + if (!GTF_SUPPORTED(features->msc)) + add_default_modes = FALSE; + + p.mon_rec = &mon_rec; + p.max_clock = &max_clock; + p.set_hsync = mon_rec.nHsync == 0; + p.set_vrefresh = mon_rec.nVrefresh == 0; + p.sync_source = &sync_source; + + xf86ForEachDetailedBlock(edid_monitor, + handle_detailed_monrec, + &p); + } + + if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, + OPTUNITS_KHZ, &clock)) + min_clock = (int) clock; + if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, + OPTUNITS_KHZ, &clock)) + max_clock = (int) clock; + + /* If we still don't have a sync range, guess wildly */ + if (!mon_rec.nHsync || !mon_rec.nVrefresh) + GuessRangeFromModes(&mon_rec, output_modes); + + /* + * These limits will end up setting a 1024x768@60Hz mode by default, + * which seems like a fairly good mode to use when nothing else is + * specified + */ + if (mon_rec.nHsync == 0) + { + mon_rec.hsync[0].lo = 31.0; + mon_rec.hsync[0].hi = 55.0; + mon_rec.nHsync = 1; + } + if (mon_rec.nVrefresh == 0) + { + mon_rec.vrefresh[0].lo = 58.0; + mon_rec.vrefresh[0].hi = 62.0; + mon_rec.nVrefresh = 1; + } + + if (add_default_modes) + default_modes = xf86GetDefaultModes (); + + /* + * If this is not an RB monitor, remove RB modes from the default + * pool. RB modes from the config or the monitor itself are fine. + */ + if (!mon_rec.reducedblanking) + xf86ValidateModesReducedBlanking (scrn, default_modes); + + if (sync_source == sync_config) + { + /* + * Check output and config modes against sync range from config file + */ + xf86ValidateModesSync (scrn, output_modes, &mon_rec); + xf86ValidateModesSync (scrn, config_modes, &mon_rec); + } + /* + * Check default modes against sync range + */ + xf86ValidateModesSync (scrn, default_modes, &mon_rec); + /* + * Check default modes against monitor max clock + */ + if (max_clock) { + xf86ValidateModesClocks(scrn, default_modes, + &min_clock, &max_clock, 1); + xf86ValidateModesClocks(scrn, output_modes, + &min_clock, &max_clock, 1); + } + + output->probed_modes = NULL; + output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); + + /* + * Check all modes against max size, interlace, and doublescan + */ + if (maxX && maxY) + xf86ValidateModesSize (scrn, output->probed_modes, + maxX, maxY, 0); + + { + int flags = (output->interlaceAllowed ? V_INTERLACE : 0) | + (output->doubleScanAllowed ? V_DBLSCAN : 0); + xf86ValidateModesFlags (scrn, output->probed_modes, flags); + } + + /* + * Check all modes against output + */ + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + if (mode->status == MODE_OK) + mode->status = (*output->funcs->mode_valid)(output, mode); + + xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes); + + output->probed_modes = xf86SortModes (output->probed_modes); + + /* Check for a configured preference for a particular mode */ + preferred_mode = preferredMode(scrn, output); + + if (preferred_mode) + { + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (!strcmp (preferred_mode, mode->name)) + { + if (mode != output->probed_modes) + { + if (mode->prev) + mode->prev->next = mode->next; + if (mode->next) + mode->next->prev = mode->prev; + mode->next = output->probed_modes; + output->probed_modes->prev = mode; + mode->prev = NULL; + output->probed_modes = mode; + } + mode->type |= (M_T_PREFERRED|M_T_USERPREF); + break; + } + } + } + + output->initial_rotation = xf86OutputInitialRotation (output); + + if (debug_modes) { + if (output->probed_modes != NULL) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "Printing probed modes for output %s\n", + output->name); + } else { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "No remaining probed modes for output %s\n", + output->name); + } + } + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + { + /* The code to choose the best mode per pipe later on will require + * VRefresh to be set. + */ + mode->VRefresh = xf86ModeVRefresh(mode); + xf86SetModeCrtc(mode, INTERLACE_HALVE_V); + + if (debug_modes) + xf86PrintModeline(scrn->scrnIndex, mode); + } + } +} + + +/** + * Copy one of the output mode lists to the ScrnInfo record + */ + +/* XXX where does this function belong? Here? */ +void +xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y); + +static DisplayModePtr +biggestMode(DisplayModePtr a, DisplayModePtr b) +{ + int A, B; + + if (!a) + return b; + if (!b) + return a; + + A = a->HDisplay * a->VDisplay; + B = b->HDisplay * b->VDisplay; + + if (A > B) + return a; + + return b; +} + +static xf86OutputPtr +SetCompatOutput(xf86CrtcConfigPtr config) +{ + xf86OutputPtr output = NULL, test = NULL; + DisplayModePtr maxmode = NULL, testmode, mode; + int o, compat = -1, count, mincount = 0; + + /* Look for one that's definitely connected */ + for (o = 0; o < config->num_output; o++) + { + test = config->output[o]; + if (!test->crtc) + continue; + if (test->status != XF86OutputStatusConnected) + continue; + if (!test->probed_modes) + continue; + + testmode = mode = test->probed_modes; + for (count = 0; mode; mode = mode->next, count++) + testmode = biggestMode(testmode, mode); + + if (!output) { + output = test; + compat = o; + maxmode = testmode; + mincount = count; + } else if (maxmode == biggestMode(maxmode, testmode)) { + output = test; + compat = o; + maxmode = testmode; + mincount = count; + } else if ((maxmode->HDisplay == testmode->HDisplay) && + (maxmode->VDisplay == testmode->VDisplay) && + count <= mincount) { + output = test; + compat = o; + maxmode = testmode; + mincount = count; + } + } + + /* If we didn't find one, take anything we can get */ + if (!output) + { + for (o = 0; o < config->num_output; o++) + { + test = config->output[o]; + if (!test->crtc) + continue; + if (!test->probed_modes) + continue; + + if (!output) { + output = test; + compat = o; + } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) { + output = test; + compat = o; + } + } + } + + if (compat >= 0) { + config->compat_output = compat; + } else { + /* Don't change the compat output when no valid outputs found */ + output = config->output[config->compat_output]; + } + + return output; +} + +void +xf86SetScrnInfoModes (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + DisplayModePtr last, mode = NULL; + + output = SetCompatOutput(config); + + if (!output) + return; /* punt */ + + crtc = output->crtc; + + /* Clear any existing modes from scrn->modes */ + while (scrn->modes != NULL) + xf86DeleteMode(&scrn->modes, scrn->modes); + + /* Set scrn->modes to the mode list for the 'compat' output */ + scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); + + if (crtc) { + for (mode = scrn->modes; mode; mode = mode->next) + if (xf86ModesEqual (mode, &crtc->desiredMode)) + break; + } + + if (scrn->modes != NULL) { + /* For some reason, scrn->modes is circular, unlike the other mode + * lists. How great is that? + */ + for (last = scrn->modes; last && last->next; last = last->next) + ; + last->next = scrn->modes; + scrn->modes->prev = last; + if (mode) { + while (scrn->modes != mode) + scrn->modes = scrn->modes->next; + } + } + scrn->currentMode = scrn->modes; +#ifdef XFreeXDGA + if (scrn->pScreen) + _xf86_di_dga_reinit_internal(scrn->pScreen); +#endif +} + +static void +xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + Bool *enabled) +{ + Bool any_enabled = FALSE; + int o; + + for (o = 0; o < config->num_output; o++) + any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE); + + if (!any_enabled) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "No outputs definitely connected, trying again...\n"); + + for (o = 0; o < config->num_output; o++) + enabled[o] = xf86OutputEnabled(config->output[o], FALSE); + } +} + +static Bool +nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index) +{ + int o = *index; + + for (o++; o < config->num_output; o++) { + if (enabled[o]) { + *index = o; + return TRUE; + } + } + + return FALSE; +} + +static Bool +aspectMatch(float a, float b) +{ + return fabs(1 - (a / b)) < 0.05; +} + +static DisplayModePtr +nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) +{ + DisplayModePtr m = NULL; + + if (!o) + return NULL; + + if (!last) + m = o->probed_modes; + else + m = last->next; + + for (; m; m = m->next) + if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay)) + return m; + + return NULL; +} + +static DisplayModePtr +bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) +{ + int o = -1, p; + DisplayModePtr mode = NULL, test = NULL, match = NULL; + + if (!nextEnabledOutput(config, enabled, &o)) + return NULL; + while ((mode = nextAspectMode(config->output[o], mode, aspect))) { + test = mode; + for (p = o; nextEnabledOutput(config, enabled, &p); ) { + test = xf86OutputFindClosestMode(config->output[p], mode); + if (!test) + break; + if (test->HDisplay != mode->HDisplay || + test->VDisplay != mode->VDisplay) { + test = NULL; + break; + } + } + + /* if we didn't match it on all outputs, try the next one */ + if (!test) + continue; + + /* if it's bigger than the last one, save it */ + if (!match || (test->HDisplay > match->HDisplay)) + match = test; + } + + /* return the biggest one found */ + return match; +} + +static Bool +xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o, p; + int max_pref_width = 0, max_pref_height = 0; + DisplayModePtr *preferred, *preferred_match; + Bool ret = FALSE; + + preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); + preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); + + /* Check if the preferred mode is available on all outputs */ + for (p = -1; nextEnabledOutput(config, enabled, &p); ) { + Rotation r = config->output[p]->initial_rotation; + DisplayModePtr mode; + if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p], + width, height))) { + int pref_width = xf86ModeWidth(preferred[p], r); + int pref_height = xf86ModeHeight(preferred[p], r); + Bool all_match = TRUE; + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + Bool match = FALSE; + xf86OutputPtr output = config->output[o]; + if (o == p) + continue; + + for (mode = output->probed_modes; mode; mode = mode->next) { + Rotation r = output->initial_rotation; + if (xf86ModeWidth(mode, r) == pref_width && + xf86ModeHeight(mode, r) == pref_height) { + preferred[o] = mode; + match = TRUE; + } + } + + all_match &= match; + } + + if (all_match && + (pref_width*pref_height > max_pref_width*max_pref_height)) { + for (o = -1; nextEnabledOutput(config, enabled, &o); ) + preferred_match[o] = preferred[o]; + max_pref_width = pref_width; + max_pref_height = pref_height; + ret = TRUE; + } + } + } + + /* + * If there's no preferred mode, but only one monitor, pick the + * biggest mode for its aspect ratio, assuming one exists. + */ + if (!ret) do { + int i = 0; + float aspect = 0.0; + + /* count the number of enabled outputs */ + for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; + + if (i != 1) + break; + + p = -1; + nextEnabledOutput(config, enabled, &p); + if (config->output[p]->mm_height) + aspect = (float)config->output[p]->mm_width / + (float)config->output[p]->mm_height; + + if (aspect) + preferred_match[p] = bestModeForAspect(config, enabled, aspect); + + if (preferred_match[p]) + ret = TRUE; + + } while (0); + + if (ret) { + /* oh good, there is a match. stash the selected modes and return. */ + memcpy(modes, preferred_match, + config->num_output * sizeof(DisplayModePtr)); + } + + xfree(preferred); + xfree(preferred_match); + return ret; +} + +static Bool +xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o; + float aspect = 0.0, *aspects; + xf86OutputPtr output; + Bool ret = FALSE; + DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL; + + aspects = xnfcalloc(config->num_output, sizeof(float)); + + /* collect the aspect ratios */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + output = config->output[o]; + if (output->mm_height) + aspects[o] = (float)output->mm_width / (float)output->mm_height; + else + aspects[o] = 4.0 / 3.0; + } + + /* check that they're all the same */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + output = config->output[o]; + if (!aspect) { + aspect = aspects[o]; + } else if (!aspectMatch(aspect, aspects[o])) { + goto no_aspect_match; + } + } + + /* if they're all 4:3, just skip ahead and save effort */ + if (!aspectMatch(aspect, 4.0/3.0)) + aspect_guess = bestModeForAspect(config, enabled, aspect); + +no_aspect_match: + base_guess = bestModeForAspect(config, enabled, 4.0/3.0); + + guess = biggestMode(base_guess, aspect_guess); + + if (!guess) + goto out; + + /* found a mode that works everywhere, now apply it */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + modes[o] = xf86OutputFindClosestMode(config->output[o], guess); + } + ret = TRUE; + +out: + xfree(aspects); + return ret; +} + +static Bool +xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + DisplayModePtr target_mode = NULL; + Rotation target_rotation = RR_Rotate_0; + DisplayModePtr default_mode; + int default_preferred, target_preferred = 0, o; + + /* User preferred > preferred > other modes */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + default_mode = xf86DefaultMode (config->output[o], width, height); + if (!default_mode) + continue; + + default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) + + ((default_mode->type & M_T_USERPREF) != 0)); + + if (default_preferred > target_preferred || !target_mode) { + target_mode = default_mode; + target_preferred = default_preferred; + target_rotation = config->output[o]->initial_rotation; + config->compat_output = o; + } + } + + if (target_mode) + modes[config->compat_output] = target_mode; + + /* Fill in other output modes */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + if (!modes[o]) + modes[o] = xf86ClosestMode(config->output[o], target_mode, + target_rotation, width, height); + } + + return (target_mode != NULL); +} + +static Bool +xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o; + + if (xf86UserConfiguredOutputs(scrn, modes)) + return xf86TargetFallback(scrn, config, modes, enabled, width, height); + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) + if (xf86OutputHasUserPreferredMode(config->output[o])) + return + xf86TargetFallback(scrn, config, modes, enabled, width, height); + + return FALSE; +} + +static Bool +xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, + float gamma_blue) +{ + int i, size = 256; + CARD16 *red, *green, *blue; + + red = malloc(3 * size * sizeof(CARD16)); + green = red + size; + blue = green + size; + + /* Only cause warning if user wanted gamma to be set. */ + if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) { + free(red); + return FALSE; + } else if (!crtc->funcs->gamma_set) { + free(red); + return TRUE; + } + + /* At this early stage none of the randr-interface stuff is up. + * So take the default gamma size for lack of something better. + */ + for (i = 0; i < size; i++) { + if (gamma_red == 1.0) + red[i] = i << 8; + else + red[i] = (CARD16)(pow((double)i/(double)(size - 1), + 1. / (double)gamma_red) * (double)(size - 1) * 256); + + if (gamma_green == 1.0) + green[i] = i << 8; + else + green[i] = (CARD16)(pow((double)i/(double)(size - 1), + 1. / (double)gamma_green) * (double)(size - 1) * 256); + + if (gamma_blue == 1.0) + blue[i] = i << 8; + else + blue[i] = (CARD16)(pow((double)i/(double)(size - 1), + 1. / (double)gamma_blue) * (double)(size - 1) * 256); + } + + /* Default size is 256, so anything else is failure. */ + if (size != crtc->gamma_size) { + free(red); + return FALSE; + } + + crtc->gamma_size = size; + memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16)); + + /* Do not set gamma now, delay until the crtc is activated. */ + + free(red); + + return TRUE; +} + +static Bool +xf86OutputSetInitialGamma(xf86OutputPtr output) +{ + XF86ConfMonitorPtr mon = output->conf_monitor; + float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; + + if (!mon) + return TRUE; + + if (!output->crtc) + return FALSE; + + /* Get configured values, where they exist. */ + if (mon->mon_gamma_red >= GAMMA_MIN && + mon->mon_gamma_red <= GAMMA_MAX) + gamma_red = mon->mon_gamma_red; + + if (mon->mon_gamma_green >= GAMMA_MIN && + mon->mon_gamma_green <= GAMMA_MAX) + gamma_green = mon->mon_gamma_green; + + if (mon->mon_gamma_blue >= GAMMA_MIN && + mon->mon_gamma_blue <= GAMMA_MAX) + gamma_blue = mon->mon_gamma_blue; + + /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */ + if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { + xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue); + return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue); + }else + return TRUE; +} + +/** + * Construct default screen configuration + * + * Given auto-detected (and, eventually, configured) values, + * construct a usable configuration for the system + * + * canGrow indicates that the driver can resize the screen to larger than its + * initially configured size via the config->funcs->resize hook. If TRUE, this + * function will set virtualX and virtualY to match the initial configuration + * and leave config->max{Width,Height} alone. If FALSE, it will bloat + * virtual[XY] to include the largest modes and set config->max{Width,Height} + * accordingly. + */ + +Bool +xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o, c; + xf86CrtcPtr *crtcs; + DisplayModePtr *modes; + Bool *enabled; + int width, height; + int i = scrn->scrnIndex; + + /* Set up the device options */ + config->options = xnfalloc (sizeof (xf86DeviceOptions)); + memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions)); + xf86ProcessOptions (scrn->scrnIndex, + scrn->options, + config->options); + config->debug_modes = xf86ReturnOptValBool (config->options, + OPTION_MODEDEBUG, FALSE); + + if (scrn->display->virtualX) + width = scrn->display->virtualX; + else + width = config->maxWidth; + if (scrn->display->virtualY) + height = scrn->display->virtualY; + else + height = config->maxHeight; + + xf86ProbeOutputModes (scrn, width, height); + + crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); + modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); + enabled = xnfcalloc (config->num_output, sizeof (Bool)); + + xf86CollectEnabledOutputs(scrn, config, enabled); + + if (xf86TargetUserpref(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n"); + else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n"); + else if (xf86TargetAspect(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n"); + else if (xf86TargetFallback(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n"); + else + xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n"); + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + if (!modes[o]) + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Output %s enabled but has no modes\n", + config->output[o]->name); + else + xf86DrvMsg (scrn->scrnIndex, X_INFO, + "Output %s using initial mode %s\n", + config->output[o]->name, modes[o]->name); + } + + /* + * Set the position of each output + */ + if (!xf86InitialOutputPositions (scrn, modes)) + { + xfree (crtcs); + xfree (modes); + return FALSE; + } + + /* + * Set initial panning of each output + */ + xf86InitialPanning (scrn); + + /* + * Assign CRTCs to fit output configuration + */ + if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height)) + { + xfree (crtcs); + xfree (modes); + return FALSE; + } + + /* XXX override xf86 common frame computation code */ + + scrn->display->frameX0 = 0; + scrn->display->frameY0 = 0; + + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->enabled = FALSE; + memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); + /* Set default gamma for all crtc's. */ + /* This is done to avoid problems later on with cloned outputs. */ + xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0); + } + + if (xf86_crtc_supports_gamma(scrn)) + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n"); + + /* + * Set initial configuration + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode = modes[o]; + xf86CrtcPtr crtc = crtcs[o]; + + if (mode && crtc) + { + crtc->desiredMode = *mode; + crtc->desiredRotation = output->initial_rotation; + crtc->desiredX = output->initial_x; + crtc->desiredY = output->initial_y; + crtc->desiredTransformPresent = FALSE; + crtc->enabled = TRUE; + memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec)); + memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec)); + memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16)); + output->crtc = crtc; + if (!xf86OutputSetInitialGamma(output)) + xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name); + } else { + output->crtc = NULL; + } + } + + if (scrn->display->virtualX == 0) + { + /* + * Expand virtual size to cover the current config and potential mode + * switches, if the driver can't enlarge the screen later. + */ + xf86DefaultScreenLimits (scrn, &width, &height, canGrow); + + scrn->display->virtualX = width; + scrn->display->virtualY = height; + } + + if (width > scrn->virtualX) + scrn->virtualX = width; + if (height > scrn->virtualY) + scrn->virtualY = height; + + /* + * Make sure the configuration isn't too small. + */ + if (width < config->minWidth || height < config->minHeight) + return FALSE; + + /* + * Limit the crtc config to virtual[XY] if the driver can't grow the + * desktop. + */ + if (!canGrow) + { + xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight, + width, height); + } + + /* Mirror output modes to scrn mode list */ + xf86SetScrnInfoModes (scrn); + + xfree (crtcs); + xfree (modes); + return TRUE; +} + +/* + * Check the CRTC we're going to map each output to vs. it's current + * CRTC. If they don't match, we have to disable the output and the CRTC + * since the driver will have to re-route things. + */ +static void +xf86PrepareOutputs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + for (o = 0; o < config->num_output; o++) { + xf86OutputPtr output = config->output[o]; +#if RANDR_GET_CRTC_INTERFACE + /* Disable outputs that are unused or will be re-routed */ + if (!output->funcs->get_crtc || + output->crtc != (*output->funcs->get_crtc)(output) || + output->crtc == NULL) +#endif + (*output->funcs->dpms)(output, DPMSModeOff); + } +} + +static void +xf86PrepareCrtcs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + for (c = 0; c < config->num_crtc; c++) { +#if RANDR_GET_CRTC_INTERFACE + xf86CrtcPtr crtc = config->crtc[c]; + xf86OutputPtr output = NULL; + uint32_t desired_outputs = 0, current_outputs = 0; + int o; + + for (o = 0; o < config->num_output; o++) { + output = config->output[o]; + if (output->crtc == crtc) + desired_outputs |= (1<funcs->get_crtc) { + desired_outputs = 0; + break; + } + if ((*output->funcs->get_crtc)(output) == crtc) + current_outputs |= (1<funcs->dpms)(crtc, DPMSModeOff); +#else + (*crtc->funcs->dpms)(crtc, DPMSModeOff); +#endif + } +} + +/* + * Using the desired mode information in each crtc, set + * modes (used in EnterVT functions, or at server startup) + */ + +Bool +xf86SetDesiredModes (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc = config->crtc[0]; + int c; + + /* A driver with this hook will take care of this */ + if (!crtc->funcs->set_mode_major) { + xf86PrepareOutputs(scrn); + xf86PrepareCrtcs(scrn); + } + + for (c = 0; c < config->num_crtc; c++) + { + xf86OutputPtr output = NULL; + int o; + RRTransformPtr transform; + + crtc = config->crtc[c]; + + /* Skip disabled CRTCs */ + if (!crtc->enabled) + continue; + + if (config->output[config->compat_output]->crtc == crtc) + output = config->output[config->compat_output]; + else + { + for (o = 0; o < config->num_output; o++) + if (config->output[o]->crtc == crtc) + { + output = config->output[o]; + break; + } + } + /* paranoia */ + if (!output) + continue; + + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->mode, 0, sizeof(crtc->mode)); + if (!crtc->desiredMode.CrtcHDisplay) + { + DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode); + + if (!mode) + return FALSE; + crtc->desiredMode = *mode; + crtc->desiredRotation = RR_Rotate_0; + crtc->desiredTransformPresent = FALSE; + crtc->desiredX = 0; + crtc->desiredY = 0; + } + + if (crtc->desiredTransformPresent) + transform = &crtc->desiredTransform; + else + transform = NULL; + if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation, + transform, crtc->desiredX, crtc->desiredY)) + return FALSE; + } + + xf86DisableUnusedFunctions(scrn); + return TRUE; +} + +/** + * In the current world order, there are lists of modes per output, which may + * or may not include the mode that was asked to be set by XFree86's mode + * selection. Find the closest one, in the following preference order: + * + * - Equality + * - Closer in size to the requested mode, but no larger + * - Closer in refresh rate to the requested mode. + */ + +DisplayModePtr +xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired) +{ + DisplayModePtr best = NULL, scan = NULL; + + for (scan = output->probed_modes; scan != NULL; scan = scan->next) + { + /* If there's an exact match, we're done. */ + if (xf86ModesEqual(scan, desired)) { + best = desired; + break; + } + + /* Reject if it's larger than the desired mode. */ + if (scan->HDisplay > desired->HDisplay || + scan->VDisplay > desired->VDisplay) + { + continue; + } + + /* + * If we haven't picked a best mode yet, use the first + * one in the size range + */ + if (best == NULL) + { + best = scan; + continue; + } + + /* Find if it's closer to the right size than the current best + * option. + */ + if ((scan->HDisplay > best->HDisplay && + scan->VDisplay >= best->VDisplay) || + (scan->HDisplay >= best->HDisplay && + scan->VDisplay > best->VDisplay)) + { + best = scan; + continue; + } + + /* Find if it's still closer to the right refresh than the current + * best resolution. + */ + if (scan->HDisplay == best->HDisplay && + scan->VDisplay == best->VDisplay && + (fabs(scan->VRefresh - desired->VRefresh) < + fabs(best->VRefresh - desired->VRefresh))) { + best = scan; + } + } + return best; +} + +/** + * When setting a mode through XFree86-VidModeExtension or XFree86-DGA, + * take the specified mode and apply it to the crtc connected to the compat + * output. Then, find similar modes for the other outputs, as with the + * InitialConfiguration code above. The goal is to clone the desired + * mode across all outputs that are currently active. + */ + +Bool +xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + Bool ok = TRUE; + xf86OutputPtr compat_output = config->output[config->compat_output]; + DisplayModePtr compat_mode; + int c; + + /* + * Let the compat output drive the final mode selection + */ + compat_mode = xf86OutputFindClosestMode (compat_output, desired); + if (compat_mode) + desired = compat_mode; + + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + DisplayModePtr crtc_mode = NULL; + int o; + + if (!crtc->enabled) + continue; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr output_mode; + + /* skip outputs not on this crtc */ + if (output->crtc != crtc) + continue; + + if (crtc_mode) + { + output_mode = xf86OutputFindClosestMode (output, crtc_mode); + if (output_mode != crtc_mode) + output->crtc = NULL; + } + else + crtc_mode = xf86OutputFindClosestMode (output, desired); + } + if (!crtc_mode) + { + crtc->enabled = FALSE; + continue; + } + if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0)) + ok = FALSE; + else + { + crtc->desiredMode = *crtc_mode; + crtc->desiredRotation = rotation; + crtc->desiredTransformPresent = FALSE; + crtc->desiredX = 0; + crtc->desiredY = 0; + } + } + xf86DisableUnusedFunctions(pScrn); +#ifdef RANDR_12_INTERFACE + xf86RandR12TellChanged (pScrn->pScreen); +#endif + return ok; +} + + +/** + * Set the DPMS power mode of all outputs and CRTCs. + * + * If the new mode is off, it will turn off outputs and then CRTCs. + * Otherwise, it will affect CRTCs before outputs. + */ +void +xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int i; + + if (!scrn->vtSema) + return; + + if (mode == DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } + + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + if (crtc->enabled) + (*crtc->funcs->dpms) (crtc, mode); + } + + if (mode != DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } +} + +/** + * Implement the screensaver by just calling down into the driver DPMS hooks. + * + * Even for monitors with no DPMS support, by the definition of our DPMS hooks, + * the outputs will still get disabled (blanked). + */ +Bool +xf86SaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (xf86IsUnblank(mode)) + xf86DPMSSet(pScrn, DPMSModeOn, 0); + else + xf86DPMSSet(pScrn, DPMSModeOff, 0); + + return TRUE; +} + +/** + * Disable all inactive crtcs and outputs + */ +void +xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int o, c; + + for (o = 0; o < xf86_config->num_output; o++) + { + xf86OutputPtr output = xf86_config->output[o]; + if (!output->crtc) + (*output->funcs->dpms)(output, DPMSModeOff); + } + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (!crtc->enabled) + { + crtc->funcs->dpms(crtc, DPMSModeOff); + memset(&crtc->mode, 0, sizeof(crtc->mode)); + xf86RotateDestroy(crtc); + crtc->active = FALSE; + } + } + if (pScrn->pScreen) + xf86_crtc_notify(pScrn->pScreen); +} + +#ifdef RANDR_12_INTERFACE + +#define EDID_ATOM_NAME "EDID" + +/** + * Set the RandR EDID property + */ +static void +xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) +{ + Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE); + + /* This may get called before the RandR resources have been created */ + if (output->randr_output == NULL) + return; + + if (data_len != 0) { + RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, + PropModeReplace, data_len, data, FALSE, TRUE); + } else { + RRDeleteOutputProperty(output->randr_output, edid_atom); + } +} + +#endif + +/* Pull out a phyiscal size from a detailed timing if available. */ +struct det_phySize_parameter { + xf86OutputPtr output; + ddc_quirk_t quirks; + Bool ret; +}; + +static void handle_detailed_physical_size(struct detailed_monitor_section + *det_mon, void *data) +{ + struct det_phySize_parameter *p; + p = (struct det_phySize_parameter *)data; + + if (p->ret == TRUE ) + return ; + + xf86DetTimingApplyQuirks(det_mon, p->quirks, + p->output->MonInfo->features.hsize, + p->output->MonInfo->features.vsize); + if (det_mon->type == DT && + det_mon->section.d_timings.h_size != 0 && + det_mon->section.d_timings.v_size != 0) { + + p->output->mm_width = det_mon->section.d_timings.h_size; + p->output->mm_height = det_mon->section.d_timings.v_size; + p->ret = TRUE; + } +} + +/** + * Set the EDID information for the specified output + */ +void +xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) +{ + ScrnInfoPtr scrn = output->scrn; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + Bool debug_modes = config->debug_modes || xf86Initialising; +#ifdef RANDR_12_INTERFACE + int size; +#endif + + if (output->MonInfo != NULL) + xfree(output->MonInfo); + + output->MonInfo = edid_mon; + + if (debug_modes) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", + output->name); + xf86PrintEDID(edid_mon); + } + + /* Set the DDC properties for the 'compat' output */ + if (output == config->output[config->compat_output]) + xf86SetDDCproperties(scrn, edid_mon); + +#ifdef RANDR_12_INTERFACE + /* Set the RandR output properties */ + size = 0; + if (edid_mon) + { + if (edid_mon->ver.version == 1) { + size = 128; + if (edid_mon->flags & EDID_COMPLETE_RAWDATA) + size += edid_mon->no_sections * 128; + } else if (edid_mon->ver.version == 2) + size = 256; + } + xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); +#endif + + if (edid_mon) { + + struct det_phySize_parameter p; + p.output = output; + p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE); + p.ret = FALSE; + xf86ForEachDetailedBlock(edid_mon, + handle_detailed_physical_size, &p); + + /* if no mm size is available from a detailed timing, check the max size field */ + if ((!output->mm_width || !output->mm_height) && + (edid_mon->features.hsize && edid_mon->features.vsize)) + { + output->mm_width = edid_mon->features.hsize * 10; + output->mm_height = edid_mon->features.vsize * 10; + } + } +} + +/** + * Return the list of modes supported by the EDID information + * stored in 'output' + */ +DisplayModePtr +xf86OutputGetEDIDModes (xf86OutputPtr output) +{ + ScrnInfoPtr scrn = output->scrn; + xf86MonPtr edid_mon = output->MonInfo; + + if (!edid_mon) + return NULL; + return xf86DDCGetModes(scrn->scrnIndex, edid_mon); +} + +/* maybe we should care about DDC1? meh. */ +xf86MonPtr +xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) +{ + ScrnInfoPtr scrn = output->scrn; + xf86MonPtr mon; + + mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE); + if (mon) + xf86DDCApplyQuirks(scrn->scrnIndex, mon); + + return mon; +} + +static char *_xf86ConnectorNames[] = { + "None", "VGA", "DVI-I", "DVI-D", + "DVI-A", "Composite", "S-Video", + "Component", "LFP", "Proprietary", + "HDMI", "DisplayPort", + }; +char * +xf86ConnectorGetName(xf86ConnectorType connector) +{ + return _xf86ConnectorNames[connector]; +} + +static void +x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) +{ + dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; + dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; + dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; + dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; + + if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; +} + +static void +x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) +{ + if (crtc->enabled) { + crtc_box->x1 = crtc->x; + crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); + crtc_box->y1 = crtc->y; + crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); + } else + crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; +} + +static int +xf86_crtc_box_area(BoxPtr box) +{ + return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); +} + +/* + * Return the crtc covering 'box'. If two crtcs cover a portion of + * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc + * with greater coverage + */ + +static xf86CrtcPtr +xf86_covering_crtc(ScrnInfoPtr pScrn, + BoxPtr box, + xf86CrtcPtr desired, + BoxPtr crtc_box_ret) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc, best_crtc; + int coverage, best_coverage; + int c; + BoxRec crtc_box, cover_box; + + best_crtc = NULL; + best_coverage = 0; + crtc_box_ret->x1 = 0; + crtc_box_ret->x2 = 0; + crtc_box_ret->y1 = 0; + crtc_box_ret->y2 = 0; + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + x86_crtc_box(crtc, &crtc_box); + x86_crtc_box_intersect(&cover_box, &crtc_box, box); + coverage = xf86_crtc_box_area(&cover_box); + if (coverage && crtc == desired) { + *crtc_box_ret = crtc_box; + return crtc; + } else if (coverage > best_coverage) { + *crtc_box_ret = crtc_box; + best_crtc = crtc; + best_coverage = coverage; + } + } + return best_crtc; +} + +/* + * For overlay video, compute the relevant CRTC and + * clip video to that. + * + * returning FALSE means there was a memory failure of some kind, + * not that the video shouldn't be displayed + */ + +Bool +xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, + xf86CrtcPtr *crtc_ret, + xf86CrtcPtr desired_crtc, + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height) +{ + Bool ret; + RegionRec crtc_region_local; + RegionPtr crtc_region = reg; + + if (crtc_ret) { + BoxRec crtc_box; + xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst, + desired_crtc, + &crtc_box); + + if (crtc) { + REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1); + crtc_region = &crtc_region_local; + REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg); + } + *crtc_ret = crtc; + } + + ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, + crtc_region, width, height); + + if (crtc_region != reg) + REGION_UNINIT (pScreen, &crtc_region_local); + + return ret; +} + +xf86_crtc_notify_proc_ptr +xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new) +{ + if (xf86CrtcConfigPrivateIndex != -1) + { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86_crtc_notify_proc_ptr old; + + old = config->xf86_crtc_notify; + config->xf86_crtc_notify = new; + return old; + } + return NULL; +} + +void +xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old) +{ + if (xf86CrtcConfigPrivateIndex != -1) + { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + config->xf86_crtc_notify = old; + } +} + +void +xf86_crtc_notify(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + if (config->xf86_crtc_notify) + config->xf86_crtc_notify(screen); +} + +Bool +xf86_crtc_supports_gamma(ScrnInfoPtr pScrn) +{ + if (xf86CrtcConfigPrivateIndex != -1) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc; + + /* for multiple drivers loaded we need this */ + if (!xf86_config) + return FALSE; + if (xf86_config->num_crtc == 0) + return FALSE; + crtc = xf86_config->crtc[0]; + + return (crtc->funcs->gamma_set != NULL); + } + + return FALSE; +} diff --git a/xorg-server/hw/xfree86/os-support/solaris/sun_bell.c b/xorg-server/hw/xfree86/os-support/solaris/sun_bell.c index 7f146eaaf..05d17492a 100644 --- a/xorg-server/hw/xfree86/os-support/solaris/sun_bell.c +++ b/xorg-server/hw/xfree86/os-support/solaris/sun_bell.c @@ -126,14 +126,15 @@ xf86OSRingBell(int loudness, int pitch, int duration) iovcnt = 0; for (cnt = 0; cnt <= repeats; cnt++) { - iov[iovcnt].iov_base = (char *) samples; - iov[iovcnt++].iov_len = sizeof(samples); if (cnt == repeats) { /* Insert a bit of silence so that multiple beeps are distinct and * not compressed into a single tone. */ iov[iovcnt].iov_base = (char *) silence; iov[iovcnt++].iov_len = sizeof(silence); + } else { + iov[iovcnt].iov_base = (char *) samples; + iov[iovcnt++].iov_len = sizeof(samples); } if ((iovcnt >= IOV_MAX) || (cnt == repeats)) { written = writev(audioFD, iov, iovcnt); diff --git a/xorg-server/hw/xfree86/parser/scan.c b/xorg-server/hw/xfree86/parser/scan.c index 03cbc8a44..cdca9ca1c 100644 --- a/xorg-server/hw/xfree86/parser/scan.c +++ b/xorg-server/hw/xfree86/parser/scan.c @@ -1207,21 +1207,21 @@ xf86getBoolValue(Bool *val, const char *str) if (*str == '\0') { *val = TRUE; } else { - if (strcmp(str, "1") == 0) + if (xf86nameCompare(str, "1") == 0) *val = TRUE; - else if (strcmp(str, "on") == 0) + else if (xf86nameCompare(str, "on") == 0) *val = TRUE; - else if (strcmp(str, "true") == 0) + else if (xf86nameCompare(str, "true") == 0) *val = TRUE; - else if (strcmp(str, "yes") == 0) + else if (xf86nameCompare(str, "yes") == 0) *val = TRUE; - else if (strcmp(str, "0") == 0) + else if (xf86nameCompare(str, "0") == 0) *val = FALSE; - else if (strcmp(str, "off") == 0) + else if (xf86nameCompare(str, "off") == 0) *val = FALSE; - else if (strcmp(str, "false") == 0) + else if (xf86nameCompare(str, "false") == 0) *val = FALSE; - else if (strcmp(str, "no") == 0) + else if (xf86nameCompare(str, "no") == 0) *val = FALSE; else return FALSE; diff --git a/xorg-server/hw/xfree86/x86emu/validate.c b/xorg-server/hw/xfree86/x86emu/validate.c index 239f6c1f3..b8c4d12d1 100644 --- a/xorg-server/hw/xfree86/x86emu/validate.c +++ b/xorg-server/hw/xfree86/x86emu/validate.c @@ -673,7 +673,7 @@ int main(int argc) VAL_LONG_LONG_BINARY(cmp_long); VAL_BYTE_UNARY(daa_byte); - VAL_BYTE_UNARY(das_byte); // Fails for 0x9A (out of range anyway) + VAL_BYTE_UNARY(das_byte); /* Fails for 0x9A (out of range anyway) */ VAL_BYTE_UNARY(dec_byte); VAL_WORD_UNARY(dec_word); diff --git a/xorg-server/hw/xfree86/x86emu/x86emu/prim_x86_gcc.h b/xorg-server/hw/xfree86/x86emu/x86emu/prim_x86_gcc.h index 5530a3ada..4c850a1bd 100644 --- a/xorg-server/hw/xfree86/x86emu/x86emu/prim_x86_gcc.h +++ b/xorg-server/hw/xfree86/x86emu/x86emu/prim_x86_gcc.h @@ -61,7 +61,7 @@ static inline void hw_cpuid (u32 *a, u32 *b, u32 *c, u32 *d) : "cc"); } -#else // ! (__PIC__ && __i386__) +#else /* ! (__PIC__ && __i386__) */ #define x86EMU_HAS_HW_CPUID 1 static inline void hw_cpuid (u32 *a, u32 *b, u32 *c, u32 *d) @@ -73,7 +73,7 @@ static inline void hw_cpuid (u32 *a, u32 *b, u32 *c, u32 *d) : "cc"); } -#endif // __PIC__ && __i386__ +#endif /* __PIC__ && __i386__ */ -#endif // __X86EMU_PRIM_X86_GCC_H +#endif /* __X86EMU_PRIM_X86_GCC_H */ diff --git a/xorg-server/hw/xquartz/GL/capabilities.c b/xorg-server/hw/xquartz/GL/capabilities.c index 43064044c..5f1f87013 100644 --- a/xorg-server/hw/xquartz/GL/capabilities.c +++ b/xorg-server/hw/xquartz/GL/capabilities.c @@ -522,7 +522,7 @@ bool getGlCapabilities(struct glCapabilities *cap) { conf = malloc(sizeof(*conf)); if(NULL == conf) { perror("malloc"); - abort(); + OsAbort(); } /* Copy the struct. */ diff --git a/xorg-server/hw/xquartz/GL/indirect.c b/xorg-server/hw/xquartz/GL/indirect.c index 176282532..44380ffa0 100644 --- a/xorg-server/hw/xquartz/GL/indirect.c +++ b/xorg-server/hw/xquartz/GL/indirect.c @@ -548,7 +548,7 @@ static CGLPixelFormatObj makeFormat(__GLXconfig *conf) { attr[i++] = conf->samples; } - attr[i++] = 0; + attr[i + 1] = 0; error = CGLChoosePixelFormat(attr, &fobj, &formats); if(error) { diff --git a/xorg-server/hw/xquartz/GL/visualConfigs.c b/xorg-server/hw/xquartz/GL/visualConfigs.c index f92677847..bef27f048 100644 --- a/xorg-server/hw/xquartz/GL/visualConfigs.c +++ b/xorg-server/hw/xquartz/GL/visualConfigs.c @@ -62,7 +62,7 @@ __GLXconfig *__glXAquaCreateVisualConfigs(int *numConfigsPtr, int screenNumber) int numConfigs = 0; __GLXconfig *visualConfigs, *c; struct glCapabilities caps; - struct glCapabilitiesConfig *conf = NULL; + struct glCapabilitiesConfig *conf; int stereo, depth, aux, buffers, stencil, accum, color, msample; if(getGlCapabilities(&caps)) { @@ -94,7 +94,6 @@ __GLXconfig *__glXAquaCreateVisualConfigs(int *numConfigsPtr, int screenNumber) */ assert(NULL != caps.configurations); - conf = caps.configurations; numConfigs = 0; diff --git a/xorg-server/hw/xquartz/X11Application.m b/xorg-server/hw/xquartz/X11Application.m index f3c8a307a..3faa1cb84 100644 --- a/xorg-server/hw/xquartz/X11Application.m +++ b/xorg-server/hw/xquartz/X11Application.m @@ -482,7 +482,7 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { return out; } -- (CFPropertyListRef) prefs_get:(NSString *)key { +- (CFPropertyListRef) prefs_get_copy:(NSString *)key { CFPropertyListRef value; value = CFPreferencesCopyAppValue ((CFStringRef) key, app_prefs_domain_cfstr); @@ -543,7 +543,7 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { CFPropertyListRef value; int ret; - value = [self prefs_get:key]; + value = [self prefs_get_copy:key]; if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ()) CFNumberGetValue (value, kCFNumberIntType, &ret); @@ -561,7 +561,7 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { CFPropertyListRef value; const char *ret = NULL; - value = [self prefs_get:key]; + value = [self prefs_get_copy:key]; if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { NSString *s = (NSString *) value; @@ -578,12 +578,13 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { CFPropertyListRef value; NSURL *ret = NULL; - value = [self prefs_get:key]; + value = [self prefs_get_copy:key]; if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { NSString *s = (NSString *) value; ret = [NSURL URLWithString:s]; + [ret retain]; } if (value != NULL) CFRelease (value); @@ -595,7 +596,7 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { CFPropertyListRef value; float ret = def; - value = [self prefs_get:key]; + value = [self prefs_get_copy:key]; if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID () @@ -613,7 +614,7 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { CFPropertyListRef value; int ret = def; - value = [self prefs_get:key]; + value = [self prefs_get_copy:key]; if (value != NULL) { if (CFGetTypeID (value) == CFNumberGetTypeID ()) @@ -637,7 +638,7 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { NSArray *ret = nil; CFPropertyListRef value; - value = [self prefs_get:key]; + value = [self prefs_get_copy:key]; if (value != NULL) { if (CFGetTypeID (value) == CFArrayGetTypeID ()) @@ -757,7 +758,7 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { NSURL *url = [self prefs_copy_url:@PREFS_UPDATE_FEED default:nil]; if(url) { [[SUUpdater sharedUpdater] setFeedURL:url]; - CFRelease(url); + [url release]; } #endif } @@ -970,6 +971,7 @@ void X11ApplicationMain (int argc, char **argv, char **envp) { // [[SUUpdater sharedUpdater] checkForUpdates:X11App]; #endif + [pool release]; [NSApp run]; /* not reached */ } diff --git a/xorg-server/hw/xquartz/darwinXinput.c b/xorg-server/hw/xquartz/darwinXinput.c index 43aea6140..90e440e54 100644 --- a/xorg-server/hw/xquartz/darwinXinput.c +++ b/xorg-server/hw/xquartz/darwinXinput.c @@ -249,3 +249,9 @@ DeleteInputDeviceRequest(DeviceIntPtr dev) { DEBUG_LOG("DeleteInputDeviceRequest(%p)\n", dev); } + +void +CloseInput (void) +{ +} + diff --git a/xorg-server/hw/xquartz/mach-startup/bundle-main.c b/xorg-server/hw/xquartz/mach-startup/bundle-main.c index 0366f3ba2..4872ff59b 100644 --- a/xorg-server/hw/xquartz/mach-startup/bundle-main.c +++ b/xorg-server/hw/xquartz/mach-startup/bundle-main.c @@ -641,30 +641,46 @@ static int execute(const char *command) { static char *command_from_prefs(const char *key, const char *default_value) { char *command = NULL; - CFStringRef cfKey = CFStringCreateWithCString(NULL, key, kCFStringEncodingASCII); - CFPropertyListRef PlistRef = CFPreferencesCopyAppValue(cfKey, kCFPreferencesCurrentApplication); + CFStringRef cfKey; + CFPropertyListRef PlistRef; + + if(!key) + return NULL; + + cfKey = CFStringCreateWithCString(NULL, key, kCFStringEncodingASCII); + + if(!cfKey) + return NULL; + + PlistRef = CFPreferencesCopyAppValue(cfKey, kCFPreferencesCurrentApplication); if ((PlistRef == NULL) || (CFGetTypeID(PlistRef) != CFStringGetTypeID())) { CFStringRef cfDefaultValue = CFStringCreateWithCString(NULL, default_value, kCFStringEncodingASCII); int len = strlen(default_value) + 1; + if(!cfDefaultValue) + goto command_from_prefs_out; + CFPreferencesSetAppValue(cfKey, cfDefaultValue, kCFPreferencesCurrentApplication); CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); + CFRelease(cfDefaultValue); command = (char *)malloc(len * sizeof(char)); if(!command) - return NULL; + goto command_from_prefs_out; strcpy(command, default_value); } else { int len = CFStringGetLength((CFStringRef)PlistRef) + 1; command = (char *)malloc(len * sizeof(char)); if(!command) - return NULL; + goto command_from_prefs_out; CFStringGetCString((CFStringRef)PlistRef, command, len, kCFStringEncodingASCII); - } - + } + +command_from_prefs_out: if (PlistRef) CFRelease(PlistRef); - + if(cfKey) + CFRelease(cfKey); return command; } diff --git a/xorg-server/hw/xquartz/mach-startup/stub.c b/xorg-server/hw/xquartz/mach-startup/stub.c index 89f9e1058..ccf5ab426 100644 --- a/xorg-server/hw/xquartz/mach-startup/stub.c +++ b/xorg-server/hw/xquartz/mach-startup/stub.c @@ -73,7 +73,6 @@ static void set_x11_path(void) { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 CFURLRef appURL = NULL; - CFBundleRef bundle = NULL; OSStatus osstatus = LSFindApplicationForInfo(kLSUnknownCreator, CFSTR(kX11AppBundleId), nil, nil, &appURL); switch (osstatus) { @@ -84,12 +83,6 @@ static void set_x11_path(void) { exit(1); } - bundle = CFBundleCreate(NULL, appURL); - if(!bundle) { - fprintf(stderr, "Xquartz: Null value returned from CFBundleCreate().\n"); - exit(2); - } - if (!CFURLGetFileSystemRepresentation(appURL, true, (unsigned char *)x11_path, sizeof(x11_path))) { fprintf(stderr, "Xquartz: Error resolving URL for %s\n", kX11AppBundleId); exit(3); diff --git a/xorg-server/hw/xquartz/pbproxy/x-selection.h b/xorg-server/hw/xquartz/pbproxy/x-selection.h index fc903d0af..614c8b091 100644 --- a/xorg-server/hw/xquartz/pbproxy/x-selection.h +++ b/xorg-server/hw/xquartz/pbproxy/x-selection.h @@ -58,15 +58,6 @@ struct atom_list { /* The unmapped window we use for fetching selections. */ Window _selection_window; - /* Last time we declared anything on the pasteboard. */ - int _my_last_change; - - /* Name of the selection we're proxying onto the pasteboard. */ - Atom _proxied_selection; - - /* When true, we're expecting a SelectionNotify event. */ - unsigned int _pending_notify :1; - Atom request_atom; struct { diff --git a/xorg-server/hw/xquartz/quartzAudio.c b/xorg-server/hw/xquartz/quartzAudio.c index af63d18f5..708202b5b 100644 --- a/xorg-server/hw/xquartz/quartzAudio.c +++ b/xorg-server/hw/xquartz/quartzAudio.c @@ -62,7 +62,6 @@ typedef struct QuartzAudioRec { UInt32 curFrame; UInt32 remainingFrames; UInt32 totalFrames; - UInt32 bytesPerFrame; double sampleRate; UInt32 fadeLength; @@ -117,9 +116,9 @@ static void QuartzFillBuffer( unsigned int bufferFrameCount; float multiplier, v; int i; - + buffer = (float *)audiobuffer->mData; - bufferFrameCount = audiobuffer->mDataByteSize / data->bytesPerFrame; + bufferFrameCount = audiobuffer->mDataByteSize / (sizeof(float) * audiobuffer->mNumberChannels); frameCount = min(bufferFrameCount, data->remainingFrames); @@ -141,7 +140,7 @@ static void QuartzFillBuffer( data->prevFrame = 0; // adjust for space eaten by prev fade - buffer += audiobuffer->mNumberChannels*frame; + b += audiobuffer->mNumberChannels*frame; bufferFrameCount -= frame; frameCount = min(bufferFrameCount, data->remainingFrames); } @@ -204,6 +203,8 @@ QuartzAudioIOProc( if (wasPlaying && !data->playing) { OSStatus err; err = AudioDeviceStop(inDevice, QuartzAudioIOProc); + if(err != noErr) + fprintf(stderr, "Error stopping audio device: %ld\n", (long int)err); } pthread_mutex_unlock(&data->lock); return 0; @@ -262,16 +263,17 @@ void QuartzAudioInit(void) UInt32 propertySize; OSStatus status; AudioDeviceID outputDevice; - AudioStreamBasicDescription outputStreamDescription; double sampleRate; - + AudioObjectPropertyAddress devicePropertyAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + AudioObjectPropertyAddress sampleRatePropertyAddress = { kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; + // Get the default output device propertySize = sizeof(outputDevice); - status = AudioHardwareGetProperty( - kAudioHardwarePropertyDefaultOutputDevice, - &propertySize, &outputDevice); + status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &devicePropertyAddress, + 0, NULL, + &propertySize, &outputDevice); if (status) { - ErrorF("QuartzAudioInit: AudioHardwareGetProperty returned %ld\n", + ErrorF("QuartzAudioInit: AudioObjectGetPropertyData(output device) returned %ld\n", (long)status); return; } @@ -281,23 +283,22 @@ void QuartzAudioInit(void) } // Get the basic device description - propertySize = sizeof(outputStreamDescription); - status = AudioDeviceGetProperty(outputDevice, 0, FALSE, - kAudioDevicePropertyStreamFormat, - &propertySize, &outputStreamDescription); + sampleRate = 0.; + propertySize = sizeof(sampleRate); + status = AudioObjectGetPropertyData(outputDevice, &sampleRatePropertyAddress, + 0, NULL, + &propertySize, &sampleRate); if (status) { - ErrorF("QuartzAudioInit: GetProperty(stream format) returned %ld\n", + ErrorF("QuartzAudioInit: AudioObjectGetPropertyData(sample rate) returned %ld\n", (long)status); return; } - sampleRate = outputStreamDescription.mSampleRate; // Fill in the playback data data.frequency = 0; data.amplitude = 0; data.curFrame = 0; data.remainingFrames = 0; - data.bytesPerFrame = outputStreamDescription.mBytesPerFrame; data.sampleRate = sampleRate; // data.bufferByteCount = bufferByteCount; data.playing = FALSE; diff --git a/xorg-server/hw/xquartz/quartzKeyboard.c b/xorg-server/hw/xquartz/quartzKeyboard.c index 96b5fa5b6..3b4eac31c 100644 --- a/xorg-server/hw/xquartz/quartzKeyboard.c +++ b/xorg-server/hw/xquartz/quartzKeyboard.c @@ -368,7 +368,7 @@ void DarwinKeyboardReloadHandler(void) { KeySymsRec keySyms; CFIndex initialKeyRepeatValue, keyRepeatValue; BOOL ok; - DeviceIntPtr pDev = darwinKeyboard; + DeviceIntPtr pDev; const char *xmodmap = PROJECTROOT "/bin/xmodmap"; const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap"; const char *homedir = getenv("HOME"); diff --git a/xorg-server/include/dix-config.h.in b/xorg-server/include/dix-config.h.in index 7907b0a25..058c8fd14 100644 --- a/xorg-server/include/dix-config.h.in +++ b/xorg-server/include/dix-config.h.in @@ -1,451 +1,449 @@ -/* dix-config.h.in: not at all generated. -*- c -*- */ - -#ifndef _DIX_CONFIG_H_ -#define _DIX_CONFIG_H_ - -/* Support BigRequests extension */ -#undef BIGREQS - -/* Builder address */ -#undef BUILDERADDR - -/* Operating System Name */ -#undef OSNAME - -/* Operating System Vendor */ -#undef OSVENDOR - -/* Builder string */ -#undef BUILDERSTRING - -/* Default font path */ -#undef COMPILEDDEFAULTFONTPATH - -/* Miscellaneous server configuration files path */ -#undef SERVER_MISC_CONFIG_PATH - -/* Support Composite Extension */ -#undef COMPOSITE - -/* Support Damage extension */ -#undef DAMAGE - -/* Build for darwin with Quartz support */ -#undef DARWIN_WITH_QUARTZ - -/* Use OsVendorVErrorF */ -#undef DDXOSVERRORF - -/* Use ddxBeforeReset */ -#undef DDXBEFORERESET - -/* Build DPMS extension */ -#undef DPMSExtension - -/* Build GLX extension */ -#undef GLXEXT - -/* Build GLX DRI loader */ -#undef GLX_DRI - -/* Path to DRI drivers */ -#undef DRI_DRIVER_PATH - -/* Support XDM-AUTH*-1 */ -#undef HASXDMAUTH - -/* Define to 1 if you have the `getdtablesize' function. */ -#undef HAS_GETDTABLESIZE - -/* Define to 1 if you have the `getifaddrs' function. */ -#undef HAS_GETIFADDRS - -/* Define to 1 if you have the `getpeereid' function. */ -#undef HAS_GETPEEREID - -/* Define to 1 if you have the `getpeerucred' function. */ -#undef HAS_GETPEERUCRED - -/* Define to 1 if you have the `mmap' function. */ -#undef HAS_MMAP - -/* Support SHM */ -#undef HAS_SHM - -/* Have the 'strlcpy' function */ -#undef HAS_STRLCPY - -/* Define to 1 if you have the header file. */ -#undef HAVE_ASM_MTRR_H - -/* Has backtrace support */ -#undef HAVE_BACKTRACE - -/* Define to 1 if you have the header file. */ -#undef HAVE_BYTESWAP_H - -/* Define to 1 if you have cbrt */ -#undef HAVE_CBRT - -/* Define to 1 if you have the header file. */ -#undef HAVE_DBM_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_DIRENT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -#undef HAVE_DOPRNT - -/* Have execinfo.h */ -#undef HAVE_EXECINFO_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_FCNTL_H - -/* Define to 1 if you have the `geteuid' function. */ -#undef HAVE_GETEUID - -/* Define to 1 if you have the `getisax' function. */ -#undef HAVE_GETISAX - -/* Define to 1 if you have the `getuid' function. */ -#undef HAVE_GETUID - -/* Define to 1 if you have the `getzoneid' function. */ -#undef HAVE_GETZONEID - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Have Quartz */ -#undef XQUARTZ - -/* Support application updating through sparkle. */ -#undef XQUARTZ_SPARKLE - -/* Prefix to use for launchd identifiers */ -#undef LAUNCHD_ID_PREFIX - -/* Build a standalone xpbproxy */ -#undef STANDALONE_XPBPROXY - -/* Define to 1 if you have the `m' library (-lm). */ -#undef HAVE_LIBM - -/* Define to 1 if you have the `link' function. */ -#undef HAVE_LINK - -/* Define to 1 if you have the header file. */ -#undef HAVE_LINUX_AGPGART_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_LINUX_APM_BIOS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_LINUX_FB_H - -/* Define to 1 if you have the `mkstemp' function. */ -#undef HAVE_MKSTEMP - -/* Define to 1 if you have the header file. */ -#undef HAVE_NDBM_H - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_RPCSVC_DBM_H - -/* Define to use libc SHA1 functions */ -#undef HAVE_SHA1_IN_LIBC - -/* Define to use CommonCrypto SHA1 functions */ -#undef HAVE_SHA1_IN_COMMONCRYPTO - -/* Define to use libmd SHA1 functions */ -#undef HAVE_SHA1_IN_LIBMD - -/* Define to use libgcrypt SHA1 functions */ -#undef HAVE_SHA1_IN_LIBGCRYPT - -/* Define to use libsha1 for SHA1 */ -#undef HAVE_SHA1_IN_LIBSHA1 - -/* Define to 1 if you have the `shmctl64' function. */ -#undef HAVE_SHMCTL64 - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strchr' function. */ -#undef HAVE_STRCHR - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the `strrchr' function. */ -#undef HAVE_STRRCHR - -/* Define to 1 if you have the `strtol' function. */ -#undef HAVE_STRTOL - -/* Define to 1 if SYSV IPC is available */ -#undef HAVE_SYSV_IPC - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_AGPIO_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_DIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_IO_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_VM86_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_TSLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_FNMATCH_H - -/* Have /dev/urandom */ -#undef HAVE_URANDOM - -/* Define to 1 if you have the `vprintf' function. */ -#undef HAVE_VPRINTF - -/* Support IPv6 for TCP connections */ -#undef IPv6 - -/* Support os-specific local connections */ -#undef LOCALCONN - -/* Support MIT-SHM Extension */ -#undef MITSHM - -/* Enable some debugging code */ -#undef DEBUG - -/* Name of package */ -#undef PACKAGE - -/* Internal define for Xinerama */ -#undef PANORAMIX - -/* Overall prefix */ -#undef PROJECTROOT - -/* Support RANDR extension */ -#undef RANDR - -/* Support Record extension */ -#undef XRECORD - -/* Support RENDER extension */ -#undef RENDER - -/* Support X resource extension */ -#undef RES - -/* Support MIT-SCREEN-SAVER extension */ -#undef SCREENSAVER - -/* Support Secure RPC ("SUN-DES-1") authentication for X11 clients */ -#undef SECURE_RPC - -/* Support SHAPE extension */ -#undef SHAPE - -/* Define to 1 on systems derived from System V Release 4 */ -#undef SVR4 - -/* Support TCP socket connections */ -#undef TCPCONN - -/* Enable touchscreen support */ -#undef TOUCHSCREEN - -/* Support tslib touchscreen abstraction library */ -#undef TSLIB - -/* Support UNIX socket connections */ -#undef UNIXCONN - -/* Define to use byteswap macros from */ -#undef USE_SYS_ENDIAN_H - -/* unaligned word accesses behave as expected */ -#undef WORKING_UNALIGNED_INT - -/* Build X string registry */ -#undef XREGISTRY - -/* Build X-ACE extension */ -#undef XACE - -/* Build SELinux extension */ -#undef XSELINUX - -/* Support XCMisc extension */ -#undef XCMISC - -/* Build Security extension */ -#undef XCSECURITY - -/* Support Xdmcp */ -#undef XDMCP - -/* Build XFree86 BigFont extension */ -#undef XF86BIGFONT - -/* Support XFree86 Video Mode extension */ -#undef XF86VIDMODE - -/* Support XFixes extension */ -#undef XFIXES - -/* Build XDGA support */ -#undef XFreeXDGA - -/* Support Xinerama extension */ -#undef XINERAMA - -/* Vendor release */ -#undef XORG_RELEASE - -/* Current Xorg version */ -#undef XORG_VERSION_CURRENT - -/* Xorg release date */ -#undef XORG_DATE - -/* Build Xv Extension */ -#undef XvExtension - -/* Build XvMC Extension */ -#undef XvMCExtension - -/* Support XSync extension */ -#undef XSYNC - -/* Support XTest extension */ -#undef XTEST - -/* Support Xv extension */ -#undef XV - -/* Build Multibuffer extension */ -#undef MULTIBUFFER - -/* Support DRI extension */ -#undef XF86DRI - -/* Build DRI2 extension */ -#undef DRI2 - -/* Build DBE support */ -#undef DBE - -/* Vendor name */ -#undef XVENDORNAME - -/* Enable GNU and other extensions to the C environment for GLIBC */ -#undef _GNU_SOURCE - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `int' if does not define. */ -#undef pid_t - -/* Build Rootless code */ -#undef ROOTLESS - -/* Define to 1 if unsigned long is 64 bits. */ -#undef _XSERVER64 - -/* System is BSD-like */ -#undef CSRG_BASED - -/* Define to 1 if `struct sockaddr_in' has a `sin_len' member */ -#undef BSD44SOCKETS - -/* Support D-Bus */ -#undef HAVE_DBUS - -/* Use libudev for input hotplug */ -#undef CONFIG_UDEV - -/* Use D-Bus for input hotplug */ -#undef CONFIG_NEED_DBUS - -/* Support the D-Bus hotplug API */ -#undef CONFIG_DBUS_API - -/* Support HAL for hotplug */ -#undef CONFIG_HAL - -/* Use only built-in fonts */ -#undef BUILTIN_FONTS - -/* Have a monotonic clock from clock_gettime() */ -#undef MONOTONIC_CLOCK - -/* Define to 1 if the DTrace Xserver provider probes should be built in */ -#undef XSERVER_DTRACE - -/* Define to 16-bit byteswap macro */ -#undef bswap_16 - -/* Define to 32-bit byteswap macro */ -#undef bswap_32 - -/* Define to 64-bit byteswap macro */ -#undef bswap_64 - -/* Need the strcasecmp function. */ -#undef NEED_STRCASECMP - -/* Need the strncasecmp function. */ -#undef NEED_STRNCASECMP - -/* Need the strcasestr function. */ -#undef NEED_STRCASESTR - -/* Define to 1 if you have the `ffs' function. */ -#undef HAVE_FFS - -/* Correctly set _XSERVER64 for OSX fat binaries */ -#ifdef __APPLE__ -#include "dix-config-apple-verbatim.h" -#endif - -#undef HAVE_AVC_NETLINK_ACQUIRE_FD - -#endif /* _DIX_CONFIG_H_ */ +/* dix-config.h.in: not at all generated. -*- c -*- */ + +#ifndef _DIX_CONFIG_H_ +#define _DIX_CONFIG_H_ + +/* Support BigRequests extension */ +#undef BIGREQS + +/* Builder address */ +#undef BUILDERADDR + +/* Operating System Name */ +#undef OSNAME + +/* Operating System Vendor */ +#undef OSVENDOR + +/* Builder string */ +#undef BUILDERSTRING + +/* Default font path */ +#undef COMPILEDDEFAULTFONTPATH + +/* Miscellaneous server configuration files path */ +#undef SERVER_MISC_CONFIG_PATH + +/* Support Composite Extension */ +#undef COMPOSITE + +/* Support Damage extension */ +#undef DAMAGE + +/* Build for darwin with Quartz support */ +#undef DARWIN_WITH_QUARTZ + +/* Use OsVendorVErrorF */ +#undef DDXOSVERRORF + +/* Use ddxBeforeReset */ +#undef DDXBEFORERESET + +/* Build DPMS extension */ +#undef DPMSExtension + +/* Build GLX extension */ +#undef GLXEXT + +/* Build GLX DRI loader */ +#undef GLX_DRI + +/* Path to DRI drivers */ +#undef DRI_DRIVER_PATH + +/* Support XDM-AUTH*-1 */ +#undef HASXDMAUTH + +/* Define to 1 if you have the `getdtablesize' function. */ +#undef HAS_GETDTABLESIZE + +/* Define to 1 if you have the `getifaddrs' function. */ +#undef HAS_GETIFADDRS + +/* Define to 1 if you have the `getpeereid' function. */ +#undef HAS_GETPEEREID + +/* Define to 1 if you have the `getpeerucred' function. */ +#undef HAS_GETPEERUCRED + +/* Define to 1 if you have the `mmap' function. */ +#undef HAS_MMAP + +/* Support SHM */ +#undef HAS_SHM + +/* Have the 'strlcpy' function */ +#undef HAS_STRLCPY + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASM_MTRR_H + +/* Has backtrace support */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H + +/* Define to 1 if you have cbrt */ +#undef HAVE_CBRT + +/* Define to 1 if you have the header file. */ +#undef HAVE_DBM_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Have execinfo.h */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the `getisax' function. */ +#undef HAVE_GETISAX + +/* Define to 1 if you have the `getuid' function. */ +#undef HAVE_GETUID + +/* Define to 1 if you have the `getzoneid' function. */ +#undef HAVE_GETZONEID + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Have Quartz */ +#undef XQUARTZ + +/* Support application updating through sparkle. */ +#undef XQUARTZ_SPARKLE + +/* Prefix to use for launchd identifiers */ +#undef LAUNCHD_ID_PREFIX + +/* Build a standalone xpbproxy */ +#undef STANDALONE_XPBPROXY + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `link' function. */ +#undef HAVE_LINK + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_AGPGART_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_APM_BIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_FB_H + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_NDBM_H + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_RPCSVC_DBM_H + +/* Define to use libc SHA1 functions */ +#undef HAVE_SHA1_IN_LIBC + +/* Define to use CommonCrypto SHA1 functions */ +#undef HAVE_SHA1_IN_COMMONCRYPTO + +/* Define to use libmd SHA1 functions */ +#undef HAVE_SHA1_IN_LIBMD + +/* Define to use libgcrypt SHA1 functions */ +#undef HAVE_SHA1_IN_LIBGCRYPT + +/* Define to use libsha1 for SHA1 */ +#undef HAVE_SHA1_IN_LIBSHA1 + +/* Define to 1 if you have the `shmctl64' function. */ +#undef HAVE_SHMCTL64 + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if SYSV IPC is available */ +#undef HAVE_SYSV_IPC + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_AGPIO_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IO_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_VM86_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TSLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FNMATCH_H + +/* Have /dev/urandom */ +#undef HAVE_URANDOM + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Support IPv6 for TCP connections */ +#undef IPv6 + +/* Support os-specific local connections */ +#undef LOCALCONN + +/* Support MIT-SHM Extension */ +#undef MITSHM + +/* Enable some debugging code */ +#undef DEBUG + +/* Name of package */ +#undef PACKAGE + +/* Internal define for Xinerama */ +#undef PANORAMIX + +/* Overall prefix */ +#undef PROJECTROOT + +/* Support RANDR extension */ +#undef RANDR + +/* Support Record extension */ +#undef XRECORD + +/* Support RENDER extension */ +#undef RENDER + +/* Support X resource extension */ +#undef RES + +/* Support MIT-SCREEN-SAVER extension */ +#undef SCREENSAVER + +/* Support Secure RPC ("SUN-DES-1") authentication for X11 clients */ +#undef SECURE_RPC + +/* Support SHAPE extension */ +#undef SHAPE + +/* Define to 1 on systems derived from System V Release 4 */ +#undef SVR4 + +/* Support TCP socket connections */ +#undef TCPCONN + +/* Enable touchscreen support */ +#undef TOUCHSCREEN + +/* Support tslib touchscreen abstraction library */ +#undef TSLIB + +/* Support UNIX socket connections */ +#undef UNIXCONN + +/* Define to use byteswap macros from */ +#undef USE_SYS_ENDIAN_H + +/* unaligned word accesses behave as expected */ +#undef WORKING_UNALIGNED_INT + +/* Build X string registry */ +#undef XREGISTRY + +/* Build X-ACE extension */ +#undef XACE + +/* Build SELinux extension */ +#undef XSELINUX + +/* Support XCMisc extension */ +#undef XCMISC + +/* Build Security extension */ +#undef XCSECURITY + +/* Support Xdmcp */ +#undef XDMCP + +/* Build XFree86 BigFont extension */ +#undef XF86BIGFONT + +/* Support XFree86 Video Mode extension */ +#undef XF86VIDMODE + +/* Support XFixes extension */ +#undef XFIXES + +/* Build XDGA support */ +#undef XFreeXDGA + +/* Support Xinerama extension */ +#undef XINERAMA + +/* Vendor release */ +#undef XORG_RELEASE + +/* Current Xorg version */ +#undef XORG_VERSION_CURRENT + +/* Xorg release date */ +#undef XORG_DATE + +/* Build Xv Extension */ +#undef XvExtension + +/* Build XvMC Extension */ +#undef XvMCExtension + +/* Support XSync extension */ +#undef XSYNC + +/* Support XTest extension */ +#undef XTEST + +/* Support Xv extension */ +#undef XV + +/* Build Multibuffer extension */ +#undef MULTIBUFFER + +/* Support DRI extension */ +#undef XF86DRI + +/* Build DRI2 extension */ +#undef DRI2 + +/* Build DBE support */ +#undef DBE + +/* Vendor name */ +#undef XVENDORNAME + +/* Enable GNU and other extensions to the C environment for GLIBC */ +#undef _GNU_SOURCE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Build Rootless code */ +#undef ROOTLESS + +/* Define to 1 if unsigned long is 64 bits. */ +#undef _XSERVER64 + +/* System is BSD-like */ +#undef CSRG_BASED + +/* Define to 1 if `struct sockaddr_in' has a `sin_len' member */ +#undef BSD44SOCKETS + +/* Support D-Bus */ +#undef HAVE_DBUS + +/* Use libudev for input hotplug */ +#undef CONFIG_UDEV + +/* Use D-Bus for input hotplug */ +#undef CONFIG_NEED_DBUS + +/* Support the D-Bus hotplug API */ +#undef CONFIG_DBUS_API + +/* Support HAL for hotplug */ +#undef CONFIG_HAL + +/* Use only built-in fonts */ +#undef BUILTIN_FONTS + +/* Have a monotonic clock from clock_gettime() */ +#undef MONOTONIC_CLOCK + +/* Define to 1 if the DTrace Xserver provider probes should be built in */ +#undef XSERVER_DTRACE + +/* Define to 16-bit byteswap macro */ +#undef bswap_16 + +/* Define to 32-bit byteswap macro */ +#undef bswap_32 + +/* Define to 64-bit byteswap macro */ +#undef bswap_64 + +/* Need the strcasecmp function. */ +#undef NEED_STRCASECMP + +/* Need the strncasecmp function. */ +#undef NEED_STRNCASECMP + +/* Need the strcasestr function. */ +#undef NEED_STRCASESTR + +/* Define to 1 if you have the `ffs' function. */ +#undef HAVE_FFS + +/* Correctly set _XSERVER64 for OSX fat binaries */ +#ifdef __APPLE__ +#include "dix-config-apple-verbatim.h" +#endif + +#endif /* _DIX_CONFIG_H_ */ diff --git a/xorg-server/include/dix.h b/xorg-server/include/dix.h index ed3acb6c4..6505fd02f 100644 --- a/xorg-server/include/dix.h +++ b/xorg-server/include/dix.h @@ -576,8 +576,8 @@ typedef struct { extern _X_EXPORT CallbackListPtr DeviceEventCallback; typedef struct { - xEventPtr events; - int count; + InternalEvent *event; + DeviceIntPtr device; } DeviceEventInfoRec; extern int XItoCoreType(int xi_type); @@ -585,7 +585,7 @@ extern Bool DevHasCursor(DeviceIntPtr pDev); extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev); extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev); extern Bool IsPointerEvent(InternalEvent *event); -extern Bool IsMaster(DeviceIntPtr dev); +extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev); extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what); diff --git a/xorg-server/include/eventconvert.h b/xorg-server/include/eventconvert.h index 277a6c4b8..b1196a00e 100644 --- a/xorg-server/include/eventconvert.h +++ b/xorg-server/include/eventconvert.h @@ -30,9 +30,9 @@ #define FP1616(integral, frac) ((integral) * (1 << 16) + (frac) * (1 << 16)) -_X_INTERNAL int EventToCore(InternalEvent *event, xEvent *core); -_X_INTERNAL int EventToXI(InternalEvent *ev, xEvent **xi, int *count); -_X_INTERNAL int EventToXI2(InternalEvent *ev, xEvent **xi); +_X_EXPORT int EventToCore(InternalEvent *event, xEvent *core); +_X_EXPORT int EventToXI(InternalEvent *ev, xEvent **xi, int *count); +_X_EXPORT int EventToXI2(InternalEvent *ev, xEvent **xi); _X_INTERNAL int GetCoreType(InternalEvent* ev); _X_INTERNAL int GetXIType(InternalEvent* ev); _X_INTERNAL int GetXI2Type(InternalEvent* ev); diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h index dad1af787..453ab82c7 100644 --- a/xorg-server/include/os.h +++ b/xorg-server/include/os.h @@ -262,6 +262,8 @@ extern _X_EXPORT void OsBlockSignals (void); extern _X_EXPORT void OsReleaseSignals (void); +extern _X_EXPORT void OsAbort (void); + #if !defined(WIN32) extern _X_EXPORT int System(char *); extern _X_EXPORT pointer Popen(char *, char *); diff --git a/xorg-server/miext/damage/damage.c b/xorg-server/miext/damage/damage.c index b7ec92a5b..2851aed8d 100644 --- a/xorg-server/miext/damage/damage.c +++ b/xorg-server/miext/damage/damage.c @@ -1705,7 +1705,7 @@ damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage) } #if DAMAGE_VALIDATE_ENABLE ErrorF ("Damage not on list\n"); - abort (); + OsAbort (); #endif } @@ -1718,7 +1718,7 @@ damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage) for (pOld = *pPrev; pOld; pOld = pOld->pNext) if (pOld == pDamage) { ErrorF ("Damage already on list\n"); - abort (); + OsAbort (); } #endif pDamage->pNext = *pPrev; @@ -1971,7 +1971,7 @@ DamageRegister (DrawablePtr pDrawable, if (pDrawable->pScreen != pDamage->pScreen) { ErrorF ("DamageRegister called with mismatched screens\n"); - abort (); + OsAbort (); } #endif @@ -1986,7 +1986,7 @@ DamageRegister (DrawablePtr pDrawable, for (pOld = *pPrev; pOld; pOld = pOld->pNextWin) if (pOld == pDamage) { ErrorF ("Damage already on window list\n"); - abort (); + OsAbort (); } #endif pDamage->pNextWin = *pPrev; @@ -2040,7 +2040,7 @@ DamageUnregister (DrawablePtr pDrawable, #if DAMAGE_VALIDATE_ENABLE if (!found) { ErrorF ("Damage not on window list\n"); - abort (); + OsAbort (); } #endif } diff --git a/xorg-server/miext/rootless/rootlessWindow.c b/xorg-server/miext/rootless/rootlessWindow.c index 53209565d..e78e2c8f1 100644 --- a/xorg-server/miext/rootless/rootlessWindow.c +++ b/xorg-server/miext/rootless/rootlessWindow.c @@ -978,7 +978,7 @@ StartFrameResize(WindowPtr pWin, Bool gravity, copy_rect.y2 = oldY2; } else - abort(); + OsAbort(); Bpp = winRec->win->drawable.bitsPerPixel / 8; copy_rect_width = copy_rect.x2 - copy_rect.x1; diff --git a/xorg-server/os/log.c b/xorg-server/os/log.c index 20cd74af6..0002e59f0 100644 --- a/xorg-server/os/log.c +++ b/xorg-server/os/log.c @@ -1,603 +1,603 @@ -/* - -Copyright 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, -Copyright 1994 Quarterdeck Office Systems. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Digital and -Quarterdeck not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT -OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE -OR PERFORMANCE OF THIS SOFTWARE. - -*/ - -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include /* for malloc() */ -#include - -#include "input.h" -#include "site.h" -#include "opaque.h" - -#ifdef WIN32 -#include -#define getpid(x) _getpid(x) -#endif - -#ifdef XF86BIGFONT -#define _XF86BIGFONT_SERVER_ -#include -#endif - -#ifdef DDXOSVERRORF -void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL; -#endif - -static FILE *logFile = NULL; -static Bool logFlush = FALSE; -static Bool logSync = FALSE; -static int logVerbosity = DEFAULT_LOG_VERBOSITY; -static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY; - -/* Buffer to information logged before the log file is opened. */ -static char *saveBuffer = NULL; -static int bufferSize = 0, bufferUnused = 0, bufferPos = 0; -static Bool needBuffer = TRUE; - -/* Prefix strings for log messages. */ -#ifndef X_UNKNOWN_STRING -#define X_UNKNOWN_STRING "(\?\?)" -#endif -#ifndef X_PROBE_STRING -#define X_PROBE_STRING "(--)" -#endif -#ifndef X_CONFIG_STRING -#define X_CONFIG_STRING "(**)" -#endif -#ifndef X_DEFAULT_STRING -#define X_DEFAULT_STRING "(==)" -#endif -#ifndef X_CMDLINE_STRING -#define X_CMDLINE_STRING "(++)" -#endif -#ifndef X_NOTICE_STRING -#define X_NOTICE_STRING "(!!)" -#endif -#ifndef X_ERROR_STRING -#define X_ERROR_STRING "(EE)" -#endif -#ifndef X_WARNING_STRING -#define X_WARNING_STRING "(WW)" -#endif -#ifndef X_INFO_STRING -#define X_INFO_STRING "(II)" -#endif -#ifndef X_NOT_IMPLEMENTED_STRING -#define X_NOT_IMPLEMENTED_STRING "(NI)" -#endif - -/* - * LogInit is called to start logging to a file. It is also called (with - * NULL arguments) when logging to a file is not wanted. It must always be - * called, otherwise log messages will continue to accumulate in a buffer. - * - * %s, if present in the fname or backup strings, is expanded to the display - * string. - */ - -const char * -LogInit(const char *fname, const char *backup) -{ - char *logFileName = NULL; - - if (fname && *fname) { - /* xalloc() can't be used yet. */ - logFileName = malloc(strlen(fname) + strlen(display) + 1); - if (!logFileName) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(logFileName, fname, display); - - if (backup && *backup) { - struct stat buf; - - if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { - char *suffix; - char *oldLog; - - oldLog = malloc(strlen(logFileName) + strlen(backup) + - strlen(display) + 1); - suffix = malloc(strlen(backup) + strlen(display) + 1); - if (!oldLog || !suffix) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(suffix, backup, display); - sprintf(oldLog, "%s%s", logFileName, suffix); - free(suffix); - if (rename(logFileName, oldLog) == -1) { - FatalError("Cannot move old log file \"%s\" to \"%s\"\n", - logFileName, oldLog); - } - free(oldLog); - } - } - if ((logFile = fopen(logFileName, "w")) == NULL) - FatalError("Cannot open log file \"%s\"\n", logFileName); - setvbuf(logFile, NULL, _IONBF, 0); - - /* Flush saved log information. */ - if (saveBuffer && bufferSize > 0) { - fwrite(saveBuffer, bufferPos, 1, logFile); - fflush(logFile); -#ifndef WIN32 - fsync(fileno(logFile)); -#endif - } - } - - /* - * Unconditionally free the buffer, and flag that the buffer is no longer - * needed. - */ - if (saveBuffer && bufferSize > 0) { - free(saveBuffer); /* Must be free(), not xfree() */ - saveBuffer = NULL; - bufferSize = 0; - } - needBuffer = FALSE; - - return logFileName; -} - -void -LogClose(void) -{ - if (logFile) { - fclose(logFile); - logFile = NULL; - } -} - -Bool -LogSetParameter(LogParameter param, int value) -{ - switch (param) { - case XLOG_FLUSH: - logFlush = value ? TRUE : FALSE; - return TRUE; - case XLOG_SYNC: - logSync = value ? TRUE : FALSE; - return TRUE; - case XLOG_VERBOSITY: - logVerbosity = value; - return TRUE; - case XLOG_FILE_VERBOSITY: - logFileVerbosity = value; - return TRUE; - default: - return FALSE; - } -} - -/* This function does the actual log message writes. */ - -void -LogVWrite(int verb, const char *f, va_list args) -{ - static char tmpBuffer[1024]; - int len = 0; - static Bool newline = TRUE; - - if (newline) { - sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0); - len = strlen(tmpBuffer); - if (logFile) - fwrite(tmpBuffer, len, 1, logFile); - } - - /* - * Since a va_list can only be processed once, write the string to a - * buffer, and then write the buffer out to the appropriate output - * stream(s). - */ - if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) { - vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args); - len = strlen(tmpBuffer); - } - newline = (tmpBuffer[len-1] == '\n'); - if ((verb < 0 || logVerbosity >= verb) && len > 0) - fwrite(tmpBuffer, len, 1, stderr); - if ((verb < 0 || logFileVerbosity >= verb) && len > 0) { - if (logFile) { - fwrite(tmpBuffer, len, 1, logFile); - if (logFlush) { - fflush(logFile); -#ifndef WIN32 - if (logSync) - fsync(fileno(logFile)); -#endif - } - } else if (needBuffer) { - /* - * Note, this code is used before OsInit() has been called, so - * xalloc() and friends can't be used. - */ - if (len > bufferUnused) { - bufferSize += 1024; - bufferUnused += 1024; - if (saveBuffer) - saveBuffer = realloc(saveBuffer, bufferSize); - else - saveBuffer = malloc(bufferSize); - if (!saveBuffer) - FatalError("realloc() failed while saving log messages\n"); - } - bufferUnused -= len; - memcpy(saveBuffer + bufferPos, tmpBuffer, len); - bufferPos += len; - } - } -} - -void -LogWrite(int verb, const char *f, ...) -{ - va_list args; - - va_start(args, f); - LogVWrite(verb, f, args); - va_end(args); -} - -void -LogVMessageVerb(MessageType type, int verb, const char *format, va_list args) -{ - const char *s = X_UNKNOWN_STRING; - char tmpBuf[1024]; - - /* Ignore verbosity for X_ERROR */ - if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) { - switch (type) { - case X_PROBED: - s = X_PROBE_STRING; - break; - case X_CONFIG: - s = X_CONFIG_STRING; - break; - case X_DEFAULT: - s = X_DEFAULT_STRING; - break; - case X_CMDLINE: - s = X_CMDLINE_STRING; - break; - case X_NOTICE: - s = X_NOTICE_STRING; - break; - case X_ERROR: - s = X_ERROR_STRING; - if (verb > 0) - verb = 0; - break; - case X_WARNING: - s = X_WARNING_STRING; - break; - case X_INFO: - s = X_INFO_STRING; - break; - case X_NOT_IMPLEMENTED: - s = X_NOT_IMPLEMENTED_STRING; - break; - case X_UNKNOWN: - s = X_UNKNOWN_STRING; - break; - case X_NONE: - s = NULL; - break; - } - - /* if s is not NULL we need a space before format */ - snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "", - s ? " " : "", - format); - LogVWrite(verb, tmpBuf, args); - } -} - -/* Log message with verbosity level specified. */ -void -LogMessageVerb(MessageType type, int verb, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - LogVMessageVerb(type, verb, format, ap); - va_end(ap); -} - -/* Log a message with the standard verbosity level of 1. */ -void -LogMessage(MessageType type, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - LogVMessageVerb(type, 1, format, ap); - va_end(ap); -} - -#ifdef __GNUC__ -void AbortServer(void) __attribute__((noreturn)); -#endif - -void -AbortServer(void) -{ -#ifdef XF86BIGFONT - XF86BigfontCleanup(); -#endif - CloseWellKnownConnections(); - OsCleanup(TRUE); - CloseDownDevices(); - AbortDDX(); - fflush(stderr); - if (CoreDump) - abort(); - exit (1); -} - -#define AUDIT_PREFIX "AUDIT: %s: %ld: " -#ifndef AUDIT_TIMEOUT -#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */ -#endif - -static int nrepeat = 0; -static int oldlen = -1; -static OsTimerPtr auditTimer = NULL; - -void -FreeAuditTimer(void) -{ - if (auditTimer != NULL) { - /* Force output of pending messages */ - TimerForce(auditTimer); - TimerFree(auditTimer); - auditTimer = NULL; - } -} - -static char * -AuditPrefix(void) -{ - time_t tm; - char *autime, *s; - char *tmpBuf; - int len; - - time(&tm); - autime = ctime(&tm); - if ((s = strchr(autime, '\n'))) - *s = '\0'; - len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1; - tmpBuf = malloc(len); - if (!tmpBuf) - return NULL; - snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid()); - return tmpBuf; -} - -void -AuditF(const char * f, ...) -{ - va_list args; - - va_start(args, f); - - VAuditF(f, args); - va_end(args); -} - -static CARD32 -AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg) -{ - char *prefix; - - if (nrepeat > 0) { - prefix = AuditPrefix(); - ErrorF("%slast message repeated %d times\n", - prefix != NULL ? prefix : "", nrepeat); - nrepeat = 0; - if (prefix != NULL) - free(prefix); - return AUDIT_TIMEOUT; - } else { - /* if the timer expires without anything to print, flush the message */ - oldlen = -1; - return 0; - } -} - -void -VAuditF(const char *f, va_list args) -{ - char *prefix; - char buf[1024]; - int len; - static char oldbuf[1024]; - - prefix = AuditPrefix(); - len = vsnprintf(buf, sizeof(buf), f, args); - - if (len == oldlen && strcmp(buf, oldbuf) == 0) { - /* Message already seen */ - nrepeat++; - } else { - /* new message */ - if (auditTimer != NULL) - TimerForce(auditTimer); - ErrorF("%s%s", prefix != NULL ? prefix : "", buf); - strlcpy(oldbuf, buf, sizeof(oldbuf)); - oldlen = len; - nrepeat = 0; - auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL); - } - if (prefix != NULL) - free(prefix); -} - -void -FatalError(const char *f, ...) -{ - va_list args; - static Bool beenhere = FALSE; - - if (beenhere) - ErrorF("\nFatalError re-entered, aborting\n"); - else - ErrorF("\nFatal server error:\n"); - - va_start(args, f); - VErrorF(f, args); - va_end(args); - ErrorF("\n"); - if (!beenhere) - OsVendorFatalError(); - if (!beenhere) { - beenhere = TRUE; - AbortServer(); - } else - abort(); - /*NOTREACHED*/ -} - -void -VErrorF(const char *f, va_list args) -{ -#ifdef DDXOSVERRORF - if (OsVendorVErrorFProc) - OsVendorVErrorFProc(f, args); - else - LogVWrite(-1, f, args); -#else - LogVWrite(-1, f, args); -#endif -} - -void -ErrorF(const char * f, ...) -{ - va_list args; - - va_start(args, f); - VErrorF(f, args); - va_end(args); -} - -/* A perror() workalike. */ - -void -Error(char *str) -{ - char *err = NULL; - int saveErrno = errno; - - if (str) { - err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1); - if (!err) - return; - sprintf(err, "%s: ", str); - strcat(err, strerror(saveErrno)); - LogWrite(-1, "%s", err); - free(err); - } else - LogWrite(-1, "%s", strerror(saveErrno)); -} - -void -LogPrintMarkers(void) -{ - /* Show what the message marker symbols mean. */ - LogWrite(0, "Markers: "); - LogMessageVerb(X_PROBED, 0, "probed, "); - LogMessageVerb(X_CONFIG, 0, "from config file, "); - LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t"); - LogMessageVerb(X_CMDLINE, 0, "from command line, "); - LogMessageVerb(X_NOTICE, 0, "notice, "); - LogMessageVerb(X_INFO, 0, "informational,\n\t"); - LogMessageVerb(X_WARNING, 0, "warning, "); - LogMessageVerb(X_ERROR, 0, "error, "); - LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, "); - LogMessageVerb(X_UNKNOWN, 0, "unknown.\n"); -} - +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, +Copyright 1994 Quarterdeck Office Systems. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital and +Quarterdeck not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT +OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include /* for malloc() */ +#include + +#include "input.h" +#include "site.h" +#include "opaque.h" + +#ifdef WIN32 +#include +#define getpid(x) _getpid(x) +#endif + +#ifdef XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include +#endif + +#ifdef DDXOSVERRORF +void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL; +#endif + +static FILE *logFile = NULL; +static Bool logFlush = FALSE; +static Bool logSync = FALSE; +static int logVerbosity = DEFAULT_LOG_VERBOSITY; +static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY; + +/* Buffer to information logged before the log file is opened. */ +static char *saveBuffer = NULL; +static int bufferSize = 0, bufferUnused = 0, bufferPos = 0; +static Bool needBuffer = TRUE; + +/* Prefix strings for log messages. */ +#ifndef X_UNKNOWN_STRING +#define X_UNKNOWN_STRING "(\?\?)" +#endif +#ifndef X_PROBE_STRING +#define X_PROBE_STRING "(--)" +#endif +#ifndef X_CONFIG_STRING +#define X_CONFIG_STRING "(**)" +#endif +#ifndef X_DEFAULT_STRING +#define X_DEFAULT_STRING "(==)" +#endif +#ifndef X_CMDLINE_STRING +#define X_CMDLINE_STRING "(++)" +#endif +#ifndef X_NOTICE_STRING +#define X_NOTICE_STRING "(!!)" +#endif +#ifndef X_ERROR_STRING +#define X_ERROR_STRING "(EE)" +#endif +#ifndef X_WARNING_STRING +#define X_WARNING_STRING "(WW)" +#endif +#ifndef X_INFO_STRING +#define X_INFO_STRING "(II)" +#endif +#ifndef X_NOT_IMPLEMENTED_STRING +#define X_NOT_IMPLEMENTED_STRING "(NI)" +#endif + +/* + * LogInit is called to start logging to a file. It is also called (with + * NULL arguments) when logging to a file is not wanted. It must always be + * called, otherwise log messages will continue to accumulate in a buffer. + * + * %s, if present in the fname or backup strings, is expanded to the display + * string. + */ + +const char * +LogInit(const char *fname, const char *backup) +{ + char *logFileName = NULL; + + if (fname && *fname) { + /* xalloc() can't be used yet. */ + logFileName = malloc(strlen(fname) + strlen(display) + 1); + if (!logFileName) + FatalError("Cannot allocate space for the log file name\n"); + sprintf(logFileName, fname, display); + + if (backup && *backup) { + struct stat buf; + + if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { + char *suffix; + char *oldLog; + + oldLog = malloc(strlen(logFileName) + strlen(backup) + + strlen(display) + 1); + suffix = malloc(strlen(backup) + strlen(display) + 1); + if (!oldLog || !suffix) + FatalError("Cannot allocate space for the log file name\n"); + sprintf(suffix, backup, display); + sprintf(oldLog, "%s%s", logFileName, suffix); + free(suffix); + if (rename(logFileName, oldLog) == -1) { + FatalError("Cannot move old log file \"%s\" to \"%s\"\n", + logFileName, oldLog); + } + free(oldLog); + } + } + if ((logFile = fopen(logFileName, "w")) == NULL) + FatalError("Cannot open log file \"%s\"\n", logFileName); + setvbuf(logFile, NULL, _IONBF, 0); + + /* Flush saved log information. */ + if (saveBuffer && bufferSize > 0) { + fwrite(saveBuffer, bufferPos, 1, logFile); + fflush(logFile); +#ifndef WIN32 + fsync(fileno(logFile)); +#endif + } + } + + /* + * Unconditionally free the buffer, and flag that the buffer is no longer + * needed. + */ + if (saveBuffer && bufferSize > 0) { + free(saveBuffer); /* Must be free(), not xfree() */ + saveBuffer = NULL; + bufferSize = 0; + } + needBuffer = FALSE; + + return logFileName; +} + +void +LogClose(void) +{ + if (logFile) { + fclose(logFile); + logFile = NULL; + } +} + +Bool +LogSetParameter(LogParameter param, int value) +{ + switch (param) { + case XLOG_FLUSH: + logFlush = value ? TRUE : FALSE; + return TRUE; + case XLOG_SYNC: + logSync = value ? TRUE : FALSE; + return TRUE; + case XLOG_VERBOSITY: + logVerbosity = value; + return TRUE; + case XLOG_FILE_VERBOSITY: + logFileVerbosity = value; + return TRUE; + default: + return FALSE; + } +} + +/* This function does the actual log message writes. */ + +void +LogVWrite(int verb, const char *f, va_list args) +{ + static char tmpBuffer[1024]; + int len = 0; + static Bool newline = TRUE; + + if (newline) { + sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0); + len = strlen(tmpBuffer); + if (logFile) + fwrite(tmpBuffer, len, 1, logFile); + } + + /* + * Since a va_list can only be processed once, write the string to a + * buffer, and then write the buffer out to the appropriate output + * stream(s). + */ + if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) { + vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args); + len = strlen(tmpBuffer); + } + newline = (tmpBuffer[len-1] == '\n'); + if ((verb < 0 || logVerbosity >= verb) && len > 0) + fwrite(tmpBuffer, len, 1, stderr); + if ((verb < 0 || logFileVerbosity >= verb) && len > 0) { + if (logFile) { + fwrite(tmpBuffer, len, 1, logFile); + if (logFlush) { + fflush(logFile); +#ifndef WIN32 + if (logSync) + fsync(fileno(logFile)); +#endif + } + } else if (needBuffer) { + /* + * Note, this code is used before OsInit() has been called, so + * xalloc() and friends can't be used. + */ + if (len > bufferUnused) { + bufferSize += 1024; + bufferUnused += 1024; + if (saveBuffer) + saveBuffer = realloc(saveBuffer, bufferSize); + else + saveBuffer = malloc(bufferSize); + if (!saveBuffer) + FatalError("realloc() failed while saving log messages\n"); + } + bufferUnused -= len; + memcpy(saveBuffer + bufferPos, tmpBuffer, len); + bufferPos += len; + } + } +} + +void +LogWrite(int verb, const char *f, ...) +{ + va_list args; + + va_start(args, f); + LogVWrite(verb, f, args); + va_end(args); +} + +void +LogVMessageVerb(MessageType type, int verb, const char *format, va_list args) +{ + const char *s = X_UNKNOWN_STRING; + char tmpBuf[1024]; + + /* Ignore verbosity for X_ERROR */ + if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) { + switch (type) { + case X_PROBED: + s = X_PROBE_STRING; + break; + case X_CONFIG: + s = X_CONFIG_STRING; + break; + case X_DEFAULT: + s = X_DEFAULT_STRING; + break; + case X_CMDLINE: + s = X_CMDLINE_STRING; + break; + case X_NOTICE: + s = X_NOTICE_STRING; + break; + case X_ERROR: + s = X_ERROR_STRING; + if (verb > 0) + verb = 0; + break; + case X_WARNING: + s = X_WARNING_STRING; + break; + case X_INFO: + s = X_INFO_STRING; + break; + case X_NOT_IMPLEMENTED: + s = X_NOT_IMPLEMENTED_STRING; + break; + case X_UNKNOWN: + s = X_UNKNOWN_STRING; + break; + case X_NONE: + s = NULL; + break; + } + + /* if s is not NULL we need a space before format */ + snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "", + s ? " " : "", + format); + LogVWrite(verb, tmpBuf, args); + } +} + +/* Log message with verbosity level specified. */ +void +LogMessageVerb(MessageType type, int verb, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(type, verb, format, ap); + va_end(ap); +} + +/* Log a message with the standard verbosity level of 1. */ +void +LogMessage(MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(type, 1, format, ap); + va_end(ap); +} + +#ifdef __GNUC__ +void AbortServer(void) __attribute__((noreturn)); +#endif + +void +AbortServer(void) +{ +#ifdef XF86BIGFONT + XF86BigfontCleanup(); +#endif + CloseWellKnownConnections(); + OsCleanup(TRUE); + CloseDownDevices(); + AbortDDX(); + fflush(stderr); + if (CoreDump) + OsAbort(); + exit (1); +} + +#define AUDIT_PREFIX "AUDIT: %s: %ld: " +#ifndef AUDIT_TIMEOUT +#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */ +#endif + +static int nrepeat = 0; +static int oldlen = -1; +static OsTimerPtr auditTimer = NULL; + +void +FreeAuditTimer(void) +{ + if (auditTimer != NULL) { + /* Force output of pending messages */ + TimerForce(auditTimer); + TimerFree(auditTimer); + auditTimer = NULL; + } +} + +static char * +AuditPrefix(void) +{ + time_t tm; + char *autime, *s; + char *tmpBuf; + int len; + + time(&tm); + autime = ctime(&tm); + if ((s = strchr(autime, '\n'))) + *s = '\0'; + len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1; + tmpBuf = malloc(len); + if (!tmpBuf) + return NULL; + snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid()); + return tmpBuf; +} + +void +AuditF(const char * f, ...) +{ + va_list args; + + va_start(args, f); + + VAuditF(f, args); + va_end(args); +} + +static CARD32 +AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg) +{ + char *prefix; + + if (nrepeat > 0) { + prefix = AuditPrefix(); + ErrorF("%slast message repeated %d times\n", + prefix != NULL ? prefix : "", nrepeat); + nrepeat = 0; + if (prefix != NULL) + free(prefix); + return AUDIT_TIMEOUT; + } else { + /* if the timer expires without anything to print, flush the message */ + oldlen = -1; + return 0; + } +} + +void +VAuditF(const char *f, va_list args) +{ + char *prefix; + char buf[1024]; + int len; + static char oldbuf[1024]; + + prefix = AuditPrefix(); + len = vsnprintf(buf, sizeof(buf), f, args); + + if (len == oldlen && strcmp(buf, oldbuf) == 0) { + /* Message already seen */ + nrepeat++; + } else { + /* new message */ + if (auditTimer != NULL) + TimerForce(auditTimer); + ErrorF("%s%s", prefix != NULL ? prefix : "", buf); + strlcpy(oldbuf, buf, sizeof(oldbuf)); + oldlen = len; + nrepeat = 0; + auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL); + } + if (prefix != NULL) + free(prefix); +} + +void +FatalError(const char *f, ...) +{ + va_list args; + static Bool beenhere = FALSE; + + if (beenhere) + ErrorF("\nFatalError re-entered, aborting\n"); + else + ErrorF("\nFatal server error:\n"); + + va_start(args, f); + VErrorF(f, args); + va_end(args); + ErrorF("\n"); + if (!beenhere) + OsVendorFatalError(); + if (!beenhere) { + beenhere = TRUE; + AbortServer(); + } else + OsAbort(); + /*NOTREACHED*/ +} + +void +VErrorF(const char *f, va_list args) +{ +#ifdef DDXOSVERRORF + if (OsVendorVErrorFProc) + OsVendorVErrorFProc(f, args); + else + LogVWrite(-1, f, args); +#else + LogVWrite(-1, f, args); +#endif +} + +void +ErrorF(const char * f, ...) +{ + va_list args; + + va_start(args, f); + VErrorF(f, args); + va_end(args); +} + +/* A perror() workalike. */ + +void +Error(char *str) +{ + char *err = NULL; + int saveErrno = errno; + + if (str) { + err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1); + if (!err) + return; + sprintf(err, "%s: ", str); + strcat(err, strerror(saveErrno)); + LogWrite(-1, "%s", err); + free(err); + } else + LogWrite(-1, "%s", strerror(saveErrno)); +} + +void +LogPrintMarkers(void) +{ + /* Show what the message marker symbols mean. */ + LogWrite(0, "Markers: "); + LogMessageVerb(X_PROBED, 0, "probed, "); + LogMessageVerb(X_CONFIG, 0, "from config file, "); + LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t"); + LogMessageVerb(X_CMDLINE, 0, "from command line, "); + LogMessageVerb(X_NOTICE, 0, "notice, "); + LogMessageVerb(X_INFO, 0, "informational,\n\t"); + LogMessageVerb(X_WARNING, 0, "warning, "); + LogMessageVerb(X_ERROR, 0, "error, "); + LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, "); + LogMessageVerb(X_UNKNOWN, 0, "unknown.\n"); +} + diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c index 79399fa53..21e25e066 100644 --- a/xorg-server/os/utils.c +++ b/xorg-server/os/utils.c @@ -1310,6 +1310,18 @@ OsReleaseSignals (void) #endif } +/* + * Pending signals may interfere with core dumping. Provide a + * mechanism to block signals when aborting. + */ + +void +OsAbort (void) +{ + OsBlockSignals(); + abort(); +} + #if !defined(WIN32) /* * "safer" versions of system(3), popen(3) and pclose(3) which give up diff --git a/xorg-server/record/record.c b/xorg-server/record/record.c index 0ec92e167..1a10c9edc 100644 --- a/xorg-server/record/record.c +++ b/xorg-server/record/record.c @@ -42,6 +42,8 @@ and Jim Haggerty of Metheus. #include "set.h" #include "swaprep.h" #include "inputstr.h" +#include "eventconvert.h" + #include #include @@ -139,7 +141,8 @@ static int RecordDeleteContext( XID /*id*/ ); - +void RecordExtensionInit(void); + /***************************************************************************/ /* client private stuff */ @@ -727,6 +730,59 @@ RecordADeliveredEventOrError(CallbackListPtr *pcbl, pointer nulldata, pointer ca } /* RecordADeliveredEventOrError */ +static void +RecordSendProtocolEvents(RecordClientsAndProtocolPtr pRCAP, + RecordContextPtr pContext, + xEvent* pev, int count) +{ + int ev; /* event index */ + + for (ev = 0; ev < count; ev++, pev++) + { + if (RecordIsMemberOfSet(pRCAP->pDeviceEventSet, + pev->u.u.type & 0177)) + { + xEvent swappedEvent; + xEvent *pEvToRecord = pev; +#ifdef PANORAMIX + xEvent shiftedEvent; + + if (!noPanoramiXExtension && + (pev->u.u.type == MotionNotify || + pev->u.u.type == ButtonPress || + pev->u.u.type == ButtonRelease || + pev->u.u.type == KeyPress || + pev->u.u.type == KeyRelease)) { + int scr = XineramaGetCursorScreen(inputInfo.pointer); + memcpy(&shiftedEvent, pev, sizeof(xEvent)); + shiftedEvent.u.keyButtonPointer.rootX += + panoramiXdataPtr[scr].x - + panoramiXdataPtr[0].x; + shiftedEvent.u.keyButtonPointer.rootY += + panoramiXdataPtr[scr].y - + panoramiXdataPtr[0].y; + pEvToRecord = &shiftedEvent; + } +#endif /* PANORAMIX */ + + if (pContext->pRecordingClient->swapped) + { + (*EventSwapVector[pEvToRecord->u.u.type & 0177]) + (pEvToRecord, &swappedEvent); + pEvToRecord = &swappedEvent; + } + + RecordAProtocolElement(pContext, NULL, + XRecordFromServer, pEvToRecord, SIZEOF(xEvent), 0); + /* make sure device events get flushed in the absence + * of other client activity + */ + SetCriticalOutputPending(); + } + } /* end for each event */ + +} /* RecordADeviceEvent */ + /* RecordADeviceEvent * * Arguments: @@ -756,55 +812,24 @@ RecordADeviceEvent(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) { if (pRCAP->pDeviceEventSet) { - int ev; /* event index */ - xEvent *pev = pei->events; - for (ev = 0; ev < pei->count; ev++, pev++) - { - if (RecordIsMemberOfSet(pRCAP->pDeviceEventSet, - pev->u.u.type & 0177)) - { - xEvent swappedEvent; - xEvent *pEvToRecord = pev; -#ifdef PANORAMIX - xEvent shiftedEvent; - - if (!noPanoramiXExtension && - (pev->u.u.type == MotionNotify || - pev->u.u.type == ButtonPress || - pev->u.u.type == ButtonRelease || - pev->u.u.type == KeyPress || - pev->u.u.type == KeyRelease)) { - int scr = XineramaGetCursorScreen(inputInfo.pointer); - memcpy(&shiftedEvent, pev, sizeof(xEvent)); - shiftedEvent.u.keyButtonPointer.rootX += - panoramiXdataPtr[scr].x - - panoramiXdataPtr[0].x; - shiftedEvent.u.keyButtonPointer.rootY += - panoramiXdataPtr[scr].y - - panoramiXdataPtr[0].y; - pEvToRecord = &shiftedEvent; - } -#endif /* PANORAMIX */ + int count; + xEvent *xi_events = NULL; - if (pContext->pRecordingClient->swapped) - { - (*EventSwapVector[pEvToRecord->u.u.type & 0177]) - (pEvToRecord, &swappedEvent); - pEvToRecord = &swappedEvent; - } + /* TODO check return values */ + if (IsMaster(pei->device)) + { + xEvent xE; + EventToCore(pei->event, &xE); + RecordSendProtocolEvents(pRCAP, pContext, &xE, 1); + } - RecordAProtocolElement(pContext, NULL, - XRecordFromServer, pEvToRecord, SIZEOF(xEvent), 0); - /* make sure device events get flushed in the absence - * of other client activity - */ - SetCriticalOutputPending(); - } - } /* end for each event */ + EventToXI(pei->event, &xi_events, &count); + RecordSendProtocolEvents(pRCAP, pContext, xi_events, count); + xfree(xi_events); } /* end this RCAP selects device events */ } /* end for each RCAP on this context */ } /* end for each enabled context */ -} /* RecordADeviceEvent */ +} /* RecordFlushAllContexts -- cgit v1.2.3