Question

Je travaille sur une application qui doit dessiner avec OpenGGL à un taux de rafraîchissement au moins égal au taux de rafraîchissement du moniteur. Et j'ai besoin d'effectuer le dessin dans un fil séparé afin que le dessin ne soit jamais verrouillé par des actions d'interface utilisateur intenses.

En fait, j'utilise un NSOpenGLView en combinaison avec CVDisplayLink Et je suis capable d'atteindre 60 à 80 images par seconde sans aucun problème.

Puisque j'ai besoin également d'afficher des commandes de cacao au-dessus de cette vue, j'ai essayé de sous-classe NSOpenGLView et le faire soutenir la couche, suivant CouchebackedOpenglview Exemple Apple.

Le résultat n'est pas satisfaisant et je reçois beaucoup d'artefacts.

Par conséquent, j'ai résolu le problème en utilisant un séparé NSWindow Pour héberger les commandes de cacao et l'ajout de cette fenêtre comme une fenêtre enfant de la fenêtre principale contenant le NSOpenGLView. Cela fonctionne bien et je suis en mesure d'obtenir tout à fait le même FPS que l'implémentation initiale.

Puisque je considère cette solution comme un hack sale, je cherche une façon alternative et plus propre de réaliser ce dont j'ai besoin.

Il y a quelques jours, je suis tombé NSOpenGLLayer Et j'ai pensé qu'il pourrait être utilisé comme une solution viable pour mon problème.

Alors enfin, après tout ce préambule, voici ma question: est-il possible de dessiner vers un NSOpenGLLayer à partir d'un fil séparé en utilisant CVDisplayLink rappeler?.

Jusqu'à présent, j'ai essayé de mettre en œuvre cela, mais je ne suis pas en mesure de tirer de la CVDisplayLink rappeler. je peux seulement -setNeedsDisplay:TRUE sur le NSOpenGLLayer du CVDisplayLink rappel puis effectuez le dessin -drawInOpenGLContext:pixelFormat:forLayerTime:displayTime: quand il est automatiquement appelé par le cacao. Mais je suppose que de cette façon je dessine du fil principal, n'est-ce pas?

Après avoir googlé pour cela que j'ai même trouvé cette Post dans lequel l'utilisateur prétend que le dessin sous lion ne peut se produire qu'à l'intérieur -drawInOpenGLContext:pixelFormat:forLayerTime:displayTime:.

Je suis sur Snow Leopard en ce moment, mais l'application devrait fonctionner parfaitement même sur Lion.

Est-ce que je manque quelque chose?

Était-ce utile?

La solution

Oui, c'est possible, mais pas le recommander. Appel display sur la couche depuis votre cvdisplaylink. Cela provoquera canDrawInContext:... être appelé et s'il revient oui, drawInContext:... sera appelé et tout cela sur n'importe quel fil appelé display. Pour rendre l'image rendue visible à l'écran, vous devez appeler [CATransaction flush]. Cette méthode a été suggérée sur la liste de diffusion Apple, bien qu'elle ne soit pas complètement sans problème (la méthode d'affichage d'une autre vue peut également être appelée sur votre fil d'arrière-plan et toutes les vues ne prennent pas en charge le rendu à partir d'un thread d'arrière-plan).

Le moyen recommandé est de rendre la couche asynchrone et de rendre le contexte OpenGL sur le fil principal. Si vous ne pouvez pas réaliser un bon framerate de cette façon, puisque votre fil principal est occupé ailleurs, il est recommandé de plutôt déplacer tout le reste (à peu près toute votre logique d'application) vers d'autres threads (par exemple en utilisant Grand Central Dispatch) et que vous ne gardez que les utilisateurs en entrée et uniquement Code de dessin sur le thread principal. Si votre fenêtre est très grande, vous n'obtiendrez peut-être toujours rien de mieux que 30 ips (une trame à deux rafraîchissements d'écran), mais cela vient du fait que la composition de Calayer semble un processus assez coûteux et il a été optimisé pour plus ou moins Couches statiques (par exemple les couches contenant une image) et non pour les couches se mettant à jour 60 ips.

Par exemple, si vous écrivez un jeu 3D, il est conseillé de ne pas mélanger du tout Calayers avec le contenu OpenGL. Si vous avez besoin d'éléments d'interface utilisateur de cacao, gardez-les séparés de votre contenu OpenGL (par exemple, divisez la fenêtre horizontalement en une pièce qui affiche uniquement OpenGL et une pièce qui affiche uniquement les contrôles) ou dessinez tous les contrôles vous-même (ce qui est assez courant pour les jeux).

Enfin et surtout, l'approche à deux fenêtres n'est pas aussi exotique que vous le pensez, c'est ainsi que VLC (le lecteur vidéo) dessine ses contrôles sur l'image vidéo (qui est également rendue par OpenGL sur Mac).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top