Index: talk/app/webrtc/java/android/org/webrtc/GlTextureFrameBuffer.java |
diff --git a/talk/app/webrtc/java/android/org/webrtc/GlTextureFrameBuffer.java b/talk/app/webrtc/java/android/org/webrtc/GlTextureFrameBuffer.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fd52c37eb4c085ae374ece167cf26e921b57b032 |
--- /dev/null |
+++ b/talk/app/webrtc/java/android/org/webrtc/GlTextureFrameBuffer.java |
@@ -0,0 +1,142 @@ |
+/* |
+ * libjingle |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions are met: |
+ * |
+ * 1. Redistributions of source code must retain the above copyright notice, |
+ * this list of conditions and the following disclaimer. |
+ * 2. Redistributions in binary form must reproduce the above copyright notice, |
+ * this list of conditions and the following disclaimer in the documentation |
+ * and/or other materials provided with the distribution. |
+ * 3. The name of the author may not be used to endorse or promote products |
+ * derived from this software without specific prior written permission. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ */ |
+ |
+package org.webrtc; |
+ |
+import android.opengl.GLES20; |
+ |
+/** |
+ * Helper class for handling OpenGL framebuffer with only color attachment and no depth or stencil |
+ * buffer. Intended for simple tasks such as texture copy, texture downscaling, and texture color |
+ * conversion. |
+ */ |
+// TODO(magjed): Add unittests for this class. |
hbos
2015/09/18 11:27:35
Would be nice, yes. Doesn't have to be in this CL.
|
+public class GlTextureFrameBuffer { |
+ private final int frameBufferId; |
+ private final int textureId; |
+ private final int pixelFormat; |
+ private int width; |
+ private int height; |
+ |
+ /** |
+ * Generate texture and framebuffer resources. An EGLContext must be bound on the current thread |
hbos
2015/09/18 11:27:35
Here and other methods assuming its not expensive:
magjed_webrtc
2015/09/18 14:32:03
Hmm, yes maybe. But when this happens, an exceptio
|
+ * when calling this function. The framebuffer is not complete until setSize() is called. |
+ */ |
+ public GlTextureFrameBuffer(int pixelFormat) { |
+ switch (pixelFormat) { |
+ case GLES20.GL_LUMINANCE: |
+ case GLES20.GL_RGB: |
+ case GLES20.GL_RGBA: |
+ this.pixelFormat = pixelFormat; |
+ break; |
+ default: |
+ throw new IllegalArgumentException("Invalid pixel format: " + pixelFormat); |
+ } |
+ |
+ textureId = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D); |
+ this.width = 0; |
+ this.height = 0; |
+ |
+ // Create framebuffer object and bind it. |
+ final int frameBuffers[] = new int[1]; |
+ GLES20.glGenFramebuffers(1, frameBuffers, 0); |
+ frameBufferId = frameBuffers[0]; |
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId); |
+ GlUtil.checkNoGLES2Error("Generate framebuffer"); |
+ |
+ // Attach the texture to the framebuffer as color attachment. |
+ GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, |
+ GLES20.GL_TEXTURE_2D, textureId, 0); |
+ GlUtil.checkNoGLES2Error("Attach texture to framebuffer"); |
+ |
+ // Restore normal framebuffer. |
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); |
+ } |
+ |
+ /** |
+ * (Re)allocate texture. Will do nothing if the requested size equals the current size. An |
+ * EGLContext must be bound on the current thread when calling this function. Must be called at |
+ * least once before using the framebuffer. May be called multiple times to change size. |
+ */ |
+ public void setSize(int width, int height) { |
+ if (width == 0 || height == 0) { |
+ throw new IllegalArgumentException("Invalid size: " + width + "x" + height); |
+ } |
+ if (width == this.width && height == this.height) { |
+ return; |
+ } |
+ this.width = width; |
+ this.height = height; |
+ |
+ // Bind our framebuffer. |
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId); |
+ GlUtil.checkNoGLES2Error("glBindFramebuffer"); |
+ |
+ // Allocate texture. |
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE0); |
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); |
+ GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, pixelFormat, width, height, 0, pixelFormat, |
+ GLES20.GL_UNSIGNED_BYTE, null); |
+ |
+ // Check that the framebuffer is in a good state. |
+ final int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); |
+ if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) { |
+ throw new IllegalStateException("Framebuffer not complete, status: " + status); |
+ } |
+ |
+ // Restore normal framebuffer. |
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); |
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); |
+ } |
+ |
+ public int getWidth() { |
+ return width; |
+ } |
+ |
+ public int getHeight() { |
+ return height; |
+ } |
+ |
+ public int getFrameBufferId() { |
+ return frameBufferId; |
+ } |
+ |
+ public int getTextureId() { |
+ return textureId; |
+ } |
+ |
+ /** |
+ * Release texture and framebuffer. An EGLContext must be bound on the current thread when calling |
+ * this function. This object should not be used after this call. |
+ */ |
+ public void release() { |
+ GLES20.glDeleteTextures(1, new int[] {textureId}, 0); |
+ GLES20.glDeleteFramebuffers(1, new int[] {frameBufferId}, 0); |
+ width = 0; |
+ height = 0; |
+ } |
+} |