There's no need to get the camera preview out of SurfaceTexture. The whole point of SurfaceTexture is to let a producer like the camera render into an OpenGL texture. Just use SurfaceTexture.
To draw on top of TextureView, just add another view on top of it. On Dec 21, 2011 9:35 PM, "Brad Grimm" <sna...@gmail.com> wrote: > Thanks for the post, it has been really helpful. > > But say I want to draw on top of a SurfaceTexture that is connected to > a Camera via setPreviewTexture. I can get the SurfaceTexture by a > SurfaceTextureListener. But if I just try to use > eglCreateWindowSurface & eglMakeCurrent it fails due to the surface > already being connected. > 1) Is it possible to draw on this surface at all? Or does binding it > to the camera make it impossible to do that. > 2) If it isn't possible. Can the surface be used (or copied) quickly > to an OpenGL texture and used in a separate surface? If so how? > 3) If not, what would be the fastest way to get the camera preview out > of a SurfaceTexture and into OpenGL? > P.S. - I too followed suit and posted to StackOverflow: > > http://stackoverflow.com/questions/8582090/possible-to-draw-on-surfacetexture-attached-to-camera > On Nov 23, 11:45 am, plafayette <pierre.lafaye...@gmail.com> wrote: > > Thanks for the quick response Romain and the sample code! Will give it > > a try. > > > > On Nov 23, 12:17 pm, Romain Guy <romain...@android.com> wrote: > > > > > > > > > > > > > > > > > GLSurfaceView handles GL setup for you, whichTextureViewwill not do. A > > >TextureViewcan 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)) { > > > ... > > > > read more ยป > > -- > You received this message because you are subscribed to the Google > Groups "Android Developers" group. > To post to this group, send email to android-developers@googlegroups.com > To unsubscribe from this group, send email to > android-developers+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/android-developers?hl=en > -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en