Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.graphics.cts;
     18 
     19 import static org.junit.Assert.assertEquals;
     20 import static android.opengl.EGL14.*;
     21 
     22 import android.graphics.SurfaceTexture;
     23 import android.opengl.EGL14;
     24 import android.opengl.EGLConfig;
     25 import android.opengl.EGLContext;
     26 import android.opengl.EGLDisplay;
     27 import android.opengl.EGLSurface;
     28 import android.opengl.GLES20;
     29 import android.support.test.filters.SmallTest;
     30 import android.view.Surface;
     31 import android.util.Log;
     32 
     33 import org.junit.Before;
     34 import org.junit.Test;
     35 import org.junit.runner.RunWith;
     36 import org.junit.runners.BlockJUnit4ClassRunner;
     37 
     38 
     39 @SmallTest
     40 @RunWith(BlockJUnit4ClassRunner.class)
     41 public class ANativeWindowTest {
     42 
     43     static {
     44         System.loadLibrary("ctsgraphics_jni");
     45     }
     46 
     47     private static final String TAG = ANativeWindowTest.class.getSimpleName();
     48     private static final boolean DEBUG = false;
     49 
     50     private EGLDisplay mEglDisplay = EGL_NO_DISPLAY;
     51     private EGLConfig mEglConfig = null;
     52     private EGLSurface mEglPbuffer = EGL_NO_SURFACE;
     53     private EGLContext mEglContext = EGL_NO_CONTEXT;
     54 
     55     @Before
     56     public void setup() throws Throwable {
     57         mEglDisplay = EGL14.eglGetDisplay(EGL_DEFAULT_DISPLAY);
     58         if (mEglDisplay == EGL_NO_DISPLAY) {
     59             throw new RuntimeException("no EGL display");
     60         }
     61         int[] major = new int[1];
     62         int[] minor = new int[1];
     63         if (!EGL14.eglInitialize(mEglDisplay, major, 0, minor, 0)) {
     64             throw new RuntimeException("error in eglInitialize");
     65         }
     66 
     67         // If we could rely on having EGL_KHR_surfaceless_context and EGL_KHR_context_no_config, we
     68         // wouldn't have to create a config or pbuffer at all.
     69 
     70         int[] numConfigs = new int[1];
     71         EGLConfig[] configs = new EGLConfig[1];
     72         if (!EGL14.eglChooseConfig(mEglDisplay,
     73                 new int[] {
     74                     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
     75                     EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
     76                     EGL_NONE},
     77                 0, configs, 0, 1, numConfigs, 0)) {
     78             throw new RuntimeException("eglChooseConfig failed");
     79         }
     80         mEglConfig = configs[0];
     81 
     82         mEglPbuffer = EGL14.eglCreatePbufferSurface(mEglDisplay, mEglConfig,
     83                 new int[] {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}, 0);
     84         if (mEglPbuffer == EGL_NO_SURFACE) {
     85             throw new RuntimeException("eglCreatePbufferSurface failed");
     86         }
     87 
     88         mEglContext = EGL14.eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
     89                 new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}, 0);
     90         if (mEglContext == EGL_NO_CONTEXT) {
     91             throw new RuntimeException("eglCreateContext failed");
     92         }
     93 
     94         if (!EGL14.eglMakeCurrent(mEglDisplay, mEglPbuffer, mEglPbuffer, mEglContext)) {
     95             throw new RuntimeException("eglMakeCurrent failed");
     96         }
     97     }
     98 
     99     @Test
    100     public void testSetBuffersTransform() {
    101         final int MIRROR_HORIZONTAL_BIT = 0x01;
    102         final int MIRROR_VERTICAL_BIT   = 0x02;
    103         final int ROTATE_90_BIT         = 0x04;
    104         final int ALL_TRANSFORM_BITS    =
    105                 MIRROR_HORIZONTAL_BIT | MIRROR_VERTICAL_BIT | ROTATE_90_BIT;
    106 
    107         // 4x4 GL-style matrices, as returned by SurfaceTexture#getTransformMatrix(). Note they're
    108         // transforming texture coordinates ([0,1]^2), so the origin for the transforms is
    109         // (0.5, 0.5), not (0,0).
    110         final float[] MIRROR_HORIZONTAL_MATRIX = new float[] {
    111             -1.0f,  0.0f,  0.0f,  0.0f,
    112              0.0f,  1.0f,  0.0f,  0.0f,
    113              0.0f,  0.0f,  1.0f,  0.0f,
    114              1.0f,  0.0f,  0.0f,  1.0f,
    115         };
    116         final float[] MIRROR_VERTICAL_MATRIX = new float[] {
    117              1.0f,  0.0f,  0.0f,  0.0f,
    118              0.0f, -1.0f,  0.0f,  0.0f,
    119              0.0f,  0.0f,  1.0f,  0.0f,
    120              0.0f,  1.0f,  0.0f,  1.0f,
    121         };
    122         final float[] ROTATE_90_MATRIX = new float[] {
    123              0.0f,  1.0f,  0.0f,  0.0f,
    124             -1.0f,  0.0f,  0.0f,  0.0f,
    125              0.0f,  0.0f,  1.0f,  0.0f,
    126              1.0f,  0.0f,  0.0f,  1.0f,
    127         };
    128 
    129         int[] texId = new int[1];
    130         GLES20.glGenTextures(1, texId, 0);
    131 
    132         SurfaceTexture consumer = new SurfaceTexture(texId[0]);
    133         consumer.setDefaultBufferSize(16, 16);
    134         Surface surface = new Surface(consumer);
    135 
    136         float[] computedTransform = new float[16];
    137         float[] receivedTransform = new float[16];
    138         float[] tmp = new float[16];
    139         for (int transform = 0; transform <= ALL_TRANSFORM_BITS; transform++) {
    140             nPushBufferWithTransform(surface, transform);
    141 
    142             // The SurfaceTexture texture transform matrix first does a vertical flip so that
    143             // "first row in memory" corresponds to "texture coordinate v=0".
    144             System.arraycopy(MIRROR_VERTICAL_MATRIX, 0, computedTransform, 0, 16);
    145 
    146             if ((transform & MIRROR_HORIZONTAL_BIT) != 0) {
    147                 matrixMultiply(computedTransform, computedTransform, MIRROR_HORIZONTAL_MATRIX, tmp);
    148             }
    149             if ((transform & MIRROR_VERTICAL_BIT) != 0) {
    150                 matrixMultiply(computedTransform, computedTransform, MIRROR_VERTICAL_MATRIX, tmp);
    151             }
    152             if ((transform & ROTATE_90_BIT) != 0) {
    153                 matrixMultiply(computedTransform, computedTransform, ROTATE_90_MATRIX, tmp);
    154             }
    155 
    156             consumer.updateTexImage();
    157             consumer.getTransformMatrix(receivedTransform);
    158 
    159             if (DEBUG) {
    160                 Log.d(TAG, String.format(
    161                         "Transform 0x%x:\n" +
    162                         "  expected: % 2.0f % 2.0f % 2.0f % 2.0f\n" +
    163                         "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
    164                         "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
    165                         "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
    166                         "  actual:   % 2.0f % 2.0f % 2.0f % 2.0f\n" +
    167                         "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
    168                         "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
    169                         "            % 2.0f % 2.0f % 2.0f % 2.0f\n",
    170                         transform,
    171                         computedTransform[ 0], computedTransform[ 1],
    172                         computedTransform[ 2], computedTransform[ 3],
    173                         computedTransform[ 4], computedTransform[ 5],
    174                         computedTransform[ 6], computedTransform[ 7],
    175                         computedTransform[ 8], computedTransform[ 9],
    176                         computedTransform[10], computedTransform[11],
    177                         computedTransform[12], computedTransform[13],
    178                         computedTransform[14], computedTransform[15],
    179                         receivedTransform[ 0], receivedTransform[ 1],
    180                         receivedTransform[ 2], receivedTransform[ 3],
    181                         receivedTransform[ 4], receivedTransform[ 5],
    182                         receivedTransform[ 6], receivedTransform[ 7],
    183                         receivedTransform[ 8], receivedTransform[ 9],
    184                         receivedTransform[10], receivedTransform[11],
    185                         receivedTransform[12], receivedTransform[13],
    186                         receivedTransform[14], receivedTransform[15]));
    187             }
    188 
    189             for (int i = 0; i < 16; i++) {
    190                 assertEquals(computedTransform[i], receivedTransform[i], 0.0f);
    191             }
    192         }
    193     }
    194 
    195     @Test
    196     public void testSetBuffersDataSpace() {
    197         final int DATASPACE_SRGB = 142671872;
    198         final int DATASPACE_UNKNOWN = 123;
    199 
    200         int[] texId = new int[1];
    201         GLES20.glGenTextures(1, texId, 0);
    202 
    203         SurfaceTexture consumer = new SurfaceTexture(texId[0]);
    204         consumer.setDefaultBufferSize(16, 16);
    205         Surface surface = new Surface(consumer);
    206 
    207         assertEquals(nGetBuffersDataSpace(surface), 0);
    208         assertEquals(nSetBuffersDataSpace(surface, DATASPACE_SRGB), 0);
    209         assertEquals(nGetBuffersDataSpace(surface), DATASPACE_SRGB);
    210 
    211         assertEquals(nSetBuffersDataSpace(null, DATASPACE_SRGB), -22);
    212         assertEquals(nGetBuffersDataSpace(null), -22);
    213         assertEquals(nGetBuffersDataSpace(surface), DATASPACE_SRGB);
    214 
    215         // set an unsupported data space should return a error code,
    216         // the original data space shouldn't change.
    217         assertEquals(nSetBuffersDataSpace(surface, DATASPACE_UNKNOWN), -22);
    218         assertEquals(nGetBuffersDataSpace(surface), DATASPACE_SRGB);
    219     }
    220 
    221     // Multiply 4x4 matrices result = a*b. result can be the same as either a or b,
    222     // allowing for result *= b. Another 4x4 matrix tmp must be provided as scratch space.
    223     private void matrixMultiply(float[] result, float[] a, float[] b, float[] tmp) {
    224         tmp[ 0] = a[ 0]*b[ 0] + a[ 4]*b[ 1] + a[ 8]*b[ 2] + a[12]*b[ 3];
    225         tmp[ 1] = a[ 1]*b[ 0] + a[ 5]*b[ 1] + a[ 9]*b[ 2] + a[13]*b[ 3];
    226         tmp[ 2] = a[ 2]*b[ 0] + a[ 6]*b[ 1] + a[10]*b[ 2] + a[14]*b[ 3];
    227         tmp[ 3] = a[ 3]*b[ 0] + a[ 7]*b[ 1] + a[11]*b[ 2] + a[15]*b[ 3];
    228 
    229         tmp[ 4] = a[ 0]*b[ 4] + a[ 4]*b[ 5] + a[ 8]*b[ 6] + a[12]*b[ 7];
    230         tmp[ 5] = a[ 1]*b[ 4] + a[ 5]*b[ 5] + a[ 9]*b[ 6] + a[13]*b[ 7];
    231         tmp[ 6] = a[ 2]*b[ 4] + a[ 6]*b[ 5] + a[10]*b[ 6] + a[14]*b[ 7];
    232         tmp[ 7] = a[ 3]*b[ 4] + a[ 7]*b[ 5] + a[11]*b[ 6] + a[15]*b[ 7];
    233 
    234         tmp[ 8] = a[ 0]*b[ 8] + a[ 4]*b[ 9] + a[ 8]*b[10] + a[12]*b[11];
    235         tmp[ 9] = a[ 1]*b[ 8] + a[ 5]*b[ 9] + a[ 9]*b[10] + a[13]*b[11];
    236         tmp[10] = a[ 2]*b[ 8] + a[ 6]*b[ 9] + a[10]*b[10] + a[14]*b[11];
    237         tmp[11] = a[ 3]*b[ 8] + a[ 7]*b[ 9] + a[11]*b[10] + a[15]*b[11];
    238 
    239         tmp[12] = a[ 0]*b[12] + a[ 4]*b[13] + a[ 8]*b[14] + a[12]*b[15];
    240         tmp[13] = a[ 1]*b[12] + a[ 5]*b[13] + a[ 9]*b[14] + a[13]*b[15];
    241         tmp[14] = a[ 2]*b[12] + a[ 6]*b[13] + a[10]*b[14] + a[14]*b[15];
    242         tmp[15] = a[ 3]*b[12] + a[ 7]*b[13] + a[11]*b[14] + a[15]*b[15];
    243 
    244         System.arraycopy(tmp, 0, result, 0, 16);
    245     }
    246 
    247     private static native void nPushBufferWithTransform(Surface surface, int transform);
    248     private static native int nSetBuffersDataSpace(Surface surface, int dataSpace);
    249     private static native int nGetBuffersDataSpace(Surface surface);
    250 }
    251