summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-09-15 16:54:52 +0200
committerSven Gothel <[email protected]>2012-09-15 16:54:52 +0200
commit4dd44b985fe0541be3a3bcd9045d201ed3ca2cc5 (patch)
treee14c927a1da9f089297aa291dcd69f2f39b4f15e /src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
parent9036376b7806a5fc61590bf49404eb71830de92f (diff)
Seamless Integration of an FBObject based GLFBODrawable as GLOffscreenAutoDrawable.FBO and as an OffscreenLayerSurface's drawable (OSX) - Fix Bugs 569 and 599
Summary: ========= The new FBObject based GLFBODrawable implementation allows the seamless utilization of FBO offscreen rendering in single buffer, double buffer and MSAA mode. The GLFBODrawable uses a parent drawable based on a dummy surface to allow a GLOffscreenAutoDrawable.FBO creation or a mutable surface supporting an existing offscreen layer surface (OSX CALayer). Offscreen GLDrawable's and GLOffscreenAutoDrawable's can be selected via the GLCapabilities. If simply !onscreen is selected in the caps instance w/o enabling FBO, PBuffer or Bitmap, the factory will automatically choose regarding availability: FBO > PBuffer > Bitmap Double buffering is supported in MSAA more (intrinsic) and explicit in non MSAA. It is preferred when delivering resources (texture id's or framebuffer names) to a shared GLContext. This is demonstrated in (emulates our OSX CALayer implementation): TestFBOOffThreadSharedContextMix2DemosES2NEWT, TestFBOOnThreadSharedContext1DemoES2NEWT and with the OSX JAWT OffscreenLayerSurface itself. FBO is the preferred choice. +++ Offscreen drawables can be resized while maintaining a bound GLContext (e.g. w/ GLAutoDrawable). Previously both, drawable and context, needed to be destroyed and recreated at offscreen resize. Common implementation in GLDrawableHelper is used in the implementations (NEWT's GLWindow, AWT GLCanvas, SWT GLCanvas). +++ Tested: ======= Manually run all unit tests on: - Linux x86_64 NVidia/AMD/Mesa3d(ES) - OSX x86_64 NVidia - Windows x86_64 NVidia - Android arm Mali-400/Tegra-2 No regressions. Disclaimer: =========== This feature is committed almost in one patch. Both previous commits were introducing / fixing the capabilities behavior: 90d45928186f2be99999461cfe45f76a783cc961 9036376b7806a5fc61590bf49404eb71830de92f I have to appologize for the huge size and impact (files and platforms) of this commit however, I could not find a better way to inject this feature in one sane piece. NativeWindow Details: ===================== Complete decoupling of platform impl. detail of surfaces implementing ProxySurface. Used to generalize dummy surfaces and EGL surfaces on top of a native platform surface. - ProxySurface.UpstreamSurfaceHook -> UpstreamSurfaceHook - abstract class ProxySurface -> interface ProxySurface + ProxySurfaceImpl - Misc. implementations JOGL Details: ===================== FBOObject: API Change / Simplification & Usability - Removed reference counter to remove complexity, allow user to choose. - Add 'dispose' flag for detachColorbuffer(..), allowing to keep attachment alive - Fix equals operation of Attachment - Check pre-exising GL errors - Interface Colobuffer gets lifecycle methods - Add static factory methods to create Attachments w/o FBObject instance - Reset: - Clip min size to 1 - Keep alive samplingSink, i.e. don't issue resetMSAATexture2DSink(..). It gets called at syncFramebuffer()/use(..) later on before actual usage. This allows the consumer to utilize the GL_FRONT buffer until (e.g.) swap. - misc bugfixes GLOffscreenAutoDrawable: API Change - Reloc and interfacing - class com.jogamp.opengl.OffscreenAutoDrawable -> javax.media.opengl.* interfaces GLOffscreenAutoDrawable extends GLAutoDrawable GLOffscreenAutoDrawable.FBO extends GLOffscreenAutoDrawable, GLFBODrawable - Added general implementation and FBO specialization - Replacing GLPBuffer (deprecated) .. usable for any offscreen GLDrawable via factory GLAutoDrawable: - Add 'GLDrawable getDelegatedDrawable()' - Refine documentation of setContext(..), remove disclaimer and fixme tags GLDrawableFactory: - Refine API doc and it's selection mechanism for offscreen. - Add createOffscreenDrawable(..) - Add createOffscreenAutoDrawable(..) - Add canCreateFBO(..) - Mark createGLPbuffer(..) deprectated Mark GLPBuffer deprecated New: GLFBODrawable extends GLDrawable GLCanvas (AWT and SWT): Add offscreen resize support w/o GLContext recreation GLAutoDrawableBase .. GLWindow: - Add offscreen resize support w/o GLContext recreation - Remove double swapBuffer call - GLBase/GLContext: - Add: - boolean hasBasicFBOSupport() - boolean hasFullFBOSupport() - int getMaxRenderbufferSamples() - boolean isTextureFormatBGRA8888Available() GLContext: Fix version detection and hasGLSL() - Version detection in setGLFunctionAvailability(..) - Query GL_VERSION ASAP and parse it and compare w/ given major/minor - Use parsed version if valid and lower than given _or_ given is invalid. - Use validated version for caching (procaddr, ..), version number, etc. - Fix hasGLSL() Since 'isGL2ES2()' is true if 'isGL2()' and the latter simply alows GL 1.*, we confine the result to a GL >= 2.0 on desktops. FIXME: May consider GL 1.5 w/ extensions. - return isGL2ES2(); + return isGLES2() || + isGL3() || + isGL2() && ctxMajorVersion>1 ; GLDrawableImpl: - Add 'associateContext(GLContext, boolean)' allowing impl. to have a (weak) reference list of bound context. This is was pulled up from the OSX specific drawable impl. - swapBuffersImpl() -> swapBuffersImpl(boolean doubleBuffered) and call it regardless of single buffering. This is required to propagate this event to impl. properly, i.e. FBODrawable requires a swap notification. - Clarify 'contextMadeCurrent(..)' protocol GLDrawableHelper: - Add resize and recreate offscreen drawable util method - Simplify required init/reshape calls for GLEventListener - GLGraphicsConfigurationUtil: - fixWinAttribBitsAndHwAccel: Reflect sharede context hw-accel bits - OSX has no offscreen bitmap, use pbuffer - use proper offscreen auto selection if offscreen and no modes are set EGL Context/Drawable/DrawableFactory: Abstract native platform code out of base classes - Use EGLWrappedSurface w/ UpstreamSurfaceHook to handle upstream (X11, WGL, ..) lifecycle - in case the EGL resource is hooked up on it. Invisible dummy surfaces: All platforms - size is now reduced to 64x64 and decoupled of actual generic mutable size - fix device lifecycle, no more leaks +++ OSX ==== Enable support for GLFBODrawableImpl in offscreen CALayer mode - NSOpenGLImpl: hooks to calayer native code - calayer code: - allows pbuffer and texures (FBO) - decouple size and draw calls avoiding flickering - enable auto resize of calayer tree MacOSXCGLContext: - NSOpenGLImpl: - Fix false pbuffer 'usage', validate the pointer - If !pbuffer, copy other window mode bits of caps - MacOSXCGLGraphicsConfiguration: - Only assume pbuffer if !onscreen - Remove reference of native pixelformat pointer Native code: - use 'respondsToSelector:' query before calling 'new' methods avoiding an error message where unsuported (prev. OSX versions) - if monitor refresh-rate is queried 0, set to default 60hz - add missing NSAutoreleasePool decoration +++ Android / NEWT: =============== Issue setVisible(..) w/o wait, i.e. queue on EDT, @Android surfaceChanged() callback. Otherwise we could deadlock: setVisible(..) -> EDT -> setVisibleImpl(..) -> 'GL-display'. the latter may may cause havoc while Android-EDT is blocked [until it's return].
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java')
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java127
1 files changed, 75 insertions, 52 deletions
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index e1e253d35..4f965f620 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -48,18 +48,21 @@ import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.MutableSurface;
-import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
-import javax.media.opengl.GLCapabilities;
+import javax.media.nativewindow.UpstreamSurfaceHook;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLFBODrawable;
+import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+import com.jogamp.nativewindow.DelegatedUpstreamSurfaceHookWithSurfaceSize;
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
/** Extends GLDrawableFactory with a few methods for handling
@@ -67,6 +70,7 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration;
Independent Bitmaps on Windows, pixmaps on X11). Direct access to
these GLDrawables is not supplied directly to end users, though
they may be instantiated by the GLJPanel implementation. */
+@SuppressWarnings("deprecation")
public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
@@ -141,55 +145,53 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
if(null != ols) {
// layered surface -> Offscreen/[FBO|PBuffer]
- final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable();
- chosenCapsMod.setOnscreen(false);
- chosenCapsMod.setDoubleBuffered(false);
- /* if( isFBOAvailable ) { // FIXME JAU: FBO n/a yet
- chosenCapsMod.setFBO(true);
- } else */
- if( canCreateGLPbuffer(adevice) ) {
- chosenCapsMod.setPBuffer(true);
- } else {
- chosenCapsMod.setFBO(false);
- chosenCapsMod.setPBuffer(false);
+ final boolean isPbufferAvailable = canCreateGLPbuffer(adevice) ;
+ if(!isPbufferAvailable && !isFBOAvailable) {
+ throw new GLException("Neither FBO nor Pbuffer is available for "+target);
}
+ final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, isFBOAvailable, isPbufferAvailable);
config.setChosenCapabilities(chosenCapsMod);
+ ols.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
- System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target);
+ System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer");
+ System.err.println("chosenCaps: "+chosenCaps);
+ System.err.println("chosenCapsMod: "+chosenCapsMod);
+ System.err.println("OffscreenLayerSurface: **** "+ols);
+ System.err.println("Target: **** "+target);
+ Thread.dumpStack();
}
if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
}
- if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) {
- // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
- final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
- result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ if( chosenCapsMod.isFBO() && isFBOAvailable ) {
+ // target surface is already a native one
+ result = createFBODrawableImpl(target, chosenCapsMod, 0);
} else {
result = createOffscreenDrawableImpl(target);
}
} else if(chosenCaps.isOnscreen()) {
// onscreen
+ final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps);
+ config.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable: "+target);
}
result = createOnscreenDrawableImpl(target);
} else {
// offscreen
- final GLCapabilitiesImmutable reqCaps = (GLCapabilitiesImmutable)config.getRequestedCapabilities();
if(DEBUG) {
- System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO req / chosen - avail, PBuffer: "+reqCaps.isFBO()+" / "+chosenCaps.isFBO()+" - "+isFBOAvailable+", "+chosenCaps.isPBuffer()+": "+target);
+ System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO chosen / avail, PBuffer: "+
+ chosenCaps.isFBO()+" / "+isFBOAvailable+", "+chosenCaps.isPBuffer()+": "+target);
}
if( ! ( target instanceof MutableSurface ) ) {
- throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target);
+ throw new IllegalArgumentException("Passed NativeSurface must implement MutableSurface for offscreen: "+target);
}
- if( reqCaps.isFBO() && isFBOAvailable ) {
- // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
- final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
- result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ if( chosenCaps.isFBO() && isFBOAvailable ) {
+ // need to hook-up a native dummy surface since source may not have
+ final ProxySurface dummySurface = createDummySurfaceImpl(adevice, true, chosenCaps, null, 64, 64);
+ dummySurface.setUpstreamSurfaceHook(new DelegatedUpstreamSurfaceHookWithSurfaceSize(dummySurface.getUpstreamSurfaceHook(), target));
+ result = createFBODrawableImpl(dummySurface, chosenCaps, 0);
} else {
- final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable();
- chosenCapsMod.setDoubleBuffered(false);
- config.setChosenCapabilities(chosenCapsMod);
result = createOffscreenDrawableImpl(target);
}
}
@@ -211,7 +213,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
//
- // PBuffer Offscreen GLDrawable construction
+ // PBuffer Offscreen GLAutoDrawable construction
//
@Override
@@ -239,7 +241,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
GLDrawableImpl drawable = null;
device.lock();
try {
- drawable = (GLDrawableImpl) createGLDrawable( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
+ drawable = createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser,
+ new UpstreamSurfaceHookMutableSize(width, height) ) );
if(null != drawable) {
drawable.setRealized(true);
}
@@ -247,10 +250,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
device.unlock();
}
- if(null==drawable) {
- throw new GLException("Could not create Pbuffer drawable for: "+device+", "+capsChosen+", "+width+"x"+height);
- }
- return new GLPbufferImpl( drawable, shareWith, true);
+ return new GLPbufferImpl( drawable, (GLContextImpl) drawable.createContext(shareWith) );
}
//---------------------------------------------------------------------------
@@ -258,6 +258,29 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
// Offscreen GLDrawable construction
//
+ public final boolean canCreateFBO(AbstractGraphicsDevice deviceReq, GLProfile glp) {
+ AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ if(null == device) {
+ throw new GLException("No shared device for requested: "+deviceReq);
+ }
+ return GLContext.isFBOAvailable(device, glp);
+ }
+
+ @Override
+ public GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice deviceReq,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser,
+ int width, int height,
+ GLContext shareWith) {
+ final GLDrawable drawable = createOffscreenDrawable( deviceReq, capsRequested, chooser, width, height );
+ drawable.setRealized(true);
+ final GLContext context = drawable.createContext(shareWith);
+ if(drawable instanceof GLFBODrawableImpl) {
+ return new GLOffscreenAutoDrawableImpl.FBOImpl( (GLFBODrawableImpl)drawable, context, null, null );
+ }
+ return new GLOffscreenAutoDrawableImpl( drawable, context, null, null);
+ }
+
@Override
public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
@@ -274,10 +297,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested,
GLContext.isFBOAvailable(device, capsRequested.getGLProfile()),
canCreateGLPbuffer(device));
+
if( capsChosen.isFBO() ) {
device.lock();
try {
- return createFBODrawableImpl(device, capsRequested, chooser, width, height);
+ final ProxySurface dummySurface = createDummySurfaceImpl(device, true, capsRequested, null, width, height);
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
+ return new GLFBODrawableImpl.ResizeableImpl(this, dummyDrawable, dummySurface, capsChosen, 0);
} finally {
device.unlock();
}
@@ -285,20 +311,17 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
device.lock();
try {
- return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
+ return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser,
+ new UpstreamSurfaceHookMutableSize(width, height) ) );
} finally {
device.unlock();
}
}
- /** Creates a platform independent offscreen FBO GLDrawable implementation */
- protected GLDrawable createFBODrawableImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
- int initialWidth, int initialHeight) {
- final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
- final NativeSurface dummySurface = createDummySurfaceImpl(device, true, dummyCaps, null, 64, 64);
+ /** Creates a platform independent FBO offscreen GLDrawable */
+ protected GLFBODrawable createFBODrawableImpl(NativeSurface dummySurface, GLCapabilitiesImmutable fboCaps, int textureUnit) {
final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
-
- return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, initialWidth, initialHeight, 0 /* textureUnit */);
+ return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, fboCaps, textureUnit);
}
/** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */
@@ -318,15 +341,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* @param capsChosen
* @param capsRequested
* @param chooser the custom chooser, may be null for default
- * @param width the initial width
- * @param height the initial height
- * @param lifecycleHook optional control of the surface's lifecycle
+ * @param upstreamHook surface size information and optional control of the surface's lifecycle
* @return the created {@link MutableSurface} instance w/o defined surface handle
*/
protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook);
+ GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook);
/**
* A dummy surface is not visible on screen and will not be used to render directly to,
@@ -341,9 +362,9 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* @param width the initial width
* @param height the initial height
*
- * @return the created {@link MutableSurface} instance w/o defined surface handle
+ * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}.
*/
- public NativeSurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ public ProxySurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
int width, int height) {
final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
@@ -369,9 +390,11 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* otherwise <code>device</code> instance is used as-is.
* @param requestedCaps
* @param chooser the custom chooser, may be null for default
- * @param width the initial width
- * @param height the initial height
- * @return the created {@link MutableSurface} instance w/o defined surface handle
+ * @param width the initial width as returned by {@link NativeSurface#getWidth()}, not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()}, not the actual dummy surface height,
+ * The latter is platform specific and small
+ * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}.
*/
public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height);