Saturday, June 6, 2009

DevDiary: Problems with DrawRect:

I've been working on a "hobby" app project off and on for the past few weeks. It involves performing full-screen page-flipping animation. Unfortunately, I keep running into system bottlenecks issues.

I know there must be a good solution, but so far I haven't found it.

Here's the problem. I have about 35 meg worth of cell-style animation, and each image is 320x480 (i.e. it takes up the full iPhone screen). There's about 1300 frame in total. There's no realistic way I can cache all these images in RAM on the iPhone. Since the animation is dynamic, I can't even cache what will be animated next as it is determined by user interaction.

What I am currently doing is loading each frame of animation on demand. This is much slower than caching the images in RAM first (I can only get about 10 FPS rather than the 30 if I were able to cache the images). But this isn't the problem. I'm ok with the lower frame rate.

The problem is I can't seem to find a good method for having low level access to the image buffer of the current view while still maintaing decent responsiveness for touch events.

I'm currently overriding the drawRect method of the UIView (I call [image drawAtPoint:(CGPointMake(0.0, 0.0))]; to render my image) and then for my animation routine, I just repeatedly call [view setNeedsDisplay]. This almost works. There are no memory issues at all since the view is just getting bitmap data written to it rather than a handle to an image. The problem is the rendering takes up so much bandwidth that the app no longer responds to touch events when running under iPhone OS 2.x. Oddly, running under 3.0 the app performs fine with touch events. But, I'd like to release the app for 2.x, so this approach won't work.

I also tried using the CALayer of a view and setting its content to my current image (via layer.content = myImage), but that causes severe memory problems with the iPhone OS. Touch events now work, but memory problems occur. Even though I'm releasing each image after the layer uses it, the memory still hangs around and eventually the iPhone OS kicks my app for being a bad citizen.

So, I'm now trying to figure out another approach. I'm wondering if using OpenGL ES would work. I've used it in another app for doing animation, but have no experience with trying to render large full screen bitmaps. Ideally, what I'd like is to just get raw access to the OpenGL framebuffer, dump my bitmap image there and then display the framebuffer. I'm hoping I don't have to treat my animation frames as textures. That seems like it would add even more overhead and slow down the frmae rate even more.

Anyone have any tips on what might be a good solution?

All content copyright © 2009  Brian Stormont, unless otherwise noted.   All rights reserved.