34 votes

Cocoa dessine sur différents écrans et perd sa performance

J'ai un document basé sur l'app, où chaque document a une fenêtre avec une NSScrollView qui fait (de façon assez continue) dessin à l'aide seulement de Cacao.

Pour appeler le dessin, je suis en utilisant un CVDisplayLink, énoncées dans le code ci-dessous:

- (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);
    }
}

Code De Rendu:

- (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]];
}

Cela fonctionne très bien, et l'animation est de babeurre.....sur un seul écran.

Dès que je déplace un document sur l'écran principal, sur un deuxième écran, l'animation devient sujet lisse comme une voiture avec la place des roues. L'animation est mauvaise dans tous les documents lors de l'un (ou plus) les documents sont sur le deuxième écran. Il y a peut être pas de documents sur l'écran principal et l'écran secondaire et de l'animation se dégradent également.

J'ai essayé sur plusieurs types de moniteurs, et plusieurs Mac, en terminant toujours dans ces résultats. Pour s'assurer que ce n'était pas un CVDisplayLink question connexe, j'ai aussi essayé le rendu à l'aide d'un NSTimer (qui le CVDisplayLink est préférable d'), avec les mêmes résultats.

Ce que je fais mal? Toute aide est grandement appréciée.

EDIT: j'ai essayé à l'aide de fil à base de dessin aussi, encore une fois avec les mêmes résultats.

EDIT: j'ai fait quelques progrès, mon fils à base de dessin (en gros une while boucle) fonctionne très bien sur un seul écran. (Soit la deuxième ou la première).

1voto

namar0x0309 Points 884

Avez-vous essayé d'appeler prepareDisplayLink chaque fois que le document entre dans un nouvel écran? Peut faire le travail. Vous pouvez le détecter grâce à la fonction windowDidMove.

0voto

El Developer Points 2695

À quelle vitesse redressez-vous les cadres? Le problème semble être que la carte ne peut continuer à redessiner qu'une certaine quantité de données. Est-ce que vous re-dessinez chaque animation indépendamment les uns des autres? Essayez de re-dessiner toutes les animations en même temps.

Le problème semble provenir d'une interaction amdirect avec le pilote de périphérique de la carte vidéo et avec votre logique. Bonne chance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X