2012-06-11 23 views
5

He estado trabajando en un proyecto en el que un usuario puede interactuar con GLSurfaceView para dibujar formas en una pantalla. Todo esto funciona bien y dandy, pero ahora estoy intentando hacer dos cosas: 1) crear una miniatura de su dibujo, y 2) guardar su dibujo. Es importante tener en cuenta que el usuario puede dibujar una imagen que es más grande que la pantalla.Forzando que OpenGL Buffer use GL 1.0 o 1.1?

Por lo que mi investigación muestra, esto se logra mejor utilizando Bitmap (que puede ser 1) representada en un Canvas para una miniatura, y 2) se guarda en el sistema de archivos, lo que logra mis dos objetivos).

Inicialmente, traté de leer el Renderer del GLSurfaceView a través de glReadPixels, pero resulta que no pude obtener los datos fuera de la pantalla de esto. En cambio, opté por hacer un buffer fuera de la pantalla para producir un render de la imagen, que podría convertirse a Bitmap.

Encontré un lovely post que proporcionaba un código para una clase llamada PixelBuffer, que ahora estoy usando. (He hecho algunos ajustes, pero todos los problemas que he tenido ocurren con o sin dicho ajuste.)

Ahora, cuando uso el getBitmap() del código (que publicaré a continuación en caso de que el PixelBuffer hilo del foro es ilegible), obtengo un grupo de called unimplemented OpenGL ES API. Esto me pareció extraño al principio, así que investigé un poco. Resulta que, por alguna razón, la clase PixelBuffer está utilizando OpenGL ES 2.0, mientras que GLSurfaceView está utilizando OpenGL ES 1.1. El dispositivo que estoy usando (Galaxy Nexus) no es compatible con 2.0. (Y por otra parte, me gustaría apoyar la más amplia gama de dispositivos posible.)

Por lo tanto, aquí está mi pregunta: ¿Cómo puedo forzar mi clase PixelBuffer utilizar la API de OpenGL ES 1.1? Ya he añadido lo siguiente en mi Manifiesto:

<uses-feature android:glEsVersion="0x00010001" /> 

Además, he intentado establecer la versión utilizando int[] version = new int[] { 1, 1 };, sin ningún resultado.

El código PixelBuffer Estoy usando: Link. La línea en cuestión que llama al Renderer está en la línea 91. El código de versión está en la línea 39-ish en adelante.

Este es el código que utilizo para crear el PixelBuffer, llamado desde el GLSurfaceView objeto:

setEGLConfigChooser(8, 8, 8, 8, 0, 0); 
    mRenderer = new MyRenderer(this); 
    setRenderer(mRenderer); 
    mPixelBuffer = new CPPixelBuffer(1440, 1280); // TODO Temporary hardcode for Galaxy Nexus wallpaper size 
    mPixelBuffer.setRenderer(mRenderer); 

Si no es posible utilizar la versión 1.1 para una fuera de la pantalla render, ¿cuál es la mejor manera de convertir mi Superficie GL a Bitmap usando la versión 1.1 o inferior?

EDITAR: A través de algunas pruebas, descubrí que con el siguiente código hace que estos errores:

// int[] version = new int[2]; 
int[] version = new int[] { // When using this line, as well as the other marked lines, instead of the line above, the errors are produced. 
    1, 1 // Marked 
}; // Marked 
int[] attribList = new int[] { 
    EGL_WIDTH, mWidth, 
    EGL_HEIGHT, mHeight, 
    EGL_VERSION, 1, // Marked 
    EGL_NONE 
}; 

06-11 15:41:52.316: E/libEGL(5618): eglMakeCurrent:674 error 3009 (EGL_BAD_MATCH) 
06-11 15:41:52.316: E/libEGL(5618): call to OpenGL ES API with no current context (logged once per thread) 

Sin embargo, ninguna de estas configuraciones de aliviar el problema en cuestión. Ambos están presentes en mi código PasteBin'd, así que pensé que sería bueno señalarlo.

+0

En realidad Galaxy Nexus admite OpenGL ES 2.0 muy bien. ¿Qué función de llamada le proporciona exactamente la "API de OpenGL ES sin implementar"? Si esa es la creación de PBufferSurface, intente usar diferentes atributos para ella. O mejor, sáltelo y use glGreadPixels desde framebuffer. –

+0

Todos los métodos (en la llamada 'onDrawFrame') me lo dan. Incluso 'gl.glLoadIdentity()'; mi ventana es literalmente enviada por ellos. No es nada 2.0 específico, por lo que esto es tan extraño para mí. _ (Sin embargo, esto no resuelve el problema para dispositivos anteriores compatibles con 1.1 ...) _ – Eric

+0

¿Tiene contexto GL creado para el hilo donde está invocando gl ... funciones? –

Respuesta

2

No encontré por alguna razón el enlace para publicar un comentario, lo siento sobre publicar esto como una respuesta.Acerca del hilo GL, normalmente está en el hilo GL solamente en

public void onDrawFrame(GL10 gl) 

Cuál es un método del Renderer. Todo debe hacerse dentro de este método. Simplemente puede poner un booleano, digamos, en el renderizador, y establecerlo en verdadero cuando desee que se haga algo en el renderizador, y eso es todo. Si haces alguna llamada fuera de este método, obtendrás errores.

También, busque en este ejemplo: Android OpenGL Screenshot lo he utilizado y ha funcionado para mí, pero no necesitará ahorrar área fuera de la pantalla, así que no sé si va a trabajar, tal vez no :)

El método debe llamarse dentro onDrawFrame

+0

Incluso con un objeto 'GL10' válido pasado a él? Simplemente debería ser una copia de seguridad de la codificación del Renderer (la mayor parte de la cual es mía, no de la clase 'Renderer'), y renderizar en su propio objeto GL. – Eric

+0

¿Te refieres a otro método en hilo diferente? Si es así, entonces sí, no podrá usar incluso si aprobó un objeto GL10 válido. Debes usarlo solo allí. Imagina cómo se escriben todos los juegos: hay un ciclo while en el que todo está hecho. Los cálculos matemáticos, por ejemplo, se pueden realizar en otros subprocesos, pero maneja los resultados en el subproceso donde los renderiza, y los objetos GL son válidos en el subproceso de representación, como los objetos GL también. Android es más inteligente y te apunta a esto, en C++ solo obtendrás un bloqueo o violación de acceso :) – XMight

+0

Ambos comparten el mismo hilo GL. Básicamente es un segundo objeto (el 'PixelBuffer') que tiene' Renderer' como una variable miembro; ellos comparten un hilo y un contexto. Básicamente llama 'mRenderer.onDrawFrame ()'. – Eric