Re: Changing CALayer's contents too rapidly causes CoreAnimation to implode?
Re: Changing CALayer's contents too rapidly causes CoreAnimation to implode?
- Subject: Re: Changing CALayer's contents too rapidly causes CoreAnimation to implode?
- From: Colin Cornaby <email@hidden>
- Date: Thu, 24 Jan 2008 17:58:41 -0800
I think rendering into an OpenGL layer might be overkill for now.
Really the image won't be changing all that often, but when the user
does wail on that stepper it happens in pretty quick succession for
that short period of time. All other filters are applied via the
filters property.
I'll sit down tonight and implement what you have suggested (drawing
into a CGBitmapContext). It seems like the simplest course from here.
Thanks,
Colin
On Jan 24, 2008, at 1:10 PM, Troy Stephens wrote:
On Jan 24, 2008, at 11:14 AM, Colin Cornaby wrote:
Thanks,
This appeared to be the issue. Removing my bitmap image rep's
release seems to have fixed both the stepper issue and the state
restore issue.
Would the best time to release my image rep be after I have changed
the contents of the layer then? Is there a chance that
CoreAnimation could still try to read my old CGImage as part of an
animation after I change the contents of my layer?
Yes. Even after you've removed the reference to the CGImage from
your layer tree, it may still be referenced by the render tree until
the render tree catches up to the change. This makes assessing the
necessary lifetime of the NSBitmapImageRep more difficult.
For a truly robust solution when images are coming and going like
this, you want the CGImage you hand off to Core Animation to own
(retain) its own source pixel data instead of depending on the
existence of an NSBitmapImageRep to keep that data around.
You should be able to do this, while keeping performance impact to a
minimum, by using CGBitmapContextCreate() with a NULL "data" pointer
to create a bitmapped CGContext that manages its own memory, drawing
the CIImage into that context (evaluation of the filter chain to
produce the output pixels happens here), and then using
CGBitmapContextCreateImage() to get a CGImage. The resultant
CGImage will then own the pixel data that it references for its full
lifetime, and you won't have to worry about keeping a supporting
NSBitmapImageRep around. It's a bit more code to write, but should
leave you in a much safer place given the image swapping you're doing.
There -might- also be faster ways of rendering a continually updated
CIImage in a layer tree. I'm not an expert on CI+CA performance
issues, but using a CIContext to render the CIImage directly into a
CAOpenGLLayer comes to mind as one possibility that might be worth
investigating. I'll see if I can find out more about that.
Troy
On Jan 24, 2008, at 10:52 AM, Troy Stephens wrote:
Hi Colin,
I suspect the problem you're encountering is that the CGImage
yielded by a given cycle is sometimes outliving the
NSBitmapImageRep it was created from, and whose pixel data the
CGImage still references. When CoreGraphics goes to render the
CGImage to a destination, it ends up walking off into memory
that's been potentially reused for some other purpose.
When using -[NSBitmapImageRep CGImage], it's vitally important to
keep the NSBItmapImageRep around for as long as the CGImage is in
use. If you fix that problem, your crashes should disappear.
Troy
On Jan 24, 2008, at 9:52 AM, Colin Cornaby wrote:
I have a image I am doing some processing on using CoreImage,
which is then set as the contents of a CoreAnimation layer. I
know that CALayer has a filters property, which I could use to
apply a CoreImage filter in realtime, but for various reasons the
image has to be preprocessed. If anyone is interested in why I
would be willing to discuss off list.
I have a stepper that adjusts the attributes of the filter. When
the stepper is hit, the filter's attributes are changed, my image
is re-rendered, and then set again as the contents of my CALayer.
I started to notice an interesting crash the other day. Holding
the stepper down and rapidly adjusting the image was causing my
app to crash. Clicking the stepper rapidly would also produce the
same results. But if I hit the stepper more slowly everything
seemed to work fine. Manually adjusting the number that the
stepper controlled also worked just fine.
I went through my code to try and determine if it was an issue
with my rendering code. I went through many steps, including
logging images out to files to see if perhaps my rendering code
was somehow screwing up and generating bad images. But my
software seemed to be generating images just fine.
The issue seems to be that if I try to set the contents property
of a CALayer in quick succession it crashes. It's still possible
that something in my code is wrong, but I spent all last night
debugging it and signs seem to point to an issue within
CoreAnimation.
Here is my post image rendering code that pushes the image into
CoreAnimation:
CIImage *finalImage = [filter valueForKey:@"outputImage"];
NSBitmapImageRep *finalImageRep = [[NSBitmapImageRep alloc]
initWithCIImage:finalImage];
CGImageRef finalCgImage = [finalImageRep CGImage];
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
[self.contentLayer setContents: (id) finalCgImage];
[CATransaction commit];
And here is the backtrace I get when I set the image too rapidly:
#0 0x96492f10 in sseCGSConvertXXXX8888TransposePermute
#1 0x9640f7f6 in argb32_image
#2 0x932e9822 in ripl_Mark
#3 0x932ebcd1 in ripl_BltImage
#4 0x932d5c25 in ripc_RenderImage
#5 0x932e631c in ripc_DrawImage
#6 0x9640343d in CGContextDrawImage
#7 0x90cb544f in create_image_by_rendering
#8 0x90cb4f48 in CARenderImageNewWithCGImage
#9 0x90cdcc78 in CARenderPrepareCGImage
#10 0x90cdcbd3 in CALayerPrepareCommit
#11 0x90cdcbd3 in CALayerPrepareCommit
#12 0x90cdcbd3 in CALayerPrepareCommit
#13 0x90cdcbd3 in CALayerPrepareCommit
#14 0x90cb112f in CAContextCommitTransaction
#15 0x90cb0e27 in CATransactionCommit
#16 0x9017a10f in -[NSCell trackMouse:inRect:ofView:untilMouseUp:]
#17 0x9060f4f7 in -[NSStepperCell
trackMouse:inRect:ofView:untilMouseUp:]
#18 0x901794cc in -[NSControl mouseDown:]
#19 0x90177d9b in -[NSWindow sendEvent:]
#20 0x90144a2c in -[NSApplication sendEvent:]
#21 0x900a2705 in -[NSApplication run]
#22 0x9006f9ba in NSApplicationMain
#23 0x00007136 in main at main.m:13
If this looks like I'm passing a bad image to CA I'll keep
plugging away at my image code and try to log what's going on
deeper in the process.
I also have this same crash occurring in another situation that
is slightly more complicated to explain, but involves when I am
loading back up a document and restoring the state. Again,
debugging shows that the image I'm passing CA is good, but CA
will either crash, or if I'm lucky, display garbage. Given that
the stepper seems to shine more light on this issue, I'm
currently trying to fix this bug in relation to the stepper
instead of looking at my state restorer right now.
If anyone has seen this sort of crash before, could they give me
some sort of clue as to what it means?
Thanks,
Colin
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden