It is definitely an option, that's what SurfaceTexture is for. It's very simple:
Create an OpenGL context Generate an OpenGL texture name Create a SurfaceTexture with the texture name Pass the SurfaceTexture to Camera Listen for updates On SurfaceTexture update, draw the texture with OpenGL using the shader you want Simple :) On Thu, Dec 22, 2011 at 11:59 AM, Brad Grimm <[email protected]> wrote: > Thanks Romain. I really just want to swap out the pixel shader on the > SurfaceTexture's OpenGL texture so I can do some filtering on the > camera preview. But it sounds like that isn't an option. I have > used ColorMatrixFilters on the view itself and they work quite well, > just not powerful enough for what I want to do. > > On Dec 21, 8:18 pm, Romain Guy <[email protected]> wrote: >> 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" <[email protected]> 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-surfac... >> > On Nov 23, 11:45 am, plafayette <[email protected]> wrote: >> > > Thanks for the quick response Romain and the sample code! Will give it >> > > a try. >> >> > > On Nov 23, 12:17 pm, Romain Guy <[email protected]> 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; >> > > > } >> >> ... >> >> 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 [email protected] > To unsubscribe from this group, send email to > [email protected] > For more options, visit this group at > http://groups.google.com/group/android-developers?hl=en -- Romain Guy Android framework engineer [email protected] -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en

