/*
 * Copyright 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.graphics.cts;

import static android.opengl.EGL14.*;

import static org.junit.Assert.assertEquals;

import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.opengl.EGLConfig;
import android.opengl.EGLContext;
import android.opengl.EGLDisplay;
import android.opengl.EGLSurface;
import android.opengl.GLES20;
import android.util.Log;
import android.view.Surface;

import androidx.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;

@SmallTest
@RunWith(BlockJUnit4ClassRunner.class)
public class ANativeWindowTest {

    static {
        System.loadLibrary("ctsgraphics_jni");
    }

    private static final String TAG = ANativeWindowTest.class.getSimpleName();
    private static final boolean DEBUG = false;

    private EGLDisplay mEglDisplay = EGL_NO_DISPLAY;
    private EGLConfig mEglConfig = null;
    private EGLSurface mEglPbuffer = EGL_NO_SURFACE;
    private EGLContext mEglContext = EGL_NO_CONTEXT;

    @Before
    public void setup() throws Throwable {
        mEglDisplay = EGL14.eglGetDisplay(EGL_DEFAULT_DISPLAY);
        if (mEglDisplay == EGL_NO_DISPLAY) {
            throw new RuntimeException("no EGL display");
        }
        int[] major = new int[1];
        int[] minor = new int[1];
        if (!EGL14.eglInitialize(mEglDisplay, major, 0, minor, 0)) {
            throw new RuntimeException("error in eglInitialize");
        }

        // If we could rely on having EGL_KHR_surfaceless_context and EGL_KHR_context_no_config, we
        // wouldn't have to create a config or pbuffer at all.

        int[] numConfigs = new int[1];
        EGLConfig[] configs = new EGLConfig[1];
        if (!EGL14.eglChooseConfig(mEglDisplay,
                new int[] {
                    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                    EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
                    EGL_NONE},
                0, configs, 0, 1, numConfigs, 0)) {
            throw new RuntimeException("eglChooseConfig failed");
        }
        mEglConfig = configs[0];

        mEglPbuffer = EGL14.eglCreatePbufferSurface(mEglDisplay, mEglConfig,
                new int[] {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}, 0);
        if (mEglPbuffer == EGL_NO_SURFACE) {
            throw new RuntimeException("eglCreatePbufferSurface failed");
        }

        mEglContext = EGL14.eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
                new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}, 0);
        if (mEglContext == EGL_NO_CONTEXT) {
            throw new RuntimeException("eglCreateContext failed");
        }

        if (!EGL14.eglMakeCurrent(mEglDisplay, mEglPbuffer, mEglPbuffer, mEglContext)) {
            throw new RuntimeException("eglMakeCurrent failed");
        }
    }

    @Test
    public void testSetBuffersTransform() {
        final int MIRROR_HORIZONTAL_BIT = 0x01;
        final int MIRROR_VERTICAL_BIT   = 0x02;
        final int ROTATE_90_BIT         = 0x04;
        final int ALL_TRANSFORM_BITS    =
                MIRROR_HORIZONTAL_BIT | MIRROR_VERTICAL_BIT | ROTATE_90_BIT;

        // 4x4 GL-style matrices, as returned by SurfaceTexture#getTransformMatrix(). Note they're
        // transforming texture coordinates ([0,1]^2), so the origin for the transforms is
        // (0.5, 0.5), not (0,0).
        final float[] MIRROR_HORIZONTAL_MATRIX = new float[] {
            -1.0f,  0.0f,  0.0f,  0.0f,
             0.0f,  1.0f,  0.0f,  0.0f,
             0.0f,  0.0f,  1.0f,  0.0f,
             1.0f,  0.0f,  0.0f,  1.0f,
        };
        final float[] MIRROR_VERTICAL_MATRIX = new float[] {
             1.0f,  0.0f,  0.0f,  0.0f,
             0.0f, -1.0f,  0.0f,  0.0f,
             0.0f,  0.0f,  1.0f,  0.0f,
             0.0f,  1.0f,  0.0f,  1.0f,
        };
        final float[] ROTATE_90_MATRIX = new float[] {
             0.0f,  1.0f,  0.0f,  0.0f,
            -1.0f,  0.0f,  0.0f,  0.0f,
             0.0f,  0.0f,  1.0f,  0.0f,
             1.0f,  0.0f,  0.0f,  1.0f,
        };

        int[] texId = new int[1];
        GLES20.glGenTextures(1, texId, 0);

        SurfaceTexture consumer = new SurfaceTexture(texId[0]);
        consumer.setDefaultBufferSize(16, 16);
        Surface surface = new Surface(consumer);

        float[] computedTransform = new float[16];
        float[] receivedTransform = new float[16];
        float[] tmp = new float[16];
        for (int transform = 0; transform <= ALL_TRANSFORM_BITS; transform++) {
            nPushBufferWithTransform(surface, transform);

            // The SurfaceTexture texture transform matrix first does a vertical flip so that
            // "first row in memory" corresponds to "texture coordinate v=0".
            System.arraycopy(MIRROR_VERTICAL_MATRIX, 0, computedTransform, 0, 16);

            if ((transform & MIRROR_HORIZONTAL_BIT) != 0) {
                matrixMultiply(computedTransform, computedTransform, MIRROR_HORIZONTAL_MATRIX, tmp);
            }
            if ((transform & MIRROR_VERTICAL_BIT) != 0) {
                matrixMultiply(computedTransform, computedTransform, MIRROR_VERTICAL_MATRIX, tmp);
            }
            if ((transform & ROTATE_90_BIT) != 0) {
                matrixMultiply(computedTransform, computedTransform, ROTATE_90_MATRIX, tmp);
            }

            consumer.updateTexImage();
            consumer.getTransformMatrix(receivedTransform);

            if (DEBUG) {
                Log.d(TAG, String.format(
                        "Transform 0x%x:\n" +
                        "  expected: % 2.0f % 2.0f % 2.0f % 2.0f\n" +
                        "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
                        "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
                        "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
                        "  actual:   % 2.0f % 2.0f % 2.0f % 2.0f\n" +
                        "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
                        "            % 2.0f % 2.0f % 2.0f % 2.0f\n" +
                        "            % 2.0f % 2.0f % 2.0f % 2.0f\n",
                        transform,
                        computedTransform[ 0], computedTransform[ 1],
                        computedTransform[ 2], computedTransform[ 3],
                        computedTransform[ 4], computedTransform[ 5],
                        computedTransform[ 6], computedTransform[ 7],
                        computedTransform[ 8], computedTransform[ 9],
                        computedTransform[10], computedTransform[11],
                        computedTransform[12], computedTransform[13],
                        computedTransform[14], computedTransform[15],
                        receivedTransform[ 0], receivedTransform[ 1],
                        receivedTransform[ 2], receivedTransform[ 3],
                        receivedTransform[ 4], receivedTransform[ 5],
                        receivedTransform[ 6], receivedTransform[ 7],
                        receivedTransform[ 8], receivedTransform[ 9],
                        receivedTransform[10], receivedTransform[11],
                        receivedTransform[12], receivedTransform[13],
                        receivedTransform[14], receivedTransform[15]));
            }

            for (int i = 0; i < 16; i++) {
                assertEquals(computedTransform[i], receivedTransform[i], 0.0f);
            }
        }
    }

    @Test
    public void testSetBuffersDataSpace() {
        final int DATASPACE_SRGB = 142671872;
        final int DATASPACE_UNKNOWN = 123;

        int[] texId = new int[1];
        GLES20.glGenTextures(1, texId, 0);

        SurfaceTexture consumer = new SurfaceTexture(texId[0]);
        consumer.setDefaultBufferSize(16, 16);
        Surface surface = new Surface(consumer);

        assertEquals(nGetBuffersDataSpace(surface), 0);
        assertEquals(nSetBuffersDataSpace(surface, DATASPACE_SRGB), 0);
        assertEquals(nGetBuffersDataSpace(surface), DATASPACE_SRGB);

        assertEquals(nSetBuffersDataSpace(null, DATASPACE_SRGB), -22);
        assertEquals(nGetBuffersDataSpace(null), -22);
        assertEquals(nGetBuffersDataSpace(surface), DATASPACE_SRGB);

        // set an unsupported data space should return a error code,
        // the original data space shouldn't change.
        assertEquals(nSetBuffersDataSpace(surface, DATASPACE_UNKNOWN), -22);
        assertEquals(nGetBuffersDataSpace(surface), DATASPACE_SRGB);
    }

    // Multiply 4x4 matrices result = a*b. result can be the same as either a or b,
    // allowing for result *= b. Another 4x4 matrix tmp must be provided as scratch space.
    private void matrixMultiply(float[] result, float[] a, float[] b, float[] tmp) {
        tmp[ 0] = a[ 0]*b[ 0] + a[ 4]*b[ 1] + a[ 8]*b[ 2] + a[12]*b[ 3];
        tmp[ 1] = a[ 1]*b[ 0] + a[ 5]*b[ 1] + a[ 9]*b[ 2] + a[13]*b[ 3];
        tmp[ 2] = a[ 2]*b[ 0] + a[ 6]*b[ 1] + a[10]*b[ 2] + a[14]*b[ 3];
        tmp[ 3] = a[ 3]*b[ 0] + a[ 7]*b[ 1] + a[11]*b[ 2] + a[15]*b[ 3];

        tmp[ 4] = a[ 0]*b[ 4] + a[ 4]*b[ 5] + a[ 8]*b[ 6] + a[12]*b[ 7];
        tmp[ 5] = a[ 1]*b[ 4] + a[ 5]*b[ 5] + a[ 9]*b[ 6] + a[13]*b[ 7];
        tmp[ 6] = a[ 2]*b[ 4] + a[ 6]*b[ 5] + a[10]*b[ 6] + a[14]*b[ 7];
        tmp[ 7] = a[ 3]*b[ 4] + a[ 7]*b[ 5] + a[11]*b[ 6] + a[15]*b[ 7];

        tmp[ 8] = a[ 0]*b[ 8] + a[ 4]*b[ 9] + a[ 8]*b[10] + a[12]*b[11];
        tmp[ 9] = a[ 1]*b[ 8] + a[ 5]*b[ 9] + a[ 9]*b[10] + a[13]*b[11];
        tmp[10] = a[ 2]*b[ 8] + a[ 6]*b[ 9] + a[10]*b[10] + a[14]*b[11];
        tmp[11] = a[ 3]*b[ 8] + a[ 7]*b[ 9] + a[11]*b[10] + a[15]*b[11];

        tmp[12] = a[ 0]*b[12] + a[ 4]*b[13] + a[ 8]*b[14] + a[12]*b[15];
        tmp[13] = a[ 1]*b[12] + a[ 5]*b[13] + a[ 9]*b[14] + a[13]*b[15];
        tmp[14] = a[ 2]*b[12] + a[ 6]*b[13] + a[10]*b[14] + a[14]*b[15];
        tmp[15] = a[ 3]*b[12] + a[ 7]*b[13] + a[11]*b[14] + a[15]*b[15];

        System.arraycopy(tmp, 0, result, 0, 16);
    }

    private static native void nPushBufferWithTransform(Surface surface, int transform);
    private static native int nSetBuffersDataSpace(Surface surface, int dataSpace);
    private static native int nGetBuffersDataSpace(Surface surface);
}
