jogamp.opengl.egl.EGLContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jogl-all-android Show documentation
Show all versions of jogl-all-android Show documentation
Java™ Binding for the OpenGL® API (Android)
The newest version!
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2011 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
* ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
* DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package jogamp.opengl.egl;
import java.nio.IntBuffer;
import java.util.Map;
import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
import com.jogamp.nativewindow.AbstractGraphicsDevice;
import com.jogamp.opengl.GLCapabilitiesImmutable;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLException;
import com.jogamp.opengl.GLProfile;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
import jogamp.opengl.egl.EGLExtImpl;
import jogamp.opengl.egl.EGLExtProcAddressTable;
import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.nio.Buffers;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
import com.jogamp.opengl.GLRendererQuirks;
import com.jogamp.opengl.egl.EGL;
import com.jogamp.opengl.egl.EGLExt;
public class EGLContext extends GLContextImpl {
// Table that holds the addresses of the native C-language entry points for
// EGL extension functions.
private EGLExtProcAddressTable eglExtProcAddressTable;
private EGLExtImpl eglExtImpl;
static final int CTX_PROFILE_COMPAT = GLContext.CTX_PROFILE_COMPAT;
static final int CTX_PROFILE_CORE = GLContext.CTX_PROFILE_CORE;
static final int CTX_PROFILE_ES = GLContext.CTX_PROFILE_ES;
public static String getGLProfile(final int major, final int minor, final int ctp) throws GLException {
return GLContext.getGLProfile(major, minor, ctp);
}
EGLContext(final GLDrawableImpl drawable,
final GLContext shareWith) {
super(drawable, shareWith);
}
@Override
protected void resetStates(final boolean isInit) {
eglExtProcAddressTable = null;
eglExtImpl = null;
super.resetStates(isInit);
}
@Override
public Object getPlatformGLExtensions() {
return getEGLExt();
}
public final EGLExt getEGLExt() {
return eglExtImpl;
}
@Override
public final ProcAddressTable getPlatformExtProcAddressTable() {
return eglExtProcAddressTable;
}
@Override
protected Map getFunctionNameMap() { return null; }
@Override
protected Map getExtensionNameMap() { return null; }
@Override
public final boolean isGLReadDrawableAvailable() {
return true;
}
@Override
protected void makeCurrentImpl() throws GLException {
final long dpy = drawable.getNativeSurface().getDisplayHandle();
if ( !EGL.eglMakeCurrent(dpy, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
throw new GLException("Error making context " + toHexString(contextHandle) +
" current on Thread " + getThreadName() +
" with display " + toHexString(dpy) +
", drawableWrite " + toHexString(drawable.getHandle()) +
", drawableRead "+ toHexString(drawableRead.getHandle()) +
" - Error code " + toHexString(EGL.eglGetError()) + ", " + this);
}
}
@Override
protected void releaseImpl() throws GLException {
if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT)) {
throw new GLException("Error freeing OpenGL context " + toHexString(contextHandle) +
": error code " + toHexString(EGL.eglGetError()));
}
}
@Override
protected void destroyImpl() throws GLException {
destroyContextARBImpl(contextHandle);
}
@Override
protected void destroyContextARBImpl(final long _context) {
if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), _context)) {
final int eglError = EGL.eglGetError();
if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */
throw new GLException("Error destroying OpenGL context " + toHexString(_context) +
": error code " + toHexString(eglError));
}
}
}
private static final int ctx_attribs_idx_major = 0;
private static final int ctx_attribs_rom[] = {
/* 0 */ EGLExt.EGL_CONTEXT_MAJOR_VERSION_KHR, 0, // alias of EGL.EGL_CONTEXT_CLIENT_VERSION
/* 2 */ EGL.EGL_NONE, EGL.EGL_NONE, // EGLExt.EGL_CONTEXT_MINOR_VERSION_KHR
/* 4 */ EGL.EGL_NONE, EGL.EGL_NONE, // EGLExt.EGL_CONTEXT_FLAGS_KHR
/* 6 */ EGL.EGL_NONE, EGL.EGL_NONE, // EGLExt.EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR
/* 8 */ EGL.EGL_NONE, EGL.EGL_NONE, // EGLExt.EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
/* 10 */ EGL.EGL_NONE
};
@Override
protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int reqMajor, final int reqMinor) {
final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
final EGLGraphicsDevice device = (EGLGraphicsDevice) config.getScreen().getDevice();
final long eglDisplay = device.getHandle();
final long eglConfig = config.getNativeConfig();
final EGLDrawableFactory factory = (EGLDrawableFactory) drawable.getFactoryImpl();
final boolean hasFullOpenGLAPISupport = factory.hasOpenGLDesktopSupport();
final boolean useKHRCreateContext = factory.hasDefaultDeviceKHRCreateContext();
final boolean ctDesktopGL = 0 == ( CTX_PROFILE_ES & ctp );
final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ;
final boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ;
final boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ;
if(DEBUG) {
System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: Start "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")
+ ", useKHRCreateContext "+useKHRCreateContext
+ ", OpenGL API Support "+hasFullOpenGLAPISupport
+ ", device "+device);
}
if ( 0 == eglDisplay ) {
throw new GLException("Error: attempted to create an OpenGL context without a display connection");
}
if ( 0 == eglConfig ) {
throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration");
}
/**
* It has been experienced w/ Mesa 10.3.2 (EGL 1.4/Gallium)
* that even though initial OpenGL context can be created w/o 'EGL_KHR_create_context',
* switching the API via 'eglBindAPI(EGL_OpenGL_API)' the latter 'eglCreateContext(..)' fails w/ EGL_BAD_ACCESS.
* Hence we require both: OpenGL API support _and_ 'EGL_KHR_create_context'.
*
* FIXME: Evaluate this issue in more detail!
*
* FIXME: Utilization of eglBindAPI(..) must be re-evaluated in case we mix ES w/ OpenGL, see EGL 1.4 spec.
* This is due to new semantics, i.e. API is bound on a per thread base,
* hence it must be switched before makeCurrent w/ different APIs, see:
* eglWaitClient();
*/
if( ctDesktopGL && !hasFullOpenGLAPISupport ) {
if(DEBUG) {
System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: DesktopGL not avail "+getGLVersion(reqMajor, reqMinor, ctp, "@creation"));
}
return 0; // n/a
}
try {
if( hasFullOpenGLAPISupport && device.getEGLVersion().compareTo(Version1_2) >= 0 ) {
EGL.eglWaitClient(); // EGL >= 1.2
}
if( !EGL.eglBindAPI( ctDesktopGL ? EGL.EGL_OPENGL_API : EGL.EGL_OPENGL_ES_API) ) {
throw new GLException("Caught: eglBindAPI to "+(ctDesktopGL ? "ES" : "GL")+" failed , error "+toHexString(EGL.eglGetError())+" - "+getGLVersion(reqMajor, reqMinor, ctp, "@creation"));
}
} catch (final GLException glex) {
if (DEBUG) {
ExceptionUtils.dumpThrowable("", glex);
}
}
final int useMajor;
if( reqMajor >= 3 &&
GLRendererQuirks.existStickyDeviceQuirk( GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) {
useMajor = 2;
} else {
useMajor = reqMajor;
}
final IntBuffer attribs = Buffers.newDirectIntBuffer(ctx_attribs_rom);
if( useKHRCreateContext ) {
attribs.put(ctx_attribs_idx_major + 1, useMajor);
int index = ctx_attribs_idx_major + 2;
if( reqMinor >= 0 ) {
attribs.put(index + 0, EGLExt.EGL_CONTEXT_MINOR_VERSION_KHR);
attribs.put(index + 1, reqMinor);
index += 2;
}
if( ctDesktopGL && ( useMajor > 3 || useMajor == 3 && reqMinor >= 2 ) ) {
attribs.put(index + 0, EGLExt.EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
if( ctBwdCompat ) {
attribs.put(index + 1, EGLExt.EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
} else {
attribs.put(index + 1, EGLExt.EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR);
}
index += 2;
}
int flags = 0;
if( ctDesktopGL && useMajor >= 3 && !ctBwdCompat && ctFwdCompat ) {
flags |= EGLExt.EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
}
if( ctDebug ) {
flags |= EGLExt.EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
}
// TODO: flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
if( 0 != flags ) {
attribs.put(index + 0, EGLExt.EGL_CONTEXT_FLAGS_KHR);
attribs.put(index + 1, flags);
index += 2;
}
if(DEBUG) {
System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: attrs.1: major "+useMajor+", flags "+toHexString(flags)+", index "+index);
}
} else {
attribs.put(ctx_attribs_idx_major + 1, useMajor);
if(DEBUG) {
System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: attrs.2: major "+useMajor);
}
}
long ctx=0;
try {
ctx = EGL.eglCreateContext(eglDisplay, eglConfig, share, attribs);
} catch (final RuntimeException re) {
if(DEBUG) {
System.err.println(getThreadName()+": Info: EGLContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(reqMajor, reqMinor, ctp, "@creation"));
ExceptionUtils.dumpThrowable("", re);
}
}
if(0!=ctx) {
if (!EGL.eglMakeCurrent(eglDisplay, drawable.getHandle(), drawableRead.getHandle(), ctx)) {
if(DEBUG) {
System.err.println(getThreadName()+": EGLContext.createContextARBImpl couldn't make current "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")+" - error "+toHexString(EGL.eglGetError()));
}
// release & destroy
EGL.eglMakeCurrent(eglDisplay, EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT);
EGL.eglDestroyContext(eglDisplay, ctx);
ctx = 0;
} else if (DEBUG) {
System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: OK "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")+", share "+share+", direct "+direct);
}
} else if (DEBUG) {
System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: NO "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")+" - error "+toHexString(EGL.eglGetError()));
}
return ctx;
}
@Override
protected boolean createImpl(final long shareWithHandle) throws GLException {
final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
final GLProfile glp = glCaps.getGLProfile();
final boolean createContextARBAvailable = isCreateContextARBAvail(device);
if(DEBUG) {
System.err.println(getThreadName() + ": EGLContext.createImpl: START "+glCaps+", share "+toHexString(shareWithHandle));
System.err.println(getThreadName() + ": Use ARB[avail["+getCreateContextARBAvailStr(device)+
"] -> "+createContextARBAvailable+"]]");
}
if( createContextARBAvailable ) {
contextHandle = createContextARB(shareWithHandle, true);
if (DEBUG) {
if( 0 != contextHandle ) {
System.err.println(getThreadName() + ": createImpl: OK (ARB) on eglDevice "+device+
", eglConfig "+config+", "+glp+", shareWith "+toHexString(shareWithHandle)+", error "+toHexString(EGL.eglGetError()));
} else {
System.err.println(getThreadName() + ": createImpl: NOT OK (ARB) - creation failed on eglDevice "+device+
", eglConfig "+config+", "+glp+", shareWith "+toHexString(shareWithHandle)+", error "+toHexString(EGL.eglGetError()));
}
}
} else {
contextHandle = 0;
}
if( 0 == contextHandle ) {
if( !glp.isGLES() ) {
throw new GLException(getThreadName()+": Unable to create desktop OpenGL context(ARB n/a) on eglDevice "+device+
", eglConfig "+config+", "+glp+", shareWith "+toHexString(shareWithHandle)+", error "+toHexString(EGL.eglGetError()));
}
final int[] reqMajorCTP = new int[] { 0, 0 };
GLContext.getRequestMajorAndCompat(glp, reqMajorCTP);
reqMajorCTP[1] |= getContextCreationFlags();
contextHandle = createContextARBImpl(shareWithHandle, true, reqMajorCTP[1], reqMajorCTP[0], 0);
if( 0 == contextHandle ) {
throw new GLException(getThreadName()+": Unable to create ES OpenGL context on eglDevice "+device+
", eglConfig "+config+", "+glp+", shareWith "+toHexString(shareWithHandle)+", error "+toHexString(EGL.eglGetError()));
}
if( !setGLFunctionAvailability(true, reqMajorCTP[0], 0, reqMajorCTP[1], false /* strictMatch */, false /* withinGLVersionsMapping */) ) {
EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT);
EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle);
contextHandle = 0;
throw new GLException("setGLFunctionAvailability !strictMatch failed");
}
}
if (DEBUG) {
System.err.println(getThreadName() + ": createImpl: Created OpenGL context 0x" +
Long.toHexString(contextHandle) +
",\n\twrite surface 0x" + Long.toHexString(drawable.getHandle()) +
",\n\tread surface 0x" + Long.toHexString(drawableRead.getHandle())+
",\n\t"+this+
",\n\tsharing with 0x" + Long.toHexString(shareWithHandle));
}
return true;
}
@Override
protected final void updateGLXProcAddressTable(final String contextFQN, final GLDynamicLookupHelper dlh) {
if( null == dlh ) {
throw new GLException("No GLDynamicLookupHelper for "+this);
}
final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
final String key = "EGL-"+adevice.getUniqueID();
// final String key = contextFQN;
if (DEBUG) {
System.err.println(getThreadName() + ": Initializing EGLextension address table: "+key);
}
ProcAddressTable table = null;
synchronized(mappedContextTypeObjectLock) {
table = mappedGLXProcAddress.get( key );
}
if(null != table) {
eglExtProcAddressTable = (EGLExtProcAddressTable) table;
if(DEBUG) {
System.err.println(getThreadName() + ": GLContext EGL ProcAddressTable reusing key("+key+") -> "+toHexString(table.hashCode()));
}
if( null == eglExtImpl || eglExtImpl.getProcAdressTable() != eglExtProcAddressTable ) {
eglExtImpl = new EGLExtImpl(this, eglExtProcAddressTable);
}
} else {
eglExtProcAddressTable = new EGLExtProcAddressTable(new GLProcAddressResolver());
resetProcAddressTable(eglExtProcAddressTable, dlh);
synchronized(mappedContextTypeObjectLock) {
mappedGLXProcAddress.put(key, eglExtProcAddressTable);
if(DEBUG) {
System.err.println(getThreadName() + ": GLContext EGL ProcAddressTable mapping key("+key+") -> "+toHexString(eglExtProcAddressTable.hashCode()));
}
}
eglExtImpl = new EGLExtImpl(this, eglExtProcAddressTable);
}
}
@Override
protected final StringBuilder getPlatformExtensionsStringImpl() {
final EGLGraphicsDevice device = (EGLGraphicsDevice) drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
return getPlatformExtensionsStringImpl(device);
}
final static StringBuilder getPlatformExtensionsStringImpl(final EGLGraphicsDevice device) {
final StringBuilder sb = new StringBuilder();
device.lock();
try{
final long handle = device.getHandle();
if (DEBUG) {
System.err.println("EGL PlatformExtensions: Device "+device);
EGLDrawableFactory.dumpEGLInfo("EGL PlatformExtensions: ", handle);
}
if( device.getEGLVersion().compareTo(Version1_5) >= 0 ) {
final String ret = EGL.eglQueryString(EGL.EGL_NO_DISPLAY, EGL.EGL_EXTENSIONS);
if (DEBUG) {
System.err.println("EGL extensions (Client): " + ret);
}
sb.append(ret).append(" ");
}
if( 0 != handle ) {
final String ret = EGL.eglQueryString(handle, EGL.EGL_EXTENSIONS);
if (DEBUG) {
System.err.println("EGL extensions (Server): " + ret);
}
sb.append(ret).append(" ");
}
} finally {
device.unlock();
}
return sb;
}
@Override
protected final Integer setSwapIntervalImpl2(final int interval) {
if( !drawable.getChosenGLCapabilities().isOnscreen() ||
hasRendererQuirk(GLRendererQuirks.NoSetSwapInterval) ) {
return null;
}
final int useInterval;
if( 0 > interval ) {
useInterval = Math.abs(interval);
} else {
useInterval = interval;
}
if( EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), useInterval) ) {
return Integer.valueOf(useInterval);
}
return null;
}
static long eglGetProcAddress(final long eglGetProcAddressHandle, final String procname)
{
if (0 == eglGetProcAddressHandle) {
throw new GLException("Passed null pointer for method \"eglGetProcAddress\"");
}
return dispatch_eglGetProcAddress0(procname, eglGetProcAddressHandle);
}
/** Entry point to C language function: __EGLFuncPtr eglGetProcAddress(const char * procname)
Part of EGL_VERSION_1_X
*/
static private native long dispatch_eglGetProcAddress0(String procname, long procAddress);
//
// Accessible ..
//
/* pp */ static final boolean isGLES1(final int majorVersion, final int ctxOptions) {
return 0 != ( ctxOptions & GLContext.CTX_PROFILE_ES ) && majorVersion == 1 ;
}
/* pp */ static final boolean isGLES2ES3(final int majorVersion, final int ctxOptions) {
if( 0 != ( ctxOptions & CTX_PROFILE_ES ) ) {
return 2 == majorVersion || 3 == majorVersion;
} else {
return false;
}
}
/* pp */ static final boolean isGLDesktop(final int ctxOptions) {
return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
}
protected static StringBuilder getGLProfile(final StringBuilder sb, final int ctp) {
return GLContext.getGLProfile(sb, ctp);
}
/* pp */ int getContextOptions() { return ctxOptions; }
protected static void remapAvailableGLVersions(final AbstractGraphicsDevice fromDevice, final AbstractGraphicsDevice toDevice) {
GLContextImpl.remapAvailableGLVersions(fromDevice, toDevice);
}
protected static synchronized void setMappedGLVersionListener(final MappedGLVersionListener mvl) {
GLContextImpl.setMappedGLVersionListener(mvl);
}
protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) {
return GLContext.getGLVersion(major, minor, ctp, gl_version);
}
protected static String toHexString(final int hex) {
return GLContext.toHexString(hex);
}
protected static String toHexString(final long hex) {
return GLContext.toHexString(hex);
}
//----------------------------------------------------------------------
// Currently unimplemented stuff
//
@Override
protected void copyImpl(final GLContext source, final int mask) throws GLException {
throw new GLException("Not yet implemented");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy