
This CL makes it possible to create a GlTextureFrameBuffer from any thread. The actual GL resources will be allocated the first time setSize() is called. The purpose is to be able to use 'final' variables more often for this class and avoid @Nullable annotations. Bug: None Change-Id: I350304bcd33fd674990254df37a615995972f322 Reviewed-on: https://webrtc-review.googlesource.com/69241 Commit-Queue: Magnus Jedvert <magjed@webrtc.org> Reviewed-by: Sami Kalliomäki <sakal@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22835}
123 lines
4.2 KiB
Java
123 lines
4.2 KiB
Java
/*
|
|
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
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. This class is not thread safe and must be used by a thread with an active GL context.
|
|
*/
|
|
// TODO(magjed): Add unittests for this class.
|
|
public class GlTextureFrameBuffer {
|
|
private final int pixelFormat;
|
|
private int frameBufferId;
|
|
private int textureId;
|
|
private int width;
|
|
private int height;
|
|
|
|
/**
|
|
* Generate texture and framebuffer resources. An EGLContext must be bound on the current thread
|
|
* 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);
|
|
}
|
|
this.width = 0;
|
|
this.height = 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;
|
|
// Lazy allocation the first time setSize() is called.
|
|
if (textureId == 0) {
|
|
textureId = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D);
|
|
}
|
|
if (frameBufferId == 0) {
|
|
final int frameBuffers[] = new int[1];
|
|
GLES20.glGenFramebuffers(1, frameBuffers, 0);
|
|
frameBufferId = frameBuffers[0];
|
|
}
|
|
|
|
// 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);
|
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
|
|
GlUtil.checkNoGLES2Error("GlTextureFrameBuffer setSize");
|
|
|
|
// Attach the texture to the framebuffer as color attachment.
|
|
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId);
|
|
GLES20.glFramebufferTexture2D(
|
|
GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, textureId, 0);
|
|
|
|
// 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);
|
|
}
|
|
|
|
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
public int getWidth() {
|
|
return width;
|
|
}
|
|
|
|
public int getHeight() {
|
|
return height;
|
|
}
|
|
|
|
/** Gets the OpenGL frame buffer id. This value is only valid after setSize() has been called. */
|
|
public int getFrameBufferId() {
|
|
return frameBufferId;
|
|
}
|
|
|
|
/** Gets the OpenGL texture id. This value is only valid after setSize() has been called. */
|
|
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);
|
|
textureId = 0;
|
|
GLES20.glDeleteFramebuffers(1, new int[] {frameBufferId}, 0);
|
|
frameBufferId = 0;
|
|
width = 0;
|
|
height = 0;
|
|
}
|
|
}
|