Chromium Code Reviews| 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; |
| + } |
| +} |