That's very ingenious. Not an OSX expert myself but it does bother me that 
you're not drawing into the context you are given but one you construct 
yourself from a piece of the window. That's not something I think iOS would 
even let you get at. 

For a start does that work layer backed? 

Is there always a guaranteed correspondence between the context passed to 
drawrect and the window like that? Does OSX never choose to render to a bitmap 
and then blend to the window store later? 

That might be another way, by the way, render to your own tiled small bitmaps 
on background threads then blit them into the real context. 

Perhaps that code is fine on OSX, I'd certainly be happier if there was a 
create context from context call you could use to relate your small contexts to 
the draw rect one. That code would keep me up nights. 

> On 6 Dec, 2013, at 18:26, Graham Cox <graham....@bigpond.com> wrote:
> 
> 
>> On 4 Dec 2013, at 9:33 pm, Graham Cox <graham....@bigpond.com> wrote:
>> 
>> But that leaves those annoying cases when you have the whole view to redraw. 
>> I wondered if it would be worth dividing up the view into rects and 
>> rendering each one on a separate thread. The problem seems to me to be that 
>> they’d all be drawing into the same CGContext, and I wonder how well that 
>> could work - e.g. one thread could set a clip ready for its next drawing 
>> operation and another could then change that clip so they’d all be tripping 
>> over each other, even though they were all drawing into a different part of 
>> the context. If access to the context were synchronised, then that would end 
>> up serialising all the drawing so there wouldn’t be any gain.
>> 
>> Has anyone trod this path? It would be useful to know whether there’s 
>> anything that can be done along these lines, because rendering 10,000 or 
>> more objects is just taking too darn long!
> 
> 
> OK, after some thought and a bit of experimentation, I think I’ve got a 
> handle on this. I just thought I’d share with the list in case anyone is 
> remotely interested, or has anything to suggest/add/criticise…
> 
> Obviously, you cannot share a graphics context across multiple threads for 
> the reasons I mentioned - a single context cannot be thread safe, by design. 
> But that doesn’t mean you can’t have a separate context per thread, all 
> drawing into the same backing store. That was my breakthrough insight I 
> guess, for what it’s worth.
> 
> So proceeding on that basis, I wrote a test view that uses a NSOperationQueue 
> to dispatch chunks of drawing work by dividing up the view into tiles, 
> creating a context for each tile (but all drawing into the same window 
> backing store). As long as you wait for the tiles to all finish, everything 
> works just tickety-boo.
> 
> Here’s the code, which is the -drawRect: method of a view. The view creates 
> an NSOperationQueue called mDrawingQueue in its -initWithFrame: method.
> 
> #define        TILE_SIZE        NSMakeSize( 100, 100 )
> #define        DRAW_THREADED    1
> 
> 
> - (void)        drawRect:(NSRect) dirtyRect
> {
>    [[NSColor whiteColor] set];
>    NSRectFill( dirtyRect );
>    
>    // get current context:
>    
>    CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
>    
>    // divide into tiles
>    
>    NSSize    tileSize = TILE_SIZE;
>    NSRect    br = self.bounds;
>    NSUInteger    tx, ty;
>    
>    tx = ceil(NSWidth( br ) / tileSize.width);
>    ty = ceil(NSHeight( br ) / tileSize.height);
>    
>    NSRect tileRect;
>    
>    tileRect.size = tileSize;
>    
>    for( NSInteger i = 0; i < ty; ++i )
>    {
>        for( NSInteger j = 0; j < tx; ++j )
>        {
>            tileRect.origin.x = br.origin.x + tileSize.width * j;
>            tileRect.origin.y = br.origin.y + tileSize.height * i;
>            
>            if([self needsToDrawRect:tileRect])
>            {
> #if DRAW_THREADED
>                NSBlockOperation* op = [NSBlockOperation 
> blockOperationWithBlock:^
>                {
>                    NSGraphicsContext* context = [NSGraphicsContext 
> graphicsContextWithWindow:[self window]];
>                    CGContextRef    ncx = [context graphicsPort];
>                    
>                    // align and clip this new context to the view
> 
>                    CGAffineTransform ctm = CGContextGetCTM( ctx );
>                    
>                    CGContextConcatCTM( ncx, ctm );
>                    CGContextClipToRect( ncx, br );
> 
>                    // also clip to the tile (not strictly necessary)
> 
>                    CGContextClipToRect( ncx, tileRect );
> 
>                    [self drawTile:tileRect inContext:ncx];
>                }];
>                
>                [mDrawingQueue addOperation:op];
> #else
>                [self drawTile:tileRect inContext:ctx];
> #endif
>        
>            }
>        }
>    }
>    
> #if DRAW_THREADED
>    // need to wait until tiles all drawn before flushing
>    [mDrawingQueue waitUntilAllOperationsAreFinished];
> #endif
> }
> 
> 
> 
> - (void)        drawTile:(NSRect) tile inContext:(CGContextRef) ctx
> {
>    // draw something in the tile. Not very challenging at the moment
> 
>    NSRect tr = NSInsetRect( tile, 10, 10 );
>    
>    CGContextSetFillColorWithColor( ctx, [[NSColor redColor] CGColor]);
>    CGContextFillRect( ctx, tr );
>    
>    CGContextSetStrokeColorWithColor(ctx, CGColorGetConstantColor( 
> kCGColorBlack ));
>    CGContextStrokeRect( ctx, tile );
> }
> 
> 
> _______________________________________________
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/rols%40rols.org
> 
> This email sent to r...@rols.org

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to