diff options
Diffstat (limited to 'src')
53 files changed, 1700 insertions, 815 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java b/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java index 69be7dc88..5c48a5df1 100644 --- a/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java +++ b/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java @@ -101,7 +101,7 @@ public class GearsObjectES2 extends GearsObject { array.bindBuffer(gl, true); final int bufferTarget = array.getVBOTarget(); final int bufferName = array.getVBOName(); - final long bufferSize = array.getSizeInBytes(); + final long bufferSize = array.getByteCount(); final int hasBufferName = gl.getBoundBuffer(bufferTarget); final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName); final boolean ok = bufferName == hasBufferName && 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(); diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/Capabilities.java b/src/nativewindow/classes/com/jogamp/nativewindow/Capabilities.java index fa172b201..ea9ca7fc4 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/Capabilities.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/Capabilities.java @@ -1,6 +1,6 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 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 @@ -121,6 +121,22 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable { return hash; } + private static boolean checkSameSuppSameValue(final VIDType type, final VisualIDHolder a, final VisualIDHolder b) { + final boolean has_a = a.isVisualIDSupported(type); + if( has_a != b.isVisualIDSupported(type) ) { + // both should either support or not support the extra X11_FBCONFIG + return false; + } + return !has_a || a.getVisualID(type) == b.getVisualID(type); + } + private static boolean checkSameValueIfBothSupp(final VIDType type, final VisualIDHolder a, final VisualIDHolder b) { + final boolean has_a = a.isVisualIDSupported(type); + if( has_a && has_a == b.isVisualIDSupported(type) ) { + return a.getVisualID(type) == b.getVisualID(type); + } + return true; + } + @Override public boolean equals(final Object obj) { if(this == obj) { return true; } @@ -128,6 +144,20 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable { return false; } final CapabilitiesImmutable other = (CapabilitiesImmutable)obj; + { + // first check whether the VID is compatible + final int id_t = this.getVisualID(VIDType.NATIVE); + final int id_o = other.getVisualID(VIDType.NATIVE); + if( id_t != id_o ) { + return false; + } + if( !checkSameSuppSameValue(VIDType.X11_FBCONFIG, this, other) ) { + return false; + } + if( !checkSameValueIfBothSupp(VIDType.EGL_CONFIG, this, other) ) { + return false; + } + } boolean res = other.getRedBits()==redBits && other.getGreenBits()==greenBits && other.getBlueBits()==blueBits && @@ -182,6 +212,17 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable { } @Override + public boolean isVisualIDSupported(final VIDType type) { + switch(type) { + case INTRINSIC: + case NATIVE: + return true; + default: + return false; + } + } + + @Override public final int getRedBits() { return redBits; } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesImmutable.java b/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesImmutable.java index 780d537b8..526d184a1 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesImmutable.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesImmutable.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2010-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: @@ -122,11 +122,11 @@ public interface CapabilitiesImmutable extends VisualIDHolder, WriteCloneable, C */ int getTransparentAlphaValue(); - /** Equality over the immutable attributes of both objects */ + /** Equality over the immutable attributes of both objects. */ @Override boolean equals(Object obj); - /** hash code over the immutable attributes of both objects */ + /** Hash code over the immutable attributes. */ @Override int hashCode(); diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsConfiguration.java index d20a6824d..220f0555b 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsConfiguration.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsConfiguration.java @@ -32,6 +32,8 @@ package com.jogamp.nativewindow; +import com.jogamp.nativewindow.VisualIDHolder.VIDType; + import jogamp.nativewindow.Debug; public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphicsConfiguration { @@ -91,6 +93,11 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics return capabilitiesChosen.getVisualID(type); } + @Override + final public boolean isVisualIDSupported(final VIDType type) { + return capabilitiesChosen.isVisualIDSupported(type); + } + /** * Set the capabilities to a new value. * diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/VisualIDHolder.java b/src/nativewindow/classes/com/jogamp/nativewindow/VisualIDHolder.java index 62b73d230..627fc4f3b 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/VisualIDHolder.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/VisualIDHolder.java @@ -1,5 +1,5 @@ /** - * Copyright 2012 JogAmp Community. All rights reserved. + * Copyright 2012-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: @@ -90,6 +90,10 @@ public interface VisualIDHolder { * </ul></li> * </ul> * </p> + * <p> + * One may use {@link #isVisualIDSupported(VIDType)} to test upfront whether a {@link VIDType} is supported, + * e.g. to avoid an exception or query or compare all available. + * </p> * Note: <code>INTRINSIC</code> and <code>NATIVE</code> are always handled, * but may result in {@link #VID_UNDEFINED}. The latter is true if * the native value are actually undefined or the corresponding object is not @@ -98,10 +102,24 @@ public interface VisualIDHolder { * @throws NativeWindowException if <code>type</code> is neither * <code>INTRINSIC</code> nor <code>NATIVE</code> * and does not match the native implementation. + * + * @see #isVisualIDSupported(VIDType) */ int getVisualID(VIDType type) throws NativeWindowException ; /** + * Returns true if the given {@link VIDType} is supported, otherwise false. + * <p> + * Note: <code>INTRINSIC</code> and <code>NATIVE</code> are always handled, + * but may result in {@link #VID_UNDEFINED}. The latter is true if + * the native value are actually undefined or the corresponding object is not + * mapped to a native visual object. + * </p> + * @see #getVisualID(VIDType) + */ + boolean isVisualIDSupported(VIDType type); + + /** * {@link #getVisualID(VIDType)} result indicating an undefined value, * which could be cause by an unsupported query. * <p> diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java index 99cfca97b..71bd033b0 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java @@ -1,5 +1,5 @@ /** - * Copyright 2012 JogAmp Community. All rights reserved. + * Copyright 2012-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: @@ -74,6 +74,19 @@ public class X11Capabilities extends Capabilities { } @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(); diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 6b102ea68..1435aa20a 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -73,6 +73,7 @@ import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; import com.jogamp.common.GlueGenVersion; +import com.jogamp.common.os.Clock; import com.jogamp.common.util.SecurityUtil; import com.jogamp.common.util.VersionUtil; import com.jogamp.common.util.locks.RecursiveLock; @@ -679,7 +680,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind public synchronized void setVisibleActionPost(final boolean visible, final boolean nativeWindowCreated) { long t0; if(Window.DEBUG_IMPLEMENTATION) { - t0 = System.nanoTime(); + t0 = Clock.currentNanos(); System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", start"); } else { t0 = 0; @@ -710,7 +711,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } } if(Window.DEBUG_IMPLEMENTATION) { - System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms"); + System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", fin: dt "+ (Clock.currentNanos()-t0)/1e6 +"ms"); } } diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java index b41c28e27..78df525ee 100644 --- a/src/newt/classes/jogamp/newt/ScreenImpl.java +++ b/src/newt/classes/jogamp/newt/ScreenImpl.java @@ -43,7 +43,7 @@ import com.jogamp.nativewindow.NativeWindowException; import com.jogamp.nativewindow.util.Dimension; import com.jogamp.nativewindow.util.Rectangle; import com.jogamp.nativewindow.util.RectangleImmutable; - +import com.jogamp.common.os.Clock; import com.jogamp.common.util.ArrayHashSet; import com.jogamp.common.util.PropertyAccess; import com.jogamp.newt.Display; @@ -184,7 +184,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { { if(null == aScreen) { if(DEBUG) { - tCreated = System.nanoTime(); + tCreated = Clock.currentNanos(); System.err.println("Screen.createNative() START ("+Display.getThreadName()+", "+this+")"); } else { tCreated = 0; @@ -200,7 +200,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { synchronized(screenList) { screensActive++; if(DEBUG) { - System.err.println("Screen.createNative() END ("+Display.getThreadName()+", "+this+"), active "+screensActive+", total "+ (System.nanoTime()-tCreated)/1e6 +"ms"); + System.err.println("Screen.createNative() END ("+Display.getThreadName()+", "+this+"), active "+screensActive+", total "+ (Clock.currentNanos()-tCreated)/1e6 +"ms"); } } ScreenMonitorState.getScreenMonitorState(this.getFQName()).addListener(this); @@ -554,7 +554,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { private final ScreenMonitorState initMonitorState() { long t0; if(DEBUG) { - t0 = System.nanoTime(); + t0 = Clock.currentNanos(); System.err.println("Screen.initMonitorState() START ("+Display.getThreadName()+", "+this+")"); } else { t0 = 0; @@ -614,7 +614,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { ScreenMonitorState.unlockScreenMonitorState(); } if(DEBUG) { - System.err.println("Screen.initMonitorState() END dt "+ (System.nanoTime()-t0)/1e6 +"ms"); + System.err.println("Screen.initMonitorState() END dt "+ (Clock.currentNanos()-t0)/1e6 +"ms"); } if( !vScrnSizeUpdated ) { updateVirtualScreenOriginAndSize(); diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 45329bed9..c860e4c3e 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -66,6 +66,7 @@ import jogamp.nativewindow.SurfaceScaleUtils; import jogamp.nativewindow.SurfaceUpdatedHelper; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.os.Clock; import com.jogamp.common.util.ArrayHashSet; import com.jogamp.common.util.Bitfield; import com.jogamp.common.util.InterruptSource; @@ -738,7 +739,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private boolean createNative() { long tStart; if(DEBUG_IMPLEMENTATION) { - tStart = System.nanoTime(); + tStart = Clock.currentNanos(); System.err.println("Window.createNative() START ("+getThreadName()+", "+this+")"); } else { tStart = 0; @@ -839,7 +840,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer ((DisplayImpl) screen.getDisplay()).dispatchMessagesNative(); // status up2date } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.createNative() END ("+getThreadName()+", "+this+") total "+ (System.nanoTime()-tStart)/1e6 +"ms"); + System.err.println("Window.createNative() END ("+getThreadName()+", "+this+") total "+ (Clock.currentNanos()-tStart)/1e6 +"ms"); } return isNativeValid() ; } diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java index 7430dcd38..f30cda4f3 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java @@ -27,6 +27,7 @@ import com.jogamp.opengl.GLRunnable; import com.jogamp.opengl.GLUniformData; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.glu.GLU; +import com.jogamp.common.os.Clock; import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; @@ -90,26 +91,29 @@ public class Bug735Inv0AppletAWT extends Applet implements Runnable { private int fcount = 0, lastm = 0; private final int fint = 1; - public void init() { + @Override +public void init() { setSize(APPLET_WIDTH, APPLET_HEIGHT); setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT)); width = APPLET_WIDTH; height = APPLET_HEIGHT; } - public void start() { + @Override +public void start() { thread = new InterruptSource.Thread(null, this, "Animation Thread"); thread.start(); } - public void run() { + @Override +public void run() { int noDelays = 0; // Number of frames with a delay of 0 ms before the // animation thread yields to other running threads. final int NO_DELAYS_PER_YIELD = 15; final int TIMEOUT_SECONDS = 2; - long beforeTime = System.nanoTime(); + long beforeTime = Clock.currentNanos(); long overSleepTime = 0L; millisOffset = System.currentTimeMillis(); @@ -125,13 +129,14 @@ public class Bug735Inv0AppletAWT extends Applet implements Runnable { if (frameCount == 1) { EventQueue.invokeLater(new Runnable() { - public void run() { + @Override + public void run() { requestFocusInWindow(); } }); } - final long afterTime = System.nanoTime(); + final long afterTime = Clock.currentNanos(); final long timeDiff = afterTime - beforeTime; final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; if (sleepTime > 0) { // some time left in this cycle @@ -139,7 +144,7 @@ public class Bug735Inv0AppletAWT extends Applet implements Runnable { Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); noDelays = 0; // Got some sleep, not delaying anymore } catch (final InterruptedException ex) { } - overSleepTime = (System.nanoTime() - afterTime) - sleepTime; + overSleepTime = (Clock.currentNanos() - afterTime) - sleepTime; } else { // sleepTime <= 0; the frame took longer than the period overSleepTime = 0L; noDelays++; @@ -148,7 +153,7 @@ public class Bug735Inv0AppletAWT extends Applet implements Runnable { noDelays = 0; } } - beforeTime = System.nanoTime(); + beforeTime = Clock.currentNanos(); } } @@ -418,7 +423,8 @@ public class Bug735Inv0AppletAWT extends Applet implements Runnable { // This allows to close the frame. frame.addWindowListener(new WindowAdapter() { - public void windowClosing(final WindowEvent e) { + @Override + public void windowClosing(final WindowEvent e) { System.exit(0); } }); diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java index b31a5f410..15826a8c0 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java @@ -27,6 +27,7 @@ import com.jogamp.opengl.GLRunnable; import com.jogamp.opengl.GLUniformData; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.glu.GLU; +import com.jogamp.common.os.Clock; import com.jogamp.common.util.InterruptSource; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; @@ -92,26 +93,29 @@ public class Bug735Inv1AppletAWT extends Applet implements Runnable { private int fcount = 0, lastm = 0; private final int fint = 1; - public void init() { + @Override +public void init() { setSize(APPLET_WIDTH, APPLET_HEIGHT); setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT)); width = APPLET_WIDTH; height = APPLET_HEIGHT; } - public void start() { + @Override +public void start() { thread = new InterruptSource.Thread(null, this, "Animation Thread"); thread.start(); } - public void run() { + @Override +public void run() { int noDelays = 0; // Number of frames with a delay of 0 ms before the // animation thread yields to other running threads. final int NO_DELAYS_PER_YIELD = 15; final int TIMEOUT_SECONDS = 2; - long beforeTime = System.nanoTime(); + long beforeTime = Clock.currentNanos(); long overSleepTime = 0L; millisOffset = System.currentTimeMillis(); @@ -127,13 +131,14 @@ public class Bug735Inv1AppletAWT extends Applet implements Runnable { if (frameCount == 1) { EventQueue.invokeLater(new Runnable() { - public void run() { + @Override + public void run() { requestFocusInWindow(); } }); } - final long afterTime = System.nanoTime(); + final long afterTime = Clock.currentNanos(); final long timeDiff = afterTime - beforeTime; final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; if (sleepTime > 0) { // some time left in this cycle @@ -141,7 +146,7 @@ public class Bug735Inv1AppletAWT extends Applet implements Runnable { Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); noDelays = 0; // Got some sleep, not delaying anymore } catch (final InterruptedException ex) { } - overSleepTime = (System.nanoTime() - afterTime) - sleepTime; + overSleepTime = (Clock.currentNanos() - afterTime) - sleepTime; } else { // sleepTime <= 0; the frame took longer than the period overSleepTime = 0L; noDelays++; @@ -150,7 +155,7 @@ public class Bug735Inv1AppletAWT extends Applet implements Runnable { noDelays = 0; } } - beforeTime = System.nanoTime(); + beforeTime = Clock.currentNanos(); } } @@ -417,7 +422,8 @@ public class Bug735Inv1AppletAWT extends Applet implements Runnable { // This allows to close the frame. frame.addWindowListener(new WindowAdapter() { - public void windowClosing(final WindowEvent e) { + @Override + public void windowClosing(final WindowEvent e) { System.exit(0); } }); diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java index d0e4448cc..31ff4193c 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java @@ -20,6 +20,7 @@ import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.awt.GLCanvas; +import com.jogamp.common.os.Clock; import com.jogamp.common.util.InterruptSource; import com.jogamp.junit.util.JunitTracer; import com.jogamp.newt.awt.NewtCanvasAWT; @@ -73,7 +74,8 @@ public class Bug735Inv2AppletAWT extends Applet implements Runnable { private final long frameRatePeriod = 1000000000L / TARGET_FPS; private int frameCount; - public void init() { + @Override +public void init() { setSize(APPLET_WIDTH, APPLET_HEIGHT); setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT)); width = APPLET_WIDTH; @@ -81,27 +83,30 @@ public class Bug735Inv2AppletAWT extends Applet implements Runnable { initGL(); } - public void start() { + @Override +public void start() { initDraw(); thread = new InterruptSource.Thread(null, this, "Animation Thread"); thread.start(); } - public void run() { + @Override +public void run() { int noDelays = 0; // Number of frames with a delay of 0 ms before the // animation thread yields to other running threads. final int NO_DELAYS_PER_YIELD = 15; final int TIMEOUT_SECONDS = 2; - long beforeTime = System.nanoTime(); + long beforeTime = Clock.currentNanos(); long overSleepTime = 0L; frameCount = 1; while (Thread.currentThread() == thread) { if (frameCount == 1) { EventQueue.invokeLater(new Runnable() { - public void run() { + @Override + public void run() { requestFocusInWindow(); } }); @@ -117,7 +122,7 @@ public class Bug735Inv2AppletAWT extends Applet implements Runnable { e.printStackTrace(); } - final long afterTime = System.nanoTime(); + final long afterTime = Clock.currentNanos(); final long timeDiff = afterTime - beforeTime; final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; if (sleepTime > 0) { // some time left in this cycle @@ -125,7 +130,7 @@ public class Bug735Inv2AppletAWT extends Applet implements Runnable { Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); noDelays = 0; // Got some sleep, not delaying anymore } catch (final InterruptedException ex) { } - overSleepTime = (System.nanoTime() - afterTime) - sleepTime; + overSleepTime = (Clock.currentNanos() - afterTime) - sleepTime; } else { // sleepTime <= 0; the frame took longer than the period overSleepTime = 0L; noDelays++; @@ -134,7 +139,7 @@ public class Bug735Inv2AppletAWT extends Applet implements Runnable { noDelays = 0; } } - beforeTime = System.nanoTime(); + beforeTime = Clock.currentNanos(); } } @@ -262,7 +267,8 @@ public class Bug735Inv2AppletAWT extends Applet implements Runnable { // This allows to close the frame. frame.addWindowListener(new WindowAdapter() { - public void windowClosing(final WindowEvent e) { + @Override + public void windowClosing(final WindowEvent e) { System.exit(0); } }); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/PerfTextRendererNEWT00.java index 84909298d..102a330ab 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/PerfTextRendererNEWT00.java @@ -41,16 +41,12 @@ import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLDrawable; import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.fixedfunc.GLMatrixFunc; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.FixMethodOrder; -import org.junit.runners.MethodSorters; - import com.jogamp.common.os.Clock; import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.VersionUtil; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.GLRegion; @@ -60,11 +56,9 @@ import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.SVertex; import com.jogamp.graph.geom.plane.AffineTransform; -import com.jogamp.junit.util.JunitTracer; import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.NEWTGLContext; -import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.GLReadBufferUtil; import com.jogamp.opengl.util.PMVMatrix; @@ -78,65 +72,54 @@ import com.jogamp.opengl.util.PMVMatrix; * - Using a single GLRegion instantiation * - Single GLRegion is filled once with shapes from text */ -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class TestTextRendererNEWT00 extends UITestCase { - final Instant t0 = Clock.getMonotonicTime(); +public class PerfTextRendererNEWT00 { + static final Instant t0i = Clock.getMonotonicTime(); + static final long t0 = Clock.currentNanos(); static final boolean DEBUG = false; static final boolean TRACE = false; static long duration = 100; // ms static boolean forceES2 = false; static boolean forceGL3 = false; - static boolean mainRun = false; - static boolean useMSAA = true; static int win_width = 1280; static int win_height = 720; static int loop_count = 1; static boolean do_perf = false; + static boolean do_snap = false; + static boolean do_vsync = false; static Font font; - static float fontSize = 24; // in pixel private final float[] fg_color = new float[] { 0, 0, 0, 1 }; - @BeforeClass - public static void setup() throws IOException { - if( null == font ) { + static { + try { font = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSans.ttf", - FontSet01.class.getClassLoader(), FontSet01.class).getInputStream(), true); + FontSet01.class.getClassLoader(), FontSet01.class).getInputStream(), true); // font = FontFactory.get(FontFactory.UBUNTU).get(FontSet.FAMILY_LIGHT, FontSet.STYLE_NONE); + } catch (final IOException e) { + e.printStackTrace(); } } - static int atoi(final String a) { - try { - return Integer.parseInt(a); - } catch (final Exception ex) { throw new RuntimeException(ex); } - } - - public static void main(final String args[]) throws IOException { + public static void main(final String args[]) throws IOException, GLException, InterruptedException { + String text = PerfTextRendererNEWT00.text_1; boolean wait = false; - mainRun = true; for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; - duration = atoi(args[i]); + duration = MiscUtils.atol(args[i], duration); } else if(args[i].equals("-width")) { i++; - win_width = atoi(args[i]); + win_width = MiscUtils.atoi(args[i], win_width); } else if(args[i].equals("-height")) { i++; - win_height = atoi(args[i]); - } else if(args[i].equals("-noMSAA")) { - useMSAA = false; + win_height = MiscUtils.atoi(args[i], win_height); } else if(args[i].equals("-es2")) { forceES2 = true; } else if(args[i].equals("-gl3")) { forceGL3 = true; } else if(args[i].equals("-font")) { i++; - font = FontFactory.get(IOUtil.getResource(args[i], TestTextRendererNEWT00.class.getClassLoader(), TestTextRendererNEWT00.class).getInputStream(), true); - } else if(args[i].equals("-fontSize")) { - i++; - fontSize = MiscUtils.atof(args[i], fontSize); + font = FontFactory.get(IOUtil.getResource(args[i], PerfTextRendererNEWT00.class.getClassLoader(), PerfTextRendererNEWT00.class).getInputStream(), true); } else if(args[i].equals("-wait")) { wait = true; } else if(args[i].equals("-loop")) { @@ -145,16 +128,26 @@ public class TestTextRendererNEWT00 extends UITestCase { if( 0 >= loop_count ) { loop_count = Integer.MAX_VALUE; } + } else if(args[i].equals("-long_text")) { + text = PerfTextRendererNEWT00.text_long; + } else if(args[i].equals("-vsync")) { + do_vsync = true; } else if(args[i].equals("-perf")) { do_perf = true; + } else if(args[i].equals("-snap")) { + do_snap = true; } } - System.err.println("Performance test enabled: "+do_perf); + System.err.println("Excessuive performance test enabled: "+do_perf); + System.err.println("VSync requested: "+do_vsync); if( wait ) { - JunitTracer.waitForKey("Start"); + MiscUtils.waitForKey("Start"); } - final String tstname = TestTextRendererNEWT00.class.getName(); - org.junit.runner.JUnitCore.main(tstname); + final int renderModes = Region.VBAA_RENDERING_BIT /* | Region.COLORCHANNEL_RENDERING_BIT */; + final int sampleCount = 4; + + final PerfTextRendererNEWT00 obj = new PerfTextRendererNEWT00(); + obj.test(renderModes, sampleCount, text); } static void sleep() { @@ -167,17 +160,28 @@ public class TestTextRendererNEWT00 extends UITestCase { static class Perf { // all td_ values are in [ns] public long td_graph = 0; - public long td_txt1 = 0; - public long td_txt2 = 0; public long td_txt = 0; public long td_draw = 0; public long td_txt_draw = 0; public long count = 0; + public Perf() { + final Instant startupMTime = Clock.getMonotonicStartupTime(); + final Instant currentMTime = Clock.getMonotonicTime(); + final Instant wallTime = Clock.getWallClockTime(); + final Duration elapsedSinceStartup = Duration.between(startupMTime, currentMTime); + System.err.printf("Perf: Elapsed since startup: %,d [ms], %,d [ns]%n", elapsedSinceStartup.toMillis(), elapsedSinceStartup.toNanos()); + System.err.printf("- monotonic startup %s, %,d [ms]%n", startupMTime, startupMTime.toEpochMilli()); + System.err.printf("- monotonic current %s, %,d [ms]%n", currentMTime, currentMTime.toEpochMilli()); + System.err.printf("- wall current %s%n", wallTime); + final long td = Clock.currentNanos(); + System.err.printf("- currentNanos: Elapsed %,d [ns]%n", (td-t0)); + System.err.printf(" - test-startup %,13d [ns]%n", t0); + System.err.printf(" - test-current %,13d [ns]%n", td); + } + public void clear() { td_graph = 0; - td_txt1 = 0; - td_txt2 = 0; td_txt = 0; td_draw = 0; td_txt_draw = 0; @@ -185,21 +189,18 @@ public class TestTextRendererNEWT00 extends UITestCase { } public void print(final PrintStream out, final long frame, final String msg) { - out.printf("%3d / %3d: Perf %s: Total: graph %,2d, txt[1 %,2d, 2 %,2d, all %,2d], draw %,2d, txt+draw %,2d [ms]%n", + out.printf("%3d / %3d: Perf %s: Total: graph %,2d, txt %,2d, draw %,2d, txt+draw %,2d [ms]%n", count, frame, msg, - TimeUnit.NANOSECONDS.toMillis(td_graph), TimeUnit.NANOSECONDS.toMillis(td_txt1), - TimeUnit.NANOSECONDS.toMillis(td_txt2), TimeUnit.NANOSECONDS.toMillis(td_txt), + TimeUnit.NANOSECONDS.toMillis(td_graph), + TimeUnit.NANOSECONDS.toMillis(td_txt), TimeUnit.NANOSECONDS.toMillis(td_draw), TimeUnit.NANOSECONDS.toMillis(td_txt_draw)); - out.printf("%3d / %3d: Perf %s: PerLoop: graph %,4d, txt[1 %,4d, 2 %,4d, all %,4d], draw %,4d, txt+draw %,4d [ns]%n", + out.printf("%3d / %3d: Perf %s: PerLoop: graph %,4d, txt %,4d, draw %,4d, txt+draw %,4d [ns]%n", count, frame, msg, - td_graph/count, td_txt1/count, td_txt2/count, td_txt/count, td_draw/count, td_txt_draw/count ); + td_graph/count, td_txt/count, td_draw/count, td_txt_draw/count ); } } - @Test - public void test02TextRendererVBAA04() throws InterruptedException, GLException, IOException { - final int renderModes = Region.VBAA_RENDERING_BIT /* | Region.COLORCHANNEL_RENDERING_BIT */; - final int sampleCount = 4; + public void test(final int renderModes, final int sampleCount, final String text) throws InterruptedException, GLException, IOException { final GLProfile glp; if(forceGL3) { glp = GLProfile.get(GLProfile.GL3); @@ -209,22 +210,34 @@ public class TestTextRendererNEWT00 extends UITestCase { glp = GLProfile.getGL2ES2(); } - final Instant t1 = Clock.getMonotonicTime(); + final Instant t1i = Clock.getMonotonicTime(); + final long t1 = Clock.currentNanos(); final GLCapabilities caps = new GLCapabilities( glp ); caps.setAlphaBits(4); - System.err.println("Requested Caps: "+caps); - System.err.println("Requested Region-RenderModes: "+Region.getRenderModeString(renderModes)); final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(caps, win_width, win_height, false); // true); final GLDrawable drawable = winctx.context.getGLDrawable(); final GL2ES2 gl = winctx.context.getGL().getGL2ES2(); - if( do_perf ) { + if( !do_vsync ) { gl.setSwapInterval(0); } - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + { + final int glerr = gl.glGetError(); + if( GL.GL_NO_ERROR != glerr ) { + System.err.println("Initial GL Error: "+glerr); + } + } + System.err.println(VersionUtil.getPlatformInfo()); + System.err.println(JoglVersion.getAllAvailableCapabilitiesInfo(winctx.window.getScreen().getDisplay().getGraphicsDevice(), null).toString()); + System.err.println(JoglVersion.getGLInfo(gl, null, false /* withCapsAndExts */).toString()); + System.err.println("VSync Swap Interval: "+gl.getSwapInterval()); + System.err.println("GLDrawable surface size: "+winctx.context.getGLDrawable().getSurfaceWidth()+" x "+winctx.context.getGLDrawable().getSurfaceHeight()); - System.err.println("Chosen: "+winctx.window.getChosenCapabilities()); + System.err.println("Requested Caps: "+caps); + System.err.println("Requested Region-RenderModes: "+Region.getRenderModeString(renderModes)); + System.err.println("Chosen Caps: "+winctx.window.getChosenCapabilities()); + System.err.println("Chosen Font: "+font.getFullFamilyName()); final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); @@ -235,32 +248,34 @@ public class TestTextRendererNEWT00 extends UITestCase { // Since we know about the size ... // final GLRegion region = GLRegion.create(gl.getGLProfile(), renderModes, null); // region.growBufferSize(123000, 62000); // hack-me - // FreeSans ~ vertices 64/char, indices 33/char + // FreeSans ~ vertices 68/char, indices 36/char // Ubuntu Light ~ vertices 100/char, indices 50/char // FreeSerif ~ vertices 115/char, indices 61/char - final int vertices_per_char = 64; // 100; - final int indices_per_char = 33; // 50; - final GLRegion region; + // final int vertices_per_char = 68; // 100; + // final int indices_per_char = 36; // 50; + // final GLRegion region = GLRegion.create(gl.getGLProfile(), renderModes, null, text.length()*vertices_per_char, text.length()*indices_per_char); + final GLRegion region = GLRegion.create(gl.getGLProfile(), renderModes, null); + System.err.println("Region post ctor w/ default initial buffer size"); + region.printBufferStats(System.err); + + final int[] verticesIndicesCount = new int[] { 0, 0 }; + TextRegionUtil.countStringRegion(region, font, text, verticesIndicesCount); + System.err.println("Region count: text "+text.length()+" chars -> vertices "+verticesIndicesCount[0]+", indices "+verticesIndicesCount[1]); + region.setBufferCapacity(verticesIndicesCount[0], verticesIndicesCount[1]); + System.err.println("Region post set-buffer-size w/ matching vertices "+verticesIndicesCount[0]+", indices "+verticesIndicesCount[1]); + region.printBufferStats(System.err); + + final Perf perf = new Perf(); if( do_perf ) { - final int char_count = text_1.length()+text_2.length(); // 664 + 670 = 1334 - region = GLRegion.create(gl.getGLProfile(), renderModes, null, char_count*vertices_per_char, char_count*indices_per_char); - } else { - // final int char_count = text_1.length()+text_2.length(); // 664 + 670 = 1334 - region = GLRegion.create(gl.getGLProfile(), renderModes, null); - // region.growBufferSize(char_count*vertices_per_char, char_count*indices_per_char); - } - - final Perf perf; - if( do_perf ) { - perf = new Perf(); region.perfCounter().enable(true); - font.perfCounter().enable(true); - } else { - perf = null; } + final AffineTransform translation = new AffineTransform(); + final AffineTransform tmp1 = new AffineTransform(); + final AffineTransform tmp2 = new AffineTransform(); + for(int loop_i=0; loop_i < loop_count; ++loop_i) { - final Instant t2 = Clock.getMonotonicTime(); // all initialized but graph + final long t2 = Clock.currentNanos(); // all initialized but graph if( null != perf ) { ++perf.count; } @@ -284,105 +299,99 @@ public class TestTextRendererNEWT00 extends UITestCase { gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); region.clear(gl); - final Instant t3 = Clock.getMonotonicTime(); // all initialized w/ graph + final long t3 = Clock.currentNanos(); // all initialized w/ graph - final float dx = 0; - final float dy = drawable.getSurfaceHeight() - 3 * fontSize * font.getLineHeight(); - final Instant t4, t5; + final long t4; + final float fontScale; { // all sizes in em final float x_width = font.getAdvanceWidth( font.getGlyphID('X') ); - final AffineTransform t = new AffineTransform(); - t.setToTranslation(3*x_width, 0f); - final AABBox tbox_1 = font.getGlyphBounds(text_1); - final AABBox rbox_1 = TextRegionUtil.addStringToRegion(region, font, t, text_1, fg_color); - t4 = Clock.getMonotonicTime(); // text_1 added to region + translation.setToTranslation(2*x_width, 0f); + final AABBox tbox_1 = font.getGlyphBounds(text, tmp1, tmp2); + final AABBox rbox_1 = TextRegionUtil.addStringToRegion(region, font, translation, text, fg_color, tmp1, tmp2); + t4 = Clock.currentNanos(); // text added to region + // int dw = drawable.getSurfaceWidth() - + fontScale = drawable.getSurfaceWidth() / ( rbox_1.getWidth() + 4*x_width ); // 2l + 2r if( 0 == loop_i && !do_perf ) { System.err.println("Text_1: tbox "+tbox_1); System.err.println("Text_1: rbox "+rbox_1); - } - - if( true || !do_perf ) { - t.setToTranslation(3*x_width, -1f*(rbox_1.getHeight()+font.getLineHeight())); - final AABBox tbox_2 = font.getGlyphBounds(text_2); - final AABBox rbox_2 = TextRegionUtil.addStringToRegion(region, font, t, text_2, fg_color); - t5 = Clock.getMonotonicTime(); // text_2 added to region - if( 0 == loop_i && !do_perf ) { - System.err.println("Text_1: tbox "+tbox_2); - System.err.println("Text_1: rbox "+rbox_2); - } - } else { - t5 = t4; + System.err.println("Font scale: "+fontScale); } } + final float dx = 0; + final float dy = drawable.getSurfaceHeight() - 2 * fontScale * font.getLineHeight(); final PMVMatrix pmv = renderer.getMatrix(); pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmv.glLoadIdentity(); pmv.glTranslatef(dx, dy, z0); - pmv.glScalef(fontSize, fontSize, 1f); + pmv.glScalef(fontScale, fontScale, 1f); region.draw(gl, renderer, sampleCountIO); - final Instant t6 = Clock.getMonotonicTime(); // text_1 added to region + final long t5 = Clock.currentNanos(); // text added to region if( null != perf ) { - final long td_graph = Duration.between(t2, t3).toNanos(); - final long td_txt1 = Duration.between(t3, t4).toNanos(); - final long td_txt2 = Duration.between(t4, t5).toNanos(); - final long td_txt = Duration.between(t3, t5).toNanos(); - final long td_draw = Duration.between(t5, t6).toNanos(); - final long td_txt_draw = Duration.between(t3, t6).toNanos(); + final long td_graph = t3 - t2; + final long td_txt = t4 - t3; + final long td_draw = t5 - t4; + final long td_txt_draw = t5 - t3; perf.td_graph += td_graph; - perf.td_txt1 += td_txt1; - perf.td_txt2 += td_txt2; perf.td_txt += td_txt; perf.td_draw += td_draw; perf.td_txt_draw += td_txt_draw; if( 0 == loop_i ) { - final long td_launch0 = Duration.between(t0, t1).toMillis(); // raw - final long td_launch1 = Duration.between(t0, t2).toMillis(); // gl - final long td_launch2 = Duration.between(t0, t3).toMillis(); // w/ graph - final long td_launch_txt = Duration.between(t0, t5).toMillis(); - final long td_launch_draw = Duration.between(t0, t6).toMillis(); - System.err.printf("%3d: Perf Launch: raw %,4d, gl %,4d, graph %,4d, txt %,4d, draw %,4d [ms]%n", - loop_i+1, td_launch0, td_launch1, td_launch2, td_launch_txt, td_launch_draw); - perf.print(System.err, loop_i+1, "Launch"); - } else { - System.err.printf("%3d: Perf: graph %2d, txt[1 %2d, 2 %2d, all %2d], draw %2d, txt+draw %2d [ms]%n", + final Duration td_launch0a = Duration.between(Clock.getMonotonicStartupTime(), t0i); // loading Gluegen - load test + final Duration td_launch0b = Duration.between(Clock.getMonotonicStartupTime(), t1i); // loading Gluegen - start test + final long td_launch1 = t1 - t0; // since loading this test + final long td_launch2 = t2 - t0; // gl + final long td_launch3 = t3 - t0; // w/ graph + final long td_launch_txt = t4 - t0; + final long td_launch_draw = t5 - t0; + System.err.printf("%n%n%3d: Perf Launch:%n"+ + "- loading GlueGen - loading test %,6d [ms]%n"+ + "- loading GlueGen - start test %,6d [ms]%n"+ + "- loading test - start test %,6d [ms]%n"+ + "- loading test - gl %,6d [ms]%n"+ + "- loading test - graph %,6d [ms]%n"+ + "- loading test - txt %,6d [ms]%n"+ + "- loading test - draw %,6d [ms]%n", loop_i+1, - TimeUnit.NANOSECONDS.toMillis(td_graph), TimeUnit.NANOSECONDS.toMillis(td_txt1), - TimeUnit.NANOSECONDS.toMillis(td_txt2), TimeUnit.NANOSECONDS.toMillis(td_txt), - TimeUnit.NANOSECONDS.toMillis(td_draw), TimeUnit.NANOSECONDS.toMillis(td_txt_draw) ); + td_launch0a.toMillis(), td_launch0b.toMillis(), + TimeUnit.NANOSECONDS.toMillis(td_launch1), TimeUnit.NANOSECONDS.toMillis(td_launch2), + TimeUnit.NANOSECONDS.toMillis(td_launch3), TimeUnit.NANOSECONDS.toMillis(td_launch_txt), + TimeUnit.NANOSECONDS.toMillis(td_launch_draw)); + perf.print(System.err, loop_i+1, "Launch"); } } - if( loop_count - 1 == loop_i && !do_perf ) { + if( loop_count - 1 == loop_i && do_snap ) { // print screen at end gl.glFinish(); printScreen(screenshot, renderModes, drawable, gl, false, sampleCount); } drawable.swapBuffers(); - if( null != perf && loop_count/3-1 == loop_i ) { + if( null != perf && loop_count/2-1 == loop_i ) { // print + reset counter @ 1/3 loops - region.perfCounter().print(System.err); - font.perfCounter().print(System.err); - perf.print(System.err, loop_i+1, "Frame"+(loop_count/3)); + if( do_perf ) { + region.perfCounter().print(System.err); + } + perf.print(System.err, loop_i+1, "Frame"+(loop_i+1)); perf.clear(); - region.perfCounter().clear(); - font.perfCounter().clear(); + if( do_perf ) { + region.perfCounter().clear(); + } } if( 0 == loop_i || loop_count - 1 == loop_i) { // print counter @ start and end System.err.println("GLRegion: for "+gl.getGLProfile()+" using int32_t indiced: "+region.usesI32Idx()); System.err.println("GLRegion: "+region); - System.err.println("Text length: text_1 "+text_1.length()+", text_2 "+text_2.length()+", total "+(text_1.length()+text_2.length())); + System.err.println("Text length: "+text.length()); region.printBufferStats(System.err); - region.perfCounter().print(System.err); - font.perfCounter().print(System.err); + if( do_perf ) { + region.perfCounter().print(System.err); + } + perf.print(System.err, loop_i+1, "Frame"+(loop_i+1)); } // region.destroy(gl); } - if( null != perf ) { - perf.print(System.err, loop_count, "FrameXX"); - } region.destroy(gl); @@ -394,20 +403,22 @@ public class TestTextRendererNEWT00 extends UITestCase { NEWTGLContext.destroyWindow(winctx); } - public static final String text_1a = - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus. \n"+ + public static final String text_long = + "JOGL: Java™ Binding for OpenGL®, providing hardware-accelerated 3D graphics.\n\n"+ + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus.\n"+ + "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies\n"+ + "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices ultricies nec a elit.\n"+ + "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia pharetra at venenatis est.\n"+ + "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat nec, volutpat nec nisi.\n"+ + "Donec ut dolor et nulla tristique varius. In nulla magna, fermentum id tempus quis, semper\n"+ + "Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem,\n" + + "I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*.\n"+ + "Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven.\n"+ + "Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte is in Yale.\n"+ + "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway…\n"+ + "Von-Vincke-Straße in Münster, Vdovino in Russia, Ytterbium in the periodic table.\n"+ + "Miłosz and Wū Wŭ all in the library? 1510–1620, 11:00 pm, and the 1980s are over.\n"+ "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+ - "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices ultricies nec a elit. \n"+ - "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia pharetra at venenatis est. \n"+ - "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat nec, volutpat nec nisi. \n"+ - "Donec ut dolor et nulla tristique varius. In nulla magna, fermentum id tempus quis, semper \n"+ - "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem, \n" + - "I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*. X\n"+ - "Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail. X\n"+ - "Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale. X\n"+ - "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.… X\n"+ - "Von-Vincke-Straße in Münster, Vdovino in Russia, Ytterbium in the periodic table. Are Toussaint L’Ouverture, Wölfflin, Wolfe, X\n"+ - "Miłosz and Wū Wŭ all in the library? 1510–1620, 11:00 pm, and the 1980s are over. X\n"+ "-------Press H to change text---------"; public static final String text_1b = @@ -426,7 +437,7 @@ public class TestTextRendererNEWT00 extends UITestCase { // ^ // | - public static final String text_1s = "Hello World. Gustav got news."; + public static final String text_1s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus."; public static final String text_1 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus. \n"+ "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+ @@ -437,15 +448,6 @@ public class TestTextRendererNEWT00 extends UITestCase { "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem, \n" + "-------Press H to change text---------"; - public static final String text_2s = "JogAmp reborn ;-)"; - public static final String text_2 = - "I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*. X\n"+ - "Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail. X\n"+ - "Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale. X\n"+ - "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.… X\n"+ - "Von-Vincke-Straße in Münster, Vdovino in Russia, Ytterbium in the periodic table. Are Toussaint L’Ouverture, Wölfflin, Wolfe, X\n"+ - "Miłosz and Wū Wŭ all in the library? 1510–1620, 11:00 pm, and the 1980s are over. X\n"+ - "-------Press H to change text---------"; public static void printScreen(final GLReadBufferUtil screenshot, final int renderModes, final GLDrawable drawable, final GL gl, final boolean exportAlpha, final int sampleCount) throws GLException, IOException { final int screenshot_num = 0; @@ -453,9 +455,9 @@ public class TestTextRendererNEWT00 extends UITestCase { final String objName = "TestTextRendererNEWT00-snap"+screenshot_num; // screenshot_num++; final String modeS = Region.getRenderModeString(renderModes); - final String bname = String.format((Locale)null, "%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName, + final String bname = String.format((Locale)null, "%s-msaa%02d-%03dx%03d-%s%04d", objName, drawable.getChosenGLCapabilities().getNumSamples(), - fontSize, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, sampleCount); + drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, sampleCount); final String filename = dir + bname +".png"; if(screenshot.readPixels(gl, false)) { screenshot.write(new File(filename)); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT20.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT20.java index a044ce9d5..624b1ff94 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT20.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT20.java @@ -36,6 +36,7 @@ import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLCapabilitiesImmutable; import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.JoglVersion; import jogamp.common.os.PlatformPropsImpl; @@ -45,6 +46,7 @@ import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; import com.jogamp.common.os.Platform; +import com.jogamp.common.util.VersionUtil; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.font.Font; @@ -52,7 +54,9 @@ import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.SVertex; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.graph.demos.GPUTextRendererListenerBase01; +import com.jogamp.opengl.test.junit.graph.demos.MSAATool; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.caps.NonFSAAGLCapsChooser; /** @@ -109,6 +113,11 @@ public class TestTextRendererNEWT20 extends UITestCase { Assert.assertNotNull(caps); final GLWindow window = GLWindow.create(caps); + if( !caps.getSampleBuffers() ) { + // Make sure to not have FSAA if not requested + // TODO: Implement in default chooser? + window.setCapabilitiesChooser(new NonFSAAGLCapsChooser(true)); + } window.setSize(width, height); window.setPosition(10, 10); window.setTitle(title); @@ -119,7 +128,7 @@ public class TestTextRendererNEWT20 extends UITestCase { } @Test - public void testTextRendererR2T01() throws InterruptedException, GLException, IOException { + public void test00TextRendererVBAA01() throws InterruptedException, GLException, IOException { if(Platform.CPUFamily.X86 != PlatformPropsImpl.CPU_ARCH.family) { // FIXME // FIXME: Disabled for now - since it doesn't seem fit for mobile (performance wise). System.err.println("disabled on non desktop (x86) arch for now .."); @@ -131,8 +140,10 @@ public class TestTextRendererNEWT20 extends UITestCase { caps.setAlphaBits(4); System.err.println("Requested: "+caps); - final GLWindow window = createWindow("text-vbaa1-msaa0", caps, win_width, win_height); + final GLWindow window = createWindow("TTRN20", caps, win_width, win_height); window.display(); + System.err.println(VersionUtil.getPlatformInfo()); + // System.err.println(JoglVersion.getAllAvailableCapabilitiesInfo(window.getScreen().getDisplay().getGraphicsDevice(), null).toString()); System.err.println("Chosen: "+window.getChosenGLCapabilities()); final RenderState rs = RenderState.createRenderState(SVertex.factory()); @@ -147,20 +158,60 @@ public class TestTextRendererNEWT20 extends UITestCase { final Runnable action_per_font = new Runnable() { @Override public void run() { - if( false ) { - textGLListener.setHeadBox(1, false); - textGLListener.setSampleCount(2); - window.display(); - textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false); - sleep(); - - textGLListener.setHeadBox(2, false); - textGLListener.setSampleCount(2); - window.display(); - textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false); - sleep(); - } + textGLListener.setHeadBox(1, false); + textGLListener.setSampleCount(4); + window.display(); + textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false); + sleep(); + + textGLListener.setHeadBox(2, false); + textGLListener.setSampleCount(4); + window.display(); + textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false); + sleep(); + } }; + final Font[] fonts = FontSet01.getSet01(); + for(final Font f : fonts) { + if( textGLListener.setFont(f) ) { + action_per_font.run(); + } + } + if(textGLListener.setFontSet(FontFactory.JAVA, 0, 0)) { + action_per_font.run(); + } + destroyWindow(window); + } + + @Test + public void test10TextRendererMSAA01() throws InterruptedException, GLException, IOException { + if(Platform.CPUFamily.X86 != PlatformPropsImpl.CPU_ARCH.family) { // FIXME + // FIXME: Disabled for now - since it doesn't seem fit for mobile (performance wise). + System.err.println("disabled on non desktop (x86) arch for now .."); + return; + } + final GLProfile glp = GLProfile.getGL2ES2(); + + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + System.err.println("Requested: "+caps); + + final GLWindow window = createWindow("TTRN20", caps, win_width, win_height); + window.display(); + System.err.println("Chosen: "+window.getChosenGLCapabilities()); + + final RenderState rs = RenderState.createRenderState(SVertex.factory()); + final TextGLListener textGLListener = new TextGLListener(glp, rs, Region.MSAA_RENDERING_BIT, 4 /* sampleCount */, DEBUG, TRACE); + textGLListener.attachInputListenerTo(window); + window.addGLEventListener(textGLListener); + textGLListener.setHeadBox(2, true); + window.display(); + // final AABBox headbox = textGLListener.getHeadBox(); + // GPUTextRendererListenerBase01.upsizeWindowSurface(window, false, (int)(headbox.getWidth()*1.5f), (int)(headbox.getHeight()*2f)); + + final Runnable action_per_font = new Runnable() { + @Override + public void run() { textGLListener.setHeadBox(1, false); textGLListener.setSampleCount(4); window.display(); @@ -187,7 +238,7 @@ public class TestTextRendererNEWT20 extends UITestCase { } @Test - public void testTextRendererMSAA01() throws InterruptedException, GLException, IOException { + public void test20TextRendererFSAA01() throws InterruptedException, GLException, IOException { final GLProfile glp = GLProfile.get(GLProfile.GL2ES2); final GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(4); @@ -195,7 +246,7 @@ public class TestTextRendererNEWT20 extends UITestCase { caps.setNumSamples(4); System.err.println("Requested: "+caps); - final GLWindow window = createWindow("text-vbaa0-msaa1", caps, 1024, 640); + final GLWindow window = createWindow("TTRN20", caps, 1024, 640); window.display(); System.err.println("Chosen: "+window.getChosenGLCapabilities()); @@ -236,13 +287,13 @@ public class TestTextRendererNEWT20 extends UITestCase { } @Test - public void testTextRendererNoSampling() throws InterruptedException, GLException, IOException { + public void test30TextRendererNoSampling() throws InterruptedException, GLException, IOException { final GLProfile glp = GLProfile.get(GLProfile.GL2ES2); final GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(4); System.err.println("Requested: "+caps); - final GLWindow window = createWindow("text-vbaa0-msaa0", caps, 1024, 640); + final GLWindow window = createWindow("TTRN20", caps, 1024, 640); window.display(); System.err.println("Chosen: "+window.getChosenGLCapabilities()); @@ -303,6 +354,8 @@ public class TestTextRendererNEWT20 extends UITestCase { final GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.setSwapInterval(1); gl.glEnable(GL.GL_DEPTH_TEST); + System.err.println(JoglVersion.getGLInfo(gl, null, false /* withCapsAndExts */).toString()); + MSAATool.dump(drawable); final RenderState rs = getRenderer().getRenderState(); rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java index f307a1196..21aee7c40 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java @@ -43,6 +43,7 @@ import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.font.FontScale; import com.jogamp.graph.font.FontSet; import com.jogamp.graph.geom.SVertex; +import com.jogamp.graph.geom.plane.AffineTransform; import com.jogamp.newt.Window; import com.jogamp.opengl.util.PMVMatrix; @@ -59,6 +60,9 @@ public abstract class TextRendererGLELBase implements GLEventListener { protected RegionRenderer renderer = null; protected TextRegionUtil textRenderUtil = null; + protected final AffineTransform tempT1 = new AffineTransform(); + protected final AffineTransform tempT2 = new AffineTransform(); + /** scale pixel, default is 1f */ protected float pixelScale = 1.0f; @@ -272,9 +276,9 @@ public abstract class TextRendererGLELBase implements GLEventListener { if( cacheRegion ) { textRenderUtil.drawString3D(gl, renderer, font, text, null, vbaaSampleCount); } else if( null != region ) { - TextRegionUtil.drawString3D(gl, region, renderer, font, text, null, vbaaSampleCount); + TextRegionUtil.drawString3D(gl, region, renderer, font, text, null, vbaaSampleCount, tempT1, tempT1); } else { - TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, null, vbaaSampleCount); + TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, null, vbaaSampleCount, tempT1, tempT1); } renderer.enable(gl, false); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java index 47205a14a..6131ca6fd 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -242,7 +242,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { } public void printScreen(final GLAutoDrawable drawable, final String dir, final String tech, final String objName, final boolean exportAlpha) throws GLException, IOException { - final String sw = String.format("-%s-S%02d-Z%04d-snap%02d-%03dx%03d", objName, sampleCount[0], (int)Math.abs(zTran), screenshot_num++, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); + final String sw = String.format("_s%02d-%s-Z%04d-snap%02d-%03dx%03d", sampleCount[0], objName, (int)Math.abs(zTran), screenshot_num++, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); final String filename = dir + tech + sw +".png"; if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java index 8fa3744fd..d18766ee1 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java @@ -46,6 +46,7 @@ import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.font.FontScale; import com.jogamp.graph.font.FontSet; +import com.jogamp.graph.geom.plane.AffineTransform; import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; @@ -90,8 +91,12 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB String headtext; AABBox headbox; + protected final AffineTransform tempT1 = new AffineTransform(); + protected final AffineTransform tempT2 = new AffineTransform(); + static final String text2 = "The quick brown fox jumps over the lazy dog"; public static final String text_help = + "JOGL: Java™ Binding for OpenGL®, providing hardware-accelerated 3D graphics.\n\n"+ "JOGAMP graph demo using Resolution Independent NURBS\n"+ "JOGAMP JOGL - OpenGL ES2 profile\n"+ "Press 1/2 to zoom in/out the below text\n"+ @@ -104,6 +109,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB "Press f to toggle fps. H for different text, space for font type\n"; public static final String textX1 = + "JOGL: Java™ Binding for OpenGL®, providing hardware-accelerated 3D graphics.\n\n"+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus. \n"+ "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+ "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices ultricies nec a elit. \n"+ @@ -114,11 +120,11 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB "-------Press H to change text---------"; public static final String textX2 = - "I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*. X\n"+ - "Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail. X\n"+ - "Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale. X\n"+ - "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.… X\n"+ - "Von-Vincke-Straße in Münster, Vdovino in Russia, Ytterbium in the periodic table. Are Toussaint L’Ouverture, Wölfflin, Wolfe, X\n"+ + "I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*.\n"+ + "Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail.\n"+ + "Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale.\n"+ + "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.…\n"+ + "Von-Vincke-Straße in Münster, Vdovino in Russia, Ytterbium in the periodic table. Are Toussaint L’Ouverture, Wölfflin, Wolfe,\n"+ "Miłosz and Wū Wŭ all in the library? 1510–1620, 11:00 pm, and the 1980s are over. X\n"+ "-------Press H to change text---------"; @@ -234,15 +240,15 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB } else { System.err.println("Using vertical default DPI of "+dpiV+", "+ppmmV+" pixel/mm"); } - fontNameBox = font.getGlyphBounds(fontName); + fontNameBox = font.getGlyphBounds(fontName, tempT1, tempT2); setHeadBox(headType, true); { final float pixelSizeFName = FontScale.toPixels(fontSizeFName, dpiV); System.err.println("XXX: fontName size "+fontSizeFName+"pt, dpiV "+dpiV+" -> "+pixelSizeFName+"px"); System.err.println("XXX: fontName boxM fu "+font.getMetricBoundsFU(fontName)); - System.err.println("XXX: fontName boxG fu "+font.getGlyphBoundsFU(fontName)); + System.err.println("XXX: fontName boxG fu "+font.getGlyphBoundsFU(fontName, tempT1, tempT2)); System.err.println("XXX: fontName boxM em "+font.getMetricBounds(fontName)); - System.err.println("XXX: fontName boxG em "+font.getGlyphBounds(fontName)); + System.err.println("XXX: fontName boxG em "+font.getGlyphBounds(fontName, tempT1, tempT2)); System.err.println("XXX: fontName box height px "+(fontNameBox.getHeight() * pixelSizeFName)); } } @@ -339,7 +345,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB pmv.glScalef(sxy, sxy, 1.0f); } // No cache, keep region alive! - TextRegionUtil.drawString3D(gl, regionFPS.clear(gl), renderer, font, text, null, sampleCountFPS); + TextRegionUtil.drawString3D(gl, regionFPS.clear(gl), renderer, font, text, null, sampleCountFPS, tempT1, tempT2); pmv.glPopMatrix(); } @@ -393,13 +399,13 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB } if(!userInput) { if( bottomTextUseFrustum ) { - TextRegionUtil.drawString3D(gl, regionBottom.clear(gl), renderer, font, text2, null, getSampleCount()); + TextRegionUtil.drawString3D(gl, regionBottom.clear(gl), renderer, font, text2, null, getSampleCount(), tempT1, tempT2); } else { textRegionUtil.drawString3D(gl, renderer, font, text2, null, getSampleCount()); } } else { if( bottomTextUseFrustum ) { - TextRegionUtil.drawString3D(gl, regionBottom.clear(gl), renderer, font, userString.toString(), null, getSampleCount()); + TextRegionUtil.drawString3D(gl, regionBottom.clear(gl), renderer, font, userString.toString(), null, getSampleCount(), tempT1, tempT2); } else { textRegionUtil.drawString3D(gl, renderer, font, userString.toString(), null, getSampleCount()); } @@ -515,7 +521,9 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB @Override public void printScreen(final GLAutoDrawable drawable, final String dir, final String tech, final String objName, final boolean exportAlpha) throws GLException, IOException { final String fn = font.getFullFamilyName().replace(' ', '_').replace('-', '_'); - super.printScreen(drawable, dir, tech+"-"+fn, "text"+getHeadBoxType()+"-"+objName, exportAlpha); + final String modes = Region.getRenderModeString(getRenderModes()); + final String fsaa = "fsaa"+drawable.getChosenGLCapabilities().getNumSamples(); + super.printScreen(drawable, dir, tech+"-"+modes, fsaa+"-"+fn+"-text"+getHeadBoxType()+"-"+objName, exportAlpha); } float fontHeadScale = 1f; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java index e8c21efbe..c1ef5f7fd 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java @@ -15,7 +15,7 @@ import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLPipelineFactory; import com.jogamp.opengl.GLRunnable; - +import com.jogamp.opengl.JoglVersion; import com.jogamp.common.net.Uri; import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.InterruptSource; @@ -114,7 +114,8 @@ public class GPUUISceneGLListener0A implements GLEventListener { private final String jogamp = "JogAmp - Jogl Graph Module Demo"; private final String truePtSize = fontSizePt+" pt font size label - true scale!"; - private final String longText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec \n"+ + private final String longText = "JOGL: Java™ Binding for the OpenGL® API.\n\n"+ + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec \n"+ "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel\n"+ "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices\n"+ "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia\n"+ @@ -178,6 +179,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { throw new RuntimeException(ioe); } sceneUIController = new SceneUIController(sceneDist, zNear, zFar); + // sceneUIController.setSampleCount(3); // easy on embedded devices w/ just 3 samples (default is 4)? screenshot = new GLReadBufferUtil(false, false); } @@ -784,7 +786,6 @@ public class GPUUISceneGLListener0A implements GLEventListener { } else { System.err.println("GPUUISceneGLListener0A: init (0)"); } - System.err.println("Chosen: "+drawable.getChosenGLCapabilities()); cDrawable = drawable; GL2ES2 gl = drawable.getGL().getGL2ES2(); if(debug) { @@ -793,6 +794,10 @@ public class GPUUISceneGLListener0A implements GLEventListener { if(trace) { gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); } + System.err.println(JoglVersion.getGLInfo(gl, null, false /* withCapsAndExts */).toString()); + System.err.println("VSync Swap Interval: "+gl.getSwapInterval()); + System.err.println("Chosen: "+drawable.getChosenGLCapabilities()); + MSAATool.dump(drawable); renderer = RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable); rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED); @@ -925,7 +930,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { if( null != animator ) { lfps = animator.getLastFPS(); tfps = animator.getTotalFPS(); - td = animator.getTotalFPSDuration()/1000f; + td = (float)animator.getLastFPSPeriod() / (float)animator.getUpdateFPSFrames(); } else { lfps = 0f; tfps = 0f; @@ -934,16 +939,18 @@ public class GPUUISceneGLListener0A implements GLEventListener { final String modeS = Region.getRenderModeString(renderModes); final String text; if( null == actionText ) { - text = String.format("%03.1f/%03.1f fps, v-sync %d, dpi %.1f, %s-samples %d, q %d, td %.0f, blend %b, alpha %d, msaa %d", - lfps, tfps, gl.getSwapInterval(), dpiH, modeS, sceneUIController.getSampleCount(), fpsLabel.getQuality(), td, + text = String.format("%03.1f/%03.1f fps, %.1f ms/f, v-sync %d, dpi %.1f, %s-samples %d, q %d, msaa %d, blend %b, alpha %d", + lfps, tfps, td, gl.getSwapInterval(), dpiH, modeS, sceneUIController.getSampleCount(), fpsLabel.getQuality(), + drawable.getChosenGLCapabilities().getNumSamples(), renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED), - drawable.getChosenGLCapabilities().getAlphaBits(), - drawable.getChosenGLCapabilities().getNumSamples()); + drawable.getChosenGLCapabilities().getAlphaBits()); } else { text = String.format("%03.1f/%03.1f fps, v-sync %d, %s", lfps, tfps, gl.getSwapInterval(), actionText); } - fpsLabel.setText(text); + if( fpsLabel.setText(text) ) { // marks dirty only if text differs. + System.err.println(text); + } } sceneUIController.display(drawable); } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java index 1e9ae7a45..e1868a74e 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java @@ -3,18 +3,29 @@ package com.jogamp.opengl.test.junit.graph.demos; import com.jogamp.nativewindow.ScalableSurface; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLProfile; - +import com.jogamp.opengl.JoglVersion; +import com.jogamp.common.util.VersionUtil; import com.jogamp.graph.curve.Region; +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.caps.NonFSAAGLCapsChooser; public class GPUUISceneNewtDemo { static final boolean DEBUG = false; static final boolean TRACE = false; + static void sleep(final long ms) { + try { + Thread.sleep(ms); + } catch (final InterruptedException ie) {} + } + public static void main(final String[] args) { int SceneMSAASamples = 0; boolean GraphVBAAMode = false; @@ -96,6 +107,11 @@ public class GPUUISceneNewtDemo { System.err.println("Graph VBAA Mode "+GraphVBAAMode); System.err.println("Graph Auto Mode "+GraphAutoMode+" no-AA dpi threshold"); + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + System.err.println(VersionUtil.getPlatformInfo()); + System.err.println(JoglVersion.getAllAvailableCapabilitiesInfo(dpy.getGraphicsDevice(), null).toString()); + final GLProfile glp; if(forceGLDef) { glp = GLProfile.getDefault(); @@ -126,21 +142,24 @@ public class GPUUISceneNewtDemo { rmode = 0; } - final GLWindow window = GLWindow.create(caps); + final GLWindow window = GLWindow.create(screen, caps); + if( 0 == SceneMSAASamples ) { + window.setCapabilitiesChooser(new NonFSAAGLCapsChooser(true)); + } window.setPosition(x, y); window.setSize(width, height); window.setTitle("GraphUI Newt Demo: graph["+Region.getRenderModeString(rmode)+"], msaa "+SceneMSAASamples); window.setSurfaceScale(reqSurfacePixelScale); - final float[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new float[2]); + // final float[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new float[2]); - final GPUUISceneGLListener0A sceneGLListener = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(fontfilename, GraphAutoMode, DEBUG, TRACE) : - new GPUUISceneGLListener0A(fontfilename, rmode, DEBUG, TRACE); + final GPUUISceneGLListener0A scene = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(fontfilename, GraphAutoMode, DEBUG, TRACE) : + new GPUUISceneGLListener0A(fontfilename, rmode, DEBUG, TRACE); - window.addGLEventListener(sceneGLListener); - sceneGLListener.attachInputListenerTo(window); + window.addGLEventListener(scene); + scene.attachInputListenerTo(window); final Animator animator = new Animator(); - animator.setUpdateFPSFrames(60, null); + animator.setUpdateFPSFrames(5*60, null); animator.add(window); window.addWindowListener(new WindowAdapter() { @@ -152,5 +171,9 @@ public class GPUUISceneNewtDemo { window.setVisible(true); animator.start(); + + // sleep(3000); + // final UIShape movie = scene.getWidget(GPUUISceneGLListener0A.BUTTON_MOVIE); } + } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/UIShapeDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/UIShapeDemo01.java index d09f00000..63c147cdd 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/UIShapeDemo01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/UIShapeDemo01.java @@ -56,6 +56,7 @@ import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.font.FontSet; import com.jogamp.graph.geom.SVertex; +import com.jogamp.graph.geom.plane.AffineTransform; import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; @@ -167,6 +168,9 @@ public class UIShapeDemo01 implements GLEventListener { boolean ignoreInput = false; + protected final AffineTransform tempT1 = new AffineTransform(); + protected final AffineTransform tempT2 = new AffineTransform(); + public UIShapeDemo01(final Font font, final int renderModes, final RenderState rs, final boolean debug, final boolean trace) { this.font = font; this.renderModes = renderModes; @@ -275,13 +279,13 @@ public class UIShapeDemo01 implements GLEventListener { } full_width_o = objCoord1[0] - objCoord0[0]; } - final AABBox txt_box_em = font.getGlyphBounds(text); + final AABBox txt_box_em = font.getGlyphBounds(text, tempT1, tempT2); final float full_width_s = full_width_o / txt_box_em.getWidth(); final float txt_scale = full_width_s/2f; pmv.glPushMatrix(); pmv.glScalef(txt_scale, txt_scale, 1f); pmv.glTranslatef(-txt_box_em.getWidth(), 0f, 0f); - final AABBox txt_box_r = TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, new float[] { 0, 0, 0, 1 }, sampleCount); + final AABBox txt_box_r = TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, new float[] { 0, 0, 0, 1 }, sampleCount, tempT1, tempT2); if( once ) { final AABBox txt_box_em2 = font.getGlyphShapeBounds(null, text); System.err.println("XXX: full_width: "+full_width_o+" / "+txt_box_em.getWidth()+" -> "+full_width_s); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/UITypeDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/UITypeDemo01.java index 5c638f953..44e014bd8 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/UITypeDemo01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/UITypeDemo01.java @@ -62,6 +62,7 @@ import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.font.FontSet; import com.jogamp.graph.font.Font.Glyph; import com.jogamp.graph.geom.SVertex; +import com.jogamp.graph.geom.plane.AffineTransform; import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; @@ -185,6 +186,9 @@ public class UITypeDemo01 implements GLEventListener { boolean ignoreInput = false; + protected final AffineTransform tempT1 = new AffineTransform(); + protected final AffineTransform tempT2 = new AffineTransform(); + @SuppressWarnings("unused") public UITypeDemo01(final Font font, final int glyph_id, final String text, final int renderModes, final RenderState rs, final boolean debug, final boolean trace) { this.font = font; @@ -341,13 +345,13 @@ public class UITypeDemo01 implements GLEventListener { System.err.println("XXX: txt_box_e2 "+txt_box_em2); } } else if( Glyph.ID_UNKNOWN == glyph_id ) { - final AABBox txt_box_em = font.getGlyphBounds(text); + final AABBox txt_box_em = font.getGlyphBounds(text, tempT1, tempT2); final float full_width_s = full_width_o / txt_box_em.getWidth(); final float full_height_s = full_height_o / txt_box_em.getHeight(); final float txt_scale = full_width_s < full_height_s ? full_width_s/2f : full_height_s/2f; pmv.glScalef(txt_scale, txt_scale, 1f); pmv.glTranslatef(-txt_box_em.getWidth(), 0f, 0f); - final AABBox txt_box_r = TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, fg_color, sampleCount); + final AABBox txt_box_r = TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, fg_color, sampleCount, tempT1, tempT2); if( once ) { final AABBox txt_box_em2 = font.getGlyphShapeBounds(null, text); System.err.println("XXX: full_width: "+full_width_o+" / "+txt_box_em.getWidth()+" -> "+full_width_s); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java index d85475451..d64b9a731 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java @@ -52,18 +52,36 @@ public class Label extends UIShape { return text; } - public void setText(final String text) { - this.text = text; - markShapeDirty(); + /** + * Returns true if text has been updated, false if unchanged. + * @param text the text to be set. + */ + public boolean setText(final String text) { + if( !this.text.equals(text) ) { + this.text = text; + markShapeDirty(); + return true; + } else { + return false; + } } public Font getFont() { return font; } - public void setFont(final Font font) { - this.font = font; - markShapeDirty(); + /** + * Returns true if font has been updated, false if unchanged. + * @param font the font to be set. + */ + public boolean setFont(final Font font) { + if( !this.font.equals(font) ) { + this.font = font; + markShapeDirty(); + return true; + } else { + return false; + } } public float getPixelSize() { @@ -97,9 +115,8 @@ public class Label extends UIShape { @Override protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) { - final AffineTransform t_sxy = new AffineTransform(); - t_sxy.setToScale(pixelSize, pixelSize); - final AABBox fbox = font.processString(shapeVisitor, t_sxy, text); + tempT1.setToScale(pixelSize, pixelSize); + final AABBox fbox = font.processString(shapeVisitor, tempT1, text, tempT2, tempT3); final float[] ctr = box.getCenter(); setRotationOrigin( ctr[0], ctr[1], ctr[2]); box.resize(fbox); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java index 5cf0f9af5..7d8f34261 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java @@ -65,10 +65,12 @@ public class Label0 { this.font = font; } - public final AABBox addShapeToRegion(final float scale, final Region region, final AffineTransform tLeft) { - final AffineTransform t_sxy = new AffineTransform(tLeft); - t_sxy.scale(scale, scale, new AffineTransform()); - return TextRegionUtil.addStringToRegion(region, font, t_sxy, text, rgbaColor); + public final AABBox addShapeToRegion(final float scale, final Region region, final AffineTransform tLeft, + final AffineTransform tmp1, final AffineTransform tmp2, final AffineTransform tmp3) + { + tmp1.setTransform(tLeft); + tmp1.scale(scale, scale, tmp2); + return TextRegionUtil.addStringToRegion(region, font, tmp1, text, rgbaColor, tmp2, tmp3); } @Override diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java index 4ea341fba..8a357c8a6 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java @@ -95,7 +95,7 @@ public class LabelButton extends RoundButton { // Precompute text-box size .. guessing pixelSize final float lw = width * ( 1f - spacingX ) ; final float lh = height * ( 1f - spacingY ) ; - final AABBox lbox0_em = label.font.getGlyphBounds(label.text); + final AABBox lbox0_em = label.font.getGlyphBounds(label.text, tempT1, tempT2); final float lsx = lw / lbox0_em.getWidth(); final float lsy = lh / lbox0_em.getHeight(); final float lScale = lsx < lsy ? lsx : lsy; @@ -117,7 +117,7 @@ public class LabelButton extends RoundButton { System.err.printf ("RIButton: tleft %f / %f, %f / %f%n", ltx[0], ltx[1], ltx[0] * lScale, ltx[1] * lScale); } - final AABBox lbox2 = label.addShapeToRegion(lScale, region, tempT1.setToTranslation(ltx[0], ltx[1])); + final AABBox lbox2 = label.addShapeToRegion(lScale, region, tempT1.setToTranslation(ltx[0], ltx[1]), tempT2, tempT3, tempT4); if( DRAW_DEBUG_BOX ) { System.err.printf("RIButton.X: lbox2 %s%n", lbox2); } @@ -165,9 +165,11 @@ public class LabelButton extends RoundButton { } public final void setLabelText(final Font labelFont, final String labelText) { - label.setFont(labelFont); - label.setText(labelText); - markShapeDirty(); + if( !label.getText().equals(labelText) || !label.getFont().equals(labelFont) ) { + label.setFont(labelFont); + label.setText(labelText); + markShapeDirty(); + } } @Override diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RoundButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RoundButton.java index 7e096f46c..1f238763d 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RoundButton.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RoundButton.java @@ -41,8 +41,6 @@ public abstract class RoundButton extends UIShape { protected float width; protected float height; protected float corner = DEFAULT_CORNER; - protected final AffineTransform tempT1 = new AffineTransform(); - protected final AffineTransform tempT2 = new AffineTransform(); protected RoundButton(final Factory<? extends Vertex> factory, final int renderModes, final float width, final float height) { super(factory, renderModes); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java index 22eeec50f..62e6e0753 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java @@ -39,6 +39,7 @@ import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Vertex.Factory; +import com.jogamp.graph.geom.plane.AffineTransform; import com.jogamp.newt.event.GestureHandler.GestureEvent; import com.jogamp.newt.event.GestureHandler.GestureListener; import com.jogamp.newt.event.MouseAdapter; @@ -61,6 +62,11 @@ public abstract class UIShape { private final int renderModes; protected final AABBox box; + protected final AffineTransform tempT1 = new AffineTransform(); + protected final AffineTransform tempT2 = new AffineTransform(); + protected final AffineTransform tempT3 = new AffineTransform(); + protected final AffineTransform tempT4 = new AffineTransform(); + protected final float[] translate = new float[] { 0f, 0f, 0f }; protected final Quaternion rotation = new Quaternion(); protected final float[] rotOrigin = new float[] { 0f, 0f, 0f }; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java index 58a7a72c1..35970bc1e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java @@ -55,6 +55,7 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +import com.jogamp.common.os.Clock; import com.jogamp.common.os.Platform; import com.jogamp.common.util.VersionNumber; import com.jogamp.common.util.awt.AWTEDTExecutor; @@ -216,12 +217,14 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { } // All AWT Mods on AWT-EDT, especially due to the follow-up complicated code! AWTEDTExecutor.singleton.invoke(true, new Runnable() { + @Override public void run() { frame.setTitle("MiniPApplet"); } } ); if (fullScreen) { try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { frame.setUndecorated(true); frame.setBackground(Color.GRAY); @@ -235,6 +238,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { } try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { frame.setLayout(null); frame.add(applet); @@ -273,7 +277,8 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { frame.add(this); frame.addWindowListener(new WindowAdapter() { - public void windowClosing(final WindowEvent e) { + @Override + public void windowClosing(final WindowEvent e) { try { dispose(); } catch (final Exception ex) { @@ -283,6 +288,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { }); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { frame.setVisible(true); } } ); @@ -301,6 +307,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { canvas.setBounds(0, 0, width, height); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { MiniPApplet.this.setLayout(new BorderLayout()); MiniPApplet.this.add(canvas, BorderLayout.CENTER); @@ -339,6 +346,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { // Setting up animation again javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { MiniPApplet.this.setLayout(new BorderLayout()); MiniPApplet.this.add(canvas, BorderLayout.CENTER); @@ -378,6 +386,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { frame = null; } else { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { MiniPApplet.this.remove(canvas); frame.remove(MiniPApplet.this); @@ -391,6 +400,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { void draw(final GL2 gl) { if( !osxCALayerAWTModBug || !justInitialized ) { AWTEDTExecutor.singleton.invoke(true, new Runnable() { + @Override public void run() { frame.setTitle("frame " + frameCount); } } ); @@ -409,7 +419,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { System.out.println(OPENGL_EXTENSIONS); final int[] temp = { 0 }; - gl.glGetIntegerv(GL2ES3.GL_MAX_SAMPLES, temp, 0); + gl.glGetIntegerv(GL.GL_MAX_SAMPLES, temp, 0); System.out.println("Maximum number of samples supported by the hardware: " + temp[0]); System.out.println("Frame: "+frame); System.out.println("Applet: "+MiniPApplet.this); @@ -475,7 +485,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { } void clock() { - final long afterTime = System.nanoTime(); + final long afterTime = Clock.currentNanos(); final long timeDiff = afterTime - beforeTime; final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; @@ -484,13 +494,13 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); } catch (final InterruptedException ex) { } - overSleepTime = (System.nanoTime() - afterTime) - sleepTime; + overSleepTime = (Clock.currentNanos() - afterTime) - sleepTime; } else { // sleepTime <= 0; the frame took longer than the period overSleepTime = 0L; } - beforeTime = System.nanoTime(); + beforeTime = Clock.currentNanos(); } class SimpleListener implements GLEventListener { @@ -512,31 +522,36 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int w, final int h) { } } - public void mouseDragged(final MouseEvent ev) { + @Override + public void mouseDragged(final MouseEvent ev) { if (printEventInfo) { System.err.println("Mouse dragged event: " + ev); } } - public void mouseMoved(final MouseEvent ev) { + @Override + public void mouseMoved(final MouseEvent ev) { if (printEventInfo) { System.err.println("Mouse moved event: " + ev); } } - public void keyPressed(final KeyEvent ev) { + @Override + public void keyPressed(final KeyEvent ev) { if (printEventInfo) { System.err.println("Key pressed event: " + ev); } } - public void keyReleased(final KeyEvent ev) { + @Override + public void keyReleased(final KeyEvent ev) { if (printEventInfo) { System.err.println("Key released event: " + ev); } } - public void keyTyped(final KeyEvent ev) { + @Override + public void keyTyped(final KeyEvent ev) { if (printEventInfo) { System.err.println("Key typed event: " + ev); } @@ -550,7 +565,8 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { private TimerTask task = null; private volatile boolean shouldRun; - protected String getBaseName(final String prefix) { + @Override + protected String getBaseName(final String prefix) { return "Custom" + prefix + "Animator" ; } @@ -566,11 +582,13 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { shouldRun = true; } - public final synchronized boolean isStarted() { + @Override + public final synchronized boolean isStarted() { return (timer != null); } - public final synchronized boolean isAnimating() { + @Override + public final synchronized boolean isAnimating() { return (timer != null) && (task != null); } @@ -581,7 +599,8 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { task = new TimerTask() { private boolean firstRun = true; - public void run() { + @Override + public void run() { if (firstRun) { Thread.currentThread().setName("OPENGL"); firstRun = false; @@ -604,7 +623,8 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { timer.schedule(task, 0, 1); } - public synchronized boolean start() { + @Override + public synchronized boolean start() { if (timer != null) { return false; } @@ -614,7 +634,8 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { } /** Stops this CustomAnimator. */ - public synchronized boolean stop() { + @Override + public synchronized boolean stop() { if (timer == null) { return false; } @@ -634,9 +655,12 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { return true; } - public final synchronized boolean isPaused() { return false; } - public synchronized boolean resume() { return false; } - public synchronized boolean pause() { return false; } + @Override + public final synchronized boolean isPaused() { return false; } + @Override + public synchronized boolean resume() { return false; } + @Override + public synchronized boolean pause() { return false; } } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestIdentOfCapabilitiesNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestIdentOfCapabilitiesNEWT.java new file mode 100644 index 000000000..4de270ce7 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestIdentOfCapabilitiesNEWT.java @@ -0,0 +1,109 @@ +/** + * 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.test.junit.jogl.caps; + +import com.jogamp.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.GLDrawableFactory; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.JoglVersion; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.junit.util.SingletonJunitCase; +import com.jogamp.nativewindow.AbstractGraphicsDevice; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestIdentOfCapabilitiesNEWT extends SingletonJunitCase { + + public static void main(final String[] args) { + final String tstname = TestIdentOfCapabilitiesNEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + @Test + public void test01DesktopCapsEquals() throws InterruptedException { + final GLDrawableFactory factory = GLDrawableFactory.getFactory(false); + if( null == factory ) { + System.err.println("No desktop factory available, bailing out"); + return; + } + testEquals(factory); + } + @Test + public void test02EGLCapsEquals() throws InterruptedException { + final GLDrawableFactory factory = GLDrawableFactory.getFactory(true); + if( null == factory ) { + System.err.println("No EGL factory available, bailing out"); + return; + } + testEquals(factory); + } + + private static List<GLCapabilitiesImmutable> getEquals(final GLCapabilitiesImmutable caps, final List<GLCapabilitiesImmutable> availCaps) { + final List<GLCapabilitiesImmutable> res = new ArrayList<GLCapabilitiesImmutable>(); + for(final GLCapabilitiesImmutable c : availCaps) { + if( c.equals(caps) ) { + res.add(c); + } + } + return res; + } + + private void testEquals(final GLDrawableFactory factory) { + final AbstractGraphicsDevice device = factory.getDefaultDevice(); + Assert.assertNotNull(device); + // System.err.println(JoglVersion.getDefaultOpenGLInfo(device, null, true).toString()); + + try { + final List<GLCapabilitiesImmutable> availCaps = factory.getAvailableCapabilities(device); + if( null != availCaps ) { + for(int i=0; i < availCaps.size(); i++) { + final GLCapabilitiesImmutable one = availCaps.get(i); + final List<GLCapabilitiesImmutable> res = getEquals(one, availCaps); + if( 1 != res.size() ) { + // oops + System.err.println("Error: "+one+" matches more than one in list, not unique:"); + res.forEach(System.err::println); + } + Assert.assertEquals(1, res.size()); + System.err.printf("#%3d/%d: %s%n", (i+1), availCaps.size(), one); + } + } + } catch (final GLException gle) { /* n/a */ } + } + + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java index ccd3a1ef0..882cb2c5f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java @@ -68,7 +68,7 @@ public class GearsObjectES1 extends GearsObject { if( validateBuffers ) { final int bufferTarget = array.getVBOTarget(); final int bufferName = array.getVBOName(); - final long bufferSize = array.getSizeInBytes(); + final long bufferSize = array.getByteCount(); final int hasBufferName = gl.getBoundBuffer(bufferTarget); final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName); final boolean ok = bufferName == hasBufferName && diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java index 1956e6fb7..88e51db8b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java @@ -43,6 +43,7 @@ import com.jogamp.opengl.GLUniformData; import com.jogamp.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.common.nio.Buffers; +import com.jogamp.common.os.Clock; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; @@ -158,6 +159,7 @@ public class ElektronenMultiplizierer implements GLEventListener { public boolean usesFullScreenMode() { return mUsesFullScreenMode; } class TimeShiftKeys extends KeyAdapter { + @Override public void keyPressed(final KeyEvent e) { if(KeyEvent.VK_RIGHT == e.getKeyCode()) { skipFrames(120); @@ -223,6 +225,7 @@ public class ElektronenMultiplizierer implements GLEventListener { return mCaps; } + @Override public void init(final GLAutoDrawable drawable) { if(drawable instanceof GLWindow) { final GLWindow glw = (GLWindow) drawable; @@ -308,16 +311,17 @@ public class ElektronenMultiplizierer implements GLEventListener { // if NO music is used sync to mainloop start ... // (add up current time due to possible turned back start time by skip frames) - mFrameSkipAverageFramerateTimeStart += System.nanoTime(); + mFrameSkipAverageFramerateTimeStart += Clock.currentNanos(); // mBaseMusic = new BaseMusic(BaseGlobalEnvironment.getInstance().getMusicFileName()); // mBaseMusic.init(); // mBaseMusic.play(); } + @Override public void display(final GLAutoDrawable drawable) { if (wantsFrameSkip()) { - mFrameSkipAverageFramerateTimeEnd = System.nanoTime(); + mFrameSkipAverageFramerateTimeEnd = Clock.currentNanos(); final double tDesiredFrameRate = getDesiredFramerate(); final double tSingleFrameTime = 1000000000.0f/tDesiredFrameRate; final double tElapsedTime = mFrameSkipAverageFramerateTimeEnd - mFrameSkipAverageFramerateTimeStart; @@ -342,7 +346,7 @@ public class ElektronenMultiplizierer implements GLEventListener { // //if music IS used sync to first second of music ... // if (BaseRoutineRuntime.getInstance().getBaseMusic().getPositionInMilliseconds()>0 && !mMusicSyncStartTimeInitialized) { // BaseLogging.getInstance().info("Synching to BaseMusic ..."); -// mFrameSkipAverageFramerateTimeStart = (long)(System.nanoTime()-((double)BaseRoutineRuntime.getInstance().getBaseMusic().getPositionInMilliseconds()*1000000.0d)); +// mFrameSkipAverageFramerateTimeStart = (long)(Clock.currentNanos()-((double)BaseRoutineRuntime.getInstance().getBaseMusic().getPositionInMilliseconds()*1000000.0d)); // mMusicSyncStartTimeInitialized = true; // } // } @@ -470,6 +474,7 @@ public class ElektronenMultiplizierer implements GLEventListener { mFrameCounter++; } + @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -493,6 +498,7 @@ public class ElektronenMultiplizierer implements GLEventListener { gl.glViewport(0, 0, width, height); } + @Override public void dispose(final GLAutoDrawable drawable) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.glDeleteFramebuffers(1, new int[] { mFrameBufferObjectID }, 0); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java index 763dbd1ba..a74b6e6f1 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java @@ -100,7 +100,7 @@ public class GearsObjectES2 extends GearsObject { array.bindBuffer(gl, true); final int bufferTarget = array.getVBOTarget(); final int bufferName = array.getVBOName(); - final long bufferSize = array.getSizeInBytes(); + final long bufferSize = array.getByteCount(); final int hasBufferName = gl.getBoundBuffer(bufferTarget); final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName); final boolean ok = bufferName == hasBufferName && diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java index 696c02490..6a7479993 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java @@ -57,7 +57,7 @@ public class GLSLMiscHelper { gl.glGetVertexAttribiv(data.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0); Assert.assertEquals(data.getVBOName(), qi[0]); final GLBufferStorage glStore = gl.getBufferStorage(data.getVBOName()); - Assert.assertEquals("GLBufferStorage size mismatch, storage "+glStore, data.getSizeInBytes(), null != glStore ? glStore.getSize() : -1); + Assert.assertEquals("GLBufferStorage size mismatch, storage "+glStore, data.getByteCount(), null != glStore ? glStore.getSize() : -1); } public static void pause(final long ms) throws InterruptedException { diff --git a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java index bf656bb4d..7f35d7a86 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java +++ b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java @@ -97,6 +97,14 @@ public class MiscUtils { return "0x" + Long.toHexString( hex ); } + public static void waitForKey(final String preMessage) { + final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println(preMessage+"> Press enter to continue"); + try { + System.err.println(stdin.readLine()); + } catch (final IOException e) { e.printStackTrace(); } + } + public static void assertFloatBufferEquals(final String errmsg, final FloatBuffer expected, final FloatBuffer actual, final float delta) { if(null == expected && null == actual) { return; diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java index 5dcfb2f98..364602216 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java @@ -36,6 +36,7 @@ import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLContext; import com.jogamp.opengl.GLDrawable; import com.jogamp.opengl.GLDrawableFactory; +import com.jogamp.opengl.util.caps.NonFSAAGLCapsChooser; import org.junit.Assert; @@ -66,6 +67,12 @@ public class NEWTGLContext { final Window window = NewtFactory.createWindow(screen, caps); Assert.assertNotNull(window); window.setSize(width, height); + if( !caps.getSampleBuffers() ) { + // Make sure to not have FSAA if not requested + // TODO: Implement in default chooser? + window.setCapabilitiesChooser(new NonFSAAGLCapsChooser(true)); + } + window.setVisible(true); Assert.assertTrue(NewtTestUtil.waitForVisible(window, true, null)); Assert.assertTrue(NewtTestUtil.waitForRealized(window, true, null)); |