Register FAQ / Rules Forum Spy Search Today's Posts Mark Forums Read
Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Mar 6, 2012, 07:27 PM   #1
ArtOfWarfare
macrumors 603
 
ArtOfWarfare's Avatar
 
Join Date: Nov 2007
Send a message via Skype™ to ArtOfWarfare
Core Graphics Lagging?

I'm trying to make an app that simply draws a line on a window that reflects the position of two touches on a trackpad. Here's the code:

Oh, quick note, startPoint and endPoint are both CGPoint iVars. This is more just me experimenting with NSTouches and Core Graphics, so I'm not too concerned with following proper practices and not having iVars.

Code:
- (void)drawRect:(NSRect)rect
{
    CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];
    CGContextSetLineCap(myContext, kCGLineCapSquare);
    CGContextSetRGBStrokeColor(myContext, 0.0, 0.0, 0.0, 1.0);
    CGContextSetLineWidth(myContext, 1.0);
    CGContextMoveToPoint(myContext, startPoint.x + 0.5, startPoint.y + 0.5);
    CGContextAddLineToPoint(myContext, endPoint.x + 0.5, endPoint.y + 0.5);
    CGContextStrokePath(myContext);
}

- (void)touchesMovedWithEvent:(NSEvent *)event
{
	NSLog(@"Touches moved.");
	NSMutableSet *touches = [[event touchesMatchingPhase:NSTouchPhaseAny inView:self] mutableCopy];
	NSTouch *firstTouch = (NSTouch *)[touches anyObject];
	[touches removeObject:firstTouch];
	NSTouch *secondTouch = (NSTouch *)[touches anyObject];
	
	if (secondTouch)
	{
		float startX = (firstTouch.normalizedPosition.x)*(self.frame.size.width);
		float startY = (firstTouch.normalizedPosition.y)*(self.frame.size.height);
		startPoint = CGPointMake(startX, startY);
		float endX = (secondTouch.normalizedPosition.x)*(self.frame.size.width);
		float endY = (secondTouch.normalizedPosition.y)*(self.frame.size.height);
		endPoint = CGPointMake(endX, endY);
		
		[self setNeedsDisplay:YES];
	}
}
If the user moves their fingers quickly enough, the line will fall behind. If the user moves their fingers quickly enough for long enough, they can actually lift their fingers up and watch the line to continue to move for several seconds after the user has stopped.

Suggestions?

Edit: I'm running this in the debugger in Xcode on an Original MacBook Air (1.6 GHz). Even so, it shouldn't matter... I'd rather if it aborted drawing anything it missed in-between and skipped to what it should look like right now.
__________________
Don't tell me Macs don't last: 2007 iMac, 2007 Mac Mini, 2008 MacBook Air, all Vintage.
(iMac obsoletion: April 28, 2015, MBA: October 14, 2015, Mac Mini: March 9, 2016)

Last edited by ArtOfWarfare; Mar 6, 2012 at 07:32 PM.
ArtOfWarfare is offline   0 Reply With Quote
Old Mar 6, 2012, 09:06 PM   #2
KnightWRX
macrumors Pentium
 
KnightWRX's Avatar
 
Join Date: Jan 2009
Location: Quebec, Canada
dumb question, have you tried :

Code:
		if(![self needsDisplay]) [self setNeedsDisplay:YES];
__________________
"What you leave behind is not what is engraved in stone monuments, but what is woven into the lives of others."
-- Pericles
KnightWRX is offline   0 Reply With Quote
Old Mar 6, 2012, 10:45 PM   #3
ArtOfWarfare
Thread Starter
macrumors 603
 
ArtOfWarfare's Avatar
 
Join Date: Nov 2007
Send a message via Skype™ to ArtOfWarfare
Quote:
Originally Posted by KnightWRX View Post
dumb question, have you tried :

Code:
		if(![self needsDisplay]) [self setNeedsDisplay:YES];
I tried; it didn't seem to change anything.

Something I discovered, however, is that the lag seems proportional to the view's size. If it's 480x360, there isn't any noticeable lag. Scale the view up to 1280x800 (fullscreen) and it's very noticeable.

Is this a limit of the CPU/GPU - I don't think this computer even has a GPU - ? It just seems... silly. All I'm trying to do is draw a single line*, it doesn't seem like it should go so slow...

*A single line several dozen times a second.
__________________
Don't tell me Macs don't last: 2007 iMac, 2007 Mac Mini, 2008 MacBook Air, all Vintage.
(iMac obsoletion: April 28, 2015, MBA: October 14, 2015, Mac Mini: March 9, 2016)
ArtOfWarfare is offline   0 Reply With Quote
Old Mar 7, 2012, 02:21 AM   #4
MorphingDragon
Banned
 
Join Date: Mar 2009
Location: The World Inbetween
Send a message via Skype™ to MorphingDragon
Don't you need to close your vector path in Quartz2D?
MorphingDragon is offline   0 Reply With Quote
Old Mar 7, 2012, 04:14 AM   #5
KnightWRX
macrumors Pentium
 
KnightWRX's Avatar
 
