10
votes

Le moyen le plus rapide de dessiner un tampon d'écran sur l'iPhone

J'ai un "rendu de logiciel" que je porte du PC à l'iPhone. Quel est le moyen le plus rapide de mettre à jour manuellement l'écran avec un tampon de pixels sur l'iPhone? Par exemple, dans Windows, la fonction la plus rapide que j'ai trouvée est SetDibitstOtevice.

Je ne sais pas grand chose à propos de l'iPhone, ni des bibliothèques, et il semble y avoir tant de couches et différents types d'éléments d'interface utilisateur afin que je puisse avoir besoin d'un beaucoup d'explication ...

Pour l'instant, je vais juste mettre à jour constamment une texture à OpenGL et rendre cela à l'écran, je doute vivement que cela va être la meilleure façon de le faire .

mise à jour:

J'ai essayé la méthode de texture de la taille d'écran openGL:

J'ai 17fps ...

J'ai utilisé un 512x512 texture (car il doit être une puissance de deux)

juste l'appel de xxx

semblait assez responsable de tout le ralentissement.

commenter le directeur et partir dans tout mon code d'interface graphique de rendu logiciel et le rendu de la texture actuellement non mise à jour, a entraîné une utilisation de 60fps, 30% d'utilisation de rendu, et aucune pointe notable de la CPU.

Notez que GetBuffer () renvoie simplement un pointeur sur le backbombeur logiciel du système d'interface graphique, il n'y a pas de ré-gigue ni de redimensionnement du tampon de toute façon, il est correctement dimensionné et formaté pour la texture, donc je suis donc assez certain Le ralentissement n'a rien à voir avec le logiciel Renderer, qui est la bonne nouvelle, on dirait que si je peux trouver un moyen de mettre à jour l'écran à 60 ans, le rendu de logiciel devrait fonctionner pour le moment.

i essayé de faire l'appel de la texture de mise à jour avec 512 320 au lieu de 512 512 c'était étrangement plus lent. .. courir à 10fps, il est également dit que l'utilisation du rendu n'est que de 5%, et tout le temps est en cours de gaspillage dans un appel à Unwiddle32BPP à l'intérieur des opengles.

Je peux modifier mon rendu logiciel pour rendre de manière native au format PIXLE, s'il en résulte un blit plus direct.

FYI, testé sur une version 2.2.1 iPod Touch G2 ( Donc, comme un iPhone 3G sur les stéroïdes)

Mise à jour 2:

Je viens de finir d'écrire la méthode de coriaison / graphique, il a l'air bien, mais je suis un peu inquiet de la mise à jour de son mise à jour L'écran chaque cadre, félicitant essentiellement l'ancien CGIMAGE, créant un tout nouveau ... Vérifiez-le dans 'Somerandomfunction' ci-dessous: Est-ce le moyen le plus rapide de mettre à jour l'image? Toute aide serait grandement appréciée. xxx


2 commentaires

Hey, j'ai également couru dans ce problème, c'est aussi la seule solution pour créer et détruire une CGIMAGE chaque cadre? (essayé cela et son plus lent que gltexsubimage). Il semble que tout le point du fournisseur direct est qu'il devrait indiquer ce tampon, donc si je le modifie, l'image est mise à jour. Toute aide à ce sujet?


Je pensais que le point d'utiliser CgdataProviderCreateDirect était un accès direct à un tampon de pixel, rafraîchi à l'aide de CadiSplayLink. Malheureusement, c'est horriblement lent. Une solution de contournement découverte?


5 Réponses :


3
votes

Le moyen le plus rapide consiste à utiliser ioframebuffer / iosurface, qui sont des cadres privés.

SO OpenGL semble être le seul moyen possible des applications AppStore.


1 commentaires

J'ai mis à jour la question avec les résultats de la méthode OpenGL, n'a pas l'air bien.



11
votes

Le plus rapide des applications App Store a approuvé que les graphiques 2D de CPU uniquement sont de créer un CGIMAGE sauvegardé par un tampon à l'aide de CGDATAPROViderCreateDirect et assignez-le à un Calayer 'S Contenu Propriété.

