From 57a879849643e79d9674198a3a77c59532fb79b4 Mon Sep 17 00:00:00 2001 From: marha Date: Thu, 28 Apr 2011 07:58:00 +0000 Subject: xserver xkeyboard-config mesa git update 28 Apr 2011 --- xorg-server/hw/xfree86/ddc/ddcProperty.c | 249 +- xorg-server/hw/xfree86/dri/dri.c | 2 - xorg-server/hw/xfree86/dri/xf86dri.c | 1325 +++++----- xorg-server/hw/xfree86/fbdevhw/fbdevhw.c | 1811 +++++++------- xorg-server/hw/xfree86/modes/xf86RandR12.c | 3647 ++++++++++++++-------------- 5 files changed, 3514 insertions(+), 3520 deletions(-) (limited to 'xorg-server/hw/xfree86') diff --git a/xorg-server/hw/xfree86/ddc/ddcProperty.c b/xorg-server/hw/xfree86/ddc/ddcProperty.c index d4ae1006d..5d6eec927 100644 --- a/xorg-server/hw/xfree86/ddc/ddcProperty.c +++ b/xorg-server/hw/xfree86/ddc/ddcProperty.c @@ -1,125 +1,124 @@ -/* - * Copyright 2006 Luc Verhaegen. - * - * 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, sub license, - * 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 (including the - * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86DDC.h" -#include -#include "property.h" -#include "propertyst.h" -#include "xf86DDC.h" -#include - -#define EDID1_ATOM_NAME "XFree86_DDC_EDID1_RAWDATA" -#define EDID2_ATOM_NAME "XFree86_DDC_EDID2_RAWDATA" - -static void -edidMakeAtom(int i, const char *name, CARD8 *data, int size) -{ - Atom atom; - unsigned char *atom_data; - - if (!(atom_data = malloc(size*sizeof(CARD8)))) - return; - - atom = MakeAtom(name, strlen(name), TRUE); - memcpy(atom_data, data, size); - xf86RegisterRootWindowProperty(i, atom, XA_INTEGER, 8, size, atom_data); -} - -static void -addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) -{ - int i, scrnIndex = pScrn->scrnIndex; - Bool makeEDID1prop = FALSE; - Bool makeEDID2prop = FALSE; - - if (DDC->flags & MONITOR_DISPLAYID) { - /* Don't bother, use RANDR already */ - return; - } else if (DDC->ver.version == 1) { - makeEDID1prop = TRUE; - } else if (DDC->ver.version == 2) { - int checksum1; - int checksum2; - makeEDID2prop = TRUE; - - /* Some monitors (eg Panasonic PanaSync4) - * report version==2 because they used EDID v2 spec document, - * although they use EDID v1 data structure :-( - * - * Try using checksum to determine when we have such a monitor. - */ - checksum2 = 0; - for (i = 0; i < 256; i++) - checksum2 += DDC->rawData[i]; - if (checksum2 % 256) { - xf86DrvMsg(scrnIndex, X_INFO, "Monitor EDID v2 checksum failed\n"); - xf86DrvMsg(scrnIndex, X_INFO, - "XFree86_DDC_EDID2_RAWDATA property may be bad\n"); - checksum1 = 0; - for (i = 0; i < 128; i++) - checksum1 += DDC->rawData[i]; - if (!(checksum1 % 256)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Monitor EDID v1 checksum passed,\n"); - xf86DrvMsg(scrnIndex, X_INFO, - "XFree86_DDC_EDID1_RAWDATA property created\n"); - makeEDID1prop = TRUE; - } - } - } else { - xf86DrvMsg(scrnIndex, X_PROBED, "unexpected EDID version %d.%d\n", - DDC->ver.version, DDC->ver.revision); - return; - } - - if (makeEDID1prop) { - int size = 128 + - (DDC->flags & EDID_COMPLETE_RAWDATA ? DDC->no_sections * 128 : 0); - - edidMakeAtom(scrnIndex, EDID1_ATOM_NAME, DDC->rawData, size); - } - - if (makeEDID2prop) - edidMakeAtom(scrnIndex, EDID2_ATOM_NAME, DDC->rawData, 256); -} - -Bool -xf86SetDDCproperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) -{ - if (!pScrn || !pScrn->monitor || !DDC) - return FALSE; - - if (DDC->flags & MONITOR_DISPLAYID) - ; - else - xf86EdidMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC); - - addRootWindowProperties(pScrn, DDC); - - return TRUE; -} +/* + * Copyright 2006 Luc Verhaegen. + * + * 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, sub license, + * 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 (including the + * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86DDC.h" +#include +#include "property.h" +#include "propertyst.h" +#include + +#define EDID1_ATOM_NAME "XFree86_DDC_EDID1_RAWDATA" +#define EDID2_ATOM_NAME "XFree86_DDC_EDID2_RAWDATA" + +static void +edidMakeAtom(int i, const char *name, CARD8 *data, int size) +{ + Atom atom; + unsigned char *atom_data; + + if (!(atom_data = malloc(size*sizeof(CARD8)))) + return; + + atom = MakeAtom(name, strlen(name), TRUE); + memcpy(atom_data, data, size); + xf86RegisterRootWindowProperty(i, atom, XA_INTEGER, 8, size, atom_data); +} + +static void +addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) +{ + int i, scrnIndex = pScrn->scrnIndex; + Bool makeEDID1prop = FALSE; + Bool makeEDID2prop = FALSE; + + if (DDC->flags & MONITOR_DISPLAYID) { + /* Don't bother, use RANDR already */ + return; + } else if (DDC->ver.version == 1) { + makeEDID1prop = TRUE; + } else if (DDC->ver.version == 2) { + int checksum1; + int checksum2; + makeEDID2prop = TRUE; + + /* Some monitors (eg Panasonic PanaSync4) + * report version==2 because they used EDID v2 spec document, + * although they use EDID v1 data structure :-( + * + * Try using checksum to determine when we have such a monitor. + */ + checksum2 = 0; + for (i = 0; i < 256; i++) + checksum2 += DDC->rawData[i]; + if (checksum2 % 256) { + xf86DrvMsg(scrnIndex, X_INFO, "Monitor EDID v2 checksum failed\n"); + xf86DrvMsg(scrnIndex, X_INFO, + "XFree86_DDC_EDID2_RAWDATA property may be bad\n"); + checksum1 = 0; + for (i = 0; i < 128; i++) + checksum1 += DDC->rawData[i]; + if (!(checksum1 % 256)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Monitor EDID v1 checksum passed,\n"); + xf86DrvMsg(scrnIndex, X_INFO, + "XFree86_DDC_EDID1_RAWDATA property created\n"); + makeEDID1prop = TRUE; + } + } + } else { + xf86DrvMsg(scrnIndex, X_PROBED, "unexpected EDID version %d.%d\n", + DDC->ver.version, DDC->ver.revision); + return; + } + + if (makeEDID1prop) { + int size = 128 + + (DDC->flags & EDID_COMPLETE_RAWDATA ? DDC->no_sections * 128 : 0); + + edidMakeAtom(scrnIndex, EDID1_ATOM_NAME, DDC->rawData, size); + } + + if (makeEDID2prop) + edidMakeAtom(scrnIndex, EDID2_ATOM_NAME, DDC->rawData, 256); +} + +Bool +xf86SetDDCproperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) +{ + if (!pScrn || !pScrn->monitor || !DDC) + return FALSE; + + if (DDC->flags & MONITOR_DISPLAYID) + ; + else + xf86EdidMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC); + + addRootWindowProperties(pScrn, DDC); + + return TRUE; +} diff --git a/xorg-server/hw/xfree86/dri/dri.c b/xorg-server/hw/xfree86/dri/dri.c index bb5482a0b..1726960ae 100644 --- a/xorg-server/hw/xfree86/dri/dri.c +++ b/xorg-server/hw/xfree86/dri/dri.c @@ -63,8 +63,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "dri.h" #include "sarea.h" #include "dristruct.h" -#include "xf86.h" -#include "xf86drm.h" #include "mi.h" #include "mipointer.h" #include "xf86_OSproc.h" diff --git a/xorg-server/hw/xfree86/dri/xf86dri.c b/xorg-server/hw/xfree86/dri/xf86dri.c index cd1085b36..e02644a30 100644 --- a/xorg-server/hw/xfree86/dri/xf86dri.c +++ b/xorg-server/hw/xfree86/dri/xf86dri.c @@ -1,663 +1,662 @@ -/************************************************************************** - -Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. -Copyright 2000 VA Linux Systems, Inc. -All Rights Reserved. - -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, sub license, 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 (including the -next paragraph) 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 NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. - -**************************************************************************/ - -/* - * Authors: - * Kevin E. Martin - * Jens Owen - * Rickard E. (Rik) Faith - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "xf86.h" - -#include -#include -#include "misc.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "servermd.h" -#define _XF86DRI_SERVER_ -#include -#include "swaprep.h" -#include "xf86str.h" -#include "dri.h" -#include "sarea.h" -#include "dristruct.h" -#include "xf86.h" -#include "xf86drm.h" -#include "protocol-versions.h" - -static int DRIErrorBase; - - - -static void XF86DRIResetProc(ExtensionEntry* extEntry); - -static unsigned char DRIReqCode = 0; - -extern void XFree86DRIExtensionInit(void); - -/*ARGSUSED*/ -static void -XF86DRIResetProc ( - ExtensionEntry* extEntry -) -{ - DRIReset(); -} - -static int -ProcXF86DRIQueryVersion( - register ClientPtr client -) -{ - xXF86DRIQueryVersionReply rep; - register int n; - - REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_XF86DRI_MAJOR_VERSION; - rep.minorVersion = SERVER_XF86DRI_MINOR_VERSION; - rep.patchVersion = SERVER_XF86DRI_PATCH_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - swapl(&rep.patchVersion, n); - } - WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); - return Success; -} - -static int -ProcXF86DRIQueryDirectRenderingCapable( - register ClientPtr client -) -{ - xXF86DRIQueryDirectRenderingCapableReply rep; - Bool isCapable; - register int n; - - REQUEST(xXF86DRIQueryDirectRenderingCapableReq); - REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if (!DRIQueryDirectRenderingCapable( screenInfo.screens[stuff->screen], - &isCapable)) { - return BadValue; - } - rep.isCapable = isCapable; - - if (!LocalClient(client) || client->swapped) - rep.isCapable = 0; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - } - - WriteToClient(client, - sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); - return Success; -} - -static int -ProcXF86DRIOpenConnection( - register ClientPtr client -) -{ - xXF86DRIOpenConnectionReply rep; - drm_handle_t hSAREA; - char* busIdString; - - REQUEST(xXF86DRIOpenConnectionReq); - REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - if (!DRIOpenConnection( screenInfo.screens[stuff->screen], - &hSAREA, - &busIdString)) { - return BadValue; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.busIdStringLength = 0; - if (busIdString) - rep.busIdStringLength = strlen(busIdString); - rep.length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) + - pad_to_int32(rep.busIdStringLength)); - - rep.hSAREALow = (CARD32)(hSAREA & 0xffffffff); -#if defined(LONG64) && !defined(__linux__) - rep.hSAREAHigh = (CARD32)(hSAREA >> 32); -#else - rep.hSAREAHigh = 0; -#endif - - WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); - if (rep.busIdStringLength) - WriteToClient(client, rep.busIdStringLength, busIdString); - return Success; -} - -static int -ProcXF86DRIAuthConnection( - register ClientPtr client -) -{ - xXF86DRIAuthConnectionReply rep; - - REQUEST(xXF86DRIAuthConnectionReq); - REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.authenticated = 1; - - if (!DRIAuthConnection( screenInfo.screens[stuff->screen], stuff->magic)) { - ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); - rep.authenticated = 0; - } - WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); - return Success; -} - -static int -ProcXF86DRICloseConnection( - register ClientPtr client -) -{ - REQUEST(xXF86DRICloseConnectionReq); - REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - DRICloseConnection( screenInfo.screens[stuff->screen]); - - return Success; -} - -static int -ProcXF86DRIGetClientDriverName( - register ClientPtr client -) -{ - xXF86DRIGetClientDriverNameReply rep; - char* clientDriverName; - - REQUEST(xXF86DRIGetClientDriverNameReq); - REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - DRIGetClientDriverName( screenInfo.screens[stuff->screen], - (int *)&rep.ddxDriverMajorVersion, - (int *)&rep.ddxDriverMinorVersion, - (int *)&rep.ddxDriverPatchVersion, - &clientDriverName); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.clientDriverNameLength = 0; - if (clientDriverName) - rep.clientDriverNameLength = strlen(clientDriverName); - rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) - - SIZEOF(xGenericReply) + - pad_to_int32(rep.clientDriverNameLength)); - - WriteToClient(client, - sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep); - if (rep.clientDriverNameLength) - WriteToClient(client, - rep.clientDriverNameLength, - clientDriverName); - return Success; -} - -static int -ProcXF86DRICreateContext( - register ClientPtr client -) -{ - xXF86DRICreateContextReply rep; - ScreenPtr pScreen; - - REQUEST(xXF86DRICreateContextReq); - REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - pScreen = screenInfo.screens[stuff->screen]; - - if (!DRICreateContext( pScreen, - NULL, - stuff->context, - (drm_context_t *)&rep.hHWContext)) { - return BadValue; - } - - WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); - return Success; -} - -static int -ProcXF86DRIDestroyContext( - register ClientPtr client -) -{ - REQUEST(xXF86DRIDestroyContextReq); - REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - if (!DRIDestroyContext( screenInfo.screens[stuff->screen], - stuff->context)) { - return BadValue; - } - - return Success; -} - -static int -ProcXF86DRICreateDrawable( - ClientPtr client -) -{ - xXF86DRICreateDrawableReply rep; - DrawablePtr pDrawable; - int rc; - - REQUEST(xXF86DRICreateDrawableReq); - REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client, - pDrawable, (drm_drawable_t *)&rep.hHWDrawable)) { - return BadValue; - } - - WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); - return Success; -} - -static int -ProcXF86DRIDestroyDrawable( - register ClientPtr client -) -{ - REQUEST(xXF86DRIDestroyDrawableReq); - DrawablePtr pDrawable; - int rc; - REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); - - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client, - pDrawable)) { - return BadValue; - } - - return Success; -} - -static int -ProcXF86DRIGetDrawableInfo( - register ClientPtr client -) -{ - xXF86DRIGetDrawableInfoReply rep; - DrawablePtr pDrawable; - int X, Y, W, H; - drm_clip_rect_t * pClipRects, *pClippedRects; - drm_clip_rect_t * pBackClipRects; - int backX, backY, rc; - - REQUEST(xXF86DRIGetDrawableInfoReq); - REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - if (!DRIGetDrawableInfo( screenInfo.screens[stuff->screen], - pDrawable, - (unsigned int*)&rep.drawableTableIndex, - (unsigned int*)&rep.drawableTableStamp, - (int*)&X, - (int*)&Y, - (int*)&W, - (int*)&H, - (int*)&rep.numClipRects, - &pClipRects, - &backX, - &backY, - (int*)&rep.numBackClipRects, - &pBackClipRects)) { - return BadValue; - } - - rep.drawableX = X; - rep.drawableY = Y; - rep.drawableWidth = W; - rep.drawableHeight = H; - rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - - SIZEOF(xGenericReply)); - - rep.backX = backX; - rep.backY = backY; - - if (rep.numBackClipRects) - rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; - - pClippedRects = pClipRects; - - if (rep.numClipRects) { - /* Clip cliprects to screen dimensions (redirected windows) */ - pClippedRects = malloc(rep.numClipRects * sizeof(drm_clip_rect_t)); - - if (pClippedRects) { - ScreenPtr pScreen = screenInfo.screens[stuff->screen]; - int i, j; - - for (i = 0, j = 0; i < rep.numClipRects; i++) { - pClippedRects[j].x1 = max(pClipRects[i].x1, 0); - pClippedRects[j].y1 = max(pClipRects[i].y1, 0); - pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); - pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); - - if (pClippedRects[j].x1 < pClippedRects[j].x2 && - pClippedRects[j].y1 < pClippedRects[j].y2) { - j++; - } - } - - rep.numClipRects = j; - } else { - rep.numClipRects = 0; - } - - rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; - } - - rep.length = bytes_to_int32(rep.length); - - WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); - - if (rep.numClipRects) { - WriteToClient(client, - sizeof(drm_clip_rect_t) * rep.numClipRects, - (char *)pClippedRects); - free(pClippedRects); - } - - if (rep.numBackClipRects) { - WriteToClient(client, - sizeof(drm_clip_rect_t) * rep.numBackClipRects, - (char *)pBackClipRects); - } - - return Success; -} - -static int -ProcXF86DRIGetDeviceInfo( - register ClientPtr client -) -{ - xXF86DRIGetDeviceInfoReply rep; - drm_handle_t hFrameBuffer; - void *pDevPrivate; - - REQUEST(xXF86DRIGetDeviceInfoReq); - REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if (!DRIGetDeviceInfo( screenInfo.screens[stuff->screen], - &hFrameBuffer, - (int*)&rep.framebufferOrigin, - (int*)&rep.framebufferSize, - (int*)&rep.framebufferStride, - (int*)&rep.devPrivateSize, - &pDevPrivate)) { - return BadValue; - } - - rep.hFrameBufferLow = (CARD32)(hFrameBuffer & 0xffffffff); -#if defined(LONG64) && !defined(__linux__) - rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32); -#else - rep.hFrameBufferHigh = 0; -#endif - - rep.length = 0; - if (rep.devPrivateSize) { - rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) - - SIZEOF(xGenericReply) + - pad_to_int32(rep.devPrivateSize)); - } - - WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); - if (rep.length) { - WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); - } - return Success; -} - -static int -ProcXF86DRIDispatch ( - register ClientPtr client -) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_XF86DRIQueryVersion: - return ProcXF86DRIQueryVersion(client); - case X_XF86DRIQueryDirectRenderingCapable: - return ProcXF86DRIQueryDirectRenderingCapable(client); - } - - if (!LocalClient(client)) - return DRIErrorBase + XF86DRIClientNotLocal; - - switch (stuff->data) - { - case X_XF86DRIOpenConnection: - return ProcXF86DRIOpenConnection(client); - case X_XF86DRICloseConnection: - return ProcXF86DRICloseConnection(client); - case X_XF86DRIGetClientDriverName: - return ProcXF86DRIGetClientDriverName(client); - case X_XF86DRICreateContext: - return ProcXF86DRICreateContext(client); - case X_XF86DRIDestroyContext: - return ProcXF86DRIDestroyContext(client); - case X_XF86DRICreateDrawable: - return ProcXF86DRICreateDrawable(client); - case X_XF86DRIDestroyDrawable: - return ProcXF86DRIDestroyDrawable(client); - case X_XF86DRIGetDrawableInfo: - return ProcXF86DRIGetDrawableInfo(client); - case X_XF86DRIGetDeviceInfo: - return ProcXF86DRIGetDeviceInfo(client); - case X_XF86DRIAuthConnection: - return ProcXF86DRIAuthConnection(client); - /* {Open,Close}FullScreen are deprecated now */ - default: - return BadRequest; - } -} - -static int -SProcXF86DRIQueryVersion( - register ClientPtr client -) -{ - register int n; - REQUEST(xXF86DRIQueryVersionReq); - swaps(&stuff->length, n); - return ProcXF86DRIQueryVersion(client); -} - -static int -SProcXF86DRIQueryDirectRenderingCapable( - register ClientPtr client -) -{ - register int n; - REQUEST(xXF86DRIQueryDirectRenderingCapableReq); - swaps(&stuff->length, n); - swapl(&stuff->screen, n); - return ProcXF86DRIQueryDirectRenderingCapable(client); -} - -static int -SProcXF86DRIDispatch ( - register ClientPtr client -) -{ - REQUEST(xReq); - - /* - * Only local clients are allowed DRI access, but remote clients still need - * these requests to find out cleanly. - */ - switch (stuff->data) - { - case X_XF86DRIQueryVersion: - return SProcXF86DRIQueryVersion(client); - case X_XF86DRIQueryDirectRenderingCapable: - return SProcXF86DRIQueryDirectRenderingCapable(client); - default: - return DRIErrorBase + XF86DRIClientNotLocal; - } -} - -void -XFree86DRIExtensionInit(void) -{ - ExtensionEntry* extEntry; - -#ifdef XF86DRI_EVENTS - EventType = CreateNewResourceType(XF86DRIFreeEvents, "DRIEvent"); -#endif - - if ( - DRIExtensionInit() && -#ifdef XF86DRI_EVENTS - EventType && ScreenPrivateIndex != -1 && -#endif - (extEntry = AddExtension(XF86DRINAME, - XF86DRINumberEvents, - XF86DRINumberErrors, - ProcXF86DRIDispatch, - SProcXF86DRIDispatch, - XF86DRIResetProc, - StandardMinorOpcode))) { - DRIReqCode = (unsigned char)extEntry->base; - DRIErrorBase = extEntry->errorBase; - } -} +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +All Rights Reserved. + +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, sub license, 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 (including the +next paragraph) 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 NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin + * Jens Owen + * Rickard E. (Rik) Faith + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "xf86.h" + +#include +#include +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XF86DRI_SERVER_ +#include +#include "swaprep.h" +#include "xf86str.h" +#include "dri.h" +#include "sarea.h" +#include "dristruct.h" +#include "xf86drm.h" +#include "protocol-versions.h" + +static int DRIErrorBase; + + + +static void XF86DRIResetProc(ExtensionEntry* extEntry); + +static unsigned char DRIReqCode = 0; + +extern void XFree86DRIExtensionInit(void); + +/*ARGSUSED*/ +static void +XF86DRIResetProc ( + ExtensionEntry* extEntry +) +{ + DRIReset(); +} + +static int +ProcXF86DRIQueryVersion( + register ClientPtr client +) +{ + xXF86DRIQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_XF86DRI_MAJOR_VERSION; + rep.minorVersion = SERVER_XF86DRI_MINOR_VERSION; + rep.patchVersion = SERVER_XF86DRI_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swapl(&rep.patchVersion, n); + } + WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + xXF86DRIQueryDirectRenderingCapableReply rep; + Bool isCapable; + register int n; + + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DRIQueryDirectRenderingCapable( screenInfo.screens[stuff->screen], + &isCapable)) { + return BadValue; + } + rep.isCapable = isCapable; + + if (!LocalClient(client) || client->swapped) + rep.isCapable = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + + WriteToClient(client, + sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRIOpenConnection( + register ClientPtr client +) +{ + xXF86DRIOpenConnectionReply rep; + drm_handle_t hSAREA; + char* busIdString; + + REQUEST(xXF86DRIOpenConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!DRIOpenConnection( screenInfo.screens[stuff->screen], + &hSAREA, + &busIdString)) { + return BadValue; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.busIdStringLength = 0; + if (busIdString) + rep.busIdStringLength = strlen(busIdString); + rep.length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) + + pad_to_int32(rep.busIdStringLength)); + + rep.hSAREALow = (CARD32)(hSAREA & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hSAREAHigh = (CARD32)(hSAREA >> 32); +#else + rep.hSAREAHigh = 0; +#endif + + WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); + if (rep.busIdStringLength) + WriteToClient(client, rep.busIdStringLength, busIdString); + return Success; +} + +static int +ProcXF86DRIAuthConnection( + register ClientPtr client +) +{ + xXF86DRIAuthConnectionReply rep; + + REQUEST(xXF86DRIAuthConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.authenticated = 1; + + if (!DRIAuthConnection( screenInfo.screens[stuff->screen], stuff->magic)) { + ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); + rep.authenticated = 0; + } + WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRICloseConnection( + register ClientPtr client +) +{ + REQUEST(xXF86DRICloseConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + DRICloseConnection( screenInfo.screens[stuff->screen]); + + return Success; +} + +static int +ProcXF86DRIGetClientDriverName( + register ClientPtr client +) +{ + xXF86DRIGetClientDriverNameReply rep; + char* clientDriverName; + + REQUEST(xXF86DRIGetClientDriverNameReq); + REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + DRIGetClientDriverName( screenInfo.screens[stuff->screen], + (int *)&rep.ddxDriverMajorVersion, + (int *)&rep.ddxDriverMinorVersion, + (int *)&rep.ddxDriverPatchVersion, + &clientDriverName); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.clientDriverNameLength = 0; + if (clientDriverName) + rep.clientDriverNameLength = strlen(clientDriverName); + rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) - + SIZEOF(xGenericReply) + + pad_to_int32(rep.clientDriverNameLength)); + + WriteToClient(client, + sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep); + if (rep.clientDriverNameLength) + WriteToClient(client, + rep.clientDriverNameLength, + clientDriverName); + return Success; +} + +static int +ProcXF86DRICreateContext( + register ClientPtr client +) +{ + xXF86DRICreateContextReply rep; + ScreenPtr pScreen; + + REQUEST(xXF86DRICreateContextReq); + REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + pScreen = screenInfo.screens[stuff->screen]; + + if (!DRICreateContext( pScreen, + NULL, + stuff->context, + (drm_context_t *)&rep.hHWContext)) { + return BadValue; + } + + WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRIDestroyContext( + register ClientPtr client +) +{ + REQUEST(xXF86DRIDestroyContextReq); + REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!DRIDestroyContext( screenInfo.screens[stuff->screen], + stuff->context)) { + return BadValue; + } + + return Success; +} + +static int +ProcXF86DRICreateDrawable( + ClientPtr client +) +{ + xXF86DRICreateDrawableReply rep; + DrawablePtr pDrawable; + int rc; + + REQUEST(xXF86DRICreateDrawableReq); + REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client, + pDrawable, (drm_drawable_t *)&rep.hHWDrawable)) { + return BadValue; + } + + WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRIDestroyDrawable( + register ClientPtr client +) +{ + REQUEST(xXF86DRIDestroyDrawableReq); + DrawablePtr pDrawable; + int rc; + REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); + + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client, + pDrawable)) { + return BadValue; + } + + return Success; +} + +static int +ProcXF86DRIGetDrawableInfo( + register ClientPtr client +) +{ + xXF86DRIGetDrawableInfoReply rep; + DrawablePtr pDrawable; + int X, Y, W, H; + drm_clip_rect_t * pClipRects, *pClippedRects; + drm_clip_rect_t * pBackClipRects; + int backX, backY, rc; + + REQUEST(xXF86DRIGetDrawableInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (!DRIGetDrawableInfo( screenInfo.screens[stuff->screen], + pDrawable, + (unsigned int*)&rep.drawableTableIndex, + (unsigned int*)&rep.drawableTableStamp, + (int*)&X, + (int*)&Y, + (int*)&W, + (int*)&H, + (int*)&rep.numClipRects, + &pClipRects, + &backX, + &backY, + (int*)&rep.numBackClipRects, + &pBackClipRects)) { + return BadValue; + } + + rep.drawableX = X; + rep.drawableY = Y; + rep.drawableWidth = W; + rep.drawableHeight = H; + rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - + SIZEOF(xGenericReply)); + + rep.backX = backX; + rep.backY = backY; + + if (rep.numBackClipRects) + rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; + + pClippedRects = pClipRects; + + if (rep.numClipRects) { + /* Clip cliprects to screen dimensions (redirected windows) */ + pClippedRects = malloc(rep.numClipRects * sizeof(drm_clip_rect_t)); + + if (pClippedRects) { + ScreenPtr pScreen = screenInfo.screens[stuff->screen]; + int i, j; + + for (i = 0, j = 0; i < rep.numClipRects; i++) { + pClippedRects[j].x1 = max(pClipRects[i].x1, 0); + pClippedRects[j].y1 = max(pClipRects[i].y1, 0); + pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); + pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); + + if (pClippedRects[j].x1 < pClippedRects[j].x2 && + pClippedRects[j].y1 < pClippedRects[j].y2) { + j++; + } + } + + rep.numClipRects = j; + } else { + rep.numClipRects = 0; + } + + rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; + } + + rep.length = bytes_to_int32(rep.length); + + WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); + + if (rep.numClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numClipRects, + (char *)pClippedRects); + free(pClippedRects); + } + + if (rep.numBackClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numBackClipRects, + (char *)pBackClipRects); + } + + return Success; +} + +static int +ProcXF86DRIGetDeviceInfo( + register ClientPtr client +) +{ + xXF86DRIGetDeviceInfoReply rep; + drm_handle_t hFrameBuffer; + void *pDevPrivate; + + REQUEST(xXF86DRIGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DRIGetDeviceInfo( screenInfo.screens[stuff->screen], + &hFrameBuffer, + (int*)&rep.framebufferOrigin, + (int*)&rep.framebufferSize, + (int*)&rep.framebufferStride, + (int*)&rep.devPrivateSize, + &pDevPrivate)) { + return BadValue; + } + + rep.hFrameBufferLow = (CARD32)(hFrameBuffer & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32); +#else + rep.hFrameBufferHigh = 0; +#endif + + rep.length = 0; + if (rep.devPrivateSize) { + rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) - + SIZEOF(xGenericReply) + + pad_to_int32(rep.devPrivateSize)); + } + + WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); + if (rep.length) { + WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); + } + return Success; +} + +static int +ProcXF86DRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_XF86DRIQueryVersion: + return ProcXF86DRIQueryVersion(client); + case X_XF86DRIQueryDirectRenderingCapable: + return ProcXF86DRIQueryDirectRenderingCapable(client); + } + + if (!LocalClient(client)) + return DRIErrorBase + XF86DRIClientNotLocal; + + switch (stuff->data) + { + case X_XF86DRIOpenConnection: + return ProcXF86DRIOpenConnection(client); + case X_XF86DRICloseConnection: + return ProcXF86DRICloseConnection(client); + case X_XF86DRIGetClientDriverName: + return ProcXF86DRIGetClientDriverName(client); + case X_XF86DRICreateContext: + return ProcXF86DRICreateContext(client); + case X_XF86DRIDestroyContext: + return ProcXF86DRIDestroyContext(client); + case X_XF86DRICreateDrawable: + return ProcXF86DRICreateDrawable(client); + case X_XF86DRIDestroyDrawable: + return ProcXF86DRIDestroyDrawable(client); + case X_XF86DRIGetDrawableInfo: + return ProcXF86DRIGetDrawableInfo(client); + case X_XF86DRIGetDeviceInfo: + return ProcXF86DRIGetDeviceInfo(client); + case X_XF86DRIAuthConnection: + return ProcXF86DRIAuthConnection(client); + /* {Open,Close}FullScreen are deprecated now */ + default: + return BadRequest; + } +} + +static int +SProcXF86DRIQueryVersion( + register ClientPtr client +) +{ + register int n; + REQUEST(xXF86DRIQueryVersionReq); + swaps(&stuff->length, n); + return ProcXF86DRIQueryVersion(client); +} + +static int +SProcXF86DRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + register int n; + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + swaps(&stuff->length, n); + swapl(&stuff->screen, n); + return ProcXF86DRIQueryDirectRenderingCapable(client); +} + +static int +SProcXF86DRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + /* + * Only local clients are allowed DRI access, but remote clients still need + * these requests to find out cleanly. + */ + switch (stuff->data) + { + case X_XF86DRIQueryVersion: + return SProcXF86DRIQueryVersion(client); + case X_XF86DRIQueryDirectRenderingCapable: + return SProcXF86DRIQueryDirectRenderingCapable(client); + default: + return DRIErrorBase + XF86DRIClientNotLocal; + } +} + +void +XFree86DRIExtensionInit(void) +{ + ExtensionEntry* extEntry; + +#ifdef XF86DRI_EVENTS + EventType = CreateNewResourceType(XF86DRIFreeEvents, "DRIEvent"); +#endif + + if ( + DRIExtensionInit() && +#ifdef XF86DRI_EVENTS + EventType && ScreenPrivateIndex != -1 && +#endif + (extEntry = AddExtension(XF86DRINAME, + XF86DRINumberEvents, + XF86DRINumberErrors, + ProcXF86DRIDispatch, + SProcXF86DRIDispatch, + XF86DRIResetProc, + StandardMinorOpcode))) { + DRIReqCode = (unsigned char)extEntry->base; + DRIErrorBase = extEntry->errorBase; + } +} diff --git a/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c b/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c index ef69d58bc..dee731be4 100644 --- a/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c +++ b/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c @@ -1,906 +1,905 @@ -/* all driver need this */ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "xf86.h" -#include "xf86_OSproc.h" - -/* pci stuff */ -#include "xf86PciInfo.h" -#include "xf86Pci.h" - -#include "xf86cmap.h" - -#include "fbdevhw.h" -#include "fbpriv.h" -#include "globals.h" -#include - -#define PAGE_MASK (~(getpagesize() - 1)) - -static XF86ModuleVersionInfo fbdevHWVersRec = -{ - "fbdevhw", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - 0, 0, 2, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - MOD_CLASS_NONE, - {0,0,0,0} -}; - -_X_EXPORT XF86ModuleData fbdevhwModuleData = { - &fbdevHWVersRec, - NULL, - NULL -}; - -#include -#include -#include -#include -#include -#include -#include -#include - -/* -------------------------------------------------------------------- */ -/* our private data, and two functions to allocate/free this */ - -#define FBDEVHWPTRLVAL(p) (p)->privates[fbdevHWPrivateIndex].ptr -#define FBDEVHWPTR(p) ((fbdevHWPtr)(FBDEVHWPTRLVAL(p))) - -static int fbdevHWPrivateIndex = -1; - -typedef struct { - /* framebuffer device: filename (/dev/fb*), handle, more */ - char* device; - int fd; - void* fbmem; - unsigned int fbmem_len; - unsigned int fboff; - char* mmio; - unsigned int mmio_len; - - /* current hardware state */ - struct fb_fix_screeninfo fix; - struct fb_var_screeninfo var; - - /* saved video mode */ - struct fb_var_screeninfo saved_var; - - /* buildin video mode */ - DisplayModeRec buildin; - -} fbdevHWRec, *fbdevHWPtr; - -Bool -fbdevHWGetRec(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr; - - if (fbdevHWPrivateIndex < 0) - fbdevHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - - if (FBDEVHWPTR(pScrn) != NULL) - return TRUE; - - fPtr = FBDEVHWPTRLVAL(pScrn) = xnfcalloc(sizeof(fbdevHWRec), 1); - return TRUE; -} - -void -fbdevHWFreeRec(ScrnInfoPtr pScrn) -{ - if (fbdevHWPrivateIndex < 0) - return; - if (FBDEVHWPTR(pScrn) == NULL) - return; - free(FBDEVHWPTR(pScrn)); - FBDEVHWPTRLVAL(pScrn) = NULL; -} - -int -fbdevHWGetFD(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr; - - fbdevHWGetRec(pScrn); - fPtr = FBDEVHWPTR(pScrn); - - return fPtr->fd; -} - -/* -------------------------------------------------------------------- */ -/* some helpers for printing debug informations */ - -#if DEBUG -static void -print_fbdev_mode(char *txt, struct fb_var_screeninfo *var) -{ - ErrorF( "fbdev %s mode:\t%d %d %d %d %d %d %d %d %d %d %d:%d:%d\n", - txt,var->pixclock, - var->xres, var->right_margin, var->hsync_len, var->left_margin, - var->yres, var->lower_margin, var->vsync_len, var->upper_margin, - var->bits_per_pixel, - var->red.length, var->green.length, var->blue.length); -} - -static void -print_xfree_mode(char *txt, DisplayModePtr mode) -{ - ErrorF( "xfree %s mode:\t%d %d %d %d %d %d %d %d %d\n", - txt,mode->Clock, - mode->HDisplay, mode->HSyncStart, mode->HSyncEnd, mode->HTotal, - mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, mode->VTotal); -} -#endif - -/* -------------------------------------------------------------------- */ -/* Convert timings between the XFree and the Frame Buffer Device */ - -static void -xfree2fbdev_fblayout(ScrnInfoPtr pScrn, struct fb_var_screeninfo *var) -{ - var->xres_virtual = pScrn->displayWidth ? pScrn->displayWidth : - pScrn->virtualX; - var->yres_virtual = pScrn->virtualY; - var->bits_per_pixel = pScrn->bitsPerPixel; - if (pScrn->defaultVisual == TrueColor || - pScrn->defaultVisual == DirectColor) { - var->red.length = pScrn->weight.red; - var->green.length = pScrn->weight.green; - var->blue.length = pScrn->weight.blue; - } else { - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - } -} - -static void -xfree2fbdev_timing(DisplayModePtr mode, struct fb_var_screeninfo *var) -{ - var->xres = mode->HDisplay; - var->yres = mode->VDisplay; - if (var->xres_virtual < var->xres) - var->xres_virtual = var->xres; - if (var->yres_virtual < var->yres) - var->yres_virtual = var->yres; - var->xoffset = var->yoffset = 0; - var->pixclock = mode->Clock ? 1000000000/mode->Clock : 0; - var->right_margin = mode->HSyncStart-mode->HDisplay; - var->hsync_len = mode->HSyncEnd-mode->HSyncStart; - var->left_margin = mode->HTotal-mode->HSyncEnd; - var->lower_margin = mode->VSyncStart-mode->VDisplay; - var->vsync_len = mode->VSyncEnd-mode->VSyncStart; - var->upper_margin = mode->VTotal-mode->VSyncEnd; - var->sync = 0; - if (mode->Flags & V_PHSYNC) - var->sync |= FB_SYNC_HOR_HIGH_ACT; - if (mode->Flags & V_PVSYNC) - var->sync |= FB_SYNC_VERT_HIGH_ACT; - if (mode->Flags & V_PCSYNC) - var->sync |= FB_SYNC_COMP_HIGH_ACT; - if (mode->Flags & V_BCAST) - var->sync |= FB_SYNC_BROADCAST; - if (mode->Flags & V_INTERLACE) - var->vmode = FB_VMODE_INTERLACED; - else if (mode->Flags & V_DBLSCAN) - var->vmode = FB_VMODE_DOUBLE; - else - var->vmode = FB_VMODE_NONINTERLACED; -} - -static Bool -fbdev_modes_equal(struct fb_var_screeninfo *set, struct fb_var_screeninfo *req) -{ - return (set->xres_virtual >= req->xres_virtual && - set->yres_virtual >= req->yres_virtual && - set->bits_per_pixel == req->bits_per_pixel && - set->red.length == req->red.length && - set->green.length == req->green.length && - set->blue.length == req->blue.length && - set->xres == req->xres && set->yres == req->yres && - set->right_margin == req->right_margin && - set->hsync_len == req->hsync_len && - set->left_margin == req->left_margin && - set->lower_margin == req->lower_margin && - set->vsync_len == req->vsync_len && - set->upper_margin == req->upper_margin && - set->sync == req->sync && set->vmode == req->vmode); -} - -static void -fbdev2xfree_timing(struct fb_var_screeninfo *var, DisplayModePtr mode) -{ - mode->Clock = var->pixclock ? 1000000000/var->pixclock : 0; - mode->HDisplay = var->xres; - mode->HSyncStart = mode->HDisplay+var->right_margin; - mode->HSyncEnd = mode->HSyncStart+var->hsync_len; - mode->HTotal = mode->HSyncEnd+var->left_margin; - mode->VDisplay = var->yres; - mode->VSyncStart = mode->VDisplay+var->lower_margin; - mode->VSyncEnd = mode->VSyncStart+var->vsync_len; - mode->VTotal = mode->VSyncEnd+var->upper_margin; - mode->Flags = 0; - mode->Flags |= var->sync & FB_SYNC_HOR_HIGH_ACT ? V_PHSYNC : V_NHSYNC; - mode->Flags |= var->sync & FB_SYNC_VERT_HIGH_ACT ? V_PVSYNC : V_NVSYNC; - mode->Flags |= var->sync & FB_SYNC_COMP_HIGH_ACT ? V_PCSYNC : V_NCSYNC; - if (var->sync & FB_SYNC_BROADCAST) - mode->Flags |= V_BCAST; - if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) - mode->Flags |= V_INTERLACE; - else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) - mode->Flags |= V_DBLSCAN; - mode->SynthClock = mode->Clock; - mode->CrtcHDisplay = mode->HDisplay; - mode->CrtcHSyncStart = mode->HSyncStart; - mode->CrtcHSyncEnd = mode->HSyncEnd; - mode->CrtcHTotal = mode->HTotal; - mode->CrtcVDisplay = mode->VDisplay; - mode->CrtcVSyncStart = mode->VSyncStart; - mode->CrtcVSyncEnd = mode->VSyncEnd; - mode->CrtcVTotal = mode->VTotal; - mode->CrtcHAdjusted = FALSE; - mode->CrtcVAdjusted = FALSE; -} - - -/* -------------------------------------------------------------------- */ -/* open correct framebuffer device */ - -/** - * Try to find the framebuffer device for a given PCI device - */ -static int -fbdev_open_pci(struct pci_device * pPci, char **namep) -{ - struct fb_fix_screeninfo fix; - char filename[256]; - int fd, i; - - for (i = 0; i < 8; i++) { - sprintf(filename, - "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics/fb%d", - pPci->domain, pPci->bus, pPci->dev, pPci->func, i); - - fd = open(filename, O_RDONLY, 0); - if (fd < 0) { - sprintf(filename, - "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics:fb%d", - pPci->domain, pPci->bus, pPci->dev, pPci->func, i); - fd = open(filename, O_RDONLY, 0); - } - if (fd >= 0) { - close(fd); - sprintf(filename, "/dev/fb%d", i); - - fd = open(filename, O_RDWR, 0); - if (fd != -1) { - if (ioctl(fd, FBIOGET_FSCREENINFO, (void*) & fix) != -1) { - if (namep) { - *namep = xnfalloc(16); - strncpy(*namep,fix.id,16); - } - - return fd; - } - close(fd); - } - } - } - - if (namep) - *namep = NULL; - - xf86DrvMsg(-1, X_ERROR, "Unable to find a valid framebuffer device\n"); - return -1; -} - -static int -fbdev_open(int scrnIndex, char *dev, char** namep) -{ - struct fb_fix_screeninfo fix; - int fd; - - /* try argument (from XF86Config) first */ - if (dev) { - fd = open(dev,O_RDWR,0); - } else { - /* second: environment variable */ - dev = getenv("FRAMEBUFFER"); - if ((NULL == dev) || ((fd = open(dev,O_RDWR,0)) == -1)) { - /* last try: default device */ - dev = "/dev/fb0"; - fd = open(dev,O_RDWR,0); - } - } - - if (fd == -1) { - xf86DrvMsg(scrnIndex, X_ERROR, - "open %s: %s\n", dev, strerror(errno)); - return -1; - } - - if (namep) { - if (-1 == ioctl(fd,FBIOGET_FSCREENINFO,(void*)(&fix))) { - *namep = NULL; - xf86DrvMsg(scrnIndex, X_ERROR, - "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); - return -1; - } else { - *namep = xnfalloc(16); - strncpy(*namep,fix.id,16); - } - } - return fd; -} - -/* -------------------------------------------------------------------- */ - -Bool -fbdevHWProbe(struct pci_device * pPci, char *device,char **namep) -{ - int fd; - - if (pPci) - fd = fbdev_open_pci(pPci,namep); - else - fd = fbdev_open(-1,device,namep); - - if (-1 == fd) - return FALSE; - close(fd); - return TRUE; -} - -Bool -fbdevHWInit(ScrnInfoPtr pScrn, struct pci_device * pPci, char *device) -{ - fbdevHWPtr fPtr; - - fbdevHWGetRec(pScrn); - fPtr = FBDEVHWPTR(pScrn); - - /* open device */ - if (pPci) - fPtr->fd = fbdev_open_pci(pPci,NULL); - else - fPtr->fd = fbdev_open(pScrn->scrnIndex,device,NULL); - if (-1 == fPtr->fd) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to open framebuffer device, consult warnings" - " and/or errors above for possible reasons\n" - "\t(you may have to look at the server log to see" - " warnings)\n"); - return FALSE; - } - - /* get current fb device settings */ - if (-1 == ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "ioctl FBIOGET_FSCREENINFO: %s\n", - strerror(errno)); - return FALSE; - } - if (-1 == ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->var))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "ioctl FBIOGET_VSCREENINFO: %s\n", - strerror(errno)); - return FALSE; - } - - /* we can use the current settings as "buildin mode" */ - fbdev2xfree_timing(&fPtr->var, &fPtr->buildin); - fPtr->buildin.name = "current"; - fPtr->buildin.next = &fPtr->buildin; - fPtr->buildin.prev = &fPtr->buildin; - fPtr->buildin.type |= M_T_BUILTIN; - - return TRUE; -} - -char* -fbdevHWGetName(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - return fPtr->fix.id; -} - -int -fbdevHWGetDepth(ScrnInfoPtr pScrn, int *fbbpp) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (fbbpp) - *fbbpp = fPtr->var.bits_per_pixel; - - if (fPtr->fix.visual == FB_VISUAL_TRUECOLOR || - fPtr->fix.visual == FB_VISUAL_DIRECTCOLOR) - return fPtr->var.red.length+fPtr->var.green.length+ - fPtr->var.blue.length; - else - return fPtr->var.bits_per_pixel; -} - -int -fbdevHWGetLineLength(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (fPtr->fix.line_length) - return fPtr->fix.line_length; - else - return fPtr->var.xres_virtual*fPtr->var.bits_per_pixel/8; -} - -int -fbdevHWGetType(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - return fPtr->fix.type; -} - -int -fbdevHWGetVidmem(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - return fPtr->fix.smem_len; -} - -static Bool -fbdevHWSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool check) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - struct fb_var_screeninfo req_var = fPtr->var, set_var; - - xfree2fbdev_fblayout(pScrn, &req_var); - xfree2fbdev_timing(mode, &req_var); - -#if DEBUG - print_xfree_mode("init", mode); - print_fbdev_mode("init", &req_var); -#endif - - set_var = req_var; - - if (check) - set_var.activate = FB_ACTIVATE_TEST; - - if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void*)(&set_var))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); - return FALSE; - } - - if (!fbdev_modes_equal(&set_var, &req_var)) { - if (!check) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUT_VSCREENINFO succeeded but modified " - "mode\n"); -#if DEBUG - print_fbdev_mode("returned", &set_var); -#endif - return FALSE; - } - - if (!check) - fPtr->var = set_var; - - return TRUE; -} - -void -fbdevHWSetVideoModes(ScrnInfoPtr pScrn) -{ - char **modename; - DisplayModePtr mode,this,last = pScrn->modes; - - if (NULL == pScrn->display->modes) - return; - - pScrn->virtualX = pScrn->display->virtualX; - pScrn->virtualY = pScrn->display->virtualY; - - for (modename = pScrn->display->modes; *modename != NULL; modename++) { - for (mode = pScrn->monitor->Modes; mode != NULL; mode = mode->next) - if (0 == strcmp(mode->name,*modename)) - break; - if (NULL == mode) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "\tmode \"%s\" not found\n", *modename); - continue; - } - - if (!fbdevHWSetMode(pScrn, mode, TRUE)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "\tmode \"%s\" test failed\n", *modename); - continue; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "\tmode \"%s\" ok\n", *modename); - - if (pScrn->virtualX < mode->HDisplay) - pScrn->virtualX = mode->HDisplay; - if (pScrn->virtualY < mode->VDisplay) - pScrn->virtualY = mode->VDisplay; - - if (NULL == pScrn->modes) { - this = pScrn->modes = xf86DuplicateMode(mode); - this->next = this; - this->prev = this; - } else { - this = xf86DuplicateMode(mode); - this->next = pScrn->modes; - this->prev = last; - last->next = this; - pScrn->modes->prev = this; - } - last = this; - } -} - -DisplayModePtr -fbdevHWGetBuildinMode(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - return &fPtr->buildin; -} - -void -fbdevHWUseBuildinMode(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - pScrn->modes = &fPtr->buildin; - pScrn->virtualX = pScrn->display->virtualX; - pScrn->virtualY = pScrn->display->virtualY; - if (pScrn->virtualX < fPtr->buildin.HDisplay) - pScrn->virtualX = fPtr->buildin.HDisplay; - if (pScrn->virtualY < fPtr->buildin.VDisplay) - pScrn->virtualY = fPtr->buildin.VDisplay; -} - -/* -------------------------------------------------------------------- */ - -static void -calculateFbmem_len(fbdevHWPtr fPtr) -{ - fPtr->fboff = (unsigned long) fPtr->fix.smem_start & ~PAGE_MASK; - fPtr->fbmem_len = (fPtr->fboff+fPtr->fix.smem_len+~PAGE_MASK) & - PAGE_MASK; -} - - -void* -fbdevHWMapVidmem(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (NULL == fPtr->fbmem) { - calculateFbmem_len(fPtr); - fPtr->fbmem = mmap(NULL, fPtr->fbmem_len, PROT_READ | PROT_WRITE, - MAP_SHARED, fPtr->fd, 0); - if (-1 == (long)fPtr->fbmem) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "mmap fbmem: %s\n", strerror(errno)); - fPtr->fbmem = NULL; - } else { - /* Perhaps we'd better add fboff to fbmem and return 0 in - fbdevHWLinearOffset()? Of course we then need to mask - fPtr->fbmem with PAGE_MASK in fbdevHWUnmapVidmem() as - well. [geert] */ - } - } - pScrn->memPhysBase = (unsigned long)fPtr->fix.smem_start & (unsigned long)(PAGE_MASK); - pScrn->fbOffset = (unsigned long)fPtr->fix.smem_start & (unsigned long)(~PAGE_MASK); - return fPtr->fbmem; -} - -int -fbdevHWLinearOffset(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - return fPtr->fboff; -} - -Bool -fbdevHWUnmapVidmem(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (NULL != fPtr->fbmem) { - if (-1 == munmap(fPtr->fbmem, fPtr->fbmem_len)) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "munmap fbmem: %s\n", strerror(errno)); - fPtr->fbmem = NULL; - } - return TRUE; -} - -void* -fbdevHWMapMMIO(ScrnInfoPtr pScrn) -{ - unsigned int mmio_off; - - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (NULL == fPtr->mmio) { - /* tell the kernel not to use accels to speed up console scrolling */ - fPtr->var.accel_flags = 0; - if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->var))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); - return FALSE; - } - mmio_off = (unsigned long) fPtr->fix.mmio_start & ~PAGE_MASK; - fPtr->mmio_len = (mmio_off+fPtr->fix.mmio_len+~PAGE_MASK) & - PAGE_MASK; - if (NULL == fPtr->fbmem) - calculateFbmem_len(fPtr); - fPtr->mmio = mmap(NULL, fPtr->mmio_len, PROT_READ | PROT_WRITE, - MAP_SHARED, fPtr->fd, fPtr->fbmem_len); - if (-1 == (long)fPtr->mmio) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "mmap mmio: %s\n", strerror(errno)); - fPtr->mmio = NULL; - } else - fPtr->mmio += mmio_off; - } - return fPtr->mmio; -} - -Bool -fbdevHWUnmapMMIO(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (NULL != fPtr->mmio) { - if (-1 == munmap((void *)((unsigned long)fPtr->mmio & PAGE_MASK), fPtr->mmio_len)) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "munmap mmio: %s\n", strerror(errno)); - fPtr->mmio = NULL; - /* FIXME: restore var.accel_flags [geert] */ - } - return TRUE; -} - -/* -------------------------------------------------------------------- */ - -Bool -fbdevHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - pScrn->vtSema = TRUE; - - /* set */ - if (!fbdevHWSetMode(pScrn, mode, FALSE)) - return FALSE; - - /* read back */ - if (0 != ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); - return FALSE; - } - if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->var))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); - return FALSE; - } - - if (pScrn->defaultVisual == TrueColor || - pScrn->defaultVisual == DirectColor) { - /* XXX: This is a hack, but it should be a NOP for all the setups that - * worked before and actually seems to fix some others... - */ - pScrn->offset.red = fPtr->var.red.offset; - pScrn->offset.green = fPtr->var.green.offset; - pScrn->offset.blue = fPtr->var.blue.offset; - pScrn->mask.red = ((1 << fPtr->var.red.length) - 1) << fPtr->var.red.offset; - pScrn->mask.green = ((1 << fPtr->var.green.length) - 1) << fPtr->var.green.offset; - pScrn->mask.blue = ((1 << fPtr->var.blue.length) - 1) << fPtr->var.blue.offset; - } - - return TRUE; -} - -/* -------------------------------------------------------------------- */ -/* video mode save/restore */ -void -fbdevHWSave(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->saved_var))) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); -} - -void -fbdevHWRestore(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->saved_var))) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); -} - -/* -------------------------------------------------------------------- */ -/* callback for xf86HandleColormaps */ - -void -fbdevHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, - LOCO *colors, VisualPtr pVisual) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - struct fb_cmap cmap; - unsigned short red,green,blue; - int i; - - cmap.len = 1; - cmap.red = &red; - cmap.green = &green; - cmap.blue = &blue; - cmap.transp = NULL; - for (i = 0; i < numColors; i++) { - cmap.start = indices[i]; - red = (colors[indices[i]].red << 8) | - colors[indices[i]].red; - green = (colors[indices[i]].green << 8) | - colors[indices[i]].green; - blue = (colors[indices[i]].blue << 8) | - colors[indices[i]].blue; - if (-1 == ioctl(fPtr->fd,FBIOPUTCMAP,(void*)&cmap)) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUTCMAP: %s\n", strerror(errno)); - } -} - -/* -------------------------------------------------------------------- */ -/* these can be hooked directly into ScrnInfoRec */ - -ModeStatus -fbdevHWValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - if (!fbdevHWSetMode(pScrn, mode, TRUE)) - return MODE_BAD; - - return MODE_OK; -} - -Bool -fbdevHWSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - - if (!fbdevHWSetMode(pScrn, mode, FALSE)) - return FALSE; - - return TRUE; -} - -void -fbdevHWAdjustFrame(int scrnIndex, int x, int y, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if ( x < 0 || x + fPtr->var.xres > fPtr->var.xres_virtual || - y < 0 || y + fPtr->var.yres > fPtr->var.yres_virtual ) - return; - - fPtr->var.xoffset = x; - fPtr->var.yoffset = y; - if (-1 == ioctl(fPtr->fd,FBIOPAN_DISPLAY,(void*)&fPtr->var)) - xf86DrvMsgVerb(scrnIndex, X_WARNING, 5, - "FBIOPAN_DISPLAY: %s\n", strerror(errno)); -} - -Bool -fbdevHWEnterVT(int scrnIndex, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) - return FALSE; - fbdevHWAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - return TRUE; -} - -void -fbdevHWLeaveVT(int scrnIndex, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - fbdevHWRestore(pScrn); -} - -void -fbdevHWDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - unsigned long fbmode; - - if (!pScrn->vtSema) - return; - - switch (mode) { - case DPMSModeOn: - fbmode = 0; - break; - case DPMSModeStandby: - fbmode = 2; - break; - case DPMSModeSuspend: - fbmode = 3; - break; - case DPMSModeOff: - fbmode = 4; - break; - default: - return; - } - - if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)fbmode)) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOBLANK: %s\n", strerror(errno)); -} - -Bool -fbdevHWSaveScreen(ScreenPtr pScreen, int mode) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - unsigned long unblank; - - if (!pScrn->vtSema) - return TRUE; - - unblank = xf86IsUnblank(mode); - - if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)(1-unblank))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOBLANK: %s\n", strerror(errno)); - return FALSE; - } - - return TRUE; -} - -xf86SwitchModeProc * -fbdevHWSwitchModeWeak(void) { return fbdevHWSwitchMode; } - -xf86AdjustFrameProc * -fbdevHWAdjustFrameWeak(void) { return fbdevHWAdjustFrame; } - -xf86EnterVTProc * -fbdevHWEnterVTWeak(void) { return fbdevHWEnterVT; } - -xf86LeaveVTProc * -fbdevHWLeaveVTWeak(void) { return fbdevHWLeaveVT; } - -xf86ValidModeProc * -fbdevHWValidModeWeak(void) { return fbdevHWValidMode; } - -xf86DPMSSetProc * -fbdevHWDPMSSetWeak(void) { return fbdevHWDPMSSet; } - -xf86LoadPaletteProc * -fbdevHWLoadPaletteWeak(void) { return fbdevHWLoadPalette; } - -SaveScreenProcPtr -fbdevHWSaveScreenWeak(void) { return fbdevHWSaveScreen; } +/* all driver need this */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "xf86.h" +#include "xf86_OSproc.h" + +/* pci stuff */ +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "xf86cmap.h" + +#include "fbdevhw.h" +#include "fbpriv.h" +#include "globals.h" +#include + +#define PAGE_MASK (~(getpagesize() - 1)) + +static XF86ModuleVersionInfo fbdevHWVersRec = +{ + "fbdevhw", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 0, 0, 2, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} +}; + +_X_EXPORT XF86ModuleData fbdevhwModuleData = { + &fbdevHWVersRec, + NULL, + NULL +}; + +#include +#include +#include +#include +#include +#include +#include + +/* -------------------------------------------------------------------- */ +/* our private data, and two functions to allocate/free this */ + +#define FBDEVHWPTRLVAL(p) (p)->privates[fbdevHWPrivateIndex].ptr +#define FBDEVHWPTR(p) ((fbdevHWPtr)(FBDEVHWPTRLVAL(p))) + +static int fbdevHWPrivateIndex = -1; + +typedef struct { + /* framebuffer device: filename (/dev/fb*), handle, more */ + char* device; + int fd; + void* fbmem; + unsigned int fbmem_len; + unsigned int fboff; + char* mmio; + unsigned int mmio_len; + + /* current hardware state */ + struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; + + /* saved video mode */ + struct fb_var_screeninfo saved_var; + + /* buildin video mode */ + DisplayModeRec buildin; + +} fbdevHWRec, *fbdevHWPtr; + +Bool +fbdevHWGetRec(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr; + + if (fbdevHWPrivateIndex < 0) + fbdevHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + + if (FBDEVHWPTR(pScrn) != NULL) + return TRUE; + + fPtr = FBDEVHWPTRLVAL(pScrn) = xnfcalloc(sizeof(fbdevHWRec), 1); + return TRUE; +} + +void +fbdevHWFreeRec(ScrnInfoPtr pScrn) +{ + if (fbdevHWPrivateIndex < 0) + return; + if (FBDEVHWPTR(pScrn) == NULL) + return; + free(FBDEVHWPTR(pScrn)); + FBDEVHWPTRLVAL(pScrn) = NULL; +} + +int +fbdevHWGetFD(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr; + + fbdevHWGetRec(pScrn); + fPtr = FBDEVHWPTR(pScrn); + + return fPtr->fd; +} + +/* -------------------------------------------------------------------- */ +/* some helpers for printing debug informations */ + +#if DEBUG +static void +print_fbdev_mode(char *txt, struct fb_var_screeninfo *var) +{ + ErrorF( "fbdev %s mode:\t%d %d %d %d %d %d %d %d %d %d %d:%d:%d\n", + txt,var->pixclock, + var->xres, var->right_margin, var->hsync_len, var->left_margin, + var->yres, var->lower_margin, var->vsync_len, var->upper_margin, + var->bits_per_pixel, + var->red.length, var->green.length, var->blue.length); +} + +static void +print_xfree_mode(char *txt, DisplayModePtr mode) +{ + ErrorF( "xfree %s mode:\t%d %d %d %d %d %d %d %d %d\n", + txt,mode->Clock, + mode->HDisplay, mode->HSyncStart, mode->HSyncEnd, mode->HTotal, + mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, mode->VTotal); +} +#endif + +/* -------------------------------------------------------------------- */ +/* Convert timings between the XFree and the Frame Buffer Device */ + +static void +xfree2fbdev_fblayout(ScrnInfoPtr pScrn, struct fb_var_screeninfo *var) +{ + var->xres_virtual = pScrn->displayWidth ? pScrn->displayWidth : + pScrn->virtualX; + var->yres_virtual = pScrn->virtualY; + var->bits_per_pixel = pScrn->bitsPerPixel; + if (pScrn->defaultVisual == TrueColor || + pScrn->defaultVisual == DirectColor) { + var->red.length = pScrn->weight.red; + var->green.length = pScrn->weight.green; + var->blue.length = pScrn->weight.blue; + } else { + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + } +} + +static void +xfree2fbdev_timing(DisplayModePtr mode, struct fb_var_screeninfo *var) +{ + var->xres = mode->HDisplay; + var->yres = mode->VDisplay; + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + var->xoffset = var->yoffset = 0; + var->pixclock = mode->Clock ? 1000000000/mode->Clock : 0; + var->right_margin = mode->HSyncStart-mode->HDisplay; + var->hsync_len = mode->HSyncEnd-mode->HSyncStart; + var->left_margin = mode->HTotal-mode->HSyncEnd; + var->lower_margin = mode->VSyncStart-mode->VDisplay; + var->vsync_len = mode->VSyncEnd-mode->VSyncStart; + var->upper_margin = mode->VTotal-mode->VSyncEnd; + var->sync = 0; + if (mode->Flags & V_PHSYNC) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (mode->Flags & V_PVSYNC) + var->sync |= FB_SYNC_VERT_HIGH_ACT; + if (mode->Flags & V_PCSYNC) + var->sync |= FB_SYNC_COMP_HIGH_ACT; + if (mode->Flags & V_BCAST) + var->sync |= FB_SYNC_BROADCAST; + if (mode->Flags & V_INTERLACE) + var->vmode = FB_VMODE_INTERLACED; + else if (mode->Flags & V_DBLSCAN) + var->vmode = FB_VMODE_DOUBLE; + else + var->vmode = FB_VMODE_NONINTERLACED; +} + +static Bool +fbdev_modes_equal(struct fb_var_screeninfo *set, struct fb_var_screeninfo *req) +{ + return (set->xres_virtual >= req->xres_virtual && + set->yres_virtual >= req->yres_virtual && + set->bits_per_pixel == req->bits_per_pixel && + set->red.length == req->red.length && + set->green.length == req->green.length && + set->blue.length == req->blue.length && + set->xres == req->xres && set->yres == req->yres && + set->right_margin == req->right_margin && + set->hsync_len == req->hsync_len && + set->left_margin == req->left_margin && + set->lower_margin == req->lower_margin && + set->vsync_len == req->vsync_len && + set->upper_margin == req->upper_margin && + set->sync == req->sync && set->vmode == req->vmode); +} + +static void +fbdev2xfree_timing(struct fb_var_screeninfo *var, DisplayModePtr mode) +{ + mode->Clock = var->pixclock ? 1000000000/var->pixclock : 0; + mode->HDisplay = var->xres; + mode->HSyncStart = mode->HDisplay+var->right_margin; + mode->HSyncEnd = mode->HSyncStart+var->hsync_len; + mode->HTotal = mode->HSyncEnd+var->left_margin; + mode->VDisplay = var->yres; + mode->VSyncStart = mode->VDisplay+var->lower_margin; + mode->VSyncEnd = mode->VSyncStart+var->vsync_len; + mode->VTotal = mode->VSyncEnd+var->upper_margin; + mode->Flags = 0; + mode->Flags |= var->sync & FB_SYNC_HOR_HIGH_ACT ? V_PHSYNC : V_NHSYNC; + mode->Flags |= var->sync & FB_SYNC_VERT_HIGH_ACT ? V_PVSYNC : V_NVSYNC; + mode->Flags |= var->sync & FB_SYNC_COMP_HIGH_ACT ? V_PCSYNC : V_NCSYNC; + if (var->sync & FB_SYNC_BROADCAST) + mode->Flags |= V_BCAST; + if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) + mode->Flags |= V_INTERLACE; + else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) + mode->Flags |= V_DBLSCAN; + mode->SynthClock = mode->Clock; + mode->CrtcHDisplay = mode->HDisplay; + mode->CrtcHSyncStart = mode->HSyncStart; + mode->CrtcHSyncEnd = mode->HSyncEnd; + mode->CrtcHTotal = mode->HTotal; + mode->CrtcVDisplay = mode->VDisplay; + mode->CrtcVSyncStart = mode->VSyncStart; + mode->CrtcVSyncEnd = mode->VSyncEnd; + mode->CrtcVTotal = mode->VTotal; + mode->CrtcHAdjusted = FALSE; + mode->CrtcVAdjusted = FALSE; +} + + +/* -------------------------------------------------------------------- */ +/* open correct framebuffer device */ + +/** + * Try to find the framebuffer device for a given PCI device + */ +static int +fbdev_open_pci(struct pci_device * pPci, char **namep) +{ + struct fb_fix_screeninfo fix; + char filename[256]; + int fd, i; + + for (i = 0; i < 8; i++) { + sprintf(filename, + "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics/fb%d", + pPci->domain, pPci->bus, pPci->dev, pPci->func, i); + + fd = open(filename, O_RDONLY, 0); + if (fd < 0) { + sprintf(filename, + "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics:fb%d", + pPci->domain, pPci->bus, pPci->dev, pPci->func, i); + fd = open(filename, O_RDONLY, 0); + } + if (fd >= 0) { + close(fd); + sprintf(filename, "/dev/fb%d", i); + + fd = open(filename, O_RDWR, 0); + if (fd != -1) { + if (ioctl(fd, FBIOGET_FSCREENINFO, (void*) & fix) != -1) { + if (namep) { + *namep = xnfalloc(16); + strncpy(*namep,fix.id,16); + } + + return fd; + } + close(fd); + } + } + } + + if (namep) + *namep = NULL; + + xf86DrvMsg(-1, X_ERROR, "Unable to find a valid framebuffer device\n"); + return -1; +} + +static int +fbdev_open(int scrnIndex, char *dev, char** namep) +{ + struct fb_fix_screeninfo fix; + int fd; + + /* try argument (from XF86Config) first */ + if (dev) { + fd = open(dev,O_RDWR,0); + } else { + /* second: environment variable */ + dev = getenv("FRAMEBUFFER"); + if ((NULL == dev) || ((fd = open(dev,O_RDWR,0)) == -1)) { + /* last try: default device */ + dev = "/dev/fb0"; + fd = open(dev,O_RDWR,0); + } + } + + if (fd == -1) { + xf86DrvMsg(scrnIndex, X_ERROR, + "open %s: %s\n", dev, strerror(errno)); + return -1; + } + + if (namep) { + if (-1 == ioctl(fd,FBIOGET_FSCREENINFO,(void*)(&fix))) { + *namep = NULL; + xf86DrvMsg(scrnIndex, X_ERROR, + "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + return -1; + } else { + *namep = xnfalloc(16); + strncpy(*namep,fix.id,16); + } + } + return fd; +} + +/* -------------------------------------------------------------------- */ + +Bool +fbdevHWProbe(struct pci_device * pPci, char *device,char **namep) +{ + int fd; + + if (pPci) + fd = fbdev_open_pci(pPci,namep); + else + fd = fbdev_open(-1,device,namep); + + if (-1 == fd) + return FALSE; + close(fd); + return TRUE; +} + +Bool +fbdevHWInit(ScrnInfoPtr pScrn, struct pci_device * pPci, char *device) +{ + fbdevHWPtr fPtr; + + fbdevHWGetRec(pScrn); + fPtr = FBDEVHWPTR(pScrn); + + /* open device */ + if (pPci) + fPtr->fd = fbdev_open_pci(pPci,NULL); + else + fPtr->fd = fbdev_open(pScrn->scrnIndex,device,NULL); + if (-1 == fPtr->fd) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to open framebuffer device, consult warnings" + " and/or errors above for possible reasons\n" + "\t(you may have to look at the server log to see" + " warnings)\n"); + return FALSE; + } + + /* get current fb device settings */ + if (-1 == ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ioctl FBIOGET_FSCREENINFO: %s\n", + strerror(errno)); + return FALSE; + } + if (-1 == ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->var))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ioctl FBIOGET_VSCREENINFO: %s\n", + strerror(errno)); + return FALSE; + } + + /* we can use the current settings as "buildin mode" */ + fbdev2xfree_timing(&fPtr->var, &fPtr->buildin); + fPtr->buildin.name = "current"; + fPtr->buildin.next = &fPtr->buildin; + fPtr->buildin.prev = &fPtr->buildin; + fPtr->buildin.type |= M_T_BUILTIN; + + return TRUE; +} + +char* +fbdevHWGetName(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + return fPtr->fix.id; +} + +int +fbdevHWGetDepth(ScrnInfoPtr pScrn, int *fbbpp) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (fbbpp) + *fbbpp = fPtr->var.bits_per_pixel; + + if (fPtr->fix.visual == FB_VISUAL_TRUECOLOR || + fPtr->fix.visual == FB_VISUAL_DIRECTCOLOR) + return fPtr->var.red.length+fPtr->var.green.length+ + fPtr->var.blue.length; + else + return fPtr->var.bits_per_pixel; +} + +int +fbdevHWGetLineLength(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (fPtr->fix.line_length) + return fPtr->fix.line_length; + else + return fPtr->var.xres_virtual*fPtr->var.bits_per_pixel/8; +} + +int +fbdevHWGetType(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + return fPtr->fix.type; +} + +int +fbdevHWGetVidmem(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + return fPtr->fix.smem_len; +} + +static Bool +fbdevHWSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool check) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + struct fb_var_screeninfo req_var = fPtr->var, set_var; + + xfree2fbdev_fblayout(pScrn, &req_var); + xfree2fbdev_timing(mode, &req_var); + +#if DEBUG + print_xfree_mode("init", mode); + print_fbdev_mode("init", &req_var); +#endif + + set_var = req_var; + + if (check) + set_var.activate = FB_ACTIVATE_TEST; + + if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void*)(&set_var))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + + if (!fbdev_modes_equal(&set_var, &req_var)) { + if (!check) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUT_VSCREENINFO succeeded but modified " + "mode\n"); +#if DEBUG + print_fbdev_mode("returned", &set_var); +#endif + return FALSE; + } + + if (!check) + fPtr->var = set_var; + + return TRUE; +} + +void +fbdevHWSetVideoModes(ScrnInfoPtr pScrn) +{ + char **modename; + DisplayModePtr mode,this,last = pScrn->modes; + + if (NULL == pScrn->display->modes) + return; + + pScrn->virtualX = pScrn->display->virtualX; + pScrn->virtualY = pScrn->display->virtualY; + + for (modename = pScrn->display->modes; *modename != NULL; modename++) { + for (mode = pScrn->monitor->Modes; mode != NULL; mode = mode->next) + if (0 == strcmp(mode->name,*modename)) + break; + if (NULL == mode) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "\tmode \"%s\" not found\n", *modename); + continue; + } + + if (!fbdevHWSetMode(pScrn, mode, TRUE)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "\tmode \"%s\" test failed\n", *modename); + continue; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "\tmode \"%s\" ok\n", *modename); + + if (pScrn->virtualX < mode->HDisplay) + pScrn->virtualX = mode->HDisplay; + if (pScrn->virtualY < mode->VDisplay) + pScrn->virtualY = mode->VDisplay; + + if (NULL == pScrn->modes) { + this = pScrn->modes = xf86DuplicateMode(mode); + this->next = this; + this->prev = this; + } else { + this = xf86DuplicateMode(mode); + this->next = pScrn->modes; + this->prev = last; + last->next = this; + pScrn->modes->prev = this; + } + last = this; + } +} + +DisplayModePtr +fbdevHWGetBuildinMode(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + return &fPtr->buildin; +} + +void +fbdevHWUseBuildinMode(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + pScrn->modes = &fPtr->buildin; + pScrn->virtualX = pScrn->display->virtualX; + pScrn->virtualY = pScrn->display->virtualY; + if (pScrn->virtualX < fPtr->buildin.HDisplay) + pScrn->virtualX = fPtr->buildin.HDisplay; + if (pScrn->virtualY < fPtr->buildin.VDisplay) + pScrn->virtualY = fPtr->buildin.VDisplay; +} + +/* -------------------------------------------------------------------- */ + +static void +calculateFbmem_len(fbdevHWPtr fPtr) +{ + fPtr->fboff = (unsigned long) fPtr->fix.smem_start & ~PAGE_MASK; + fPtr->fbmem_len = (fPtr->fboff+fPtr->fix.smem_len+~PAGE_MASK) & + PAGE_MASK; +} + + +void* +fbdevHWMapVidmem(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (NULL == fPtr->fbmem) { + calculateFbmem_len(fPtr); + fPtr->fbmem = mmap(NULL, fPtr->fbmem_len, PROT_READ | PROT_WRITE, + MAP_SHARED, fPtr->fd, 0); + if (-1 == (long)fPtr->fbmem) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "mmap fbmem: %s\n", strerror(errno)); + fPtr->fbmem = NULL; + } else { + /* Perhaps we'd better add fboff to fbmem and return 0 in + fbdevHWLinearOffset()? Of course we then need to mask + fPtr->fbmem with PAGE_MASK in fbdevHWUnmapVidmem() as + well. [geert] */ + } + } + pScrn->memPhysBase = (unsigned long)fPtr->fix.smem_start & (unsigned long)(PAGE_MASK); + pScrn->fbOffset = (unsigned long)fPtr->fix.smem_start & (unsigned long)(~PAGE_MASK); + return fPtr->fbmem; +} + +int +fbdevHWLinearOffset(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + return fPtr->fboff; +} + +Bool +fbdevHWUnmapVidmem(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (NULL != fPtr->fbmem) { + if (-1 == munmap(fPtr->fbmem, fPtr->fbmem_len)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "munmap fbmem: %s\n", strerror(errno)); + fPtr->fbmem = NULL; + } + return TRUE; +} + +void* +fbdevHWMapMMIO(ScrnInfoPtr pScrn) +{ + unsigned int mmio_off; + + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (NULL == fPtr->mmio) { + /* tell the kernel not to use accels to speed up console scrolling */ + fPtr->var.accel_flags = 0; + if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->var))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + mmio_off = (unsigned long) fPtr->fix.mmio_start & ~PAGE_MASK; + fPtr->mmio_len = (mmio_off+fPtr->fix.mmio_len+~PAGE_MASK) & + PAGE_MASK; + if (NULL == fPtr->fbmem) + calculateFbmem_len(fPtr); + fPtr->mmio = mmap(NULL, fPtr->mmio_len, PROT_READ | PROT_WRITE, + MAP_SHARED, fPtr->fd, fPtr->fbmem_len); + if (-1 == (long)fPtr->mmio) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "mmap mmio: %s\n", strerror(errno)); + fPtr->mmio = NULL; + } else + fPtr->mmio += mmio_off; + } + return fPtr->mmio; +} + +Bool +fbdevHWUnmapMMIO(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (NULL != fPtr->mmio) { + if (-1 == munmap((void *)((unsigned long)fPtr->mmio & PAGE_MASK), fPtr->mmio_len)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "munmap mmio: %s\n", strerror(errno)); + fPtr->mmio = NULL; + /* FIXME: restore var.accel_flags [geert] */ + } + return TRUE; +} + +/* -------------------------------------------------------------------- */ + +Bool +fbdevHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + pScrn->vtSema = TRUE; + + /* set */ + if (!fbdevHWSetMode(pScrn, mode, FALSE)) + return FALSE; + + /* read back */ + if (0 != ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->var))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + + if (pScrn->defaultVisual == TrueColor || + pScrn->defaultVisual == DirectColor) { + /* XXX: This is a hack, but it should be a NOP for all the setups that + * worked before and actually seems to fix some others... + */ + pScrn->offset.red = fPtr->var.red.offset; + pScrn->offset.green = fPtr->var.green.offset; + pScrn->offset.blue = fPtr->var.blue.offset; + pScrn->mask.red = ((1 << fPtr->var.red.length) - 1) << fPtr->var.red.offset; + pScrn->mask.green = ((1 << fPtr->var.green.length) - 1) << fPtr->var.green.offset; + pScrn->mask.blue = ((1 << fPtr->var.blue.length) - 1) << fPtr->var.blue.offset; + } + + return TRUE; +} + +/* -------------------------------------------------------------------- */ +/* video mode save/restore */ +void +fbdevHWSave(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->saved_var))) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); +} + +void +fbdevHWRestore(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->saved_var))) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); +} + +/* -------------------------------------------------------------------- */ +/* callback for xf86HandleColormaps */ + +void +fbdevHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO *colors, VisualPtr pVisual) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + struct fb_cmap cmap; + unsigned short red,green,blue; + int i; + + cmap.len = 1; + cmap.red = &red; + cmap.green = &green; + cmap.blue = &blue; + cmap.transp = NULL; + for (i = 0; i < numColors; i++) { + cmap.start = indices[i]; + red = (colors[indices[i]].red << 8) | + colors[indices[i]].red; + green = (colors[indices[i]].green << 8) | + colors[indices[i]].green; + blue = (colors[indices[i]].blue << 8) | + colors[indices[i]].blue; + if (-1 == ioctl(fPtr->fd,FBIOPUTCMAP,(void*)&cmap)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUTCMAP: %s\n", strerror(errno)); + } +} + +/* -------------------------------------------------------------------- */ +/* these can be hooked directly into ScrnInfoRec */ + +ModeStatus +fbdevHWValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + if (!fbdevHWSetMode(pScrn, mode, TRUE)) + return MODE_BAD; + + return MODE_OK; +} + +Bool +fbdevHWSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + + if (!fbdevHWSetMode(pScrn, mode, FALSE)) + return FALSE; + + return TRUE; +} + +void +fbdevHWAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if ( x < 0 || x + fPtr->var.xres > fPtr->var.xres_virtual || + y < 0 || y + fPtr->var.yres > fPtr->var.yres_virtual ) + return; + + fPtr->var.xoffset = x; + fPtr->var.yoffset = y; + if (-1 == ioctl(fPtr->fd,FBIOPAN_DISPLAY,(void*)&fPtr->var)) + xf86DrvMsgVerb(scrnIndex, X_WARNING, 5, + "FBIOPAN_DISPLAY: %s\n", strerror(errno)); +} + +Bool +fbdevHWEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) + return FALSE; + fbdevHWAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + return TRUE; +} + +void +fbdevHWLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + fbdevHWRestore(pScrn); +} + +void +fbdevHWDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + unsigned long fbmode; + + if (!pScrn->vtSema) + return; + + switch (mode) { + case DPMSModeOn: + fbmode = 0; + break; + case DPMSModeStandby: + fbmode = 2; + break; + case DPMSModeSuspend: + fbmode = 3; + break; + case DPMSModeOff: + fbmode = 4; + break; + default: + return; + } + + if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)fbmode)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOBLANK: %s\n", strerror(errno)); +} + +Bool +fbdevHWSaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + unsigned long unblank; + + if (!pScrn->vtSema) + return TRUE; + + unblank = xf86IsUnblank(mode); + + if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)(1-unblank))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOBLANK: %s\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +xf86SwitchModeProc * +fbdevHWSwitchModeWeak(void) { return fbdevHWSwitchMode; } + +xf86AdjustFrameProc * +fbdevHWAdjustFrameWeak(void) { return fbdevHWAdjustFrame; } + +xf86EnterVTProc * +fbdevHWEnterVTWeak(void) { return fbdevHWEnterVT; } + +xf86LeaveVTProc * +fbdevHWLeaveVTWeak(void) { return fbdevHWLeaveVT; } + +xf86ValidModeProc * +fbdevHWValidModeWeak(void) { return fbdevHWValidMode; } + +xf86DPMSSetProc * +fbdevHWDPMSSetWeak(void) { return fbdevHWDPMSSet; } + +xf86LoadPaletteProc * +fbdevHWLoadPaletteWeak(void) { return fbdevHWLoadPalette; } + +SaveScreenProcPtr +fbdevHWSaveScreenWeak(void) { return fbdevHWSaveScreen; } diff --git a/xorg-server/hw/xfree86/modes/xf86RandR12.c b/xorg-server/hw/xfree86/modes/xf86RandR12.c index bd8421713..cb20d1c35 100644 --- a/xorg-server/hw/xfree86/modes/xf86RandR12.c +++ b/xorg-server/hw/xfree86/modes/xf86RandR12.c @@ -1,1824 +1,1823 @@ -/* - * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 "xf86.h" -#include "os.h" -#include "globals.h" -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86DDC.h" -#include "mipointer.h" -#include "windowstr.h" -#include "inputstr.h" -#include -#include - -#include "xf86Crtc.h" -#include "xf86RandR12.h" - -typedef struct _xf86RandR12Info { - int virtualX; - int virtualY; - int mmWidth; - int mmHeight; - int maxX; - int maxY; - int pointerX; - int pointerY; - Rotation rotation; /* current mode */ - Rotation supported_rotations; /* driver supported */ - - /* Used to wrap EnterVT so we can re-probe the outputs when a laptop unsuspends - * (actually, any time that we switch back into our VT). - * - * See https://bugs.freedesktop.org/show_bug.cgi?id=21554 - */ - xf86EnterVTProc *orig_EnterVT; -} XF86RandRInfoRec, *XF86RandRInfoPtr; - -#ifdef RANDR_12_INTERFACE -static Bool xf86RandR12Init12 (ScreenPtr pScreen); -static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen); -#endif - -static int xf86RandR12Generation; - -static DevPrivateKeyRec xf86RandR12KeyRec; -static DevPrivateKey xf86RandR12Key; -#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) \ - dixLookupPrivate(&(p)->devPrivates, xf86RandR12Key)) - - -static int -xf86RandR12ModeRefresh (DisplayModePtr mode) -{ - if (mode->VRefresh) - return (int) (mode->VRefresh + 0.5); - else - return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); -} - -/* Adapt panning area; return TRUE if panning area was valid without adaption */ -static int -xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeight) -{ - int ret = TRUE; - - if (crtc->version < 2) - return FALSE; - - if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1) { - /* Panning in X is disabled */ - if (crtc->panningTotalArea.x1 || crtc->panningTotalArea.x2) - /* Illegal configuration -> fail/disable */ - ret = FALSE; - crtc->panningTotalArea.x1 = crtc->panningTotalArea.x2 = 0; - crtc->panningTrackingArea.x1 = crtc->panningTrackingArea.x2 = 0; - crtc->panningBorder[0] = crtc->panningBorder[2] = 0; - } else { - /* Panning in X is enabled */ - if (crtc->panningTotalArea.x1 < 0) { - /* Panning region outside screen -> move inside */ - crtc->panningTotalArea.x2 -= crtc->panningTotalArea.x1; - crtc->panningTotalArea.x1 = 0; - ret = FALSE; - } - if (crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay) { - /* Panning region smaller than displayed area -> crop to displayed area */ - crtc->panningTotalArea.x2 = crtc->panningTotalArea.x1 + crtc->mode.HDisplay; - ret = FALSE; - } - if (crtc->panningTotalArea.x2 > screenWidth) { - /* Panning region larger than screen -> move inside, then crop to screen */ - crtc->panningTotalArea.x1 -= crtc->panningTotalArea.x2 - screenWidth; - crtc->panningTotalArea.x2 = screenWidth; - ret = FALSE; - if (crtc->panningTotalArea.x1 < 0) - crtc->panningTotalArea.x1 = 0; - } - if (crtc->panningBorder[0] + crtc->panningBorder[2] > crtc->mode.HDisplay) { - /* Borders too large -> set to 0 */ - crtc->panningBorder[0] = crtc->panningBorder[2] = 0; - ret = FALSE; - } - } - - if (crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) { - /* Panning in Y is disabled */ - if (crtc->panningTotalArea.y1 || crtc->panningTotalArea.y2) - /* Illegal configuration -> fail/disable */ - ret = FALSE; - crtc->panningTotalArea.y1 = crtc->panningTotalArea.y2 = 0; - crtc->panningTrackingArea.y1 = crtc->panningTrackingArea.y2 = 0; - crtc->panningBorder[1] = crtc->panningBorder[3] = 0; - } else { - /* Panning in Y is enabled */ - if (crtc->panningTotalArea.y1 < 0) { - /* Panning region outside screen -> move inside */ - crtc->panningTotalArea.y2 -= crtc->panningTotalArea.y1; - crtc->panningTotalArea.y1 = 0; - ret = FALSE; - } - if (crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay) { - /* Panning region smaller than displayed area -> crop to displayed area */ - crtc->panningTotalArea.y2 = crtc->panningTotalArea.y1 + crtc->mode.VDisplay; - ret = FALSE; - } - if (crtc->panningTotalArea.y2 > screenHeight) { - /* Panning region larger than screen -> move inside, then crop to screen */ - crtc->panningTotalArea.y1 -= crtc->panningTotalArea.y2 - screenHeight; - crtc->panningTotalArea.y2 = screenHeight; - ret = FALSE; - if (crtc->panningTotalArea.y1 < 0) - crtc->panningTotalArea.y1 = 0; - } - if (crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) { - /* Borders too large -> set to 0 */ - crtc->panningBorder[1] = crtc->panningBorder[3] = 0; - ret = FALSE; - } - } - - return ret; -} - -/* - * The heart of the panning operation: - * - * Given a frame buffer position (fb_x, fb_y), - * and a crtc position (crtc_x, crtc_y), - * and a transform matrix which maps frame buffer to crtc, - * compute a panning position (pan_x, pan_y) that - * makes the resulting transform line those two up - */ - -static void -xf86ComputeCrtcPan (Bool transform_in_use, - struct pixman_f_transform *m, - double screen_x, double screen_y, - double crtc_x, double crtc_y, - int old_pan_x, int old_pan_y, - int *new_pan_x, int *new_pan_y) -{ - if (transform_in_use) { - /* - * Given the current transform, M, the current position - * on the Screen, S, and the desired position on the CRTC, - * C, compute a translation, T, such that: - * - * M T S = C - * - * where T is of the form - * - * | 1 0 dx | - * | 0 1 dy | - * | 0 0 1 | - * - * M T S = - * | M00 Sx + M01 Sy + M00 dx + M01 dy + M02 | | Cx F | - * | M10 Sx + M11 Sy + M10 dx + M11 dy + M12 | = | Cy F | - * | M20 Sx + M21 Sy + M20 dx + M21 dy + M22 | | F | - * - * R = M S - * - * Cx F = M00 dx + M01 dy + R0 - * Cy F = M10 dx + M11 dy + R1 - * F = M20 dx + M21 dy + R2 - * - * Zero out dx, then dy - * - * F (Cx M10 - Cy M00) = - * (M10 M01 - M00 M11) dy + M10 R0 - M00 R1 - * F (M10 - Cy M20) = - * (M10 M21 - M20 M11) dy + M10 R2 - M20 R1 - * - * F (Cx M11 - Cy M01) = - * (M11 M00 - M01 M10) dx + M11 R0 - M01 R1 - * F (M11 - Cy M21) = - * (M11 M20 - M21 M10) dx + M11 R2 - M21 R1 - * - * Make some temporaries - * - * T = | Cx M10 - Cy M00 | - * | Cx M11 - Cy M01 | - * - * U = | M10 M01 - M00 M11 | - * | M11 M00 - M01 M10 | - * - * Q = | M10 R0 - M00 R1 | - * | M11 R0 - M01 R1 | - * - * P = | M10 - Cy M20 | - * | M11 - Cy M21 | - * - * W = | M10 M21 - M20 M11 | - * | M11 M20 - M21 M10 | - * - * V = | M10 R2 - M20 R1 | - * | M11 R2 - M21 R1 | - * - * Rewrite: - * - * F T0 = U0 dy + Q0 - * F P0 = W0 dy + V0 - * F T1 = U1 dx + Q1 - * F P1 = W1 dx + V1 - * - * Solve for F (two ways) - * - * F (W0 T0 - U0 P0) = W0 Q0 - U0 V0 - * - * W0 Q0 - U0 V0 - * F = ------------- - * W0 T0 - U0 P0 - * - * F (W1 T1 - U1 P1) = W1 Q1 - U1 V1 - * - * W1 Q1 - U1 V1 - * F = ------------- - * W1 T1 - U1 P1 - * - * We'll use which ever solution works (denominator != 0) - * - * Finally, solve for dx and dy: - * - * dx = (F T1 - Q1) / U1 - * dx = (F P1 - V1) / W1 - * - * dy = (F T0 - Q0) / U0 - * dy = (F P0 - V0) / W0 - */ - double r[3]; - double q[2], u[2], t[2], v[2], w[2], p[2]; - double f; - struct pict_f_vector d; - int i; - - /* Get the un-normalized crtc coordinates again */ - for (i = 0; i < 3; i++) - r[i] = m->m[i][0] * screen_x + m->m[i][1] * screen_y + m->m[i][2]; - - /* Combine values into temporaries */ - for (i = 0; i < 2; i++) { - q[i] = m->m[1][i] * r[0] - m->m[0][i] * r[1]; - u[i] = m->m[1][i] * m->m[0][1-i] - m->m[0][i] * m->m[1][1-i]; - t[i] = m->m[1][i] * crtc_x - m->m[0][i] * crtc_y; - - v[i] = m->m[1][i] * r[2] - m->m[2][i] * r[1]; - w[i] = m->m[1][i] * m->m[2][1-i] - m->m[2][i] * m->m[1][1-i]; - p[i] = m->m[1][i] - m->m[2][i] * crtc_y; - } - - /* Find a way to compute f */ - f = 0; - for (i = 0; i < 2; i++) { - double a = w[i] * q[i] - u[i] * v[i]; - double b = w[i] * t[i] - u[i] * p[i]; - if (b != 0) { - f = a/b; - break; - } - } - - /* Solve for the resulting transform vector */ - for (i = 0; i < 2; i++) { - if (u[i]) - d.v[1-i] = (t[i] * f - q[i]) / u[i]; - else if (w[1]) - d.v[1-i] = (p[i] * f - v[i]) / w[i]; - else - d.v[1-i] = 0; - } - *new_pan_x = old_pan_x - floor (d.v[0] + 0.5); - *new_pan_y = old_pan_y - floor (d.v[1] + 0.5); - } else { - *new_pan_x = screen_x - crtc_x; - *new_pan_y = screen_y - crtc_y; - } -} - -static void -xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y) -{ - int newX, newY; - int width, height; - Bool panned = FALSE; - - if (crtc->version < 2) - return; - - if (! crtc->enabled || - (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1 && - crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1)) - return; - - newX = crtc->x; - newY = crtc->y; - width = crtc->mode.HDisplay; - height = crtc->mode.VDisplay; - - if ((crtc->panningTrackingArea.x2 <= crtc->panningTrackingArea.x1 || - (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2)) && - (crtc->panningTrackingArea.y2 <= crtc->panningTrackingArea.y1 || - (y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2))) - { - struct pict_f_vector c; - - /* - * Pre-clip the mouse position to the panning area so that we don't - * push the crtc outside. This doesn't deal with changes to the - * panning values, only mouse position changes. - */ - if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) - { - if (x < crtc->panningTotalArea.x1) - x = crtc->panningTotalArea.x1; - if (x >= crtc->panningTotalArea.x2) - x = crtc->panningTotalArea.x2 - 1; - } - if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) - { - if (y < crtc->panningTotalArea.y1) - y = crtc->panningTotalArea.y1; - if (y >= crtc->panningTotalArea.y2) - y = crtc->panningTotalArea.y2 - 1; - } - - c.v[0] = x; - c.v[1] = y; - c.v[2] = 1.0; - if (crtc->transform_in_use) { - pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c); - } else { - c.v[0] -= crtc->x; - c.v[1] -= crtc->y; - } - - if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { - if (c.v[0] < crtc->panningBorder[0]) { - c.v[0] = crtc->panningBorder[0]; - panned = TRUE; - } - if (c.v[0] >= width - crtc->panningBorder[2]) { - c.v[0] = width - crtc->panningBorder[2] - 1; - panned = TRUE; - } - } - if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { - if (c.v[1] < crtc->panningBorder[1]) { - c.v[1] = crtc->panningBorder[1]; - panned = TRUE; - } - if (c.v[1] >= height - crtc->panningBorder[3]) { - c.v[1] = height - crtc->panningBorder[3] - 1; - panned = TRUE; - } - } - if (panned) - xf86ComputeCrtcPan (crtc->transform_in_use, - &crtc->f_framebuffer_to_crtc, - x, y, c.v[0], c.v[1], - newX, newY, &newX, &newY); - } - - /* - * Ensure that the crtc is within the panning region. - * - * XXX This computation only works when we do not have a transform - * in use. - */ - if (!crtc->transform_in_use) - { - /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */ - if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { - if (newX > crtc->panningTotalArea.x2 - width) - newX = crtc->panningTotalArea.x2 - width; - if (newX < crtc->panningTotalArea.x1) - newX = crtc->panningTotalArea.x1; - } - if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { - if (newY > crtc->panningTotalArea.y2 - height) - newY = crtc->panningTotalArea.y2 - height; - if (newY < crtc->panningTotalArea.y1) - newY = crtc->panningTotalArea.y1; - } - } - if (newX != crtc->x || newY != crtc->y) - xf86CrtcSetOrigin (crtc, newX, newY); -} - -static Bool -xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) -{ - RRScreenSizePtr pSize; - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - DisplayModePtr mode; - int refresh0 = 60; - int maxX = 0, maxY = 0; - - *rotations = randrp->supported_rotations; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = scrp->virtualX; - randrp->virtualY = scrp->virtualY; - } - - /* Re-probe the outputs for new monitors or modes */ - if (scrp->vtSema) - { - xf86ProbeOutputModes (scrp, 0, 0); - xf86SetScrnInfoModes (scrp); - } - - for (mode = scrp->modes; ; mode = mode->next) - { - int refresh = xf86RandR12ModeRefresh (mode); - if (randrp->maxX == 0 || randrp->maxY == 0) - { - if (maxX < mode->HDisplay) - maxX = mode->HDisplay; - if (maxY < mode->VDisplay) - maxY = mode->VDisplay; - } - if (mode == scrp->modes) - refresh0 = refresh; - pSize = RRRegisterSize (pScreen, - mode->HDisplay, mode->VDisplay, - randrp->mmWidth, randrp->mmHeight); - if (!pSize) - return FALSE; - RRRegisterRate (pScreen, pSize, refresh); - - if (xf86ModesEqual(mode, scrp->currentMode)) - { - RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); - } - if (mode->next == scrp->modes) - break; - } - - if (randrp->maxX == 0 || randrp->maxY == 0) - { - randrp->maxX = maxX; - randrp->maxY = maxY; - } - - return TRUE; -} - -static Bool -xf86RandR12SetMode (ScreenPtr pScreen, - DisplayModePtr mode, - Bool useVirtual, - int mmWidth, - int mmHeight) -{ - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - int oldWidth = pScreen->width; - int oldHeight = pScreen->height; - int oldmmWidth = pScreen->mmWidth; - int oldmmHeight = pScreen->mmHeight; - WindowPtr pRoot = pScreen->root; - DisplayModePtr currentMode = NULL; - Bool ret = TRUE; - - if (pRoot) - (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); - if (useVirtual) - { - scrp->virtualX = randrp->virtualX; - scrp->virtualY = randrp->virtualY; - } - else - { - scrp->virtualX = mode->HDisplay; - scrp->virtualY = mode->VDisplay; - } - - if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) - { - /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ - pScreen->width = scrp->virtualY; - pScreen->height = scrp->virtualX; - pScreen->mmWidth = mmHeight; - pScreen->mmHeight = mmWidth; - } - else - { - pScreen->width = scrp->virtualX; - pScreen->height = scrp->virtualY; - pScreen->mmWidth = mmWidth; - pScreen->mmHeight = mmHeight; - } - if (scrp->currentMode == mode) { - /* Save current mode */ - currentMode = scrp->currentMode; - /* Reset, just so we ensure the drivers SwitchMode is called */ - scrp->currentMode = NULL; - } - /* - * We know that if the driver failed to SwitchMode to the rotated - * version, then it should revert back to it's prior mode. - */ - if (!xf86SwitchMode (pScreen, mode)) - { - ret = FALSE; - scrp->virtualX = pScreen->width = oldWidth; - scrp->virtualY = pScreen->height = oldHeight; - pScreen->mmWidth = oldmmWidth; - pScreen->mmHeight = oldmmHeight; - scrp->currentMode = currentMode; - } - - /* - * Make sure the layout is correct - */ - xf86ReconfigureLayout(); - - /* - * Make sure the whole screen is visible - */ - xf86SetViewport (pScreen, pScreen->width, pScreen->height); - xf86SetViewport (pScreen, 0, 0); - if (pRoot) - (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); - return ret; -} - -Bool -xf86RandR12SetConfig (ScreenPtr pScreen, - Rotation rotation, - int rate, - RRScreenSizePtr pSize) -{ - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - DisplayModePtr mode; - int pos[MAXDEVICES][2]; - Bool useVirtual = FALSE; - int maxX = 0, maxY = 0; - Rotation oldRotation = randrp->rotation; - DeviceIntPtr dev; - Bool view_adjusted = FALSE; - - randrp->rotation = rotation; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = scrp->virtualX; - randrp->virtualY = scrp->virtualY; - } - - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (!IsMaster(dev) && !IsFloating(dev)) - continue; - - miPointerGetPosition(dev, &pos[dev->id][0], &pos[dev->id][1]); - } - - for (mode = scrp->modes; ; mode = mode->next) - { - if (randrp->maxX == 0 || randrp->maxY == 0) - { - if (maxX < mode->HDisplay) - maxX = mode->HDisplay; - if (maxY < mode->VDisplay) - maxY = mode->VDisplay; - } - if (mode->HDisplay == pSize->width && - mode->VDisplay == pSize->height && - (rate == 0 || xf86RandR12ModeRefresh (mode) == rate)) - break; - if (mode->next == scrp->modes) - { - if (pSize->width == randrp->virtualX && - pSize->height == randrp->virtualY) - { - mode = scrp->modes; - useVirtual = TRUE; - break; - } - if (randrp->maxX == 0 || randrp->maxY == 0) - { - randrp->maxX = maxX; - randrp->maxY = maxY; - } - return FALSE; - } - } - - if (randrp->maxX == 0 || randrp->maxY == 0) - { - randrp->maxX = maxX; - randrp->maxY = maxY; - } - - if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth, - pSize->mmHeight)) { - randrp->rotation = oldRotation; - return FALSE; - } - - /* - * Move the cursor back where it belongs; SwitchMode repositions it - * FIXME: duplicated code, see modes/xf86RandR12.c - */ - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (!IsMaster(dev) && !IsFloating(dev)) - continue; - - if (pScreen == miPointerGetScreen(dev)) { - int px = pos[dev->id][0]; - int py = pos[dev->id][1]; - - px = (px >= pScreen->width ? (pScreen->width - 1) : px); - py = (py >= pScreen->height ? (pScreen->height - 1) : py); - - /* Setting the viewpoint makes only sense on one device */ - if (!view_adjusted && IsMaster(dev)) { - xf86SetViewport(pScreen, px, py); - view_adjusted = TRUE; - } - - (*pScreen->SetCursorPosition) (dev, pScreen, px, py, FALSE); - } - } - - return TRUE; -} - -static Bool -xf86RandR12ScreenSetSize (ScreenPtr pScreen, - CARD16 width, - CARD16 height, - CARD32 mmWidth, - CARD32 mmHeight) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - WindowPtr pRoot = pScreen->root; - PixmapPtr pScrnPix; - Bool ret = FALSE; - int c; - - if (xf86RandR12Key) { - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = pScrn->virtualX; - randrp->virtualY = pScrn->virtualY; - } - } - if (pRoot && pScrn->vtSema) - (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); - - /* Let the driver update virtualX and virtualY */ - if (!(*config->funcs->resize)(pScrn, width, height)) - goto finish; - - ret = TRUE; - /* Update panning information */ - for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = config->crtc[c]; - if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 || - crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { - if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1) - crtc->panningTotalArea.x2 += width - pScreen->width; - if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1) - crtc->panningTotalArea.y2 += height - pScreen->height; - if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1) - crtc->panningTrackingArea.x2 += width - pScreen->width; - if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1) - crtc->panningTrackingArea.y2 += height - pScreen->height; - xf86RandR13VerifyPanningArea (crtc, width, height); - xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); - } - } - - pScrnPix = (*pScreen->GetScreenPixmap)(pScreen); - pScreen->width = pScrnPix->drawable.width = width; - pScreen->height = pScrnPix->drawable.height = height; - randrp->mmWidth = pScreen->mmWidth = mmWidth; - randrp->mmHeight = pScreen->mmHeight = mmHeight; - - xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1); - xf86SetViewport (pScreen, 0, 0); - -finish: - if (pRoot && pScrn->vtSema) - (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); -#if RANDR_12_INTERFACE - if (xf86RandR12Key && pScreen->root && ret) - RRScreenSizeNotify (pScreen); -#endif - return ret; -} - -Rotation -xf86RandR12GetRotation(ScreenPtr pScreen) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - - return randrp->rotation; -} - -Bool -xf86RandR12CreateScreenResources (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config; - XF86RandRInfoPtr randrp; - int c; - int width, height; - int mmWidth, mmHeight; -#ifdef PANORAMIX - /* XXX disable RandR when using Xinerama */ - if (!noPanoramiXExtension) - return TRUE; -#endif - - config = XF86_CRTC_CONFIG_PTR(pScrn); - randrp = XF86RANDRINFO(pScreen); - /* - * Compute size of screen - */ - width = 0; height = 0; - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation); - int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation); - - if (crtc->enabled) { - if (crtc_width > width) - width = crtc_width; - if (crtc_height > height) - height = crtc_height; - if (crtc->panningTotalArea.x2 > width) - width = crtc->panningTotalArea.x2; - if (crtc->panningTotalArea.y2 > height) - height = crtc->panningTotalArea.y2; - } - } - - if (width && height) - { - /* - * Compute physical size of screen - */ - if (monitorResolution) - { - mmWidth = width * 25.4 / monitorResolution; - mmHeight = height * 25.4 / monitorResolution; - } - else - { - xf86OutputPtr output = xf86CompatOutput(pScrn); - - if (output && - output->conf_monitor && - (output->conf_monitor->mon_width > 0 && - output->conf_monitor->mon_height > 0)) - { - /* - * Prefer user configured DisplaySize - */ - mmWidth = output->conf_monitor->mon_width; - mmHeight = output->conf_monitor->mon_height; - } - else - { - /* - * Otherwise, just set the screen to DEFAULT_DPI - */ - mmWidth = width * 25.4 / DEFAULT_DPI; - mmHeight = height * 25.4 / DEFAULT_DPI; - } - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Setting screen physical size to %d x %d\n", - mmWidth, mmHeight); - /* - * This is the initial setting of the screen size. - * We have to pre-set it here, otherwise panning would be adapted - * to the new screen size. - */ - pScreen->width = width; - pScreen->height = height; - xf86RandR12ScreenSetSize (pScreen, - width, - height, - mmWidth, - mmHeight); - } - - if (xf86RandR12Key == NULL) - return TRUE; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = pScrn->virtualX; - randrp->virtualY = pScrn->virtualY; - } - xf86CrtcSetScreenSubpixelOrder (pScreen); -#if RANDR_12_INTERFACE - if (xf86RandR12CreateScreenResources12 (pScreen)) - return TRUE; -#endif - return TRUE; -} - - -Bool -xf86RandR12Init (ScreenPtr pScreen) -{ - rrScrPrivPtr rp; - XF86RandRInfoPtr randrp; - -#ifdef PANORAMIX - /* XXX disable RandR when using Xinerama */ - if (!noPanoramiXExtension) - { - if (xf86NumScreens == 1) - noPanoramiXExtension = TRUE; - else - return TRUE; - } -#endif - - if (xf86RandR12Generation != serverGeneration) - xf86RandR12Generation = serverGeneration; - - xf86RandR12Key = &xf86RandR12KeyRec; - if (!dixRegisterPrivateKey(&xf86RandR12KeyRec, PRIVATE_SCREEN, 0)) - return FALSE; - - randrp = malloc(sizeof (XF86RandRInfoRec)); - if (!randrp) - return FALSE; - - if (!RRScreenInit(pScreen)) - { - free(randrp); - return FALSE; - } - rp = rrGetScrPriv(pScreen); - rp->rrGetInfo = xf86RandR12GetInfo; - rp->rrSetConfig = xf86RandR12SetConfig; - - randrp->virtualX = -1; - randrp->virtualY = -1; - randrp->mmWidth = pScreen->mmWidth; - randrp->mmHeight = pScreen->mmHeight; - - randrp->rotation = RR_Rotate_0; /* initial rotated mode */ - - randrp->supported_rotations = RR_Rotate_0; - - randrp->maxX = randrp->maxY = 0; - - dixSetPrivate(&pScreen->devPrivates, xf86RandR12Key, randrp); - -#if RANDR_12_INTERFACE - if (!xf86RandR12Init12 (pScreen)) - return FALSE; -#endif - return TRUE; -} - -void -xf86RandR12CloseScreen (ScreenPtr pScreen) -{ - XF86RandRInfoPtr randrp; - - if (xf86RandR12Key == NULL) - return; - - randrp = XF86RANDRINFO(pScreen); -#if RANDR_12_INTERFACE - xf86Screens[pScreen->myNum]->EnterVT = randrp->orig_EnterVT; -#endif - - free(randrp); -} - -void -xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations) -{ - XF86RandRInfoPtr randrp; -#if RANDR_12_INTERFACE - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - int c; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); -#endif - - if (xf86RandR12Key == NULL) - return; - - randrp = XF86RANDRINFO(pScreen); -#if RANDR_12_INTERFACE - for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = config->crtc[c]; - - RRCrtcSetRotations (crtc->randr_crtc, rotations); - } -#endif - randrp->supported_rotations = rotations; -} - -void -xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms) -{ - XF86RandRInfoPtr randrp; -#if RANDR_13_INTERFACE - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - int c; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); -#endif - - if (xf86RandR12Key == NULL) - return; - - randrp = XF86RANDRINFO(pScreen); -#if RANDR_13_INTERFACE - for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = config->crtc[c]; - - RRCrtcSetTransformSupport (crtc->randr_crtc, transforms); - } -#endif -} - -void -xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) -{ - ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; - - if (xf86RandR12Generation != serverGeneration || - XF86RANDRINFO(pScreen)->virtualX == -1) - { - *x = pScrn->virtualX; - *y = pScrn->virtualY; - } else { - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - - *x = randrp->virtualX; - *y = randrp->virtualY; - } -} - -#if RANDR_12_INTERFACE - -#define FLAG_BITS (RR_HSyncPositive | \ - RR_HSyncNegative | \ - RR_VSyncPositive | \ - RR_VSyncNegative | \ - RR_Interlace | \ - RR_DoubleScan | \ - RR_CSync | \ - RR_CSyncPositive | \ - RR_CSyncNegative | \ - RR_HSkewPresent | \ - RR_BCast | \ - RR_PixelMultiplex | \ - RR_DoubleClock | \ - RR_ClockDivideBy2) - -static Bool -xf86RandRModeMatches (RRModePtr randr_mode, - DisplayModePtr mode) -{ -#if 0 - if (match_name) - { - /* check for same name */ - int len = strlen (mode->name); - if (randr_mode->mode.nameLength != len) return FALSE; - if (memcmp (randr_mode->name, mode->name, len) != 0) return FALSE; - } -#endif - - /* check for same timings */ - if (randr_mode->mode.dotClock / 1000 != mode->Clock) return FALSE; - if (randr_mode->mode.width != mode->HDisplay) return FALSE; - if (randr_mode->mode.hSyncStart != mode->HSyncStart) return FALSE; - if (randr_mode->mode.hSyncEnd != mode->HSyncEnd) return FALSE; - if (randr_mode->mode.hTotal != mode->HTotal) return FALSE; - if (randr_mode->mode.hSkew != mode->HSkew) return FALSE; - if (randr_mode->mode.height != mode->VDisplay) return FALSE; - if (randr_mode->mode.vSyncStart != mode->VSyncStart) return FALSE; - if (randr_mode->mode.vSyncEnd != mode->VSyncEnd) return FALSE; - if (randr_mode->mode.vTotal != mode->VTotal) return FALSE; - - /* check for same flags (using only the XF86 valid flag bits) */ - if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS)) - return FALSE; - - /* everything matches */ - return TRUE; -} - -static Bool -xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) -{ - ScreenPtr pScreen = randr_crtc->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RRModePtr randr_mode = NULL; - int x; - int y; - Rotation rotation; - int numOutputs; - RROutputPtr *randr_outputs; - RROutputPtr randr_output; - xf86CrtcPtr crtc = randr_crtc->devPrivate; - xf86OutputPtr output; - int i, j; - DisplayModePtr mode = &crtc->mode; - Bool ret; - - randr_outputs = malloc(config->num_output * sizeof (RROutputPtr)); - if (!randr_outputs) - return FALSE; - x = crtc->x; - y = crtc->y; - rotation = crtc->rotation; - numOutputs = 0; - randr_mode = NULL; - for (i = 0; i < config->num_output; i++) - { - output = config->output[i]; - if (output->crtc == crtc) - { - randr_output = output->randr_output; - randr_outputs[numOutputs++] = randr_output; - /* - * We make copies of modes, so pointer equality - * isn't sufficient - */ - for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++) - { - RRModePtr m = (j < randr_output->numModes ? - randr_output->modes[j] : - randr_output->userModes[j-randr_output->numModes]); - - if (xf86RandRModeMatches (m, mode)) - { - randr_mode = m; - break; - } - } - } - } - ret = RRCrtcNotify (randr_crtc, randr_mode, x, y, - rotation, - crtc->transformPresent ? &crtc->transform : NULL, - numOutputs, randr_outputs); - free(randr_outputs); - return ret; -} - -/* - * Convert a RandR mode to a DisplayMode - */ -static void -xf86RandRModeConvert (ScrnInfoPtr scrn, - RRModePtr randr_mode, - DisplayModePtr mode) -{ - memset(mode, 0, sizeof(DisplayModeRec)); - mode->status = MODE_OK; - - mode->Clock = randr_mode->mode.dotClock / 1000; - - mode->HDisplay = randr_mode->mode.width; - mode->HSyncStart = randr_mode->mode.hSyncStart; - mode->HSyncEnd = randr_mode->mode.hSyncEnd; - mode->HTotal = randr_mode->mode.hTotal; - mode->HSkew = randr_mode->mode.hSkew; - - mode->VDisplay = randr_mode->mode.height; - mode->VSyncStart = randr_mode->mode.vSyncStart; - mode->VSyncEnd = randr_mode->mode.vSyncEnd; - mode->VTotal = randr_mode->mode.vTotal; - mode->VScan = 0; - - mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS; - - xf86SetModeCrtc (mode, scrn->adjustFlags); -} - -static Bool -xf86RandR12CrtcSet (ScreenPtr pScreen, - RRCrtcPtr randr_crtc, - RRModePtr randr_mode, - int x, - int y, - Rotation rotation, - int num_randr_outputs, - RROutputPtr *randr_outputs) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc = randr_crtc->devPrivate; - RRTransformPtr transform; - Bool changed = FALSE; - int o, ro; - xf86CrtcPtr *save_crtcs; - Bool save_enabled = crtc->enabled; - - if (!crtc->scrn->vtSema) - return FALSE; - - save_crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr)); - if ((randr_mode != NULL) != crtc->enabled) - changed = TRUE; - else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode)) - changed = TRUE; - - if (rotation != crtc->rotation) - changed = TRUE; - - transform = RRCrtcGetTransform (randr_crtc); - if ((transform != NULL) != crtc->transformPresent) - changed = TRUE; - else if (transform && memcmp (&transform->transform, &crtc->transform.transform, - sizeof (transform->transform)) != 0) - changed = TRUE; - - if (x != crtc->x || y != crtc->y) - changed = TRUE; - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - xf86CrtcPtr new_crtc; - - save_crtcs[o] = output->crtc; - - if (output->crtc == crtc) - new_crtc = NULL; - else - new_crtc = output->crtc; - for (ro = 0; ro < num_randr_outputs; ro++) - if (output->randr_output == randr_outputs[ro]) - { - new_crtc = crtc; - break; - } - if (new_crtc != output->crtc) - { - changed = TRUE; - output->crtc = new_crtc; - } - } - for (ro = 0; ro < num_randr_outputs; ro++) - if (randr_outputs[ro]->pendingProperties) - changed = TRUE; - - /* XXX need device-independent mode setting code through an API */ - if (changed) - { - crtc->enabled = randr_mode != NULL; - - if (randr_mode) - { - DisplayModeRec mode; - RRTransformPtr transform = RRCrtcGetTransform (randr_crtc); - - xf86RandRModeConvert (pScrn, randr_mode, &mode); - if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y)) - { - crtc->enabled = save_enabled; - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - output->crtc = save_crtcs[o]; - } - free(save_crtcs); - return FALSE; - } - xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height); - xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); - /* - * Save the last successful setting for EnterVT - */ - crtc->desiredMode = mode; - crtc->desiredRotation = rotation; - if (transform) { - crtc->desiredTransform = *transform; - crtc->desiredTransformPresent = TRUE; - } else - crtc->desiredTransformPresent = FALSE; - - crtc->desiredX = x; - crtc->desiredY = y; - } - xf86DisableUnusedFunctions (pScrn); - } - free(save_crtcs); - return xf86RandR12CrtcNotify (randr_crtc); -} - -static Bool -xf86RandR12CrtcSetGamma (ScreenPtr pScreen, - RRCrtcPtr randr_crtc) -{ - xf86CrtcPtr crtc = randr_crtc->devPrivate; - - if (crtc->funcs->gamma_set == NULL) - return FALSE; - - if (!crtc->scrn->vtSema) - return TRUE; - - /* Realloc local gamma if needed. */ - if (randr_crtc->gammaSize != crtc->gamma_size) { - CARD16 *tmp_ptr; - tmp_ptr = realloc(crtc->gamma_red, 3 * crtc->gamma_size * sizeof (CARD16)); - if (!tmp_ptr) - return FALSE; - crtc->gamma_red = tmp_ptr; - crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; - crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; - } - - crtc->gamma_size = randr_crtc->gammaSize; - memcpy (crtc->gamma_red, randr_crtc->gammaRed, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_green, randr_crtc->gammaGreen, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_blue, randr_crtc->gammaBlue, crtc->gamma_size * sizeof (CARD16)); - - /* Only set it when the crtc is actually running. - * Otherwise it will be set when it's activated. - */ - if (crtc->active) - crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); - - return TRUE; -} - -static Bool -xf86RandR12CrtcGetGamma (ScreenPtr pScreen, - RRCrtcPtr randr_crtc) -{ - xf86CrtcPtr crtc = randr_crtc->devPrivate; - - if (!crtc->gamma_size) - return FALSE; - - if (!crtc->gamma_red || !crtc->gamma_green || !crtc->gamma_blue) - return FALSE; - - /* Realloc randr gamma if needed. */ - if (randr_crtc->gammaSize != crtc->gamma_size) { - CARD16 *tmp_ptr; - tmp_ptr = realloc(randr_crtc->gammaRed, 3 * crtc->gamma_size * sizeof (CARD16)); - if (!tmp_ptr) - return FALSE; - randr_crtc->gammaRed = tmp_ptr; - randr_crtc->gammaGreen = randr_crtc->gammaRed + crtc->gamma_size; - randr_crtc->gammaBlue = randr_crtc->gammaGreen + crtc->gamma_size; - } - randr_crtc->gammaSize = crtc->gamma_size; - memcpy (randr_crtc->gammaRed, crtc->gamma_red, crtc->gamma_size * sizeof (CARD16)); - memcpy (randr_crtc->gammaGreen, crtc->gamma_green, crtc->gamma_size * sizeof (CARD16)); - memcpy (randr_crtc->gammaBlue, crtc->gamma_blue, crtc->gamma_size * sizeof (CARD16)); - - return TRUE; -} - -static Bool -xf86RandR12OutputSetProperty (ScreenPtr pScreen, - RROutputPtr randr_output, - Atom property, - RRPropertyValuePtr value) -{ - xf86OutputPtr output = randr_output->devPrivate; - - /* If we don't have any property handler, then we don't care what the - * user is setting properties to. - */ - if (output->funcs->set_property == NULL) - return TRUE; - - /* - * This function gets called even when vtSema is FALSE, as - * drivers will need to remember the correct value to apply - * when the VT switch occurs - */ - return output->funcs->set_property(output, property, value); -} - -static Bool -xf86RandR13OutputGetProperty (ScreenPtr pScreen, - RROutputPtr randr_output, - Atom property) -{ - xf86OutputPtr output = randr_output->devPrivate; - - if (output->funcs->get_property == NULL) - return TRUE; - - /* Should be safe even w/o vtSema */ - return output->funcs->get_property(output, property); -} - -static Bool -xf86RandR12OutputValidateMode (ScreenPtr pScreen, - RROutputPtr randr_output, - RRModePtr randr_mode) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86OutputPtr output = randr_output->devPrivate; - DisplayModeRec mode; - - xf86RandRModeConvert (pScrn, randr_mode, &mode); - /* - * This function may be called when vtSema is FALSE, so - * the underlying function must either avoid touching the hardware - * or return FALSE when vtSema is FALSE - */ - if (output->funcs->mode_valid (output, &mode) != MODE_OK) - return FALSE; - return TRUE; -} - -static void -xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode) -{ -} - -/** - * Given a list of xf86 modes and a RandR Output object, construct - * RandR modes and assign them to the output - */ -static Bool -xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) -{ - DisplayModePtr mode; - RRModePtr *rrmodes = NULL; - int nmode = 0; - int npreferred = 0; - Bool ret = TRUE; - int pref; - - for (mode = modes; mode; mode = mode->next) - nmode++; - - if (nmode) { - rrmodes = malloc(nmode * sizeof (RRModePtr)); - - if (!rrmodes) - return FALSE; - nmode = 0; - - for (pref = 1; pref >= 0; pref--) { - for (mode = modes; mode; mode = mode->next) { - if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) { - xRRModeInfo modeInfo; - RRModePtr rrmode; - - modeInfo.nameLength = strlen (mode->name); - modeInfo.width = mode->HDisplay; - modeInfo.dotClock = mode->Clock * 1000; - modeInfo.hSyncStart = mode->HSyncStart; - modeInfo.hSyncEnd = mode->HSyncEnd; - modeInfo.hTotal = mode->HTotal; - modeInfo.hSkew = mode->HSkew; - - modeInfo.height = mode->VDisplay; - modeInfo.vSyncStart = mode->VSyncStart; - modeInfo.vSyncEnd = mode->VSyncEnd; - modeInfo.vTotal = mode->VTotal; - modeInfo.modeFlags = mode->Flags; - - rrmode = RRModeGet (&modeInfo, mode->name); - if (rrmode) { - rrmodes[nmode++] = rrmode; - npreferred += pref; - } - } - } - } - } - - ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred); - free(rrmodes); - return ret; -} - -/* - * Mirror the current mode configuration to RandR - */ -static Bool -xf86RandR12SetInfo12 (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RROutputPtr *clones; - RRCrtcPtr *crtcs; - int ncrtc; - int o, c, l; - RRCrtcPtr randr_crtc; - int nclone; - - clones = malloc(config->num_output * sizeof (RROutputPtr)); - crtcs = malloc(config->num_crtc * sizeof (RRCrtcPtr)); - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - ncrtc = 0; - for (c = 0; c < config->num_crtc; c++) - if (output->possible_crtcs & (1 << c)) - crtcs[ncrtc++] = config->crtc[c]->randr_crtc; - - if (output->crtc) - randr_crtc = output->crtc->randr_crtc; - else - randr_crtc = NULL; - - if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc)) - { - free(crtcs); - free(clones); - return FALSE; - } - - RROutputSetPhysicalSize(output->randr_output, - output->mm_width, - output->mm_height); - xf86RROutputSetModes (output->randr_output, output->probed_modes); - - switch (output->status) { - case XF86OutputStatusConnected: - RROutputSetConnection (output->randr_output, RR_Connected); - break; - case XF86OutputStatusDisconnected: - RROutputSetConnection (output->randr_output, RR_Disconnected); - break; - case XF86OutputStatusUnknown: - RROutputSetConnection (output->randr_output, RR_UnknownConnection); - break; - } - - RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order); - - /* - * Valid clones - */ - nclone = 0; - for (l = 0; l < config->num_output; l++) - { - xf86OutputPtr clone = config->output[l]; - - if (l != o && (output->possible_clones & (1 << l))) - clones[nclone++] = clone->randr_output; - } - if (!RROutputSetClones (output->randr_output, clones, nclone)) - { - free(crtcs); - free(clones); - return FALSE; - } - } - free(crtcs); - free(clones); - return TRUE; -} - - - -/* - * Query the hardware for the current state, then mirror - * that to RandR - */ -static Bool -xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if (!pScrn->vtSema) - return TRUE; - xf86ProbeOutputModes (pScrn, 0, 0); - xf86SetScrnInfoModes (pScrn); - return xf86RandR12SetInfo12 (pScreen); -} - -static Bool -xf86RandR12CreateObjects12 (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - int c; - int o; - - if (!RRInit ()) - return FALSE; - - /* - * Configure crtcs - */ - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->randr_crtc = RRCrtcCreate (pScreen, crtc); - RRCrtcGammaSetSize (crtc->randr_crtc, 256); - } - /* - * Configure outputs - */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->randr_output = RROutputCreate (pScreen, output->name, - strlen (output->name), - output); - - if (output->funcs->create_resources != NULL) - output->funcs->create_resources(output); - RRPostPendingProperties (output->randr_output); - } - return TRUE; -} - -static Bool -xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) -{ - int c; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - - if (xf86RandR12Key == NULL) - return TRUE; - - for (c = 0; c < config->num_crtc; c++) - xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); - - RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight, - config->maxWidth, config->maxHeight); - return TRUE; -} - -/* - * Something happened within the screen configuration due - * to DGA, VidMode or hot key. Tell RandR - */ - -void -xf86RandR12TellChanged (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - int c; - - if (xf86RandR12Key == NULL) - return; - - xf86RandR12SetInfo12 (pScreen); - for (c = 0; c < config->num_crtc; c++) - xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); - - RRTellChanged (pScreen); -} - -static void -xf86RandR12PointerMoved (int scrnIndex, int x, int y) -{ - ScreenPtr pScreen = screenInfo.screens[scrnIndex]; - ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - int c; - - randrp->pointerX = x; - randrp->pointerY = y; - for (c = 0; c < config->num_crtc; c++) - xf86RandR13Pan (config->crtc[c], x, y); -} - -static Bool -xf86RandR13GetPanning (ScreenPtr pScreen, - RRCrtcPtr randr_crtc, - BoxPtr totalArea, - BoxPtr trackingArea, - INT16 *border) -{ - xf86CrtcPtr crtc = randr_crtc->devPrivate; - - if (crtc->version < 2) - return FALSE; - if (totalArea) - memcpy (totalArea, &crtc->panningTotalArea, sizeof(BoxRec)); - if (trackingArea) - memcpy (trackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); - if (border) - memcpy (border, crtc->panningBorder, 4*sizeof(INT16)); - - return TRUE; -} - -static Bool -xf86RandR13SetPanning (ScreenPtr pScreen, - RRCrtcPtr randr_crtc, - BoxPtr totalArea, - BoxPtr trackingArea, - INT16 *border) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - xf86CrtcPtr crtc = randr_crtc->devPrivate; - BoxRec oldTotalArea; - BoxRec oldTrackingArea; - INT16 oldBorder[4]; - - - if (crtc->version < 2) - return FALSE; - - memcpy (&oldTotalArea, &crtc->panningTotalArea, sizeof(BoxRec)); - memcpy (&oldTrackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); - memcpy (oldBorder, crtc->panningBorder, 4*sizeof(INT16)); - - if (totalArea) - memcpy (&crtc->panningTotalArea, totalArea, sizeof(BoxRec)); - if (trackingArea) - memcpy (&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec)); - if (border) - memcpy (crtc->panningBorder, border, 4*sizeof(INT16)); - - if (xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height)) { - xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); - return TRUE; - } else { - /* Restore old settings */ - memcpy (&crtc->panningTotalArea, &oldTotalArea, sizeof(BoxRec)); - memcpy (&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec)); - memcpy (crtc->panningBorder, oldBorder, 4*sizeof(INT16)); - return FALSE; - } -} - -/* - * Compatibility with XF86VidMode's gamma changer. This necessarily clobbers - * any per-crtc setup. You asked for it... - */ - -static void -gamma_to_ramp(float gamma, CARD16 *ramp, int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (gamma == 1.0) - ramp[i] = i << 8; - else - ramp[i] = (CARD16)(pow((double)i / (double)(size - 1), 1. / gamma) - * (double)(size - 1) * 256); - } -} - -static int -xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma) -{ - CARD16 *points, *red, *green, *blue; - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); - int size; - - if (!crtc) - return Success; - - size = max(0, crtc->gammaSize); - if (!size) - return Success; - - points = calloc(size, 3 * sizeof(CARD16)); - if (!points) - return BadAlloc; - - red = points; - green = points + size; - blue = points + 2 * size; - - gamma_to_ramp(gamma.red, red, size); - gamma_to_ramp(gamma.green, green, size); - gamma_to_ramp(gamma.blue, blue, size); - RRCrtcGammaSet(crtc, red, green, blue); - - free(points); - - pScrn->gamma = gamma; - - return Success; -} - -static Bool -xf86RandR12EnterVT (int screen_index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[screen_index]; - ScrnInfoPtr pScrn = xf86Screens[screen_index]; - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - rrScrPrivPtr rp = rrGetScrPriv(pScreen); - Bool ret; - int i; - - if (randrp->orig_EnterVT) { - pScrn->EnterVT = randrp->orig_EnterVT; - ret = pScrn->EnterVT (screen_index, flags); - randrp->orig_EnterVT = pScrn->EnterVT; - pScrn->EnterVT = xf86RandR12EnterVT; - if (!ret) - return FALSE; - } - - /* reload gamma */ - for (i = 0; i < rp->numCrtcs; i++) - xf86RandR12CrtcSetGamma(pScreen, rp->crtcs[i]); - - return RRGetInfo (pScreen, TRUE); /* force a re-probe of outputs and notify clients about changes */ -} - -static Bool -xf86RandR12Init12 (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - rrScrPrivPtr rp = rrGetScrPriv(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - int i; - - rp->rrGetInfo = xf86RandR12GetInfo12; - rp->rrScreenSetSize = xf86RandR12ScreenSetSize; - rp->rrCrtcSet = xf86RandR12CrtcSet; - rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma; - rp->rrCrtcGetGamma = xf86RandR12CrtcGetGamma; - rp->rrOutputSetProperty = xf86RandR12OutputSetProperty; - rp->rrOutputValidateMode = xf86RandR12OutputValidateMode; -#if RANDR_13_INTERFACE - rp->rrOutputGetProperty = xf86RandR13OutputGetProperty; - rp->rrGetPanning = xf86RandR13GetPanning; - rp->rrSetPanning = xf86RandR13SetPanning; -#endif - rp->rrModeDestroy = xf86RandR12ModeDestroy; - rp->rrSetConfig = NULL; - pScrn->PointerMoved = xf86RandR12PointerMoved; - pScrn->ChangeGamma = xf86RandR12ChangeGamma; - - randrp->orig_EnterVT = pScrn->EnterVT; - pScrn->EnterVT = xf86RandR12EnterVT; - - if (!xf86RandR12CreateObjects12 (pScreen)) - return FALSE; - - /* - * Configure output modes - */ - if (!xf86RandR12SetInfo12 (pScreen)) - return FALSE; - for (i = 0; i < rp->numCrtcs; i++) { - xf86RandR12CrtcGetGamma(pScreen, rp->crtcs[i]); - } - return TRUE; -} - -#endif - -Bool -xf86RandR12PreInit (ScrnInfoPtr pScrn) -{ - return TRUE; -} +/* + * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 "xf86.h" +#include "os.h" +#include "globals.h" +#include "xf86Priv.h" +#include "xf86DDC.h" +#include "mipointer.h" +#include "windowstr.h" +#include "inputstr.h" +#include +#include + +#include "xf86Crtc.h" +#include "xf86RandR12.h" + +typedef struct _xf86RandR12Info { + int virtualX; + int virtualY; + int mmWidth; + int mmHeight; + int maxX; + int maxY; + int pointerX; + int pointerY; + Rotation rotation; /* current mode */ + Rotation supported_rotations; /* driver supported */ + + /* Used to wrap EnterVT so we can re-probe the outputs when a laptop unsuspends + * (actually, any time that we switch back into our VT). + * + * See https://bugs.freedesktop.org/show_bug.cgi?id=21554 + */ + xf86EnterVTProc *orig_EnterVT; +} XF86RandRInfoRec, *XF86RandRInfoPtr; + +#ifdef RANDR_12_INTERFACE +static Bool xf86RandR12Init12 (ScreenPtr pScreen); +static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen); +#endif + +static int xf86RandR12Generation; + +static DevPrivateKeyRec xf86RandR12KeyRec; +static DevPrivateKey xf86RandR12Key; +#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) \ + dixLookupPrivate(&(p)->devPrivates, xf86RandR12Key)) + + +static int +xf86RandR12ModeRefresh (DisplayModePtr mode) +{ + if (mode->VRefresh) + return (int) (mode->VRefresh + 0.5); + else + return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); +} + +/* Adapt panning area; return TRUE if panning area was valid without adaption */ +static int +xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeight) +{ + int ret = TRUE; + + if (crtc->version < 2) + return FALSE; + + if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1) { + /* Panning in X is disabled */ + if (crtc->panningTotalArea.x1 || crtc->panningTotalArea.x2) + /* Illegal configuration -> fail/disable */ + ret = FALSE; + crtc->panningTotalArea.x1 = crtc->panningTotalArea.x2 = 0; + crtc->panningTrackingArea.x1 = crtc->panningTrackingArea.x2 = 0; + crtc->panningBorder[0] = crtc->panningBorder[2] = 0; + } else { + /* Panning in X is enabled */ + if (crtc->panningTotalArea.x1 < 0) { + /* Panning region outside screen -> move inside */ + crtc->panningTotalArea.x2 -= crtc->panningTotalArea.x1; + crtc->panningTotalArea.x1 = 0; + ret = FALSE; + } + if (crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay) { + /* Panning region smaller than displayed area -> crop to displayed area */ + crtc->panningTotalArea.x2 = crtc->panningTotalArea.x1 + crtc->mode.HDisplay; + ret = FALSE; + } + if (crtc->panningTotalArea.x2 > screenWidth) { + /* Panning region larger than screen -> move inside, then crop to screen */ + crtc->panningTotalArea.x1 -= crtc->panningTotalArea.x2 - screenWidth; + crtc->panningTotalArea.x2 = screenWidth; + ret = FALSE; + if (crtc->panningTotalArea.x1 < 0) + crtc->panningTotalArea.x1 = 0; + } + if (crtc->panningBorder[0] + crtc->panningBorder[2] > crtc->mode.HDisplay) { + /* Borders too large -> set to 0 */ + crtc->panningBorder[0] = crtc->panningBorder[2] = 0; + ret = FALSE; + } + } + + if (crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) { + /* Panning in Y is disabled */ + if (crtc->panningTotalArea.y1 || crtc->panningTotalArea.y2) + /* Illegal configuration -> fail/disable */ + ret = FALSE; + crtc->panningTotalArea.y1 = crtc->panningTotalArea.y2 = 0; + crtc->panningTrackingArea.y1 = crtc->panningTrackingArea.y2 = 0; + crtc->panningBorder[1] = crtc->panningBorder[3] = 0; + } else { + /* Panning in Y is enabled */ + if (crtc->panningTotalArea.y1 < 0) { + /* Panning region outside screen -> move inside */ + crtc->panningTotalArea.y2 -= crtc->panningTotalArea.y1; + crtc->panningTotalArea.y1 = 0; + ret = FALSE; + } + if (crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay) { + /* Panning region smaller than displayed area -> crop to displayed area */ + crtc->panningTotalArea.y2 = crtc->panningTotalArea.y1 + crtc->mode.VDisplay; + ret = FALSE; + } + if (crtc->panningTotalArea.y2 > screenHeight) { + /* Panning region larger than screen -> move inside, then crop to screen */ + crtc->panningTotalArea.y1 -= crtc->panningTotalArea.y2 - screenHeight; + crtc->panningTotalArea.y2 = screenHeight; + ret = FALSE; + if (crtc->panningTotalArea.y1 < 0) + crtc->panningTotalArea.y1 = 0; + } + if (crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) { + /* Borders too large -> set to 0 */ + crtc->panningBorder[1] = crtc->panningBorder[3] = 0; + ret = FALSE; + } + } + + return ret; +} + +/* + * The heart of the panning operation: + * + * Given a frame buffer position (fb_x, fb_y), + * and a crtc position (crtc_x, crtc_y), + * and a transform matrix which maps frame buffer to crtc, + * compute a panning position (pan_x, pan_y) that + * makes the resulting transform line those two up + */ + +static void +xf86ComputeCrtcPan (Bool transform_in_use, + struct pixman_f_transform *m, + double screen_x, double screen_y, + double crtc_x, double crtc_y, + int old_pan_x, int old_pan_y, + int *new_pan_x, int *new_pan_y) +{ + if (transform_in_use) { + /* + * Given the current transform, M, the current position + * on the Screen, S, and the desired position on the CRTC, + * C, compute a translation, T, such that: + * + * M T S = C + * + * where T is of the form + * + * | 1 0 dx | + * | 0 1 dy | + * | 0 0 1 | + * + * M T S = + * | M00 Sx + M01 Sy + M00 dx + M01 dy + M02 | | Cx F | + * | M10 Sx + M11 Sy + M10 dx + M11 dy + M12 | = | Cy F | + * | M20 Sx + M21 Sy + M20 dx + M21 dy + M22 | | F | + * + * R = M S + * + * Cx F = M00 dx + M01 dy + R0 + * Cy F = M10 dx + M11 dy + R1 + * F = M20 dx + M21 dy + R2 + * + * Zero out dx, then dy + * + * F (Cx M10 - Cy M00) = + * (M10 M01 - M00 M11) dy + M10 R0 - M00 R1 + * F (M10 - Cy M20) = + * (M10 M21 - M20 M11) dy + M10 R2 - M20 R1 + * + * F (Cx M11 - Cy M01) = + * (M11 M00 - M01 M10) dx + M11 R0 - M01 R1 + * F (M11 - Cy M21) = + * (M11 M20 - M21 M10) dx + M11 R2 - M21 R1 + * + * Make some temporaries + * + * T = | Cx M10 - Cy M00 | + * | Cx M11 - Cy M01 | + * + * U = | M10 M01 - M00 M11 | + * | M11 M00 - M01 M10 | + * + * Q = | M10 R0 - M00 R1 | + * | M11 R0 - M01 R1 | + * + * P = | M10 - Cy M20 | + * | M11 - Cy M21 | + * + * W = | M10 M21 - M20 M11 | + * | M11 M20 - M21 M10 | + * + * V = | M10 R2 - M20 R1 | + * | M11 R2 - M21 R1 | + * + * Rewrite: + * + * F T0 = U0 dy + Q0 + * F P0 = W0 dy + V0 + * F T1 = U1 dx + Q1 + * F P1 = W1 dx + V1 + * + * Solve for F (two ways) + * + * F (W0 T0 - U0 P0) = W0 Q0 - U0 V0 + * + * W0 Q0 - U0 V0 + * F = ------------- + * W0 T0 - U0 P0 + * + * F (W1 T1 - U1 P1) = W1 Q1 - U1 V1 + * + * W1 Q1 - U1 V1 + * F = ------------- + * W1 T1 - U1 P1 + * + * We'll use which ever solution works (denominator != 0) + * + * Finally, solve for dx and dy: + * + * dx = (F T1 - Q1) / U1 + * dx = (F P1 - V1) / W1 + * + * dy = (F T0 - Q0) / U0 + * dy = (F P0 - V0) / W0 + */ + double r[3]; + double q[2], u[2], t[2], v[2], w[2], p[2]; + double f; + struct pict_f_vector d; + int i; + + /* Get the un-normalized crtc coordinates again */ + for (i = 0; i < 3; i++) + r[i] = m->m[i][0] * screen_x + m->m[i][1] * screen_y + m->m[i][2]; + + /* Combine values into temporaries */ + for (i = 0; i < 2; i++) { + q[i] = m->m[1][i] * r[0] - m->m[0][i] * r[1]; + u[i] = m->m[1][i] * m->m[0][1-i] - m->m[0][i] * m->m[1][1-i]; + t[i] = m->m[1][i] * crtc_x - m->m[0][i] * crtc_y; + + v[i] = m->m[1][i] * r[2] - m->m[2][i] * r[1]; + w[i] = m->m[1][i] * m->m[2][1-i] - m->m[2][i] * m->m[1][1-i]; + p[i] = m->m[1][i] - m->m[2][i] * crtc_y; + } + + /* Find a way to compute f */ + f = 0; + for (i = 0; i < 2; i++) { + double a = w[i] * q[i] - u[i] * v[i]; + double b = w[i] * t[i] - u[i] * p[i]; + if (b != 0) { + f = a/b; + break; + } + } + + /* Solve for the resulting transform vector */ + for (i = 0; i < 2; i++) { + if (u[i]) + d.v[1-i] = (t[i] * f - q[i]) / u[i]; + else if (w[1]) + d.v[1-i] = (p[i] * f - v[i]) / w[i]; + else + d.v[1-i] = 0; + } + *new_pan_x = old_pan_x - floor (d.v[0] + 0.5); + *new_pan_y = old_pan_y - floor (d.v[1] + 0.5); + } else { + *new_pan_x = screen_x - crtc_x; + *new_pan_y = screen_y - crtc_y; + } +} + +static void +xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y) +{ + int newX, newY; + int width, height; + Bool panned = FALSE; + + if (crtc->version < 2) + return; + + if (! crtc->enabled || + (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1 && + crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1)) + return; + + newX = crtc->x; + newY = crtc->y; + width = crtc->mode.HDisplay; + height = crtc->mode.VDisplay; + + if ((crtc->panningTrackingArea.x2 <= crtc->panningTrackingArea.x1 || + (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2)) && + (crtc->panningTrackingArea.y2 <= crtc->panningTrackingArea.y1 || + (y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2))) + { + struct pict_f_vector c; + + /* + * Pre-clip the mouse position to the panning area so that we don't + * push the crtc outside. This doesn't deal with changes to the + * panning values, only mouse position changes. + */ + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) + { + if (x < crtc->panningTotalArea.x1) + x = crtc->panningTotalArea.x1; + if (x >= crtc->panningTotalArea.x2) + x = crtc->panningTotalArea.x2 - 1; + } + if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) + { + if (y < crtc->panningTotalArea.y1) + y = crtc->panningTotalArea.y1; + if (y >= crtc->panningTotalArea.y2) + y = crtc->panningTotalArea.y2 - 1; + } + + c.v[0] = x; + c.v[1] = y; + c.v[2] = 1.0; + if (crtc->transform_in_use) { + pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c); + } else { + c.v[0] -= crtc->x; + c.v[1] -= crtc->y; + } + + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { + if (c.v[0] < crtc->panningBorder[0]) { + c.v[0] = crtc->panningBorder[0]; + panned = TRUE; + } + if (c.v[0] >= width - crtc->panningBorder[2]) { + c.v[0] = width - crtc->panningBorder[2] - 1; + panned = TRUE; + } + } + if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { + if (c.v[1] < crtc->panningBorder[1]) { + c.v[1] = crtc->panningBorder[1]; + panned = TRUE; + } + if (c.v[1] >= height - crtc->panningBorder[3]) { + c.v[1] = height - crtc->panningBorder[3] - 1; + panned = TRUE; + } + } + if (panned) + xf86ComputeCrtcPan (crtc->transform_in_use, + &crtc->f_framebuffer_to_crtc, + x, y, c.v[0], c.v[1], + newX, newY, &newX, &newY); + } + + /* + * Ensure that the crtc is within the panning region. + * + * XXX This computation only works when we do not have a transform + * in use. + */ + if (!crtc->transform_in_use) + { + /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */ + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { + if (newX > crtc->panningTotalArea.x2 - width) + newX = crtc->panningTotalArea.x2 - width; + if (newX < crtc->panningTotalArea.x1) + newX = crtc->panningTotalArea.x1; + } + if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { + if (newY > crtc->panningTotalArea.y2 - height) + newY = crtc->panningTotalArea.y2 - height; + if (newY < crtc->panningTotalArea.y1) + newY = crtc->panningTotalArea.y1; + } + } + if (newX != crtc->x || newY != crtc->y) + xf86CrtcSetOrigin (crtc, newX, newY); +} + +static Bool +xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + RRScreenSizePtr pSize; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int refresh0 = 60; + int maxX = 0, maxY = 0; + + *rotations = randrp->supported_rotations; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = scrp->virtualX; + randrp->virtualY = scrp->virtualY; + } + + /* Re-probe the outputs for new monitors or modes */ + if (scrp->vtSema) + { + xf86ProbeOutputModes (scrp, 0, 0); + xf86SetScrnInfoModes (scrp); + } + + for (mode = scrp->modes; ; mode = mode->next) + { + int refresh = xf86RandR12ModeRefresh (mode); + if (randrp->maxX == 0 || randrp->maxY == 0) + { + if (maxX < mode->HDisplay) + maxX = mode->HDisplay; + if (maxY < mode->VDisplay) + maxY = mode->VDisplay; + } + if (mode == scrp->modes) + refresh0 = refresh; + pSize = RRRegisterSize (pScreen, + mode->HDisplay, mode->VDisplay, + randrp->mmWidth, randrp->mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh); + + if (xf86ModesEqual(mode, scrp->currentMode)) + { + RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); + } + if (mode->next == scrp->modes) + break; + } + + if (randrp->maxX == 0 || randrp->maxY == 0) + { + randrp->maxX = maxX; + randrp->maxY = maxY; + } + + return TRUE; +} + +static Bool +xf86RandR12SetMode (ScreenPtr pScreen, + DisplayModePtr mode, + Bool useVirtual, + int mmWidth, + int mmHeight) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int oldWidth = pScreen->width; + int oldHeight = pScreen->height; + int oldmmWidth = pScreen->mmWidth; + int oldmmHeight = pScreen->mmHeight; + WindowPtr pRoot = pScreen->root; + DisplayModePtr currentMode = NULL; + Bool ret = TRUE; + + if (pRoot) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); + if (useVirtual) + { + scrp->virtualX = randrp->virtualX; + scrp->virtualY = randrp->virtualY; + } + else + { + scrp->virtualX = mode->HDisplay; + scrp->virtualY = mode->VDisplay; + } + + if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) + { + /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ + pScreen->width = scrp->virtualY; + pScreen->height = scrp->virtualX; + pScreen->mmWidth = mmHeight; + pScreen->mmHeight = mmWidth; + } + else + { + pScreen->width = scrp->virtualX; + pScreen->height = scrp->virtualY; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + } + if (scrp->currentMode == mode) { + /* Save current mode */ + currentMode = scrp->currentMode; + /* Reset, just so we ensure the drivers SwitchMode is called */ + scrp->currentMode = NULL; + } + /* + * We know that if the driver failed to SwitchMode to the rotated + * version, then it should revert back to it's prior mode. + */ + if (!xf86SwitchMode (pScreen, mode)) + { + ret = FALSE; + scrp->virtualX = pScreen->width = oldWidth; + scrp->virtualY = pScreen->height = oldHeight; + pScreen->mmWidth = oldmmWidth; + pScreen->mmHeight = oldmmHeight; + scrp->currentMode = currentMode; + } + + /* + * Make sure the layout is correct + */ + xf86ReconfigureLayout(); + + /* + * Make sure the whole screen is visible + */ + xf86SetViewport (pScreen, pScreen->width, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); + return ret; +} + +Bool +xf86RandR12SetConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int pos[MAXDEVICES][2]; + Bool useVirtual = FALSE; + int maxX = 0, maxY = 0; + Rotation oldRotation = randrp->rotation; + DeviceIntPtr dev; + Bool view_adjusted = FALSE; + + randrp->rotation = rotation; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = scrp->virtualX; + randrp->virtualY = scrp->virtualY; + } + + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!IsMaster(dev) && !IsFloating(dev)) + continue; + + miPointerGetPosition(dev, &pos[dev->id][0], &pos[dev->id][1]); + } + + for (mode = scrp->modes; ; mode = mode->next) + { + if (randrp->maxX == 0 || randrp->maxY == 0) + { + if (maxX < mode->HDisplay) + maxX = mode->HDisplay; + if (maxY < mode->VDisplay) + maxY = mode->VDisplay; + } + if (mode->HDisplay == pSize->width && + mode->VDisplay == pSize->height && + (rate == 0 || xf86RandR12ModeRefresh (mode) == rate)) + break; + if (mode->next == scrp->modes) + { + if (pSize->width == randrp->virtualX && + pSize->height == randrp->virtualY) + { + mode = scrp->modes; + useVirtual = TRUE; + break; + } + if (randrp->maxX == 0 || randrp->maxY == 0) + { + randrp->maxX = maxX; + randrp->maxY = maxY; + } + return FALSE; + } + } + + if (randrp->maxX == 0 || randrp->maxY == 0) + { + randrp->maxX = maxX; + randrp->maxY = maxY; + } + + if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth, + pSize->mmHeight)) { + randrp->rotation = oldRotation; + return FALSE; + } + + /* + * Move the cursor back where it belongs; SwitchMode repositions it + * FIXME: duplicated code, see modes/xf86RandR12.c + */ + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!IsMaster(dev) && !IsFloating(dev)) + continue; + + if (pScreen == miPointerGetScreen(dev)) { + int px = pos[dev->id][0]; + int py = pos[dev->id][1]; + + px = (px >= pScreen->width ? (pScreen->width - 1) : px); + py = (py >= pScreen->height ? (pScreen->height - 1) : py); + + /* Setting the viewpoint makes only sense on one device */ + if (!view_adjusted && IsMaster(dev)) { + xf86SetViewport(pScreen, px, py); + view_adjusted = TRUE; + } + + (*pScreen->SetCursorPosition) (dev, pScreen, px, py, FALSE); + } + } + + return TRUE; +} + +static Bool +xf86RandR12ScreenSetSize (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + WindowPtr pRoot = pScreen->root; + PixmapPtr pScrnPix; + Bool ret = FALSE; + int c; + + if (xf86RandR12Key) { + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + } + if (pRoot && pScrn->vtSema) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); + + /* Let the driver update virtualX and virtualY */ + if (!(*config->funcs->resize)(pScrn, width, height)) + goto finish; + + ret = TRUE; + /* Update panning information */ + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 || + crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { + if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1) + crtc->panningTotalArea.x2 += width - pScreen->width; + if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1) + crtc->panningTotalArea.y2 += height - pScreen->height; + if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1) + crtc->panningTrackingArea.x2 += width - pScreen->width; + if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1) + crtc->panningTrackingArea.y2 += height - pScreen->height; + xf86RandR13VerifyPanningArea (crtc, width, height); + xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); + } + } + + pScrnPix = (*pScreen->GetScreenPixmap)(pScreen); + pScreen->width = pScrnPix->drawable.width = width; + pScreen->height = pScrnPix->drawable.height = height; + randrp->mmWidth = pScreen->mmWidth = mmWidth; + randrp->mmHeight = pScreen->mmHeight = mmHeight; + + xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1); + xf86SetViewport (pScreen, 0, 0); + +finish: + if (pRoot && pScrn->vtSema) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); +#if RANDR_12_INTERFACE + if (xf86RandR12Key && pScreen->root && ret) + RRScreenSizeNotify (pScreen); +#endif + return ret; +} + +Rotation +xf86RandR12GetRotation(ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + return randrp->rotation; +} + +Bool +xf86RandR12CreateScreenResources (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config; + XF86RandRInfoPtr randrp; + int c; + int width, height; + int mmWidth, mmHeight; +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + return TRUE; +#endif + + config = XF86_CRTC_CONFIG_PTR(pScrn); + randrp = XF86RANDRINFO(pScreen); + /* + * Compute size of screen + */ + width = 0; height = 0; + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation); + int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation); + + if (crtc->enabled) { + if (crtc_width > width) + width = crtc_width; + if (crtc_height > height) + height = crtc_height; + if (crtc->panningTotalArea.x2 > width) + width = crtc->panningTotalArea.x2; + if (crtc->panningTotalArea.y2 > height) + height = crtc->panningTotalArea.y2; + } + } + + if (width && height) + { + /* + * Compute physical size of screen + */ + if (monitorResolution) + { + mmWidth = width * 25.4 / monitorResolution; + mmHeight = height * 25.4 / monitorResolution; + } + else + { + xf86OutputPtr output = xf86CompatOutput(pScrn); + + if (output && + output->conf_monitor && + (output->conf_monitor->mon_width > 0 && + output->conf_monitor->mon_height > 0)) + { + /* + * Prefer user configured DisplaySize + */ + mmWidth = output->conf_monitor->mon_width; + mmHeight = output->conf_monitor->mon_height; + } + else + { + /* + * Otherwise, just set the screen to DEFAULT_DPI + */ + mmWidth = width * 25.4 / DEFAULT_DPI; + mmHeight = height * 25.4 / DEFAULT_DPI; + } + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Setting screen physical size to %d x %d\n", + mmWidth, mmHeight); + /* + * This is the initial setting of the screen size. + * We have to pre-set it here, otherwise panning would be adapted + * to the new screen size. + */ + pScreen->width = width; + pScreen->height = height; + xf86RandR12ScreenSetSize (pScreen, + width, + height, + mmWidth, + mmHeight); + } + + if (xf86RandR12Key == NULL) + return TRUE; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + xf86CrtcSetScreenSubpixelOrder (pScreen); +#if RANDR_12_INTERFACE + if (xf86RandR12CreateScreenResources12 (pScreen)) + return TRUE; +#endif + return TRUE; +} + + +Bool +xf86RandR12Init (ScreenPtr pScreen) +{ + rrScrPrivPtr rp; + XF86RandRInfoPtr randrp; + +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + { + if (xf86NumScreens == 1) + noPanoramiXExtension = TRUE; + else + return TRUE; + } +#endif + + if (xf86RandR12Generation != serverGeneration) + xf86RandR12Generation = serverGeneration; + + xf86RandR12Key = &xf86RandR12KeyRec; + if (!dixRegisterPrivateKey(&xf86RandR12KeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + randrp = malloc(sizeof (XF86RandRInfoRec)); + if (!randrp) + return FALSE; + + if (!RRScreenInit(pScreen)) + { + free(randrp); + return FALSE; + } + rp = rrGetScrPriv(pScreen); + rp->rrGetInfo = xf86RandR12GetInfo; + rp->rrSetConfig = xf86RandR12SetConfig; + + randrp->virtualX = -1; + randrp->virtualY = -1; + randrp->mmWidth = pScreen->mmWidth; + randrp->mmHeight = pScreen->mmHeight; + + randrp->rotation = RR_Rotate_0; /* initial rotated mode */ + + randrp->supported_rotations = RR_Rotate_0; + + randrp->maxX = randrp->maxY = 0; + + dixSetPrivate(&pScreen->devPrivates, xf86RandR12Key, randrp); + +#if RANDR_12_INTERFACE + if (!xf86RandR12Init12 (pScreen)) + return FALSE; +#endif + return TRUE; +} + +void +xf86RandR12CloseScreen (ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp; + + if (xf86RandR12Key == NULL) + return; + + randrp = XF86RANDRINFO(pScreen); +#if RANDR_12_INTERFACE + xf86Screens[pScreen->myNum]->EnterVT = randrp->orig_EnterVT; +#endif + + free(randrp); +} + +void +xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations) +{ + XF86RandRInfoPtr randrp; +#if RANDR_12_INTERFACE + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int c; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); +#endif + + if (xf86RandR12Key == NULL) + return; + + randrp = XF86RANDRINFO(pScreen); +#if RANDR_12_INTERFACE + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + RRCrtcSetRotations (crtc->randr_crtc, rotations); + } +#endif + randrp->supported_rotations = rotations; +} + +void +xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms) +{ + XF86RandRInfoPtr randrp; +#if RANDR_13_INTERFACE + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int c; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); +#endif + + if (xf86RandR12Key == NULL) + return; + + randrp = XF86RANDRINFO(pScreen); +#if RANDR_13_INTERFACE + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + RRCrtcSetTransformSupport (crtc->randr_crtc, transforms); + } +#endif +} + +void +xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) +{ + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + + if (xf86RandR12Generation != serverGeneration || + XF86RANDRINFO(pScreen)->virtualX == -1) + { + *x = pScrn->virtualX; + *y = pScrn->virtualY; + } else { + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + *x = randrp->virtualX; + *y = randrp->virtualY; + } +} + +#if RANDR_12_INTERFACE + +#define FLAG_BITS (RR_HSyncPositive | \ + RR_HSyncNegative | \ + RR_VSyncPositive | \ + RR_VSyncNegative | \ + RR_Interlace | \ + RR_DoubleScan | \ + RR_CSync | \ + RR_CSyncPositive | \ + RR_CSyncNegative | \ + RR_HSkewPresent | \ + RR_BCast | \ + RR_PixelMultiplex | \ + RR_DoubleClock | \ + RR_ClockDivideBy2) + +static Bool +xf86RandRModeMatches (RRModePtr randr_mode, + DisplayModePtr mode) +{ +#if 0 + if (match_name) + { + /* check for same name */ + int len = strlen (mode->name); + if (randr_mode->mode.nameLength != len) return FALSE; + if (memcmp (randr_mode->name, mode->name, len) != 0) return FALSE; + } +#endif + + /* check for same timings */ + if (randr_mode->mode.dotClock / 1000 != mode->Clock) return FALSE; + if (randr_mode->mode.width != mode->HDisplay) return FALSE; + if (randr_mode->mode.hSyncStart != mode->HSyncStart) return FALSE; + if (randr_mode->mode.hSyncEnd != mode->HSyncEnd) return FALSE; + if (randr_mode->mode.hTotal != mode->HTotal) return FALSE; + if (randr_mode->mode.hSkew != mode->HSkew) return FALSE; + if (randr_mode->mode.height != mode->VDisplay) return FALSE; + if (randr_mode->mode.vSyncStart != mode->VSyncStart) return FALSE; + if (randr_mode->mode.vSyncEnd != mode->VSyncEnd) return FALSE; + if (randr_mode->mode.vTotal != mode->VTotal) return FALSE; + + /* check for same flags (using only the XF86 valid flag bits) */ + if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS)) + return FALSE; + + /* everything matches */ + return TRUE; +} + +static Bool +xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) +{ + ScreenPtr pScreen = randr_crtc->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + RRModePtr randr_mode = NULL; + int x; + int y; + Rotation rotation; + int numOutputs; + RROutputPtr *randr_outputs; + RROutputPtr randr_output; + xf86CrtcPtr crtc = randr_crtc->devPrivate; + xf86OutputPtr output; + int i, j; + DisplayModePtr mode = &crtc->mode; + Bool ret; + + randr_outputs = malloc(config->num_output * sizeof (RROutputPtr)); + if (!randr_outputs) + return FALSE; + x = crtc->x; + y = crtc->y; + rotation = crtc->rotation; + numOutputs = 0; + randr_mode = NULL; + for (i = 0; i < config->num_output; i++) + { + output = config->output[i]; + if (output->crtc == crtc) + { + randr_output = output->randr_output; + randr_outputs[numOutputs++] = randr_output; + /* + * We make copies of modes, so pointer equality + * isn't sufficient + */ + for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++) + { + RRModePtr m = (j < randr_output->numModes ? + randr_output->modes[j] : + randr_output->userModes[j-randr_output->numModes]); + + if (xf86RandRModeMatches (m, mode)) + { + randr_mode = m; + break; + } + } + } + } + ret = RRCrtcNotify (randr_crtc, randr_mode, x, y, + rotation, + crtc->transformPresent ? &crtc->transform : NULL, + numOutputs, randr_outputs); + free(randr_outputs); + return ret; +} + +/* + * Convert a RandR mode to a DisplayMode + */ +static void +xf86RandRModeConvert (ScrnInfoPtr scrn, + RRModePtr randr_mode, + DisplayModePtr mode) +{ + memset(mode, 0, sizeof(DisplayModeRec)); + mode->status = MODE_OK; + + mode->Clock = randr_mode->mode.dotClock / 1000; + + mode->HDisplay = randr_mode->mode.width; + mode->HSyncStart = randr_mode->mode.hSyncStart; + mode->HSyncEnd = randr_mode->mode.hSyncEnd; + mode->HTotal = randr_mode->mode.hTotal; + mode->HSkew = randr_mode->mode.hSkew; + + mode->VDisplay = randr_mode->mode.height; + mode->VSyncStart = randr_mode->mode.vSyncStart; + mode->VSyncEnd = randr_mode->mode.vSyncEnd; + mode->VTotal = randr_mode->mode.vTotal; + mode->VScan = 0; + + mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS; + + xf86SetModeCrtc (mode, scrn->adjustFlags); +} + +static Bool +xf86RandR12CrtcSet (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + RRModePtr randr_mode, + int x, + int y, + Rotation rotation, + int num_randr_outputs, + RROutputPtr *randr_outputs) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc = randr_crtc->devPrivate; + RRTransformPtr transform; + Bool changed = FALSE; + int o, ro; + xf86CrtcPtr *save_crtcs; + Bool save_enabled = crtc->enabled; + + if (!crtc->scrn->vtSema) + return FALSE; + + save_crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr)); + if ((randr_mode != NULL) != crtc->enabled) + changed = TRUE; + else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode)) + changed = TRUE; + + if (rotation != crtc->rotation) + changed = TRUE; + + transform = RRCrtcGetTransform (randr_crtc); + if ((transform != NULL) != crtc->transformPresent) + changed = TRUE; + else if (transform && memcmp (&transform->transform, &crtc->transform.transform, + sizeof (transform->transform)) != 0) + changed = TRUE; + + if (x != crtc->x || y != crtc->y) + changed = TRUE; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + xf86CrtcPtr new_crtc; + + save_crtcs[o] = output->crtc; + + if (output->crtc == crtc) + new_crtc = NULL; + else + new_crtc = output->crtc; + for (ro = 0; ro < num_randr_outputs; ro++) + if (output->randr_output == randr_outputs[ro]) + { + new_crtc = crtc; + break; + } + if (new_crtc != output->crtc) + { + changed = TRUE; + output->crtc = new_crtc; + } + } + for (ro = 0; ro < num_randr_outputs; ro++) + if (randr_outputs[ro]->pendingProperties) + changed = TRUE; + + /* XXX need device-independent mode setting code through an API */ + if (changed) + { + crtc->enabled = randr_mode != NULL; + + if (randr_mode) + { + DisplayModeRec mode; + RRTransformPtr transform = RRCrtcGetTransform (randr_crtc); + + xf86RandRModeConvert (pScrn, randr_mode, &mode); + if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y)) + { + crtc->enabled = save_enabled; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + output->crtc = save_crtcs[o]; + } + free(save_crtcs); + return FALSE; + } + xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height); + xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); + /* + * Save the last successful setting for EnterVT + */ + crtc->desiredMode = mode; + crtc->desiredRotation = rotation; + if (transform) { + crtc->desiredTransform = *transform; + crtc->desiredTransformPresent = TRUE; + } else + crtc->desiredTransformPresent = FALSE; + + crtc->desiredX = x; + crtc->desiredY = y; + } + xf86DisableUnusedFunctions (pScrn); + } + free(save_crtcs); + return xf86RandR12CrtcNotify (randr_crtc); +} + +static Bool +xf86RandR12CrtcSetGamma (ScreenPtr pScreen, + RRCrtcPtr randr_crtc) +{ + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + if (crtc->funcs->gamma_set == NULL) + return FALSE; + + if (!crtc->scrn->vtSema) + return TRUE; + + /* Realloc local gamma if needed. */ + if (randr_crtc->gammaSize != crtc->gamma_size) { + CARD16 *tmp_ptr; + tmp_ptr = realloc(crtc->gamma_red, 3 * crtc->gamma_size * sizeof (CARD16)); + if (!tmp_ptr) + return FALSE; + crtc->gamma_red = tmp_ptr; + crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; + crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; + } + + crtc->gamma_size = randr_crtc->gammaSize; + memcpy (crtc->gamma_red, randr_crtc->gammaRed, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_green, randr_crtc->gammaGreen, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_blue, randr_crtc->gammaBlue, crtc->gamma_size * sizeof (CARD16)); + + /* Only set it when the crtc is actually running. + * Otherwise it will be set when it's activated. + */ + if (crtc->active) + crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, + crtc->gamma_blue, crtc->gamma_size); + + return TRUE; +} + +static Bool +xf86RandR12CrtcGetGamma (ScreenPtr pScreen, + RRCrtcPtr randr_crtc) +{ + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + if (!crtc->gamma_size) + return FALSE; + + if (!crtc->gamma_red || !crtc->gamma_green || !crtc->gamma_blue) + return FALSE; + + /* Realloc randr gamma if needed. */ + if (randr_crtc->gammaSize != crtc->gamma_size) { + CARD16 *tmp_ptr; + tmp_ptr = realloc(randr_crtc->gammaRed, 3 * crtc->gamma_size * sizeof (CARD16)); + if (!tmp_ptr) + return FALSE; + randr_crtc->gammaRed = tmp_ptr; + randr_crtc->gammaGreen = randr_crtc->gammaRed + crtc->gamma_size; + randr_crtc->gammaBlue = randr_crtc->gammaGreen + crtc->gamma_size; + } + randr_crtc->gammaSize = crtc->gamma_size; + memcpy (randr_crtc->gammaRed, crtc->gamma_red, crtc->gamma_size * sizeof (CARD16)); + memcpy (randr_crtc->gammaGreen, crtc->gamma_green, crtc->gamma_size * sizeof (CARD16)); + memcpy (randr_crtc->gammaBlue, crtc->gamma_blue, crtc->gamma_size * sizeof (CARD16)); + + return TRUE; +} + +static Bool +xf86RandR12OutputSetProperty (ScreenPtr pScreen, + RROutputPtr randr_output, + Atom property, + RRPropertyValuePtr value) +{ + xf86OutputPtr output = randr_output->devPrivate; + + /* If we don't have any property handler, then we don't care what the + * user is setting properties to. + */ + if (output->funcs->set_property == NULL) + return TRUE; + + /* + * This function gets called even when vtSema is FALSE, as + * drivers will need to remember the correct value to apply + * when the VT switch occurs + */ + return output->funcs->set_property(output, property, value); +} + +static Bool +xf86RandR13OutputGetProperty (ScreenPtr pScreen, + RROutputPtr randr_output, + Atom property) +{ + xf86OutputPtr output = randr_output->devPrivate; + + if (output->funcs->get_property == NULL) + return TRUE; + + /* Should be safe even w/o vtSema */ + return output->funcs->get_property(output, property); +} + +static Bool +xf86RandR12OutputValidateMode (ScreenPtr pScreen, + RROutputPtr randr_output, + RRModePtr randr_mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86OutputPtr output = randr_output->devPrivate; + DisplayModeRec mode; + + xf86RandRModeConvert (pScrn, randr_mode, &mode); + /* + * This function may be called when vtSema is FALSE, so + * the underlying function must either avoid touching the hardware + * or return FALSE when vtSema is FALSE + */ + if (output->funcs->mode_valid (output, &mode) != MODE_OK) + return FALSE; + return TRUE; +} + +static void +xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode) +{ +} + +/** + * Given a list of xf86 modes and a RandR Output object, construct + * RandR modes and assign them to the output + */ +static Bool +xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) +{ + DisplayModePtr mode; + RRModePtr *rrmodes = NULL; + int nmode = 0; + int npreferred = 0; + Bool ret = TRUE; + int pref; + + for (mode = modes; mode; mode = mode->next) + nmode++; + + if (nmode) { + rrmodes = malloc(nmode * sizeof (RRModePtr)); + + if (!rrmodes) + return FALSE; + nmode = 0; + + for (pref = 1; pref >= 0; pref--) { + for (mode = modes; mode; mode = mode->next) { + if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) { + xRRModeInfo modeInfo; + RRModePtr rrmode; + + modeInfo.nameLength = strlen (mode->name); + modeInfo.width = mode->HDisplay; + modeInfo.dotClock = mode->Clock * 1000; + modeInfo.hSyncStart = mode->HSyncStart; + modeInfo.hSyncEnd = mode->HSyncEnd; + modeInfo.hTotal = mode->HTotal; + modeInfo.hSkew = mode->HSkew; + + modeInfo.height = mode->VDisplay; + modeInfo.vSyncStart = mode->VSyncStart; + modeInfo.vSyncEnd = mode->VSyncEnd; + modeInfo.vTotal = mode->VTotal; + modeInfo.modeFlags = mode->Flags; + + rrmode = RRModeGet (&modeInfo, mode->name); + if (rrmode) { + rrmodes[nmode++] = rrmode; + npreferred += pref; + } + } + } + } + } + + ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred); + free(rrmodes); + return ret; +} + +/* + * Mirror the current mode configuration to RandR + */ +static Bool +xf86RandR12SetInfo12 (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + RROutputPtr *clones; + RRCrtcPtr *crtcs; + int ncrtc; + int o, c, l; + RRCrtcPtr randr_crtc; + int nclone; + + clones = malloc(config->num_output * sizeof (RROutputPtr)); + crtcs = malloc(config->num_crtc * sizeof (RRCrtcPtr)); + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + ncrtc = 0; + for (c = 0; c < config->num_crtc; c++) + if (output->possible_crtcs & (1 << c)) + crtcs[ncrtc++] = config->crtc[c]->randr_crtc; + + if (output->crtc) + randr_crtc = output->crtc->randr_crtc; + else + randr_crtc = NULL; + + if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc)) + { + free(crtcs); + free(clones); + return FALSE; + } + + RROutputSetPhysicalSize(output->randr_output, + output->mm_width, + output->mm_height); + xf86RROutputSetModes (output->randr_output, output->probed_modes); + + switch (output->status) { + case XF86OutputStatusConnected: + RROutputSetConnection (output->randr_output, RR_Connected); + break; + case XF86OutputStatusDisconnected: + RROutputSetConnection (output->randr_output, RR_Disconnected); + break; + case XF86OutputStatusUnknown: + RROutputSetConnection (output->randr_output, RR_UnknownConnection); + break; + } + + RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order); + + /* + * Valid clones + */ + nclone = 0; + for (l = 0; l < config->num_output; l++) + { + xf86OutputPtr clone = config->output[l]; + + if (l != o && (output->possible_clones & (1 << l))) + clones[nclone++] = clone->randr_output; + } + if (!RROutputSetClones (output->randr_output, clones, nclone)) + { + free(crtcs); + free(clones); + return FALSE; + } + } + free(crtcs); + free(clones); + return TRUE; +} + + + +/* + * Query the hardware for the current state, then mirror + * that to RandR + */ +static Bool +xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (!pScrn->vtSema) + return TRUE; + xf86ProbeOutputModes (pScrn, 0, 0); + xf86SetScrnInfoModes (pScrn); + return xf86RandR12SetInfo12 (pScreen); +} + +static Bool +xf86RandR12CreateObjects12 (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + int o; + + if (!RRInit ()) + return FALSE; + + /* + * Configure crtcs + */ + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->randr_crtc = RRCrtcCreate (pScreen, crtc); + RRCrtcGammaSetSize (crtc->randr_crtc, 256); + } + /* + * Configure outputs + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->randr_output = RROutputCreate (pScreen, output->name, + strlen (output->name), + output); + + if (output->funcs->create_resources != NULL) + output->funcs->create_resources(output); + RRPostPendingProperties (output->randr_output); + } + return TRUE; +} + +static Bool +xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) +{ + int c; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + + if (xf86RandR12Key == NULL) + return TRUE; + + for (c = 0; c < config->num_crtc; c++) + xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); + + RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight, + config->maxWidth, config->maxHeight); + return TRUE; +} + +/* + * Something happened within the screen configuration due + * to DGA, VidMode or hot key. Tell RandR + */ + +void +xf86RandR12TellChanged (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + + if (xf86RandR12Key == NULL) + return; + + xf86RandR12SetInfo12 (pScreen); + for (c = 0; c < config->num_crtc; c++) + xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); + + RRTellChanged (pScreen); +} + +static void +xf86RandR12PointerMoved (int scrnIndex, int x, int y) +{ + ScreenPtr pScreen = screenInfo.screens[scrnIndex]; + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int c; + + randrp->pointerX = x; + randrp->pointerY = y; + for (c = 0; c < config->num_crtc; c++) + xf86RandR13Pan (config->crtc[c], x, y); +} + +static Bool +xf86RandR13GetPanning (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border) +{ + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + if (crtc->version < 2) + return FALSE; + if (totalArea) + memcpy (totalArea, &crtc->panningTotalArea, sizeof(BoxRec)); + if (trackingArea) + memcpy (trackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); + if (border) + memcpy (border, crtc->panningBorder, 4*sizeof(INT16)); + + return TRUE; +} + +static Bool +xf86RandR13SetPanning (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + xf86CrtcPtr crtc = randr_crtc->devPrivate; + BoxRec oldTotalArea; + BoxRec oldTrackingArea; + INT16 oldBorder[4]; + + + if (crtc->version < 2) + return FALSE; + + memcpy (&oldTotalArea, &crtc->panningTotalArea, sizeof(BoxRec)); + memcpy (&oldTrackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); + memcpy (oldBorder, crtc->panningBorder, 4*sizeof(INT16)); + + if (totalArea) + memcpy (&crtc->panningTotalArea, totalArea, sizeof(BoxRec)); + if (trackingArea) + memcpy (&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec)); + if (border) + memcpy (crtc->panningBorder, border, 4*sizeof(INT16)); + + if (xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height)) { + xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); + return TRUE; + } else { + /* Restore old settings */ + memcpy (&crtc->panningTotalArea, &oldTotalArea, sizeof(BoxRec)); + memcpy (&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec)); + memcpy (crtc->panningBorder, oldBorder, 4*sizeof(INT16)); + return FALSE; + } +} + +/* + * Compatibility with XF86VidMode's gamma changer. This necessarily clobbers + * any per-crtc setup. You asked for it... + */ + +static void +gamma_to_ramp(float gamma, CARD16 *ramp, int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (gamma == 1.0) + ramp[i] = i << 8; + else + ramp[i] = (CARD16)(pow((double)i / (double)(size - 1), 1. / gamma) + * (double)(size - 1) * 256); + } +} + +static int +xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma) +{ + CARD16 *points, *red, *green, *blue; + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + int size; + + if (!crtc) + return Success; + + size = max(0, crtc->gammaSize); + if (!size) + return Success; + + points = calloc(size, 3 * sizeof(CARD16)); + if (!points) + return BadAlloc; + + red = points; + green = points + size; + blue = points + 2 * size; + + gamma_to_ramp(gamma.red, red, size); + gamma_to_ramp(gamma.green, green, size); + gamma_to_ramp(gamma.blue, blue, size); + RRCrtcGammaSet(crtc, red, green, blue); + + free(points); + + pScrn->gamma = gamma; + + return Success; +} + +static Bool +xf86RandR12EnterVT (int screen_index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[screen_index]; + ScrnInfoPtr pScrn = xf86Screens[screen_index]; + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + rrScrPrivPtr rp = rrGetScrPriv(pScreen); + Bool ret; + int i; + + if (randrp->orig_EnterVT) { + pScrn->EnterVT = randrp->orig_EnterVT; + ret = pScrn->EnterVT (screen_index, flags); + randrp->orig_EnterVT = pScrn->EnterVT; + pScrn->EnterVT = xf86RandR12EnterVT; + if (!ret) + return FALSE; + } + + /* reload gamma */ + for (i = 0; i < rp->numCrtcs; i++) + xf86RandR12CrtcSetGamma(pScreen, rp->crtcs[i]); + + return RRGetInfo (pScreen, TRUE); /* force a re-probe of outputs and notify clients about changes */ +} + +static Bool +xf86RandR12Init12 (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + rrScrPrivPtr rp = rrGetScrPriv(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int i; + + rp->rrGetInfo = xf86RandR12GetInfo12; + rp->rrScreenSetSize = xf86RandR12ScreenSetSize; + rp->rrCrtcSet = xf86RandR12CrtcSet; + rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma; + rp->rrCrtcGetGamma = xf86RandR12CrtcGetGamma; + rp->rrOutputSetProperty = xf86RandR12OutputSetProperty; + rp->rrOutputValidateMode = xf86RandR12OutputValidateMode; +#if RANDR_13_INTERFACE + rp->rrOutputGetProperty = xf86RandR13OutputGetProperty; + rp->rrGetPanning = xf86RandR13GetPanning; + rp->rrSetPanning = xf86RandR13SetPanning; +#endif + rp->rrModeDestroy = xf86RandR12ModeDestroy; + rp->rrSetConfig = NULL; + pScrn->PointerMoved = xf86RandR12PointerMoved; + pScrn->ChangeGamma = xf86RandR12ChangeGamma; + + randrp->orig_EnterVT = pScrn->EnterVT; + pScrn->EnterVT = xf86RandR12EnterVT; + + if (!xf86RandR12CreateObjects12 (pScreen)) + return FALSE; + + /* + * Configure output modes + */ + if (!xf86RandR12SetInfo12 (pScreen)) + return FALSE; + for (i = 0; i < rp->numCrtcs; i++) { + xf86RandR12CrtcGetGamma(pScreen, rp->crtcs[i]); + } + return TRUE; +} + +#endif + +Bool +xf86RandR12PreInit (ScrnInfoPtr pScrn) +{ + return TRUE; +} -- cgit v1.2.3