summaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt')
-rw-r--r--src/newt/classes/com/jogamp/newt/Display.java119
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java4
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java156
-rw-r--r--src/newt/classes/jogamp/newt/PointerIconImpl.java63
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java8
-rw-r--r--src/newt/classes/jogamp/newt/driver/PNGIcon.java35
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java58
-rw-r--r--src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java92
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java50
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java38
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java20
-rw-r--r--src/newt/native/MacWindow.m32
-rw-r--r--src/newt/native/WindowsWindow.c16
-rw-r--r--src/newt/native/X11Display.c15
-rw-r--r--src/newt/native/X11Window.c20
15 files changed, 481 insertions, 245 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 8d1445f80..4b38fcca5 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -30,14 +30,14 @@ package com.jogamp.newt;
import java.io.IOException;
import java.lang.ref.WeakReference;
-import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.nativewindow.util.PointImmutable;
import jogamp.newt.Debug;
@@ -47,6 +47,7 @@ import com.jogamp.newt.util.EDTUtil;
public abstract class Display {
public static final boolean DEBUG = Debug.debug("Display");
+ protected static final boolean DEBUG_POINTER_ICON = Debug.debug("Display.PointerIcon");
/** return precomputed hashCode from FQN {@link #getFQName()} */
@Override
@@ -66,7 +67,9 @@ public abstract class Display {
/**
* Native PointerIcon handle.
* <p>
- * Instances can be created via {@link Display}'s {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) createPointerIcon(..)}.
+ * Instances can be created via {@link Display}'s
+ * {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) createPointerIcon(pngResource, ..)}
+ * or {@link Display#createPointerIcon(PixelRectangle, int, int) createPointerIcon(pixelrect, ..)}.
* </p>
* <p>
* Instance is {@link #destroy()}'ed automatically if it's {@link #getDisplay() associated Display} is destroyed.
@@ -75,23 +78,65 @@ public abstract class Display {
* Instance can be re-validated after destruction via {@link #validate()}.
* </p>
* <p>
+ * {@link PointerIcon} must not be {@link #destroy() destroyed} while in use!
+ * </p>
+ * <p>
* {@link PointerIcon} may be {@link #destroy() destroyed} manually after use,
* i.e. when no {@link Window} {@link Window#setPointerIcon(PointerIcon) uses them} anymore.
+ * However, this is not required.
* </p>
* <p>
* PointerIcons can be used via {@link Window#setPointerIcon(PointerIcon)}.
* </p>
*/
- public static interface PointerIcon {
+ public static interface PointerIcon extends PixelRectangle {
/**
- * @return the associated Display
+ * Always neatly packed, i.e. width * bytes_per_pixel.
+ * <p>
+ * {@inheritDoc}
+ * </p>
*/
- Display getDisplay();
+ @Override
+ int getStride();
+
+ /**
+ * Always false, i.e. origin is TOP-LEFT.
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ boolean isGLOriented();
+
+ /**
+ * Computes a hash code over:
+ * <ul>
+ * <li>display</li>
+ * <li>pixelformat</li>
+ * <li>size</li>
+ * <li>stride</li>
+ * <li>isGLOriented</li>
+ * <li>pixels</li>
+ * <li>hotspot</li>
+ * </ul>
+ * Dismissing the native handle!
+ * <p>
+ * The hashCode shall be computed only once with first call
+ * and stored for later retrieval to enhance performance.
+ * </p>
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ @Override
+ int hashCode();
/**
- * @return the single {@link IOUtil.ClassResources}.
+ * @return the associated Display
*/
- IOUtil.ClassResources getResource();
+ Display getDisplay();
+
+ /** Returns the hotspot. */
+ PointImmutable getHotspot();
/**
* Returns true if valid, otherwise false.
@@ -116,35 +161,69 @@ public abstract class Display {
* </p>
*/
void destroy();
+ }
- /** Returns the size, i.e. width and height. */
- DimensionImmutable getSize();
+ /**
+ * Returns the native platform's {@link PointerIcon.PixelFormat} for pointer-icon pixel data.
+ * <p>
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ * </p>
+ */
+ public abstract PixelFormat getNativePointerIconPixelFormat();
- /** Returns the hotspot. */
- PointImmutable getHotspot();
+ /**
+ * Returns the native platform's direct NIO buffer requirement pointer-icon pixel data.
+ * <p>
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ * </p>
+ */
+ public abstract boolean getNativePointerIconForceDirectNIO();
- @Override
- String toString();
- }
+ /**
+ * Returns the newly created {@link PointerIcon} or <code>null</code> if not implemented on platform.
+ * <p>
+ * See {@link PointerIcon} for lifecycle semantics.
+ * </p>
+ *
+ * @param pngResource single PNG resource for the {@link PointerIcon}. Only the first entry of {@link IOUtil.ClassResources#resourcePaths} is used.
+ * @param hotX pointer hotspot x-coord, origin is upper-left corner
+ * @param hotY pointer hotspot y-coord, origin is upper-left corner
+ *
+ * @throws IllegalArgumentException if pngResource is null or invalid
+ * @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}.
+ * @throws IOException if the <code>pngResource</code> could not be {@link IOUtil.ClassResources#resolve(int) resolved}
+ * or via the PNG parser processing the input stream.
+ *
+ * @see PointerIcon
+ * @see Window#setPointerIcon(PointerIcon)
+ */
+ public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException, IOException;
/**
* Returns the newly created {@link PointerIcon} or <code>null</code> if not implemented on platform.
* <p>
* See {@link PointerIcon} for lifecycle semantics.
* </p>
+ * <p>
+ * In case {@link #getNativePointerIconPixelFormat()} or {@link #getNativePointerIconForceDirectNIO()}
+ * is not matched by the given <code>pixelrect</code>, the <code>pixelrect</code> is converted
+ * into the required {@link PixelFormat} and NIO type.
+ * </p>
*
- * @param pngResource single PNG resource, only the first entry of {@link IOUtil.ClassResources#resourcePaths} is used.
+ * @param pixelrect {@link PixelRectangle} source for the {@link PointerIcon}
* @param hotX pointer hotspot x-coord, origin is upper-left corner
* @param hotY pointer hotspot y-coord, origin is upper-left corner
+ *
+ * @throws IllegalArgumentException if pixelrect is null.
* @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}.
- * @throws MalformedURLException
- * @throws InterruptedException
- * @throws IOException
*
* @see PointerIcon
* @see Window#setPointerIcon(PointerIcon)
+ * @see #getNativePointerIconPixelFormat()
+ * @see #getNativePointerIconForceDirectNIO()
*/
- public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws IllegalStateException, MalformedURLException, InterruptedException, IOException;
+ public abstract PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY) throws IllegalArgumentException, IllegalStateException;
/**
* Manual trigger the native creation, if it is not done yet.<br>
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
index 7ffbc2e83..472672fd9 100644
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
@@ -235,10 +235,10 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
glWindow.setVisible(true);
glWindow.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
if( null == pointerIconTest ) {
- final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/jogamp-32x32.png" } );
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/crosshair-lumina-trans-32x32.png" } );
final Display disp = glWindow.getScreen().getDisplay();
try {
- pointerIconTest = disp.createPointerIcon(res, 16, 0);
+ pointerIconTest = disp.createPointerIcon(res, 16, 16);
} catch (Exception e) {
e.printStackTrace();
}
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index 346c03b15..4c7169ec4 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -34,7 +34,9 @@
package jogamp.newt;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.newt.Display;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.event.NEWTEvent;
@@ -43,17 +45,25 @@ import com.jogamp.newt.event.NEWTEventConsumer;
import jogamp.newt.event.NEWTEventTask;
import com.jogamp.newt.util.EDTUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
import java.io.IOException;
-import java.net.MalformedURLException;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.util.PixelFormatUtil;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
public abstract class DisplayImpl extends Display {
private static int serialno = 1;
+ private static final boolean pngUtilAvail;
static {
NativeWindowFactory.addCustomShutdownHook(true /* head */, new Runnable() {
@@ -64,8 +74,14 @@ public abstract class DisplayImpl extends Display {
DisplayImpl.shutdownAll();
}
});
+
+ final ClassLoader cl = DisplayImpl.class.getClassLoader();
+ pngUtilAvail = ReflectionUtil.isClassAvailable("jogamp.opengl.util.pngj.PngReader", cl) &&
+ ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.PNGPixelRect", cl);
}
+ public static final boolean isPNGUtilAvailable() { return pngUtilAvail; }
+
final ArrayList<PointerIconImpl> pointerIconList = new ArrayList<PointerIconImpl>();
/** Executed from EDT! */
@@ -86,13 +102,94 @@ public abstract class DisplayImpl extends Display {
}
@Override
- public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- return createPointerIcon(false /* isTemp */, pngResource, hotX, hotY);
+ public PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.BGRA8888; }
+ @Override
+ public boolean getNativePointerIconForceDirectNIO() { return false; }
+
+ @Override
+ public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException, IOException
+ {
+ if( !isNativeValid() ) {
+ throw new IllegalStateException("Display.createPointerIcon(1): Display invalid "+this);
+ }
+ if( null == pngResource || 0 >= pngResource.resourceCount() ) {
+ throw new IllegalArgumentException("Null or invalid pngResource "+pngResource);
+ }
+ if( !pngUtilAvail ) {
+ return null;
+ }
+ final PointerIconImpl[] res = { null };
+ runOnEDTIfAvail(true, new Runnable() {
+ public void run() {
+ try {
+ if( !DisplayImpl.this.isNativeValid() ) {
+ throw new IllegalStateException("Display.createPointerIcon(2): Display invalid "+DisplayImpl.this);
+ }
+ final URLConnection urlConn = pngResource.resolve(0);
+ if( null == urlConn ) {
+ throw new IOException("Could not resolve "+pngResource.resourcePaths[0]);
+ }
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(),
+ getNativePointerIconPixelFormat(),
+ getNativePointerIconForceDirectNIO(),
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ final long handle = createPointerIconImplChecked(image.getPixelformat(), image.getSize().getWidth(), image.getSize().getHeight(),
+ image.getPixels(), hotX, hotY);
+ final PointImmutable hotspot = new Point(hotX, hotY);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconPNG.0: "+image+", handle: "+toHexString(handle)+", hot "+hotspot);
+ }
+ if( 0 != handle ) {
+ res[0] = new PointerIconImpl(DisplayImpl.this, image, hotspot, handle);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconPNG.0: "+res[0]);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } } );
+ if( null != res[0] ) {
+ synchronized(pointerIconList) {
+ pointerIconList.add(res[0]);
+ }
+ }
+ return res[0];
}
- PointerIcon createPointerIcon(final boolean isTemp, final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
+
+ @Override
+ public final PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException
+ {
if( !isNativeValid() ) {
throw new IllegalStateException("Display.createPointerIcon(1): Display invalid "+this);
}
+ if( null == pixelrect ) {
+ throw new IllegalArgumentException("Null or pixelrect");
+ }
+ final PixelRectangle fpixelrect;
+ if( getNativePointerIconPixelFormat() != pixelrect.getPixelformat() || pixelrect.isGLOriented() ) {
+ // conversion !
+ fpixelrect = PixelFormatUtil.convert32(pixelrect, getNativePointerIconPixelFormat(),
+ 0 /* ddestStride */, false /* isGLOriented */, getNativePointerIconForceDirectNIO() );
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: Conversion-FMT "+pixelrect+" -> "+fpixelrect);
+ }
+ } else if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixelrect.getPixels()) ) {
+ // transfer to direct NIO
+ final ByteBuffer sBB = pixelrect.getPixels();
+ final ByteBuffer dBB = Buffers.newDirectByteBuffer(sBB.array(), sBB.arrayOffset());
+ fpixelrect = new PixelRectangle.GenericPixelRect(pixelrect.getPixelformat(), pixelrect.getSize(), pixelrect.getStride(), pixelrect.isGLOriented(), dBB);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: Conversion-NIO "+pixelrect+" -> "+fpixelrect);
+ }
+ } else {
+ fpixelrect = pixelrect;
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: No conversion "+fpixelrect);
+ }
+ }
final PointerIconImpl[] res = { null };
runOnEDTIfAvail(true, new Runnable() {
public void run() {
@@ -100,22 +197,63 @@ public abstract class DisplayImpl extends Display {
if( !DisplayImpl.this.isNativeValid() ) {
throw new IllegalStateException("Display.createPointerIcon(2): Display invalid "+DisplayImpl.this);
}
- res[0] = createPointerIconImpl(pngResource, hotX, hotY);
+ if( null != fpixelrect ) {
+ final long handle = createPointerIconImplChecked(fpixelrect.getPixelformat(),
+ fpixelrect.getSize().getWidth(),
+ fpixelrect.getSize().getHeight(),
+ fpixelrect.getPixels(), hotX, hotY);
+ if( 0 != handle ) {
+ res[0] = new PointerIconImpl(DisplayImpl.this, fpixelrect, new Point(hotX, hotY), handle);
+ }
+ }
} catch (Exception e) {
e.printStackTrace();
}
} } );
- if( !isTemp ) {
+ if( null != res[0] ) {
synchronized(pointerIconList) {
pointerIconList.add(res[0]);
}
}
return res[0];
}
- /** Executed from EDT! */
- protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- return null;
+
+ /**
+ * Executed from EDT!
+ *
+ * @param pixelformat the <code>pixels</code>'s format
+ * @param width the <code>pixels</code>'s width
+ * @param height the <code>pixels</code>'s height
+ * @param pixels the <code>pixels</code>
+ * @param hotX the PointerIcon's hot-spot x-coord
+ * @param hotY the PointerIcon's hot-spot x-coord
+ * @return if successful a valid handle (not null), otherwise null.
+ */
+ protected final long createPointerIconImplChecked(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ if( getNativePointerIconPixelFormat() != pixelformat ) {
+ throw new IllegalArgumentException("Pixelformat no "+getNativePointerIconPixelFormat()+", but "+pixelformat);
+ }
+ if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixels) ) {
+ throw new IllegalArgumentException("pixel buffer is not direct "+pixels);
+ }
+ return createPointerIconImpl(pixelformat, width, height, pixels, hotX, hotY);
+ }
+
+ /**
+ * Executed from EDT!
+ *
+ * @param pixelformat the <code>pixels</code>'s format
+ * @param width the <code>pixels</code>'s width
+ * @param height the <code>pixels</code>'s height
+ * @param pixels the <code>pixels</code>
+ * @param hotX the PointerIcon's hot-spot x-coord
+ * @param hotY the PointerIcon's hot-spot x-coord
+ * @return if successful a valid handle (not null), otherwise null.
+ */
+ protected long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return 0;
}
+
/** Executed from EDT! */
protected void destroyPointerIconImpl(final long displayHandle, long piHandle) { }
diff --git a/src/newt/classes/jogamp/newt/PointerIconImpl.java b/src/newt/classes/jogamp/newt/PointerIconImpl.java
index e2388be67..7c8535f20 100644
--- a/src/newt/classes/jogamp/newt/PointerIconImpl.java
+++ b/src/newt/classes/jogamp/newt/PointerIconImpl.java
@@ -27,27 +27,63 @@
*/
package jogamp.newt;
+import java.nio.ByteBuffer;
+
import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelRectangle;
import javax.media.nativewindow.util.PointImmutable;
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.common.util.IOUtil.ClassResources;
import com.jogamp.newt.Display;
import com.jogamp.newt.Display.PointerIcon;
public class PointerIconImpl implements PointerIcon {
private final DisplayImpl display;
- private final IOUtil.ClassResources resource;
+ private final PixelFormat pixelformat;
private final DimensionImmutable size;
+ private final ByteBuffer pixels;
private final PointImmutable hotspot;
private long handle;
- public PointerIconImpl(DisplayImpl display, ClassResources resource, final DimensionImmutable size, final PointImmutable hotspot, final long handle) {
+ private int hashCode = 0;
+ private volatile boolean hashCodeComputed = false;
+
+ public PointerIconImpl(final DisplayImpl display, final PixelFormat pixelformat, final DimensionImmutable size, final ByteBuffer pixels, final PointImmutable hotspot, final long handle) {
this.display = display;
- this.resource = resource;
+ this.pixelformat = pixelformat;
this.size = size;
+ this.pixels = pixels;
this.hotspot = hotspot;
+
this.handle=handle;
}
+ public PointerIconImpl(final DisplayImpl display, final PixelRectangle pixelrect, final PointImmutable hotspot, final long handle) {
+ this.display = display;
+ this.pixelformat = pixelrect.getPixelformat();
+ this.size = pixelrect.getSize();
+ this.pixels = pixelrect.getPixels();
+ this.hotspot = hotspot;
+ this.handle=handle;
+ }
+
+ @Override
+ public int hashCode() {
+ if( !hashCodeComputed ) { // DBL CHECKED OK VOLATILE
+ synchronized (this) {
+ if( !hashCodeComputed ) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + display.getFQName().hashCode();
+ hash = ((hash << 5) - hash) + pixelformat.hashCode();
+ hash = ((hash << 5) - hash) + size.hashCode();
+ hash = ((hash << 5) - hash) + getStride();
+ hash = ((hash << 5) - hash) + ( isGLOriented() ? 1 : 0);
+ hash = ((hash << 5) - hash) + pixels.hashCode();
+ hashCode = ((hash << 5) - hash) + hotspot.hashCode();
+ }
+ }
+ }
+ return hashCode;
+ }
+
public synchronized final long getHandle() { return handle; }
public synchronized final long validatedHandle() {
synchronized(display.pointerIconList) {
@@ -57,8 +93,7 @@ public class PointerIconImpl implements PointerIcon {
}
if( 0 == handle ) {
try {
- final PointerIconImpl temp = (PointerIconImpl) display.createPointerIcon(true /* isTemp */, resource, hotspot.getX(), hotspot.getY());
- handle = temp.handle;
+ handle = display.createPointerIconImpl(pixelformat, size.getWidth(), size.getHeight(), pixels, hotspot.getX(), hotspot.getY());
return handle;
} catch (Exception e) {
e.printStackTrace();
@@ -71,7 +106,9 @@ public class PointerIconImpl implements PointerIcon {
@Override
public final Display getDisplay() { return display; }
@Override
- public final IOUtil.ClassResources getResource() { return resource; }
+ public final PixelFormat getPixelformat() { return pixelformat; }
+ @Override
+ public final ByteBuffer getPixels() { return pixels; }
@Override
public synchronized final boolean isValid() { return 0 != handle; }
@Override
@@ -116,11 +153,19 @@ public class PointerIconImpl implements PointerIcon {
return size;
}
@Override
+ public final int getStride() {
+ return size.getWidth() * pixelformat.bytesPerPixel();
+ }
+ @Override
+ public final boolean isGLOriented() {
+ return false;
+ }
+ @Override
public final PointImmutable getHotspot() {
return hotspot;
}
@Override
public final String toString() {
- return "PointerIcon["+DisplayImpl.toHexString(super.hashCode())+", "+display.getFQName()+", "+resource.resourcePaths[0]+", 0x"+Long.toHexString(handle)+", "+size+", "+hotspot+"]";
+ return "PointerIcon[obj 0x"+Integer.toHexString(super.hashCode())+", "+display.getFQName()+", 0x"+Long.toHexString(handle)+", "+pixelformat+", "+size+", "+hotspot+", pixels "+pixels+"]";
}
} \ No newline at end of file
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 50f30f04d..dc9affd63 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -53,6 +53,7 @@ import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.util.DimensionImmutable;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.PixelRectangle;
import javax.media.nativewindow.util.Point;
import javax.media.nativewindow.util.PointImmutable;
import javax.media.nativewindow.util.Rectangle;
@@ -61,7 +62,6 @@ import javax.media.nativewindow.util.RectangleImmutable;
import jogamp.nativewindow.SurfaceUpdatedHelper;
import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.IntBitfield;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.locks.LockFactory;
@@ -1700,7 +1700,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
/**
* Helper method to delegate {@link #setPointerVisibleImpl(boolean)} to
- * {@link OffscreenLayerSurface#hideCursor()} or {@link OffscreenLayerSurface#setCursor(IOUtil.ClassResources, PointImmutable)}.
+ * {@link OffscreenLayerSurface#hideCursor()} or {@link OffscreenLayerSurface#setCursor(PixelRectangle, PointImmutable)}.
* <p>
* Note: JAWTWindow is an OffscreenLayerSurface.
* </p>
@@ -1755,7 +1755,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
/**
* Helper method to delegate {@link #setPointerIconIntern(PointerIconImpl)} to
- * {@link OffscreenLayerSurface#setCursor(IOUtil.ClassResources, PointImmutable)}.
+ * {@link OffscreenLayerSurface#setCursor(PixelRectangle, PointImmutable)}
* <p>
* Note: JAWTWindow is an OffscreenLayerSurface.
* </p>
@@ -1777,7 +1777,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
final OffscreenLayerSurface ols = (OffscreenLayerSurface) parent;
try {
if( null != pi ) {
- return ols.setCursor(pi.getResource(), pi.getHotspot());
+ return ols.setCursor(pi, pi.getHotspot());
} else {
return ols.setCursor(null, null); // default
}
diff --git a/src/newt/classes/jogamp/newt/driver/PNGIcon.java b/src/newt/classes/jogamp/newt/driver/PNGIcon.java
index ffa62978f..967acd413 100644
--- a/src/newt/classes/jogamp/newt/driver/PNGIcon.java
+++ b/src/newt/classes/jogamp/newt/driver/PNGIcon.java
@@ -32,6 +32,7 @@ import java.net.MalformedURLException;
import java.nio.ByteBuffer;
import jogamp.newt.Debug;
+import jogamp.newt.DisplayImpl;
import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.ReflectionUtil;
@@ -45,8 +46,7 @@ public class PNGIcon {
Debug.initSingleton();
final ClassLoader cl = PNGIcon.class.getClassLoader();
- avail = ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl) &&
- ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.texture.spi.PNGImage", cl);
+ avail = DisplayImpl.isPNGUtilAvailable() && ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl);
}
/** Returns true if PNG decoder is available. */
@@ -55,7 +55,11 @@ public class PNGIcon {
}
/**
- * Implemented for X11.
+ * Special implementation for X11 Window Icons
+ * <p>
+ * The returned byte buffer is a direct buffer!
+ * </p>
+ *
* @param resources
* @param data_size
* @param elem_bytesize
@@ -73,29 +77,4 @@ public class PNGIcon {
}
throw new UnsupportedOperationException(err0);
}
-
- /**
- * Implemented for Windows.
- * @param resources
- * @param toBGRA if true, arranges stores in BGRA888 order, otherwise RGBA888
- * @param width
- * @param height
- * @param data_size
- * @param resourcesIdx
- * @return pixels with origin at upper-left corner.
- * If storing RGBA8888, component R is located on the lowest 8-bit.
- * If storing BGRA8888, component B is located on the lowest 8-bit.
- * Component A is located on the highest 8-bit.
- *
- * @throws UnsupportedOperationException if not implemented
- * @throws InterruptedException
- * @throws IOException
- * @throws MalformedURLException
- */
- public static ByteBuffer singleToRGBAImage(IOUtil.ClassResources resources, int resourceIdx, boolean toBGRA, int[] width, int[] height, int[] data_size) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
- if( avail ) {
- return jogamp.newt.driver.opengl.JoglUtilPNGIcon.singleToRGBAImage(resources, resourceIdx, toBGRA, width, height, data_size);
- }
- throw new UnsupportedOperationException(err0);
- }
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
index 30583c48c..d850a18af 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
@@ -34,28 +34,25 @@
package jogamp.newt.driver.macosx;
-import java.io.IOException;
-import java.net.MalformedURLException;
+import java.net.URLConnection;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PixelFormat;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.newt.NewtFactory;
+import com.jogamp.opengl.util.PNGPixelRect;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
-import jogamp.newt.PointerIconImpl;
-import jogamp.newt.driver.PNGIcon;
public class DisplayDriver extends DisplayImpl {
- private static final int defaultIconWidth, defaultIconHeight;
- private static final Buffer defaultIconData;
+ private static final PNGPixelRect defaultIconData;
static {
NEWTJNILibLoader.loadNEWT();
@@ -67,21 +64,23 @@ public class DisplayDriver extends DisplayImpl {
throw new NativeWindowException("Failed to initialize jmethodIDs");
}
{
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
- Buffer data=null;
- if( PNGIcon.isAvailable() ) {
+ PNGPixelRect image=null;
+ if( DisplayImpl.isPNGUtilAvailable() ) {
try {
+ // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
- data = PNGIcon.singleToRGBAImage(iconRes, iconRes.resourceCount()-1, false /* toBGRA */, width, height, data_size);
+ final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1);
+ image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, true /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
} catch (Exception e) {
e.printStackTrace();
}
}
- defaultIconWidth = width[0];
- defaultIconHeight = height[0];
- defaultIconData = data;
+ defaultIconData = image;
if( null != defaultIconData ) {
- DisplayDriver.setAppIcon0(defaultIconData, defaultIconWidth, defaultIconHeight);
+ final Buffer pixels = defaultIconData.getPixels();
+ DisplayDriver.setAppIcon0(
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */,
+ defaultIconData.getSize().getWidth(), defaultIconData.getSize().getHeight());
}
}
@@ -112,17 +111,20 @@ public class DisplayDriver extends DisplayImpl {
aDevice.close();
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ * </p>
+ */
@Override
- protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- if( PNGIcon.isAvailable() ) {
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
- if( null != pngResource && 0 < pngResource.resourceCount() ) {
- final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size);
- return new PointerIconImpl( this, pngResource, new Dimension(width[0], height[0]),
- new Point(hotX, hotY), createPointerIcon0(data, width[0], height[0], hotX, hotY));
- }
- }
- return null;
+ public final boolean getNativePointerIconForceDirectNIO() { return true; }
+
+ @Override
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createPointerIcon0(
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */,
+ width, height, hotX, hotY);
}
@Override
@@ -140,8 +142,8 @@ public class DisplayDriver extends DisplayImpl {
private static native boolean initNSApplication0();
private static native void runNSApplication0();
private static native void stopNSApplication0();
- /* pp */ static native void setAppIcon0(Object iconData, int iconWidth, int iconHeight);
- private static native long createPointerIcon0(Object iconData, int iconWidth, int iconHeight, int hotX, int hotY);
+ /* pp */ static native void setAppIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height);
+ private static native long createPointerIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
private static native long destroyPointerIcon0(long handle);
}
diff --git a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
index 216a0cb20..551929b8d 100644
--- a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
+++ b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
@@ -32,20 +32,22 @@ import java.net.MalformedURLException;
import java.net.URLConnection;
import java.nio.ByteBuffer;
+import javax.media.nativewindow.util.PixelFormat;
+
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IOUtil;
-import com.jogamp.opengl.util.texture.spi.PNGImage;
+import com.jogamp.opengl.util.PNGPixelRect;
public class JoglUtilPNGIcon {
public static ByteBuffer arrayToX11BGRAImages(IOUtil.ClassResources resources, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
- final PNGImage[] images = new PNGImage[resources.resourceCount()];
+ final PNGPixelRect[] images = new PNGPixelRect[resources.resourceCount()];
data_size[0] = 0;
for(int i=0; i<resources.resourceCount(); i++) {
final URLConnection urlConn = resources.resolve(i);
- final PNGImage image = PNGImage.read(urlConn.getInputStream());
- data_size[0] += 2 + image.getWidth() * image.getHeight();
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ data_size[0] += 2 + image.getSize().getWidth() * image.getSize().getHeight();
images[i] = image;
}
final boolean is64Bit = Platform.is64Bit();
@@ -53,31 +55,26 @@ public class JoglUtilPNGIcon {
final ByteBuffer buffer = Buffers.newDirectByteBuffer( data_size[0] * elem_bytesize[0] );
for(int i=0; i<images.length; i++) {
- final PNGImage image1 = images[i];
+ final PNGPixelRect image1 = images[i];
+ final int width = image1.getSize().getWidth();
+ final int height = image1.getSize().getHeight();
if( is64Bit ) {
- buffer.putLong(image1.getWidth());
- buffer.putLong(image1.getHeight());
+ buffer.putLong(width);
+ buffer.putLong(height);
} else {
- buffer.putInt(image1.getWidth());
- buffer.putInt(image1.getHeight());
+ buffer.putInt(width);
+ buffer.putInt(height);
}
- final ByteBuffer bb = image1.getData();
- final int bpp = image1.getBytesPerPixel();
- final int stride = image1.getWidth() * bpp;
- for(int y=0; y<image1.getHeight(); y++) {
- int bbOff = image1.isGLOriented() ? ( image1.getHeight() - 1 - y ) * stride : y * stride;
- for(int x=0; x<image1.getWidth(); x++) {
- // Source: R G B A
- // Dest: B G R A
+ final ByteBuffer bb = image1.getPixels();
+ final int stride = image1.getStride();
+ for(int y=0; y<height; y++) {
+ int bbOff = y * stride;
+ for(int x=0; x<width; x++) {
long pixel;
- pixel = ( 0xffL & bb.get(bbOff++) ) << 16; // R
+ pixel = ( 0xffL & bb.get(bbOff++) ); // B
pixel |= ( 0xffL & bb.get(bbOff++) ) << 8; // G
- pixel |= ( 0xffL & bb.get(bbOff++) ); // B
- if( 4 == bpp ) {
- pixel |= ( 0xffL & bb.get(bbOff++) ) << 24;
- } else {
- pixel |= 0x00000000ff000000L;
- }
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 16; // R
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 24; // A
if( is64Bit ) {
buffer.putLong(pixel);
} else {
@@ -89,51 +86,4 @@ public class JoglUtilPNGIcon {
buffer.rewind();
return buffer;
}
-
- public static ByteBuffer singleToRGBAImage(IOUtil.ClassResources resources, int resourceIdx, boolean toBGRA, int[] width, int[] height, int[] data_size) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
- width[0] = 0;
- height[0] = 0;
- data_size[0] = 0;
- final URLConnection urlConn = resources.resolve(resourceIdx);
- final PNGImage image = PNGImage.read(urlConn.getInputStream());
- width[0] = image.getWidth();
- height[0] = image.getHeight();
- data_size[0] = image.getWidth() * image.getHeight();
-
- final int elem_bytesize = 4; // BGRA
- final ByteBuffer buffer = Buffers.newDirectByteBuffer( data_size[0] * elem_bytesize );
-
- final ByteBuffer bb = image.getData();
- final int bpp = image.getBytesPerPixel();
- final int stride = image.getWidth() * bpp;
- for(int y=0; y<image.getHeight(); y++) {
- int bbOff = image.isGLOriented() ? ( image.getHeight() - 1 - y ) * stride : y * stride;
- for(int x=0; x<image.getWidth(); x++) {
- // Source: R G B A
- final byte r, g, b, a;
- r = bb.get(bbOff++); // R
- g = bb.get(bbOff++); // G
- b = bb.get(bbOff++); // B
- if( 4 == bpp ) {
- a = bb.get(bbOff++); // A
- } else {
- a = (byte)0xff; // A
- }
- if( toBGRA ) {
- // Dest: B G R A
- buffer.put(b);
- buffer.put(g);
- buffer.put(r);
- } else {
- // Dest: R G B A
- buffer.put(r);
- buffer.put(g);
- buffer.put(b);
- }
- buffer.put(a);
- }
- }
- buffer.rewind();
- return buffer;
- }
}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
index a4db50165..a30431788 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
@@ -34,8 +34,7 @@
package jogamp.newt.driver.windows;
-import java.io.IOException;
-import java.net.MalformedURLException;
+import java.net.URLConnection;
import java.nio.Buffer;
import java.nio.ByteBuffer;
@@ -43,18 +42,16 @@ import jogamp.nativewindow.windows.RegisteredClass;
import jogamp.nativewindow.windows.RegisteredClassFactory;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
-import jogamp.newt.PointerIconImpl;
-import jogamp.newt.driver.PNGIcon;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PixelFormat;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.newt.NewtFactory;
+import com.jogamp.opengl.util.PNGPixelRect;
public class DisplayDriver extends DisplayImpl {
@@ -66,17 +63,18 @@ public class DisplayDriver extends DisplayImpl {
NEWTJNILibLoader.loadNEWT();
{
long[] _defaultIconHandle = { 0, 0 };
- if( PNGIcon.isAvailable() ) {
+ if( DisplayImpl.isPNGUtilAvailable() ) {
try {
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
{
- final ByteBuffer icon_data_small = PNGIcon.singleToRGBAImage(iconRes, 0, true /* toBGRA */, width, height, data_size);
- _defaultIconHandle[0] = DisplayDriver.createBGRA8888Icon0(icon_data_small, width[0], height[0], false, 0, 0);
+ final URLConnection urlConn = iconRes.resolve(0);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ _defaultIconHandle[0] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0);
}
{
- final ByteBuffer icon_data_big = PNGIcon.singleToRGBAImage(iconRes, iconRes.resourceCount()-1, true /* toBGRA */, width, height, data_size);
- _defaultIconHandle[1] = DisplayDriver.createBGRA8888Icon0(icon_data_big, width[0], height[0], false, 0, 0);
+ final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ _defaultIconHandle[1] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0);
}
} catch (Exception e) {
e.printStackTrace();
@@ -127,16 +125,8 @@ public class DisplayDriver extends DisplayImpl {
}
@Override
- protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- if( PNGIcon.isAvailable() ) {
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
- if( null != pngResource && 0 < pngResource.resourceCount() ) {
- final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size);
- return new PointerIconImpl( this, pngResource, new Dimension(width[0], height[0]),
- new Point(hotX, hotY), createBGRA8888Icon0(data, width[0], height[0], true, hotX, hotY));
- }
- }
- return null;
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createBGRA8888Icon0(pixels, width, height, true, hotX, hotY);
}
@Override
@@ -149,16 +139,18 @@ public class DisplayDriver extends DisplayImpl {
//
private static native void DispatchMessages0();
- static long createBGRA8888Icon0(Buffer data, int width, int height, boolean isCursor, int hotX, int hotY) {
- if( null == data ) {
+ static long createBGRA8888Icon0(Buffer pixels, int width, int height, boolean isCursor, int hotX, int hotY) {
+ if( null == pixels ) {
throw new IllegalArgumentException("data buffer/size");
}
- if( !Buffers.isDirect(data) ) {
- throw new IllegalArgumentException("data buffer is not direct "+data);
- }
- return createBGRA8888Icon0(data, Buffers.getDirectBufferByteOffset(data), width, height, isCursor, hotX, hotY);
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return createBGRA8888Icon0(
+ pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, isCursor, hotX, hotY);
}
- private static native long createBGRA8888Icon0(Object data, int data_offset, int width, int height, boolean isCursor, int hotX, int hotY);
+ private static native long createBGRA8888Icon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, boolean isCursor, int hotX, int hotY);
private static native void destroyIcon0(long handle);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
index 150337df4..4d1388eec 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
@@ -34,25 +34,19 @@
package jogamp.newt.driver.x11;
-import java.io.IOException;
-import java.net.MalformedURLException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PixelFormat;
import com.jogamp.common.nio.Buffers;
-import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import jogamp.nativewindow.x11.X11Util;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
-import jogamp.newt.PointerIconImpl;
-import jogamp.newt.driver.PNGIcon;
public class DisplayDriver extends DisplayImpl {
@@ -132,16 +126,11 @@ public class DisplayDriver extends DisplayImpl {
protected Boolean isXineramaEnabled() { return isNativeValid() ? Boolean.valueOf(((X11GraphicsDevice)aDevice).isXineramaEnabled()) : null; }
@Override
- protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- if( PNGIcon.isAvailable() ) {
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
- if( null != pngResource && 0 < pngResource.resourceCount() ) {
- final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, false /* toBGRA */, width, height, data_size);
- final long handle = createPointerIcon0(getHandle(), data, width[0], height[0], hotX, hotY);
- return new PointerIconImpl(DisplayDriver.this, pngResource, new Dimension(width[0], height[0]), new Point(hotX, hotY), handle);
- }
- }
- return null;
+ public final PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.RGBA8888; }
+
+ @Override
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createPointerIcon(getHandle(), pixels, width, height, hotX, hotY);
}
@Override
@@ -166,13 +155,16 @@ public class DisplayDriver extends DisplayImpl {
private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */); // XKB disabled for now
- static long createPointerIcon0(long display, Buffer data, int width, int height, int hotX, int hotY) {
- if( !Buffers.isDirect(data) ) {
- throw new IllegalArgumentException("data buffer is not direct "+data);
- }
- return createPointerIcon0(display, data, Buffers.getDirectBufferByteOffset(data), width, height, hotX, hotY);
+ private static long createPointerIcon(long display, Buffer pixels, int width, int height, int hotX, int hotY) {
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return createPointerIcon0(display,
+ pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, hotX, hotY);
}
- private static native long createPointerIcon0(long display, Object data, int data_offset, int width, int height, int hotX, int hotY);
+ private static native long createPointerIcon0(long display, Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
+
static native void destroyPointerIcon0(long display, long handle);
/** X11 Window delete atom marker used on EDT */
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index ad1744f2e..0eda37eac 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -50,6 +50,7 @@ import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
import com.jogamp.newt.NewtFactory;
@@ -74,6 +75,7 @@ public class WindowDriver extends WindowImpl {
Buffer _icon_data=null;
if( PNGIcon.isAvailable() ) {
try {
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
final int[] data_size = { 0 }, elem_bytesize = { 0 };
_icon_data = PNGIcon.arrayToX11BGRAImages(NewtFactory.getWindowIcons(), data_size, elem_bytesize);
_icon_data_size = data_size[0];
@@ -124,7 +126,7 @@ public class WindowDriver extends WindowImpl {
( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
edtDevice.lock();
try {
- setWindowHandle(CreateWindow0(getParentWindowHandle(),
+ setWindowHandle(CreateWindow(getParentWindowHandle(),
edtDevice.getHandle(), screen.getIndex(), visualID,
display.getJavaObjectAtom(), display.getWindowDeleteAtom(),
getX(), getY(), getWidth(), getHeight(), autoPosition(), flags,
@@ -430,10 +432,24 @@ public class WindowDriver extends WindowImpl {
protected static native boolean initIDs0();
+ private long CreateWindow(long parentWindowHandle, long display, int screen_index,
+ int visualID, long javaObjectAtom, long windowDeleteAtom,
+ int x, int y, int width, int height, boolean autoPosition, int flags,
+ int pixelDataSize, Buffer pixels) {
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ if( !Buffers.isDirect(pixels) ) {
+ throw new IllegalArgumentException("data buffer is not direct "+pixels);
+ }
+ return CreateWindow0(parentWindowHandle, display, screen_index,
+ visualID, javaObjectAtom, windowDeleteAtom,
+ x, y, width, height, autoPosition, flags,
+ pixelDataSize,
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */);
+ }
private native long CreateWindow0(long parentWindowHandle, long display, int screen_index,
int visualID, long javaObjectAtom, long windowDeleteAtom,
int x, int y, int width, int height, boolean autoPosition, int flags,
- int iconDataSize, Object iconData);
+ int pixelDataSize, Object pixels, int pixels_byte_offset, boolean pixels_is_direct);
private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/ ); // XKB disabled for now
private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle,
long windowDeleteAtom, int x, int y, int width, int height, int flags);
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index 359b67b39..c6fd805a5 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -287,9 +287,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplic
[pool release];
}
-static NSImage * createNSImageFromData(JNIEnv *env, jobject jiconData, jint jiconWidth, jint jiconHeight) {
- if( NULL != jiconData ) {
- unsigned char * iconData = (unsigned char *) (*env)->GetDirectBufferAddress(env, jiconData);
+static NSImage * createNSImageFromData(JNIEnv *env, unsigned char * iconData, jint jiconWidth, jint jiconHeight) {
+ if( NULL != iconData ) {
NSInteger iconWidth = (NSInteger) jiconWidth;
NSInteger iconHeight = (NSInteger) jiconHeight;
const NSInteger bpc = 8 /* bits per component */, spp=4 /* RGBA */, bpp = bpc * spp;
@@ -319,28 +318,47 @@ static NSImage * createNSImageFromData(JNIEnv *env, jobject jiconData, jint jico
* Method: setAppIcon0
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_setAppIcon0
- (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight)
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height)
{
+ if( 0 == pixels ) {
+ return;
+ }
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight);
+ // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
if( NULL != nsImage ) {
[nsImage autorelease];
[NSApp setApplicationIconImage: nsImage];
}
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
[pool release];
}
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPointerIcon0
- (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight, jint hotX, jint hotY)
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
{
+ if( 0 == pixels ) {
+ return 0;
+ }
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight);
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
NSCursor * res = NULL;
if( NULL != nsImage ) {
[nsImage autorelease];
NSPoint hotP = { hotX, hotY };
res = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP];
}
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
[pool release];
DBG_PRINT( "createPointerIcon0 %p\n", res);
return (jlong) (intptr_t) res;
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index 1fd8d0039..c20e156c1 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -2368,9 +2368,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_warpPointer0
JNIEXPORT jlong JNICALL
Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, jobject _unused,
- jobject data, jint data_offset, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) {
+ jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) {
- const unsigned char * data_ptr = (const unsigned char *) (*env)->GetDirectBufferAddress(env, data) + data_offset;
+ if( 0 == pixels ) {
+ return 0;
+ }
+
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
const int bytes = 4 * width * height; // BGRA8888
DWORD dwWidth, dwHeight;
@@ -2403,10 +2409,14 @@ Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, j
hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
(void **)&lpBits, NULL, (DWORD)0);
- memcpy(lpBits, data_ptr, bytes);
+ memcpy(lpBits, pixelPtr + pixels_byte_offset, bytes);
ReleaseDC(NULL,hdc);
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
// Create an empty mask bitmap.
HBITMAP hMonoBitmap = CreateBitmap(dwWidth,dwHeight,1,1,NULL);
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 19e733111..b62a9b234 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -678,13 +678,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
* Signature: (JJILjava/lang/Object;I)V
*/
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerIcon0
- (JNIEnv *env, jclass clazz, jlong display, jobject data, jint data_offset, jint width, jint height, jint hotX, jint hotY)
+ (JNIEnv *env, jclass clazz, jlong display, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
{
Cursor c;
- if( 0 != data ) {
+ if( 0 != pixels ) {
Display * dpy = (Display *) (intptr_t) display;
- char * data_ptr = (char *) (*env)->GetDirectBufferAddress(env, data) + data_offset;
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
XcursorImage ci;
ci.version = 1; // XCURSOR_IMAGE_VERSION;
ci.size = width; // nominal size (assume square ..)
@@ -693,11 +695,14 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerI
ci.xhot = hotX;
ci.yhot = hotY;
ci.delay = 0;
- ci.pixels = (XcursorPixel *)(intptr_t)data_ptr;
+ ci.pixels = (XcursorPixel *)(intptr_t)(pixelPtr + pixels_byte_offset);
c = XcursorImageLoadCursor (dpy, &ci);
- DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", data_ptr, width, height, hotX, hotY, (void *)c);
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+ DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", (pixelPtr+pixels_byte_offset), width, height, hotX, hotY, (void *)c);
} else {
c = 0;
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index da2778004..54b85c243 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -512,7 +512,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
jint visualID,
jlong javaObjectAtom, jlong windowDeleteAtom,
jint x, jint y, jint width, jint height, jboolean autoPosition, int flags,
- jint iconDataSize, jobject iconData)
+ jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct)
{
Display * dpy = (Display *)(intptr_t)display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
@@ -632,10 +632,16 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
{
XEvent event;
int left=0, right=0, top=0, bottom=0;
-
- if( 0 < iconDataSize && NULL != iconData ) {
- const unsigned char * iconDataPtr = (const unsigned char *) (*env)->GetDirectBufferAddress(env, iconData);
- NewtWindows_setIcon(dpy, window, (int)iconDataSize, iconDataPtr);
+ const unsigned char * pixelPtr = NULL;
+
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ DBG_PRINT("X11: CreateWindow icon: size %d, pixels %p, offset %d, direct %d\n", pixelDataSize, (void*)pixels, pixels_byte_offset, pixels_is_direct);
+ if( 0 < pixelDataSize && NULL != pixels ) {
+ pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ DBG_PRINT("X11: CreateWindow icon: NIO %p\n", pixelPtr);
+ NewtWindows_setIcon(dpy, window, (int)pixelDataSize, pixelPtr+pixels_byte_offset);
}
XMapWindow(dpy, window);
@@ -643,6 +649,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
XSync(dpy, False);
+ if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
// send insets before visibility, allowing java code a proper sync point!
NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom);
(*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);