Pour de meilleurs résultats, utilisez le KCGIMAGEALPHAPREMULTIPLIEDFIRST | kccgbitmapbyteorder32little ou kcgimaquealphanone | kccgbitmapbyteorder32little types bitmap et double tampon de sorte que l'affichage ne soit jamais dans un état incohérent.

Edit: Cela devrait être plus rapide que de dessiner à une texture OpenGL en théorie, mais comme toujours, le profil doit être sûr.

EDIT2: CADISPAYLINK est une classe utile quelle que soit la méthode de composition que vous utilisez.


14 commentaires

Est-ce que cela serait assez rapide pour faire 24 fps vidéo?


@ ST3FAN: J'espère que c'est assez rapide pour faire au moins 60fps! Je commence à avoir le sentiment que l'API et les OS de l'iPhone sont encore plus ballés que les fenêtres de bureau! @RPetrich, merci, je vais l'essayer. Je sais à peine quoi que ce soit sur l'iPhone Dev, comme l'interface graphique ect, donc cela pourrait me faire un moment, pouvez-vous recommander un bon modèle à utiliser pour commencer? J'ai seulement utilisé l'Open Gl One.


Matt Les API iPhone sont extrêmement belles comparées à Win32. Certaines choses ne sont tout simplement pas possibles avec le code de cacao de niveau supérieur. Fichez un bug Reuqest avec Apple si vous pensez que cela nécessite une API de cacao plus agréable.


D'après mon expérience, l'écriture directe vers une texture OpenGL sera le moyen le plus rapide de présenter une teneur en 2-D à l'écran. L'animation principale est superposée sur OpenGL, le contenu d'une calayeuse les amène à être transféré dans une texture OpenGL. Vous pouvez éviter l'intermédiaire en écrivant directement à la texture. Sur le Mac, nous avons des extensions pour le transfert de mémoire directe à une texture: développeur.apple.com/mac/library/documentation/graphicsimagin g / ... , mais je ne vois rien de même sur l'iPhone.


@matt: Je n'ai pas vraiment de modèles adaptés à votre situation; Je ne pense pas que vous puissiez obtenir plus de 60Hz car l'affichage ne met pas à jour plus vite que cela. En outre, la corianimation a été conçue avec une accélération matérielle à l'esprit - autant de travail que possible est déchargée au GPU.


@Brad Larson: Sur l'iPhone, tout se termine dans un graphique de scène quartzcore qui est rendu par le GPU. Dans le cas de la teneur en OpenGL, la scène est rendue à une calayeuse par le GPU dans votre application, puis cette couche est composée (avec le reste du graphique) sur la tramebuffer dans le tremplin. OpenGL chemin: CPU Render -> OGL Texture -> OGL Calayer -> Cadrebuffer. Chemin de Calayer: Rendoir CPU -> Calayeur standard -> Cadrebuffer.


@Rpetrich: C'est intéressant, mais il court contre mon expérience sur le Mac. Dans mes tests, le moyen le plus rapide d'afficher un rectangle 2-D (un flux vidéo en direct de 60 FPS à partir d'une caméra CCD) consistait à utiliser OpenGL directement (hébergé dans un caopengllacheer). S'appuyant sur le contenu d'une calayeuse était nettement plus lent. Maintenant, il s'agit d'une plate-forme différente et j'utilisais les extensions de transfert de texture OpenGL décrites ci-dessus, je pourrais donc me tromper de la manière dont l'iPhone gère cette même situation.


@Brad Larson: Saisir le contenu d'une calayeuse sera toujours lent que cela implique une copie (sur la CPU no moins, où elle est lente). Réglage du contenu, d'autre part peut être rapide si le nouveau contenu est déjà sur la mémoire vidéo. Étant donné que l'iPhone utilise un modèle de mémoire unifié, toute la mémoire est la mémoire vidéo. J'imagine que le système d'exploitation X se comporte beaucoup différemment (et l'utilisation de iosurface serait nécessaire).


@Rpetrich: fascinant. Votre suggestion serait donc d'utiliser deux cgimages avec des données d'image fournies via une mémoire tampon dans cgdataProviderCreateDrederect (), puis échangeez-les comme le contenu d'une calayeuse pour chaque autre cadre à afficher? Je voudrais essayer cela et voir comment cela fonctionne.


