Improve CGContextDrawImage performance - macos

I have a custom NSView that has it's own drawRect. I draw a lot of images using CGContextDrawImage into the view. The NsView is in a NSScrollView. The issue I am having is, while scrolling, the drawrect takes too long. the scrolling isn't smooth.
I did try setting wantslayer to true, to enable layer-backed drawing. Now the scrolling is smooth until the next drawrect is called, i.e till next time a new dirtyRect has to be redrawn.
Since I have to use drawrect to draw the contents, is there a way to improve scrolling performance?
if not, is there an alternative?
Update:
the call that's taking time.
I tried what Rob suggested below (using NSImageView for each image). that helped. I see smooth scrolling while setting the images as well.
But I would like to know why CGContextDrawImage takes time? especially rgbaf16_sample_rgbaf_inner. is there a way to avoid it?

Related

Combining drawRect: with other UIKit drawing

I'm working on some other person's code, which does most of the UI drawing in drawRect:. However, I need to add some animations (UIActivityIndicator animating, for example) to the view, and since drawRect: appears to be frame based, there doesn't seem to be an easy way.
I understand it is a mistake to fiddle with view hierarchies in drawRect, so I can't simply addSubview:. I want the activity indicator to do its own drawing, after drawRect:, because it should overlap. How should I approach this?

CALayer with Animation on Scroll View

So, I have a CALayer added to a UIScrollView that does some path animations. In my application, I resize the scroll view and shift everything to create a "negative" region. Using contentOffset with UIScroll views, all my subviews are shifted and there is no flashing effect. However, when the lines on the CALayer are shifted, there is a flashing effect because they are drawn in the "negative" area first, then shifted over.
This was happening as an animation at first, but I used CATransaction -begin and -commit to remove the animation. The flashing is still occurring though because the lines are still drawn and then moved.
Is there anyway to solve with?
Thanks in advance.
Edit: I figured out a way to fix this. Before, I was adding each animation to an animation layer, which was then added to the UISCrollView. Instead, I added each animation directly to the UISCrollView and then shift all layers appropriately as before. CATransaction -begin and -commit are still needed to remove any sort of animation of the shift.
I figured out a way to fix this. Before, I was adding each animation to an animation layer, which was then added to the UISCrollView. Instead, I added each animation directly to the UISCrollView and then shift all layers appropriately as before. CATransaction -begin and -commit are still needed to remove any sort of animation of the shift.

Blurry NSImageView

I have an NSImageView in a view that utilizes Core Animation. Prior to using Core Animation the image looks fine but now its blurry and low quality. If I let NSImageView have a bezel border the issue goes away but I need it to have no border. Had this happened to anyone else?
Imgae in the background with no border, same image in the front with a border.
Thanks
EDIT: I forgot to mention that the image is an icon file (ICNS) so it has various sizes. The bordered view loads the correct size and the transparent one loads the smallest and stretches it.
Although not the way I wanted to, I managed to create a fix for the issue. The issue seemed to be the way that NSImageView was drawing the image so I created a custom NSView subclass with support for the same bindings I used in my original image view. Im not sure why the blurry-ness happend in the beginning, but drawing the image by hand in an NSView seems to do the trick.
Your image may be drawing in a non-pixel-aligned way. Have you tried shifting it by a half pixel?
Apple has a good demonstration of this in the BlurryView app in their "Cocoa Tips and Tricks" sample code.
Cocoa Tips and Tricks

Drastic slowdown using layer backed NSOpenGLView

I needed to display some Cocoa widgets on top of an NSOpenGLView in an existing app. I followed the example in Apple's LayerBackedOpenGLView example code. The NSOpenGLView is given a backing layer using:
[glView setWantsLayer:YES]
Then the Cocoa NSView with the widgets is added as a subview of the glView. This is basically working and is twice ad fast as my previous approach where I added the NSView containing the widgets to a child window of the window containing the glView (this was the other solution I found on the web).
There were two problems.
The first is that some textures that I use with blending were no longer getting the blend right. After searching around a bit it looked like I might need to clear the alpha channel of the OpenGLView. This bit of code that I call after drawing a frame seems to have fixed this problem:
Code:
glColorMask(FALSE, FALSE, FALSE, TRUE); //This ensures that only alpha will be effected
glClearColor(0, 0, 0, 1); //alphaValue - Value to which you need to clear
glClear(GL_COLOR_BUFFER_BIT);
glColorMask(TRUE, TRUE, TRUE, TRUE); //Put color mask back to what it was.
Can someone explain why this is needed when using the CALayer, but not without?
The second problem I don't have a solution for. It seems that when I pan to the part of the scene where problem is #1 was observed, the frame rate drops from something like 110 FPS down to 10 FPS. Again, this only started happening after I added the backing layer. This doesn't always happen. Sometimes the FPS stays high when panning over this part of the scene but that is rare. I assume it must have something with how the textures here are blended, but I have no idea what.
Any thoughts?
I did figure out a workaround to the slowdown. The OpenGL view has a HUD (heads up display) view that goes on top of it. I had installed another NSView as a subview if it. Both the HUD and the subview have lots of alpha manipulation and for some reason that tickled a real slowdown in compositing the layers. I could easily instal this subview as a subview of the OpenGL view and when I did this everything sped up again. So although I don't fully understand the slowdown, I do have a good work around for it.

drawRect makes scrolling slow in UIScrollView

I've got a UIScrollView with a (custom) UIView inside of it.
In my scrollViewDidScroll-method I'm calling
[myCustomView setNeedsDisplay];
This makes the scrolling noticeably slower, if I'm implementing the drawRect: method in my custom UIView - even if it's completely empty.
As soon as I delete the drawRect: method, it's smooth again.
I have absolutely no idea, why... anyone of you?
I hate drawrect too
"It's because of the way hardware-accellerated animation works in Cocoa.
If you don't have a custom drawRect method, the system caches the pixels for your view in video memory. When it needs to redraw them, it just blits the pixels onto the screen.
If you have a custom drawRect method, the system instead has to call your drawRect method to render the pixels in main memory, then copy those pixels into video memory, THEN draw the pixels to the screen for each an every frame. The docs say to avoid drawRect if you can.
I think main memory and video memory are shared on most/all iOS devices, but the system still has a lot more work to do when you implement a drawRect method for a view.
You would probably be better served to use an OpenGL layer and render to that with OpenGL calls, since OpenGL talks directly with the display hardware."
link to that quote: http://www.iphonedevsdk.com/forum/iphone-sdk-development/80637-drawrect-makes-scrolling-slow-uiscrollview.html

Resources