From: <eli...@us...> - 2006-06-30 18:56:49
|
Revision: 2397 Author: elias_naur Date: 2006-06-30 11:56:37 -0700 (Fri, 30 Jun 2006) ViewCVS: http://svn.sourceforge.net/java-game-lib/?rev=2397&view=rev Log Message: ----------- Linux: Fixed Display.setIcon memory leak. Modified Paths: -------------- trunk/LWJGL/src/java/org/lwjgl/opengl/DisplayImplementation.java trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java trunk/LWJGL/src/native/linux/org_lwjgl_opengl_Display.c Added Paths: ----------- trunk/LWJGL/src/java/org/lwjgl/test/applet/ Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/DisplayImplementation.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/DisplayImplementation.java 2006-06-30 16:47:46 UTC (rev 2396) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/DisplayImplementation.java 2006-06-30 18:56:37 UTC (rev 2397) @@ -242,5 +242,5 @@ * @param icons Array of icons in RGBA mode * @return number of icons used. */ - public int setIcon(ByteBuffer[] icons); + public int setIcon(ByteBuffer[] icons); } Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java =================================================================== --- trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java 2006-06-30 16:47:46 UTC (rev 2396) +++ trunk/LWJGL/src/java/org/lwjgl/opengl/LinuxDisplay.java 2006-06-30 18:56:37 UTC (rev 2397) @@ -692,7 +692,28 @@ throw new UnsupportedOperationException(); } + private static void convertIcon(ByteBuffer icon, int width, int height) { + int x = 0; + int y = 5; + byte r,g,b,a; + int depth = 4; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + r = icon.get((x*4)+(y*width*4)); + g = icon.get((x*4)+(y*width*4)+1); + b = icon.get((x*4)+(y*width*4)+2); + a = icon.get((x*4)+(y*width*4)+3); + + icon.put((x*depth)+(y*width*depth), b); // blue + icon.put((x*depth)+(y*width*depth)+1, g); // green + icon.put((x*depth)+(y*width*depth)+2, r); + icon.put((x*depth)+(y*width*depth)+3, a); + } + } + } + /** * Sets one or more icons for the Display. * <ul> @@ -700,23 +721,36 @@ * <li>Linux (and similar platforms) expect one 32x32 icon.</li> * <li>Mac OS X should be supplied one 128x128 icon</li> * </ul> - * The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions nescesarry for the specific platform. + * The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions necessary for the specific platform. * * @param icons Array of icons in RGBA mode * @return number of icons used. */ public int setIcon(ByteBuffer[] icons) { - for (int i=0;i<icons.length;i++) { - int size = icons[i].limit() / 4; - - if (((int) Math.sqrt(size)) == 32) { - nSetWindowIcon(icons[i]); - return 1; + lockAWT(); + try { + incDisplay(); + try { + for (int i=0;i<icons.length;i++) { + int size = icons[i].limit() / 4; + int dimension = (int)Math.sqrt(size); + if (dimension == 32) { + convertIcon(icons[i], dimension, dimension); + nSetWindowIcon(icons[i], icons[i].capacity(), dimension, dimension); + return 1; + } + } + return 0; + } finally { + decDisplay(); } + } catch (LWJGLException e) { + LWJGLUtil.log("Failed to set display icon: " + e); + return 0; + } finally { + unlockAWT(); } - - return 0; } - private static native int nSetWindowIcon(ByteBuffer icon); + private static native void nSetWindowIcon(ByteBuffer icon, int icons_size, int width, int height); } Modified: trunk/LWJGL/src/native/linux/org_lwjgl_opengl_Display.c =================================================================== --- trunk/LWJGL/src/native/linux/org_lwjgl_opengl_Display.c 2006-06-30 16:47:46 UTC (rev 2396) +++ trunk/LWJGL/src/native/linux/org_lwjgl_opengl_Display.c 2006-06-30 18:56:37 UTC (rev 2397) @@ -74,6 +74,7 @@ static Colormap cmap; static Window current_win; static int current_depth; +static Pixmap current_icon_pixmap; static Visual *current_visual; @@ -316,6 +317,13 @@ free(title); } +static void freeIconPixmap() { + if (current_icon_pixmap != 0) { + XFreePixmap(getDisplay(), current_icon_pixmap); + current_icon_pixmap = 0; + } +} + static void destroyWindow(JNIEnv *env) { if (glx_window != None) { lwjgl_glXDestroyWindow(getDisplay(), glx_window); @@ -323,6 +331,7 @@ } XDestroyWindow(getDisplay(), current_win); XFreeColormap(getDisplay(), cmap); + freeIconPixmap(); setRepeatMode(env, AutoRepeatModeDefault); } @@ -513,61 +522,53 @@ jawt.Unlock(env); } -static int setIcon(char *data,int width,int height) { +static void setIcon(JNIEnv *env, char *data, int icon_size, int width,int height) { XWMHints* win_hints; - int x = 0; - int y = 5; - char r,g,b,a; - - int depth = 4; - - for (y=0;y<height;y++) { - for (x=0;x<width;x++) { - r = data[(x*4)+(y*width*4)]; - g = data[(x*4)+(y*width*4)+1]; - b = data[(x*4)+(y*width*4)+2]; - a = data[(x*4)+(y*width*4)+3]; - - data[(x*depth)+(y*width*depth)] = b; // blue - data[(x*depth)+(y*width*depth)+1] = g; // green - data[(x*depth)+(y*width*depth)+2] = r; - data[(x*depth)+(y*width*depth)+3] = a; - } + freeIconPixmap(); + current_icon_pixmap = XCreatePixmap(getDisplay(), getCurrentWindow(), width, height, current_depth); + /* We need to copy the image data since XDestroyImage will also free its data buffer, which can't be allowed + * since the data buffer is managed by the jvm (it's the storage for the direct ByteBuffer) + */ + char *icon_copy = (char *)malloc(sizeof(*icon_copy)*icon_size); + + if (icon_copy == NULL) { + throwException(env, "malloc failed"); + return; } + memcpy(icon_copy, data, icon_size); + XImage *image = XCreateImage(getDisplay(), current_visual, current_depth, ZPixmap, 0, icon_copy, width, height, 32, 0); + if (image == NULL) { + freeIconPixmap(); + free(icon_copy); + throwException(env, "XCreateImage failed"); + return; + } - Pixmap icon_pixmap = XCreatePixmap(getDisplay(), getCurrentWindow(), width, height, current_depth); + GC gc = XCreateGC(getDisplay(), current_icon_pixmap, 0, NULL); + XPutImage(getDisplay(), current_icon_pixmap, gc, image, 0, 0, 0, 0, width, height); + XFreeGC(getDisplay(), gc); + XDestroyImage(image); + // We won't free icon_copy because it is freed by XDestroyImage - XImage *image = XCreateImage(getDisplay(), current_visual, current_depth, ZPixmap, 0, data, width, height, 32, 0); - - GC gc = XCreateGC(getDisplay(), icon_pixmap, 0, NULL); - - XPutImage(getDisplay(), icon_pixmap, gc, image, 0, 0, 0, 0, width, height); - win_hints = XAllocWMHints(); - if (!win_hints) { - return -1; + if (win_hints == NULL) { + throwException(env, "XAllocWMHints failed"); + return; } - win_hints->flags = IconPixmapHint; - win_hints->icon_pixmap = icon_pixmap; + win_hints->flags = IconPixmapHint; + win_hints->icon_pixmap = current_icon_pixmap; XSetWMHints(getDisplay(), getCurrentWindow(), win_hints); XFree(win_hints); XFlush(getDisplay()); - - return 0; } -JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetWindowIcon - (JNIEnv *env, jclass clazz, jobject iconBuffer) +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetWindowIcon + (JNIEnv *env, jclass clazz, jobject iconBuffer, jint icon_size, jint width, jint height) { char *imgData = (char *)(*env)->GetDirectBufferAddress(env, iconBuffer); - if (setIcon(imgData,32,32) == 0) - { - return 1; - } - - return 0; + setIcon(env, imgData, icon_size, width, height); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |