Hi Phil,

> It doesn't sound right to me that this behaviour is an implementation detail 
> of X.org.
> Developers need to know that either it does or it doesn't. Were you given a
> good rationale?

The explanation was that Pixmaps are reference counted, and therefor
stay alive if a XRender-picture points to it. A window is not
reference counted, and therefor all its resources are destroyed
immediatly. GC's are not affected because they are not bound to a
drawable, thats why it hasn't been a problem for the JDK to free GCs
later than the Window.
I find this explanation fishy, but the general recommendation was to
free Pictures before the drawable in any case.

The patch attached does free the picture before destroying the window,
however casting surfaceData to XRSurfaceData in XWindow.java is ugly -
and the patch assumes nobody calls XDestroyWindow for a
SurfaceData-Drawable except destroy(). Suggestions welcome ;)

With that patch I get rid of all XErrors and also can't reproduce the
XDnD-Exception anymore.

> I don't see how that helped on its own. If the Picture is implicitly freed
> by XDestroyWindow then
> xsdo->xrPic is still going to be != None .. or am I overlooking something?

My initial analysis was wrong - somehow I thought the problem is
solved, but it wasn't.

Thanks Clemens

PS: Is there some java-side equivalent in SurfaceData for X11SD_Dispose?
I have a GC on the java side with no references on the native side and
if possible would like to free it at dispose time without writing C
code.
--- old/make/sun/awt/mapfile-mawt-vers	2010-09-24 22:25:13.453158179 +0200
+++ new/make/sun/awt/mapfile-mawt-vers	2010-09-24 22:25:13.060159227 +0200
@@ -424,6 +424,7 @@
 		Java_sun_java2d_xr_XRSurfaceData_initXRPicture;
 		Java_sun_java2d_xr_XRSurfaceData_initIDs;
 		Java_sun_java2d_xr_XRSurfaceData_XRInitSurface;
+		Java_sun_java2d_xr_XRSurfaceData_freeXSDOPicture;
 		Java_sun_java2d_xr_XRBackendNative_initIDs;
 		Java_sun_java2d_xr_XIDGenerator_bufferXIDs;
 		Java_sun_java2d_xr_XRBackendNative_freeGC;
--- old/make/sun/xawt/mapfile-vers	2010-09-24 22:25:14.103157831 +0200
+++ new/make/sun/xawt/mapfile-vers	2010-09-24 22:25:13.850167398 +0200
@@ -375,6 +375,7 @@
         Java_sun_java2d_xr_XRSurfaceData_initXRPicture;
         Java_sun_java2d_xr_XRSurfaceData_initIDs;
         Java_sun_java2d_xr_XRSurfaceData_XRInitSurface;
+	Java_sun_java2d_xr_XRSurfaceData_freeXSDOPicture;
 	Java_sun_java2d_xr_XRBackendNative_initIDs;
 	Java_sun_java2d_xr_XRBackendNative_freeGC;
 	Java_sun_java2d_xr_XRBackendNative_createGC;
--- old/src/solaris/classes/sun/awt/X11/XWindow.java	2010-09-24 22:25:14.690157342 +0200
+++ new/src/solaris/classes/sun/awt/X11/XWindow.java	2010-09-24 22:25:14.421408215 +0200
@@ -44,6 +44,8 @@
 import sun.java2d.SunGraphics2D;
 import sun.java2d.SurfaceData;
 
+import sun.java2d.xr.XRSurfaceData;
+
 public class XWindow extends XBaseWindow implements X11ComponentPeer {
     private static PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XWindow");
     private static PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XWindow");
@@ -1383,6 +1385,18 @@
         destroy();
     }
 
+    void destroy() {
+        XToolkit.awtLock();
+        try {
+              if(surfaceData != null && surfaceData instanceof XRSurfaceData) {
+                 ((XRSurfaceData) surfaceData).freeSurfacePicture();
+              }
+              super.destroy();
+        } finally {
+            XToolkit.awtUnlock();
+        }
+    }
+
     public Point getLocationOnScreen() {
         synchronized (target.getTreeLock()) {
             Component comp = target;
--- old/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java	2010-09-24 22:25:15.309407237 +0200
+++ new/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java	2010-09-24 22:25:15.025418970 +0200
@@ -55,6 +55,8 @@
 
     native void initXRPicture(long xsdo, int pictForm);
 
+    native void freeXSDOPicture(long xsdo);
+
     public static final String DESC_BYTE_A8_X11 = "Byte A8 Pixmap";
     public static final String DESC_INT_RGB_X11 = "Integer RGB Pixmap";
     public static final String DESC_INT_ARGB_X11 = "Integer ARGB-Pre Pixmap";
@@ -396,6 +398,10 @@
     int validatedRepeat = XRUtils.RepeatNone;
     int validatedFilter = XRUtils.FAST;
 
+    public void freeSurfacePicture() {
+	  freeXSDOPicture(getNativeOps());
+    }
+ 
     /**
      * Validates an XRSurfaceData when used as source. Note that the clip is
      * applied when used as source as well as destination.
--- old/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	2010-09-24 22:25:15.937407516 +0200
+++ new/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	2010-09-24 22:25:15.665159018 +0200
@@ -375,6 +375,12 @@
     AWT_LOCK();
 
     xsdo->invalid = JNI_TRUE;
+
+    if(xsdo->xrPic != None) {
+       XRenderFreePicture(awt_display, xsdo->xrPic);
+       xsdo->xrPic = None;
+    }
+    
     if (xsdo->isPixmap == JNI_TRUE && xsdo->drawable != 0) {
 #ifdef MITSHM
         if (xsdo->shmPMData.shmSegInfo != NULL) {
@@ -407,10 +413,6 @@
         xsdo->cachedGC = NULL;
     }
 
-    if(xsdo->xrPic != None) {
-      XRenderFreePicture(awt_display, xsdo->xrPic);
-    }
-
     AWT_UNLOCK();
 #endif /* !HEADLESS */
 }
--- old/src/solaris/native/sun/java2d/x11/XRSurfaceData.c	2010-09-24 22:25:16.631157831 +0200
+++ new/src/solaris/native/sun/java2d/x11/XRSurfaceData.c	2010-09-24 22:25:16.299407586 +0200
@@ -114,3 +114,26 @@
     XShared_initSurface(env, xsdo, depth, width, height, drawable);
 #endif /* !HEADLESS */
 }
+
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRSurfaceData_freeXSDOPicture(JNIEnv *env, jobject xsd,
+                                                  jlong pXSData)
+{
+#ifndef HEADLESS
+    X11SDOps *xsdo;
+
+    J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_freeXSDOPicture");
+
+    xsdo = X11SurfaceData_GetOps(env, xsd);
+    if (xsdo == NULL) {
+        return;
+    }
+
+    if(xsdo->xrPic != None) {
+       XRenderFreePicture(awt_display, xsdo->xrPic);
+       xsdo->xrPic = None;
+    }
+#endif /* !HEADLESS */
+}
+

Reply via email to