Ich versuche, ein ganz einfaches openGL ES 1-Programm laufen eine glatte solide 60fps auf ein paar Geräte da draußen, und ich bekomme auf HTC Wunsch stecken. Das Telefon selbst ist schnell, bissig, leistungsstark, und insgesamt ein Kinderspiel zu bedienen; jedoch kann ich nicht scheinen, um anzuzeigen alles Vollbild bei 60fps mit OpenGL. Nachdem ich lange Zeit mit meiner Anwendung feststeckte, beschloss ich, eine Testanwendung mit Code direkt aus dem Beispielcode aus der Dokumentation zu erstellen.
Ich tue Folgendes. Einfacher Initialisierungscode mit GLSurfaceView. Ich habe drei Versionen von onDrawFrame, alle ganz einfach. Eine ist leer. Eine enthält nur glClear. Eine enthält gerade genug Status, um nur ein Fullscreen-Quad zu zeichnen. Trace mal vor, und nach. In meinem Programm gibt es keine andere Ansicht als meine GLSurfaceView. Ich kann die Zeiten, die ich erhalte, nicht erklären.
In allen Fällen wird die Funktion onDrawFrame selbst immer unter 2 ms beendet. Aber sehr oft, onDrawFrame wird nicht wieder vor 30~40ms aufgerufen, fallen meine Bildrate den ganzen Weg zu 30fps oder weniger. Ich erhalte etwa 50fps mit einem leeren onDrawFrame, 45 mit glClear und 35 mit einem Quad. Derselbe Code läuft mit 60 fps auf dem HTC Magic, auf dem Samsung Galaxy S und auf dem Sharp ISO1. Das Sony Experia X10 schafft wegen seines Bildschirms nur 30 fps. Ich habe viel kompliziertere Szenen mit soliden 60 Bildern pro Sekunde auf dem HTC Magic gemacht, das sehr im Vergleich zum Desire untermotorisiert. Ich habe kein Nexus One zum Testen zur Hand. Sicher, ich habe nur Puffer-Swapping, um ein paar Millisekunden zu blockieren. Aber es springt einfach über Frames die ganze Zeit.
Versuchen herauszufinden, was das Telefon macht außerhalb des onDrawFrame-Handlers, habe ich versucht, Debug.startMethodTracing zu verwenden. Es gibt keine Möglichkeit, wie ich die Aufzeichnung dazu bringen kann, die tatsächliche Zeit, die das Telefon außerhalb der Schleife verbringt, wiederzugeben. Am Ende von onDrawFrame verwende ich startMethodTracing und speichere dann die aktuelle Zeit (SystemClock.uptimeMillis) in einer Variablen. Am Anfang der nächsten Schleife protokolliere ich die Zeitdifferenz seit dem letzten Verlassen der Funktion und stopMethodTracing. Diese Funktion wird immer wieder aufgerufen, also sorge ich dafür, dass sie stoppt, sobald ich eine Aufzeichnung für eine Iteration mit einer Pause von 40+ ms erhalte. Die Zeitskala der resultierenden Aufzeichnung liegt unter 2 ms, als ob das System 38 ms außerhalb meines Programms verbracht hätte.
Ich habe viele Dinge ausprobiert. Aufzählung von EGL-Konfigurationen und probiere sie alle nacheinander aus. Nur um zu sehen, ob sich etwas ändert, habe ich zu einem Rendering when Dirty Schema gewechselt, das bei jedem Frame einen Redraw anfordert. Aber ohne Erfolg. Was auch immer ich tue, die erwartete Zeitspanne von 14~16ms, um die Puffer zu tauschen, dauert etwa die Hälfte der Zeit 30+ms, und egal was ich tue, es scheint, als würde das Gerät auf zwei Bildschirmaktualisierungen warten. ps auf dem Gerät zeigt meine Anwendung bei etwa 10% cPU und System_server bei 35%. Natürlich habe ich auch das Offensichtliche versucht, andere Prozesse zu beenden, das Gerät neu zu starten... Ich erhalte immer genau das gleiche Ergebnis.
Ich habe nicht das gleiche Problem mit der Leinwandzeichnung.
Weiß jemand, warum sich der Desire (und afaict nur der Desire) so verhält?
Zur Veranschaulichung: So sieht mein Testcode aus:
public class GLTest extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(this);
mGLView.setRenderer(new ClearRenderer());
setContentView(mGLView);
}
@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}
private GLSurfaceView mGLView;
}
class ClearRenderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) {}
public void onSurfaceChanged(GL10 gl, int w, int h) { gl.glViewport(0, 0, w, h); }
long start;
long end;
public void onDrawFrame(GL10 gl)
{
start = System.currentTimeMillis();
if (start - end > 20)
Log.e("END TO START", Long.toString(start - end));
// gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
end = System.currentTimeMillis();
if (end - start > 15)
Log.e("START TO END", Long.toString(end - start));
}
}