Join Date: Jan 2009
Location: Quebec, Canada
Quote:
Originally Posted by ArtOfWarfare View Post
I tried; it didn't seem to change anything.

Something I discovered, however, is that the lag seems proportional to the view's size. If it's 480x360, there isn't any noticeable lag. Scale the view up to 1280x800 (fullscreen) and it's very noticeable.

Is this a limit of the CPU/GPU - I don't think this computer even has a GPU - ? It just seems... silly. All I'm trying to do is draw a single line*, it doesn't seem like it should go so slow...

*A single line several dozen times a second.
have you tried setNeedsDisplayInRect to limit the area you have to redraw ?

If your computer has no GPU, you're not seeing anything on screen. The GPU is a new fangled term for graphics card.
__________________
"What you leave behind is not what is engraved in stone monuments, but what is woven into the lives of others."
-- Pericles
KnightWRX is offline   0 Reply With Quote
Old Mar 7, 2012, 09:42 AM   #6
ArtOfWarfare
Thread Starter
macrumors 603
 
ArtOfWarfare's Avatar
 
Join Date: Nov 2007
Send a message via Skype™ to ArtOfWarfare
Quote:
Originally Posted by MorphingDragon View Post
Don't you need to close your vector path in Quartz2D?
I'm not sure what you're referring to...


Quote:
Originally Posted by KnightWRX View Post
have you tried setNeedsDisplayInRect to limit the area you have to redraw ?
I have tried that now. It performs better, but I'm having a little bit of difficulty in determining where I need to redraw... right now I have it simply redrawing the area where the line is, but I can see lots of partially drawn lines from where the line was. If I simply pick my fingers up and put them down someplace else entirely, I can get multiple full lines drawn. I guess the solution is going to be making sure the old line's rectangle, in addition to the new line's rectangle, is redrawn.

Quote:
Originally Posted by KnightWRX View Post
If your computer has no GPU, you're not seeing anything on screen. The GPU is a new fangled term for graphics card.
When I said GPU I was referring to a dedicated GPU, as opposed to an integrated one. (I think... hardware isn't my strong point... working on improving that in school...)
__________________
Don't tell me Macs don't last: 2007 iMac, 2007 Mac Mini, 2008 MacBook Air, all Vintage.
(iMac obsoletion: April 28, 2015, MBA: October 14, 2015, Mac Mini: March 9, 2016)
ArtOfWarfare is offline   0 Reply With Quote
Old Mar 7, 2012, 10:30 AM   #7
chown33
macrumors 603
 
Join Date: Aug 2009
Use the timestamp of the event to limit the update rate (more specifically, the interval between events). Also use the distance between touches to limit the update rate.

If the time between two events is small, and the distance is small, redraw nothing. Heck, you could probably get away with just looking at the distance between event N's position and event N-1's position, regardless of timestamp. Using timestamp, however, gives you better filtering for fine movement. That is, multiple repeated events at the new location will cause the tracking to move to that location, even if the distance is small.

"Small" simply means below some threshold. You will probably have to experiment to find an optimal value. I suggest starting it fairly high, like 10 or 20 pixels, so you can actually observe the effects of the filtering. Then make it smaller until it feels like a good balance between responsive (fast) and accurate (tracks fine movement).

The goal here is to avoid redraws. So every time you call setNeedsDisplay:YES, you are forcing a redraw, whether the content to be drawn really needs it or not. Figure out a way to measure your redraw rate, and show it to you, and then use that metric to work on the spatial/temporal filtering (distance and timestamp differences).


Oh, and I'd bet cash money that if you take out the NSLog, it will be markedly faster. Because adding NSLog's to a real-time process is a recipe for real-time failure.
chown33 is offline   0 Reply With Quote
Old Mar 7, 2012, 02:57 PM   #8
KnightWRX
macrumors Pentium
 
KnightWRX's Avatar
 
Join Date: Jan 2009
Location: Quebec, Canada
Quote:
Originally Posted by chown33 View Post
Use the timestamp of the event to limit the update rate (more specifically, the interval between events). Also use the distance between touches to limit the update rate.
Could you also use [[NSRunLoop mainLoop] cancelPerformSelector:target:argument:] to delete the drawRect call from the main loop before issuing another redraw command ?
__________________
"What you leave behind is not what is engraved in stone monuments, but what is woven into the lives of others."
-- Pericles
KnightWRX is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
Graphics card to get for Mac Pro 1,1 2.66 GHz quad core Synergy67 Buying Tips and Advice 5 Apr 20, 2013 09:14 PM
How does the iPad 4 double graphics performance, when it's still quad-core? yow. iPad 3 Oct 23, 2012 07:10 PM
What do you rather, discrete graphics or quad core? n0cus Mac mini 1 Oct 23, 2012 05:28 PM
whats the best graphics card for a 2006 dual core king tech 1 Mac Pro 3 Jul 2, 2012 07:33 PM
Resolved: Safari Lagging/Entire Iphone Lagging Kaemon iPhone Tips, Help and Troubleshooting 6 Jun 26, 2012 03:04 PM

Forum Jump

All times are GMT -5. The time now is 11:49 AM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC