Android GlRectDrawer: Add test for OES texture rendering

BUG=webrtc:4742
R=hbos@webrtc.org

Review URL: https://codereview.webrtc.org/1367913003 .

Cr-Commit-Position: refs/heads/master@{#10109}
This commit is contained in:
Magnus Jedvert
2015-09-29 16:40:02 +02:00
parent 1d640e53bd
commit 24b52f8322

View File

@ -28,22 +28,25 @@ package org.webrtc;
import android.test.ActivityTestCase; import android.test.ActivityTestCase;
import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.MediumTest;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Random; import java.util.Random;
import android.graphics.SurfaceTexture;
import android.opengl.EGL14; import android.opengl.EGL14;
import android.opengl.Matrix; import android.opengl.EGLContext;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.opengl.Matrix;
public class GlRectDrawerTest extends ActivityTestCase { public final class GlRectDrawerTest extends ActivityTestCase {
// Resolution of the test image. // Resolution of the test image.
private static final int WIDTH = 16; private static final int WIDTH = 16;
private static final int HEIGHT = 16; private static final int HEIGHT = 16;
// Seed for random pixel creation. // Seed for random pixel creation.
private static final int SEED = 42; private static final int SEED = 42;
// When comparing pixels, allow some slack for float arithmetic and integer rounding. // When comparing pixels, allow some slack for float arithmetic and integer rounding.
final float MAX_DIFF = 1.0f; private static final float MAX_DIFF = 1.0f;
private static float normalizedByte(byte b) { private static float normalizedByte(byte b) {
return (b & 0xFF) / 255.0f; return (b & 0xFF) / 255.0f;
@ -95,7 +98,7 @@ public class GlRectDrawerTest extends ActivityTestCase {
} }
@SmallTest @SmallTest
public void testRgbRendering() throws Exception { public void testRgbRendering() {
// Create EGL base with a pixel buffer as display output. // Create EGL base with a pixel buffer as display output.
final EglBase eglBase = new EglBase(EGL14.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER); final EglBase eglBase = new EglBase(EGL14.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER);
eglBase.createPbufferSurface(WIDTH, HEIGHT); eglBase.createPbufferSurface(WIDTH, HEIGHT);
@ -134,7 +137,7 @@ public class GlRectDrawerTest extends ActivityTestCase {
} }
@SmallTest @SmallTest
public void testYuvRendering() throws Exception { public void testYuvRendering() {
// Create EGL base with a pixel buffer as display output. // Create EGL base with a pixel buffer as display output.
EglBase eglBase = new EglBase(EGL14.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER); EglBase eglBase = new EglBase(EGL14.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER);
eglBase.createPbufferSurface(WIDTH, HEIGHT); eglBase.createPbufferSurface(WIDTH, HEIGHT);
@ -206,4 +209,108 @@ public class GlRectDrawerTest extends ActivityTestCase {
GLES20.glDeleteTextures(3, yuvTextures, 0); GLES20.glDeleteTextures(3, yuvTextures, 0);
eglBase.release(); eglBase.release();
} }
/**
* The purpose here is to test GlRectDrawer.oesDraw(). Unfortunately, there is no easy way to
* create an OES texture, which is needed for input to oesDraw(). Most of the test is concerned
* with creating OES textures in the following way:
* - Create SurfaceTexture with help from SurfaceTextureHelper.
* - Create an EglBase with the SurfaceTexture as EGLSurface.
* - Upload RGB texture with known content.
* - Draw the RGB texture onto the EglBase with the SurfaceTexture as target.
* - Wait for an OES texture to be produced.
* The actual oesDraw() test is this:
* - Create an EglBase with a pixel buffer as target.
* - Render the OES texture onto the pixel buffer.
* - Read back the pixel buffer and compare it with the known RGB data.
*/
@MediumTest
public void testOesRendering() throws InterruptedException {
/**
* Stub class to convert RGB ByteBuffers to OES textures by drawing onto a SurfaceTexture.
*/
class StubOesTextureProducer {
private final EglBase eglBase;
private final GlRectDrawer drawer;
private final int rgbTexture;
public StubOesTextureProducer(
EGLContext sharedContext, SurfaceTexture surfaceTexture, int width, int height) {
eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN);
surfaceTexture.setDefaultBufferSize(width, height);
eglBase.createSurface(surfaceTexture);
assertEquals(eglBase.surfaceWidth(), width);
assertEquals(eglBase.surfaceHeight(), height);
drawer = new GlRectDrawer();
eglBase.makeCurrent();
rgbTexture = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D);
}
public void draw(ByteBuffer rgbPlane) {
eglBase.makeCurrent();
// Upload RGB data to texture.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, rgbTexture);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, WIDTH,
HEIGHT, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, rgbPlane);
// Draw the RGB data onto the SurfaceTexture.
final float[] identityMatrix = new float[16];
Matrix.setIdentityM(identityMatrix, 0);
drawer.drawRgb(rgbTexture, identityMatrix);
eglBase.swapBuffers();
}
public void release() {
eglBase.makeCurrent();
drawer.release();
GLES20.glDeleteTextures(1, new int[] {rgbTexture}, 0);
eglBase.release();
}
}
// Create EGL base with a pixel buffer as display output.
final EglBase eglBase = new EglBase(EGL14.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER);
eglBase.createPbufferSurface(WIDTH, HEIGHT);
// Create resources for generating OES textures.
final SurfaceTextureHelper surfaceTextureHelper =
new SurfaceTextureHelper(eglBase.getContext());
final StubOesTextureProducer oesProducer = new StubOesTextureProducer(
eglBase.getContext(), surfaceTextureHelper.getSurfaceTexture(), WIDTH, HEIGHT);
final SurfaceTextureHelperTest.MockTextureListener listener =
new SurfaceTextureHelperTest.MockTextureListener();
surfaceTextureHelper.setListener(listener);
// Create RGB byte buffer plane with random content.
final ByteBuffer rgbPlane = ByteBuffer.allocateDirect(WIDTH * HEIGHT * 3);
final Random random = new Random(SEED);
random.nextBytes(rgbPlane.array());
// Draw the frame and block until an OES texture is delivered.
oesProducer.draw(rgbPlane);
listener.waitForNewFrame();
// Real test starts here.
// Draw the OES texture on the pixel buffer.
eglBase.makeCurrent();
final GlRectDrawer drawer = new GlRectDrawer();
drawer.drawOes(listener.oesTextureId, listener.transformMatrix);
// Download the pixels in the pixel buffer as RGBA. Not all platforms support RGB, e.g. Nexus 9.
final ByteBuffer rgbaData = ByteBuffer.allocateDirect(WIDTH * HEIGHT * 4);
GLES20.glReadPixels(0, 0, WIDTH, HEIGHT, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, rgbaData);
GlUtil.checkNoGLES2Error("glReadPixels");
// Assert rendered image is pixel perfect to source RGB.
assertEquals(WIDTH, HEIGHT, stripAlphaChannel(rgbaData), rgbPlane);
drawer.release();
surfaceTextureHelper.returnTextureFrame();
oesProducer.release();
surfaceTextureHelper.disconnect();
eglBase.release();
}
} }