From bd98b927b910d9421e63cf0dbc2b746eec019f80 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Wed, 8 Jan 2014 21:56:26 +0100
Subject: Bug 935: NEWT PointerIcon: Utilize Toolkit Agnostic PixelFormat and
Conversion Utilities (Allowing 'arbitrary' PointerIcon data input)
Commit fe28bc125429b38cdcd016746081f4a6d521c6fd added the notion of toolkit agnostic PixelFormat and conversion utilities,
utilized and further tested by this patch.
+++
- PointerIcon is a PixelRectangle
and hence holds the decoded data.
This allows on-the-fly conversion if required
as well as recreation w/o PNG re-decoding.
- Using array-backed PointerIcon data where possible,
allowing better performance when converting PixelFormat etc.
- NEWT Display adds 'createPointerIcon(final IOUtil.ClassResources pngResource...'
method to support agnostic PointerIcon creation.
- NEWT Display adds methods to allow users to avoid PixelFormat and
Buffer NIO type forced conversion:
- PixelFormat getNativePointerIconPixelFormat()
- boolean getNativePointerIconForceDirectNIO()
+++
PNGImage -> PNGPixelRect
Deleted: com.jogamp.opengl.util.texture.spi.PNGImage
Added: com.jogamp.opengl.util.PNGPixelRect
(We hope nobody was using PNGImage directly since it was a service-plugin for TextureIO)
PNGPixelRect is a PixelRectangle
PNGPixelRect actually is implemented OpenGL agnostic,
however - since our PNGJ support lives under package 'jogamp.opengl.util.pngj'
it cannot be moved up (yet).
PNGPixelRect now handles all PixelFormat for the target format
and also added support for grayscale+alpha (2 channels).
The latter is force-converted to RGB* - similar to paletted.
Further more, PNGPixelRect allows simply passing an OutputStream to write the PNG data.
Used by: TextureIO and NEWT
+++
- OffscreenSurfaceLayer's setCursor(..) uses the agnostic PixelRectangle
instead of a PNG resource.
- AWTMisc uses the PixelRectangle to produce the AWT Cursor
and converts it to the required format.
Hence same pixels are used for NEWT and AWT pointer/cursor icon.
- TestGearsES2Newt and NewtAWTReparentingKeyAdapter 'tests'
iterate over 3 custom PointerIcon when pressed 'c'.
- JOGLNewtAppletBase uses the new custom PointerIcon
'newt/data/crosshair-lumina-trans-32x32.png', which is included in NEWT (213 bytes only).
-
---
src/newt/classes/com/jogamp/newt/Display.java | 119 +++++++++++++---
.../jogamp/newt/awt/applet/JOGLNewtAppletBase.java | 4 +-
src/newt/classes/jogamp/newt/DisplayImpl.java | 156 +++++++++++++++++++--
src/newt/classes/jogamp/newt/PointerIconImpl.java | 63 +++++++--
src/newt/classes/jogamp/newt/WindowImpl.java | 8 +-
src/newt/classes/jogamp/newt/driver/PNGIcon.java | 35 +----
.../jogamp/newt/driver/macosx/DisplayDriver.java | 58 ++++----
.../jogamp/newt/driver/opengl/JoglUtilPNGIcon.java | 92 +++---------
.../jogamp/newt/driver/windows/DisplayDriver.java | 50 +++----
.../jogamp/newt/driver/x11/DisplayDriver.java | 38 ++---
.../jogamp/newt/driver/x11/WindowDriver.java | 20 ++-
src/newt/native/MacWindow.m | 32 ++++-
src/newt/native/WindowsWindow.c | 16 ++-
src/newt/native/X11Display.c | 15 +-
src/newt/native/X11Window.c | 20 ++-
15 files changed, 481 insertions(+), 245 deletions(-)
(limited to 'src/newt')
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.
*
- * 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, ..)}.
*
*
* 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()}.
*
*
+ * {@link PointerIcon} must not be {@link #destroy() destroyed} while in use!
+ *
+ *
* {@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.
*
*
* PointerIcons can be used via {@link Window#setPointerIcon(PointerIcon)}.
*
*/
- public static interface PointerIcon {
+ public static interface PointerIcon extends PixelRectangle {
/**
- * @return the associated Display
+ * Always neatly packed, i.e. width * bytes_per_pixel.
+ *
+ * {@inheritDoc}
+ *
*/
- Display getDisplay();
+ @Override
+ int getStride();
+
+ /**
+ * Always false, i.e. origin is TOP-LEFT.
+ *
+ * {@inheritDoc}
+ *
+ */
+ boolean isGLOriented();
+
+ /**
+ * Computes a hash code over:
+ *
+ * - display
+ * - pixelformat
+ * - size
+ * - stride
+ * - isGLOriented
+ * - pixels
+ * - hotspot
+ *
+ * Dismissing the native handle!
+ *
+ * The hashCode shall be computed only once with first call
+ * and stored for later retrieval to enhance performance.
+ *
+ *
+ * {@inheritDoc}
+ *
+ */
+ @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 {
*
*/
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.
+ *
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ *
+ */
+ public abstract PixelFormat getNativePointerIconPixelFormat();
- /** Returns the hotspot. */
- PointImmutable getHotspot();
+ /**
+ * Returns the native platform's direct NIO buffer requirement pointer-icon pixel data.
+ *
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ *
+ */
+ public abstract boolean getNativePointerIconForceDirectNIO();
- @Override
- String toString();
- }
+ /**
+ * Returns the newly created {@link PointerIcon} or null
if not implemented on platform.
+ *
+ * See {@link PointerIcon} for lifecycle semantics.
+ *
+ *
+ * @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 pngResource
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 null
if not implemented on platform.
*
* See {@link PointerIcon} for lifecycle semantics.
*
+ *
+ * In case {@link #getNativePointerIconPixelFormat()} or {@link #getNativePointerIconForceDirectNIO()}
+ * is not matched by the given pixelrect
, the pixelrect
is converted
+ * into the required {@link PixelFormat} and NIO type.
+ *
*
- * @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.
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 pointerIconList = new ArrayList();
/** 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 pixels
's format
+ * @param width the pixels
's width
+ * @param height the pixels
's height
+ * @param pixels the pixels
+ * @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 pixels
's format
+ * @param width the pixels
's width
+ * @param height the pixels
's height
+ * @param pixels the pixels
+ * @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)}.
*
* Note: JAWTWindow is an OffscreenLayerSurface.
*
@@ -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)}
*
* Note: JAWTWindow is an OffscreenLayerSurface.
*
@@ -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
+ *
+ * The returned byte buffer is a direct buffer!
+ *
+ *
* @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}
+ *
+ * NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ *
+ */
@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; iGetDirectBufferAddress(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);
--
cgit v1.2.3