CA Department of Corrections, 7th & Folsom

Tags: ,
Current Music: Front 242 -- Loud ♬

dear XCopyArea, please stop exploring your frame buffer, it freaks me out.

Dear Lazyweb,

Here's today's unanswerable Mac programming question:

When I'm copying bits from an image to a window, Shark seems to show that I'm spending more than half of my time doing colorspace conversions:

    29.9%   CGContextDrawImage
    29.9%     CGContextDelegateDrawImage
    29.7%     ripc_DrawImage
    20.6%       ripc_AcquireImage
    20.0%         CGSImageDataLockWithReference
    19.8%           img_data_lock
    16.5%             img_colormatch_read
    14.6%               CGColorTransformConvertData
    14.4%                 CWMatchBitmap

My understanding is that this should only happen if my image and context did not have the same colorspace; if the colorspaces were already the same, then this should turn into basically a memmove(), which is what I want. (And what X11.app appears to accomplish somehow.)

In the case I'm looking at, I'm trying to copy a rectangle from a window, back onto itself, without scaling. Say, 50x50@10,10 to 50x50@200,200. I'm getting the bits off of the window with:

    NSBitmapImageRep *bm = [NSBitmapImageRep alloc];
    [bm initWithFocusedViewRect:rect];
    CGDataProviderRef prov = CGDataProviderCreateWithData (...);
    CGImageRef cgi = CGImageCreate (...);

The colorspace I'm using when creating that image is the default one of this window's CGDirectDisplayID, so it should match:

    CMGetProfileByAVID ((CMDisplayIDType) cgdpy, &profile);
    colorspace = CGColorSpaceCreateWithPlatformColorSpace (profile);

Then I draw the bits back onto the window with CGContextDrawImage(). CGImageGetColorSpace() says the image I'm drawing has the color space I expect. So how do I tell why I'm getting a colorspace mismatch?

I also hate that this process involves copying the image data at least twice, but I don't see any way around that. But the main problem here seems to be that not only is it copying it, it's bit-twiddling it too.

Reading the bits off the window is also slow, but according to Shark, it doesn't seem to be calling any obvious "convert" routines; looks like it spends all of its time directly inside of _NSReadImage:

    30.1%   -[NSBitmapImageRep initWithFocusedViewRect:]
    28.5%     _NSReadImage
     3.4%       _NSImageRealloc
     0.4%       CGSLockWindowRectBits
     0.4%       _NSImageMalloc
     0.4%       CGSUnlockWindowBits
     1.3%     -[NSBitmapImageRep initWithBitmapDataPlanes:...]

The thing is, I'm just implementing the X11 routine XCopyArea() here. When running an actual X11 program against Apple's X11.app, XCopyArea() is fast, so I know that it's possible to move bits around in the frame buffer fast, in a 2D-graphics context. I just can't see how. I'm guessing that the real X11 server is not going in via NSBitmapImageRep and CGContextDrawImage(), but I have yet to find any lower level API that will give me more direct access to an NSView's backing store.

Tags: , , , ,