mirror of https://github.com/NekoX-Dev/NekoX.git
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;
|
|
}
|
|
}
|