diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt index 32a7a64025..3227190e6f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt @@ -1691,7 +1691,7 @@ class SettingsFragmentPresenter( // If we only support OpenGLES then we need both OpenGLES 3.1 and AEP val helper = EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT) - if (helper.supportsOpenGL() && helper.GetVersion() >= 320 || helper.supportsGLES3() && helper.GetVersion() >= 310 && helper.SupportsExtension( + if (helper.supportsOpenGL() && helper.getVersion() >= 320 || helper.supportsGLES3() && helper.getVersion() >= 310 && helper.supportsExtension( "GL_ANDROID_extension_pack_es31a" ) ) { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.java deleted file mode 100644 index b8e9dcc2cb..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright 2013 Dolphin Emulator Project - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -package org.dolphinemu.dolphinemu.utils; - -import android.opengl.GLES30; - -import org.dolphinemu.dolphinemu.NativeLibrary; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; -import javax.microedition.khronos.opengles.GL10; - -/** - * Utility class that abstracts all the stuff about - * EGL initialization out of the way if all that is - * wanted is to query the underlying GL API for information. - */ -public final class EGLHelper -{ - private final EGL10 mEGL; - private final EGLDisplay mDisplay; - private EGLConfig[] mEGLConfigs; - private EGLContext mEGLContext; - private EGLSurface mEGLSurface; - private GL10 mGL; - - // GL support flags - private boolean supportGL; - private boolean supportGLES2; - private boolean supportGLES3; - - // Renderable type bitmasks - public static final int EGL_OPENGL_ES_BIT = 0x0001; - public static final int EGL_OPENGL_ES2_BIT = 0x0004; - public static final int EGL_OPENGL_BIT = 0x0008; - public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040; - - // API types - public static final int EGL_OPENGL_ES_API = 0x30A0; - public static final int EGL_OPENGL_API = 0x30A2; - - /** - * Constructor - *

- * Initializes the underlying {@link EGLSurface} with a width and height of 1. - * This is useful if all you need to use this class for is to query information - * from specific API contexts. - * - * @param renderableType Bitmask indicating which types of client API contexts - * the framebuffer config must support. - */ - public EGLHelper(int renderableType) - { - this(1, 1, renderableType); - } - - /** - * Constructor - * - * @param width Width of the underlying {@link EGLSurface}. - * @param height Height of the underlying {@link EGLSurface}. - * @param renderableType Bitmask indicating which types of client API contexts - * the framebuffer config must support. - */ - public EGLHelper(int width, int height, int renderableType) - { - // Initialize handle to an EGL display. - mEGL = (EGL10) EGLContext.getEGL(); - mDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - - // If a display is present, initialize EGL. - if (mDisplay != EGL10.EGL_NO_DISPLAY) - { - int[] version = new int[2]; - if (mEGL.eglInitialize(mDisplay, version)) - { - // Detect supported GL APIs, initialize configs, etc. - detect(); - - // Create context and surface - create(width, height, renderableType); - } - else - { - Log.error("[EGLHelper] Error initializing EGL."); - } - } - else - { - Log.error("[EGLHelper] Error initializing EGL display."); - } - } - - /** - * Releases all resources associated with this helper. - *

- * This should be called whenever this helper is no longer needed. - */ - public void closeHelper() - { - mEGL.eglTerminate(mDisplay); - } - - /** - * Gets information through EGL.
- *

- * Index 0: Vendor
- * Index 1: Version
- * Index 2: Renderer
- * Index 3: Extensions
- * - * @return information retrieved through EGL. - */ - public String[] getEGLInfo() - { - return new String[]{ - mGL.glGetString(GL10.GL_VENDOR), - mGL.glGetString(GL10.GL_VERSION), - mGL.glGetString(GL10.GL_RENDERER), - mGL.glGetString(GL10.GL_EXTENSIONS), - }; - } - - /** - * Whether or not this device supports OpenGL. - * - * @return true if this device supports OpenGL; false otherwise. - */ - public boolean supportsOpenGL() - { - return supportGL; - } - - /** - * Whether or not this device supports OpenGL ES 2. - *
- * Note that if this returns true, then OpenGL ES 1 is also supported. - * - * @return true if this device supports OpenGL ES 2; false otherwise. - */ - public boolean supportsGLES2() - { - return supportGLES2; - } - - /** - * Whether or not this device supports OpenGL ES 3. - *
- * Note that if this returns true, then OpenGL ES 1 and 2 are also supported. - * - * @return true if this device supports OpenGL ES 3; false otherwise. - */ - public boolean supportsGLES3() - { - return supportGLES3; - } - - /** - * Gets the underlying {@link EGL10} instance. - * - * @return the underlying {@link EGL10} instance. - */ - public EGL10 getEGL() - { - return mEGL; - } - - /** - * Gets the underlying {@link GL10} instance. - * - * @return the underlying {@link GL10} instance. - */ - public GL10 getGL() - { - return mGL; - } - - /** - * Gets the underlying {@link EGLDisplay}. - * - * @return the underlying {@link EGLDisplay} - */ - public EGLDisplay getDisplay() - { - return mDisplay; - } - - /** - * Gets all supported framebuffer configurations for this device. - * - * @return all supported framebuffer configurations for this device. - */ - public EGLConfig[] getConfigs() - { - return mEGLConfigs; - } - - /** - * Gets the underlying {@link EGLContext}. - * - * @return the underlying {@link EGLContext}. - */ - public EGLContext getContext() - { - return mEGLContext; - } - - /** - * Gets the underlying {@link EGLSurface}. - * - * @return the underlying {@link EGLSurface}. - */ - public EGLSurface getSurface() - { - return mEGLSurface; - } - - // Detects the specific kind of GL modes that are supported - private void detect() - { - // Get total number of configs available. - int[] numConfigs = new int[1]; - if (!mEGL.eglGetConfigs(mDisplay, null, 0, numConfigs)) - { - Log.error("[EGLHelper] Error retrieving number of EGL configs available."); - return; - } - - // Now get all the configurations - mEGLConfigs = new EGLConfig[numConfigs[0]]; - if (!mEGL.eglGetConfigs(mDisplay, mEGLConfigs, mEGLConfigs.length, numConfigs)) - { - Log.error("[EGLHelper] Error retrieving all EGL configs."); - return; - } - - for (EGLConfig mEGLConfig : mEGLConfigs) - { - int[] attribVal = new int[1]; - boolean ret = - mEGL.eglGetConfigAttrib(mDisplay, mEGLConfig, EGL10.EGL_RENDERABLE_TYPE, attribVal); - if (ret) - { - if ((attribVal[0] & EGL_OPENGL_BIT) != 0) - supportGL = true; - - if ((attribVal[0] & EGL_OPENGL_ES2_BIT) != 0) - supportGLES2 = true; - - if ((attribVal[0] & EGL_OPENGL_ES3_BIT_KHR) != 0) - supportGLES3 = true; - } - } - } - - // Creates the context and surface. - private void create(int width, int height, int renderableType) - { - int[] attribs = { - EGL10.EGL_WIDTH, width, - EGL10.EGL_HEIGHT, height, - EGL10.EGL_NONE - }; - - // Initially we just assume GLES2 will be the default context. - int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - int[] ctx_attribs = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL10.EGL_NONE - }; - - // Determine the type of context that will be created - // and change the attribute arrays accordingly. - switch (renderableType) - { - case EGL_OPENGL_ES_BIT: - ctx_attribs[1] = 1; - break; - - case EGL_OPENGL_BIT: - ctx_attribs[0] = EGL10.EGL_NONE; - break; - - case EGL_OPENGL_ES3_BIT_KHR: - ctx_attribs[1] = 3; - break; - - case EGL_OPENGL_ES2_BIT: - default: // Fall-back to GLES 2. - ctx_attribs[1] = 2; - break; - } - if (renderableType == EGL_OPENGL_BIT) - NativeLibrary.eglBindAPI(EGL_OPENGL_API); - else - NativeLibrary.eglBindAPI(EGL_OPENGL_ES_API); - - mEGLContext = - mEGL.eglCreateContext(mDisplay, mEGLConfigs[0], EGL10.EGL_NO_CONTEXT, ctx_attribs); - mEGLSurface = mEGL.eglCreatePbufferSurface(mDisplay, mEGLConfigs[0], attribs); - mEGL.eglMakeCurrent(mDisplay, mEGLSurface, mEGLSurface, mEGLContext); - mGL = (GL10) mEGLContext.getGL(); - } - - /** - * Simplified call to {@link GL10#glGetString(int)} - *

- * Accepts the following constants: - *

- * - * @param glEnum A symbolic constant within {@link GL10}. - * @return the string information represented by {@code glEnum}. - */ - public String glGetString(int glEnum) - { - return mGL.glGetString(glEnum); - } - - /** - * Simplified call to {@link GLES30#glGetStringi(int, int)} - *

- * Accepts the following constants: - *

- * - * @param glEnum A symbolic GL constant - * @param index The index of the string to return. - * @return the string information represented by {@code glEnum} and {@code index}. - */ - public String glGetStringi(int glEnum, int index) - { - return GLES30.glGetStringi(glEnum, index); - } - - public boolean SupportsExtension(String extension) - { - int[] num_ext = new int[1]; - GLES30.glGetIntegerv(GLES30.GL_NUM_EXTENSIONS, num_ext, 0); - - for (int i = 0; i < num_ext[0]; ++i) - { - String ext = GLES30.glGetStringi(GLES30.GL_EXTENSIONS, i); - if (ext.equals(extension)) - return true; - } - return false; - } - - public int GetVersion() - { - int[] major = new int[1]; - int[] minor = new int[1]; - GLES30.glGetIntegerv(GLES30.GL_MAJOR_VERSION, major, 0); - GLES30.glGetIntegerv(GLES30.GL_MINOR_VERSION, minor, 0); - return major[0] * 100 + minor[0] * 10; - } - - /** - * Simplified call to {@link GL10#glGetIntegerv(int, int[], int) - * - * @param glEnum A symbolic GL constant. - * @return the integer information represented by {@code glEnum}. - */ - public int glGetInteger(int glEnum) - { - int[] val = new int[1]; - mGL.glGetIntegerv(glEnum, val, 0); - return val[0]; - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.kt new file mode 100644 index 0000000000..df561f534f --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.kt @@ -0,0 +1,176 @@ +/* + * Copyright 2013 Dolphin Emulator Project + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +package org.dolphinemu.dolphinemu.utils + +import android.opengl.GLES30 + +import org.dolphinemu.dolphinemu.NativeLibrary + +import javax.microedition.khronos.egl.EGL10 +import javax.microedition.khronos.egl.EGLConfig +import javax.microedition.khronos.egl.EGLContext +import javax.microedition.khronos.egl.EGLDisplay +import javax.microedition.khronos.egl.EGLSurface + +/** + * Utility class that abstracts all the stuff about + * EGL initialization out of the way if all that is + * wanted is to query the underlying GL API for information. + */ +class EGLHelper(width: Int, height: Int, renderableType: Int) { + private val mEGL: EGL10 = EGLContext.getEGL() as EGL10 + private val mDisplay: EGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY) + private lateinit var mEGLConfigs: Array + private lateinit var mEGLContext: EGLContext + private lateinit var mEGLSurface: EGLSurface + + // GL support flags + private var supportGL = false + private var supportGLES3 = false + + /** + * Constructor + * + * Initializes the underlying [EGLSurface] with a width and height of 1. + * This is useful if all you need to use this class for is to query information + * from specific API contexts. + * + * @param renderableType Bitmask indicating which types of client API contexts + * the framebuffer config must support. + */ + constructor(renderableType: Int) : this(1, 1, renderableType) + + init { + // If a display is present, initialize EGL. + if (mDisplay != EGL10.EGL_NO_DISPLAY) { + val version = IntArray(2) + if (mEGL.eglInitialize(mDisplay, version)) { + // Detect supported GL APIs, initialize configs, etc. + detect() + + // Create context and surface + create(width, height, renderableType) + } else { + Log.error("[EGLHelper] Error initializing EGL.") + } + } else { + Log.error("[EGLHelper] Error initializing EGL display.") + } + } + + /** + * Whether or not this device supports OpenGL. + * + * @return true if this device supports OpenGL; false otherwise. + */ + fun supportsOpenGL(): Boolean { + return supportGL + } + + /** + * Whether or not this device supports OpenGL ES 3. + * + * Note that if this returns true, then OpenGL ES 1 and 2 are also supported. + * + * @return true if this device supports OpenGL ES 3; false otherwise. + */ + fun supportsGLES3(): Boolean { + return supportGLES3 + } + + // Detects the specific kind of GL modes that are supported + private fun detect() { + // Get total number of configs available. + val numConfigs = IntArray(1) + if (!mEGL.eglGetConfigs(mDisplay, null, 0, numConfigs)) { + Log.error("[EGLHelper] Error retrieving number of EGL configs available.") + return + } + + // Now get all the configurations + val eglConfigs = arrayOfNulls(numConfigs[0]) + if (!mEGL.eglGetConfigs(mDisplay, eglConfigs, eglConfigs.size, numConfigs)) { + Log.error("[EGLHelper] Error retrieving all EGL configs.") + return + } + mEGLConfigs = Array(eglConfigs.size) { i -> eglConfigs[i]!! } + + for (eglConfig in mEGLConfigs) { + val attribVal = IntArray(1) + val ret = + mEGL.eglGetConfigAttrib(mDisplay, eglConfig, EGL10.EGL_RENDERABLE_TYPE, attribVal) + if (ret) { + if ((attribVal[0] and EGL_OPENGL_BIT) != 0) supportGL = true + + if ((attribVal[0] and EGL_OPENGL_ES3_BIT_KHR) != 0) supportGLES3 = true + } + } + } + + // Creates the context and surface. + private fun create(width: Int, height: Int, renderableType: Int) { + val attribs = intArrayOf( + EGL10.EGL_WIDTH, width, EGL10.EGL_HEIGHT, height, EGL10.EGL_NONE + ) + + // Initially we just assume GLES2 will be the default context. + val eglContextClientVersion = 0x3098 + val ctxAttribs = intArrayOf( + eglContextClientVersion, 2, EGL10.EGL_NONE + ) + + // Determine the type of context that will be created + // and change the attribute arrays accordingly. + when (renderableType) { + EGL_OPENGL_ES_BIT -> ctxAttribs[1] = 1 + EGL_OPENGL_BIT -> ctxAttribs[0] = EGL10.EGL_NONE + EGL_OPENGL_ES3_BIT_KHR -> ctxAttribs[1] = 3 + EGL_OPENGL_ES2_BIT -> ctxAttribs[1] = 2 + else -> ctxAttribs[1] = 2 // Fall-back to GLES 2. + } + if (renderableType == EGL_OPENGL_BIT) { + NativeLibrary.eglBindAPI(EGL_OPENGL_API) + } else { + NativeLibrary.eglBindAPI(EGL_OPENGL_ES_API) + } + + mEGLContext = + mEGL.eglCreateContext(mDisplay, mEGLConfigs[0], EGL10.EGL_NO_CONTEXT, ctxAttribs) + mEGLSurface = mEGL.eglCreatePbufferSurface(mDisplay, mEGLConfigs[0], attribs) + mEGL.eglMakeCurrent(mDisplay, mEGLSurface, mEGLSurface, mEGLContext) + } + + fun supportsExtension(extension: String): Boolean { + val numExt = IntArray(1) + GLES30.glGetIntegerv(GLES30.GL_NUM_EXTENSIONS, numExt, 0) + + for (i in 0 until numExt[0]) { + val ext = GLES30.glGetStringi(GLES30.GL_EXTENSIONS, i) + if (ext.equals(extension)) return true + } + return false + } + + fun getVersion(): Int { + val major = IntArray(1) + val minor = IntArray(1) + GLES30.glGetIntegerv(GLES30.GL_MAJOR_VERSION, major, 0) + GLES30.glGetIntegerv(GLES30.GL_MINOR_VERSION, minor, 0) + return major[0] * 100 + minor[0] * 10 + } + + companion object { + // Renderable type bitmasks + const val EGL_OPENGL_ES_BIT = 0x0001 + const val EGL_OPENGL_ES2_BIT = 0x0004 + const val EGL_OPENGL_BIT = 0x0008 + const val EGL_OPENGL_ES3_BIT_KHR = 0x0040 + + // API types + const val EGL_OPENGL_ES_API = 0x30A0 + const val EGL_OPENGL_API = 0x30A2 + } +}