summaryrefslogtreecommitdiff
path: root/hw/darwin/iokit
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-25 19:29:01 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-25 19:29:01 +0000
commit90f1536dd315cd265bfc7ef35058761a65a01734 (patch)
treece1f7aed9444ad2577d62a6e5a2dd36008771c6c /hw/darwin/iokit
parentd461855a73d8c9f51a18673aef7ce88f94a71629 (diff)
Initial revisionXORG-STABLE
Diffstat (limited to 'hw/darwin/iokit')
-rw-r--r--hw/darwin/iokit/xfIOKit.c770
-rw-r--r--hw/darwin/iokit/xfIOKit.h57
-rw-r--r--hw/darwin/iokit/xfIOKitCursor.c735
-rw-r--r--hw/darwin/iokit/xfIOKitStartup.c115
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;
+}