Dali Clock again

More Dali Clock: source and this time two binaries, one using the straightforward Aqua way of rendering, and the other using the lower level Quartz way, which I thought would be faster, but as far as I can tell, it's not. In fact, I think it's slower. Certainly it's flakier and a lot more complicated... Check out "#ifdef BE_QUARTZY" in DaliClockView.m for the difference.

All I'm able to understand from Shark is, "yup, spending all your time pushing bits to the screen." Shark seems to suggest that the Quartz way is faster, but Top disagrees. Grumble.

Is there an Aqua way to draw a 1bpp bitmap with a given fg/bg, besides dropping all the way down to CGContextFillRect? Because (as you can see in drawRect) that's a fuckin' pain in the ass when you're dealing with foreground and background colors that can have different amounts of transparency (e.g., making it continue to work when the numbers are a "hole" in the window.)

Tags: , , ,

5 Responses:

  1. jchos says:

    It will be faster to cache all of the individual numeral bitmaps into NSImages and then render the NSImages into the View. This will give the system a chance to convert the images into a native format and possibly keep them in video memory.

    • jwz says:

      In the original X version, I had a giant cache of (server-side) images in order to make it able to run over a 14.4kbps X11 dialup connection (I had an X terminal at home, all apps ran remotely, it was back when dinosaurs ruled the earth.) Anyway, two problems with that: first, cacheing all possible transitions would be 10×10! = 36,288,000 images (and they all get used, when you click to display the date) so instead you just cache the common ones (0-9 increasing, 2-0, 5-0) and do it the hard way for the others. But, the second problem here is the color cycling, which as far as I can tell, I can only accomplish by re-encoding each bitmap to a pixmap, which is where almost all of the time is being spent right now. So even with a cache of the 1bpp images, we're back to square one.

      That was kind of long-winded, but my point is that I think the real problem that I need to solve is "get a 1bpp image onto the screen fast". I don't think caches of full-color images solve that for me.

  2. clamu says:

    I found one very minor bug in the prefs.

    When first viewing the prefs dialog the countdown timer field defaults to the current time. This field seems to require the time in 24hr format - but if the time is displayed in 12hr format, then it will grab the 12hr version of the time, so 6pm becomes 6am for example.

  3. alierak says:

    I vaguely recall from a WWDC presentation that Aqua rendering runs in higher-priority threads to make the UI responsive. The more of your rendering work you do in normal threads, the slower it will probably appear.

  4. jchos says:

    This is one way to draw the 1bpp image without invoking CG or colorize. On 10.3, this very slow, but perhaps it is faster on 10.4.

    NSBitmapImageRep *imgrep = [NSBitmapImageRep alloc];

    char *planes[] = {config.bitmap, config.bitmap};


    if (! imgrep) abort();

    [img setSize:[imgrep size]];

    [img setScalesWhenResized:NO];

    [[self window] setBackgroundColor:bg];

    [img addRepresentation:imgrep];

    NSImage *tmpimage = [[[NSImage alloc] initWithSize:fromrect.size] autorelease];

    [tmpimage lockFocus];

    [fg setFill];

    [NSBezierPath fillRect:fromrect];

    [img drawInRect:fromrect

    [tmpimage unlockFocus];

    [tmpimage drawInRect:torect

    [img removeRepresentation:imgrep];

    [imgrep release];