From 203f795cd3332d6d61c210c8b7901de069d9166a Mon Sep 17 00:00:00 2001
From: Sven Gothel
+ * Please see {@link #setStorage(GL, Attachment)} for details.
+ *
+ * Implementations are allowed to specialize {@link FBObject.Attachment.StorageDefinition}
+ * for the special use-case of:
+ *
+ * // Renderbuffer (Color, Debt, Stencil, ..) storage definition w/o multisamples
+ * gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, a.format, a.getWidth(), a.getHeight());
+ * // Renderbuffer (Color, Debt, Stencil, ..) storage definition with multisamples
+ * gl.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, a.format, a.getWidth(), a.getHeight());
+ * // TextureAttachment
+ * gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
+ *
+ * The storage is setup within {@link Attachment#initialize(GL)} and hence the {@link Attachment}
+ * instance's {@link Attachment#setStorageDefinition(StorageDefinition)}.
+ *
+ * @param gl current {@link GL} instance
+ * @param a instance of the {@link Attachment} this {@link StorageDefinition} has been assigned to via {@link Attachment#setStorageDefinition(StorageDefinition)}.
+ */
+ public void setStorage(final GL gl, final Attachment a);
+ }
/** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */
public final Type type;
@@ -176,6 +201,9 @@ public class FBObject {
private int name;
+ /** Every implementation needs to have set their default instance via {@link #setStorageDefinition(StorageDefinition). */
+ private StorageDefinition storageDefinition;
+
protected Attachment(final Type type, final int iFormat, final int width, final int height, final int name) {
this.type = type;
this.format = iFormat;
@@ -184,6 +212,17 @@ public class FBObject {
this.name = name;
}
+ /**
+ * Override implementation default {@link StorageDefinition}
+ * @see {@link StorageDefinition#setStorage(GL, Attachment)}
+ */
+ public void setStorageDefinition(final StorageDefinition sd) { this.storageDefinition = sd; }
+
+ /**
+ * Accessor to call {@link StorageDefinition#setStorage(GL, Attachment)} within {@link #initialize(GL)} for implementations of {@link Attachment}.
+ */
+ protected final void setStorage(final GL gl) { storageDefinition.setStorage(gl, this); }
+
/**
* Writes the internal format to the given GLCapabilities object.
* @param caps the destination for format bits
@@ -372,6 +411,7 @@ public class FBObject {
*/
public RenderAttachment(final Type type, final int iFormat, final int samples, final int width, final int height, final int name) {
super(validateType(type), iFormat, width, height, name);
+ this.setStorageDefinition(defStorageDefinition);
this.samples = samples;
}
@@ -432,11 +472,7 @@ public class FBObject {
setName(name[0]);
gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName());
- if( samples > 0 ) {
- ((GL2ES3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight());
- } else {
- gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight());
- }
+ setStorage(gl);
if( checkError ) {
final int glerr = gl.glGetError();
if(GL.GL_NO_ERROR != glerr) {
@@ -451,6 +487,16 @@ public class FBObject {
}
return init;
}
+ private final StorageDefinition defStorageDefinition = new StorageDefinition() {
+ @Override
+ public void setStorage(final GL gl, final Attachment a) {
+ // a == this.super for this instance
+ if( samples > 0 ) {
+ gl.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight());
+ } else {
+ gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight());
+ }
+ } };
@Override
public void free(final GL gl) {
@@ -482,49 +528,6 @@ public class FBObject {
public final TextureAttachment getTextureAttachment() { throw new GLException("Not a TextureAttachment, but ColorAttachment"); }
@Override
public final ColorAttachment getColorAttachment() { return this; }
-
- @Override
- public boolean initialize(final GL gl) throws GLException {
- final boolean init = 0 == getName();
- if( init ) {
- final boolean checkError = DEBUG || GLContext.DEBUG_GL;
- if( checkError ) {
- checkPreGLError(gl);
- }
- final int[] name = new int[] { -1 };
- gl.glGenRenderbuffers(1, name, 0);
- setName(name[0]);
-
- gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName());
- if( getSamples() > 0 ) {
- ((GL2ES3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, getSamples(), format, getWidth(), getHeight());
- } else {
- // FIXME: Need better way to inject the IOS EAGL Layer into FBObject
- // FIXME: May want to implement optional injection of a BufferStorage SPI?
- final GLContext ctx = gl.getContext();
- final Long iosEAGLLayer = (Long) ctx.getAttachedObject("IOS_EAGL_LAYER");
- if( null != iosEAGLLayer ) {
- EAGL.eaglBindDrawableStorageToRenderbuffer(gl.getContext().contextHandle, GL.GL_RENDERBUFFER, iosEAGLLayer.longValue());
- } else {
- gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight());
- }
- }
- if( checkError ) {
- final int glerr = gl.glGetError();
- if(GL.GL_NO_ERROR != glerr) {
- gl.glDeleteRenderbuffers(1, name, 0);
- setName(0);
- throw new GLException("GL Error "+toHexString(glerr)+" while creating "+this);
- }
- }
- if(DEBUG) {
- System.err.println("Attachment.init.X: "+this);
- }
- }
- return init;
- }
-
-
}
/** Texture FBO attachment */
@@ -548,6 +551,7 @@ public class FBObject {
public TextureAttachment(final Type type, final int iFormat, final int width, final int height, final int dataFormat, final int dataType,
final int magFilter, final int minFilter, final int wrapS, final int wrapT, final int name) {
super(validateType(type), iFormat, width, height, name);
+ this.setStorageDefinition(defStorageDefinition);
this.dataFormat = dataFormat;
this.dataType = dataType;
this.magFilter = magFilter;
@@ -604,7 +608,7 @@ public class FBObject {
int glerr = gl.glGetError();
if(GL.GL_NO_ERROR == glerr) {
preTexImage2D = false;
- gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
+ setStorage(gl);
glerr = gl.glGetError();
}
if(GL.GL_NO_ERROR != glerr) {
@@ -613,7 +617,7 @@ public class FBObject {
throw new GLException("GL Error "+toHexString(glerr)+" while creating (pre TexImage2D "+preTexImage2D+") "+this);
}
} else {
- gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
+ setStorage(gl);
}
if(DEBUG) {
System.err.println("Attachment.init.X: "+this);
@@ -621,6 +625,12 @@ public class FBObject {
}
return init;
}
+ private final StorageDefinition defStorageDefinition = new StorageDefinition() {
+ @Override
+ public void setStorage(final GL gl, final Attachment a) {
+ // a == this.super for this instance
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
+ } };
@Override
public void free(final GL gl) {
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index 2e108d3ce..fad77d76d 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -55,6 +55,7 @@ import com.jogamp.nativewindow.OffscreenLayerSurface;
import com.jogamp.nativewindow.ProxySurface;
import com.jogamp.nativewindow.MutableSurface;
import com.jogamp.nativewindow.UpstreamSurfaceHook;
+import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilitiesChooser;
@@ -68,7 +69,6 @@ import com.jogamp.opengl.GLOffscreenAutoDrawable;
import com.jogamp.opengl.GLProfile;
import com.jogamp.common.ExceptionUtils;
-import com.jogamp.common.os.Platform;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.nativewindow.DelegatedUpstreamSurfaceHookWithSurfaceSize;
import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook;
@@ -76,9 +76,6 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
import com.jogamp.opengl.GLAutoDrawableDelegate;
import com.jogamp.opengl.GLRendererQuirks;
-import jogamp.common.os.PlatformPropsImpl;
-
-
/** Extends GLDrawableFactory with a few methods for handling
typically software-accelerated offscreen rendering (Device
Independent Bitmaps on Windows, pixmaps on X11). Direct access to
@@ -264,6 +261,36 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
*/
public abstract GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions);
+ /**
+ * Extends definition of {@link FBObject.Attachment.StorageDefinition}
+ * for general onscreen FBO layer storage requirements.
+ *
+ *
+ *
+ * If a valid unit is returned, i.e. >= 0, a color texturebuffer is used, otherwise a color renderbuffer. + *
+ */ + public int getTextureUnit(); + } + + protected OnscreenFBOColorbufferStorageDefinition getOnscreenFBOColorbufStorageDef() { return null; } + //--------------------------------------------------------------------------- // Dispatching GLDrawable construction in respect to the NativeSurface Capabilities // @@ -273,29 +300,41 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { throw new IllegalArgumentException("Null target"); } final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration(); + final GLCapabilitiesImmutable reqCaps = (GLCapabilitiesImmutable) config.getRequestedCapabilities(); final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); final AbstractGraphicsDevice adevice = config.getScreen().getDevice(); final boolean isFBOAvailable = GLContext.isFBOAvailable(adevice, chosenCaps.getGLProfile()); GLDrawable result = null; adevice.lock(); try { + final OnscreenFBOColorbufferStorageDefinition onscreenFBOColorbufStorageDef = getOnscreenFBOColorbufStorageDef(); final boolean forceOnscreenFBOLayer; - final boolean useFBORendertarget; - if( chosenCaps.isOnscreen() && Platform.OSType.IOS == PlatformPropsImpl.OS_TYPE ) // FIXME: avoid hardcoding? - { + final int fboTextureUnit; + if( reqCaps.isOnscreen() && null != onscreenFBOColorbufStorageDef) { forceOnscreenFBOLayer = true; - useFBORendertarget = true; + fboTextureUnit = onscreenFBOColorbufStorageDef.getTextureUnit(); } else { forceOnscreenFBOLayer = false; - useFBORendertarget = false; + fboTextureUnit = 0; // assume texture unit 0 (default) is used at all } final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true); if(null != ols || forceOnscreenFBOLayer ) { - final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice); - - // layered surface -> Offscreen/[FBO|PBuffer] - if( !chosenCapsMod.isFBO() && !chosenCapsMod.isPBuffer() ) { - throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target); + final GLCapabilitiesImmutable chosenCapsMod0 = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice); + final GLCapabilitiesImmutable chosenCapsMod; + if( forceOnscreenFBOLayer && !onscreenFBOColorbufStorageDef.isDoubleBufferSupported() ) { + chosenCapsMod = GLGraphicsConfigurationUtil.fixDoubleBufferedGLCapabilities(chosenCapsMod0, false); + } else { + chosenCapsMod = chosenCapsMod0; + } + if( forceOnscreenFBOLayer ) { + if( !chosenCapsMod.isFBO() ) { + throw new GLException("FBO is not available for "+chosenCapsMod+", "+target); + } + } else { + // layered surface -> Offscreen/[FBO|PBuffer] + if( !chosenCapsMod.isFBO() && !chosenCapsMod.isPBuffer() ) { + throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target); + } } config.setChosenCapabilities(chosenCapsMod); if( null != ols ) { @@ -303,10 +342,11 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } if(DEBUG) { System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer"); + System.err.println("requestedCaps: "+reqCaps); System.err.println("chosenCaps: "+chosenCaps); System.err.println("chosenCapsMod: "+chosenCapsMod); System.err.println("OffscreenLayerSurface: **** "+ols); - System.err.println("forceOnscreenFBOLayer: **** "+forceOnscreenFBOLayer+", useFBORendertarget "+useFBORendertarget); + System.err.println("forceOnscreenFBOLayer: **** "+forceOnscreenFBOLayer+", fboTextureUnit "+fboTextureUnit); System.err.println("Target: **** "+target); ExceptionUtils.dumpStack(System.err); } @@ -314,7 +354,11 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target); } if( chosenCapsMod.isFBO() ) { - result = createFBODrawableImpl(target, chosenCapsMod, useFBORendertarget?-1:0); + final GLFBODrawableImpl fboDrawable = (GLFBODrawableImpl) createFBODrawableImpl(target, chosenCapsMod, fboTextureUnit); + if( forceOnscreenFBOLayer ) { + fboDrawable.setColorRenderbufferStorageDef(onscreenFBOColorbufStorageDef); + } + result = fboDrawable; } else { result = createOffscreenDrawableImpl(target); } @@ -523,7 +567,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } } - /** Creates a platform independent unrealized FBO offscreen GLDrawable */ + /** + * Creates a platform independent unrealized FBO offscreen GLDrawable + * @param dummySurface used for dummy-drawable and as surface for {@link GLFBODrawable} + * @param fboCaps + * @param textureUnit if valid, i.e. >= 0, signals using a color texturebuffer {@link GLFBODrawable#FBOMODE_USE_TEXTURE}, otherwise a color renderbuffer is used. + * @return + */ protected final GLFBODrawable createFBODrawableImpl(final NativeSurface dummySurface, final GLCapabilitiesImmutable fboCaps, final int textureUnit) { final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface); return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, fboCaps, textureUnit); diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java index 64cca7bdd..ea226b407 100644 --- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -76,6 +76,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { // private DoubleBufferMode doubleBufferMode; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + private FBObject.Attachment.StorageDefinition colorRenderbufferStorageDef; private SwapBufferContext swapBufferContext; public static interface SwapBufferContext { @@ -87,7 +88,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { * @param parent * @param surface * @param fboCaps the requested FBO capabilities - * @param textureUnit if valid, i.e. >= 0, signals {@link #FBOMODE_USE_TEXTURE}, otherwise a color renderbuffer is assumed + * @param textureUnit if valid, i.e. >= 0, signals using a color texturebuffer {@link GLFBODrawable#FBOMODE_USE_TEXTURE}, otherwise a color renderbuffer is used. */ protected GLFBODrawableImpl(final GLDrawableFactoryImpl factory, final GLDrawableImpl parent, final NativeSurface surface, final GLCapabilitiesImmutable fboCaps, final int textureUnit) { @@ -100,6 +101,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { this.texUnit = textureUnit>=0 ? textureUnit : 0; this.samples = fboCaps.getNumSamples(); this.fboResetQuirk = false; + this.colorRenderbufferStorageDef = null; this.swapBufferContext = null; } @@ -117,7 +119,11 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbo); } if(samples > 0 || !useTexture) { - fbo.attachColorbuffer(gl, 0, useAlpha); + final FBObject.ColorAttachment ca = fbo.createColorAttachment(useAlpha); + if( null != colorRenderbufferStorageDef ) { + ca.setStorageDefinition(colorRenderbufferStorageDef); + } + fbo.attachColorbuffer(gl, 0, ca); } else { fbo.attachTexture2D(gl, 0, useAlpha); } @@ -135,7 +141,11 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { { ssink.init(gl, width, height, 0); if( !useTexture ) { - ssink.attachColorbuffer(gl, 0, useAlpha); + final FBObject.ColorAttachment ca = ssink.createColorAttachment(useAlpha); + if( null != colorRenderbufferStorageDef ) { + ca.setStorageDefinition(colorRenderbufferStorageDef); + } + ssink.attachColorbuffer(gl, 0, ca); } else { ssink.attachTexture2D(gl, 0, useAlpha); } @@ -249,6 +259,24 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { swapBufferContext = sbc; } + /** + * Inject custom {@link FBObject.Attachment.StorageDefinition} specialization for the use-case of: + *+ * This IOS onscreen drawable implementation actually is only a dummy implementation + *
+ */ @Override protected GLDrawableImpl createOnscreenDrawableImpl(final NativeSurface target) { if (target == null) { -- cgit v1.2.3