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:
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user