diff options
Diffstat (limited to 'src/jogl')
19 files changed, 1014 insertions, 512 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java index fb0ff6a7e..fc8d41660 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java +++ b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java @@ -140,6 +140,17 @@ public final class OutlineShape implements Comparable<OutlineShape> { public void visit(final OutlineShape shape, final AffineTransform t); } + /** + * Constrained {@link OutlineShape} visitor w/o {@link AffineTransform}. + */ + public static interface Visitor2 { + /** + * Visiting the given {@link OutlineShape}. + * @param shape may be used as is, otherwise a copy shall be made if intended to be modified. + */ + public void visit(final OutlineShape shape); + } + /** Initial {@link #getSharpness()} value, which can be modified via {@link #setSharpness(float)}. */ public static final float DEFAULT_SHARPNESS = 0.5f; @@ -968,20 +979,20 @@ public final class OutlineShape implements Comparable<OutlineShape> { * </p> */ public final ArrayList<Vertex> getVertices() { - final boolean updated; + // final boolean updated; if( 0 != ( DIRTY_VERTICES & dirtyBits ) ) { vertices.clear(); for(int i=0; i<outlines.size(); i++) { vertices.addAll(outlines.get(i).getVertices()); } dirtyBits &= ~DIRTY_VERTICES; - updated = true; - } else { - updated = false; - } - if(Region.DEBUG_INSTANCE) { - System.err.println("OutlineShape.getVertices(): o "+outlines.size()+", v "+vertices.size()+", updated "+updated); + // updated = true; + // } else { + // updated = false; } + // if(Region.DEBUG_INSTANCE) { + // System.err.println("OutlineShape.getVertices(): o "+outlines.size()+", v "+vertices.size()+", updated "+updated); + // } return vertices; } diff --git a/src/jogl/classes/com/jogamp/graph/curve/Region.java b/src/jogl/classes/com/jogamp/graph/curve/Region.java index 068e0aabd..0ffcad2c1 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/Region.java +++ b/src/jogl/classes/com/jogamp/graph/curve/Region.java @@ -28,8 +28,9 @@ package com.jogamp.graph.curve; import java.io.PrintStream; -import java.time.Duration; -import java.time.Instant; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -91,13 +92,16 @@ public abstract class Region { public static final int VARWEIGHT_RENDERING_BIT = 1 << 8; /** - * Rendering-Mode bit for {@link #getRenderModes() Region} + * Rendering-Mode bit for {@link #getRenderModes() Region} to optionally enable a color-channel per vertex. * <p> - * If set, a color channel attribute per vertex is added to the stream, - * otherwise only the - * {@link com.jogamp.graph.curve.opengl.RegionRenderer#setColorStatic(com.jogamp.opengl.GL2ES2, float, float, float, float) static color} - * is being used. + * If set, a color channel attribute per vertex is added to the stream via {@link #addOutlineShape(OutlineShape, AffineTransform, float[])}, + * otherwise {@link com.jogamp.graph.curve.opengl.RegionRenderer#setColorStatic(com.jogamp.opengl.GL2ES2, float, float, float, float) static color} + * can being used for a monotonic color. * </p> + * @see #getRenderModes() + * @see #hasColorChannel() + * @see #addOutlineShape(OutlineShape, AffineTransform, float[]) + * @see com.jogamp.graph.curve.opengl.RegionRenderer#setColorStatic(com.jogamp.opengl.GL2ES2, float, float, float, float) */ public static final int COLORCHANNEL_RENDERING_BIT = 1 << 9; @@ -200,10 +204,26 @@ public abstract class Region { /** * Allow the renderer buffers to pre-emptively grow for given vertices- and index counts. - * @param verticeCount number of vertices to hold - * @param indexCount number of indices to hold + * @param verticesCount number of vertices to hold + * @param indicesCount number of indices to hold + * @see #setBufferCapacity(int, int) + * @see #countOutlineShape(OutlineShape, int[]) + * @see #countOutlineShapes(List, int[]) + */ + public abstract void growBuffer(int verticesCount, int indicesCount); + + /** + * Set the renderer buffers pre-emptively for given vertices- and index counts. + * <p> + * If the buffers already exceeds given numbers, the buffers are unchanged. + * </p> + * @param verticesCount number of vertices to hold + * @param indicesCount number of indices to hold + * @see #growBuffer(int, int) + * @see #countOutlineShape(OutlineShape, int[]) + * @see #countOutlineShapes(List, int[]) */ - public abstract void growBufferSize(int verticeCount, int indexCount); + public abstract void setBufferCapacity(int verticesCount, int indicesCount); protected abstract void pushVertex(final float[] coords, final float[] texParams, float[] rgba); protected abstract void pushVertices(final float[] coords1, final float[] coords2, final float[] coords3, @@ -230,6 +250,7 @@ public abstract class Region { /** * Returns true if capable of two pass rendering - VBAA, otherwise false. + * @see #getRenderModes() */ public final boolean isVBAA() { return Region.isVBAA(renderModes); @@ -237,6 +258,7 @@ public abstract class Region { /** * Returns true if capable of two pass rendering - MSAA, otherwise false. + * @see #getRenderModes() */ public final boolean isMSAA() { return Region.isMSAA(renderModes); @@ -244,15 +266,19 @@ public abstract class Region { /** * Returns true if capable of variable weights, otherwise false. + * @see #getRenderModes() */ public final boolean hasVariableWeight() { return Region.hasVariableWeight(renderModes); } /** - * Returns true if render mode has a color channel, - * i.e. the bit {@link #COLORCHANNEL_RENDERING_BIT} is set, - * otherwise false. + * Returns true if {@link #getRenderModes()} has a color channel, i.e. {@link #COLORCHANNEL_RENDERING_BIT} is set. + * Otherwise returns false. + * @see #COLORCHANNEL_RENDERING_BIT + * @see #getRenderModes() + * @see #addOutlineShape(OutlineShape, AffineTransform, float[]) + * @see com.jogamp.graph.curve.opengl.RegionRenderer#setColorStatic(com.jogamp.opengl.GL2ES2, float, float, float, float) */ public boolean hasColorChannel() { return Region.hasColorChannel(renderModes); @@ -262,6 +288,7 @@ public abstract class Region { * Returns true if render mode has a color texture, * i.e. the bit {@link #COLORTEXTURE_RENDERING_BIT} is set, * otherwise false. + * @see #getRenderModes() */ public boolean hasColorTexture() { return Region.hasColorTexture(renderModes); @@ -332,13 +359,25 @@ public abstract class Region { pushNewVerticesImpl(vertIn1, vertIn2, vertIn3, transform, rgba); } + protected static void put3i(final IntBuffer b, final int v1, final int v2, final int v3) { + b.put(v1); b.put(v2); b.put(v3); + } + protected static void put3s(final ShortBuffer b, final short v1, final short v2, final short v3) { + b.put(v1); b.put(v2); b.put(v3); + } + protected static void put3f(final FloatBuffer b, final float v1, final float v2, final float v3) { + b.put(v1); b.put(v2); b.put(v3); + } + protected static void put4f(final FloatBuffer b, final float v1, final float v2, final float v3, final float v4) { + b.put(v1); b.put(v2); b.put(v3); b.put(v4); + } + private final AABBox tmpBox = new AABBox(); protected static final int GL_UINT16_MAX = 0xffff; // 65,535 protected static final int GL_INT32_MAX = 0x7fffffff; // 2,147,483,647 static class Perf { - Instant t0 = null, t1 = null, t2 = null; // all td_ values are in [ns] long td_vertices = 0; long td_tri_push_idx = 0; @@ -362,7 +401,6 @@ public abstract class Region { } public void clear() { - t0 = null; t1 = null; t2 = null; td_vertices = 0; td_tri_push_idx = 0; td_tri_push_vertidx = 0; @@ -396,11 +434,11 @@ public abstract class Region { } @Override - public Duration getTotalDuration() { + public long getTotalDuration() { if( null != perf ) { - return Duration.ofNanos(perf.td_total); + return perf.td_total; } else { - return Duration.ZERO; + return 0; } } @@ -413,19 +451,54 @@ public abstract class Region { public PerfCounterCtrl perfCounter() { return perfCounterCtrl; } /** + * Count required number of vertices and indices adding to given int[2] `vertIndexCount` array. + * <p> + * The region's buffer can be either set using {@link Region#setBufferCapacity(int, int)} or grown using {@link Region#growBuffer(int, int)}. + * </p> + * @param shape the {@link OutlineShape} to count + * @param vertIndexCount the int[2] storage where the counted vertices and indices are added, vertices at [0] and indices at [1] + * @see #setBufferCapacity(int, int) + * @see #growBuffer(int, int) + */ + public final void countOutlineShape(final OutlineShape shape, final int[/*2*/] vertIndexCount) { + final List<Triangle> trisIn = shape.getTriangles(OutlineShape.VerticesState.QUADRATIC_NURBS); + final ArrayList<Vertex> vertsIn = shape.getVertices(); + { + final int verticeCount = vertsIn.size() + shape.getAddedVerticeCount(); + final int indexCount = trisIn.size() * 3; + vertIndexCount[0] += verticeCount; + vertIndexCount[1] += Math.min( Math.ceil(verticeCount * 0.6), indexCount ); + } + } + + /** + * Count required number of vertices and indices adding to given int[2] `vertIndexCount` array. + * <p> + * The region's buffer can be either set using {@link Region#setBufferCapacity(int, int)} or grown using {@link Region#growBuffer(int, int)}. + * </p> + * @param shapes list of {@link OutlineShape} to count + * @param vertIndexCount the int[2] storage where the counted vertices and indices are added, vertices at [0] and indices at [1] + * @see #setBufferCapacity(int, int) + * @see #growBuffer(int, int) + */ + public final void countOutlineShapes(final List<OutlineShape> shapes, final int[/*2*/] vertIndexCount) { + for (int i = 0; i < shapes.size(); i++) { + countOutlineShape(shapes.get(i), vertIndexCount); + } + } + + /** * Add the given {@link OutlineShape} to this region with the given optional {@link AffineTransform}. * <p> * In case {@link #setFrustum(Frustum) frustum culling is set}, the {@link OutlineShape} * is dropped if it's {@link OutlineShape#getBounds() bounding-box} is fully outside of the frustum. * The optional {@link AffineTransform} is applied to the bounding-box beforehand. * </p> - * @param rgbaColor TODO + * @param shape the {@link OutlineShape} to add + * @param t the optional {@link AffineTransform} to be applied on each vertex + * @param rgbaColor if {@link #hasColorChannel()} RGBA color must be passed, otherwise value is ignored. */ public final void addOutlineShape(final OutlineShape shape, final AffineTransform t, final float[] rgbaColor) { - if( null != perf ) { - ++perf.count; - perf.t0 = Clock.getMonotonicTime(); - } if( null != frustum ) { final AABBox shapeBox = shape.getBounds(); final AABBox shapeBoxT; @@ -436,12 +509,56 @@ public abstract class Region { shapeBoxT = shapeBox; } if( frustum.isAABBoxOutside(shapeBoxT) ) { - if(DEBUG_INSTANCE) { - System.err.println("Region.addOutlineShape(): Dropping outside shapeBoxT: "+shapeBoxT); - } return; } } + if( null == perf && !DEBUG_INSTANCE ) { + addOutlineShape0(shape, t, rgbaColor); + } else { + addOutlineShape1(shape, t, rgbaColor); + } + markShapeDirty(); + } + private final void addOutlineShape0(final OutlineShape shape, final AffineTransform t, final float[] rgbaColor) { + final List<Triangle> trisIn = shape.getTriangles(OutlineShape.VerticesState.QUADRATIC_NURBS); + final ArrayList<Vertex> vertsIn = shape.getVertices(); + { + final int verticeCount = vertsIn.size() + shape.getAddedVerticeCount(); + final int indexCount = trisIn.size() * 3; + growBuffer(verticeCount, indexCount); + } + + final int idxOffset = numVertices; + if( vertsIn.size() >= 3 ) { + // + // Processing Vertices + // + for(int i=0; i<vertsIn.size(); i++) { + pushNewVertexImpl(vertsIn.get(i), t, rgbaColor); + } + final int trisIn_sz = trisIn.size(); + for(int i=0; i < trisIn_sz; ++i) { + final Triangle triIn = trisIn.get(i); + // triEx.addVertexIndicesOffset(idxOffset); + // triangles.add( triEx ); + final Vertex[] triInVertices = triIn.getVertices(); + final int tv0Idx = triInVertices[0].getId(); + + if ( max_indices - idxOffset > tv0Idx ) { + // valid 'known' idx - move by offset + pushIndices(tv0Idx+idxOffset, + triInVertices[1].getId()+idxOffset, + triInVertices[2].getId()+idxOffset); + } else { + // FIXME: If exceeding max_indices, we would need to generate a new buffer w/ indices + pushNewVerticesIdxImpl(triInVertices[0], triInVertices[1], triInVertices[2], t, rgbaColor); + } + } + } + } + private final void addOutlineShape1(final OutlineShape shape, final AffineTransform t, final float[] rgbaColor) { + ++perf.count; + final long t0 = Clock.currentNanos(); final List<Triangle> trisIn = shape.getTriangles(OutlineShape.VerticesState.QUADRATIC_NURBS); final ArrayList<Vertex> vertsIn = shape.getVertices(); { @@ -453,31 +570,29 @@ public abstract class Region { System.err.println("Region.addOutlineShape().0: VerticeCount "+vertsIn.size()+" + "+addedVerticeCount+" = "+verticeCount); System.err.println("Region.addOutlineShape().0: IndexCount "+indexCount); } - growBufferSize(verticeCount, indexCount); + growBuffer(verticeCount, indexCount); } final int idxOffset = numVertices; int vertsVNewIdxCount = 0, vertsTMovIdxCount = 0, vertsTNewIdxCount = 0, tris = 0; final int vertsDupCountV = 0, vertsDupCountT = 0, vertsKnownMovedT = 0; if( vertsIn.size() >= 3 ) { - if(DEBUG_INSTANCE) { - System.err.println("Region.addOutlineShape(): Processing Vertices"); - } + // if(DEBUG_INSTANCE) { + // System.err.println("Region.addOutlineShape(): Processing Vertices"); + // } for(int i=0; i<vertsIn.size(); i++) { pushNewVertexImpl(vertsIn.get(i), t, rgbaColor); vertsVNewIdxCount++; } - if( null != perf ) { - perf.t1 = Clock.getMonotonicTime(); - perf.td_vertices += Duration.between(perf.t0, perf.t1).toNanos(); - } - if(DEBUG_INSTANCE) { - System.err.println("Region.addOutlineShape(): Processing Triangles"); - } - for(final Triangle triIn : trisIn) { - if( null != perf ) { - perf.t2 = Clock.getMonotonicTime(); - } + final long t1 = Clock.currentNanos(); + perf.td_vertices += t1 - t0; + // if(DEBUG_INSTANCE) { + // System.err.println("Region.addOutlineShape(): Processing Triangles"); + // } + final int trisIn_sz = trisIn.size(); + for(int i=0; i < trisIn_sz; ++i) { + final Triangle triIn = trisIn.get(i); + final long t2 = Clock.currentNanos(); // if(Region.DEBUG_INSTANCE) { // System.err.println("T["+i+"]: "+triIn); // } @@ -486,47 +601,33 @@ public abstract class Region { final Vertex[] triInVertices = triIn.getVertices(); final int tv0Idx = triInVertices[0].getId(); - if( null != perf ) { - perf.td_tri_misc += Duration.between(perf.t2, Clock.getMonotonicTime()).toNanos(); - } + perf.td_tri_misc += Clock.currentNanos() - t2; if ( max_indices - idxOffset > tv0Idx ) { // valid 'known' idx - move by offset // if(Region.DEBUG_INSTANCE) { // System.err.println("T["+i+"]: Moved "+tv0Idx+" + "+idxOffset+" -> "+(tv0Idx+idxOffset)); // } - if( null != perf ) { - final Instant tpi = Clock.getMonotonicTime(); - pushIndices(tv0Idx+idxOffset, - triInVertices[1].getId()+idxOffset, - triInVertices[2].getId()+idxOffset); - perf.td_tri_push_idx += Duration.between(tpi, Clock.getMonotonicTime()).toNanos(); - } else { - pushIndices(tv0Idx+idxOffset, - triInVertices[1].getId()+idxOffset, - triInVertices[2].getId()+idxOffset); - } + final long tpi = Clock.currentNanos(); + pushIndices(tv0Idx+idxOffset, + triInVertices[1].getId()+idxOffset, + triInVertices[2].getId()+idxOffset); + perf.td_tri_push_idx += Clock.currentNanos() - tpi; vertsTMovIdxCount+=3; } else { - // FIXME: Invalid idx - generate new one + // FIXME: If exceeding max_indices, we would need to generate a new buffer w/ indices // if( Region.DEBUG_INSTANCE) { // System.err.println("T["+i+"]: New Idx "+numVertices); // } - if( null != perf ) { - final Instant tpvi = Clock.getMonotonicTime(); - pushNewVerticesIdxImpl(triInVertices[0], triInVertices[1], triInVertices[2], t, rgbaColor); - perf.td_tri_push_vertidx += Duration.between(tpvi, Clock.getMonotonicTime()).toNanos(); - } else { - pushNewVerticesIdxImpl(triInVertices[0], triInVertices[1], triInVertices[2], t, rgbaColor); - } + final long tpvi = Clock.currentNanos(); + pushNewVerticesIdxImpl(triInVertices[0], triInVertices[1], triInVertices[2], t, rgbaColor); + perf.td_tri_push_vertidx += Clock.currentNanos() - tpvi; vertsTNewIdxCount+=3; } tris++; } - if( null != perf ) { - final Instant ttriX = Clock.getMonotonicTime(); - perf.td_tri_total += Duration.between(perf.t1, ttriX).toNanos(); - perf.td_total += Duration.between(perf.t0, ttriX).toNanos(); - } + final long ttriX = Clock.currentNanos(); + perf.td_tri_total += ttriX - t1; + perf.td_total += ttriX - t0; } if(DEBUG_INSTANCE) { System.err.println("Region.addOutlineShape().X: idx[ui32 "+usesI32Idx()+", offset "+idxOffset+"], tris: "+tris+", verts [idx "+vertsTNewIdxCount+", add "+vertsTNewIdxCount+" = "+(vertsVNewIdxCount+vertsTNewIdxCount)+"]"); @@ -537,9 +638,19 @@ public abstract class Region { System.err.println("Region.addOutlineShape().X: box "+box); printBufferStats(System.err); } - markShapeDirty(); } + /** + * Add the given list of {@link OutlineShape}s to this region with the given optional {@link AffineTransform}. + * <p> + * In case {@link #setFrustum(Frustum) frustum culling is set}, the {@link OutlineShape}s + * are dropped if it's {@link OutlineShape#getBounds() bounding-box} is fully outside of the frustum. + * The optional {@link AffineTransform} is applied to the bounding-box beforehand. + * </p> + * @param shapes list of {@link OutlineShape} to add + * @param t the optional {@link AffineTransform} to be applied on each vertex + * @param rgbaColor if {@link #hasColorChannel()} RGBA color must be passed, otherwise value is ignored. + */ public final void addOutlineShapes(final List<OutlineShape> shapes, final AffineTransform transform, final float[] rgbaColor) { for (int i = 0; i < shapes.size(); i++) { addOutlineShape(shapes.get(i), transform, rgbaColor); diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java index 9baa99420..e02752f73 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java @@ -30,6 +30,7 @@ package com.jogamp.graph.curve.opengl; import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLArrayData;
+import com.jogamp.opengl.util.GLArrayDataClient;
import com.jogamp.opengl.util.GLArrayDataEditable;
import com.jogamp.opengl.GLProfile;
@@ -77,6 +78,9 @@ public abstract class GLRegion extends Region { */
public static final int defaultIndicesCount = 10*33;
+ // private static final float growthFactor = 1.2f; // avg +5% size but 15% more overhead (34% total)
+ protected static final float growthFactor = GLArrayDataClient.DEFAULT_GROWTH_FACTOR; // avg +20% size, but 15% less CPU overhead compared to 1.2 (19% total)
+
/**
* Create a GLRegion using the passed render mode
*
@@ -142,9 +146,9 @@ public abstract class GLRegion extends Region { protected static void printAndCount(final PrintStream out, final String name, final GLArrayData data, final int[] size, final int[] capacity) {
out.print(name+"[");
if( null != data ) {
- data.printStats(out);
- size[0] += data.getSizeInBytes();
- capacity[0] += data.getCapacityInBytes();
+ out.print(data.fillStatsToString());
+ size[0] += data.getByteCount();
+ capacity[0] += data.getByteCapacity();
out.print("]");
} else {
out.print("null]");
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java index 547a07fba..8d55c6136 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java @@ -115,6 +115,27 @@ public class TextRegionUtil { } /** + * Count required number of vertices and indices adding to given int[2] `vertIndexCount` array. + * <p> + * The region's buffer can be either set using {@link Region#setBufferCapacity(int, int)} or grown using {@link Region#growBuffer(int, int)}. + * </p> + * @param region the {@link GLRegion} sink + * @param font the target {@link Font} + * @param str string text + * @param vertIndexCount the int[2] storage where the counted vertices and indices are added, vertices at [0] and indices at [1] + * @see Region#setBufferCapacity(int, int) + * @see Region#growBuffer(int, int) + */ + public static void countStringRegion(final Region region, final Font font, final CharSequence str, final int[/*2*/] vertIndexCount) { + final OutlineShape.Visitor2 visitor = new OutlineShape.Visitor2() { + @Override + public final void visit(final OutlineShape shape) { + region.countOutlineShape(shape, vertIndexCount); + } }; + font.processString(visitor, str); + } + + /** * Render the string in 3D space w.r.t. the font int font em-size [0..1] at the end of an internally cached {@link GLRegion}. * <p> * The shapes added to the GLRegion are in font em-size [0..1]. @@ -156,6 +177,15 @@ public class TextRegionUtil { } /** + * Try using {@link #drawString3D(GL2ES2, int, RegionRenderer, Font, CharSequence, float[], int[], AffineTransform, AffineTransform)} to reuse {@link AffineTransform} instances. + */ + public static AABBox drawString3D(final GL2ES2 gl, final int renderModes, + final RegionRenderer renderer, final Font font, final CharSequence str, + final float[] rgbaColor, final int[/*1*/] sampleCount) { + return drawString3D(gl, renderModes, renderer, font, str, rgbaColor, sampleCount, new AffineTransform(), new AffineTransform()); + } + + /** * Render the string in 3D space w.r.t. the font in font em-size [0..1] at the end of an internally temporary {@link GLRegion}. * <p> * The shapes added to the GLRegion are in font em-size [0..1]. @@ -166,7 +196,7 @@ public class TextRegionUtil { * <p> * In case of a multisampling region renderer, i.e. {@link Region#VBAA_RENDERING_BIT}, recreating the {@link GLRegion} * is a huge performance impact. - * In such case better use {@link #drawString3D(GL2ES2, GLRegion, RegionRenderer, Font, CharSequence, float[], int[])} + * In such case better use {@link #drawString3D(GL2ES2, GLRegion, RegionRenderer, Font, CharSequence, float[], int[], AffineTransform, AffineTransform)} * instead. * </p> * @param gl the current GL state @@ -176,23 +206,33 @@ public class TextRegionUtil { * @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored. * @param sampleCount desired multisampling sample count for msaa-rendering. * The actual used scample-count is written back when msaa-rendering is enabled, otherwise the store is untouched. + * @param tmp1 temp {@link AffineTransform} to be reused + * @param tmp2 temp {@link AffineTransform} to be reused * @throws Exception if TextRenderer not initialized * @return the bounding box of the given string from the produced and rendered GLRegion */ public static AABBox drawString3D(final GL2ES2 gl, final int renderModes, final RegionRenderer renderer, final Font font, final CharSequence str, - final float[] rgbaColor, final int[/*1*/] sampleCount) { + final float[] rgbaColor, final int[/*1*/] sampleCount, final AffineTransform tmp1, final AffineTransform tmp2) { if(!renderer.isInitialized()){ throw new GLException("TextRendererImpl01: not initialized!"); } final GLRegion region = GLRegion.create(gl.getGLProfile(), renderModes, null); - final AABBox res = addStringToRegion(region, font, null, str, rgbaColor); + final AABBox res = addStringToRegion(region, font, null, str, rgbaColor, tmp1, tmp2); region.draw(gl, renderer, sampleCount); region.destroy(gl); return res; } /** + * Try using {@link #drawString3D(GL2ES2, GLRegion, RegionRenderer, Font, CharSequence, float[], int[], AffineTransform, AffineTransform)} to reuse {@link AffineTransform} instances. + */ + public static AABBox drawString3D(final GL2ES2 gl, final GLRegion region, final RegionRenderer renderer, + final Font font, final CharSequence str, final float[] rgbaColor, final int[/*1*/] sampleCount) { + return drawString3D(gl, region, renderer, font, str, rgbaColor, sampleCount, new AffineTransform(), new AffineTransform()); + } + + /** * Render the string in 3D space w.r.t. the font in font em-size [0..1] at the end of the given {@link GLRegion}. * <p> * User might want to {@link GLRegion#clear(GL2ES2)} the region before calling this method. @@ -211,16 +251,18 @@ public class TextRegionUtil { * @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored. * @param sampleCount desired multisampling sample count for msaa-rendering. * The actual used scample-count is written back when msaa-rendering is enabled, otherwise the store is untouched. + * @param tmp1 temp {@link AffineTransform} to be reused + * @param tmp2 temp {@link AffineTransform} to be reused * @return the bounding box of the given string from the produced and rendered GLRegion * @throws Exception if TextRenderer not initialized */ public static AABBox drawString3D(final GL2ES2 gl, final GLRegion region, final RegionRenderer renderer, final Font font, final CharSequence str, final float[] rgbaColor, - final int[/*1*/] sampleCount) { + final int[/*1*/] sampleCount, final AffineTransform tmp1, final AffineTransform tmp2) { if(!renderer.isInitialized()){ throw new GLException("TextRendererImpl01: not initialized!"); } - final AABBox res = addStringToRegion(region, font, null, str, rgbaColor); + final AABBox res = addStringToRegion(region, font, null, str, rgbaColor, tmp1, tmp2); region.draw(gl, renderer, sampleCount); return res; } diff --git a/src/jogl/classes/com/jogamp/graph/font/Font.java b/src/jogl/classes/com/jogamp/graph/font/Font.java index 907bbde8a..1b5452a45 100644 --- a/src/jogl/classes/com/jogamp/graph/font/Font.java +++ b/src/jogl/classes/com/jogamp/graph/font/Font.java @@ -27,9 +27,6 @@ */ package com.jogamp.graph.font; -import java.io.PrintStream; - -import com.jogamp.common.util.PerfCounterCtrl; import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.geom.plane.AffineTransform; import com.jogamp.opengl.math.geom.AABBox; @@ -259,6 +256,24 @@ public interface Font { StringBuilder getAllNames(final StringBuilder string, final String separator); /** + * Returns the hash code based on {@link #NAME_UNIQUNAME}. + * <p> + * {@inheritDoc} + * </p> + */ + @Override + int hashCode(); + + /** + * Returns true if other instance is of same type and {@link #NAME_UNIQUNAME} is equal. + * <p> + * {@inheritDoc} + * </p> + */ + @Override + boolean equals(final Object o); + + /** * Return advance-width of given glyphID in font-units, sourced from `hmtx` table. * @param glyphID */ @@ -329,17 +344,29 @@ public interface Font { AABBox getMetricBounds(final CharSequence string); /** + * Try using {@link #getGlyphBounds(CharSequence, AffineTransform, AffineTransform)} to reuse {@link AffineTransform} instances. + */ + AABBox getGlyphBounds(final CharSequence string); + + /** * Returns accurate bounding box by taking each glyph's font em-sized bounding box into account. * <p> * Glyph bounds is based on each glyph's bounding box and `hhea' composed line height. * </p> * @param string string text + * @param tmp1 temp {@link AffineTransform} to be reused + * @param tmp2 temp {@link AffineTransform} to be reused * @return the bounding box of the given string in font em-size [0..1] * @see #getGlyphBoundsFU(CharSequence) * @see #getGlyphShapeBounds(CharSequence) * @see #getMetricBounds(CharSequence) */ - AABBox getGlyphBounds(final CharSequence string); + AABBox getGlyphBounds(final CharSequence string, final AffineTransform tmp1, final AffineTransform tmp2); + + /** + * Try using {@link #getGlyphBoundsFU(CharSequence, AffineTransform, AffineTransform)} to reuse {@link AffineTransform} instances. + */ + AABBox getGlyphBoundsFU(final CharSequence string); /** * Returns accurate bounding box by taking each glyph's font-units sized bounding box into account. @@ -347,10 +374,12 @@ public interface Font { * Glyph bounds is based on each glyph's bounding box and `hhea' composed line height. * </p> * @param string string text + * @param tmp1 temp {@link AffineTransform} to be reused + * @param tmp2 temp {@link AffineTransform} to be reused * @return the bounding box of the given string in font-units [0..1] * @see #getGlyphBounds(CharSequence) */ - AABBox getGlyphBoundsFU(final CharSequence string); + AABBox getGlyphBoundsFU(final CharSequence string, final AffineTransform tmp1, final AffineTransform tmp2); /** * Returns accurate bounding box by taking each glyph's font em-sized {@link OutlineShape} into account. @@ -388,16 +417,8 @@ public interface Font { boolean isPrintableChar(final char c); /** - * Visit each {@link Glyph}'s {@link OutlineShape} of the string with the {@link OutlineShape.Visitor} - * while passing the progressed {@link AffineTransform}. - * <p> - * The produced shapes are in font em-size [0..1], but can be adjusted with the given transform, progressed and passed to the visitor. - * </p> - * @param visitor handling each glyph's outline shape in font em-size [0..1] and the given {@link AffineTransform} - * @param transform optional given transform - * @param font the target {@link Font} - * @param string string text - * @return the bounding box of the given string by taking each glyph's font em-sized [0..1] {@link OutlineShape} into account. + * Try using {@link #processString(com.jogamp.graph.curve.OutlineShape.Visitor, AffineTransform, CharSequence, AffineTransform, AffineTransform)} + * to reuse {@link AffineTransform} instances. */ AABBox processString(final OutlineShape.Visitor visitor, final AffineTransform transform, final CharSequence string); @@ -406,7 +427,7 @@ public interface Font { * Visit each {@link Glyph}'s {@link OutlineShape} of the string with the {@link OutlineShape.Visitor} * while passing the progressed {@link AffineTransform}. * <p> - * The produced shapes are in font em-size [0..1], but can be adjusted with the given transform, progressed and passed to the visitor. + * The processed shapes are in font em-size [0..1], but can be adjusted with the given transform, progressed and passed to the visitor. * </p> * @param visitor handling each glyph's outline shape in font em-size [0..1] and the given {@link AffineTransform} * @param transform optional given transform @@ -420,7 +441,15 @@ public interface Font { final CharSequence string, final AffineTransform temp1, final AffineTransform temp2); - PerfCounterCtrl perfCounter(); + /** + * Visit each {@link Glyph}'s {@link OutlineShape} of the string with the constrained {@link OutlineShape.Visitor2}. + * <p> + * The processed shapes are in font em-size [0..1]. + * </p> + * @param visitor handling each glyph's outline shape in font em-size [0..1] + * @param string string text + */ + void processString(final OutlineShape.Visitor2 visitor, final CharSequence string); /** Returns {@link #getFullFamilyName()} */ @Override diff --git a/src/jogl/classes/com/jogamp/opengl/GLArrayData.java b/src/jogl/classes/com/jogamp/opengl/GLArrayData.java index d209addbb..17ffd57e9 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLArrayData.java +++ b/src/jogl/classes/com/jogamp/opengl/GLArrayData.java @@ -28,7 +28,6 @@ package com.jogamp.opengl; -import java.io.PrintStream; import java.nio.Buffer; import com.jogamp.opengl.fixedfunc.GLPointerFunc; @@ -173,26 +172,109 @@ public interface GLArrayData { public int getBytesPerComp(); /** - * The current number of used elements. + * Returns true if data has been {@link com.jogamp.opengl.util.GLArrayDataEditable#seal(boolean) sealed} (flipped to read), otherwise false (writing mode). + * + * @see com.jogamp.opengl.util.GLArrayDataEditable#seal(boolean) + * @see com.jogamp.opengl.util.GLArrayDataEditable#seal(GL, boolean) + */ + public boolean sealed(); + + /** + * Returns the element position (written elements) if not {@link #sealed()} or + * the element limit (available to read) after {@link #sealed()} (flip). * <p> * On element consist out of {@link #getCompsPerElem()} components. * </p> - * In case the buffer's position is 0 (sealed, flipped), it's based on it's limit instead of it's position. + * @see #sealed() + * @see #getByteCount() + * @see #elemPosition() + * @see #remainingElems() + * @see #getElemCapacity() */ public int getElemCount(); /** - * The currently used size in bytes.<br> - * In case the buffer's position is 0 (sealed, flipped), it's based on it's limit instead of it's position. + * Returns the element position. + * <p> + * On element consist out of {@link #getCompsPerElem()} components. + * </p> + * @see #bytePosition() + * @see #getElemCount() + * @see #remainingElems() + * @see #getElemCapacity() + */ + public int elemPosition(); + + /** + * The current number of remaining elements. + * <p> + * On element consist out of {@link #getCompsPerElem()} components. + * </p> + * Returns the number of elements between the current position and the limit, i.e. remaining elements to write in this buffer. + * @see #remainingBytes() + * @see #getElemCount() + * @see #elemPosition() + * @see #getElemCapacity() + */ + public int remainingElems(); + + /** + * Return the element capacity. + * <p> + * On element consist out of {@link #getCompsPerElem()} components. + * </p> + * @see #getByteCapacity() + * @see #getElemCount() + * @see #elemPosition() + * @see #remainingElems() + */ + public int getElemCapacity(); + + /** + * Returns the byte position (written elements) if not {@link #sealed()} or + * the byte limit (available to read) after {@link #sealed()} (flip). + * @see #sealed() + * @see #getElemCount() + * @see #bytePosition() + * @see #remainingBytes() + * @see #getByteCapacity() + */ + public int getByteCount(); + + /** + * Returns the bytes position. + * @see #elemPosition() + * @see #getByteCount() + * @see #remainingElems() + * @see #getElemCapacity() + */ + public int bytePosition(); + + /** + * The current number of remaining bytes. + * <p> + * Returns the number of bytes between the current position and the limit, i.e. remaining bytes to write in this buffer. + * </p> + * @see #remainingElems() + * @see #getByteCount() + * @see #bytePosition() + * @see #getByteCapacity() */ - public int getSizeInBytes(); + public int remainingBytes(); /** - * The current capacity in bytes. + * Return the capacity in bytes. + * @see #getElemCapacity() + * @see #getByteCount() + * @see #bytePosition() + * @see #remainingBytes() */ - public int getCapacityInBytes(); + public int getByteCapacity(); - public void printStats(final PrintStream out); + /** Returns a string with detailed buffer fill stats. */ + public String fillStatsToString(); + /** Returns a string with detailed buffer element stats, i.e. sealed, count, position, remaining, limit and capacity. */ + public String elemStatsToString(); /** * True, if GL shall normalize fixed point data while converting diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java index 792d2c474..e5f9e5336 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java @@ -161,9 +161,6 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData public final boolean isVBOWritten() { return bufferWritten; } @Override - public final boolean sealed() { return sealed; } - - @Override public final boolean enabled() { return bufferEnabled; } // @@ -172,7 +169,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData @Override public final void setVBOWritten(final boolean written) { - bufferWritten = ( 0 == mappedElementCount ) ? written : true; + bufferWritten = ( 0 == mappedElemCount ) ? written : true; } @Override @@ -232,7 +229,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData } sealed = false; bufferEnabled = false; - bufferWritten = ( 0 == mappedElementCount ) ? false : true; + bufferWritten = ( 0 == mappedElemCount ) ? false : true; } @Override @@ -240,7 +237,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData { if( sealed == seal ) return; sealed = seal; - bufferWritten = ( 0 == mappedElementCount ) ? false : true; + bufferWritten = ( 0 == mappedElemCount ) ? false : true; if( seal ) { if ( null != buffer ) { buffer.flip(); @@ -407,17 +404,16 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData return "GLArrayDataClient["+name+ ", index "+index+ ", location "+location+ - ", isVertexAttribute "+isVertexAttribute+ + ", isVertexAttribute "+isVertexAttr+ ", usesGLSL "+usesGLSL+ ", usesShaderState "+(null!=shaderState)+ - ", dataType 0x"+Integer.toHexString(componentType)+ - ", bufferClazz "+componentClazz+ - ", elements "+getElemCount()+ - ", compsPerElem "+componentsPerElement+ + ", dataType 0x"+Integer.toHexString(compType)+ + ", bufferClazz "+compClazz+ + ", compsPerElem "+compsPerElement+ ", stride "+strideB+"b "+strideL+"c"+ - ", mappedElementCount "+mappedElementCount+ - ", initialElementCount "+initialElementCount+ - ", sealed "+sealed+ + ", initElemCount "+initElemCount+ + ", mappedElemCount "+mappedElemCount+ + ", "+elemStatsToString()+ ", bufferEnabled "+bufferEnabled+ ", bufferWritten "+bufferWritten+ ", buffer "+buffer+ @@ -429,7 +425,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData * Returning element-count from given componentCount, rounding up to componentsPerElement. */ public int compsToElemCount(final int componentCount) { - return ( componentCount + componentsPerElement - 1 ) / componentsPerElement; + return ( componentCount + compsPerElement - 1 ) / compsPerElement; } /** @@ -441,15 +437,31 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData * @return true if buffer size has changed, i.e. grown. Otherwise false. */ public final boolean growIfNeeded(final int spareComponents) { + if( buffer.remaining() < spareComponents ) { + if( 0 != mappedElemCount ) { + throw new GLException("Mapped buffer can't grow. Insufficient storage size: Needed "+spareComponents+" components, "+ + "mappedElementCount "+mappedElemCount+ + ", has mapped buffer "+buffer+"; "+this); + } + final int has_comps = buffer.capacity(); + final int required_elems = compsToElemCount(has_comps + spareComponents); + final int new_elems = compsToElemCount( (int)( has_comps * growthFactor + 0.5f ) ); + final int elementCount = Math.max( new_elems, required_elems ); + return reserve( elementCount ); + } + return false; + } + + public final boolean growIfNeeded0(final int spareComponents) { if( buffer==null || buffer.remaining()<spareComponents ) { - if( 0 != mappedElementCount ) { + if( 0 != mappedElemCount ) { throw new GLException("Mapped buffer can't grow. Insufficient storage size: Needed "+spareComponents+" components, "+ - "mappedElementCount "+mappedElementCount+ + "mappedElementCount "+mappedElemCount+ ", has mapped buffer "+buffer+"; "+this); } if( null == buffer ) { final int required_elems = compsToElemCount(spareComponents); - return reserve( Math.max( initialElementCount, required_elems ) ); + return reserve( Math.max( initElemCount, required_elems ) ); } else { final int has_comps = buffer.capacity(); final int required_elems = compsToElemCount(has_comps + spareComponents); @@ -479,37 +491,37 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData } // add the stride delta - elementCount += (elementCount/componentsPerElement)*(strideL-componentsPerElement); + elementCount += (elementCount/compsPerElement)*(strideL-compsPerElement); final int osize = (buffer!=null) ? buffer.capacity() : 0; - final int nsize = elementCount * componentsPerElement; + final int nsize = elementCount * compsPerElement; if( nsize <= osize ) { return false; } final Buffer oldBuffer = buffer; - if(componentClazz==ByteBuffer.class) { + if(compClazz==ByteBuffer.class) { final ByteBuffer newBBuffer = Buffers.newDirectByteBuffer( nsize ); if(oldBuffer!=null) { oldBuffer.flip(); newBBuffer.put((ByteBuffer)oldBuffer); } buffer = newBBuffer; - } else if(componentClazz==ShortBuffer.class) { + } else if(compClazz==ShortBuffer.class) { final ShortBuffer newSBuffer = Buffers.newDirectShortBuffer( nsize ); if(oldBuffer!=null) { oldBuffer.flip(); newSBuffer.put((ShortBuffer)oldBuffer); } buffer = newSBuffer; - } else if(componentClazz==IntBuffer.class) { + } else if(compClazz==IntBuffer.class) { final IntBuffer newIBuffer = Buffers.newDirectIntBuffer( nsize ); if(oldBuffer!=null) { oldBuffer.flip(); newIBuffer.put((IntBuffer)oldBuffer); } buffer = newIBuffer; - } else if(componentClazz==FloatBuffer.class) { + } else if(compClazz==FloatBuffer.class) { final FloatBuffer newFBuffer = Buffers.newDirectFloatBuffer( nsize ); if(oldBuffer!=null) { oldBuffer.flip(); @@ -517,10 +529,10 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData } buffer = newFBuffer; } else { - throw new GLException("Given Buffer Class not supported: "+componentClazz+":\n\t"+this); + throw new GLException("Given Buffer Class not supported: "+compClazz+":\n\t"+this); } if(DEBUG) { - System.err.println("*** Size: Reserve: comps: "+componentsPerElement+", "+(osize/componentsPerElement)+"/"+osize+" -> "+(nsize/componentsPerElement)+"/"+nsize+ + System.err.println("*** Size: Reserve: comps: "+compsPerElement+", "+(osize/compsPerElement)+"/"+osize+" -> "+(nsize/compsPerElement)+"/"+nsize+ "; "+oldBuffer+" -> "+buffer+"; "+this); } return true; @@ -556,7 +568,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData } // immutable types - this.initialElementCount = initialElementCount; + this.initElemCount = initialElementCount; this.growthFactor = growthFactor; try { final Constructor<? extends GLArrayHandler> ctor = handlerClass.getConstructor(GLArrayDataEditable.class); @@ -597,7 +609,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData super(src); // immutable types - this.initialElementCount = src.initialElementCount; + this.initElemCount = src.initElemCount; if( null != src.glArrayHandler ) { final Class<? extends GLArrayHandler> clazz = src.glArrayHandler.getClass(); try { @@ -614,7 +626,6 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData // mutable types this.growthFactor = src.growthFactor; this.isValidated = src.isValidated; - this.sealed = src.sealed; this.bufferEnabled = src.bufferEnabled; this.bufferWritten = src.bufferWritten; this.enableBufferAlways = src.enableBufferAlways; @@ -644,13 +655,12 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData growthFactor = Math.max(1f, v); } - protected final int initialElementCount; + protected final int initElemCount; protected final GLArrayHandler glArrayHandler; protected final boolean usesGLSL; protected float growthFactor; private boolean isValidated = false; - protected boolean sealed; protected boolean bufferEnabled; protected boolean bufferWritten; protected boolean enableBufferAlways; diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java index 9430f585f..fad217c05 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java @@ -40,8 +40,6 @@ import java.nio.*; */ public interface GLArrayDataEditable extends GLArrayData { - public boolean sealed(); - public boolean enabled(); /** @@ -176,6 +174,7 @@ public interface GLArrayDataEditable extends GLArrayData { * ie position:=limit and limit:=capacity.</p> * * @see #seal(boolean) + * @see #sealed() */ public void seal(boolean seal); diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java index 9fd35c74f..e530ad627 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java @@ -321,10 +321,10 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE } final int subStrideB = ( 0 == getStride() ) ? getCompsPerElem() * getBytesPerComp() : getStride(); final GLArrayDataWrapper ad; - if( 0 < mappedElementCount ) { + if( 0 < mappedElemCount ) { ad = GLArrayDataWrapper.createFixed( index, comps, getCompType(), - getNormalized(), subStrideB, mappedElementCount, + getNormalized(), subStrideB, mappedElemCount, getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); } else { ad = GLArrayDataWrapper.createFixed( @@ -422,10 +422,10 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE } final int subStrideB = ( 0 == getStride() ) ? getCompsPerElem() * getBytesPerComp() : getStride(); final GLArrayDataWrapper ad; - if( 0 < mappedElementCount ) { + if( 0 < mappedElemCount ) { ad = GLArrayDataWrapper.createGLSL( name, comps, getCompType(), - getNormalized(), subStrideB, mappedElementCount, + getNormalized(), subStrideB, mappedElemCount, getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); } else { ad = GLArrayDataWrapper.createGLSL( @@ -495,7 +495,7 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE } checkSeal(true); bindBuffer(gl, true); - gl.glBufferData(getVBOTarget(), getSizeInBytes(), null, getVBOUsage()); + gl.glBufferData(getVBOTarget(), getByteCount(), null, getVBOUsage()); final GLBufferStorage storage = gl.mapBuffer(getVBOTarget(), access); setMappedBuffer(storage); bindBuffer(gl, false); @@ -512,7 +512,7 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE } checkSeal(true); bindBuffer(gl, true); - gl.glBufferData(getVBOTarget(), getSizeInBytes(), null, getVBOUsage()); + gl.glBufferData(getVBOTarget(), getByteCount(), null, getVBOUsage()); final GLBufferStorage storage = gl.mapBufferRange(getVBOTarget(), offset, length, access); setMappedBuffer(storage); bindBuffer(gl, false); @@ -523,16 +523,16 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE private final void setMappedBuffer(final GLBufferStorage storage) { mappedStorage = storage; final ByteBuffer bb = storage.getMappedBuffer(); - if(componentClazz==ByteBuffer.class) { + if(compClazz==ByteBuffer.class) { buffer = bb; - } else if(componentClazz==ShortBuffer.class) { + } else if(compClazz==ShortBuffer.class) { buffer = bb.asShortBuffer(); - } else if(componentClazz==IntBuffer.class) { + } else if(compClazz==IntBuffer.class) { buffer = bb.asIntBuffer(); - } else if(componentClazz==FloatBuffer.class) { + } else if(compClazz==FloatBuffer.class) { buffer = bb.asFloatBuffer(); } else { - throw new GLException("Given Buffer Class not supported: "+componentClazz+":\n\t"+this); + throw new GLException("Given Buffer Class not supported: "+compClazz+":\n\t"+this); } } @@ -553,23 +553,22 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE return "GLArrayDataServer["+name+ ", index "+index+ ", location "+location+ - ", isVertexAttribute "+isVertexAttribute+ + ", isVertexAttribute "+isVertexAttr+ ", usesGLSL "+usesGLSL+ ", usesShaderState "+(null!=shaderState)+ - ", dataType 0x"+Integer.toHexString(componentType)+ - ", bufferClazz "+componentClazz+ - ", elements "+getElemCount()+ - ", components "+componentsPerElement+ + ", dataType 0x"+Integer.toHexString(compType)+ + ", bufferClazz "+compClazz+ + ", compsPerElem "+compsPerElement+ ", stride "+strideB+"b "+strideL+"c"+ - ", initialElementCount "+initialElementCount+ - ", mappedElementCount "+mappedElementCount+ + ", initElemCount "+initElemCount+ + ", mappedElemCount "+mappedElemCount+ + ", "+elemStatsToString()+ ", mappedStorage "+mappedStorage+ ", vboEnabled "+vboEnabled+ ", vboName "+vboName+ ", vboUsage 0x"+Integer.toHexString(vboUsage)+ ", vboTarget 0x"+Integer.toHexString(vboTarget)+ ", vboOffset "+vboOffset+ - ", sealed "+sealed+ ", bufferEnabled "+bufferEnabled+ ", bufferWritten "+bufferWritten+ ", buffer "+buffer+ diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java index 699a0be0d..21d375dbc 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java @@ -28,7 +28,6 @@ package com.jogamp.opengl.util; -import java.io.PrintStream; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.FloatBuffer; @@ -51,7 +50,9 @@ public class GLArrayDataWrapper implements GLArrayData { /** * Create a VBO, using a predefined fixed function array index, wrapping the given data. - * + * <p> + * This buffer is always {@link #sealed()}. + * </p> * @param index The GL array index * @param comps The array component number * @param dataType The array index GL data type @@ -76,7 +77,9 @@ public class GLArrayDataWrapper implements GLArrayData { /** * Create a VBO, using a predefined fixed function array index, wrapping the mapped data characteristics. - * + * <p> + * This buffer is always {@link #sealed()}. + * </p> * @param index The GL array index * @param comps The array component number * @param dataType The array index GL data type @@ -101,7 +104,9 @@ public class GLArrayDataWrapper implements GLArrayData { /** * Create a VBO, using a custom GLSL array attribute name, wrapping the given data. - * + * <p> + * This buffer is always {@link #sealed()}. + * </p> * @param name The custom name for the GL attribute, maybe null if gpuBufferTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER} * @param comps The array component number * @param dataType The array index GL data type @@ -125,7 +130,9 @@ public class GLArrayDataWrapper implements GLArrayData { /** * Create a VBO, using a custom GLSL array attribute name, wrapping the mapped data characteristics. - * + * <p> + * This buffer is always {@link #sealed()}. + * </p> * @param name The custom name for the GL attribute, maybe null if gpuBufferTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER} * @param comps The array component number * @param dataType The array index GL data type @@ -183,7 +190,7 @@ public class GLArrayDataWrapper implements GLArrayData { // @Override - public final boolean isVertexAttribute() { return isVertexAttribute; } + public final boolean isVertexAttribute() { return isVertexAttr; } @Override public final int getIndex() { return index; } @@ -229,53 +236,119 @@ public class GLArrayDataWrapper implements GLArrayData { public Buffer getBuffer() { return buffer; } @Override - public final int getCompsPerElem() { return componentsPerElement; } + public final int getCompsPerElem() { return compsPerElement; } @Override - public final int getCompType() { return componentType; } + public final int getCompType() { return compType; } @Override - public final int getBytesPerComp() { return bytesPerComponent; } + public final int getBytesPerComp() { return bytesPerComp; } + + @Override + public final boolean sealed() { return sealed; } @Override public final int getElemCount() { - if( 0 != mappedElementCount ) { - return mappedElementCount; + if( 0 != mappedElemCount ) { + return mappedElemCount; + } else if( null != buffer ) { + if( sealed ) { + return ( buffer.limit() * bytesPerComp ) / strideB ; + } else { + return ( buffer.position() * bytesPerComp ) / strideB ; + } + } else { + return 0; + } + } + + @Override + public final int elemPosition() { + if( 0 != mappedElemCount ) { + return mappedElemCount; + } else if( null != buffer ) { + return ( buffer.position() * bytesPerComp ) / strideB ; + } else { + return 0; + } + } + + @Override + public int remainingElems() { + if( null != buffer ) { + return ( buffer.remaining() * bytesPerComp ) / strideB ; + } else { + return 0; + } + } + + @Override + public int getElemCapacity() { + if( null != buffer ) { + return ( buffer.capacity() * bytesPerComp ) / strideB ; + } else { + return 0; + } + } + + @Override + public final int getByteCount() { + if( 0 != mappedElemCount ) { + return mappedElemCount * compsPerElement * bytesPerComp ; } else if( null != buffer ) { - final int remainingComponents = ( 0 == buffer.position() ) ? buffer.limit() : buffer.position(); - return ( remainingComponents * bytesPerComponent ) / strideB ; + if( sealed ) { + return buffer.limit() * bytesPerComp ; + } else { + return buffer.position() * bytesPerComp ; + } } else { return 0; } } @Override - public final int getSizeInBytes() { - if( 0 != mappedElementCount ) { - return mappedElementCount * componentsPerElement * bytesPerComponent ; + public final int bytePosition() { + if( 0 != mappedElemCount ) { + return mappedElemCount * compsPerElement * bytesPerComp ; } else if( null != buffer ) { - return ( buffer.position()==0 ) ? ( buffer.limit() * bytesPerComponent ) : ( buffer.position() * bytesPerComponent ) ; + return buffer.position() * bytesPerComp; } else { return 0; } } @Override - public int getCapacityInBytes() { + public int remainingBytes() { + if( null != buffer ) { + return buffer.remaining() * bytesPerComp; + } else { + return 0; + } + } + + @Override + public int getByteCapacity() { if( null != buffer ) { - return buffer.capacity() * bytesPerComponent; + return buffer.capacity() * bytesPerComp; } else { return 0; } } @Override - public void printStats(final PrintStream out) { - final int sz_bytes = getSizeInBytes(); - final int cap_bytes = getCapacityInBytes(); - final float filled = (float)sz_bytes/(float)cap_bytes; - out.printf("elements %,d / %,d, bytes %,d / %,d, filled %.1f%%, left %.1f%%", - getElemCount(), cap_bytes / (componentsPerElement * bytesPerComponent), sz_bytes, cap_bytes, filled*100f, (1f-filled)*100f); + public String fillStatsToString() { + final int cnt_bytes = getByteCount(); + final int cap_bytes = getByteCapacity(); + final float filled = (float)cnt_bytes/(float)cap_bytes; + return String.format("elements %,d cnt / %,d cap, bytes %,d cnt / %,d cap, filled %.1f%%, left %.1f%%", + getElemCount(), getElemCapacity(), cnt_bytes, cap_bytes, filled*100f, (1f-filled)*100f); + } + + @Override + public String elemStatsToString() { + final int elem_limit = null != buffer ? ( buffer.limit() * bytesPerComp ) / strideB : 0; + return String.format("sealed %b, elements %,d cnt, [%,d pos .. %,d rem .. %,d lim .. %,d cap]", + sealed(), getElemCount(), elemPosition(), remainingElems(), elem_limit, getElemCapacity()); } @Override @@ -284,7 +357,7 @@ public class GLArrayDataWrapper implements GLArrayData { @Override public final int getStride() { return strideB; } - public final Class<?> getBufferClass() { return componentClazz; } + public final Class<?> getBufferClass() { return compClazz; } @Override public void destroy(final GL gl) { @@ -300,13 +373,13 @@ public class GLArrayDataWrapper implements GLArrayData { return "GLArrayDataWrapper["+name+ ", index "+index+ ", location "+location+ - ", isVertexAttribute "+isVertexAttribute+ - ", dataType 0x"+Integer.toHexString(componentType)+ - ", bufferClazz "+componentClazz+ - ", elements "+getElemCount()+ - ", components "+componentsPerElement+ + ", isVertexAttribute "+isVertexAttr+ + ", dataType 0x"+Integer.toHexString(compType)+ + ", bufferClazz "+compClazz+ + ", compsPerElem "+compsPerElement+ ", stride "+strideB+"b "+strideL+"c"+ - ", mappedElementCount "+mappedElementCount+ + ", mappedElemCount "+mappedElemCount+ + ", "+elemStatsToString()+ ", buffer "+buffer+ ", vboEnabled "+vboEnabled+ ", vboName "+vboName+ @@ -399,33 +472,33 @@ public class GLArrayDataWrapper implements GLArrayData { } // immutable types - this.componentType = componentType; - componentClazz = getBufferClass(componentType); - bytesPerComponent = GLBuffers.sizeOfGLType(componentType); - if(0 > bytesPerComponent) { + this.compType = componentType; + compClazz = getBufferClass(componentType); + bytesPerComp = GLBuffers.sizeOfGLType(componentType); + if(0 > bytesPerComp) { throw new GLException("Given componentType not supported: "+componentType+":\n\t"+this); } if(0 >= componentsPerElement) { throw new GLException("Invalid number of components: " + componentsPerElement); } - this.componentsPerElement = componentsPerElement; + this.compsPerElement = componentsPerElement; - if(0<stride && stride<componentsPerElement*bytesPerComponent) { - throw new GLException("stride ("+stride+") lower than component bytes, "+componentsPerElement+" * "+bytesPerComponent); + if(0<stride && stride<componentsPerElement*bytesPerComp) { + throw new GLException("stride ("+stride+") lower than component bytes, "+componentsPerElement+" * "+bytesPerComp); } - if(0<stride && stride%bytesPerComponent!=0) { - throw new GLException("stride ("+stride+") not a multiple of bpc "+bytesPerComponent); + if(0<stride && stride%bytesPerComp!=0) { + throw new GLException("stride ("+stride+") not a multiple of bpc "+bytesPerComp); } - this.strideB=(0==stride)?componentsPerElement*bytesPerComponent:stride; - this.strideL=strideB/bytesPerComponent; + this.strideB=(0==stride)?componentsPerElement*bytesPerComp:stride; + this.strideL=strideB/bytesPerComp; if( GLBuffers.isGLTypeFixedPoint(componentType) ) { this.normalized = normalized; } else { this.normalized = false; } - this.mappedElementCount = mappedElementCount; - this.isVertexAttribute = isVertexAttribute; + this.mappedElemCount = mappedElementCount; + this.isVertexAttr = isVertexAttribute; // mutable types this.index = index; @@ -455,6 +528,7 @@ public class GLArrayDataWrapper implements GLArrayData { this.vboUsage=vboUsage; this.vboTarget=vboTarget; this.alive=true; + this.sealed = true; } /** @@ -468,15 +542,15 @@ public class GLArrayDataWrapper implements GLArrayData { */ public GLArrayDataWrapper(final GLArrayDataWrapper src) { // immutable types - this.componentType = src.componentType; - this.componentClazz = src.componentClazz; - this.bytesPerComponent = src.bytesPerComponent; - this.componentsPerElement = src.componentsPerElement; + this.compType = src.compType; + this.compClazz = src.compClazz; + this.bytesPerComp = src.bytesPerComp; + this.compsPerElement = src.compsPerElement; this.strideB = src.strideB; this.strideL = src.strideL; this.normalized = src.normalized; - this.mappedElementCount = src.mappedElementCount; - this.isVertexAttribute = src.isVertexAttribute; + this.mappedElemCount = src.mappedElemCount; + this.isVertexAttr = src.isVertexAttr; // mutable types this.alive = src.alive; @@ -497,20 +571,22 @@ public class GLArrayDataWrapper implements GLArrayData { this.vboEnabled = src.vboEnabled; this.vboUsage = src.vboUsage; this.vboTarget = src.vboTarget; + this.sealed = src.sealed; } - protected final int componentType; - protected final Class<?> componentClazz; - protected final int bytesPerComponent; - protected final int componentsPerElement; - /** stride in bytes; strideB >= componentsPerElement * componentByteSize */ + protected final int compType; + protected final Class<?> compClazz; + protected final int bytesPerComp; + protected final int compsPerElement; + /** stride in bytes; strideB >= compsPerElement * bytesPerComp */ protected final int strideB; /** stride in logical components */ protected final int strideL; protected final boolean normalized; - protected final int mappedElementCount; - protected final boolean isVertexAttribute; + protected final int mappedElemCount; + protected final boolean isVertexAttr; + // mutable types protected boolean alive; protected int index; protected int location; @@ -521,5 +597,6 @@ public class GLArrayDataWrapper implements GLArrayData { protected boolean vboEnabled; protected int vboUsage; protected int vboTarget; + protected boolean sealed; } diff --git a/src/jogl/classes/com/jogamp/opengl/util/caps/NonFSAAGLCapsChooser.java b/src/jogl/classes/com/jogamp/opengl/util/caps/NonFSAAGLCapsChooser.java new file mode 100644 index 000000000..5dc7d7f48 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/caps/NonFSAAGLCapsChooser.java @@ -0,0 +1,84 @@ +/** + * Copyright 2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util.caps; + +import java.util.ArrayList; +import java.util.List; + +import com.jogamp.nativewindow.CapabilitiesImmutable; +import com.jogamp.opengl.DefaultGLCapabilitiesChooser; +import com.jogamp.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.GLCapabilitiesChooser; + +/** + * Custom {@link GLCapabilitiesChooser}, filtering out all full screen anti-aliasing (FSAA, multisample) capabilities, + * i.e. all matching {@link GLCapabilitiesImmutable} with {@link GLCapabilitiesImmutable#getSampleBuffers()}. + */ +public class NonFSAAGLCapsChooser extends DefaultGLCapabilitiesChooser { + private final boolean verbose; + public NonFSAAGLCapsChooser(final boolean verbose) { + this.verbose = verbose; + } + public NonFSAAGLCapsChooser() { + this.verbose = false; + } + + @Override + public int chooseCapabilities(final CapabilitiesImmutable desired, + final List<? extends CapabilitiesImmutable> available, + int recommendedIdx) { + final GLCapabilitiesImmutable recommended; + if( 0 <= recommendedIdx && recommendedIdx < available.size() ) { + recommended = (GLCapabilitiesImmutable) available.get(recommendedIdx); + } else { + recommended = null; + recommendedIdx = -1; + } + final List<GLCapabilitiesImmutable> clean = new ArrayList<GLCapabilitiesImmutable>(); + for (int i = 0; i < available.size(); i++) { + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) available.get(i); + if ( caps.getSampleBuffers() ) { + /** if( caps.equals(recommended) ) { // the matching index is enough! + System.err.println("Dropping["+i+"] "+caps+", matched recommended["+recommendedIdx+"] = "+recommended); + recommendedIdx = -1; + } else */ + if( recommendedIdx == i ) { + if( verbose ) { + System.err.println("Dropping["+i+"] "+caps+", sameidx recommended["+recommendedIdx+"] = "+recommended); + } + recommendedIdx = -1; + } else if( verbose ) { + System.err.println("Dropping "+caps+" != recommended["+recommendedIdx+"]"); + } + } else { + clean.add(caps); + } + } + return super.chooseCapabilities(desired, clean, recommendedIdx); + } +} diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java index b7a244f81..89693bb66 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java @@ -29,6 +29,8 @@ package jogamp.graph.curve.opengl; import java.io.PrintStream; import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLProfile; @@ -51,13 +53,15 @@ import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureSequence; -public class VBORegion2PMSAAES2 extends GLRegion { +public final class VBORegion2PMSAAES2 extends GLRegion { private static final boolean DEBUG_FBO_1 = false; private static final boolean DEBUG_FBO_2 = false; private final RenderState.ProgramLocal rsLocal; // Pass-1: + private int curVerticesCap = 0; + private int curIndicesCap = 0; private GLArrayDataServer gca_VerticesAttr; private GLArrayDataServer gca_CurveParamsAttr; private GLArrayDataServer gca_ColorsAttr; @@ -84,58 +88,6 @@ public class VBORegion2PMSAAES2 extends GLRegion { final int[] maxTexSize = new int[] { -1 } ; - /** - * <p> - * Since multiple {@link Region}s may share one - * {@link ShaderProgram}, the uniform data must always be updated. - * </p> - * - * @param gl - * @param renderer - * @param renderModes - * @param pass1 - * @param quality - * @param sampleCount - */ - public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final boolean pass1, final int quality, final int sampleCount) { - final RenderState rs = renderer.getRenderState(); - final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount, colorTexSeq); - final ShaderProgram sp = renderer.getRenderState().getShaderProgram(); - final boolean updateLocLocal; - if( pass1 ) { - updateLocLocal = !sp.equals(spPass1); - spPass1 = sp; - if( DEBUG ) { - System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal); - } - if( updateLocLocal ) { - rs.updateAttributeLoc(gl, true, gca_VerticesAttr, true); - rs.updateAttributeLoc(gl, true, gca_CurveParamsAttr, true); - if( null != gca_ColorsAttr ) { - rs.updateAttributeLoc(gl, true, gca_ColorsAttr, true); - } - } - rsLocal.update(gl, rs, updateLocLocal, renderModes, true, true); - rs.updateUniformLoc(gl, updateLocLocal, gcu_PMVMatrix02, true); - if( null != gcu_ColorTexUnit ) { - rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, true); - rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, true); - } - } else { - updateLocLocal = !sp.equals(spPass2); - spPass2 = sp; - if( DEBUG ) { - System.err.println("XXX changedSP.p2 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal); - } - if( updateLocLocal ) { - rs.updateAttributeLoc(gl, true, gca_FboVerticesAttr, true); - rs.updateAttributeLoc(gl, true, gca_FboTexCoordsAttr, true); - } - rsLocal.update(gl, rs, updateLocLocal, renderModes, false, true); - rs.updateUniformDataLoc(gl, updateLocLocal, false /* updateData */, gcu_FboTexUnit, true); // FIXME always update if changing tex-unit - } - } - public VBORegion2PMSAAES2(final GLProfile glp, final int renderModes, final TextureSequence colorTexSeq, final int pass2TexUnit, final int initialVerticesCount, final int initialIndicesCount) { @@ -146,20 +98,8 @@ public class VBORegion2PMSAAES2 extends GLRegion { // We leave GLArrayDataClient.DEFAULT_GROWTH_FACTOR intact for avg +19% size, but 15% less CPU overhead compared to 1.2 (19% total) // Pass 1: - indicesBuffer = GLArrayDataServer.createData(3, glIdxType(), initialIndicesCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); - - gca_VerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL.GL_FLOAT, - false, initialVerticesCount, GL.GL_STATIC_DRAW); - - gca_CurveParamsAttr = GLArrayDataServer.createGLSL(AttributeNames.CURVEPARAMS_ATTR_NAME, 3, GL.GL_FLOAT, - false, initialVerticesCount, GL.GL_STATIC_DRAW); + initBuffer(initialVerticesCount, initialIndicesCount); - if( hasColorChannel() ) { - gca_ColorsAttr = GLArrayDataServer.createGLSL(AttributeNames.COLOR_ATTR_NAME, 4, GL.GL_FLOAT, - false, initialVerticesCount, GL.GL_STATIC_DRAW); - } else { - gca_ColorsAttr = null; - } if( hasColorTexture() ) { gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit()); colorTexBBox = new float[4]; @@ -194,13 +134,54 @@ public class VBORegion2PMSAAES2 extends GLRegion { false, 4, GL.GL_STATIC_DRAW); } + private void initBuffer(final int verticeCount, final int indexCount) { + indicesBuffer = GLArrayDataServer.createData(3, glIdxType(), indexCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); + indicesBuffer.setGrowthFactor(growthFactor); + curIndicesCap = indicesBuffer.getElemCapacity(); + + gca_VerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL.GL_FLOAT, + false, verticeCount, GL.GL_STATIC_DRAW); + gca_VerticesAttr.setGrowthFactor(growthFactor); + gca_CurveParamsAttr = GLArrayDataServer.createGLSL(AttributeNames.CURVEPARAMS_ATTR_NAME, 3, GL.GL_FLOAT, + false, verticeCount, GL.GL_STATIC_DRAW); + gca_CurveParamsAttr.setGrowthFactor(growthFactor); + if( hasColorChannel() ) { + gca_ColorsAttr = GLArrayDataServer.createGLSL(AttributeNames.COLOR_ATTR_NAME, 4, GL.GL_FLOAT, + false, verticeCount, GL.GL_STATIC_DRAW); + gca_ColorsAttr.setGrowthFactor(growthFactor); + } + curVerticesCap = gca_VerticesAttr.getElemCapacity(); + } + @Override - public void growBufferSize(final int verticeCount, final int indexCount) { - indicesBuffer.growIfNeeded(indexCount * indicesBuffer.getCompsPerElem()); - gca_VerticesAttr.growIfNeeded(verticeCount * gca_VerticesAttr.getCompsPerElem()); - gca_CurveParamsAttr.growIfNeeded(verticeCount * gca_CurveParamsAttr.getCompsPerElem()); - if( null != gca_ColorsAttr ) { - gca_ColorsAttr.growIfNeeded(verticeCount * gca_ColorsAttr.getCompsPerElem()); + public void growBuffer(final int verticesCount, final int indicesCount) { + if( curIndicesCap < indicesBuffer.elemPosition() + indicesCount ) { + indicesBuffer.growIfNeeded(indicesCount * indicesBuffer.getCompsPerElem()); + curIndicesCap = indicesBuffer.getElemCapacity(); + } + if( curVerticesCap < gca_VerticesAttr.elemPosition() + verticesCount ) { + gca_VerticesAttr.growIfNeeded(verticesCount * gca_VerticesAttr.getCompsPerElem()); + gca_CurveParamsAttr.growIfNeeded(verticesCount * gca_CurveParamsAttr.getCompsPerElem()); + if( null != gca_ColorsAttr ) { + gca_ColorsAttr.growIfNeeded(verticesCount * gca_ColorsAttr.getCompsPerElem()); + } + curVerticesCap = gca_VerticesAttr.getElemCapacity(); + } + } + + @Override + public void setBufferCapacity(final int verticesCount, final int indicesCount) { + if( curIndicesCap < indicesCount ) { + indicesBuffer.reserve(indicesCount); + curIndicesCap = indicesBuffer.getElemCapacity(); + } + if( curVerticesCap < verticesCount ) { + gca_VerticesAttr.reserve(verticesCount); + gca_CurveParamsAttr.reserve(verticesCount); + if( null != gca_ColorsAttr ) { + gca_ColorsAttr.reserve(verticesCount); + } + curVerticesCap = gca_VerticesAttr.getElemCapacity(); } } @@ -240,15 +221,11 @@ public class VBORegion2PMSAAES2 extends GLRegion { @Override protected final void pushVertex(final float[] coords, final float[] texParams, final float[] rgba) { - // NIO array[3] is much slows than group/single - // gca_VerticesAttr.putf(coords, 0, 3); - // gca_CurveParamsAttr.putf(texParams, 0, 3); - gca_VerticesAttr.put3f(coords[0], coords[1], coords[2]); - gca_CurveParamsAttr.put3f(texParams[0], texParams[1], texParams[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords[0], coords[1], coords[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams[0], texParams[1], texParams[2]); if( null != gca_ColorsAttr ) { if( null != rgba ) { - // gca_ColorsAttr.putf(rgba, 0, 4); - gca_ColorsAttr.put4f(rgba[0], rgba[1], rgba[2], rgba[3]); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), rgba[0], rgba[1], rgba[2], rgba[3]); } else { throw new IllegalArgumentException("Null color given for COLOR_CHANNEL rendering mode"); } @@ -258,18 +235,18 @@ public class VBORegion2PMSAAES2 extends GLRegion { @Override protected final void pushVertices(final float[] coords1, final float[] coords2, final float[] coords3, final float[] texParams1, final float[] texParams2, final float[] texParams3, final float[] rgba) { - gca_VerticesAttr.put3f(coords1[0], coords1[1], coords1[2]); - gca_VerticesAttr.put3f(coords2[0], coords2[1], coords2[2]); - gca_VerticesAttr.put3f(coords3[0], coords3[1], coords3[2]); - gca_CurveParamsAttr.put3f(texParams1[0], texParams1[1], texParams1[2]); - gca_CurveParamsAttr.put3f(texParams2[0], texParams2[1], texParams2[2]); - gca_CurveParamsAttr.put3f(texParams3[0], texParams3[1], texParams3[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords1[0], coords1[1], coords1[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords2[0], coords2[1], coords2[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords3[0], coords3[1], coords3[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams1[0], texParams1[1], texParams1[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams2[0], texParams2[1], texParams2[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams3[0], texParams3[1], texParams3[2]); if( null != gca_ColorsAttr ) { if( null != rgba ) { final float r=rgba[0], g=rgba[1], b=rgba[2], a=rgba[3]; - gca_ColorsAttr.put4f(r, g, b, a); - gca_ColorsAttr.put4f(r, g, b, a); - gca_ColorsAttr.put4f(r, g, b, a); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), r, g, b, a); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), r, g, b, a); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), r, g, b, a); } else { throw new IllegalArgumentException("Null color given for COLOR_CHANNEL rendering mode"); } @@ -288,9 +265,9 @@ public class VBORegion2PMSAAES2 extends GLRegion { @Override protected final void pushIndices(final int idx1, final int idx2, final int idx3) { if( usesI32Idx() ) { - indicesBuffer.put3i(idx1, idx2, idx3); + put3i((IntBuffer)indicesBuffer.getBuffer(), idx1, idx2, idx3); } else { - indicesBuffer.put3s((short)idx1, (short)idx2, (short)idx3); + put3s((ShortBuffer)indicesBuffer.getBuffer(), (short)idx1, (short)idx2, (short)idx3); } } @@ -342,6 +319,58 @@ public class VBORegion2PMSAAES2 extends GLRegion { // the buffers were disabled, since due to real/fbo switching and other vbo usage } + /** + * <p> + * Since multiple {@link Region}s may share one + * {@link ShaderProgram}, the uniform data must always be updated. + * </p> + * + * @param gl + * @param renderer + * @param renderModes + * @param pass1 + * @param quality + * @param sampleCount + */ + public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final boolean pass1, final int quality, final int sampleCount) { + final RenderState rs = renderer.getRenderState(); + final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount, colorTexSeq); + final ShaderProgram sp = renderer.getRenderState().getShaderProgram(); + final boolean updateLocLocal; + if( pass1 ) { + updateLocLocal = !sp.equals(spPass1); + spPass1 = sp; + if( DEBUG ) { + System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal); + } + if( updateLocLocal ) { + rs.updateAttributeLoc(gl, true, gca_VerticesAttr, true); + rs.updateAttributeLoc(gl, true, gca_CurveParamsAttr, true); + if( null != gca_ColorsAttr ) { + rs.updateAttributeLoc(gl, true, gca_ColorsAttr, true); + } + } + rsLocal.update(gl, rs, updateLocLocal, renderModes, true, true); + rs.updateUniformLoc(gl, updateLocLocal, gcu_PMVMatrix02, true); + if( null != gcu_ColorTexUnit ) { + rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, true); + rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, true); + } + } else { + updateLocLocal = !sp.equals(spPass2); + spPass2 = sp; + if( DEBUG ) { + System.err.println("XXX changedSP.p2 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal); + } + if( updateLocLocal ) { + rs.updateAttributeLoc(gl, true, gca_FboVerticesAttr, true); + rs.updateAttributeLoc(gl, true, gca_FboTexCoordsAttr, true); + } + rsLocal.update(gl, rs, updateLocLocal, renderModes, false, true); + rs.updateUniformDataLoc(gl, updateLocLocal, false /* updateData */, gcu_FboTexUnit, true); // FIXME always update if changing tex-unit + } + } + private final AABBox drawWinBox = new AABBox(); private final int[] drawView = new int[] { 0, 0, 0, 0 }; private final float[] drawVec4Tmp0 = new float[4]; diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java index 2998f3fe1..9567bab10 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java @@ -29,6 +29,8 @@ package jogamp.graph.curve.opengl; import java.io.PrintStream; import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLProfile; @@ -56,7 +58,7 @@ import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureSequence; -public class VBORegion2PVBAAES2 extends GLRegion { +public final class VBORegion2PVBAAES2 extends GLRegion { private static final boolean DEBUG_FBO_1 = false; private static final boolean DEBUG_FBO_2 = false; @@ -93,6 +95,8 @@ public class VBORegion2PVBAAES2 extends GLRegion { private final RenderState.ProgramLocal rsLocal; // Pass-1: + private int curVerticesCap = 0; + private int curIndicesCap = 0; private GLArrayDataServer gca_VerticesAttr; private GLArrayDataServer gca_CurveParamsAttr; private GLArrayDataServer gca_ColorsAttr; @@ -174,9 +178,6 @@ public class VBORegion2PVBAAES2 extends GLRegion { } } - // private static final float growthFactor = 1.2f; // avg +5% size but 15% more overhead (34% total) - private static final float growthFactor = GLArrayDataClient.DEFAULT_GROWTH_FACTOR; // avg +20% size, but 15% less CPU overhead compared to 1.2 (19% total) - public VBORegion2PVBAAES2(final GLProfile glp, final int renderModes, final TextureSequence colorTexSeq, final int pass2TexUnit, final int initialVerticesCount, final int initialIndicesCount) { @@ -185,7 +186,7 @@ public class VBORegion2PVBAAES2 extends GLRegion { rsLocal = new RenderState.ProgramLocal(); // Pass 1: - growBufferSize(initialVerticesCount, initialIndicesCount); + initBuffer(initialVerticesCount, initialIndicesCount); if( hasColorTexture() ) { gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit()); @@ -222,37 +223,58 @@ public class VBORegion2PVBAAES2 extends GLRegion { false, 4, GL.GL_STATIC_DRAW); } + private void initBuffer(final int verticeCount, final int indexCount) { + indicesBuffer = GLArrayDataServer.createData(3, glIdxType(), indexCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); + indicesBuffer.setGrowthFactor(growthFactor); + curIndicesCap = indicesBuffer.getElemCapacity(); + + gca_VerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL.GL_FLOAT, + false, verticeCount, GL.GL_STATIC_DRAW); + gca_VerticesAttr.setGrowthFactor(growthFactor); + gca_CurveParamsAttr = GLArrayDataServer.createGLSL(AttributeNames.CURVEPARAMS_ATTR_NAME, 3, GL.GL_FLOAT, + false, verticeCount, GL.GL_STATIC_DRAW); + gca_CurveParamsAttr.setGrowthFactor(growthFactor); + if( hasColorChannel() ) { + gca_ColorsAttr = GLArrayDataServer.createGLSL(AttributeNames.COLOR_ATTR_NAME, 4, GL.GL_FLOAT, + false, verticeCount, GL.GL_STATIC_DRAW); + gca_ColorsAttr.setGrowthFactor(growthFactor); + } + curVerticesCap = gca_VerticesAttr.getElemCapacity(); + } + @Override - public void growBufferSize(final int verticeCount, final int indexCount) { - if(null == indicesBuffer ) { - indicesBuffer = GLArrayDataServer.createData(3, glIdxType(), indexCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); - indicesBuffer.setGrowthFactor(growthFactor); - } else { - indicesBuffer.growIfNeeded(indexCount * indicesBuffer.getCompsPerElem()); - } - if( null == gca_VerticesAttr ) { - gca_VerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL.GL_FLOAT, - false, verticeCount, GL.GL_STATIC_DRAW); - gca_VerticesAttr.setGrowthFactor(growthFactor); - } else { - gca_VerticesAttr.growIfNeeded(verticeCount * gca_VerticesAttr.getCompsPerElem()); - } - if( null == gca_CurveParamsAttr ) { - gca_CurveParamsAttr = GLArrayDataServer.createGLSL(AttributeNames.CURVEPARAMS_ATTR_NAME, 3, GL.GL_FLOAT, - false, verticeCount, GL.GL_STATIC_DRAW); - gca_CurveParamsAttr.setGrowthFactor(growthFactor); - } else { - gca_CurveParamsAttr.growIfNeeded(verticeCount * gca_CurveParamsAttr.getCompsPerElem()); + public void growBuffer(final int verticesCount, final int indicesCount) { + if( curIndicesCap < indicesBuffer.elemPosition() + indicesCount ) { + // System.err.printf("XXX Buffer grow - Indices: %d < ( %d = %d + %d ); Status: %s%n", + // curIndicesCap, indicesBuffer.elemPosition() + indicesCount, indicesBuffer.elemPosition(), indicesCount, indicesBuffer.elemStatsToString()); + indicesBuffer.growIfNeeded(indicesCount * indicesBuffer.getCompsPerElem()); + curIndicesCap = indicesBuffer.getElemCapacity(); + } + if( curVerticesCap < gca_VerticesAttr.elemPosition() + verticesCount ) { + // System.err.printf("XXX Buffer grow - Verices: %d < ( %d = %d + %d ); Status: %s%n", + // curVerticesCap, gca_VerticesAttr.elemPosition() + verticesCount, gca_VerticesAttr.elemPosition(), verticesCount, gca_VerticesAttr.elemStatsToString()); + gca_VerticesAttr.growIfNeeded(verticesCount * gca_VerticesAttr.getCompsPerElem()); + gca_CurveParamsAttr.growIfNeeded(verticesCount * gca_CurveParamsAttr.getCompsPerElem()); + if( null != gca_ColorsAttr ) { + gca_ColorsAttr.growIfNeeded(verticesCount * gca_ColorsAttr.getCompsPerElem()); + } + curVerticesCap = gca_VerticesAttr.getElemCapacity(); } + } - if( null == gca_ColorsAttr ) { - if( hasColorChannel() ) { - gca_ColorsAttr = GLArrayDataServer.createGLSL(AttributeNames.COLOR_ATTR_NAME, 4, GL.GL_FLOAT, - false, verticeCount, GL.GL_STATIC_DRAW); - gca_ColorsAttr.setGrowthFactor(growthFactor); + @Override + public void setBufferCapacity(final int verticesCount, final int indicesCount) { + if( curIndicesCap < indicesCount ) { + indicesBuffer.reserve(indicesCount); + curIndicesCap = indicesBuffer.getElemCapacity(); + } + if( curVerticesCap < verticesCount ) { + gca_VerticesAttr.reserve(verticesCount); + gca_CurveParamsAttr.reserve(verticesCount); + if( null != gca_ColorsAttr ) { + gca_ColorsAttr.reserve(verticesCount); } - } else { - gca_ColorsAttr.growIfNeeded(verticeCount * gca_ColorsAttr.getCompsPerElem()); + curVerticesCap = gca_VerticesAttr.getElemCapacity(); } } @@ -299,12 +321,15 @@ public class VBORegion2PVBAAES2 extends GLRegion { // NIO array[3] is much slows than group/single // gca_VerticesAttr.putf(coords, 0, 3); // gca_CurveParamsAttr.putf(texParams, 0, 3); - gca_VerticesAttr.put3f(coords[0], coords[1], coords[2]); - gca_CurveParamsAttr.put3f(texParams[0], texParams[1], texParams[2]); + // gca_VerticesAttr.put3f(coords[0], coords[1], coords[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords[0], coords[1], coords[2]); + // gca_CurveParamsAttr.put3f(texParams[0], texParams[1], texParams[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams[0], texParams[1], texParams[2]); if( null != gca_ColorsAttr ) { if( null != rgba ) { // gca_ColorsAttr.putf(rgba, 0, 4); - gca_ColorsAttr.put4f(rgba[0], rgba[1], rgba[2], rgba[3]); + // gca_ColorsAttr.put4f(rgba[0], rgba[1], rgba[2], rgba[3]); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), rgba[0], rgba[1], rgba[2], rgba[3]); } else { throw new IllegalArgumentException("Null color given for COLOR_CHANNEL rendering mode"); } @@ -314,18 +339,27 @@ public class VBORegion2PVBAAES2 extends GLRegion { @Override protected final void pushVertices(final float[] coords1, final float[] coords2, final float[] coords3, final float[] texParams1, final float[] texParams2, final float[] texParams3, final float[] rgba) { - gca_VerticesAttr.put3f(coords1[0], coords1[1], coords1[2]); - gca_VerticesAttr.put3f(coords2[0], coords2[1], coords2[2]); - gca_VerticesAttr.put3f(coords3[0], coords3[1], coords3[2]); - gca_CurveParamsAttr.put3f(texParams1[0], texParams1[1], texParams1[2]); - gca_CurveParamsAttr.put3f(texParams2[0], texParams2[1], texParams2[2]); - gca_CurveParamsAttr.put3f(texParams3[0], texParams3[1], texParams3[2]); + // gca_VerticesAttr.put3f(coords1[0], coords1[1], coords1[2]); + // gca_VerticesAttr.put3f(coords2[0], coords2[1], coords2[2]); + // gca_VerticesAttr.put3f(coords3[0], coords3[1], coords3[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords1[0], coords1[1], coords1[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords2[0], coords2[1], coords2[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords3[0], coords3[1], coords3[2]); + // gca_CurveParamsAttr.put3f(texParams1[0], texParams1[1], texParams1[2]); + // gca_CurveParamsAttr.put3f(texParams2[0], texParams2[1], texParams2[2]); + // gca_CurveParamsAttr.put3f(texParams3[0], texParams3[1], texParams3[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams1[0], texParams1[1], texParams1[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams2[0], texParams2[1], texParams2[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams3[0], texParams3[1], texParams3[2]); if( null != gca_ColorsAttr ) { if( null != rgba ) { final float r=rgba[0], g=rgba[1], b=rgba[2], a=rgba[3]; - gca_ColorsAttr.put4f(r, g, b, a); - gca_ColorsAttr.put4f(r, g, b, a); - gca_ColorsAttr.put4f(r, g, b, a); + // gca_ColorsAttr.put4f(r, g, b, a); + // gca_ColorsAttr.put4f(r, g, b, a); + // gca_ColorsAttr.put4f(r, g, b, a); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), r, g, b, a); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), r, g, b, a); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), r, g, b, a); } else { throw new IllegalArgumentException("Null color given for COLOR_CHANNEL rendering mode"); } @@ -344,9 +378,11 @@ public class VBORegion2PVBAAES2 extends GLRegion { @Override protected final void pushIndices(final int idx1, final int idx2, final int idx3) { if( usesI32Idx() ) { - indicesBuffer.put3i(idx1, idx2, idx3); + // indicesBuffer.put3i(idx1, idx2, idx3); + put3i((IntBuffer)indicesBuffer.getBuffer(), idx1, idx2, idx3); } else { - indicesBuffer.put3s((short)idx1, (short)idx2, (short)idx3); + // indicesBuffer.put3s((short)idx1, (short)idx2, (short)idx3); + put3s((ShortBuffer)indicesBuffer.getBuffer(), (short)idx1, (short)idx2, (short)idx3); } } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java index 5a4c0c731..adf3e4bc2 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java @@ -29,6 +29,8 @@ package jogamp.graph.curve.opengl; import java.io.PrintStream; import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; @@ -48,9 +50,11 @@ import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureSequence; -public class VBORegionSPES2 extends GLRegion { +public final class VBORegionSPES2 extends GLRegion { private final RenderState.ProgramLocal rsLocal; + private int curVerticesCap = 0; + private int curIndicesCap = 0; private GLArrayDataServer gca_VerticesAttr = null; private GLArrayDataServer gca_CurveParamsAttr = null; private GLArrayDataServer gca_ColorsAttr; @@ -67,22 +71,8 @@ public class VBORegionSPES2 extends GLRegion { rsLocal = new RenderState.ProgramLocal(); - // We leave GLArrayDataClient.DEFAULT_GROWTH_FACTOR intact for avg +19% size, but 15% less CPU overhead compared to 1.2 (19% total) + initBuffer(initialVerticesCount, initialIndicesCount); - indicesBuffer = GLArrayDataServer.createData(3, glIdxType(), initialIndicesCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); - - gca_VerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL.GL_FLOAT, - false, initialVerticesCount, GL.GL_STATIC_DRAW); - - gca_CurveParamsAttr = GLArrayDataServer.createGLSL(AttributeNames.CURVEPARAMS_ATTR_NAME, 3, GL.GL_FLOAT, - false, initialVerticesCount, GL.GL_STATIC_DRAW); - - if( hasColorChannel() ) { - gca_ColorsAttr = GLArrayDataServer.createGLSL(AttributeNames.COLOR_ATTR_NAME, 4, GL.GL_FLOAT, - false, initialVerticesCount, GL.GL_STATIC_DRAW); - } else { - gca_ColorsAttr = null; - } if( hasColorTexture() ) { gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit()); colorTexBBox = new float[4]; @@ -94,13 +84,54 @@ public class VBORegionSPES2 extends GLRegion { } } + private void initBuffer(final int verticeCount, final int indexCount) { + indicesBuffer = GLArrayDataServer.createData(3, glIdxType(), indexCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); + indicesBuffer.setGrowthFactor(growthFactor); + curIndicesCap = indicesBuffer.getElemCapacity(); + + gca_VerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL.GL_FLOAT, + false, verticeCount, GL.GL_STATIC_DRAW); + gca_VerticesAttr.setGrowthFactor(growthFactor); + gca_CurveParamsAttr = GLArrayDataServer.createGLSL(AttributeNames.CURVEPARAMS_ATTR_NAME, 3, GL.GL_FLOAT, + false, verticeCount, GL.GL_STATIC_DRAW); + gca_CurveParamsAttr.setGrowthFactor(growthFactor); + if( hasColorChannel() ) { + gca_ColorsAttr = GLArrayDataServer.createGLSL(AttributeNames.COLOR_ATTR_NAME, 4, GL.GL_FLOAT, + false, verticeCount, GL.GL_STATIC_DRAW); + gca_ColorsAttr.setGrowthFactor(growthFactor); + } + curVerticesCap = gca_VerticesAttr.getElemCapacity(); + } + @Override - public void growBufferSize(final int verticeCount, final int indexCount) { - indicesBuffer.growIfNeeded(indexCount * indicesBuffer.getCompsPerElem()); - gca_VerticesAttr.growIfNeeded(verticeCount * gca_VerticesAttr.getCompsPerElem()); - gca_CurveParamsAttr.growIfNeeded(verticeCount * gca_CurveParamsAttr.getCompsPerElem()); - if( null != gca_ColorsAttr ) { - gca_ColorsAttr.growIfNeeded(verticeCount * gca_ColorsAttr.getCompsPerElem()); + public void growBuffer(final int verticesCount, final int indicesCount) { + if( curIndicesCap < indicesBuffer.elemPosition() + indicesCount ) { + indicesBuffer.growIfNeeded(indicesCount * indicesBuffer.getCompsPerElem()); + curIndicesCap = indicesBuffer.getElemCapacity(); + } + if( curVerticesCap < gca_VerticesAttr.elemPosition() + verticesCount ) { + gca_VerticesAttr.growIfNeeded(verticesCount * gca_VerticesAttr.getCompsPerElem()); + gca_CurveParamsAttr.growIfNeeded(verticesCount * gca_CurveParamsAttr.getCompsPerElem()); + if( null != gca_ColorsAttr ) { + gca_ColorsAttr.growIfNeeded(verticesCount * gca_ColorsAttr.getCompsPerElem()); + } + curVerticesCap = gca_VerticesAttr.getElemCapacity(); + } + } + + @Override + public void setBufferCapacity(final int verticesCount, final int indicesCount) { + if( curIndicesCap < indicesCount ) { + indicesBuffer.reserve(indicesCount); + curIndicesCap = indicesBuffer.getElemCapacity(); + } + if( curVerticesCap < verticesCount ) { + gca_VerticesAttr.reserve(verticesCount); + gca_CurveParamsAttr.reserve(verticesCount); + if( null != gca_ColorsAttr ) { + gca_ColorsAttr.reserve(verticesCount); + } + curVerticesCap = gca_VerticesAttr.getElemCapacity(); } } @@ -142,15 +173,11 @@ public class VBORegionSPES2 extends GLRegion { @Override protected final void pushVertex(final float[] coords, final float[] texParams, final float[] rgba) { - // NIO array[3] is much slows than group/single - // gca_VerticesAttr.putf(coords, 0, 3); - // gca_CurveParamsAttr.putf(texParams, 0, 3); - gca_VerticesAttr.put3f(coords[0], coords[1], coords[2]); - gca_CurveParamsAttr.put3f(texParams[0], texParams[1], texParams[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords[0], coords[1], coords[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams[0], texParams[1], texParams[2]); if( null != gca_ColorsAttr ) { if( null != rgba ) { - // gca_ColorsAttr.putf(rgba, 0, 4); - gca_ColorsAttr.put4f(rgba[0], rgba[1], rgba[2], rgba[3]); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), rgba[0], rgba[1], rgba[2], rgba[3]); } else { throw new IllegalArgumentException("Null color given for COLOR_CHANNEL rendering mode"); } @@ -160,18 +187,18 @@ public class VBORegionSPES2 extends GLRegion { @Override protected final void pushVertices(final float[] coords1, final float[] coords2, final float[] coords3, final float[] texParams1, final float[] texParams2, final float[] texParams3, final float[] rgba) { - gca_VerticesAttr.put3f(coords1[0], coords1[1], coords1[2]); - gca_VerticesAttr.put3f(coords2[0], coords2[1], coords2[2]); - gca_VerticesAttr.put3f(coords3[0], coords3[1], coords3[2]); - gca_CurveParamsAttr.put3f(texParams1[0], texParams1[1], texParams1[2]); - gca_CurveParamsAttr.put3f(texParams2[0], texParams2[1], texParams2[2]); - gca_CurveParamsAttr.put3f(texParams3[0], texParams3[1], texParams3[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords1[0], coords1[1], coords1[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords2[0], coords2[1], coords2[2]); + put3f((FloatBuffer)gca_VerticesAttr.getBuffer(), coords3[0], coords3[1], coords3[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams1[0], texParams1[1], texParams1[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams2[0], texParams2[1], texParams2[2]); + put3f((FloatBuffer)gca_CurveParamsAttr.getBuffer(), texParams3[0], texParams3[1], texParams3[2]); if( null != gca_ColorsAttr ) { if( null != rgba ) { final float r=rgba[0], g=rgba[1], b=rgba[2], a=rgba[3]; - gca_ColorsAttr.put4f(r, g, b, a); - gca_ColorsAttr.put4f(r, g, b, a); - gca_ColorsAttr.put4f(r, g, b, a); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), r, g, b, a); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), r, g, b, a); + put4f((FloatBuffer)gca_ColorsAttr.getBuffer(), r, g, b, a); } else { throw new IllegalArgumentException("Null color given for COLOR_CHANNEL rendering mode"); } @@ -190,9 +217,9 @@ public class VBORegionSPES2 extends GLRegion { @Override protected final void pushIndices(final int idx1, final int idx2, final int idx3) { if( usesI32Idx() ) { - indicesBuffer.put3i(idx1, idx2, idx3); + put3i((IntBuffer)indicesBuffer.getBuffer(), idx1, idx2, idx3); } else { - indicesBuffer.put3s((short)idx1, (short)idx2, (short)idx3); + put3s((ShortBuffer)indicesBuffer.getBuffer(), (short)idx1, (short)idx2, (short)idx3); } } diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java index ebc3eeacc..12128f5ad 100644 --- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java @@ -42,14 +42,7 @@ import jogamp.graph.font.typecast.ot.table.KernTable; import jogamp.graph.font.typecast.ot.table.KerningPair; import jogamp.graph.font.typecast.ot.table.PostTable; -import java.io.PrintStream; -import java.time.Duration; -import java.time.Instant; -import java.util.concurrent.TimeUnit; - -import com.jogamp.common.os.Clock; import com.jogamp.common.util.IntObjectHashMap; -import com.jogamp.common.util.PerfCounterCtrl; import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; @@ -293,17 +286,22 @@ class TypecastFont implements Font { @Override public AABBox getGlyphBounds(final CharSequence string) { - return getGlyphBoundsFU(string).scale2(1.0f/metrics.getUnitsPerEM(), new float[3]); + return getGlyphBounds(string, new AffineTransform(), new AffineTransform()); + } + @Override + public AABBox getGlyphBounds(final CharSequence string, final AffineTransform tmp1, final AffineTransform tmp2) { + return getGlyphBoundsFU(string, tmp1, tmp2).scale2(1.0f/metrics.getUnitsPerEM(), new float[3]); } @Override public AABBox getGlyphBoundsFU(final CharSequence string) { + return getGlyphBoundsFU(string, new AffineTransform(), new AffineTransform()); + } + @Override + public AABBox getGlyphBoundsFU(final CharSequence string, final AffineTransform temp1, final AffineTransform temp2) { if (null == string || 0 == string.length() ) { return new AABBox(); } - final AffineTransform temp1 = new AffineTransform(); - final AffineTransform temp2 = new AffineTransform(); - final AABBox res = new AABBox(); final int charCount = string.length(); @@ -367,68 +365,6 @@ class TypecastFont implements Font { return processString(visitor, transform, string, new AffineTransform(), new AffineTransform()); } - static class Perf { - Instant t0 = null; - // all td_ values are in [ns] - long td_visitor = 0; - long td_total = 0; - long count = 0; - - public void print(final PrintStream out) { - out.printf("TypecastFont.process(): count %,3d, total %,5d [ms], per-add %,4.2f [ns]%n", count, TimeUnit.NANOSECONDS.toMillis(td_total), - ((double)td_total/(double)count)); - out.printf(" visitor %,5d [ms], per-add %,4.2f [ns]%n", TimeUnit.NANOSECONDS.toMillis(td_visitor), - ((double)td_visitor/(double)count)); - } - - public void clear() { - t0 = null; - td_visitor = 0; - td_total = 0; - count = 0; - } - } - private Perf perf = null; - - private final PerfCounterCtrl perfCounterCtrl = new PerfCounterCtrl() { - @Override - public void enable(final boolean enable) { - if( enable ) { - if( null != perf ) { - perf.clear(); - } else { - perf = new Perf(); - } - } else { - perf = null; - } - } - - @Override - public void clear() { - if( null != perf ) { - perf.clear(); - } - } - - @Override - public Duration getTotalDuration() { - if( null != perf ) { - return Duration.ofNanos(perf.td_total); - } else { - return Duration.ZERO; - } - } - - @Override - public void print(final PrintStream out) { - if( null != perf ) { - perf.print(out); - } - } }; - @Override - public PerfCounterCtrl perfCounter() { return perfCounterCtrl; } - @Override public AABBox processString(final OutlineShape.Visitor visitor, final AffineTransform transform, final CharSequence string, @@ -436,10 +372,6 @@ class TypecastFont implements Font { if (null == string || 0 == string.length() ) { return new AABBox(); } - if( null != perf ) { - ++perf.count; - perf.t0 = Clock.getMonotonicTime(); - } final AABBox res = new AABBox(); final int charCount = string.length(); @@ -479,26 +411,33 @@ class TypecastFont implements Font { } temp1.translate(advanceTotal, y, temp2); res.resize(temp1.transform(glyphShape.getBounds(), temp_box)); - if( null != perf ) { - final Instant t1 = Clock.getMonotonicTime(); - visitor.visit(glyphShape, temp1); - final Instant t2 = Clock.getMonotonicTime(); - perf.td_visitor += Duration.between(t1, t2).toNanos(); - } else { - visitor.visit(glyphShape, temp1); - } + visitor.visit(glyphShape, temp1); advanceTotal += glyph.getAdvance(); left_glyph = glyph; } } - if( null != perf ) { - final Instant tX = Clock.getMonotonicTime(); - perf.td_total += Duration.between(perf.t0, tX).toNanos(); - } return res; } @Override + public void processString(final OutlineShape.Visitor2 visitor, final CharSequence string) { + if (null == string || 0 == string.length() ) { + return; + } + final int charCount = string.length(); + + for(int i=0; i< charCount; i++) { + final char character = string.charAt(i); + if( '\n' != character ) { + final OutlineShape glyphShape = getGlyph(getGlyphID(character)).getShape(); + if( null != glyphShape ) { // also covers 'space' and all non-contour symbols + visitor.visit(glyphShape); + } + } + } + } + + @Override final public int getNumGlyphs() { return font.getNumGlyphs(); } @@ -517,8 +456,7 @@ class TypecastFont implements Font { public final boolean equals(final Object o) { if( this == o ) { return true; } if( o instanceof TypecastFont ) { - final TypecastFont of = (TypecastFont)o; - return of.font.getName(Font.NAME_UNIQUNAME).equals(font.getName(Font.NAME_UNIQUNAME)); + return ((TypecastFont)o).font.getName(Font.NAME_UNIQUNAME).equals(font.getName(Font.NAME_UNIQUNAME)); } return false; } diff --git a/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java b/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java index 7f8f262e9..61d6d965b 100644 --- a/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java +++ b/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java @@ -30,16 +30,26 @@ package jogamp.opengl; import java.io.PrintStream; import java.util.concurrent.TimeUnit; +import com.jogamp.common.os.Clock; import com.jogamp.opengl.FPSCounter; /** * Default implementation of FPSCounter to be used for FPSCounter implementing renderer. */ public class FPSCounterImpl implements FPSCounter { - private int fpsUpdateFramesInterval; private PrintStream fpsOutputStream ; - private long fpsStartTime, fpsLastUpdateTime, fpsLastPeriod, fpsTotalDuration; + + // counter in [ns] + private long fpsStartTimeNS, fpsLastUpdateTimeNS; + + // counter in [ms] + private long fpsLastPeriodMS, fpsTotalDurationMS; + + // counter in events + private int fpsUpdateFramesInterval; private int fpsTotalFrames; + + // counter in fps private float fpsLast, fpsTotal; /** Creates a disabled instance */ @@ -52,25 +62,24 @@ public class FPSCounterImpl implements FPSCounter { * update interval is reached.<br> * * Shall be called by actual FPSCounter implementing renderer, after display a new frame. - * */ public final synchronized void tickFPS() { fpsTotalFrames++; if(fpsUpdateFramesInterval>0 && fpsTotalFrames%fpsUpdateFramesInterval == 0) { - final long now = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); - fpsLastPeriod = now - fpsLastUpdateTime; - fpsLastPeriod = Math.max(fpsLastPeriod, 1); // div 0 - fpsLast = ( fpsUpdateFramesInterval * 1000f ) / ( fpsLastPeriod ) ; + final long now = Clock.currentNanos(); + fpsLastPeriodMS = TimeUnit.NANOSECONDS.toMillis(now - fpsLastUpdateTimeNS); + fpsLastPeriodMS = Math.max(fpsLastPeriodMS, 1); // div 0 + fpsLast = ( fpsUpdateFramesInterval * 1000f ) / ( fpsLastPeriodMS ) ; - fpsTotalDuration = now - fpsStartTime; - fpsTotalDuration = Math.max(fpsTotalDuration, 1); // div 0 - fpsTotal= ( fpsTotalFrames * 1000f ) / ( fpsTotalDuration ) ; + fpsTotalDurationMS = TimeUnit.NANOSECONDS.toMillis(now - fpsStartTimeNS); + fpsTotalDurationMS = Math.max(fpsTotalDurationMS, 1); // div 0 + fpsTotal= ( fpsTotalFrames * 1000f ) / ( fpsTotalDurationMS ) ; if(null != fpsOutputStream) { fpsOutputStream.println(toString()); } - fpsLastUpdateTime = now; + fpsLastUpdateTimeNS = now; } } @@ -82,8 +91,8 @@ public class FPSCounterImpl implements FPSCounter { fpsLastS = fpsLastS.substring(0, fpsLastS.indexOf('.') + 2); String fpsTotalS = String.valueOf(fpsTotal); fpsTotalS = fpsTotalS.substring(0, fpsTotalS.indexOf('.') + 2); - sb.append(fpsTotalDuration/1000 +" s: "+ fpsUpdateFramesInterval+" f / "+ fpsLastPeriod+" ms, " + fpsLastS+" fps, "+ fpsLastPeriod/fpsUpdateFramesInterval+" ms/f; "+ - "total: "+ fpsTotalFrames+" f, "+ fpsTotalS+ " fps, "+ fpsTotalDuration/fpsTotalFrames+" ms/f"); + sb.append(fpsTotalDurationMS/1000 +" s: "+ fpsUpdateFramesInterval+" f / "+ fpsLastPeriodMS+" ms, " + fpsLastS+" fps, "+ fpsLastPeriodMS/fpsUpdateFramesInterval+" ms/f; "+ + "total: "+ fpsTotalFrames+" f, "+ fpsTotalS+ " fps, "+ fpsTotalDurationMS/fpsTotalFrames+" ms/f"); return sb; } @@ -101,12 +110,12 @@ public class FPSCounterImpl implements FPSCounter { @Override public final synchronized void resetFPSCounter() { - fpsStartTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); // overwrite startTime to real init one - fpsLastUpdateTime = fpsStartTime; - fpsLastPeriod = 0; + fpsStartTimeNS = Clock.currentNanos(); + fpsLastUpdateTimeNS = fpsStartTimeNS; + fpsLastPeriodMS = 0; fpsTotalFrames = 0; fpsLast = 0f; fpsTotal = 0f; - fpsLastPeriod = 0; fpsTotalDuration=0; + fpsLastPeriodMS = 0; fpsTotalDurationMS=0; } @Override @@ -116,17 +125,17 @@ public class FPSCounterImpl implements FPSCounter { @Override public final synchronized long getFPSStartTime() { - return fpsStartTime; + return TimeUnit.NANOSECONDS.toMillis(fpsStartTimeNS); } @Override public final synchronized long getLastFPSUpdateTime() { - return fpsLastUpdateTime; + return TimeUnit.NANOSECONDS.toMillis(fpsLastUpdateTimeNS); } @Override public final synchronized long getLastFPSPeriod() { - return fpsLastPeriod; + return fpsLastPeriodMS; } @Override @@ -141,7 +150,7 @@ public class FPSCounterImpl implements FPSCounter { @Override public final synchronized long getTotalFPSDuration() { - return fpsTotalDuration; + return fpsTotalDurationMS; } @Override diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index d97e0e201..7964416fe 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -50,6 +50,7 @@ import java.util.Map; import java.util.Set; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.os.Clock; import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.os.Platform; import com.jogamp.common.util.Bitfield; @@ -1200,7 +1201,7 @@ public abstract class GLContextImpl extends GLContext { if (DEBUG) { System.err.println(getThreadName() + ": createContextARB-MapGLVersions START (GLDesktop "+hasOpenGLDesktopSupport+", GLES "+hasOpenGLESSupport+", minorVersion "+hasMinorVersionSupport+") on "+device); } - final long t0 = ( DEBUG ) ? System.nanoTime() : 0; + final long t0 = ( DEBUG ) ? Clock.currentNanos() : 0; boolean success = false; // Following GLProfile.GL_PROFILE_LIST_ALL order of profile detection { GL4bc, GL3bc, GL2, GL4, GL3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 } boolean hasGL4bc = false; @@ -1350,7 +1351,7 @@ public abstract class GLContextImpl extends GLContext { GLContext.setAvailableGLVersionsSet(device, true); } if(DEBUG) { - final long t1 = System.nanoTime(); + final long t1 = Clock.currentNanos(); System.err.println(getThreadName() + ": createContextARB-MapGLVersions END (success "+success+") on "+device+", profileAliasing: "+PROFILE_ALIASING+", total "+(t1-t0)/1e6 +"ms"); if( success ) { System.err.println(GLContext.dumpAvailableGLVersions(null).toString()); diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java index 6c497c9e3..558fa88f2 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java @@ -93,7 +93,7 @@ public class GLSLArrayHandler extends GLVBOArrayHandler { if(!ad.isVBOWritten()) { glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); if(null!=buffer) { - glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage()); + glsl.glBufferData(ad.getVBOTarget(), ad.getByteCount(), buffer, ad.getVBOUsage()); } ad.setVBOWritten(true); st.vertexAttribPointer(glsl, ad); @@ -144,7 +144,7 @@ public class GLSLArrayHandler extends GLVBOArrayHandler { if(!ad.isVBOWritten()) { glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); if(null!=buffer) { - glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage()); + glsl.glBufferData(ad.getVBOTarget(), ad.getByteCount(), buffer, ad.getVBOUsage()); } ad.setVBOWritten(true); glsl.glVertexAttribPointer(ad); diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java index 740289fa6..8c74ba090 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java @@ -32,6 +32,7 @@ import jogamp.nativewindow.x11.XVisualInfo; import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.VisualIDHolder; +import com.jogamp.nativewindow.VisualIDHolder.VIDType; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLProfile; @@ -92,6 +93,19 @@ public class X11GLCapabilities extends GLCapabilities { } @Override + final public boolean isVisualIDSupported(final VIDType type) { + switch(type) { + case INTRINSIC: + case NATIVE: + case X11_XVISUAL: + case X11_FBCONFIG: + return true; + default: + return false; + } + } + + @Override public StringBuilder toString(StringBuilder sink) { if(null == sink) { sink = new StringBuilder(); |