开发者

Why is drawInContext so slow here?

I'm using the QuartzImage class in one of the demo projects and what I'm was trying to achieve was a simple frame display unit that basically draws an image (320x480) every 1/10th of sec. So my "frame rate" should be 10 frames per sec.

In the QuartzImage demo class, there is a drawInContext method and in this method, it's basically drawing a CGImageRef using the CGContextDrawImage(), I measured the time it took to finish complete and it's taking on average around ~200ms.

2011-03-24 11:12:33.350 QuartzDemo[3159:207] drawInContext took 0.19105 secs

-(void)drawInContext:(CGContextRef)context
{
    CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
    CGRect imageRect;
    imageRect.origin = CGPointMake(0.0, 0.0);
    imageRect.size = CGSizeMake(320.0f, 480.0f);
    CGContextDrawImage(context, imageRect, image);
    CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
    NSLog(@"drawInContext took %2.5f secs", end - start);
}

Can anyone explain why it's taking that long and if there is any other way of improving the performance? 200ms just seems much more longer than it should have taken.

UPDATES I tried @Brad-Larson's suggestion but no开发者_开发百科t seeing a lot of performance improvement.

So the updated version is I got my own class

@interface FDisplay : UIView {
    CALayer *imgFrame;
    NSInteger frameNum;
}
end

So in my Class implementation

- (id)initWithFrame:(CGRect)frame {
    ............

    frameNum = 0;
    NSString *file = [NSString stringWithFormat:@"frame%d",frameNum];
    UIImage *img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:file ofType:@"jpg"]];
    imgFrame = [CALayer layer];
    CGFloat     nativeWidth = CGImageGetWidth(img.CGImage);
    CGFloat     nativeHeight = CGImageGetHeight(img.CGImage);
    CGRect      startFrame = CGRectMake(0.0, 0.0, nativeWidth, nativeHeight);
    imgFrame.contents = (id)img.CGImage;
    imgFrame.frame = startFrame;
    CALayer *l = [self layer];
    [l addSublayer:imgFrame];
}

I have a NSTimer going at 0.1f calling my refresh method

NSString *file = [NSString stringWithFormat:@"frame%d",frameNum];
UIImage *img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:file ofType:@"jpg"]];
frameNum++;
if (frameNum>100) 
    frameNum = 0;

[CATransaction begin]; 
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 
[imgFrame setContents:(id)img.CGImage];
[CATransaction commit];
end = CFAbsoluteTimeGetCurrent();
NSLog(@"(%d)refresh took %2.5f secs", [[self subviews] count],end - start);

I think I got everything right but the frame rate is still way low,

refresh took 0.15960 secs


Using Quartz to draw out images is about the slowest way you could do this, due to the way that content is presented to the screen.

As a step up, you could use a UIImageView and swap out its hosting image for each frame. An even faster approach might be to use a CALayer and set its contents property to a CGImageRef representing each image frame. You may need to disable implicit animations using a CATransaction for this to be as fast as it can be. If I recall, I was able to get 320x480 images to be drawn at over 15 FPS on an original iPhone using the latter method.

Finally, for optimal performance you could set up an OpenGL ES display with a rectangle that filled the screen and supply the images as textures to be rendered on that rectangle. This would require significantly more code, but it would be extremely fast.


I have been porting my game from Android to iPhone and I was shocked by the performance of Quartz. The same code on Android is 10x faster than on iPhone. I have a few DrawImages, and a bunch of line draws and beziers. It's so slow on iOS, specially iPhone 4, where the processor struggles to keep up with the retina display resolution. My game performed perfectly at 60fps in almost ANY android device.

I tried several approaches for rendering (always avoiding OpenGL). I started by drawing everything at every frame. Then I started rendering as much as I could before the game loop, by using UIImage's. Now I'm trying to go with CALayers. Although I can see the game at steady 60FPS on iPhone 3GS and 4S, the most I can get on the iPhone 4 is 45 FPS.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