/*
 * 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 org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import android.hardware.SyncFence;
import android.opengl.EGL14;
import android.opengl.EGL15;
import android.opengl.EGLConfig;
import android.opengl.EGLContext;
import android.opengl.EGLDisplay;
import android.opengl.EGLExt;
import android.opengl.EGLImage;
import android.opengl.EGLSurface;
import android.opengl.EGLSync;
import android.opengl.GLES20;
import android.os.SystemProperties;

import androidx.test.filters.SmallTest;

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

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

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

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

    private EGLDisplay mEglDisplay = EGL15.EGL_NO_DISPLAY;
    private EGLConfig mEglConfig = null;
    private EGLSurface mEglPbuffer = EGL15.EGL_NO_SURFACE;
    private EGLContext mEglContext = EGL15.EGL_NO_CONTEXT;
    private int mEglVersion = 0;

    @Before
    public void setup() throws Throwable {
        int error;

        mEglDisplay = EGL15.eglGetPlatformDisplay(EGL15.EGL_PLATFORM_ANDROID_KHR,
                EGL14.EGL_DEFAULT_DISPLAY,
                new long[] {
                    EGL14.EGL_NONE },
                0);
        if (mEglDisplay == EGL15.EGL_NO_DISPLAY) {
            throw new RuntimeException("no EGL display");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglGetPlatformDisplay failed");
        }

        int[] major = new int[1];
        int[] minor = new int[1];
        if (!EGL14.eglInitialize(mEglDisplay, major, 0, minor, 0)) {
            throw new RuntimeException("error in eglInitialize");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglInitialize failed");
        }
        mEglVersion = major[0] * 10 + minor[0];

        // 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[] {
                    EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
                    EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT,
                    EGL14.EGL_NONE},
                0, configs, 0, 1, numConfigs, 0)) {
            throw new RuntimeException("eglChooseConfig failed");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglChooseConfig failed");
        }

        mEglConfig = configs[0];

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


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


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

    @After
    public void teardown() throws Throwable {
        EGL14.eglTerminate(mEglDisplay);
    }

    @Test
    public void testEGL15SyncFence() {
        if (mEglVersion < 15) {
            return;
        }
        EGLSync sync = EGL15.eglCreateSync(mEglDisplay, EGL15.EGL_SYNC_FENCE,
                new long[] {
                    EGL14.EGL_NONE },
                0);
        if (sync == EGL15.EGL_NO_SYNC) {
            throw new RuntimeException("eglCreateSync failed");
        }
        int error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglCreateSync failed");
        }

        GLES20.glFlush();
        error = GLES20.glGetError();
        if (error != GLES20.GL_NO_ERROR) {
            throw new RuntimeException("glFlush failed");
        }

        int status = EGL15.eglClientWaitSync(mEglDisplay, sync, 0, EGL15.EGL_FOREVER);
        if (status != EGL15.EGL_CONDITION_SATISFIED) {
            throw new RuntimeException("eglClientWaitSync failed");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglClientWaitSync failed");
        }

        if (!EGL15.eglDestroySync(mEglDisplay, sync)) {
            throw new RuntimeException("eglDestroySync failed");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglDestroySync failed");
        }
    }

    @Test
    public void testEGL15AndroidNativeFence() {
        if (mEglVersion < 15) {
            return;
        }
        String eglExtensions = EGL14.eglQueryString(mEglDisplay, EGL14.EGL_EXTENSIONS);
        if (!eglExtensions.contains("EGL_ANDROID_native_fence_sync")) {
            return;
        }
        long before = System.nanoTime();
        EGLSync sync = EGL15.eglCreateSync(mEglDisplay, EGLExt.EGL_SYNC_NATIVE_FENCE_ANDROID,
                new long[] {
                        EGL14.EGL_NONE },
                0);
        assertNotEquals(sync, EGL15.EGL_NO_SYNC);
        assertEquals(EGL14.EGL_SUCCESS, EGL14.eglGetError());

        SyncFence nativeFence = EGLExt.eglDupNativeFenceFDANDROID(mEglDisplay, sync);
        assertNotNull(nativeFence);
        assertEquals(EGL14.EGL_SUCCESS, EGL14.eglGetError());
        // If the fence isn't valid, trigger a flush & try again
        if (!nativeFence.isValid()) {
            GLES20.glFlush();
            assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError());

            // Have flushed, native fence should be populated
            nativeFence = EGLExt.eglDupNativeFenceFDANDROID(mEglDisplay, sync);
            assertNotNull(nativeFence);
            assertTrue(nativeFence.isValid());
            assertEquals(EGL14.EGL_SUCCESS, EGL14.eglGetError());
        }

        long signaledTime = nativeFence.getSignalTime();
        // We don't know if the fence has or hasn't signaled yet. But either way it must be
        // greater than before the fence was created (either signaled, or PENDING which is LONG_MAX)
        assertThat("getSignalTime before waiting", signaledTime, greaterThan(before));
        // Similarly, if the fence has signaled it must be less than now
        assertThat("getSignalTime before waiting", signaledTime,
                anyOf(equalTo(SyncFence.SIGNAL_TIME_PENDING), lessThan(System.nanoTime())));

        assertTrue(EGL15.eglDestroySync(mEglDisplay, sync));
        assertEquals(EGL14.EGL_SUCCESS, EGL14.eglGetError());

        assertTrue(nativeFence.awaitForever());
        signaledTime = nativeFence.getSignalTime();
        assertNotEquals(SyncFence.SIGNAL_TIME_INVALID, signaledTime);
        assertThat("getSignalTime after waiting", signaledTime, greaterThan(before));

        nativeFence.close();
        assertFalse(nativeFence.isValid());
        assertEquals(SyncFence.SIGNAL_TIME_INVALID, nativeFence.getSignalTime());
    }

    @Test
    public void testEGL15GetSyncType() {
        if (mEglVersion < 15) {
            return;
        }
        EGLSync sync = EGL15.eglCreateSync(mEglDisplay, EGL15.EGL_SYNC_FENCE,
                new long[] {
                    EGL14.EGL_NONE },
                0);
        if (sync == EGL15.EGL_NO_SYNC) {
            throw new RuntimeException("eglCreateSync failed");
        }
        int error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglCreateSync failed");
        }

        long[] type = new long[1];
        boolean success = EGL15.eglGetSyncAttrib(mEglDisplay, sync, EGL15.EGL_SYNC_TYPE, type, 0);
        if (!success) {
            throw new RuntimeException("eglGetSyncAttrib failed (returned false)");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglGetSyncAttrib failed");
        }
        assertEquals(type[0], EGL15.EGL_SYNC_FENCE);

        if (!EGL15.eglDestroySync(mEglDisplay, sync)) {
            throw new RuntimeException("eglDestroySync failed");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglDestroySync failed");
        }
    }

    @Test
    public void testEGL15WaitSync() {
        if (mEglVersion < 15) {
            return;
        }
        EGLSync sync = EGL15.eglCreateSync(mEglDisplay, EGL15.EGL_SYNC_FENCE,
                new long[] {
                    EGL14.EGL_NONE },
                0);
        if (sync == EGL15.EGL_NO_SYNC) {
            throw new RuntimeException("eglCreateSync failed");
        }
        int error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglCreateSync failed");
        }

        boolean success = EGL15.eglWaitSync(mEglDisplay, sync, 0);
        if (!success) {
            throw new RuntimeException("eglWaitSync failed (returned false)");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglWaitSync failed");
        }

        if (!EGL15.eglDestroySync(mEglDisplay, sync)) {
            throw new RuntimeException("eglDestroySync failed");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglDestroySync failed");
        }
    }

    @Test
    public void testEGL15CreateImage() {
        if (mEglVersion < 15) {
            return;
        }

        int error;
        int srcTex = 1;
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, srcTex);
        error = GLES20.glGetError();
        if (error != GLES20.GL_NO_ERROR) {
            throw new RuntimeException("glBindTexture failed");
        }

        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 64, 64, 0,
                            GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
        error = GLES20.glGetError();
        if (error != GLES20.GL_NO_ERROR) {
            throw new RuntimeException("glTexImage2D failed");
        }

        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
                               GLES20.GL_LINEAR);
        error = GLES20.glGetError();
        if (error != GLES20.GL_NO_ERROR) {
            throw new RuntimeException("glTexParameteri failed");
        }

        long[] attribs = new long[] {
                EGL15.EGL_GL_TEXTURE_LEVEL, 0,
                EGL14.EGL_NONE };
        EGLImage image = EGL15.eglCreateImage(mEglDisplay, mEglContext,
                EGL15.EGL_GL_TEXTURE_2D, srcTex, attribs, 0);
        if (image == EGL15.EGL_NO_IMAGE) {
            throw new RuntimeException("eglCreateImage failed, got EGL_NO_IMAGE");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglCreateImage failed");
        }

        boolean success = EGL15.eglDestroyImage(mEglDisplay, image);
        if (!success) {
            throw new RuntimeException("eglDestroyImage failed (returned false)");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglDestroyImage failed");
        }
    }

    @Test
    public void testEGL15CreatePlatformPixmap() {
        if (mEglVersion < 15) {
            return;
        }

        long[] attribs = new long[] { EGL14.EGL_NONE };
        boolean unsupported = false;
        try {
            EGLSurface surface = EGL15.eglCreatePlatformPixmapSurface(mEglDisplay,
                    mEglConfig, null, attribs, 0);
        } catch (UnsupportedOperationException e) {
            unsupported = true;
        }
        if (!unsupported) {
            throw new RuntimeException("eglCreatePlatformPixmapSurface is not supported on Android,"
                    + " why did call not report that!");
        }
    }

    @Test
    public void testEGL15CreateDebugContext() {
        int error;

        if (mEglVersion < 15) {
            return;
        }

        // Required functionality for devices released with Android R (11),
        // skip if launched with older version of Android.
        if (SystemProperties.getInt("ro.product.first_api_level", 0) < 30) {
            return;
        }

        mEglContext = EGL14.eglCreateContext(mEglDisplay, mEglConfig, EGL14.EGL_NO_CONTEXT,
                new int[] { EGL15.EGL_CONTEXT_OPENGL_DEBUG, EGL14.EGL_FALSE, EGL14.EGL_NONE }, 0);
        if (mEglContext == EGL15.EGL_NO_CONTEXT) {
            throw new RuntimeException("eglCreateContext failed");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglCreateContext failed");
        }
        EGL14.eglDestroyContext(mEglDisplay, mEglContext);

        mEglContext = EGL14.eglCreateContext(mEglDisplay, mEglConfig, EGL14.EGL_NO_CONTEXT,
                new int[] { EGL15.EGL_CONTEXT_OPENGL_DEBUG, EGL14.EGL_TRUE, EGL14.EGL_NONE }, 0);
        if (mEglContext == EGL15.EGL_NO_CONTEXT) {
            throw new RuntimeException("eglCreateContext failed");
        }
        error = EGL14.eglGetError();
        if (error != EGL14.EGL_SUCCESS) {
            throw new RuntimeException("eglCreateContext failed");
        }
        EGL14.eglDestroyContext(mEglDisplay, mEglContext);
    }
}

// Note: Need to add tests for eglCreatePlatformWindowSurface
