Ответ 1
Вы пытались позвонить prepareDisplayLink каждый раз, когда документ переходит на новый экран? Могу выполнить эту работу. Вы можете обнаружить это из функции windowDidMove.
У меня есть приложение на основе документов, в котором каждый документ имеет одно окно с NSScrollView, которое выполняет некоторые (довольно непрерывные) чертежи, используя только Cocoa.
Чтобы вызвать чертеж, я использую CVDisplayLink, описанный в коде ниже:
- (void)windowControllerDidLoadNib:(NSWindowController *) aController {
//other stuff...
[self prepareDisplayLink]; //For some reason putting this in awakeFromNib crashes
}
//Prep the display link.
- (void)prepareDisplayLink {
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
CVDisplayLinkSetCurrentCGDisplay(displayLink, ((CGDirectDisplayID)[[[[[self windowForSheet]screen]deviceDescription]objectForKey:@"NSScreenNumber"]intValue]));
CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, self);
}
//Callback to draw frame
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
NSAutoreleasePool *pool =[[NSAutoreleasePool alloc]init];
CVReturn result = [(ScrollView*)displayLinkContext getFrameForTime:outputTime];
[pool drain];
return result;
}
//Drawing function:
- (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime
{
[scrollView lockFocusIfCanDraw];
[self addToCurrentPostion:(dist/time)*CVDisplayLinkGetActualOutputVideoRefreshPeriod(displayLink)]; //Redraws the scrollview];
[scrollView unlockFocus];
return kCVReturnSuccess;
}
//Set the display when the window moves:
- (void)windowDidMove:(NSNotification *)notification {
if ([notification object] == [self windowForSheet]) {
CVDisplayLinkSetCurrentCGDisplay(displayLink, ((CGDirectDisplayID)[[[[[self windowForSheet]screen]deviceDescription]objectForKey:@"NSScreenNumber"]intValue]));
}
}
//Start or stop the animation:
- (IBAction)toggleAnim:(id)sender {
if (CVDisplayLinkIsRunning(displayLink)) {
CVDisplayLinkStop(displayLink);
}
else {
CVDisplayLinkStart(displayLink);
}
}
Код рендеринга:
- (void)addToCurrentPostion:(float)amnt {
fCurrentPosition += amnt; //fCurrentPositon is a float ivar
if (scrollView) [[scrollView contentView]scrollToPoint:NSMakePoint(0,(int)fCurrentPosition)];
if (scrollView) [scrollView reflectScrolledClipView:[scrollView contentView]];
}
Это отлично работает, а анимация - маслянистая..... на одном экране.
Как только я переношу один документ с главного экрана на второй монитор, анимация становится примерно такой же гладкой, как автомобиль с квадратными колесами. Анимация становится плохой во всех документах, если на втором экране находятся какие-либо (или более) документы. На главном экране не может быть никаких документов, а на вторичном экране и анимации также будет ухудшаться.
Я пробовал это на нескольких типах мониторов и нескольких Mac, всегда заканчивая этими результатами. Чтобы убедиться, что это не проблема с CVDisplayLink, я также попытался выполнить рендеринг с использованием NSTimer (с которым CVDisplayLink предпочтительнее) с теми же результатами.
Что я делаю неправильно? Любая помощь приветствуется.
РЕДАКТИРОВАТЬ: Я также попытался использовать рисование на основе нитей, опять же с теми же результатами.
РЕДАКТИРОВАТЬ: Я добился определенного прогресса, так как мой нитевидный чертеж (в основном цикл while
) очень хорошо работает только на одном экране. (Либо второй, либо первый).
Вы пытались позвонить prepareDisplayLink каждый раз, когда документ переходит на новый экран? Могу выполнить эту работу. Вы можете обнаружить это из функции windowDidMove.
Как быстро вы перерисовываете фреймы? Кажется, проблема заключается в том, что карта может только перерисовывать определенный объем данных. Вы перерисовываете каждую анимацию независимо друг от друга? Попробуйте повторно рисовать все анимации одновременно.
Проблема, по-видимому, исходит от апарт-взаимодействия с драйвером устройства видеокарты и вашей логикой. Удачи.