IOAccelSurfaceControl.c   [plain text]


/*
 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */

#include <CoreFoundation/CoreFoundation.h>

#include <IOKit/IOKitLib.h>
#include <IOKit/graphics/IOAccelSurfaceControl.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <stdlib.h>


#define arrayCnt(var) (sizeof(var)/sizeof(var[0]))
#define regionSize(rgn) ((size_t) IOACCEL_SIZEOF_DEVICE_REGION(rgn))

IOReturn IOAccelFindAccelerator( io_service_t framebuffer,
                                io_service_t * pAccelerator, UInt32 * pFramebufferIndex )
{
    IOReturn      kr;
    io_service_t  accelerator = MACH_PORT_NULL;

    mach_port_t     	   masterPort;
    CFMutableDictionaryRef props = 0;
    CFStringRef            cfStr;
    CFNumberRef            cfNum;
    const char *           cStr;
    char *	           buffer = NULL;

    *pAccelerator = MACH_PORT_NULL;
    *pFramebufferIndex = 0;

    do {

        IOMasterPort(MACH_PORT_NULL, &masterPort);

        kr = IORegistryEntryCreateCFProperties( framebuffer, &props,
                                                kCFAllocatorDefault, kNilOptions);
        if( kr != kIOReturnSuccess)
            continue;
        kr = kIOReturnError;
        cfStr = CFDictionaryGetValue( props, CFSTR(kIOAccelTypesKey) );
        if( !cfStr)
            continue;

        cStr = CFStringGetCStringPtr( cfStr, kCFStringEncodingMacRoman);
        if( !cStr) {
            CFIndex bufferSize = CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfStr),
            	    kCFStringEncodingMacRoman) + sizeof('\0');
            buffer = malloc( bufferSize);
            if( buffer && CFStringGetCString( cfStr, buffer, bufferSize, kCFStringEncodingMacRoman))
                cStr = buffer;
        }
        if( !cStr)
            continue;

        accelerator = IORegistryEntryFromPath( masterPort, cStr );
        if( !accelerator)
            continue;
        if( !IOObjectConformsTo( accelerator, kIOAcceleratorClassName )) {
            IOObjectRelease( accelerator );
            accelerator = MACH_PORT_NULL;
            continue;
        }

        cfNum = CFDictionaryGetValue( props, CFSTR(kIOAccelIndexKey) );
        if( cfNum) 
            CFNumberGetValue( cfNum, kCFNumberSInt32Type, pFramebufferIndex );

        kr = kIOReturnSuccess;

    } while( false );

    if( buffer)
        free( buffer);
    if( props)
        CFRelease( props);

    *pAccelerator = accelerator;

    return( kr );
}

static io_connect_t idConnect;
enum { kAlloc, kFree };

IOReturn IOAccelCreateAccelID(IOOptionBits options, IOAccelID * identifier)
{
    IOReturn err;

    if (!idConnect)
    {
	io_service_t
	service = IORegistryEntryFromPath(kIOMasterPortDefault, 
					kIOServicePlane ":/IOResources/IODisplayWrangler");
	if (service) 
	{
	    err = IOServiceOpen(service, mach_task_self(), 0, &idConnect);
	    IOObjectRelease(service);
	}
    }

    if (!idConnect)
	return (kIOReturnNotReady);

    uint64_t inData[] = { options, *identifier };
    uint64_t outData;
    uint32_t outLen = 1;
    err = IOConnectCallScalarMethod(idConnect, kAlloc,
			         inData,   arrayCnt(inData),
			        &outData,  &outLen);
    *identifier = (IOAccelID) outData;

    return (err);
}

IOReturn IOAccelDestroyAccelID(IOOptionBits options, IOAccelID identifier)
{
    IOReturn err;

    if (!idConnect)
	return (kIOReturnNotReady);

    uint64_t inData[] = { options, identifier };
    err = IOConnectCallScalarMethod(idConnect, kFree,
			         inData, arrayCnt(inData), NULL, NULL);

    return (err);
}

