[Android] Initial introduction of the EGLHelper utility class. Should simplify all interop with the EGL/GL APIs. Not hooked up yet. However it is entirely functional.
This commit is contained in:
parent
45964e4b46
commit
f8abdbf91a
|
@ -0,0 +1,295 @@
|
|||
package org.dolphinemu.dolphinemu.utils;
|
||||
|
||||
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;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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.e("EGLHelper", "Error initializing EGL.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e("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: Renderer <br/>
|
||||
* Index 2: Version <br/>
|
||||
* Index 3: Extensions <br/>
|
||||
*
|
||||
* @return information retrieved through EGL.
|
||||
*/
|
||||
public String[] getEGLInfo()
|
||||
{
|
||||
String[] info = {
|
||||
mGL.glGetString(GL10.GL_VENDOR),
|
||||
mGL.glGetString(GL10.GL_RENDERER),
|
||||
mGL.glGetString(GL10.GL_VERSION),
|
||||
mGL.glGetString(GL10.GL_EXTENSIONS),
|
||||
};
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 boolean detect()
|
||||
{
|
||||
// Attributes for a visual in RGBA format with at least 8 bits per color.
|
||||
int[] attribs = {
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
// Get total number of configs available.
|
||||
int[] numConfigs = new int[1];
|
||||
if (!mEGL.eglChooseConfig(mDisplay, attribs, null, 0, numConfigs))
|
||||
{
|
||||
Log.e("EGLHelper", "Error retrieving number of EGL configs available.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now get all the configurations
|
||||
mEGLConfigs = new EGLConfig[numConfigs[0]];
|
||||
if (!mEGL.eglChooseConfig(mDisplay, attribs, mEGLConfigs, mEGLConfigs.length, numConfigs))
|
||||
{
|
||||
Log.e("EGLHelper", "Error retrieving all EGL configs.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mEGLConfigs.length; i++)
|
||||
{
|
||||
int[] attribVal = new int[1];
|
||||
boolean ret = mEGL.eglGetConfigAttrib(mDisplay, mEGLConfigs[i], 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;
|
||||
}
|
||||
}
|
||||
|
||||
return 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_RENDERABLE_TYPE, renderableType,
|
||||
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:
|
||||
attribs[5] = EGL_OPENGL_ES_BIT;
|
||||
ctx_attribs[1] = 1;
|
||||
break;
|
||||
|
||||
case EGL_OPENGL_BIT:
|
||||
attribs[5] = EGL_OPENGL_BIT;
|
||||
ctx_attribs[0] = EGL10.EGL_NONE;
|
||||
break;
|
||||
|
||||
case EGL_OPENGL_ES3_BIT_KHR:
|
||||
attribs[5] = EGL_OPENGL_ES3_BIT_KHR;
|
||||
ctx_attribs[1] = 3;
|
||||
break;
|
||||
|
||||
case EGL_OPENGL_ES2_BIT:
|
||||
default: // Fall-back to GLES 2.
|
||||
attribs[5] = EGL_OPENGL_ES2_BIT;
|
||||
ctx_attribs[1] = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue