7032904: XRender: Java2Demo : Infinite loop in Java_sun_java2d_loops_MaskBlit_MaskBlit on OEL 5.6 x64
authorbae
Mon, 30 May 2011 12:05:22 +0400
changeset 9760 5c5883cf6c96
parent 9759 90976a831a86
child 9761 a9315b1a26e9
7032904: XRender: Java2Demo : Infinite loop in Java_sun_java2d_loops_MaskBlit_MaskBlit on OEL 5.6 x64 Reviewed-by: prr
jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java
jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c
--- a/jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java	Fri May 27 13:25:54 2011 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java	Mon May 30 12:05:22 2011 +0400
@@ -121,7 +121,7 @@
 
                     // only attempt to initialize Xrender if it was requested
                     if (xRenderRequested) {
-                        xRenderAvailable = initXRender();
+                        xRenderAvailable = initXRender(xRenderVerbose);
                         if (xRenderVerbose && !xRenderAvailable) {
                             System.out.println(
                                          "Could not enable XRender pipeline");
@@ -159,7 +159,7 @@
     private static boolean xRenderVerbose;
     private static boolean xRenderAvailable;
 
-    private static native boolean initXRender();
+    private static native boolean initXRender(boolean verbose);
     public static boolean isXRenderAvailable() {
         return xRenderAvailable;
     }
--- a/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c	Fri May 27 13:25:54 2011 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c	Mon May 30 12:05:22 2011 +0400
@@ -66,9 +66,10 @@
 } XRadialGradient;
 #endif
 
+#include <dlfcn.h>
+
 #ifdef __solaris__
 /* Solaris 10 will not have these symbols at runtime */
-#include <dlfcn.h>
 #include <link.h>
 
 typedef Picture (*XRenderCreateLinearGradientFuncType)
@@ -104,12 +105,20 @@
       TRANSFORM.matrix[2][2] = 1<<16;                                                          \
     }
 
+/* The xrender pipleine requires libXrender.so version 0.9.3 or later. */
+#define REQUIRED_XRENDER_VER1 0
+#define REQUIRED_XRENDER_VER2 9
+#define REQUIRED_XRENDER_VER3 3
 
-static jboolean IsXRenderAvailable() {
+#define PKGINFO_LINE_LEN_MAX 256
+#define PKGINFO_LINE_CNT_MAX 50
+
+static jboolean IsXRenderAvailable(jboolean verbose) {
 
     void *xrenderlib;
 
     int major_opcode, first_event, first_error;
+    jboolean available = JNI_TRUE;
 
     if (!XQueryExtension(awt_display, "RENDER",
                          &major_opcode, &first_event, &first_error)) {
@@ -120,23 +129,113 @@
     xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);
     if (xrenderlib != NULL) {
 
-        XRenderCreateLinearGradientFunc =
-            (XRenderCreateLinearGradientFuncType)
-            dlsym(xrenderlib, "XRenderCreateLinearGradient");
+      XRenderCreateLinearGradientFunc =
+        (XRenderCreateLinearGradientFuncType)
+        dlsym(xrenderlib, "XRenderCreateLinearGradient");
+
+      XRenderCreateRadialGradientFunc =
+        (XRenderCreateRadialGradientFuncType)
+        dlsym(xrenderlib, "XRenderCreateRadialGradient");
+
+      if (XRenderCreateLinearGradientFunc == NULL ||
+          XRenderCreateRadialGradientFunc == NULL)
+      {
+        available = JNI_FALSE;
+      }
+      dlclose(xrenderlib);
+    } else {
+      available = JNI_FALSE;
+    }
+#else
+    Dl_info info;
+    jboolean versionInfoIsFound = JNI_FALSE;
+
+    memset(&info, 0, sizeof(Dl_info));
+    if (dladdr(&XRenderChangePicture, &info) && info.dli_fname != NULL) {
+      char pkgInfoPath[FILENAME_MAX];
+      char *pkgFileName = "/pkgconfig/xrender.pc";
+      size_t pkgFileNameLen = strlen(pkgFileName);
+      size_t pos, len = strlen(info.dli_fname);
+
+      pos = len;
+      while (pos > 0 && info.dli_fname[pos] != '/') {
+        pos -= 1;
+      }
+
+      if (pos > 0 && pos < (FILENAME_MAX - pkgFileNameLen - 1)) {
+        struct stat stat_info;
+
+        // compose absolute filename to package config
+        strncpy(pkgInfoPath, info.dli_fname, pos);
+
+        strcpy(pkgInfoPath + pos, pkgFileName);
+        pkgInfoPath[pos + pkgFileNameLen] = '\0';
 
-        XRenderCreateRadialGradientFunc =
-            (XRenderCreateRadialGradientFuncType)
-            dlsym(xrenderlib, "XRenderCreateRadialGradient");
+        // check whether the config file exist and is a regular file
+        if ((stat(pkgInfoPath, &stat_info)== 0) &&
+            S_ISREG(stat_info.st_mode))
+        {
+          FILE *fp = fopen(pkgInfoPath, "r");
+          if (fp != NULL) {
+            char line[PKGINFO_LINE_LEN_MAX];
+            int lineCount = PKGINFO_LINE_CNT_MAX;
+            char *versionPrefix = "Version: ";
+            size_t versionPrefixLen = strlen(versionPrefix);
+
+            // look for version
+            while(fgets(line,sizeof(line),fp) != NULL && --lineCount > 0) {
+              size_t lineLen = strlen(line);
+
+              if (lineLen > versionPrefixLen &&
+                  strncmp(versionPrefix, line, versionPrefixLen) == 0)
+              {
+                int v1 = 0, v2 = 0, v3 = 0;
+                int numNeeded = 3,numProcessed;
+                char* version = line + versionPrefixLen;
+                numProcessed = sscanf(version, "%d.%d.%d", &v1, &v2, &v3);
+
+                if (numProcessed == numNeeded) {
+                  // we successfuly read the library version
+                  versionInfoIsFound = JNI_TRUE;
 
-        if (XRenderCreateLinearGradientFunc == NULL ||
-            XRenderCreateRadialGradientFunc == NULL)
-        {
-            dlclose(xrenderlib);
-            return JNI_FALSE;
+                  if (REQUIRED_XRENDER_VER1 == v1 &&
+                      ((REQUIRED_XRENDER_VER2 > v2) ||
+                       ((REQUIRED_XRENDER_VER2 == v2) && (REQUIRED_XRENDER_VER3 > v3))))
+                  {
+                    available = JNI_FALSE;
+
+                    if (verbose) {
+                      printf("INFO: the version %d.%d.%d of libXrender.so is "
+                             "not supported.\n\tSee release notes for more details.\n",
+                             v1, v2, v3);
+                      fflush(stdout);
+                    }
+                  } else {
+                    if (verbose) {
+                      printf("INFO: The version of libXrender.so "
+                             "is detected as %d.%d%d\n", v1, v2, v3);
+                      fflush(stdout);
+                    }
+                  }
+                }
+                break;
+              }
+            }
+            fclose(fp);
+          }
         }
+      }
+    }
+    if (verbose && !versionInfoIsFound) {
+      printf("WARNING: The version of libXrender.so cannot be detected.\n,"
+             "The pipe line will be enabled, but note that versions less than 0.9.3\n"
+             "may cause hangs and crashes\n"
+             "\tSee the release notes for more details.\n");
+      fflush(stdout);
     }
 #endif
-    return JNI_TRUE;
+
+    return available;
 }
 /*
  * Class:     sun_awt_X11GraphicsEnvironment
@@ -145,7 +244,7 @@
  */
 JNIEXPORT jboolean JNICALL
 Java_sun_awt_X11GraphicsEnvironment_initXRender
- (JNIEnv *env, jclass x11ge)
+(JNIEnv *env, jclass x11ge, jboolean verbose)
 {
 #ifndef HEADLESS
     static jboolean xrenderAvailable = JNI_FALSE;
@@ -153,7 +252,7 @@
 
     if (firstTime) {
         AWT_LOCK();
-        xrenderAvailable = IsXRenderAvailable();
+        xrenderAvailable = IsXRenderAvailable(verbose);
         AWT_UNLOCK();
         firstTime = JNI_FALSE;
     }