IOReturn IOAccelCreateSurface( io_service_t accelerator, UInt32 wID, eIOAccelSurfaceModeBits modebits,
                                IOAccelConnect *connect )
{
	IOReturn	kr;
	io_connect_t	window = MACH_PORT_NULL;

	*connect = NULL;

        /* Create a context */
        kr = IOServiceOpen( accelerator,
                    mach_task_self(),
                    kIOAccelSurfaceClientType,
                    &window );

        if( kr != kIOReturnSuccess)
        {
		return kr;
        }

	/* Set the window id */
	uint64_t data[] = { wID, modebits };
	kr = IOConnectCallScalarMethod(window, kIOAccelSurfaceSetIDMode,
				   data, arrayCnt(data), NULL, NULL);
	if(kr != kIOReturnSuccess)
	{
		IOServiceClose(window);
		return kr;
	}

	*connect = (IOAccelConnect) (uintptr_t) window;

	return kIOReturnSuccess;
}

IOReturn IOAccelDestroySurface( IOAccelConnect connect )
{
	IOReturn kr;

	if(!connect)
		return kIOReturnError;

	kr = IOServiceClose((io_connect_t) (uintptr_t) connect);

	return kr;
}


IOReturn IOAccelSetSurfaceScale( IOAccelConnect connect, IOOptionBits options,
                                    IOAccelSurfaceScaling * scaling, UInt32 scalingSize )
{
	uint64_t inData = options;
	IOReturn result;

	
	result = IOConnectCallMethod((io_connect_t) (uintptr_t) connect, 
				kIOAccelSurfaceSetScale,
				&inData, 1, 
				scaling, (size_t) scalingSize,
			    NULL, NULL, NULL, NULL); // no output

	return result;
}


IOReturn IOAccelSetSurfaceFramebufferShape( IOAccelConnect connect, IOAccelDeviceRegion *rgn,
                                            eIOAccelSurfaceShapeBits options, UInt32 framebufferIndex )
{
	uint64_t inData[] = { options, framebufferIndex };
	IOReturn result;
	size_t   rgnSize = regionSize(rgn);
		
	result = IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceSetShape,
			        inData, arrayCnt(inData), rgn, rgnSize,
			        NULL, NULL, NULL, NULL); // no output
	return result;
}

IOReturn IOAccelSetSurfaceFramebufferShapeWithBacking( IOAccelConnect connect, IOAccelDeviceRegion *rgn,
                                            eIOAccelSurfaceShapeBits options, UInt32 framebufferIndex,
					    IOVirtualAddress backing, UInt32 rowbytes )
{
        IOReturn err;

        err = IOAccelSetSurfaceFramebufferShapeWithBackingAndLength(connect, rgn, options, 
			framebufferIndex, backing, rowbytes, rgn->bounds.h * rowbytes);

	return (err);
}

IOReturn IOAccelSetSurfaceFramebufferShapeWithBackingAndLength( IOAccelConnect connect, IOAccelDeviceRegion *rgn,
                                            eIOAccelSurfaceShapeBits options, UInt32 framebufferIndex,
					    IOVirtualAddress backing, UInt32 rowbytes, UInt32 backingLength )
{
    IOReturn err;
    uint64_t inData[] =
		{ options, framebufferIndex, backing, rowbytes, backingLength };
    size_t   rgnSize = regionSize(rgn);


    err =  IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceSetShapeBackingAndLength,
	    inData, arrayCnt(inData), rgn, rgnSize,
	    NULL, NULL, NULL, NULL); // no output
	
	return (err);
}

IOReturn IOAccelSurfaceControl( IOAccelConnect connect,
                                    UInt32 selector, UInt32 arg, UInt32 * result) 
{
	uint64_t inData[] = { selector, arg };
	uint64_t outData;
	uint32_t outSize = 1;

	IOReturn err =  IOConnectCallScalarMethod((io_connect_t) (uintptr_t)connect, kIOAccelSurfaceControl,
		inData, arrayCnt(inData), &outData, &outSize);
	*result = (UInt32) outData;
    
        return( err );
}

