This commit is contained in:
Simonx22 2026-05-07 18:00:14 -04:00 committed by GitHub
commit 8432044a83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 177 additions and 387 deletions

View File

@ -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"
)
) {

View File

@ -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
* <p>
* 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.
* <p>
* This should be called whenever this helper is no longer needed.
*/
public void closeHelper()
{
mEGL.eglTerminate(mDisplay);
}
/**
* Gets information through EGL.<br/>
* <p>
* Index 0: Vendor <br/>
* Index 1: Version <br/>
* Index 2: Renderer <br/>
* Index 3: Extensions <br/>
*
* @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.
* <br/>
* 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.
* <br/>
* 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)}
* <p>
* Accepts the following constants:
* <ul>
* <li>GL_VENDOR - Company responsible for the GL implementation.</li>
* <li>GL_VERSION - Version or release number.</li>
* <li>GL_RENDERER - Name of the renderer</li>
* <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
* </ul>
*
* @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)}
* <p>
* Accepts the following constants:
* <ul>
* <li>GL_VENDOR - Company responsible for the GL implementation.</li>
* <li>GL_VERSION - Version or release number.</li>
* <li>GL_RENDERER - Name of the renderer</li>
* <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
* <li>GL_EXTENSIONS - Extension string supported by the implementation at {@code index}.</li>
* </ul>
*
* @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];
}
}

View File

@ -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<EGLConfig>
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<EGLConfig>(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
}
}