1/*
2 * Copyright (C) 2016 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
17package android.hardware.cts;
18
19import android.opengl.EGL14;
20import android.opengl.EGLConfig;
21import android.opengl.EGLContext;
22import android.opengl.EGLDisplay;
23import android.opengl.EGLExt;
24import android.opengl.GLES20;
25
26import java.util.regex.Matcher;
27import java.util.regex.Pattern;
28
29/**
30 * Utilities to test EGL APIs.
31 */
32final class Egl14Utils {
33    private Egl14Utils() {
34    }
35
36    /**
37     * Returns an initialized default display.
38     */
39    static EGLDisplay createEglDisplay() {
40        EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
41        if (eglDisplay == EGL14.EGL_NO_DISPLAY) {
42            throw new IllegalStateException("no EGL display");
43        }
44
45        int[] major = new int[1];
46        int[] minor = new int[1];
47        if (!EGL14.eglInitialize(eglDisplay, major, 0, minor, 0)) {
48            throw new IllegalStateException("error in eglInitialize");
49        }
50
51        return eglDisplay;
52    }
53
54    /**
55     * Returns a new GL ES 2.0 context for the specified {@code eglDisplay}.
56     */
57    static EGLContext createEglContext(EGLDisplay eglDisplay) {
58        return createEglContext(eglDisplay, getEglConfig(eglDisplay, 2), 2);
59    }
60
61    /**
62     * Returns a new GL ES context for the specified display, config and version.
63     */
64    static EGLContext createEglContext(EGLDisplay eglDisplay, EGLConfig eglConfig, int version) {
65        int[] contextAttributes = { EGL14.EGL_CONTEXT_CLIENT_VERSION, version, EGL14.EGL_NONE };
66        return EGL14.eglCreateContext(eglDisplay, eglConfig,
67                EGL14.EGL_NO_CONTEXT, contextAttributes, 0);
68    }
69
70    /**
71     * Destroys the GL context identified by {@code eglDisplay} and {@code eglContext}.
72     */
73    static void destroyEglContext(EGLDisplay eglDisplay, EGLContext eglContext) {
74        EGL14.eglMakeCurrent(eglDisplay,
75                EGL14.EGL_NO_SURFACE,
76                EGL14.EGL_NO_SURFACE,
77                EGL14.EGL_NO_CONTEXT);
78        int error = EGL14.eglGetError();
79        if (error != EGL14.EGL_SUCCESS) {
80            throw new RuntimeException("error releasing context: " + error);
81        }
82
83        EGL14.eglDestroyContext(eglDisplay, eglContext);
84        error = EGL14.eglGetError();
85        if (error != EGL14.EGL_SUCCESS) {
86            throw new RuntimeException("error destroying context: " + error);
87        }
88    }
89
90    static void releaseAndTerminate(EGLDisplay eglDisplay) {
91        int error;
92        EGL14.eglReleaseThread();
93        error = EGL14.eglGetError();
94        if (error != EGL14.EGL_SUCCESS) {
95            throw new RuntimeException("error releasing thread: " + error);
96        }
97
98        EGL14.eglTerminate(eglDisplay);
99        error = EGL14.eglGetError();
100        if (error != EGL14.EGL_SUCCESS) {
101            throw new RuntimeException("error terminating display: " + error);
102        }
103    }
104
105    static EGLConfig getEglConfig(EGLDisplay eglDisplay, int version) {
106        // Get an EGLConfig.
107        int renderableType = EGL14.EGL_OPENGL_ES2_BIT;
108        if (version == 3) {
109            renderableType = EGLExt.EGL_OPENGL_ES3_BIT_KHR;
110        }
111        final int RED_SIZE = 8;
112        final int GREEN_SIZE = 8;
113        final int BLUE_SIZE = 8;
114        final int ALPHA_SIZE = 8;
115        final int DEPTH_SIZE = 0;
116        final int STENCIL_SIZE = 0;
117        final int[] DEFAULT_CONFIGURATION = new int[] {
118                EGL14.EGL_RENDERABLE_TYPE, renderableType,
119                EGL14.EGL_RED_SIZE, RED_SIZE,
120                EGL14.EGL_GREEN_SIZE, GREEN_SIZE,
121                EGL14.EGL_BLUE_SIZE, BLUE_SIZE,
122                EGL14.EGL_ALPHA_SIZE, ALPHA_SIZE,
123                EGL14.EGL_DEPTH_SIZE, DEPTH_SIZE,
124                EGL14.EGL_STENCIL_SIZE, STENCIL_SIZE,
125                EGL14.EGL_NONE};
126
127        int[] configsCount = new int[1];
128        EGLConfig[] eglConfigs = new EGLConfig[1];
129        if (!EGL14.eglChooseConfig(
130                eglDisplay, DEFAULT_CONFIGURATION, 0, eglConfigs, 0, 1, configsCount, 0)) {
131            throw new RuntimeException("eglChooseConfig failed");
132        }
133        return eglConfigs[0];
134    }
135
136    /**
137     * Checks for a GL error using {@link GLES20#glGetError()}.
138     *
139     * @throws RuntimeException if there is a GL error
140     */
141    static void checkGlError() {
142        int errorCode;
143        if ((errorCode = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
144            throw new RuntimeException("gl error: " + Integer.toHexString(errorCode));
145        }
146    }
147}
148