From 2ed62b3c9b8218ead78861b68465b63be13baf3a Mon Sep 17 00:00:00 2001 From: Magnus Jedvert Date: Wed, 11 Apr 2018 14:25:14 +0200 Subject: [PATCH] Android: Allow construction of GlTextureFrameBuffer from non-OpenGL thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Sami Kalliomäki Cr-Commit-Position: refs/heads/master@{#22835} --- sdk/android/api/org/webrtc/EglRenderer.java | 11 ++----- .../api/org/webrtc/GlTextureFrameBuffer.java | 29 +++++++++++-------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/sdk/android/api/org/webrtc/EglRenderer.java b/sdk/android/api/org/webrtc/EglRenderer.java index c6e98123aa..dccd11105b 100644 --- a/sdk/android/api/org/webrtc/EglRenderer.java +++ b/sdk/android/api/org/webrtc/EglRenderer.java @@ -131,7 +131,8 @@ public class EglRenderer implements VideoRenderer.Callbacks, VideoSink { private long renderSwapBufferTimeNs; // Used for bitmap capturing. - @Nullable private GlTextureFrameBuffer bitmapTextureFramebuffer; + private final GlTextureFrameBuffer bitmapTextureFramebuffer = + new GlTextureFrameBuffer(GLES20.GL_RGBA); private final Runnable logStatisticsRunnable = new Runnable() { @Override @@ -233,10 +234,7 @@ public class EglRenderer implements VideoRenderer.Callbacks, VideoSink { drawer = null; } frameDrawer.release(); - if (bitmapTextureFramebuffer != null) { - bitmapTextureFramebuffer.release(); - bitmapTextureFramebuffer = null; - } + bitmapTextureFramebuffer.release(); if (eglBase != null) { logD("eglBase detach and release."); eglBase.detachCurrent(); @@ -637,9 +635,6 @@ public class EglRenderer implements VideoRenderer.Callbacks, VideoSink { continue; } - if (bitmapTextureFramebuffer == null) { - bitmapTextureFramebuffer = new GlTextureFrameBuffer(GLES20.GL_RGBA); - } bitmapTextureFramebuffer.setSize(scaledWidth, scaledHeight); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, bitmapTextureFramebuffer.getFrameBufferId()); diff --git a/sdk/android/api/org/webrtc/GlTextureFrameBuffer.java b/sdk/android/api/org/webrtc/GlTextureFrameBuffer.java index 164dff29cb..b906fe56e0 100644 --- a/sdk/android/api/org/webrtc/GlTextureFrameBuffer.java +++ b/sdk/android/api/org/webrtc/GlTextureFrameBuffer.java @@ -15,13 +15,13 @@ 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. + * 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 frameBufferId; - private final int textureId; private final int pixelFormat; + private int frameBufferId; + private int textureId; private int width; private int height; @@ -39,16 +39,8 @@ public class GlTextureFrameBuffer { default: throw new IllegalArgumentException("Invalid pixel format: " + pixelFormat); } - - // Create texture. - textureId = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D); this.width = 0; this.height = 0; - - // Create framebuffer object. - final int frameBuffers[] = new int[1]; - GLES20.glGenFramebuffers(1, frameBuffers, 0); - frameBufferId = frameBuffers[0]; } /** @@ -57,7 +49,7 @@ public class GlTextureFrameBuffer { * 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) { + if (width <= 0 || height <= 0) { throw new IllegalArgumentException("Invalid size: " + width + "x" + height); } if (width == this.width && height == this.height) { @@ -65,6 +57,15 @@ public class GlTextureFrameBuffer { } 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); @@ -96,10 +97,12 @@ public class GlTextureFrameBuffer { 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; } @@ -110,7 +113,9 @@ public class GlTextureFrameBuffer { */ 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; }