diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-25 19:29:01 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-25 19:29:01 +0000 |
commit | 90f1536dd315cd265bfc7ef35058761a65a01734 (patch) | |
tree | ce1f7aed9444ad2577d62a6e5a2dd36008771c6c /hw/darwin/iokit | |
parent | d461855a73d8c9f51a18673aef7ce88f94a71629 (diff) |
Initial revisionXORG-STABLE
Diffstat (limited to 'hw/darwin/iokit')
-rw-r--r-- | hw/darwin/iokit/xfIOKit.c | 770 | ||||
-rw-r--r-- | hw/darwin/iokit/xfIOKit.h | 57 | ||||
-rw-r--r-- | hw/darwin/iokit/xfIOKitCursor.c | 735 | ||||
-rw-r--r-- | hw/darwin/iokit/xfIOKitStartup.c | 115 |
4 files changed, 1677 insertions, 0 deletions
diff --git a/hw/darwin/iokit/xfIOKit.c b/hw/darwin/iokit/xfIOKit.c new file mode 100644 index 000000000..6b4bd75c2 --- /dev/null +++ b/hw/darwin/iokit/xfIOKit.c @@ -0,0 +1,770 @@ +/************************************************************** + * + * IOKit support for the Darwin X Server + * + * HISTORY: + * Original port to Mac OS X Server by John Carmack + * Port to Darwin 1.0 by Dave Zarzycki + * Significantly rewritten for XFree86 4.0.1 by Torrey Lyons + * + **************************************************************/ +/* + * Copyright (c) 2001-2002 Torrey T. Lyons. 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, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/iokit/xfIOKit.c,v 1.2 2003/10/16 23:50:09 torrey Exp $ */ + +#include "X.h" +#include "Xproto.h" +#include "os.h" +#include "servermd.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "mi.h" +#include "mibstore.h" +#include "mipointer.h" +#include "micmap.h" +#include "shadow.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <unistd.h> +#include <fcntl.h> +#include <pthread.h> + +#include <mach/mach_interface.h> + +#define NO_CFPLUGIN +#include <IOKit/IOKitLib.h> +#include <IOKit/hidsystem/IOHIDShared.h> +#include <IOKit/graphics/IOGraphicsLib.h> +#include <drivers/event_status_driver.h> + +// Define this to work around bugs in the display drivers for +// older PowerBook G3's. If the X server starts without this +// #define, you don't need it. +#undef OLD_POWERBOOK_G3 + +#include "darwin.h" +#include "xfIOKit.h" + +// Globals +int xfIOKitScreenIndex = 0; +io_connect_t xfIOKitInputConnect = 0; + +static pthread_t inputThread; +static EvGlobals * evg; +static mach_port_t masterPort; +static mach_port_t notificationPort; +static IONotificationPortRef NotificationPortRef; +static mach_port_t pmNotificationPort; +static io_iterator_t fbIter; + + +/* + * XFIOKitStoreColors + * This is a callback from X to change the hardware colormap + * when using PsuedoColor. + */ +static void XFIOKitStoreColors( + ColormapPtr pmap, + int numEntries, + xColorItem *pdefs) +{ + kern_return_t kr; + int i; + IOColorEntry *newColors; + ScreenPtr pScreen = pmap->pScreen; + XFIOKitScreenPtr iokitScreen = XFIOKIT_SCREEN_PRIV(pScreen); + + assert( newColors = (IOColorEntry *) + xalloc( numEntries*sizeof(IOColorEntry) )); + + // Convert xColorItem values to IOColorEntry + // assume the colormap is PsuedoColor + // as we do not support DirectColor + for (i = 0; i < numEntries; i++) { + newColors[i].index = pdefs[i].pixel; + newColors[i].red = pdefs[i].red; + newColors[i].green = pdefs[i].green; + newColors[i].blue = pdefs[i].blue; + } + + kr = IOFBSetCLUT( iokitScreen->fbService, 0, numEntries, + kSetCLUTByValue, newColors ); + kern_assert( kr ); + + xfree( newColors ); +} + + +/* + * DarwinModeBell + * FIXME + */ +void DarwinModeBell( + int loud, + DeviceIntPtr pDevice, + pointer ctrl, + int fbclass) +{ +} + + +/* + * DarwinModeGiveUp + * Closes the connections to IOKit services + */ +void DarwinModeGiveUp( void ) +{ + int i; + + // we must close the HID System first + // because it is a client of the framebuffer + NXCloseEventStatus( darwinParamConnect ); + IOServiceClose( xfIOKitInputConnect ); + for (i = 0; i < screenInfo.numScreens; i++) { + XFIOKitScreenPtr iokitScreen = + XFIOKIT_SCREEN_PRIV(screenInfo.screens[i]); + IOServiceClose( iokitScreen->fbService ); + } +} + + +/* + * ClearEvent + * Clear an event from the HID System event queue + */ +static void ClearEvent(NXEvent * ep) +{ + static NXEvent nullEvent = {NX_NULLEVENT, {0, 0 }, 0, -1, 0 }; + + *ep = nullEvent; + ep->data.compound.subType = ep->data.compound.misc.L[0] = + ep->data.compound.misc.L[1] = 0; +} + + +/* + * XFIOKitHIDThread + * Read the HID System event queue, translate it to an X event, + * and queue it for processing. + */ +static void *XFIOKitHIDThread(void *unused) +{ + for (;;) { + NXEQElement *oldHead; + mach_msg_return_t kr; + mach_msg_empty_rcv_t msg; + + kr = mach_msg((mach_msg_header_t*) &msg, MACH_RCV_MSG, 0, + sizeof(msg), notificationPort, 0, MACH_PORT_NULL); + kern_assert(kr); + + while (evg->LLEHead != evg->LLETail) { + NXEvent ev; + xEvent xe; + + // Extract the next event from the kernel queue + oldHead = (NXEQElement*)&evg->lleq[evg->LLEHead]; + ev_lock(&oldHead->sema); + ev = oldHead->event; + ClearEvent(&oldHead->event); + evg->LLEHead = oldHead->next; + ev_unlock(&oldHead->sema); + + memset(&xe, 0, sizeof(xe)); + + // These fields should be filled in for every event + xe.u.keyButtonPointer.rootX = ev.location.x; + xe.u.keyButtonPointer.rootY = ev.location.y; + xe.u.keyButtonPointer.time = GetTimeInMillis(); + + switch( ev.type ) { + case NX_MOUSEMOVED: + xe.u.u.type = MotionNotify; + break; + + case NX_LMOUSEDOWN: + xe.u.u.type = ButtonPress; + xe.u.u.detail = 1; + break; + + case NX_LMOUSEUP: + xe.u.u.type = ButtonRelease; + xe.u.u.detail = 1; + break; + + // A newer kernel generates multi-button events with + // NX_SYSDEFINED. Button 2 isn't handled correctly by + // older kernels anyway. Just let NX_SYSDEFINED events + // handle these. +#if 0 + case NX_RMOUSEDOWN: + xe.u.u.type = ButtonPress; + xe.u.u.detail = 2; + break; + + case NX_RMOUSEUP: + xe.u.u.type = ButtonRelease; + xe.u.u.detail = 2; + break; +#endif + + case NX_KEYDOWN: + xe.u.u.type = KeyPress; + xe.u.u.detail = ev.data.key.keyCode; + break; + + case NX_KEYUP: + xe.u.u.type = KeyRelease; + xe.u.u.detail = ev.data.key.keyCode; + break; + + case NX_FLAGSCHANGED: + xe.u.u.type = kXDarwinUpdateModifiers; + xe.u.clientMessage.u.l.longs0 = ev.flags; + break; + + case NX_SYSDEFINED: + if (ev.data.compound.subType == 7) { + xe.u.u.type = kXDarwinUpdateButtons; + xe.u.clientMessage.u.l.longs0 = + ev.data.compound.misc.L[0]; + xe.u.clientMessage.u.l.longs1 = + ev.data.compound.misc.L[1]; + } else { + continue; + } + break; + + case NX_SCROLLWHEELMOVED: + xe.u.u.type = kXDarwinScrollWheel; + xe.u.clientMessage.u.s.shorts0 = + ev.data.scrollWheel.deltaAxis1; + break; + + default: + continue; + } + + DarwinEQEnqueue(&xe); + } + } + + return NULL; +} + + +/* + * XFIOKitPMThread + * Handle power state notifications + */ +static void *XFIOKitPMThread(void *arg) +{ + ScreenPtr pScreen = (ScreenPtr)arg; + XFIOKitScreenPtr iokitScreen = XFIOKIT_SCREEN_PRIV(pScreen); + + for (;;) { + mach_msg_return_t kr; + mach_msg_empty_rcv_t msg; + + kr = mach_msg((mach_msg_header_t*) &msg, MACH_RCV_MSG, 0, + sizeof(msg), pmNotificationPort, 0, MACH_PORT_NULL); + kern_assert(kr); + + // display is powering down + if (msg.header.msgh_id == 0) { + IOFBAcknowledgePM( iokitScreen->fbService ); + xf86SetRootClip(pScreen, FALSE); + } + // display just woke up + else if (msg.header.msgh_id == 1) { + xf86SetRootClip(pScreen, TRUE); + } + } + return NULL; +} + + +/* + * SetupFBandHID + * Setup an IOFramebuffer service and connect the HID system to it. + */ +static Bool SetupFBandHID( + int index, + DarwinFramebufferPtr dfb, + XFIOKitScreenPtr iokitScreen) +{ + kern_return_t kr; + io_service_t service; + io_connect_t fbService; + vm_address_t vram; + vm_size_t shmemSize; + int i; + UInt32 numModes; + IODisplayModeInformation modeInfo; + IODisplayModeID displayMode, *allModes; + IOIndex displayDepth; + IOFramebufferInformation fbInfo; + IOPixelInformation pixelInfo; + StdFBShmem_t *cshmem; + + // find and open the IOFrameBuffer service + service = IOIteratorNext(fbIter); + if (service == 0) + return FALSE; + + kr = IOServiceOpen( service, mach_task_self(), + kIOFBServerConnectType, &iokitScreen->fbService ); + IOObjectRelease( service ); + if (kr != KERN_SUCCESS) { + ErrorF("Failed to connect as window server to screen %i.\n", index); + return FALSE; + } + fbService = iokitScreen->fbService; + + // create the slice of shared memory containing cursor state data + kr = IOFBCreateSharedCursor( fbService, + kIOFBCurrentShmemVersion, + 32, 32 ); + if (kr != KERN_SUCCESS) + return FALSE; + + // Register for power management events for the framebuffer's device + kr = IOCreateReceivePort(kOSNotificationMessageID, &pmNotificationPort); + kern_assert(kr); + kr = IOConnectSetNotificationPort( fbService, 0, + pmNotificationPort, 0 ); + if (kr != KERN_SUCCESS) { + ErrorF("Power management registration failed.\n"); + } + + // SET THE SCREEN PARAMETERS + // get the current screen resolution, refresh rate and depth + kr = IOFBGetCurrentDisplayModeAndDepth( fbService, + &displayMode, + &displayDepth ); + if (kr != KERN_SUCCESS) + return FALSE; + + // use the current screen resolution if the user + // only wants to change the refresh rate + if (darwinDesiredRefresh != -1 && darwinDesiredWidth == 0) { + kr = IOFBGetDisplayModeInformation( fbService, + displayMode, + &modeInfo ); + if (kr != KERN_SUCCESS) + return FALSE; + darwinDesiredWidth = modeInfo.nominalWidth; + darwinDesiredHeight = modeInfo.nominalHeight; + } + + // use the current resolution and refresh rate + // if the user doesn't have a preference + if (darwinDesiredWidth == 0) { + + // change the pixel depth if desired + if (darwinDesiredDepth != -1) { + kr = IOFBGetDisplayModeInformation( fbService, + displayMode, + &modeInfo ); + if (kr != KERN_SUCCESS) + return FALSE; + if (modeInfo.maxDepthIndex < darwinDesiredDepth) { + ErrorF("Discarding screen %i:\n", index); + ErrorF("Current screen resolution does not support desired pixel depth.\n"); + return FALSE; + } + + displayDepth = darwinDesiredDepth; + kr = IOFBSetDisplayModeAndDepth( fbService, displayMode, + displayDepth ); + if (kr != KERN_SUCCESS) + return FALSE; + } + + // look for display mode with correct resolution and refresh rate + } else { + + // get an array of all supported display modes + kr = IOFBGetDisplayModeCount( fbService, &numModes ); + if (kr != KERN_SUCCESS) + return FALSE; + assert(allModes = (IODisplayModeID *) + xalloc( numModes * sizeof(IODisplayModeID) )); + kr = IOFBGetDisplayModes( fbService, numModes, allModes ); + if (kr != KERN_SUCCESS) + return FALSE; + + for (i = 0; i < numModes; i++) { + kr = IOFBGetDisplayModeInformation( fbService, allModes[i], + &modeInfo ); + if (kr != KERN_SUCCESS) + return FALSE; + + if (modeInfo.flags & kDisplayModeValidFlag && + modeInfo.nominalWidth == darwinDesiredWidth && + modeInfo.nominalHeight == darwinDesiredHeight) { + + if (darwinDesiredDepth == -1) + darwinDesiredDepth = modeInfo.maxDepthIndex; + if (modeInfo.maxDepthIndex < darwinDesiredDepth) { + ErrorF("Discarding screen %i:\n", index); + ErrorF("Desired screen resolution does not support desired pixel depth.\n"); + return FALSE; + } + + if ((darwinDesiredRefresh == -1 || + (darwinDesiredRefresh << 16) == modeInfo.refreshRate)) { + displayMode = allModes[i]; + displayDepth = darwinDesiredDepth; + kr = IOFBSetDisplayModeAndDepth(fbService, + displayMode, + displayDepth); + if (kr != KERN_SUCCESS) + return FALSE; + break; + } + } + } + + xfree( allModes ); + if (i >= numModes) { + ErrorF("Discarding screen %i:\n", index); + ErrorF("Desired screen resolution or refresh rate is not supported.\n"); + return FALSE; + } + } + + kr = IOFBGetPixelInformation( fbService, displayMode, displayDepth, + kIOFBSystemAperture, &pixelInfo ); + if (kr != KERN_SUCCESS) + return FALSE; + +#ifdef __i386__ + /* x86 in 8bit mode currently needs fixed color map... */ + if( pixelInfo.bitsPerComponent == 8 ) { + pixelInfo.pixelType = kIOFixedCLUTPixels; + } +#endif + +#ifdef OLD_POWERBOOK_G3 + if (pixelInfo.pixelType == kIOCLUTPixels) + pixelInfo.pixelType = kIOFixedCLUTPixels; +#endif + + kr = IOFBGetFramebufferInformationForAperture( fbService, + kIOFBSystemAperture, + &fbInfo ); + if (kr != KERN_SUCCESS) + return FALSE; + + // FIXME: 1x1 IOFramebuffers are sometimes used to indicate video + // outputs without a monitor connected to them. Since IOKit Xinerama + // does not really work, this often causes problems on PowerBooks. + // For now we explicitly check and ignore these screens. + if (fbInfo.activeWidth <= 1 || fbInfo.activeHeight <= 1) { + ErrorF("Discarding screen %i:\n", index); + ErrorF("Invalid width or height.\n"); + return FALSE; + } + + kr = IOConnectMapMemory( fbService, kIOFBCursorMemory, + mach_task_self(), (vm_address_t *) &cshmem, + &shmemSize, kIOMapAnywhere ); + if (kr != KERN_SUCCESS) + return FALSE; + iokitScreen->cursorShmem = cshmem; + + kr = IOConnectMapMemory( fbService, kIOFBSystemAperture, + mach_task_self(), &vram, &shmemSize, + kIOMapAnywhere ); + if (kr != KERN_SUCCESS) + return FALSE; + + iokitScreen->framebuffer = (void*)vram; + dfb->x = cshmem->screenBounds.minx; + dfb->y = cshmem->screenBounds.miny; + dfb->width = fbInfo.activeWidth; + dfb->height = fbInfo.activeHeight; + dfb->pitch = fbInfo.bytesPerRow; + dfb->bitsPerPixel = fbInfo.bitsPerPixel; + dfb->colorBitsPerPixel = pixelInfo.componentCount * + pixelInfo.bitsPerComponent; + dfb->bitsPerComponent = pixelInfo.bitsPerComponent; + + // allocate shadow framebuffer + iokitScreen->shadowPtr = shadowAlloc(dfb->width, dfb->height, + dfb->bitsPerPixel); + dfb->framebuffer = iokitScreen->shadowPtr; + + // Note: Darwin kIORGBDirectPixels = X TrueColor, not DirectColor + if (pixelInfo.pixelType == kIORGBDirectPixels) { + dfb->colorType = TrueColor; + } else if (pixelInfo.pixelType == kIOCLUTPixels) { + dfb->colorType = PseudoColor; + } else if (pixelInfo.pixelType == kIOFixedCLUTPixels) { + dfb->colorType = StaticColor; + } + + // Inform the HID system that the framebuffer is also connected to it. + kr = IOConnectAddClient( xfIOKitInputConnect, fbService ); + kern_assert( kr ); + + // We have to have added at least one screen + // before we can enable the cursor. + kr = IOHIDSetCursorEnable(xfIOKitInputConnect, TRUE); + kern_assert( kr ); + + return TRUE; +} + + +/* + * DarwinModeAddScreen + * IOKit specific initialization for each screen. + */ +Bool DarwinModeAddScreen( + int index, + ScreenPtr pScreen) +{ + DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); + XFIOKitScreenPtr iokitScreen; + + // allocate space for private per screen storage + iokitScreen = xalloc(sizeof(XFIOKitScreenRec)); + XFIOKIT_SCREEN_PRIV(pScreen) = iokitScreen; + + // setup hardware framebuffer + iokitScreen->fbService = 0; + if (! SetupFBandHID(index, dfb, iokitScreen)) { + if (iokitScreen->fbService) { + IOServiceClose(iokitScreen->fbService); + } + return FALSE; + } + + return TRUE; +} + + +/* + * XFIOKitShadowUpdate + * Update the damaged regions of the shadow framebuffer on the screen. + */ +static void XFIOKitShadowUpdate(ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); + XFIOKitScreenPtr iokitScreen = XFIOKIT_SCREEN_PRIV(pScreen); + RegionPtr damage = &pBuf->damage; + int numBox = REGION_NUM_RECTS(damage); + BoxPtr pBox = REGION_RECTS(damage); + int pitch = dfb->pitch; + int bpp = dfb->bitsPerPixel/8; + + // Loop through all the damaged boxes + while (numBox--) { + int width, height, offset; + unsigned char *src, *dst; + + width = (pBox->x2 - pBox->x1) * bpp; + height = pBox->y2 - pBox->y1; + offset = (pBox->y1 * pitch) + (pBox->x1 * bpp); + src = iokitScreen->shadowPtr + offset; + dst = iokitScreen->framebuffer + offset; + + while (height--) { + memcpy(dst, src, width); + dst += pitch; + src += pitch; + } + + // Get the next box + pBox++; + } +} + + +/* + * DarwinModeSetupScreen + * Finalize IOKit specific initialization of each screen. + */ +Bool DarwinModeSetupScreen( + int index, + ScreenPtr pScreen) +{ + DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); + pthread_t pmThread; + + // initalize cursor support + if (! XFIOKitInitCursor(pScreen)) { + return FALSE; + } + + // initialize shadow framebuffer support + if (! shadowInit(pScreen, XFIOKitShadowUpdate, NULL)) { + ErrorF("Failed to initalize shadow framebuffer for screen %i.\n", + index); + return FALSE; + } + + // initialize colormap handling as needed + if (dfb->colorType == PseudoColor) { + pScreen->StoreColors = XFIOKitStoreColors; + } + + // initialize power manager handling + pthread_create( &pmThread, NULL, XFIOKitPMThread, + (void *) pScreen ); + + return TRUE; +} + + +/* + * DarwinModeInitOutput + * One-time initialization of IOKit output support. + */ +void DarwinModeInitOutput( + int argc, + char **argv) +{ + static unsigned long generation = 0; + kern_return_t kr; + io_iterator_t iter; + io_service_t service; + vm_address_t shmem; + vm_size_t shmemSize; + + ErrorF("Display mode: IOKit\n"); + + // Allocate private storage for each screen's IOKit specific info + if (generation != serverGeneration) { + xfIOKitScreenIndex = AllocateScreenPrivateIndex(); + generation = serverGeneration; + } + + kr = IOMasterPort(bootstrap_port, &masterPort); + kern_assert( kr ); + + // Find and open the HID System Service + // Do this now to be sure the Mac OS X window server is not running. + kr = IOServiceGetMatchingServices( masterPort, + IOServiceMatching( kIOHIDSystemClass ), + &iter ); + kern_assert( kr ); + + assert( service = IOIteratorNext( iter ) ); + + kr = IOServiceOpen( service, mach_task_self(), kIOHIDServerConnectType, + &xfIOKitInputConnect ); + if (kr != KERN_SUCCESS) { + ErrorF("Failed to connect to the HID System as the window server!\n"); +#ifdef DARWIN_WITH_QUARTZ + FatalError("Quit the Mac OS X window server or use the -quartz option.\n"); +#else + FatalError("Make sure you have quit the Mac OS X window server.\n"); +#endif + } + + IOObjectRelease( service ); + IOObjectRelease( iter ); + + // Setup the event queue in memory shared by the kernel and X server + kr = IOHIDCreateSharedMemory( xfIOKitInputConnect, + kIOHIDCurrentShmemVersion ); + kern_assert( kr ); + + kr = IOConnectMapMemory( xfIOKitInputConnect, kIOHIDGlobalMemory, + mach_task_self(), &shmem, &shmemSize, + kIOMapAnywhere ); + kern_assert( kr ); + + evg = (EvGlobals *)(shmem + ((EvOffsets *)shmem)->evGlobalsOffset); + + assert(sizeof(EvGlobals) == evg->structSize); + + NotificationPortRef = IONotificationPortCreate( masterPort ); + + notificationPort = IONotificationPortGetMachPort(NotificationPortRef); + + kr = IOConnectSetNotificationPort( xfIOKitInputConnect, + kIOHIDEventNotification, + notificationPort, 0 ); + kern_assert( kr ); + + evg->movedMask |= NX_MOUSEMOVEDMASK; + + // find number of framebuffers + kr = IOServiceGetMatchingServices( masterPort, + IOServiceMatching( IOFRAMEBUFFER_CONFORMSTO ), + &fbIter ); + kern_assert( kr ); + + darwinScreensFound = 0; + while ((service = IOIteratorNext(fbIter))) { + IOObjectRelease( service ); + darwinScreensFound++; + } + IOIteratorReset(fbIter); +} + + +/* + * DarwinModeInitInput + * One-time initialization of IOKit input support. + */ +void DarwinModeInitInput( + int argc, + char **argv) +{ + kern_return_t kr; + int fd[2]; + + kr = IOHIDSetEventsEnable(xfIOKitInputConnect, TRUE); + kern_assert( kr ); + + // Start event passing thread + assert( pipe(fd) == 0 ); + darwinEventReadFD = fd[0]; + darwinEventWriteFD = fd[1]; + fcntl(darwinEventReadFD, F_SETFL, O_NONBLOCK); + pthread_create(&inputThread, NULL, + XFIOKitHIDThread, NULL); + +} + + +/* + * DarwinModeProcessEvent + * Process IOKit specific events. + */ +void DarwinModeProcessEvent( + xEvent *xe) +{ + // No mode specific events + ErrorF("Unknown X event caught: %d\n", xe->u.u.type); +} diff --git a/hw/darwin/iokit/xfIOKit.h b/hw/darwin/iokit/xfIOKit.h new file mode 100644 index 000000000..413dfd7e8 --- /dev/null +++ b/hw/darwin/iokit/xfIOKit.h @@ -0,0 +1,57 @@ +/* + xfIOKit.h + + IOKit specific functions and definitions +*/ +/* + * Copyright (c) 2001-2002 Torrey T. Lyons. 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, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/iokit/xfIOKit.h,v 1.1 2003/05/14 05:27:56 torrey Exp $ */ + +#ifndef _XFIOKIT_H +#define _XFIOKIT_H + +#include <pthread.h> +#include <IOKit/graphics/IOFramebufferShared.h> +#include "X11/Xproto.h" +#include "screenint.h" +#include "darwin.h" + +typedef struct { + io_connect_t fbService; + StdFBShmem_t *cursorShmem; + unsigned char *framebuffer; + unsigned char *shadowPtr; +} XFIOKitScreenRec, *XFIOKitScreenPtr; + +#define XFIOKIT_SCREEN_PRIV(pScreen) \ + ((XFIOKitScreenPtr)pScreen->devPrivates[xfIOKitScreenIndex].ptr) + +extern int xfIOKitScreenIndex; // index into pScreen.devPrivates +extern io_connect_t xfIOKitInputConnect; + +Bool XFIOKitInitCursor(ScreenPtr pScreen); + +#endif /* _XFIOKIT_H */ diff --git a/hw/darwin/iokit/xfIOKitCursor.c b/hw/darwin/iokit/xfIOKitCursor.c new file mode 100644 index 000000000..f3c80145f --- /dev/null +++ b/hw/darwin/iokit/xfIOKitCursor.c @@ -0,0 +1,735 @@ +/************************************************************** + * + * Cursor support for Darwin X Server + * + * Three different cursor modes are possible: + * X (0) - tracking via Darwin kernel, + * display via X machine independent + * Kernel (1) - tracking and display via Darwin kernel + * (not currently supported) + * Hardware (2) - tracking and display via hardware + * + * The X software cursor uses the Darwin software cursor + * routines in IOFramebuffer.cpp to track the cursor, but + * displays the cursor image using the X machine + * independent display cursor routines in midispcur.c. + * + * The kernel cursor uses IOFramebuffer.cpp routines to + * track and display the cursor. This gives better + * performance as the display calls don't have to cross + * the kernel boundary. Unfortunately, this mode has + * synchronization issues with the user land X server + * and isn't currently used. + * + * Hardware cursor support lets the hardware handle these + * details. + * + * Kernel and hardware cursor mode only work for cursors + * up to a certain size, currently 16x16 pixels. If a + * bigger cursor is set, we fallback to X cursor mode. + * + * HISTORY: + * 1.0 by Torrey T. Lyons, October 30, 2000 + * + **************************************************************/ +/* + * Copyright (c) 2001-2002 Torrey T. Lyons. 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, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/iokit/xfIOKitCursor.c,v 1.1 2003/05/14 05:27:56 torrey Exp $ */ + +#include "scrnintstr.h" +#include "cursorstr.h" +#include "mipointrst.h" +#include "micmap.h" +#define NO_CFPLUGIN +#include <IOKit/graphics/IOGraphicsLib.h> +#include <IOKit/hidsystem/IOHIDLib.h> +#include "darwin.h" +#include "xfIOKit.h" + +#define DUMP_DARWIN_CURSOR FALSE + +#define CURSOR_PRIV(pScreen) \ + ((XFIOKitCursorScreenPtr)pScreen->devPrivates[darwinCursorScreenIndex].ptr) + +// The cursors format are documented in IOFramebufferShared.h. +#define RGBto34WithGamma(red, green, blue) \ + ( 0x000F \ + | (((red) & 0xF) << 12) \ + | (((green) & 0xF) << 8) \ + | (((blue) & 0xF) << 4) ) +#define RGBto38WithGamma(red, green, blue) \ + ( 0xFF << 24 \ + | (((red) & 0xFF) << 16) \ + | (((green) & 0xFF) << 8) \ + | (((blue) & 0xFF)) ) +#define HighBitOf32 0x80000000 + +typedef struct { + Bool canHWCursor; + short cursorMode; + RecolorCursorProcPtr RecolorCursor; + InstallColormapProcPtr InstallColormap; + QueryBestSizeProcPtr QueryBestSize; + miPointerSpriteFuncPtr spriteFuncs; + ColormapPtr pInstalledMap; +} XFIOKitCursorScreenRec, *XFIOKitCursorScreenPtr; + +static int darwinCursorScreenIndex = -1; +static unsigned long darwinCursorGeneration = 0; + +/* +=========================================================================== + + Pointer sprite functions + +=========================================================================== +*/ + +/* + Realizing the Darwin hardware cursor (ie. converting from the + X representation to the IOKit representation) is complicated + by the fact that we have three different potential cursor + formats to go to, one for each bit depth (8, 15, or 24). + The IOKit formats are documented in IOFramebufferShared.h. + X cursors are represented as two pieces, a source and a mask. + The mask is a bitmap indicating which parts of the cursor are + transparent and which parts are drawn. The source is a bitmap + indicating which parts of the non-transparent portion of the the + cursor should be painted in the foreground color and which should + be painted in the background color. The bitmaps are given in + 32-bit format with least significant byte and bit first. + (This is opposite PowerPC Darwin.) +*/ + +typedef struct { + unsigned char image[CURSORWIDTH*CURSORHEIGHT]; + unsigned char mask[CURSORWIDTH*CURSORHEIGHT]; +} cursorPrivRec, *cursorPrivPtr; + +/* + * XFIOKitRealizeCursor8 + * Convert the X cursor representation to an 8-bit depth + * format for Darwin. This function assumes the maximum cursor + * width is a multiple of 8. + */ +static Bool +XFIOKitRealizeCursor8( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + cursorPrivPtr newCursor; + unsigned char *newSourceP, *newMaskP; + CARD32 *oldSourceP, *oldMaskP; + xColorItem fgColor, bgColor; + int index, x, y, rowPad; + int cursorWidth, cursorHeight; + ColormapPtr pmap; + + // check cursor size just to be sure + cursorWidth = pCursor->bits->width; + cursorHeight = pCursor->bits->height; + if (cursorHeight > CURSORHEIGHT || cursorWidth > CURSORWIDTH) + return FALSE; + + // get cursor colors in colormap + index = pScreen->myNum; + pmap = miInstalledMaps[index]; + if (!pmap) return FALSE; + + fgColor.red = pCursor->foreRed; + fgColor.green = pCursor->foreGreen; + fgColor.blue = pCursor->foreBlue; + FakeAllocColor(pmap, &fgColor); + bgColor.red = pCursor->backRed; + bgColor.green = pCursor->backGreen; + bgColor.blue = pCursor->backBlue; + FakeAllocColor(pmap, &bgColor); + FakeFreeColor(pmap, fgColor.pixel); + FakeFreeColor(pmap, bgColor.pixel); + + // allocate memory for new cursor image + newCursor = xalloc( sizeof(cursorPrivRec) ); + if (!newCursor) + return FALSE; + memset( newCursor->image, pScreen->blackPixel, CURSORWIDTH*CURSORHEIGHT ); + memset( newCursor->mask, 0, CURSORWIDTH*CURSORHEIGHT ); + + // convert to 8-bit Darwin cursor format + oldSourceP = (CARD32 *) pCursor->bits->source; + oldMaskP = (CARD32 *) pCursor->bits->mask; + newSourceP = newCursor->image; + newMaskP = newCursor->mask; + rowPad = CURSORWIDTH - cursorWidth; + + for (y = 0; y < cursorHeight; y++) { + for (x = 0; x < cursorWidth; x++) { + if (*oldSourceP & (HighBitOf32 >> x)) + *newSourceP = fgColor.pixel; + else + *newSourceP = bgColor.pixel; + if (*oldMaskP & (HighBitOf32 >> x)) + *newMaskP = 255; + else + *newSourceP = pScreen->blackPixel; + newSourceP++; newMaskP++; + } + oldSourceP++; oldMaskP++; + newSourceP += rowPad; newMaskP += rowPad; + } + + // save the result + pCursor->devPriv[pScreen->myNum] = (pointer) newCursor; + return TRUE; +} + + +/* + * XFIOKitRealizeCursor15 + * Convert the X cursor representation to an 15-bit depth + * format for Darwin. + */ +static Bool +XFIOKitRealizeCursor15( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + unsigned short *newCursor; + unsigned short fgPixel, bgPixel; + unsigned short *newSourceP; + CARD32 *oldSourceP, *oldMaskP; + int x, y, rowPad; + int cursorWidth, cursorHeight; + + // check cursor size just to be sure + cursorWidth = pCursor->bits->width; + cursorHeight = pCursor->bits->height; + if (cursorHeight > CURSORHEIGHT || cursorWidth > CURSORWIDTH) + return FALSE; + + // allocate memory for new cursor image + newCursor = xalloc( CURSORWIDTH*CURSORHEIGHT*sizeof(short) ); + if (!newCursor) + return FALSE; + memset( newCursor, 0, CURSORWIDTH*CURSORHEIGHT*sizeof(short) ); + + // calculate pixel values + fgPixel = RGBto34WithGamma( pCursor->foreRed, pCursor->foreGreen, + pCursor->foreBlue ); + bgPixel = RGBto34WithGamma( pCursor->backRed, pCursor->backGreen, + pCursor->backBlue ); + + // convert to 15-bit Darwin cursor format + oldSourceP = (CARD32 *) pCursor->bits->source; + oldMaskP = (CARD32 *) pCursor->bits->mask; + newSourceP = newCursor; + rowPad = CURSORWIDTH - cursorWidth; + + for (y = 0; y < cursorHeight; y++) { + for (x = 0; x < cursorWidth; x++) { + if (*oldMaskP & (HighBitOf32 >> x)) { + if (*oldSourceP & (HighBitOf32 >> x)) + *newSourceP = fgPixel; + else + *newSourceP = bgPixel; + } else { + *newSourceP = 0; + } + newSourceP++; + } + oldSourceP++; oldMaskP++; + newSourceP += rowPad; + } + +#if DUMP_DARWIN_CURSOR + // Write out the cursor + ErrorF("Cursor: 0x%x\n", pCursor); + ErrorF("Width = %i, Height = %i, RowPad = %i\n", cursorWidth, + cursorHeight, rowPad); + for (y = 0; y < cursorHeight; y++) { + newSourceP = newCursor + y*CURSORWIDTH; + for (x = 0; x < cursorWidth; x++) { + if (*newSourceP == fgPixel) + ErrorF("x"); + else if (*newSourceP == bgPixel) + ErrorF("o"); + else + ErrorF(" "); + newSourceP++; + } + ErrorF("\n"); + } +#endif + + // save the result + pCursor->devPriv[pScreen->myNum] = (pointer) newCursor; + return TRUE; +} + + +/* + * XFIOKitRealizeCursor24 + * Convert the X cursor representation to an 24-bit depth + * format for Darwin. This function assumes the maximum cursor + * width is a multiple of 8. + */ +static Bool +XFIOKitRealizeCursor24( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + unsigned int *newCursor; + unsigned int fgPixel, bgPixel; + unsigned int *newSourceP; + CARD32 *oldSourceP, *oldMaskP; + int x, y, rowPad; + int cursorWidth, cursorHeight; + + // check cursor size just to be sure + cursorWidth = pCursor->bits->width; + cursorHeight = pCursor->bits->height; + if (cursorHeight > CURSORHEIGHT || cursorWidth > CURSORWIDTH) + return FALSE; + + // allocate memory for new cursor image + newCursor = xalloc( CURSORWIDTH*CURSORHEIGHT*sizeof(int) ); + if (!newCursor) + return FALSE; + memset( newCursor, 0, CURSORWIDTH*CURSORHEIGHT*sizeof(int) ); + + // calculate pixel values + fgPixel = RGBto38WithGamma( pCursor->foreRed, pCursor->foreGreen, + pCursor->foreBlue ); + bgPixel = RGBto38WithGamma( pCursor->backRed, pCursor->backGreen, + pCursor->backBlue ); + + // convert to 24-bit Darwin cursor format + oldSourceP = (CARD32 *) pCursor->bits->source; + oldMaskP = (CARD32 *) pCursor->bits->mask; + newSourceP = newCursor; + rowPad = CURSORWIDTH - cursorWidth; + + for (y = 0; y < cursorHeight; y++) { + for (x = 0; x < cursorWidth; x++) { + if (*oldMaskP & (HighBitOf32 >> x)) { + if (*oldSourceP & (HighBitOf32 >> x)) + *newSourceP = fgPixel; + else + *newSourceP = bgPixel; + } else { + *newSourceP = 0; + } + newSourceP++; + } + oldSourceP++; oldMaskP++; + newSourceP += rowPad; + } + +#if DUMP_DARWIN_CURSOR + // Write out the cursor + ErrorF("Cursor: 0x%x\n", pCursor); + ErrorF("Width = %i, Height = %i, RowPad = %i\n", cursorWidth, + cursorHeight, rowPad); + for (y = 0; y < cursorHeight; y++) { + newSourceP = newCursor + y*CURSORWIDTH; + for (x = 0; x < cursorWidth; x++) { + if (*newSourceP == fgPixel) + ErrorF("x"); + else if (*newSourceP == bgPixel) + ErrorF("o"); + else + ErrorF(" "); + newSourceP++; + } + ErrorF("\n"); + } +#endif + + // save the result + pCursor->devPriv[pScreen->myNum] = (pointer) newCursor; + return TRUE; +} + + +/* + * XFIOKitRealizeCursor + * + */ +static Bool +XFIOKitRealizeCursor( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + Bool result; + XFIOKitCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); + DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); + + if ((pCursor->bits->height > CURSORHEIGHT) || + (pCursor->bits->width > CURSORWIDTH) || + // FIXME: this condition is not needed after kernel cursor works + !ScreenPriv->canHWCursor) { + result = (*ScreenPriv->spriteFuncs->RealizeCursor)(pScreen, pCursor); + } else if (dfb->bitsPerPixel == 8) { + result = XFIOKitRealizeCursor8(pScreen, pCursor); + } else if (dfb->bitsPerPixel == 16) { + result = XFIOKitRealizeCursor15(pScreen, pCursor); + } else { + result = XFIOKitRealizeCursor24(pScreen, pCursor); + } + + return result; +} + + +/* + * XFIOKitUnrealizeCursor + * + */ +static Bool +XFIOKitUnrealizeCursor( + ScreenPtr pScreen, + CursorPtr pCursor) +{ + Bool result; + XFIOKitCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); + + if ((pCursor->bits->height > CURSORHEIGHT) || + (pCursor->bits->width > CURSORWIDTH) || + // FIXME: this condition is not needed after kernel cursor works + !ScreenPriv->canHWCursor) { + result = (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pScreen, pCursor); + } else { + xfree( pCursor->devPriv[pScreen->myNum] ); + result = TRUE; + } + + return result; +} + + +/* + * XFIOKitSetCursor + * Set the cursor sprite and position + * Use hardware cursor if possible + */ +static void +XFIOKitSetCursor( + ScreenPtr pScreen, + CursorPtr pCursor, + int x, + int y) +{ + kern_return_t kr; + DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); + XFIOKitScreenPtr iokitScreen = XFIOKIT_SCREEN_PRIV(pScreen); + StdFBShmem_t *cshmem = iokitScreen->cursorShmem; + XFIOKitCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); + + // are we supposed to remove the cursor? + if (!pCursor) { + if (ScreenPriv->cursorMode == 0) + (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, 0, x, y); + else { + if (!cshmem->cursorShow) { + cshmem->cursorShow++; + if (cshmem->hardwareCursorActive) { + kr = IOFBSetCursorVisible(iokitScreen->fbService, FALSE); + kern_assert( kr ); + } + } + } + return; + } + + // can we use the kernel or hardware cursor? + if ((pCursor->bits->height <= CURSORHEIGHT) && + (pCursor->bits->width <= CURSORWIDTH) && + // FIXME: condition not needed when kernel cursor works + ScreenPriv->canHWCursor) { + + if (ScreenPriv->cursorMode == 0) // remove the X cursor + (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, 0, x, y); + ScreenPriv->cursorMode = 1; // kernel cursor + + // change the cursor image in shared memory + if (dfb->bitsPerPixel == 8) { + cursorPrivPtr newCursor = + (cursorPrivPtr) pCursor->devPriv[pScreen->myNum]; + memcpy(cshmem->cursor.bw8.image[0], newCursor->image, + CURSORWIDTH*CURSORHEIGHT); + memcpy(cshmem->cursor.bw8.mask[0], newCursor->mask, + CURSORWIDTH*CURSORHEIGHT); + } else if (dfb->bitsPerPixel == 16) { + unsigned short *newCursor = + (unsigned short *) pCursor->devPriv[pScreen->myNum]; + memcpy(cshmem->cursor.rgb.image[0], newCursor, + 2*CURSORWIDTH*CURSORHEIGHT); + } else { + unsigned int *newCursor = + (unsigned int *) pCursor->devPriv[pScreen->myNum]; + memcpy(cshmem->cursor.rgb24.image[0], newCursor, + 4*CURSORWIDTH*CURSORHEIGHT); + } + + // FIXME: We always use a full size cursor, even if the image + // is smaller because I couldn't get the padding to come out + // right otherwise. + cshmem->cursorSize[0].width = CURSORWIDTH; + cshmem->cursorSize[0].height = CURSORHEIGHT; + cshmem->hotSpot[0].x = pCursor->bits->xhot; + cshmem->hotSpot[0].y = pCursor->bits->yhot; + + // try to use a hardware cursor + if (ScreenPriv->canHWCursor) { + kr = IOFBSetNewCursor(iokitScreen->fbService, 0, 0, 0); + // FIXME: this is a fatal error without the kernel cursor + kern_assert( kr ); +#if 0 + if (kr != KERN_SUCCESS) { + ErrorF("Could not set new cursor with kernel return 0x%x.\n", kr); + ScreenPriv->canHWCursor = FALSE; + } +#endif + } + + // make the new cursor visible + if (cshmem->cursorShow) + cshmem->cursorShow--; + + if (!cshmem->cursorShow && ScreenPriv->canHWCursor) { + kr = IOFBSetCursorVisible(iokitScreen->fbService, TRUE); + // FIXME: this is a fatal error without the kernel cursor + kern_assert( kr ); +#if 0 + if (kr != KERN_SUCCESS) { + ErrorF("Couldn't set hardware cursor visible with kernel return 0x%x.\n", kr); + ScreenPriv->canHWCursor = FALSE; + } else +#endif + ScreenPriv->cursorMode = 2; // hardware cursor + } + + return; + } + + // otherwise we use a software cursor + if (ScreenPriv->cursorMode) { + /* remove the kernel or hardware cursor */ + XFIOKitSetCursor(pScreen, 0, x, y); + } + + ScreenPriv->cursorMode = 0; + (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, pCursor, x, y); +} + + +/* + * XFIOKitMoveCursor + * Move the cursor. This is a noop for a kernel or hardware cursor. + */ +static void +XFIOKitMoveCursor( + ScreenPtr pScreen, + int x, + int y) +{ + XFIOKitCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); + + // only the X cursor needs to be explicitly moved + if (!ScreenPriv->cursorMode) + (*ScreenPriv->spriteFuncs->MoveCursor)(pScreen, x, y); +} + +static miPointerSpriteFuncRec darwinSpriteFuncsRec = { + XFIOKitRealizeCursor, + XFIOKitUnrealizeCursor, + XFIOKitSetCursor, + XFIOKitMoveCursor +}; + + +/* +=========================================================================== + + Pointer screen functions + +=========================================================================== +*/ + +/* + * XFIOKitCursorOffScreen + */ +static Bool XFIOKitCursorOffScreen(ScreenPtr *pScreen, int *x, int *y) +{ return FALSE; +} + + +/* + * XFIOKitCrossScreen + */ +static void XFIOKitCrossScreen(ScreenPtr pScreen, Bool entering) +{ return; +} + + +/* + * XFIOKitWarpCursor + * Change the cursor position without generating an event or motion history + */ +static void +XFIOKitWarpCursor( + ScreenPtr pScreen, + int x, + int y) +{ + kern_return_t kr; + + kr = IOHIDSetMouseLocation( xfIOKitInputConnect, x, y ); + if (kr != KERN_SUCCESS) { + ErrorF("Could not set cursor position with kernel return 0x%x.\n", kr); + } + miPointerWarpCursor(pScreen, x, y); +} + +static miPointerScreenFuncRec darwinScreenFuncsRec = { + XFIOKitCursorOffScreen, + XFIOKitCrossScreen, + XFIOKitWarpCursor, + DarwinEQPointerPost, + DarwinEQSwitchScreen +}; + + +/* +=========================================================================== + + Other screen functions + +=========================================================================== +*/ + +/* + * XFIOKitCursorQueryBestSize + * Handle queries for best cursor size + */ +static void +XFIOKitCursorQueryBestSize( + int class, + unsigned short *width, + unsigned short *height, + ScreenPtr pScreen) +{ + XFIOKitCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); + + if (class == CursorShape) { + *width = CURSORWIDTH; + *height = CURSORHEIGHT; + } else + (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); +} + + +/* + * XFIOKitInitCursor + * Initialize cursor support + */ +Bool +XFIOKitInitCursor( + ScreenPtr pScreen) +{ + XFIOKitScreenPtr iokitScreen = XFIOKIT_SCREEN_PRIV(pScreen); + XFIOKitCursorScreenPtr ScreenPriv; + miPointerScreenPtr PointPriv; + kern_return_t kr; + + // start with no cursor displayed + if (!iokitScreen->cursorShmem->cursorShow++) { + if (iokitScreen->cursorShmem->hardwareCursorActive) { + kr = IOFBSetCursorVisible(iokitScreen->fbService, FALSE); + kern_assert( kr ); + } + } + + // initialize software cursor handling (always needed as backup) + if (!miDCInitialize(pScreen, &darwinScreenFuncsRec)) { + return FALSE; + } + + // allocate private storage for this screen's hardware cursor info + if (darwinCursorGeneration != serverGeneration) { + if ((darwinCursorScreenIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + darwinCursorGeneration = serverGeneration; + } + + ScreenPriv = xcalloc( 1, sizeof(XFIOKitCursorScreenRec) ); + if (!ScreenPriv) return FALSE; + + pScreen->devPrivates[darwinCursorScreenIndex].ptr = (pointer) ScreenPriv; + + // check if a hardware cursor is supported + if (!iokitScreen->cursorShmem->hardwareCursorCapable) { + ScreenPriv->canHWCursor = FALSE; + ErrorF("Hardware cursor not supported.\n"); + } else { + // we need to make sure that the hardware cursor really works + ScreenPriv->canHWCursor = TRUE; + kr = IOFBSetNewCursor(iokitScreen->fbService, 0, 0, 0); + if (kr != KERN_SUCCESS) { + ErrorF("Could not set hardware cursor with kernel return 0x%x.\n", kr); + ScreenPriv->canHWCursor = FALSE; + } + kr = IOFBSetCursorVisible(iokitScreen->fbService, TRUE); + if (kr != KERN_SUCCESS) { + ErrorF("Couldn't set hardware cursor visible with kernel return 0x%x.\n", kr); + ScreenPriv->canHWCursor = FALSE; + } + IOFBSetCursorVisible(iokitScreen->fbService, FALSE); + } + + ScreenPriv->cursorMode = 0; + ScreenPriv->pInstalledMap = NULL; + + // override some screen procedures + ScreenPriv->QueryBestSize = pScreen->QueryBestSize; + pScreen->QueryBestSize = XFIOKitCursorQueryBestSize; +// ScreenPriv->ConstrainCursor = pScreen->ConstrainCursor; +// pScreen->ConstrainCursor = XFIOKitConstrainCursor; + + // initialize hardware cursor handling + PointPriv = (miPointerScreenPtr) + pScreen->devPrivates[miPointerScreenIndex].ptr; + + ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; + PointPriv->spriteFuncs = &darwinSpriteFuncsRec; + + /* Other routines that might be overridden */ +/* + CursorLimitsProcPtr CursorLimits; + RecolorCursorProcPtr RecolorCursor; +*/ + + return TRUE; +} diff --git a/hw/darwin/iokit/xfIOKitStartup.c b/hw/darwin/iokit/xfIOKitStartup.c new file mode 100644 index 000000000..9d25c69fe --- /dev/null +++ b/hw/darwin/iokit/xfIOKitStartup.c @@ -0,0 +1,115 @@ +/************************************************************** + * + * Startup code for the IOKit Darwin X Server + * + **************************************************************/ +/* + * Copyright (c) 2001-2003 Torrey T. Lyons. 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, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/iokit/xfIOKitStartup.c,v 1.2 2003/11/01 08:13:08 torrey Exp $ */ + +#include "darwin.h" +#include "darwinKeyboard.h" +#include "micmap.h" + +void GlxExtensionInit(void); +void GlxWrapInitVisuals(miInitVisualsProcPtr *procPtr); + + +/* + * DarwinHandleGUI + * This function is called first from main(). + * It does nothing for the IOKit X server. + */ +void DarwinHandleGUI( + int argc, + char *argv[], + char *envp[] ) +{ +} + + +/* + * DarwinGlxExtensionInit + * Initialize the GLX extension. + * Mesa is linked into the IOKit mode X server so we just call directly. + */ +void DarwinGlxExtensionInit(void) +{ + GlxExtensionInit(); +} + + +/* + * DarwinGlxWrapInitVisuals + */ +void DarwinGlxWrapInitVisuals( + miInitVisualsProcPtr *procPtr) +{ + GlxWrapInitVisuals(procPtr); +} + + +/* + * DarwinModeProcessArgument + * Process IOKit specific command line arguments. + */ +int DarwinModeProcessArgument( + int argc, + char *argv[], + int i) +{ +#ifdef DARWIN_WITH_QUARTZ + // XDarwinStartup uses these arguments to indicate which X server + // should be started. Ignore them here. + if (!strcmp( argv[i], "-fullscreen" ) || + !strcmp( argv[i], "-rootless" ) || + !strcmp( argv[i], "-quartz" )) + { + return 1; + } +#else + if (!strcmp( argv[i], "-fullscreen" ) || + !strcmp( argv[i], "-rootless" ) || + !strcmp( argv[i], "-quartz" )) + { + FatalError("Command line option %s is not available without Quartz " + "support.\n", argv[i]); + } +#endif + + return 0; +} + + +/* + * DarwinModeReadSystemKeymap + * IOKit has no alternative to NXKeyMapping API. + */ +Bool DarwinModeReadSystemKeymap( + darwinKeyboardInfo *info) +{ + return FALSE; +} |