@Brad Larson: Oui, c'est le gist de celui-ci. Si c'est le seul calque visible à l'écran, la seule copie devrait être du GPU de la Calayer à la tramebuffer. Si vous essayez de l'essayer, j'aimerais le voir par rapport à la tuyauterie à travers OpenGL.


Merci pour les gars de discussion, c'est un peu de perspicacité. Je vais essayer tout cela ce soir. Je suis un peu inquiet de savoir si cela fonctionnera de toute façon, nous ciblons réellement l'iPad. Il semble avoir 4 fois le résolution (1024x768) avec fondamentalement le même processeur que les 3gs ... Ce n'est qu'une chose de base graphique, (avantages sur ca? Sa plate-forme multi-plate-forme, je sais comment cela fonctionne et peut le modifier quand même Je veux). Mais cela pourrait être trop trop. De plus, comme je l'ai dit, je n'ai aucune idée de iPhone / OSX Stuff, alors si quelqu'un l'essaie, j'aimerais un pas à pas!


@matt: Le problème que vous rencontrerez n'est pas dans la mémoire tampon à l'écran suffisamment rapidement, mais dans le dessin au tampon lui-même - le GPU a beaucoup de matériel dédié conçu pour pousser les pixels que la CPU ne peut même pas venir proche de.


@Rpetrich: Hey, je suis arrivé avec du code à l'aide de la méthode de la certification, je ne suis pas sûr de la façon dont je mettez à jour l'image chaque image .. Supprimez-la et créez-le chaque image ... Vérifiez-le ci-dessus dans le Q. "Update2" n'a pas encore eu la chance de tester cela sur le matériel, testera demain. THX


Après avoir passé beaucoup de temps à ce problème, je peux dire avec confiance cette réponse est tout simplement fausse. La performance avec CoreGraphics est vraiment très mauvaise, en particulier avec les dispositifs de rétine où de nombreux pixels doivent être poussés. La bonne solution consiste à utiliser OpenGL. Oui, GltextImage2D est un goulot d'étranglement, mais c'est bien plus rapide dans presque tous les cas.



1
votes

Peut-être que vous pourriez peut-être abstraiter les méthodes utilisées dans le rendu de logiciel sur un shader GPU ... pourraient obtenir une meilleure performance. Vous auriez besoin d'envoyer les données "vidéo" codées comme une texture.


1 commentaires

C'est une bonne idée, pas pour mon cas malheureusement, mais certainement pour les autres.



0
votes

Une méthode plus rapide que les deux cgdataProvider et gltexsubimage est d'utiliser cvopenglestextureCache . Le cvopenglestextureCache vous permet de modifier directement une texture opengl dans la mémoire graphique sans repousser.

Je l'ai utilisé pour une vue d'animation rapide que vous pouvez voir ici:

https://github.com/justinmeiners/image-Squence-Streenence-streaming

C'est un peu difficile à utiliser et je suis tombé sur là après avoir posé ma propre question à propos de ce sujet: Comment mettre directement à jour les pixels - avec CGIMAGE et Direct CGDataProvider


0 commentaires

3
votes

Juste pour poster mon commentaire à la réponse de @ Rpetrich sous forme de réponse, je dirai dans mes tests, j'ai trouvé OpenGL soit le moyen le plus rapide. J'ai mis en place un objet simple (sous-classe UIView) appelé eEpixelViewer qui le fait suffisamment génériquement pour fonctionner La plupart des gens que je pense.

Il utilise OpenGL pour pousser les pixels dans une grande variété de formats (24BPP RGB, RGBA 32 bits et plusieurs formats YPCBCR) à l'écran aussi efficacement que possible. La solution réalise 60fps pour la plupart des formats de pixels sur presque tous les appareils iOS, y compris ceux âgés. L'utilisation est super simple et ne nécessite aucune connaissance OpenGL: P>

pixelViewer.pixelFormat = kCVPixelFormatType_32RGBA;
pixelViewer.sourceImageSize = CGSizeMake(1024, 768);
EEPixelViewerPlane plane;
plane.width = 1024;
plane.height = 768;
plane.data = pixelBuffer;
plane.rowBytes = plane.width * 4;
[pixelViewer displayPixelBufferPlanes: &plane count: 1 withCompletion:nil];


0 commentaires