IOReturn IOAccelReadLockSurface( IOAccelConnect connect, IOAccelSurfaceInformation * info, UInt32 infoSize )
{
	size_t size = (size_t) infoSize;
	IOReturn ret =  IOConnectCallStructMethod((io_connect_t) (uintptr_t)connect, kIOAccelSurfaceReadLock,
					      NULL, 0, info, &size);


	return ret;
}

IOReturn IOAccelReadLockSurfaceWithOptions( IOAccelConnect connect, IOOptionBits options,
					    IOAccelSurfaceInformation * info, UInt32 infoSize )
{
	uint64_t inData = options;
	size_t size = (size_t) infoSize;
	IOReturn ret =  IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceReadLockOptions,
				        &inData, 1,		// in scalar
				        NULL,    0,		// in struct
				        NULL,    NULL,		// out scalar
				        info,    &size);	// out struct


	return ret;
}

IOReturn IOAccelWriteLockSurface( IOAccelConnect connect, IOAccelSurfaceInformation * info, UInt32 infoSize )
{
	size_t size = (size_t) infoSize;
	IOReturn ret =  IOConnectCallStructMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceWriteLock,
					      NULL, 0, info, &size);

	return ret;
}

IOReturn IOAccelWriteLockSurfaceWithOptions( IOAccelConnect connect, IOOptionBits options,
					     IOAccelSurfaceInformation * info, UInt32 infoSize )
{
	uint64_t inData = options;
	size_t size = (size_t) infoSize;
	IOReturn ret =  IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceWriteLockOptions,
				        &inData, 1,		// in scalar
				        NULL,    0,		// in struct
				        NULL,    NULL,		// out scalar
				        info,    &size);	// out struct

	return ret;
}

IOReturn IOAccelReadUnlockSurface( IOAccelConnect connect )
{
	return IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceReadUnlock,
			       NULL, 0,    NULL, 0,	// input
			       NULL, NULL, NULL, NULL);	// output
}

IOReturn IOAccelReadUnlockSurfaceWithOptions( IOAccelConnect connect, IOOptionBits options )
{
	uint64_t inData = options;
	return IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceReadUnlockOptions,
			       &inData, 1, NULL, 0,	// input
			       NULL, NULL, NULL, NULL);	// output
}

IOReturn IOAccelWriteUnlockSurface( IOAccelConnect connect )
{
	return IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceWriteUnlock,
			       NULL, 0,    NULL, 0,	// input
			       NULL, NULL, NULL, NULL);	// output
}

IOReturn IOAccelWriteUnlockSurfaceWithOptions( IOAccelConnect connect, IOOptionBits options )
{
	uint64_t inData = options;
	return IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceWriteUnlockOptions,
			       &inData, 1, NULL, 0,	// input
			       NULL, NULL, NULL, NULL);	// output
}

IOReturn IOAccelWaitForSurface( IOAccelConnect connect __unused )
{
	return kIOReturnSuccess;
}

IOReturn IOAccelQueryLockSurface( IOAccelConnect connect )
{
	return IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceQueryLock,
			       NULL, 0,    NULL, 0,	// input
			       NULL, NULL, NULL, NULL);	// output
}

/* Flush surface to visible region */
IOReturn IOAccelFlushSurfaceOnFramebuffers( IOAccelConnect connect, IOOptionBits options, UInt32 framebufferMask )
{
	uint64_t inData[] = { framebufferMask, options };
	return IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceFlush,
			       inData, arrayCnt(inData), NULL, 0,// input
				NULL, NULL, NULL, NULL);	 // output
}

IOReturn IOAccelReadSurface( IOAccelConnect connect, IOAccelSurfaceReadData * parameters )
{
	IOReturn result;
	

	result = IOConnectCallMethod((io_connect_t) (uintptr_t) connect, kIOAccelSurfaceRead,
	       NULL, 0, parameters, sizeof( IOAccelSurfaceReadData), // input
	       NULL, NULL, NULL, NULL); // no output

	return result;
}