/*
 * Copyright (C) 2012 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.
 */

#include <EGL/egl.h>
#define EGL_EGLEXT_PROTOTYPES // for egl*Sync*
#include <EGL/eglext.h>
#include <cutils/log.h>
#include <jni.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

typedef EGLSyncKHR EGLAPIENTRY (*TypeEglCreateSyncKHR)(EGLDisplay dpy, \
    EGLenum type, const EGLint *attrib_list);
typedef EGLBoolean EGLAPIENTRY (*TypeEglDestroySyncKHR)(EGLDisplay dpy, \
    EGLSyncKHR sync);
typedef EGLint EGLAPIENTRY (*TypeEglClientWaitSyncKHR)(EGLDisplay dpy, \
    EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);

static TypeEglCreateSyncKHR mEglCreateSyncKHR = NULL;
static TypeEglClientWaitSyncKHR mEglClientWaitSyncKHR = NULL;
static TypeEglDestroySyncKHR mEglDestroySyncKHR = NULL;
static bool mInitialized = false;
static bool mEglKhrFenceSyncSupported = false;

bool IsEglKHRFenceSyncSupported(EGLDisplay& display)
{
    if (!mInitialized) {
        const char* eglExtensions = eglQueryString(display, EGL_EXTENSIONS);
        if (eglExtensions && strstr(eglExtensions, "EGL_KHR_fence_sync")) {
            mEglCreateSyncKHR = (TypeEglCreateSyncKHR) eglGetProcAddress("eglCreateSyncKHR");
            mEglClientWaitSyncKHR =
                    (TypeEglClientWaitSyncKHR) eglGetProcAddress("eglClientWaitSyncKHR");
            mEglDestroySyncKHR = (TypeEglDestroySyncKHR) eglGetProcAddress("eglDestroySyncKHR");
            if (mEglCreateSyncKHR != NULL && mEglClientWaitSyncKHR != NULL
                    && mEglDestroySyncKHR != NULL) {
                mEglKhrFenceSyncSupported = true;
            }
        }
        mInitialized = true;
    }
    return mEglKhrFenceSyncSupported;
}

extern "C" JNIEXPORT \
jboolean JNICALL Java_android_openglperf_cts_OpenGlPerfNative_waitForEglCompletion(JNIEnv* env,
        jclass clazz, jlong waitTimeInNs)
{
    EGLDisplay dpy = eglGetCurrentDisplay();
    if (!IsEglKHRFenceSyncSupported(dpy)) {
        return JNI_FALSE;
    }
    EGLSyncKHR sync = mEglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
    if (sync == EGL_NO_SYNC_KHR) {
        return JNI_FALSE;
    }
    jboolean res = JNI_TRUE;
    EGLint result = mEglClientWaitSyncKHR(dpy, sync, 0, waitTimeInNs);
    if (result == EGL_FALSE) {
        ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
        res = JNI_FALSE;
    } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
        ALOGE("FrameCompletion: timeout waiting for fence");
        res = JNI_FALSE;
    }
    mEglDestroySyncKHR(dpy, sync);
    return res;
}
