There is a dearth of high-quality information on this topic -- any updates 
on the crashes or on syncing the thread, or on best practices using 
TextureView with OpenGL? I'm looking to migrate from GLSurfaceView to 
TextureView to work around some issues with view composition, but the lack 
of an official solution makes me nervous. I've noticed that even when using 
Choreographer, there are inexplicable jitters in the displayed frames that 
don't occur with GLSurfaceView and are not visible by observing the logs or 
frame timestamps.

On Wednesday, 11 July 2012 16:43:50 UTC-4, mor...@gmail.com wrote:
>
> Hi Romain,
>
> I am wondering about the Thread.sleep() call in the rendering thread's run 
> loop. Is that technically necessary? If so, may I ask why? And if so, then 
> how would one implement a high-framerate OpenGL game (for instance) using 
> TextureView?
>
> What prompted these questions is that I have run into a few devices where 
> this code 'crashes' with (randomly) one of the two following errors. Are 
> you able to comment on this?
>
>
>    1. queueBuffer: slot 2 is current! 
>    2. dequeueBuffer: buffer 0 is both FREE and current! 
>    
>
>
> Many thanks,
> -Nathan Morse
>
>
> On Wednesday, November 23, 2011 9:17:28 AM UTC-8, Romain Guy (Google) 
> wrote:
>>
>> GLSurfaceView handles GL setup for you, which TextureView will not do. A 
>> TextureView can be used as the native window when you create an EGL 
>> surface. Here is an example (the interesting part is the call 
>> to eglCreateWindowSurface()):
>>
>>     @Override
>>     public void onSurfaceTextureAvailable(SurfaceTexture surface, int 
>> width, int height) {
>>         mRenderThread = new RenderThread(getResources(), surface);
>>         mRenderThread.start();
>>     }
>>
>>     private static class RenderThread extends Thread {
>>         private static final String LOG_TAG = "GLTextureView";
>>
>>         static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
>>         static final int EGL_OPENGL_ES2_BIT = 4;
>>
>>         private volatile boolean mFinished;
>>
>>         private final Resources mResources;
>>         private final SurfaceTexture mSurface;
>>         
>>         private EGL10 mEgl;
>>         private EGLDisplay mEglDisplay;
>>         private EGLConfig mEglConfig;
>>         private EGLContext mEglContext;
>>         private EGLSurface mEglSurface;
>>         private GL mGL;
>>
>>         RenderThread(Resources resources, SurfaceTexture surface) {
>>             mResources = resources;
>>             mSurface = surface;
>>         }
>>
>>         private static final String sSimpleVS =
>>                 "attribute vec4 position;\n" +
>>                 "attribute vec2 texCoords;\n" +
>>                 "varying vec2 outTexCoords;\n" +
>>                 "\nvoid main(void) {\n" +
>>                 "    outTexCoords = texCoords;\n" +
>>                 "    gl_Position = position;\n" +
>>                 "}\n\n";
>>         private static final String sSimpleFS =
>>                 "precision mediump float;\n\n" +
>>                 "varying vec2 outTexCoords;\n" +
>>                 "uniform sampler2D texture;\n" +
>>                 "\nvoid main(void) {\n" +
>>                 "    gl_FragColor = texture2D(texture, outTexCoords);\n" +
>>                 "}\n\n";
>>
>>         private static final int FLOAT_SIZE_BYTES = 4;
>>         private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 
>> * FLOAT_SIZE_BYTES;
>>         private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
>>         private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
>>         private final float[] mTriangleVerticesData = {
>>                 // X, Y, Z, U, V
>>                 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
>>                  1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
>>                 -1.0f,  1.0f, 0.0f, 0.0f, 1.0f,
>>                  1.0f,  1.0f, 0.0f, 1.0f, 1.0f,
>>         };
>>
>>         @Override
>>         public void run() {
>>             initGL();
>>             
>>             FloatBuffer triangleVertices = 
>> ByteBuffer.allocateDirect(mTriangleVerticesData.length
>>                     * 
>> FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
>>             triangleVertices.put(mTriangleVerticesData).position(0);
>>
>>             int texture = loadTexture(R.drawable.large_photo);
>>             int program = buildProgram(sSimpleVS, sSimpleFS);
>>
>>             int attribPosition = glGetAttribLocation(program, "position");
>>             checkGlError();
>>
>>             int attribTexCoords = glGetAttribLocation(program, 
>> "texCoords");
>>             checkGlError();
>>
>>             int uniformTexture = glGetUniformLocation(program, "texture");
>>             checkGlError();
>>
>>             glBindTexture(GL_TEXTURE_2D, texture);
>>             checkGlError();
>>
>>             glUseProgram(program);
>>             checkGlError();
>>
>>             glEnableVertexAttribArray(attribPosition);
>>             checkGlError();
>>
>>             glEnableVertexAttribArray(attribTexCoords);
>>             checkGlError();
>>
>>             glUniform1i(uniformTexture, texture);
>>             checkGlError();
>>             
>>             while (!mFinished) {
>>                 checkCurrent();
>>
>>                 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
>>                 checkGlError();
>>
>>                 glClear(GL_COLOR_BUFFER_BIT);
>>                 checkGlError();
>>
>>                 // drawQuad
>>                 
>> triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
>>                 glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
>>                         TRIANGLE_VERTICES_DATA_STRIDE_BYTES, 
>> triangleVertices);
>>
>>                 
>> triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
>>                 glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
>>                         TRIANGLE_VERTICES_DATA_STRIDE_BYTES, 
>> triangleVertices);
>>
>>                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
>>
>>                 if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
>>                     throw new RuntimeException("Cannot swap buffers");
>>                 }
>>                 checkEglError();
>>
>>                 try {
>>                     Thread.sleep(2000);
>>                 } catch (InterruptedException e) {
>>                     // Ignore
>>                 }
>>             }
>>
>>             finishGL();
>>         }
>>
>>         private int loadTexture(int resource) {
>>             int[] textures = new int[1];
>>
>>             glActiveTexture(GL_TEXTURE0);
>>             glGenTextures(1, textures, 0);
>>             checkGlError();
>>
>>             int texture = textures[0];
>>             glBindTexture(GL_TEXTURE_2D, texture);
>>             checkGlError();
>>             
>>             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
>> GL_LINEAR);
>>             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
>> GL_LINEAR);
>>
>>             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
>> GL_CLAMP_TO_EDGE);
>>             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
>> GL_CLAMP_TO_EDGE);
>>
>>             Bitmap bitmap = BitmapFactory.decodeResource(mResources, 
>> resource);
>>
>>             GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, 
>> GL_UNSIGNED_BYTE, 0);
>>             checkGlError();
>>
>>             bitmap.recycle();
>>
>>             return texture;
>>         }
>>         
>>         private int buildProgram(String vertex, String fragment) {
>>             int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
>>             if (vertexShader == 0) return 0;
>>
>>             int fragmentShader = buildShader(fragment, 
>> GL_FRAGMENT_SHADER);
>>             if (fragmentShader == 0) return 0;
>>
>>             int program = glCreateProgram();
>>             glAttachShader(program, vertexShader);
>>             checkGlError();
>>
>>             glAttachShader(program, fragmentShader);
>>             checkGlError();
>>
>>             glLinkProgram(program);
>>             checkGlError();
>>
>>             int[] status = new int[1];
>>             glGetProgramiv(program, GL_LINK_STATUS, status, 0);
>>             if (status[0] != GL_TRUE) {
>>                 String error = glGetProgramInfoLog(program);
>>                 Log.d(LOG_TAG, "Error while linking program:\n" + error);
>>                 glDeleteShader(vertexShader);
>>                 glDeleteShader(fragmentShader);
>>                 glDeleteProgram(program);
>>                 return 0;
>>             }
>>
>>             return program;
>>         }
>>         
>>         private int buildShader(String source, int type) {
>>             int shader = glCreateShader(type);
>>
>>             glShaderSource(shader, source);
>>             checkGlError();
>>
>>             glCompileShader(shader);
>>             checkGlError();
>>
>>             int[] status = new int[1];
>>             glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
>>             if (status[0] != GL_TRUE) {
>>                 String error = glGetShaderInfoLog(shader);
>>                 Log.d(LOG_TAG, "Error while compiling shader:\n" + error);
>>                 glDeleteShader(shader);
>>                 return 0;
>>             }
>>             
>>             return shader;
>>         }
>>
>>         private void checkEglError() {
>>             int error = mEgl.eglGetError();
>>             if (error != EGL10.EGL_SUCCESS) {
>>                 Log.w(LOG_TAG, "EGL error = 0x" + 
>> Integer.toHexString(error));
>>             }
>>         }
>>
>>         private void checkGlError() {
>>             int error = glGetError();
>>             if (error != GL_NO_ERROR) {
>>                 Log.w(LOG_TAG, "GL error = 0x" + 
>> Integer.toHexString(error));
>>             }
>>         }
>>
>>         private void finishGL() {
>>             mEgl.eglDestroyContext(mEglDisplay, mEglContext);
>>             mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
>>         }
>>
>>         private void checkCurrent() {
>>             if (!mEglContext.equals(mEgl.eglGetCurrentContext()) ||
>>                     
>> !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
>>                 if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, 
>> mEglSurface, mEglContext)) {
>>                     throw new RuntimeException("eglMakeCurrent failed "
>>                             + 
>> GLUtils.getEGLErrorString(mEgl.eglGetError()));
>>                 }
>>             }
>>         }
>>         
>>         private void initGL() {
>>             mEgl = (EGL10) EGLContext.getEGL();
>>
>>             mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
>>             if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
>>                 throw new RuntimeException("eglGetDisplay failed "
>>                         + GLUtils.getEGLErrorString(mEgl.eglGetError()));
>>             }
>>             
>>             int[] version = new int[2];
>>             if (!mEgl.eglInitialize(mEglDisplay, version)) {
>>                 throw new RuntimeException("eglInitialize failed " +
>>                         GLUtils.getEGLErrorString(mEgl.eglGetError()));
>>             }
>>
>>             mEglConfig = chooseEglConfig();
>>             if (mEglConfig == null) {
>>                 throw new RuntimeException("eglConfig not initialized");
>>             }
>>             
>>             mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
>>
>>             mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, 
>> mEglConfig, mSurface, null);
>>
>>             if (mEglSurface == null || mEglSurface == 
>> EGL10.EGL_NO_SURFACE) {
>>                 int error = mEgl.eglGetError();
>>                 if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
>>                     Log.e(LOG_TAG, "createWindowSurface returned 
>> EGL_BAD_NATIVE_WINDOW.");
>>                     return;
>>                 }
>>                 throw new RuntimeException("createWindowSurface failed "
>>                         + GLUtils.getEGLErrorString(error));
>>             }
>>
>>             if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, 
>> mEglSurface, mEglContext)) {
>>                 throw new RuntimeException("eglMakeCurrent failed "
>>                         + GLUtils.getEGLErrorString(mEgl.eglGetError()));
>>             }
>>
>>             mGL = mEglContext.getGL();
>>         }
>>         
>>
>>         EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, 
>> EGLConfig eglConfig) {
>>             int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, 
>> EGL10.EGL_NONE };
>>             return egl.eglCreateContext(eglDisplay, eglConfig, 
>> EGL10.EGL_NO_CONTEXT, attrib_list);            
>>         }
>>
>>         private EGLConfig chooseEglConfig() {
>>             int[] configsCount = new int[1];
>>             EGLConfig[] configs = new EGLConfig[1];
>>             int[] configSpec = getConfig();
>>             if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 
>> 1, configsCount)) {
>>                 throw new IllegalArgumentException("eglChooseConfig 
>> failed " +
>>                         GLUtils.getEGLErrorString(mEgl.eglGetError()));
>>             } else if (configsCount[0] > 0) {
>>                 return configs[0];
>>             }
>>             return null;
>>         }
>>         
>>         private int[] getConfig() {
>>             return new int[] {
>>                     EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
>>                     EGL10.EGL_RED_SIZE, 8,
>>                     EGL10.EGL_GREEN_SIZE, 8,
>>                     EGL10.EGL_BLUE_SIZE, 8,
>>                     EGL10.EGL_ALPHA_SIZE, 8,
>>                     EGL10.EGL_DEPTH_SIZE, 0,
>>                     EGL10.EGL_STENCIL_SIZE, 0,
>>                     EGL10.EGL_NONE
>>             };
>>         }
>>
>>         void finish() {
>>             mFinished = true;
>>         }
>>     }
>>
>> On Wed, Nov 23, 2011 at 8:54 AM, plafayette <pierre.l...@gmail.com 
>> <javascript:>> wrote:
>>
>>> The TextureView documentation states that it can be used to render
>>> OpenGL content.
>>>
>>> In the blog post announcing TextureView, it states:
>>>
>>> A TextureView can just as easily be used to embed an OpenGL scene in
>>> your application. As of Android 4.0, eglCreateWindowSurface() can be
>>> used to render into a SurfaceTexture object.
>>>
>>> Which seems to imply that to use TextureView instead of GLSurfaceView,
>>> one would have to do all the EGL setup themselves and manage the
>>> EGLContext and the threading (since GLSurfaceView maintains a
>>> GLThread). There doesn't seem to be any sample code in the Android 4.0
>>> SDK that demonstrates how the "TextureView can just as easily be used
>>> to embed an OpenGL scene". TextureView seems to plug in more cleanly
>>> to the Camera preview (setPreviewTexture) and MediaPlayer
>>> (setSurface).
>>>
>>> Is it possible to use GLSurfaceView in conjunction with TextureView by
>>> using GLSurfaceView.setEGLWindowSurfaceFactory to make it render to
>>> the TextureView's SurfaceTexture?
>>>
>>> Again, it would be nice if there were some sample code.
>>>
>>> p.s. Posted on stackoverflow.com as well. Feel free to answer:
>>>
>>> http://stackoverflow.com/questions/8231978/how-to-replace-glsurfaceview-with-textureview-in-android-ice-cream-sandwich
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Android Developers" group.
>>> To post to this group, send email to android-d...@googlegroups.com 
>>> <javascript:>
>>> To unsubscribe from this group, send email to
>>> android-developers+unsubscr...@googlegroups.com <javascript:>
>>> For more options, visit this group at
>>> http://groups.google.com/group/android-developers?hl=en
>>>
>>
>>
>>
>> -- 
>> Romain Guy
>> Android framework engineer
>> roma...@android.com <javascript:>
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"Android Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to android-developers+unsubscr...@googlegroups.com.
To post to this group, send email to android-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/android-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/android-developers/858d9852-91fb-4c4c-ae2d-52b4931d21c1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to